I am working with iterative methods, and thus with large sparse matrices.
For instance, I want to set up a matrix like this:
1 1 0 0 1 0 0 0 0 0
1 1 1 0 0 1 0 0 0 0
0 1 1 1 0 0 1 0 0 0
0 0 1 1 1 0 0 1 0 0
1 0 0 1 1 1 0 0 1 0
0 1 0 0 1 1 1 0 0 1
So that only certain diagonals are non-zero. In my programming, I will be working with much larger matrix sizes, but Idea is the same: Only a few diagonals are non-zero, all other entries are zeros.
I know, how to do it in for loop, but it seems to be not effective, if the matrix size is large. Also I work with symmetric matrices.
I would appreciate, if you provide me a code for my sample matrix along with description.
You want spdiags:
m = 6; %// number of rows
n = 10; %// number of columns
diags = [-4 -1 0 1 4]; %// diagonals to be filled
A = spdiags(ones(min(m,n), numel(diags)), diags, m, n);
This gives:
>> full(A)
ans =
1 1 0 0 1 0 0 0 0 0
1 1 1 0 0 1 0 0 0 0
0 1 1 1 0 0 1 0 0 0
0 0 1 1 1 0 0 1 0 0
1 0 0 1 1 1 0 0 1 0
0 1 0 0 1 1 1 0 0 1
Related
I am trying to display some value of n consecutive numbers of a vector (in this example, vector x).
x = [1
1
1
1
1
1
0
0
0
0
1
1
0
0
0
0
0
0
1
0
1
0
1
0
1
0
1
1
0
0
1
1
1
1
1
1
0
0
1
1
1
1
0
0
1
1
1
1
1
1
0
0
0
0
0
1
0
0
1
0
0
0
0
1
0
0
1
0
1
0
0
0
1
0
0
0
0
1
0
1
0
0
1
0
0
0
0
1
1
0
0
0
1
0
0
0
0
0
0
1
0
1
0
0
0
0
1
0
1
0
0
0
1
0
0
0
0
0
0
1
0
0
0
1
0
0
1
1
1
1
1
1
0
0
1
1
0
0
1
0
1
0
0
0
0
0
0
1
0
1
0
0];
For example, I may want the first 3 values of 4 consecutive numbers which would be (3 values of 4 bits each):
1111
1100
0011
I may want the first 4 values of 2 consecutive numbers which would be (4 values of 2 bits each):
11
11
11
00
x is a double array. What would be an easy way to achieve this?
The simplest way is to reshape x to a matrix with your desired number of bits per value as the number of rows (MATLAB is column-major). For example, to get 4-digit values:
t = reshape(x,4,[]);
This will only work if the length of x evenly divides into 4. You could first crop x to the right number of elements to avoid errors where the length is not evenly divisible:
t = reshape(x(1:4*3),4,[]);
Now the transposed matrix t, converted to a string, looks like your desired output:
c = char(t.' + '0');
The output is a 3x4 char array:
'1111'
'1100'
'0011'
You can convert these binary representations back to numbers with bin2dec:
b = bin2dec(c);
The output is a 3-element double vector:
15
12
3
There is a grid, the edges of which are always wall.
The internal area of the grid is also divided by walls into several sub-areas, like this
1 = Wall,
0 = Empty.
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 1 1 1 0 0 0 1
1 0 0 0 0 0 0 0 1 0 1 1 1 1 1
1 0 0 0 0 0 0 0 1 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
I need to find the smallest empty sub-area.
How do i do it?
Telescope's suggestion is correct. Here's a slightly more detailed illustration of how you might approach this.
Given an M x N grid, you will loop over the (M - 2)(N - 2) subgrid ignoring the outer walls. When looking at a given grid cell:
if the grid cell is 0, you have not seen this area yet; begin a flood fill here that counts the number of adjacent 0s and changes them to 2 to mark them as having been seen already in some enclosed area, to avoid having to re-flood this area again later
if a grid cell is 1, it's an interior wall and should be skipped
if the grid cell is 2, you have seen this area already and can skip it
At the end, you'll have counted the area of each distinct enclosed section and can choose the biggest, smallest, or whichever you need to know.
This algorithm will visit each cell at most a few times (worst case is a 1 surrounded by 0s which the flood fill will bump into up to four times, and the wall will be checked once during the subgrid scan). Therefore, the time complexity is O(MN). The algorithm uses the grid itself to keep track of what it has done so far, so no extra memory is used; if the grid must not be modified in place, an extra O(MN) memory can be allocated for a working copy.
I'm not quite sure how to describe what I mean, so let me try to explain by example (bear with me).
When you simply increment an integer you get a binary sequence like so (let's assume 8 bits for this question):
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 0 1 1
0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 1
0 0 0 0 0 1 1 0
0 0 0 0 0 1 1 1
0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 1
0 0 0 0 1 0 1 0
0 0 0 0 1 0 1 1
0 0 0 0 1 1 0 0
0 0 0 0 1 1 0 1
0 0 0 0 1 1 1 0
0 0 0 0 1 1 1 1
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1
0 0 0 1 0 0 1 0
0 0 0 1 0 0 1 1
0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 1
0 0 0 1 0 1 1 0
0 0 0 1 0 1 1 1
0 0 0 1 1 0 0 0
0 0 0 1 1 0 0 1
0 0 0 1 1 0 1 0
0 0 0 1 1 0 1 1
0 0 0 1 1 1 0 0
0 0 0 1 1 1 0 1
0 0 0 1 1 1 1 0
0 0 0 1 1 1 1 1
[ ... etc ... ]
One way to visualize this is that each column represents a "clock". Each clock/column is half the frequency of its right neighbor.
So the right-most clock has one 0 followed by one 1, etc. The next clock has two 0s followed by two 1s, etc and so on...
I'm interested in a sequence of binary strings in which each clock is an integer division of its neighbor.
So the right-most clock is still one 0, one 1, the next clock is still two 0s, two 1s, but the third clock is three 0s and three 1s, etc.
Instead of /1 /2 /4 /8 /16 ... it's now /1 /2 /3 /4 /5 ....
The sequence now looks like this:
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 1 1 1
0 0 0 0 1 1 0 0
0 0 0 1 1 1 0 1
0 0 1 1 1 0 1 0
0 1 1 1 1 0 1 1
1 1 1 1 0 0 0 0
1 1 1 1 0 1 0 1
1 1 1 0 0 1 1 0
1 1 1 0 0 1 1 1
1 1 0 0 1 0 0 0
1 1 0 0 1 0 0 1
1 0 0 0 1 0 1 0
1 0 0 1 1 1 1 1
0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 1
0 0 1 1 0 0 1 0
0 0 1 1 0 0 1 1
[ ... etc ... ]
Question: Is there an operation/algorithm which can give me the value at i given the value at i-1?
In other words, let's say I'm at the 4th step (0 0 0 0 0 1 1 1). Is there some operation I can perform on this number to get the value at the 5th step (0 0 0 0 1 1 0 0), and similarly for any other step?
In the divide-by-2 case you simply increment the number (i++) but in the divide-by-N case I can't seem to figure out a similar way to go from one to the next. Am I missing something obvious?
I've tried translating the sequencing into decimal but that pattern is 0, 1, 2, 7, 12, 29, 58, etc which doesn't stand out to me as anything obvious.
The brute-force way that I'm doing it now is that I have an array of counters (one for each column/clock) and I independently reset each count when the respective column's "period" is reached (so 2 for the first column, 3 for the next, etc). But that feels ugly.
I'd love to do this directly on the number without requiring an array of counters. Is this even possible? Is this a known sequence? I'm not even sure what to Google to be honest. I'd appreciate any kind of leads on this. I'm happy to go down the rabbit hole with some guidance.
UPDATE
As per #borrible's observation, there are more than one values for i-1 for a given i so it turns out the solution to my original question is ambiguous. So I will expand my question to allow i as an input (in addition to the i-1th value.
Without knowing i you are only going be able to generate the successor to a given sequence if that sequence uniquely implies i (modulo the number of bit sequences). If this is not the case the successor to a given sequence is ambiguous.
Lets consider the first few sequences for 3 bits:
0 0 0
0 0 1
0 1 0
1 1 1
1 0 0
1 0 1
0 1 0
0 1 1
Note that 0 1 0 is succeeded by both 1 1 1 and 0 1 1; i.e. it is ambiguous. Given 0 1 0 but not i you cannot deduce the next sequence. You can see a similar ambiguity in 4 bit sequences for 0 1 1 1 etc...
In other words, without knowing i, your problem is not generally solvable.
This sequence can be considered as a set of state machines, each with 2,4,6,...,16 states. The least common multiple of 2,4,6,...,16, i.e. the length of the sequence, is 1680. Eight bits only lets us represent 256 values, so even if we were allowed to select the state encoding (which we aren't!), we wouldn't be able to uniquely identify all possible states.
If we know the index i (or, as the sequence length is 1680, it is sufficient to know the index modulo 1680), digit j is given by (i mod (2 * j)) / j.
I am trying to check if in a square matrix there is more than one true value in all possible diagonals and anti-diagonals, and return true, otherwise false.
So far I have tried as following but is not covering all possible diagonals:
n=8; %matrix dimension 8 x 8
diag= sum(A(1:n+1:end));
d1=diag>=2;
antiDiag=sum(A(n:n-1:end));
d2=antiDiag>=2;
if ~any(d1(:)) || ~any(d2(:))
res= true;
else
res=false;
end
this is a false:
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1
this is a true:
0 0 0 0 0 0 0 1
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Since these are my first steps in using Matlab, is there a specific function or a better way to achieve the result I am looking for?
To detect if there are more than one nonzero value in any diagonal or anti-diagonal (not just the main diagonal and antidiagonal): get the row and column indices of nonzero values, ii and jj; and then check if any value of ii-jj (diagonals) or ii+jj (anti-diagonals) is repeated:
[ii, jj] = find(A);
res = (numel(unique(ii-jj)) < numel(ii)) || (numel(unique(ii+jj)) < numel(ii));
One approach:
n=8; %// size of square matrix
A = logical(randi(2,n)-1); %// Create a logical matrix of 0s and 1s
d1 = sum(A(1:n+1:end)); %// sum all the values of Main diagonal
d2 = sum(A(n:n-1:end-1)); %// sum all the values of Main anti-diag
result = d1>=2 | d2>=2 %// result is true when any one of them is > than or = to 2
Sample run:
Inputs:
>> A
A =
0 1 1 1 1 0 1 0
0 1 1 1 1 1 0 0
0 1 0 1 1 0 0 1
0 1 1 0 1 1 0 0
0 1 0 1 1 0 0 1
1 0 0 0 1 1 0 1
1 1 1 1 1 1 0 0
1 1 1 1 0 0 0 1
Output:
result =
1
Note: This approach considers only the Main diag and Main Anti-Diag (considering the example you provided). If you want for all possible diags, the other answer from Luis Mendo is the way to go
Using #Santhan Salai's generating technique, we can use the diag function (to pull out the main diagonal of the matrix), the fliplr to flip over the center column and any to reduced to a single value.
n=8; %// size of square matrix
A = logical(randi(2,n)-1); %// Create a logical matrix of 0s and 1s
any([diag(A) ; diag(fliplr(A))])
I have large array. Now I need a matrix with 8 elements in every row. My array looks like this:
A= Columns 1 through 18
0 0 0 0 0 0 0 0 0 0 1 1 0 1 1 1 0 0
Columns 19 through 36
0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 0 0
and so on. How I can get [nx8] matrix? For example:
B=[0 0 0 0 0 0 0 0
0 0 1 1 0 1 1 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0]
I've tried reshape, but it didn't work correctly. I get one 1 where shouldn't be.
B=reshape(A,[],8)
You almost have it. The problem is that Matlab fills the matrix column-wise, whereas you seem to want it filled row-rise. So create an 8-row matrix and then transpose:
reshape(A,8,[]).'
What about vec2mat
vec2mat
vec2mat(A,8)