The simple recursive function doesn't work well - matlab

It's just an easy recursive function test.
It should stop at n = 3, but not.
Could you please tell me where is wrong in my code?
Thank you!
>> recursiveFunction(0)
101
1
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
2
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
3
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
function recursiveFunction(callHierarchie)
callHierarchie = callHierarchie + 1;
disp(callHierarchie + 100);
for n = 1:3
disp(n);
if callHierarchie <= 2
disp('g');
recursiveFunction(callHierarchie);
end
end
end

The problem is both how you're generating your output and how you're interpreting your output. Here's a Python equivalent function that generates the same output:
def recursiveFunction1(callHierarchie):
callHierarchie = callHierarchie + 1
print("{:>6}".format(callHierarchie + 100))
for n in range(1, 4):
print("{:>6}".format(n))
if callHierarchie <= 2:
print('g')
recursiveFunction(callHierarchie)
recursiveFunction(0)
Folks can verify it produces the same output. Let's modify the code to indent based on the recursion level:
def recursiveFunction(callHierarchie):
callHierarchie = callHierarchie + 1
print(" " * callHierarchie, "{:>6}".format(callHierarchie + 100))
for n in range(1, 4):
print(" " * callHierarchie, "{:>6}".format(n))
if callHierarchie <= 2:
print(" " * callHierarchie, 'g')
recursiveFunction(callHierarchie)
Now the output displays slightly differently:
% python3 test.py
101
1
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
2
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
3
g
102
1
g
103
1
2
3
2
g
103
1
2
3
3
g
103
1
2
3
%
You can see that n does stop at 3, but the extra numbers you were seeing were n at a different level of recursion!

Related

How do I subtract every row of a matrix with every row of a second matrix in matlab?

I have two matrices A (51 rows X 5100 columns) and B (51rows X 5100 columns) and I want to subtract every row of A with every row of B to obtain another matric C (2601 rows X 5100 columns). How can I have the matrix C?
You can do that by
permuting the matrices' dimensions to obtain 3D arrays of size (in your example) 51 × 1 × 5100 and 1 × 51 × 5100 respectively;
subtracting with implicit expansion, which gives an array of size 51 × 51 × 5100;
reshaping to collapse the first two dimensions into one, which gives the final 51*51 × 5100 matrix.
A = rand(51, 5100); % example matrix
B = rand(51, 5100); % example matrix, same number of columns
C = reshape(permute(A, [1 3 2]) - permute(B, [3 1 2]), [], size(A, 2));
The crux of the problem lies in getting the correct pairs of rows for both matrices. To do this, you could use the meshgrid() function to generate a matrix that varies from 1:n along its rows, and another that varies along its columns (where n is the number of rows).
For example:
mtx1 = reshape(1:9, 3, 3);
mtx2 = reshape(101:109, 3, 3);
n1 = size(mtx1, 1);
n2 = size(mtx2, 1);
[r1, r2] = meshgrid(1:n1, 1:n2);
This gives:
r1 =
1 2 3
1 2 3
1 2 3
r2 =
1 1 1
2 2 2
3 3 3
Next, flatten both r1 and r2:
f1 = r1(:)
f2 = r2(:)
Now, we have:
f1 =
1
1
1
2
2
2
3
3
3
f2 =
1
2
3
1
2
3
1
2
3
We can use f1 and f2 as the indices for our pairs of rows:
mtx1(f1, :) repeats the first row of mtx1 three times, then the second row, then the third row
mtx1(f1, :)
1 4 7
1 4 7
1 4 7
2 5 8
2 5 8
2 5 8
3 6 9
3 6 9
3 6 9
mtx2(f2, :) repeats the entire matrix mtx2 three times
mtx2(f2, :)
101 104 107
102 105 108
103 106 109
101 104 107
102 105 108
103 106 109
101 104 107
102 105 108
103 106 109
Subtract these two, and you get your pairwise difference of rows:
mtx2(f2, :) - mtx1(f1, :)
100 100 100
101 101 101
102 102 102
99 99 99
100 100 100
101 101 101
98 98 98
99 99 99
100 100 100
This also works when mtx1 and mtx2 have different row counts.

Merge 2 vectors according their time values

I would like to merge 2 vectors according their time values. This should look like this (column 1 = time, column 2 = actual value):
A =
1 234
3 121
4 456
6 6756
B =
2 435
5 90
10 365
Result:
C =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
Is there an elegant way to realize this in Matlab?
Here's an easy one-liner:
C = sortrows([A;B])
C =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
Note that this assumes that all of the time values in column 1 are unique. If this is not the case, you can use accumarray:
A =
1 234
3 121
4 456
6 6756
B =
2 435
5 90
10 365
B = [B; 1 512]
B =
2 435
5 90
10 365
1 512
C = [A;B];
D = accumarray(C(:,1),C(:,2));
U = unique(C(:,1));
E = [U,D(U)]
E =
1 746 %// 764 = 234 + 512
2 435
3 121
4 456
5 90
6 6756
10 365
First I would merge these matrices and then sort them by first column.
C = [A; B]
[Y, I] = sort(C(:,1))
C = C(I,:)
First you want to vertical concatenation:
A = [1 234; 3 121; 4 456; 6 6756];
B = [2 435; 5 90; 10 365];
C = vertcat(A,B)
Then you want to sort your answer based on the first column:
[~,inx]=sort(C(:,1));
out = C(inx,:);
>> out =
1 234
2 435
3 121
4 456
5 90
6 6756
10 365
So much more difficult than the 1 liner:
out = sortrows(C,1)
Why Matlab, why don't you have an option in sort to keep the index!
In the general case, you will need to do some form of concatenation and sorting. This is a one liner
C = sort([A,B],1);

How to combine numbers in different columns using matlab

excel has an equation or function to combine number in different column, as you can see in the picture below. having the same data in matlab , how can i combine numbers in a different columns.
having a d data:
a b c d
1 1 1 3
2 1 0 5
1 2 5 30
3 4 1 26
-1 1 1 3
since 111 and -111 have the same values of d, so i combine it so that 1st cell in 1st column became 111,-111 and their d become 6 because i add it up, so can matlab do that? thanks
a=[1 1 1 3;2 1 0 5; 1 2 5 30; 3 4 1 26; -1 1 1 3]
len=size(a);
x2=[]
for i=1:len(1)
s=num2str(a(i,1:len(2)-1));
s=s(s~=' ');
x2(i,:)=[str2num(s) (a(i,len(2)))];
end
Result:
x2 =
111 3
210 5
125 30
341 26
-111 3
now to find the repeated indices:
u=unique(x2(:,2));
n=histc(x2(:,2),u);
ind=find(x2(:,2)==u(n>1))
Result:
ind =
1
5
Ok now to sum and combine:
xx=x2(ind,:)
ss=sum(xx(:,2));
s=num2str(xx(:,1)');
s=strrep(s, ' ', ',')
x2(min(ind),2) = ss;
x2(ind(ind~=min(ind)),:) = []
C = num2cell(x2);
C(min(ind),1) = cellstr(s)
The final result is:
C =
'111,-111' [ 6]
[ 210] [ 5]
[ 125] [30]
[ 341] [26]

How to sum values among matrices of structures under certain conditions in Matlab?

I am new in matlab and I am not familiar with array of matrices. I have a number of matrices nx6:
<26x6 double>
<21x6 double>
<27x6 double>
<36x6 double>
<29x6 double>
<30x6 double>
....
Each matrix is of this type:
>> Matrix{1,1}
A B C D E F
1 2 6 223 735064.287500000 F11
2 3 6 223 735064.288194445 F12
3 4 6 223 735064.288888889 F13
4 5 6 223 735064.290277778 F14
>> Matrix{2,1}
A B C D E F
1 2 6 223 735064.700694445 F21
2 3 6 223 735064.701388889 F22
3 4 6 223 735064.702083333 F23
4 5 6 223 735064.702777778 F24
>> Matrix{3,1}
A B C D E F
1 2 7 86 735064.3541666666 F31
2 3 7 86 735064.3548611112 F32
3 4 7 86 735064.3555555555 F33
4 5 7 86 735064.3562499999 F34
5 6 7 86 735064.702777778 F35
>> Matrix{4,1}
A B C D E F
1 2 7 86 735064.3569444444 F41
2 3 7 86 735064.3576388888 F42
3 4 7 86 735064.3583333333 F43
4 5 7 86 735064.3590277778 F44
5 6 6 86 735064.702777778 F45
Where E and F are dates in datenum format. Specifically F is the time difference.
Considering all matrices at once, I would like to sum the values of column F among all the matrices that have equal values in columns A, B, D.
For each value of the column D (the number of bus), I would like to obtain a new matrix like the following one:
A B C D H
1 2 6 223 F11+F21
2 3 6 223 F12+F22
3 4 6 223 F13+F23
4 5 6 223 F14+F24
A B C D H
1 2 7 86 F31+F41
2 3 7 86 F32+F42
3 4 7 86 F33+F43
4 5 7 86 F34+F44
5 6 7 86 F35+F45
Thank you in advance for you help!
This approach should get you started. I suggested setting up a matrix that stores the comparison between the columns 1,2 and 4. Based on that matrix you can then generate your output matrix. This saves you nested if statements and checks in your loop.
Here's an example (please note that I changed row 3 of Matrix{1,1}):
Matrix{1,1} = [ ...
1 2 6 223 735064.287500000 1;
2 3 6 223 735064.288194445 2;
3 4 6 223 735064.288888889 3;
4 5 6 223 735064.290277778 4];
Matrix{2,1} = [ ...
1 2 6 223 735064.700694445 10;
2 3 6 223 735064.701388889 10;
2 4 6 223 735064.702083333 10;
4 5 6 223 735064.702777778 10];
COMP = Matrix{1,1}(:,[1:2 4])==Matrix{2,1}(:,[1:2 4]);
a = 1;
for i=1:size(Matrix{1,1},1)
if sum(COMP(i,:)) == 3
SUM{1,1}(a,1:5) = Matrix{1,1}(i,1:5);
SUM{1,1}(a,6) = Matrix{1,1}(i,6) + Matrix{2,1}(i,6);
a = a + 1;
end
end
The matrix COMP stores a 1 for each element that is the same in Matrix{1,1} and Matrix{2,1} when comparing columns 1, 2 and 4.
This reduces the if-statement to a check if all elements in a row agree (hence sum == 3). If that condition is satisfied, a new matrix is generated (SUM{1,1}) which sums the entries in column 6, in this case:
SUM{1,1}(:,6) =
11
12
14

Laplacian Filter Formula

I tried Laplacian filter method but i think I did somethings wrong with its formula.
My original matrix (f)
a b
a 1 2
b 3 4
New matrix (g) by padding old matrix and replicating the origial one for using 3x3 filter mask
a b c d e f
a 1 2 1 2 1 2
b 3 4 3 4 3 4
c 1 2 1 2 1 2
d 3 4 3 4 3 4
e 1 2 1 2 1 2
f 3 4 3 4 3 4
The filter (m)
a b c
a 0 1 0
b 1 -4 1
c 0 1 0
Then I start at [c,c] in the new matrix. What I did in the calculation was
g(c,c) = g (c,c) + -1* (m(a,a)*g(b,b) + m(a,b)*g(b,c) + m(a,c)*g(b,d) + m(b,a)*g(c,b) + m(b,b)*g(c,c) + m(b,c)*g(c,d) + m(c,a)*g(d,b) + m(c,b)*g(d,c) + m(c,c)*g(d,d));
After performing the filter on g(c,c) , g(c,d) , g(d,c) , g (d,d), I crop the matrix as filtered these filter point to the new matrix, but the result look really weird. (not like in the book). I tried doing it in matlab by myself.
Can someday help me with this? Thank you very much
To get the same results as Nasser's method using conv2 and filter2 (which are only the same because your filter has symmetric rows), first you can't do it in-place. Previously filtered entries will mess up the subsequent calculations. Second, I'm not sure where that g(c,c) + -1* comes in. A normal filter calculation for g(c,c) would be:
r(c,c) = m(a,a)*g(b,b) + m(a,b)*g(b,c) + m(a,c)*g(b,d) +...
m(b,a)*g(c,b) + m(b,b)*g(c,c) + m(b,c)*g(c,d) +...
m(c,a)*g(d,b) + m(c,b)*g(d,c) + m(c,c)*g(d,d);
where r is the result matrix. This method (repeated for the other 3 values in the original matrix) gives:
r =
c d
c 6 2
d -2 -6
UPDATE
using:
A =
1 2 1 2 1 2
3 4 3 4 3 4
1 2 1 2 1 2
3 4 3 4 3 4
1 2 1 2 1 2
3 4 3 4 3 4
mask =
0 1 0
1 -4 1
0 1 0
imfilter gives:
imfilter(A,mask)
ans =
1 -2 3 -2 3 -3
-6 -6 -2 -6 -2 -9
4 2 6 2 6 1
-6 -6 -2 -6 -2 -9
4 2 6 2 6 1
-7 -8 -3 -8 -3 -11
The function suggested above,
for i=1:2
for j=1:2
r(i,j) = m(1,1)*g(i+1,j+1) + m(1,2)*g(i+1,j+2) + m(1,3)*g(i+1,j+3) +...
m(2,1)*g(i+2,j+1) + m(2,2)*g(i+2,j+2) + m(2,3)*g(i+2,j+3) +...
m(3,1)*g(i+3,j+1) + m(3,2)*g(i+3,j+2) + m(3,3)*g(i+3,j+3);
end
end
gives:
ans =
6 2
-2 -6
Does this match what you expect to see?
Note: The function above is not how I would implement it, but it follows the example that you gave for clarity.