How do I shorten execution time by replacing the while-loop? - matrix

I have written a small code in Octave and part of it is checking whether values in the first rows of two matrices are equal, and if so, adding the value of the second row of the second matrix to the value of the second row of the first matrix.
This is that part of the code that I have written, using a small set of data:
PositionLoadArray =
1 5 3 7 4 6 9 2 1 2
1 2 3 4 5 6 7 8 9 10
X =
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0
x=1; #row number in matrix X
y=1; #row number in matrix PositionLoadArray
while y<=columns(PositionLoadArray)
if PositionLoadArray(1,y)==X(1,x)
X(2,x)=X(2,x)+PositionLoadArray(,y);
y=y+1;
x=1;
else
x=x+1;
endif
endwhile
This gives the result:
X =
0 1 2 3 4 5 6 7 8 9
0 10 18 3 5 2 6 4 0 7
The loop runs and works perfectly for small sets like the one above (i.e. where the total number of columns for X and PositionLoadArray (max. values of x and y, respectively) are small). But the loop takes hours to be executed with larger values.
How can I reduce the execution time and get the same result?

Try
X(2, X(1,:) == Y(1,:)) += Y(2, X(1,:) == Y(1,:))

Related

plotting multiple graphs and animation from a data file in gnuplot

Suppose I have the following sample data file.
0 1 2
0 3 4
0 1 9
0 9 2
0 19 0
0 6 1
0 11 0
1 3 2
1 3 4
1 1 6
1 9 2
1 15 0
1 6 6
1 11 1
2 3 2
2 4 4
2 1 6
2 9 6
2 15 0
2 6 6
2 11 1
first column gives value of time. Second gives values of x and 3rd column y. I wish to plot graphs of y as functions of x from this data file at different times,
i.e, for t=0, I shall plot using 2:3 with lines up to t=0 index. Then same thing I shall do for the variables at t=1.
At the end of the day, I want to get a gif, i.e, an animation of how the y vs x graph changes shape as time goes on. How can I do this in gnuplot?
What have you tried so far? (Check help ternary and help gif)
You need to filter your data with the ternary operator and then create the animation.
Code:
### plot filtered data and animate
reset session
$Data <<EOD
0 1 2
0 3 4
0 1 9
0 9 2
0 19 0
0 6 1
0 11 0
1 3 2
1 3 4
1 1 6
1 9 2
1 15 0
1 6 6
1 11 1
2 3 2
2 4 4
2 1 6
2 9 6
2 15 0
2 6
2 11 1
EOD
set terminal gif animate delay 50 optimize
set output "myAnimation.gif"
set xrange[0:20]
set yrange[0:10]
do for [i=0:2] {
plot $Data u 2:($1==i?$3:NaN) w lp pt 7 ti sprintf("Time: %g",i)
}
set output
### end of code
Result:
Addition:
The meaning of $1==i?$3:NaN in words:
If the value in the first column is equal to i then the result is the value in the third column else it will be NaN ("Not a Number").

Picking out exacly one value from each row and column of a matrix

This is not exactly a question about code, but I need some help with the logic of the algorithm.
Given an NxN matrix which has at least one zero value on each row and column, how would you chose N zeros so that there is exactly one value on each row and each column? For example:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3
Clearly, you first have to choose the zeros that are singular on each row or column. I am not sure about the case when there is an equal number of zeros on several rows and columns. How would I pick the optimal values so that no line or column is left out?
This is the problem of finding a maximum cardinality matching in a bipartite graph: the rows represent one set of vertices u_1, u_2, ..., u_N, the columns the other set v_1, v_2, ..., v_N, and there is an edge u_i -- v_j whenever there is a 0 at matrix position (i, j).
It can be solved using maximum flow algorithms such as Ford-Fulkerson in O(N^3) time, or with the more specialised Hopcroft-Karp algorithm in O(N^2.5) time. In fact these algorithms solve a slightly more general problem: It will find a largest-possible set of unique (row, column) pairs such that each pair has a 0 in the matrix. (In your case, you happen to know that there is a solution with N such pairs: this is obviously best-possible.)
Select the row with least number of zeros.
For every zero in that row, pick the one whose column has the least number of zeros.
Mark that row and column in some way (maybe remove all zeors from them after storing the index of the selected zero? This one is up to you).
The marked rows and columns are skipped in the next iteration.
Repeat until all unmarked rows and columns are traversed, or until a further solution can't be built.
So for the sample problem, this is how the solution can be visualized ( < and ^ represent marked rows and columns ):
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3 // Row with least zeros, and last one to be accessed
Iteration 1:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5
0 8 0 1 3
8 6 0 1 3 <
_ _ ^ _ _
Iteration 2:
0 4 6 0 2
0 8 9 5 0
4 0 9 8 5 <
0 8 0 1 3
8 6 0 1 3 <
_ ^ ^ _ _
Iteration 3:
0 4 6 0 2
0 8 9 5 0 <
4 0 9 8 5 <
0 8 0 1 3
8 6 0 1 3 <
_ ^ ^ _ ^
Iteration 4:
0 4 6 0 2 <
0 8 9 5 0 <
4 0 9 8 5 <
0 8 0 1 3
8 6 0 1 3 <
_ ^ ^ ^ ^
Iteration 5:
0 4 6 0 2 <
0 8 9 5 0 <
4 0 9 8 5 <
0 8 0 1 3 <
8 6 0 1 3 <
^ ^ ^ ^ ^

Efficiently construct a square matrix with unique numbers in each row

A matrix of size nxn needs to be constructed with the desired properties.
n is even. (given as input to the algorithm)
Matrix should contain integers from 0 to n-1
Main diagonal should contain only zeroes and matrix should be symmetric.
All numbers in each row should be different.
For various n , any one of the possible output is required.
input
2
output
0 1
1 0
input
4
output
0 1 3 2
1 0 2 3
3 2 0 1
2 3 1 0
Now the only idea that comes to my mind is to brute-force build combinations recursively and prune.
How can this be done in a iterative way perhaps efficiently?
IMO, You can handle your answer by an algorithm to handle this:
If 8x8 result is:
0 1 2 3 4 5 6 7
1 0 3 2 5 4 7 6
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
4 5 6 7 0 1 2 3
5 4 7 6 1 0 3 2
6 7 4 5 2 3 0 1
7 6 5 4 3 2 1 0
You have actually a matrix of two 4x4 matrices in below pattern:
m0 => 0 1 2 3 m1 => 4 5 6 7 pattern => m0 m1
1 0 3 2 5 4 7 6 m1 m0
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
And also each 4x4 is a matrix of two 2x2 matrices with a relation to a power of 2:
m0 => 0 1 m1 => 2 3 pattern => m0 m1
1 0 3 2 m1 m0
In other explanation I should say you have a 2x2 matrix of 0 and 1 then you expand it to a 4x4 matrix by replacing each cell with a new 2x2 matrix:
0 => 0+2*0 1+2*0 1=> 0+2*1 1+2*1
1+2*0 0+2*0 1+2*1 0+2*1
result => 0 1 2 3
1 0 3 2
2 3 0 1
3 2 1 0
Now expand it again:
0,1=> as above 2=> 0+2*2 1+2*2 3=> 0+2*3 1+2*3
1+2*2 0+2*2 1+2*3 0+2*3
I can calculate value of each cell by this C# sample code:
// i: row, j: column, n: matrix dimension
var v = 0;
var m = 2;
do
{
var p = m/2;
v = v*2 + (i%(n/p) < n/m == j%(n/p) < n/m ? 0 : 1);
m *= 2;
} while (m <= n);
We know each row must contain each number. Likewise, each row contains each number.
Let us take CS convention of indices starting from 0.
First, consider how to place the 1's in the matrix. Choose a random number k0, from 1 to n-1. Place the 1 in row 0 at position (0,k0). In row 1, if k0 = 1 in which case there is already a one placed. Otherwise, there are n-2 free positions and place the 1 at position (1,k1). Continue in this way until all the 1 are placed. In the final row there is exactly one free position.
Next, repeat with the 2 which have to fit in the remaining places.
Now the problem is that we might not be able to actually complete the square. We may find there are some constraints which make it impossible to fill in the last digits. The problem is that checking a partially filled latin square is NP-complete.(wikipedia) This basically means pretty compute intensive and there no know short-cut algorithm. So I think the best you can do is generate squares and test if they work or not.
If you only want one particular square for each n then there might be simpler ways of generating them.
The link Ted Hopp gave in his comment Latin Squares. Simple Construction does provide a method for generating a square starting with the addition of integers mod n.
I might be wrong, but if you just look for printing a symmetric table - a special case of latin squares isomorphic to the symmetric difference operation table over a powerset({0,1,..,n}) mapped to a ring {0,1,2,..,2^n-1}.
One can also produce such a table, using XOR(i,j) where i and j are n*n table indexes.
For example:
def latin_powerset(n):
for i in range(n):
for j in range(n):
yield (i, j, i^j)
Printing tuples coming from previously defined special-case generator of symmetric latin squares declared above:
def print_latin_square(sq, n=None):
cells = [c for c in sq]
if n is None:
# find the length of the square side
n = 1; n2 = len(cells)
while n2 != n*n:
n += 1
rows = list()
for i in range(n):
rows.append(" ".join("{0}".format(cells[i*n + j][2]) for j in range(n)))
print("\n".join(rows))
square = latin_powerset(8)
print(print_latin_square(square))
outputs:
0 1 2 3 4 5 6 7
1 0 3 2 5 4 7 6
2 3 0 1 6 7 4 5
3 2 1 0 7 6 5 4
4 5 6 7 0 1 2 3
5 4 7 6 1 0 3 2
6 7 4 5 2 3 0 1
7 6 5 4 3 2 1 0
See also
This covers more generic cases of latin squares, rather than that super symmetrical case with the trivial code above:
https://www.cut-the-knot.org/arithmetic/latin2.shtml (also pointed in the comments above for symmetric latin square construction)
https://doc.sagemath.org/html/en/reference/combinat/sage/combinat/matrices/latin.html

Find row and column number of eight neighbors conditionally in Matlab

I have a 6 * 6 matrix
A=
3 8 8 8 8 8
4 6 1 0 7 -1
9 7 0 2 6 -1
7 0 0 5 4 4
4 -1 0 2 8 1
1 -1 0 8 3 9
I am interested in finding row and column number of neighbors starting from A(4,4)=5. But They will be linked to A(4,4) as neighbor only if A(4,4) has element 4 on right, 6 on left, 2 on top, 8 on bottom 1 on top left diagonally, 3 on top right diagonally, 7 on bottom left diagonally and 9 on bottom right diagonally. TO be more clear A(4,4) will have neighbors if the neighbors are surrounding A(4,4) as follows:
1 2 3;
6 5 4;
7 8 9;
And this will continue as each neighbor is found.
Also 0 and -1 will be ignored. In the end I want to have these cells' row and column number as shown in figure below. Is there any way to visualize this network as well. This is sample only. I really have a huge matrix.
A = [3 8 8 8 8 8;
4 6 1 0 7 -1;
9 7 0 2 6 -1;
7 0 0 5 4 4;
4 -1 0 2 8 1;
1 -1 0 8 3 9];
test = [1 2 3;
6 5 4;
7 8 9];
%//Pad A with zeros on each side so that comparing with test never overruns the boundries
%//BTW if you have the image processing toolbox you can use the padarray() function to handle this
P = zeros(size(A) + 2);
P(2:end-1, 2:end-1) = A;
current = zeros(size(A) + 2);
past = zeros(size(A) + 2);
%//Initial state (starting point)
current(5,5) = 1; %//This is A(4,4) but shifted up 1 because of the padding
condition = 1;
while sum(condition(:)) > 0;
%//get the coordinates of any new values added to current
[x, y] = find(current - past);
%//update past to last iterations current
past = current;
%//loop through all the coordinates returned by find above
for ii=1:size(x);
%//Make coord vectors that represent the current coordinate plus it 8 immediate neighbours.
%//Note that this is why we padded the side in the beginning, so if we hit a coordinate on an edge, we can still get 8 neighbours for it!
xcoords = x(ii)-1:x(ii)+1;
ycoords = y(ii)-1:y(ii)+1;
%//Update current based on comparing the coord and its neighbours against the test matrix, be sure to keep the past found points hence the OR
current(xcoords, ycoords) = (P(xcoords, ycoords) == test) | current(xcoords, ycoords);
end
%//The stopping condition is when current == past
condition = current - past;
end
%//Strip off the padded sides
FinalAnswer = current(2:end-1, 2:end-1)
[R, C] = find(FinalAnswer);
coords = [R C] %//This line is unnecessary, it just prints out the results at the end for you.
OK cool you got very close, so here is the final solution with the loops. It runs in about 0.002 seconds so it's pretty quick I think. The output is
FinalAnswer =
0 0 0 0 0 0
0 1 1 0 0 0
0 1 0 1 0 0
1 0 0 1 1 1
0 0 0 0 1 0
0 0 0 0 0 1
coords =
4 1
2 2
3 2
2 3
3 4
4 4
4 5
5 5
4 6
6 6

Adding zeros between every 2 elements of a matrix in matlab/octave

I am interested in how can I add rows and columns of zeros in a matrix so that it looks like this:
1 0 2 0 3
1 2 3 0 0 0 0 0
2 3 4 => 2 0 3 0 4
5 4 3 0 0 0 0 0
5 0 4 0 3
Actually I am interested in how can I do this efficiently, because walking the matrix and adding zeros takes a lot of time if you work with a big matrix.
Update:
Thank you very much.
Now I'm trying to replace the zeroes with the sum of their neighbors:
1 0 2 0 3 1 3 2 5 3
1 2 3 0 0 0 0 0 3 8 5 12... and so on
2 3 4 => 2 0 3 0 4 =>
5 4 3 0 0 0 0 0
5 0 4 0 3
as you can see i'm considering all the 8 neighbors of an element, but again using for and walking the matrix slows me down quite a bit, is there a faster way ?
Let your little matrix be called m1. Then:
m2 = zeros(5)
m2(1:2:end,1:2:end) = m1(:,:)
Obviously this is hard-wired to your example, I'll leave it to you to generalise.
Here are two ways to do part 2 of the question. The first does the shifts explicitly, and the second uses conv2. The second way should be faster.
M=[1 2 3; 2 3 4 ; 5 4 3];
% this matrix (M expanded) has zeros inserted, but also an extra row and column of zeros
Mex = kron(M,[1 0 ; 0 0 ]);
% The sum matrix is built from shifts of the original matrix
Msum = Mex + circshift(Mex,[1 0]) + ...
circshift(Mex,[-1 0]) +...
circshift(Mex,[0 -1]) + ...
circshift(Mex,[0 1]) + ...
circshift(Mex,[1 1]) + ...
circshift(Mex,[-1 1]) + ...
circshift(Mex,[1 -1]) + ...
circshift(Mex,[-1 -1]);
% trim the extra line
Msum = Msum(1:end-1,1:end-1)
% another version, a bit more fancy:
MexTrimmed = Mex(1:end-1,1:end-1);
MsumV2 = conv2(MexTrimmed,ones(3),'same')
Output:
Msum =
1 3 2 5 3
3 8 5 12 7
2 5 3 7 4
7 14 7 14 7
5 9 4 7 3
MsumV2 =
1 3 2 5 3
3 8 5 12 7
2 5 3 7 4
7 14 7 14 7
5 9 4 7 3

Resources