How to build a binary matrix from sums - arrays

I have two decimal number variables, colSum and rowSum, using those I want to build a matrix of binary values based on those sums, the rowSum array variable is the result of adding all the 1's for each row, the same goes for colSum array.
So ,if you have
rowSum = [0,1,2]
colSum = [1,1,1]
you will have to build properly the following array
matrix = [
[0,0,0],
[0,0,1],
[1,1,0]
]
I'm using this method in PHP, that works for a 3x3 matrix, but not for a bigger one, like 8x8.
First ,fill all the 1's in the rows using the rowSum value.
Then ,try to find a wrong sum value of 2 columns, with a pivot I inter-change them (1 with a cero value) in the same row, until i get the correct value of colSum.
But it will not work because I need some control of the criteria to change the 1 and 0 in the same row for two columns...
This is the method I'm using.
Let's say we have this Matrix (N=3 -> NxN):
0 0 0
0 0 1
1 1 0
then we have the following arrays
R0 = {0,1,2} //--> result of sums of each rows: ( 0+0+0, 0+0+1 , 1+1+0 )
C0 = {1,1,1} // ->sums of each columns
Step 1
Create and fill a NxN array using as many 1's as R0(i) in each row:
0 0 0
1 0 0
1 1 0
compute sums of this new matrix now:
R1 = {0,1,2}
C1 = {2,1,0}
Step 2
Check if for all the elements of the column sums of the created matrix has the same value as C0 (origin)
for ( i=0, N-1) do
if C0(i)!=C1(i) then
ReplaceColumn(i)
end
end
To replace a column we have to dig inside the conditions.
C0(0) = 1 != C1(0) = 2
the first column sum does meet the condition to call the replace ,so
Step 3
Choose criteria for apply the branch & bound method and find the best row to change column that satisfy the global condition (all column sums).
The amount of changes for a difference between columns sums is:
|C0(i)-C1(i)|
for this example, |C0(0)-C1(0)| = 1 change.
Go back condition must be if the change generates a greater difference between the total sum of columns.
Σi,N(|C0(i)-C1(i)|)
So, could this method really work?

Is the goal to construct the matrix that satisfies the row and column sums or a matrix that satisfies them? It's not clear from the question, but if it's the former ("the" case) then it's not going to possible.
Suppose it were the case that you could uniquely represent any m × m matrix of bits in this way. Then consider the following hypothetical compression algorithm.
Take 22n bits of data
Treat it as 2n × 2n bits
To describe the data, use 2 × 2n row and column sums, each using at most log2(2n) = n bits
The data is compressed to 2 × n × 2n bits
Since 2 × n × 2n << 22n and this process could just keep being repeated, the supposition that you can uniquely represent any m × m matrix of bits by only its row and column sums is false.

Related

Getting corresponding coordinates of a vectorized matrix

I have a matrix X of size n x m. I resized X to a vector a of length n x m.
How can I know "automatically" that the ith element in vector a corresponds to what element position (coordinates) in X?
I have written the following MATLAB code but I do not know how to continue.
X = rand(10,10);
[n,m] = size(X);
a = reshape(X, [n*m, 1]);
t = zeros(length(a),1);
for i = 1 : length(a)
t(i) = % I want to perform here the sum over the x and y coordinate values of the element in X
% that corresponds to the ith element in vector a.
end
Any help will be very appreciated.
That's what ind2sub does:
[row, col] = ind2sub([m n], i);
However, you may prefer to do it manually:
row = mod(i-1,m)+1;
col = floor((i-1)/m)+1;
This works because Matlab used column-major order for storing array elements. For example, in a 3×4 matrix the order in which the elements are stored in memory is as follows:
1 4 7 10
2 5 8 11
3 6 9 12
So the entry in the 2nd row, 3rd column is the 8th element in (column-major) linear order. When this matrix is reshaped into a vector (or into any other shape) this linear order is preserved. Therefore you can retrieve the original coordinates by divisions and modulus operations. Note also that, since Matlab's indexing is 1-based (as opposed to 0-based), the modulus operations need to be shifted by 1.

Creating a Binary Matrix from an Array of Indices

Definition of Problem
I have two arrays called weights and indices respectively:
weights = [1, 3, 2];
indices = [1, 1, 2, 3, 2, 4];
m = 4; % Number of Rows in Matrix
n = 3; % Number of Columns in Matrix
M = zeros(m, n);
The array called indices is storing the indices where I need to store a 1 in every column.
For instance for the first column at row 1 which is indicated in indices(1) I need to store a 1 and this is indicated by weights(1) which is equal to 1.
M(indices(1), 1) = 1;
For column 2, at rows 1 to 3 (indices(2:4)) I need to store a 1. The range of indices for column 2 are again indicated by weights(2).
M(indices(2:4),2) = 1;
Similarly, for column 3, at rows 2 and 4 (indices(5:6)) I need to store a 1. The range of indices for column 3 are again indicated by weights(3).
M(indices(5:6),3) = 1;
Expected Binary Matrix
The expected and resulting binary matrix is:
1 1 0
0 1 1
0 1 0
0 0 1
Solution
Is there any way I can do this in generalized manner by using both the weights and indices arrays rather than doing it in a hard coded manner to create create the binary matrix M?
You just have a weird way of describing your indices, so you just need to convert them to something standard.
columsn_idx=repelem(1:n,weights); % repeat column number as much as needed
row_idx=indices ; % just for clarity
M(sub2ind([m,n],row_idx,columsn_idx))=1;% Use linear indices

Can shift, rotate, and flip operations on a 2D matrix be combined into a single operation? [duplicate]

This question already has an answer here:
C++/OpenGL convert world coords to screen(2D) coords
(1 answer)
Closed 5 years ago.
Say I have a n by n matrix that has each cell as either a 0 or a 1. There is a list of commands that feed into a program. These commands specify an operation (shift, rotate, flip) and a value x, to specify the magnitude of the operation. The operation will only move cells with a 1 in it. A "UP 3" operation would cause all cells with "1" to shift up by 3.
In the case where there are multiple operations that must be sequentially applied to the matrix, for optimization, what I can do is combine contiguous operations of the same type. As in (up, down, left, right) would all be the same type (shift). CW and CCW rotations would be the same type. And Flip in the x or y directions would be the same type. I can combine multiple operations of the same type if they happen one after another. (i.e. UP 3, DOWN 2 -> results in a net UP 1). I want to know if there is a way to do a single "net" operation by combining operations of different types.
So I want to know, in my operations list, if I have for example, 1 UP, 1 CW, 3 RIGHT, 1 Y FLIP, 2 DOWN.
Instead of doing the above 6 instructions in 6 "moves", is there a mathematical/programming way to combine those into a single instruction for a square n by n matrix?
Must be do-able in C.
In the comments, there is some confusion about the terminology, so let's clarify the terms.
Let's say you have a set of nine unique operations: UP, DOWN, LEFT, RIGHT, ROTATE+90, ROTATE+180, ROTATE+270, HFLIP, and VFLIP. You have implemented each of these as a separate function, copying the contents of an N-by-N matrix to a new matrix.
(Also note that you cannot shift, rotate, or flip/mirror "only ones" in a matrix with only ones and zeros in it. If you try, the effect is the same as when you apply the operation to both ones and zeros. Try it, and you'll see.)
If I've understood correctly, the question can be restated as
Is there a way to combine any sequence of those operations, so that I only need one double loop, rather than a double loop for each individual operation?
The answer is Yes, but the implementation is tricky, and there are two different ways the shifts (UP, DOWN, LEFT, RIGHT) can operate, depending on whether elements that are "shifted out" appear from the other edge, or are lost. As an example, consider a RIGHT operation on a 4×4 matrix:
Horizontally periodic nonperiodic
0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1
0 1 1 1 ⇒ 1 0 1 1 0 1 1 1 ⇒ 0 0 1 1
0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
The matrix can be nonperiodic, horizontally periodic, vertically periodic, or fully periodic (i.e., both horizontally and vertically periodic).
For simplicity, let's assume nonperiodic boundaries: The ones are lost, if they are shifted outside the matrix. Zeros are always "shifted in". (This is the easiest case.)
Any combination of the nine unique operations, in any order, even repeated, can be implemented using a single double loop:
For newrow = 1 to N:
row = oldrow
col = oldcol
For newcol = 1 to N:
If (row >= 1) and (row <= N) and
(col >= 1) and (col <= N) and
(oldmatrix[row][col] == 1):
newmatrix[newrow][newcol] = 1
Else:
newmatrix[newrow][newcol] = 0
End if
row = row + colsteprow
col = col + colstepcol
End For
oldrow = oldrow + rowsteprow
oldcol = oldcol + rowstepcol
End For
As I said, this is a bit tricky. Think of superimposing the old and new matrices, but with the sequence of operations applied, and extending the old matrix (row and column numbers) to infinity. (Thus, the row and column numbers in the old matrix are no longer limited to 1..N, but can be any integer.)
You need to identify the row and column numbers (in the old matrix), that correspond to three elements in the new matrix: the first column in the first row, the second column in the first row, and the first column in the second row.
Let row11 and col11 identify the element in the old, infinite matrix, that coincides with the first column, first row in the new matrix; row12 and col12 the element that coincides with the second column, first row in the new matrix; and row21, col21 the element that coincides with the first column, second row in the new matrix.
(In other words, you only need to track how your operations relocate/rotate/mirror these three cells in the old matrix. Hint: reverse.)
Then, at the beginning of the above pseudocode, set oldrow = row11, oldcol = col11, colsteprow = row12 - row11, colstepcol = col12 - col11, rowsteprow = row21 - row11, and rowstepcol = col21 - col11.
Essentially, colsteprow and colstepcol form an integer vector that tells us how an increment in the column number in the new matrix, corresponds to a change of row and/or column in the old matrix. (One of them will always be zero, and the other either +1 or -1.)
Similarly, rowsteprow and rowstepcol tells us how an increment in the row number in the new matrix corresponds to a change in row and/or column numbers in the old matrix.
If your matrix is horizontally periodic, then you wrap oldcol == 0 to oldcol = N, and oldcol == N+1 to oldcol == 1, and drop the If check for oldcol. Similarly, if your matrix is vertically periodic, then you wrap oldrow == 0 to oldrow = N, and oldrow == N+1 to oldrow = 1, and you drop the If check for oldrow.
If you find it hard to fathom how this works, get a transparent sheet of something, and draw a small grid on it, labeling each cell with the row and column numbers. On a paper, draw a small matrix, with same sized cells. The operations shift, rotate, and mirror the transparent sheet on top of the paper. Experiment and observe.

Look at each row separately in a matrix (Matlab)

I have a matrix in Matlab(2012) with 3 columns and X number of rows, X is defined by the user, so varies each time. For this example though I will use a fixed 5x3 matrix.
So I would like to perform an iterative function on each row within the matrix, while the value in the third column is below a certain value. Then store the new values within the same matrix, so overwrite the original values.
The code below is a simplified version of the problem.
M=[-2 -5 -3 -2 -4]; %Vector containing random values
Vf_X=M+1; %Defining the first column of the matrix
Vf_Y=M+2; %Defining the secound column of the matrix
Vf_Z=M; %Defining the third column of the matrix
Vf=[Vf_X',Vf_Y',Vf_Z']; %Creating the matrix
while Vf(:,3)<0
Vf=Vf+1;
end
disp(Vf)
The result I get is
1 2 0
-2 -1 -3
0 1 -1
1 2 0
-1 0 -2
Ideally I would like to get this result instead
1 2 0
1 2 0
1 2 0
1 2 0
1 2 0
The while will not start if any value is above zero to begin with and stops as soon as one value goes above zero.
I hope this makes sense and I have supplied enough information
Thank you for your time and help.
Your current problem is that you stop iterating the very moment any of the values in the third row break the condition. Correct me if I'm wrong, but what I think you want is to continue doing iterations on the remaining rows, until the conditions are broken by all third columns.
You could do that like this:
inds = true(size(Vf,1),1);
while any(inds)
Vf(inds,:) = Vf(inds,:)+1;
inds = Vf(:,3) < 0;
end
Of course, for the simple addition you provide, there is a better and faster way:
inds = Vf(:,3)<0;
Vf(inds,:) = bsxfun(#minus, Vf(inds,:), Vf(inds,3));
But for general functions, the while above will do the trick.

Finding the maximum area in given binary data

I have a problem with describing algorithm for finding maximum rectangular area of binary data, where 1 occurs k-times more often than 0. Data is always n^2 bits like this:
For example data for n = 4 looks like:
1 0 1 0
0 0 1 1
0 1 1 1
1 1 0 1
Value of k can be 1 .. j (k = 1 means, that number of 0 and 1 is equal).
For above example of data and for k = 1 solution is:
1 0 1 0 <- 4 x '0' and 4 x '1'
0 0 1 1
0 1 1 1
1 1 0 1
But in this example:
1 1 1 0
0 1 0 0
0 0 0 0
0 1 1 1
Solution would be:
1 1 1 0
0 1 0 0
0 0 0 0
0 1 1 1
I tried with few brute force algorithms but for n > 20 it is getting too slow. Can you advise me how I should solve this problem?
As RBerteig proposed - the problem can be also described like that: "In a given square bitmap with cells set to 1 or 0 by some arbitrary process, find the largest rectangular area where the 1's and 0's occur in a specified ratio, k."
Bruteforce should do just fine here for n < 100, if properly implemented: solution below has O(n^4) time and O(n^2) memory complexity. 10^8 operations should be well under 1 second on modern PC (especially considering that each operation is very cheap: few additions and subtractions).
Some observations
There're O(n^4) sub-rectangles to consider and each of them can be a solution.
If we can find number of 1's and 0's in each sub-rectangle in O(1) (constant time), we'll solve problem in O(n^4) time.
If we know number of 1's in some sub-rectangle, we can find number of zeroes (through area).
So, the problem is reduced to following: create data structure allowing to find number of 1's in each sub-rectangle in constant time.
Now, imagine we have sub-rectangle [i0..i1]x[j0..j1]. I.e., it occupies rows between i0 and i1 and columns between j0 and j1. And let count_ones be the function to count number of 1's in subrectangle.
This is the main observation:
count_ones([i0..i1]x[j0..j1]) = count_ones([0..i1]x[0..j1]) - count_ones([0..i0 - 1]x[0..j1]) - count_ones([0..i1]x[0..j0 - 1]) + count_ones([0..i0 - 1]x[0..j0 - 1])
Same observation with practical example:
AAAABBB
AAAABBB
CCCCDDD
CCCCDDD
CCCCDDD
CCCCDDD
If we need to find number of 1's in D sub-rectangle (3x4), we can do it by taking number of 1's in the whole rectangle (A + B + C + D), subtracting number of 1's in (A + B) rectangle, subtracting number of 1's in (A + C) rectangle, and adding number of 1's in (A) rectangle. (A + B + C + D) - (A + B) - (A + C) + (A) = D
Thus, we need table sums, for each i and j containing number of 1's in sub-rectangle [0..i][0..j].
You can create this table in O(n^2), but even the direct way to fill it (for each i and j iterate all elements of [0..i][0..j] area) will be O(n^4).
Having this table,
count_ones([i0..i1]x[j0..j1]) = sums[i1][j1] - sums[i0 - 1][j1] - sums[i1][j0 - 1] + sums[i0 - 1][j0 - 1]
Therefore, time complexity O(n^4) reached.
This is still brute force, but something you should note is that you don't have to recompute everything from scratch for a new i*j rectangle. Instead, for each possible rectangle size, you can move the rectangle across the n*n grid one step at a time, decrementing the counts for the bits no longer within the rectangle and incrementing the counts for the bits that newly entered the rectangle. You could potentially combine this with varying the rectangle size, and try to find an optimal pattern for moving and resizing the rectangle.
Just some hints..
You could impose better restrictions on the values. The requirement leads to condition
N1*(k+1) == S*k, where N1 is number of ones in an area, and S=dx*dy is its surface.
It can be rewritten in better form:
N1/k == S/(k+1).
Because the greatest common divisor of numbers n and n+1 is always 1, then N1 have to be multiple of k and dx*dy to be multiple of k+1. It reduces greatly the possible space of solutions, the larger is k, the better (for dx*dy case you'll need to play with prime divisors of k+1).
Now, because you need just the surface of the largest area with such property, it would be wise to start from largest areas and move to smaller ones. By trying dx*dy from n^2 downto k+1 that would satisfy the divisor and the bounding conditions, you'll find quite fast the solution, muuuch faster than O(n^4), because of a special reason: except cases when the array was specially constructed, if we assume a random input, the probability that there are N1 ones out of S values in the (n-dx+1)*(n-dy+1) areas that have the surface S will constantly grow with decrease of S. (large values of k will make the probability smaller, but in the same time they will make the filter for dx and dy pairs stronger).
Also, this problem: http://ioinformatics.org/locations/ioi99/contest/land/land.shtml , looks somehow similar, maybe you'll find some ideas in their solution.

Resources