Curious behaviour with anonymous functions in Octave and MATLAB - matlab

Hi I am curious why I am getting the following behaviour with MATLAB and Octave
octave:7> pdf = #(x) (0<=x && x<1).* (x) + (1<=x && x <=2).* (2-x);
octave:8>
octave:8> t = 0:0.1:1;
octave:9>
octave:9> y = pdf(t)
y =
0 0 0 0 0 0 0 0 0 0 0
octave:10>
I get the same behavior with MATLAB i.e. y is a zero vector.
But if I add the following for loop
for i=1:size(t,1)
y(i) = pdf(t(i))
end
then I get the correct result.
Columns 1 through 19:
0.00000 0.10000 0.20000 0.30000 0.40000 0.50000 0.60000 0.70000 0.80000 0.90000 1.00000 0.90000 0.80000 0.70000 0.60000 0.50000 0.40000 0.30000 0.20000
Columns 20 and 21:
0.10000 0.00000

The && and || are the short circuit operators, meant for use with scalars. Replace with & or |. I get an error when executing the above (vectorized) code in Matlab (R2011B).
After replacing the && with & it seems to work as you expect.

Related

Changing diagonal values if equal to 1

I want to change the diagonal values if equal to 1.
is it possible to look for diagonals and change the values in this particular diagonal to another value.
For example:
X =
1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1
I want to change this diagonal :
1
0
1
to
2.2
0
2.2
I tried:
XX(logical(eye(size(XX)))) = 2
but this will change all the values not only ones.
Could you please explain how to do that for other diagonals?
The function diag is useful to manipulate diagonals. It only extracts a diagonal from a matrix, or forms a new matrix given a vector of diagonal elements. But with appropriate arithmetic this is sufficient:
X = [1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1];
k = 2; % which diagonal to change
d = diag(X,k); % the old diagonal
n = d;
n(n==1) = 2.2; % the new diagonal values
X = X - diag(d,k) + diag(n,k); % subtract old values from diagonal, add new ones
Output:
X =
1.00000 1.00000 2.20000 0.00000
1.00000 1.00000 0.00000 2.20000
1.00000 0.00000 1.00000 1.00000
0.00000 1.00000 1.00000 1.00000
Here comes a solution only using linear indexing. I wanted to avoid generating additional matrices. Nothing's wrong with Cris Luengo's answer, that was just for fun.
% Input.
X = [1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1]
% Which diagonal to change.
k = 2;
% Determine dimension.
dim = size(X, 1);
% Calculate indices of diagonal elements.
idx = (max(abs(k), k * dim) + 1):(dim + 1):numel(X);
idx = idx(1:end+min(k+1, 0));
% Replace diagonal elements with new value.
X(idx(X(idx) == 1)) = 2.2
Output:
X =
1.00000 1.00000 2.20000 0.00000
1.00000 1.00000 0.00000 2.20000
1.00000 0.00000 1.00000 1.00000
0.00000 1.00000 1.00000 1.00000

Substitute a vector of variables for syms when using linsolve for linear equations

I am trying to solve linear equations with many variables. So i used this to create multiple variables.
xvariables = sym('x', [n 1])
where n is the number of variables and it created a vector of variables x1 x2 x3...xn
So how do I use this vector beside syms when using linsolve instead of listing out all the variables?
% syms xvariables (something like that) instead of:
syms x2 x3 x4 x5 x6 x7 x8
eqn1 = 0.5*x2 + 0.12*x3 == 21.8;
eqn2 = 0.12*x2 + 0.5*x3 + 0.12*x4 == 21.9;
eqn3 = 0.12*x3 + 0.5*x4 + 0.12*x5 == 47.8;
eqn4 = 0.12*x4 + 0.5*x5 + 0.12*x6 == 37.6;
eqn5 = 0.12*x5 + 0.5*x6 + 0.12*x7 == 27.5;
eqn6 = 0.12*x6 + 0.5*x7 + 0.12*x8 == 52.5;
eqn7 = 0.12*x7 + 0.5*x8 == 59;
[A,B] = equationsToMatrix([eqn1, eqn2, eqn3, eqn4, eqn5, eqn6, eqn7], [x2, x3, x4, x5, x6, x7, x8])
X = linsolve(A,B)
I hope that makes sense. Thanks!
When using sym('x',[n 1]) you are creating a symbolic vector with automatically generated elements [x1; x2; ...; xn]. The elements do not directly appear in the MATLAB workspace but they are accessible by using parentheses on the created variable (xvariables in your question, x in my answer). Therefore we use the same syntax as with a 'normal' vector/matrix. Thus xn can be accessed with x(n).
For the equations we can use a vector as well and store them in a single variable eqn. This additionally simplifies the call to equationsToMatrix.
This yields the following code:
x = sym('x', [7 1]);
eqn(1) = 0.50*x(1) + 0.12*x(2) == 21.8;
eqn(2) = 0.12*x(1) + 0.50*x(2) + 0.12*x(3) == 21.9;
eqn(3) = 0.12*x(2) + 0.50*x(3) + 0.12*x(4) == 47.8;
eqn(4) = 0.12*x(3) + 0.50*x(4) + 0.12*x(5) == 37.6;
eqn(5) = 0.12*x(4) + 0.50*x(5) + 0.12*x(6) == 27.5;
eqn(6) = 0.12*x(5) + 0.50*x(6) + 0.12*x(7) == 52.5;
eqn(7) = 0.12*x(6) + 0.50*x(7) == 59;
[A,B] = equationsToMatrix(eqn, x)
X = linsolve(A,B)
You have better to use the mldivideoperator. (symbol \) (in my opinion!)
You have your matrix P that contains the equation:
p =
[0.50000 0.12000 0.00000 0.00000 0.00000 0.00000 0.00000;
0.12000 0.50000 0.12000 0.00000 0.00000 0.00000 0.00000;
0.00000 0.12000 0.50000 0.12000 0.00000 0.00000 0.00000;
0.00000 0.00000 0.12000 0.50000 0.12000 0.00000 0.00000;
0.00000 0.00000 0.00000 0.12000 0.50000 0.12000 0.00000;
0.00000 0.00000 0.00000 0.00000 0.12000 0.50000 0.12000;
0.00000 0.00000 0.00000 0.00000 0.00000 0.12000 0.50000]
or if you don't want to write the 0:
p = zeros(7)
p(1,1) = 0.5;
p(1,2) = 0.12;
p(2,1) = 0.12;
...
Your vector s that contains the solution
s = [21.8,21.9,47.8,37.6,27.5,52.5,59]'
And you can resolve your system with:
>> res = p\s
res =
40.0000 %x2
15.0000 %x3
80.0000 %x...
50.0000
25.0000
75.0000
100.0000

Combining columns of two matrices of different dimension in Matlab?

I have a matrix in Matlab A of dimension nx3, e.g. n=8
A=[ 0.3 2 2;
0.3 7 7;
0.3 10 10;
0 15 15;
0.3 18 2;
0.3 23 7;
0 26 10;
0.3 31 15]
and a matrix B of dimension mx4, e.g. m=17
B=[1 1 0.05 0.05;
2 2 0.22 0.22;
3 3 0.19 0.05;
5 5 0.02 0.02;
6 6 0.19 0 ;
7 7 0.30 0.11;
10 10 0.27 0.08;
11 11 0.19 0 ;
12 12 0.05 0.05;
18 2 0.25 0.08;
19 3 0.25 0.08;
21 5 0.02 0.02;
22 6 0.22 0.08;
23 7 0.22 0.08;
30 14 0.19 0.08;
31 15 0.19 0.08;
32 16 0.05 0.05]
I want to create a matrix C following these steps WITHOUT USING LOOPS:
1) Generate C=[];
2) Consider B(i,1). If there exists A(j,2)=B(i,1) [it can happen only once] report C=[ C; B(i,1) B(i,2) B(i,3) B(i,4) A(i,1)]. Do this for i=1,...,m.
3) Consider B(h,1) such that there is no j with A(j,2)=B(h,1). Report C=[C; B(h,1) B(h,2) B(h,3) B(h,4) 0]. Do this for h=1,...,m.
4) Consider A(h,2) such that there is no j with B(j,1)=A(h,2). Report C=[C; A(h,2) A(h,3) 0 0 A(h,1)]. Do this for h=1,...,n.
In the example above I want to get
C=[2 2 0.22 0.22 0.3;
7 7 0.30 0.11 0.3;
10 10 0.27 0.08 0.3;
18 2 0.25 0.08 0.3;
23 7 0.22 0.08 0.3;
31 15 0.19 0.08 0.3; %end step 2)
---------------------
1 1 0.05 0.05 0 ;
3 3 0.19 0.05 0 ;
5 5 0.02 0.02 0 ;
6 6 0.19 0 0 ;
11 11 0.19 0 0 ;
12 12 0.05 0.05 0 ;
19 3 0.25 0.08 0 ;
21 5 0.02 0.02 0 ;
22 6 0.22 0.08 0 ;
30 14 0.19 0.08 0 ;
32 16 0.05 0.05 0 ;
----------------------- %end step 3)
15 15 0 0 0 ;
26 10 0 0 0 ] %end step 4)
These code does what I want but it is too slow with bigger matrices
C=[];
%Step 1)
for l=1:size(B,1)
for h=1:size(A,1)
if B(l,1)==A(h,2)
C=[C; B(l,:) A(h,1)];
end
end
end
% Steps 2) and 3)
C=[C; ...
[B(logical(1-ismember(B(:,1), A(:,2))),:) zeros(size(B(logical(1-ismember(B(:,1), A(:,2))),:),1),1)];...
[A(logical(1-ismember(A(:,2), B(:,1))),2:3) ...
zeros(size(A(logical(1-ismember(A(:,2), B(:,1)))),1),2) ...
A(logical(1-ismember(A(:,2), B(:,1))),1)]];
Although it smells strongly like homework, here is some code. See it as a tutorial on matrix operations (tested with Octave).
% Step 1
[~,j,k] = intersect(B(:,1),A(:,2));
C = [B(j,:) A(k,1)];
% Step 2
[~,k] = setdiff(B(:,1),A(:,2));
C = [C; B(k,:) zeros(size(k,1),1)]
% Step 3
[~,k] = setdiff(A(:,2),B(:,1));
C = [C; A(k,[2 3]) zeros(size(k,1),2) A(k,1)]
C =
2.00000 2.00000 0.22000 0.22000 0.30000
7.00000 7.00000 0.30000 0.11000 0.30000
10.00000 10.00000 0.27000 0.08000 0.30000
18.00000 2.00000 0.25000 0.08000 0.30000
23.00000 7.00000 0.22000 0.08000 0.30000
31.00000 15.00000 0.19000 0.08000 0.30000
1.00000 1.00000 0.05000 0.05000 0.00000
3.00000 3.00000 0.19000 0.05000 0.00000
5.00000 5.00000 0.02000 0.02000 0.00000
6.00000 6.00000 0.19000 0.00000 0.00000
11.00000 11.00000 0.19000 0.00000 0.00000
12.00000 12.00000 0.05000 0.05000 0.00000
19.00000 3.00000 0.25000 0.08000 0.00000
21.00000 5.00000 0.02000 0.02000 0.00000
22.00000 6.00000 0.22000 0.08000 0.00000
30.00000 14.00000 0.19000 0.08000 0.00000
32.00000 16.00000 0.05000 0.05000 0.00000
15.00000 15.00000 0.00000 0.00000 0.00000
26.00000 10.00000 0.00000 0.00000 0.00000

How do you create a 3d array which increase the value with each layer in Matlab?

i.e, a 3d matrix where all the values on each layer are the same, but the value on each sheet increments as the layers are increased.
The increment could be defined by x = (0:0.5:2*pi), for example.
I've tried using repmat, but this only seems to produce the matrix in another orientation.
Thanks!
One more possibility: use ndgrid, used here to create a 4-by-5-by-#x array:
x = 0:0.5:2*pi;
[~,~,out] = ndgrid(1:4,1:5,x);
You can do this using repmat and permute:
x = (0:0.5:2*pi);
y = repmat(x',[1,5,5]);
z = permute(y,[2,3,1]);
size(z)
ans =
5 5 13
z(:,:,1)
ans =
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
z(:,:,2)
ans =
0.50000 0.50000 0.50000 0.50000 0.50000
0.50000 0.50000 0.50000 0.50000 0.50000
0.50000 0.50000 0.50000 0.50000 0.50000
0.50000 0.50000 0.50000 0.50000 0.50000
0.50000 0.50000 0.50000 0.50000 0.50000
Define x
x = (0:0.5:2*pi);
This will have the values varying along the row (2nd dimension). Change your x to vary along the dimension you want (3rd dimension):
x = permute(x, [1, 3, 2]);
then repmat it:
x = repmat(x, [3, 3, 1]);

Rotation matrix is not orthogonal

I have rotation matrix which is not orthogonal. Whats wrong. I can't get it.
Exterior=[-6.6861,12.6118,-8.0660,[-0.4467,-0.3168,0.2380]*pi/180];%# deg 2 rad
%#data
ax=Exterior(4);
by=Exterior(5);
cz=Exterior(6);
%#Rotation in X
Rx = [1 0 0
0 cos(ax) -sin(ax)
0 sin(ax) cos(ax)];
%#Rotation in Y
Ry = [cos(by) 0 sin(by)
0 1 0
-sin(by) 0 cos(by)];
%#Rotation in Z
Rz = [cos(cz) -sin(cz) 0
sin(cz) cos(cz) 0
0 0 1];
R=Rx*Ry*Rz;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
R =
0.99998 -0.0041538 -0.0055292
0.0041969 0.99996 0.0077962
0.0054966 -0.0078192 0.99995
Orthogonality check
Inv(R)-R'=
2.2204e-016 2.6021e-018 8.6736e-019
0 1.1102e-016 -1.7347e-018
-2.6021e-018 3.4694e-018 2.2204e-016
R*R'=
2.2204e-016 2.6021e-018 8.6736e-019
0 1.1102e-016 -1.7347e-018
-2.6021e-018 3.4694e-018 2.2204e-016
Why there is different signs.???????
Any mistake??
Looks like the numbers in your orthogonality check are just due to rounding errors... They're really quite tiny.
There is an error in the question, pointed out by #ChisA. The OP pasted the same matrix for inv(R)-R' and R*R'
If we reconstruct the input file:
Exterior = [-6.681,12.6118,-8.0660,[-0.4467,-03168,0.2380]*pi/180]
ax = Exterior(4)
by = Exterior(5)
cz = Exterior(6)
Rx = [1 0 0 ; 0 cos(ax) -sin(ax) ; 0 sin(ax) cos(ax)]
Ry = [cos(by) 0 sin(by) ; 0 1 0 ; -sin(by) 0 cos(by)]
Rz = [cos(cz) -sin(cz) 0 ; sin(cz) cos(cz) 0 ; 0 0 1]
R = Rx*Ry*Rz
inv(R)-R'
R*R'
And run in through Octave (I don't have MATLAB):
Exterior =
-6.6810e+00 1.2612e+01 -8.0660e+00 -7.7964e-03 -5.5292e+01 4.1539e-03
ax = -0.0077964
by = -55.292
cz = 0.0041539
Rx =
1.00000 0.00000 0.00000
0.00000 0.99997 0.00780
0.00000 -0.00780 0.99997
Ry =
0.30902 0.00000 0.95106
0.00000 1.00000 0.00000
-0.95106 0.00000 0.30902
Rz =
0.99999 -0.00415 0.00000
0.00415 0.99999 0.00000
0.00000 0.00000 1.00000
R =
0.3090143 -0.0012836 0.9510565
-0.0032609 0.9999918 0.0024092
-0.9510518 -0.0038458 0.3090076
ans =
-5.5511e-17 1.3010e-18 1.1102e-16
2.1684e-19 0.0000e+00 -4.3368e-19
-1.1102e-16 -4.3368e-19 -5.5511e-17
ans =
1.0000e+00 -1.9651e-19 -4.6621e-18
-1.9651e-19 1.0000e+00 8.4296e-19
-4.6621e-18 8.4296e-19 1.0000e+00
Notice the R*R' is very close to I and inv(R)-R' is very close to 0.
Notice also that I get different small values than the OP. Because I am using a different piece of software the rounding errors will be different. So you should never rely on an exact comparison between two floating point numbers. You always should include some tolerance.
I hope this makes things a little clearer. See the comment by #gnovice below for links to more detailed information about rounding errors.
I don't understand why R*R' should be nearly zero. It should be the 3x3 identity matrix.
You might have a copy and paste error on your original question.