Matlab Matrix dimensions must agree - matlab

Why am I getting this error? The matrices are absolutely of the same size:
L=rand(4,1000);
for i=1:1000;
A(i)=logzn(0.1,0.4,L(4,i));
B(i)=logzn(0.3,0.7,L(4,i));
C(i)=logzn(0.5,1.0,L(4,i));
end
F=(~A&B | ~B&C);
Here's the logzn function:
function [ y ] = logzn( aMin,aMax,x )
if ((aMin<=x)&&(aMax>=x))
y=1;
else
y=0;
end
Here's the error I get:
Error using &
Matrix dimensions must agree.

The error means exactly what it says, that A, B, and C are not the same size. You can check it with:
isequal(size(A), size(B)) && isequal(size(A), size(C))
That being said, the code as you've posted it doesn't have any issues; however if the error is in fact coming from these lines of code, you must have initialized A, B, and C to be different sizes somewhere else in the script (or you potentially used the same variable names previously and didn't clear them). You will want to pre-allocate them before the loop to ensure they are the same size.
L = rand(4, 1000);
[A, B, C] = deal(zeros(size(L,2), 1));
for k = 1:size(L,2);
A(k)=logzn(0.1,0.4,L(4,k));
B(k)=logzn(0.3,0.7,L(4,k));
C(k)=logzn(0.5,1.0,L(4,k));
end
F=(~A&B | ~B&C);

Related

Matlab 'Function Unset/Unused'

I am new to Matlab, so there is a lot I do not understand; I have three questions, as followed:
The biggest issue I have revolves around function B= upper_triang(A) where it states that it is 'a function unused'. Reading through the Matlab tooltip, and I am guessing that it has to do with a value that has not been defined? ANd B of course being unset, but I thought I defined B as a function, so why is it unset? I am assuming that B is U, but in the math part that is ahh, so I am not sure what it would be.
To give context to my code I sent the part of the homework code I have a question on.
%%%This is for part a for problem 1.
A=zeros(8,8);%%%For the size column and row size of matrix A.
for j=1:8
for k=1:8
if j==k
A(j,k)=-2;
end
if abs(j-k)==1
A(j,k)=1;
end
end
end
[L,U]=lu(A); %%%Proving L and U.
L*U; %%%Proving that L*U=A, thus it is correct.
%%%This is for part b for problem 1
function B= upper_triang(A)
%%%Input A--> Matrix for m*n for the size
%%%Output B--> Is the upper triangular matrix of the same size
[m,n]=size(A);
for k=1:m-1
for i=k+1:m
u=A(i,k)/A(k,k);
for j=(k):n
A(i,j)=A(i,j)-u*A(k,j);
end
end
end
B-A;
end
Function being unused
The problem here is that you've only created a function, but you've never used it. Everything after the function B = upper_triang(A) just tells Matlab what to do in case that function is ever called, but your never do.
I'm guessing that, after your LU decomposition but before the declaration of your function, you should add a line
B = upper_triang(A);
Output unset
There is a second problem which is that, while you declared that B should be the output of your function upper_triang(), it it not "created" anywhere in the function itself.
There should be a line somewhere with
B = something;
Now, my linear algebra is quite rusty but I think that what you're trying to do should rather be:
%%%This is for part b for problem 1
function B= upper_triang(A)
%%%Input A--> Matrix for m*n for the size
%%%Output B--> Is the upper triangular matrix of the same size
[m,n]=size(A);
B = A; % copy the input matrix in B, and work with it from now on
for k=1:m-1
for i=k+1:m
u=B(i,k)/B(k,k);
for j=(k):n
B(i,j)=B(i,j)-u*B(k,j);
end
end
end
B = B - A; % not really sure about this
end

Add debug code to error messages in Matlab?

In Matlab, I often have to work with matrices coming from another person's code, and there's not always a clear convention on the orientation of the matrices (transposed or not) and if a certain row/column is added. Therefore I spend much of my time debugging the following error
Error using *
Inner matrix dimensions must agree.
And similar errors for +,.*,-,etc.
It would save me a lot of time if I could modify this error message to include the dimensions, so that I know which one to switch, and potentially guess where the wrong dimension got into. Hence, I would like to somehow modify the error message to include the dimensions at hand:
Error using *
Inner matrix dimensions must agree: 243 x 23 and 98 x 23.
Is this possible, and if so, how can I do it? I currently spend a lot of time adding/removing/testing debug code that prints out this info, so any solution that brings this any closer would be helpful!
You can use a try-catch block:
a = rand(12);
b = rand(10);
try
c = a*b;
catch err
% Because err is read-only, generate new error structure
% We can copy most of old one
newerr.identifier = err.identifier;
newerr.cause = err.cause;
newerr.stack = err.stack;
newerr.message = sprintf('%s size(a): [%u, %u] size(b): [%u, %u]', err.message, size(a), size(b));
error(newerr) % Throw new error
end
Now we get:
Error using testcode (line 5)
Inner matrix dimensions must agree. size(a): [12, 12] size(b): [10, 10]
Each arithmetic operator in Matlab has an associated method that gets called when you invoke that operator. For example, the method corresponding to * (matrix multiplication) is called mtimes.
For each operator, you can define a method for variables of type double that shadows the builtin method and modifies its behaviour: in your case, include custom error checking and then call the builtin method.
The advantages of this approach are:
No modification in your code is neccessary: you will use *, *., + etc normally; but their (error-checking) behaviour will change.
When (you think) you're done debugging, you only need to remove your custom methods from the path. This will restore normal behaviour and thus avoid any speed penalty. Later, if you need to debug again, all you need to do is place the modified methods back on the path.
In the following I use * and its associated mtimes as an example. Your new mtimes method should be placed in Matlab's path, in an appropriate folder so that it has precedence over the bulitin mtimes. That means the folder should be up in Matlab's path. Or you can use the current folder, which has precedence over all others.
Within the selected folder create a folder called #double, and in it create a file called mtimes.m. This tells Matlab that your mtimes.m file should be used whenever the * is invoked with double inputs.
The contents of mtimes.m whould be something along the following lines:
function C = mtimes(A,B)
if ndims(A)~=2 || ndims(B)~=2
%// number of dimensions is incorrect
error('MATLAB:mtimes_modified:ndims', ...
'One of the arrays is not a matrix: numbers of dimensions are %i and %i',...
ndims(A), ndims(B));
elseif max(size(A))>1 & max(size(B))>1 size(A,2)~=size(B,1)
%// dimensions are not appropriate for matrix multiplication,
%// or for multiplying by a matrix by a scalar
error('MATLAB:plus_modified:dimagree',...
'Sizes do not match: %i x %i and %i x %i', ...
size(A,1), size(A,2), size(B,1), size(B,2));
else
C = builtin('mtimes', A, B); %// call actual mtimes to multiply matrices
end
Example results:
>> rand(3,4,5)*rand(6,7)
Error using * (line 3)
One of the arrays is not a matrix: numbers of dimensions are 3 and 2
>> rand(3,4)*rand(2,5)
Error using * (line 7)
Sizes do not match: 3 x 4 and 2 x 5
>> rand(3,4)*rand(4,2)
ans =
0.3162 0.3009
1.2628 0.7552
1.2488 0.8559
If you must do it with many calculations of matrices, then you can write functions like this for example:
function C = matproduct(A, B)
try
C = A * B;
catch ME
switch ME.identifier
case 'MATLAB:dimagree'
msg = [ME.message, ' Size of ', inputname(1), ' :', num2str(size(A)), '. Size of ', inputname(2), ' :', num2str(size(B)), '.'];
case 'MATLAB:innerdim'
msg = [ME.message, ' Size of ', inputname(1), ' :', num2str(size(A)), '. Size of ', inputname(2), ' :', num2str(size(B)), '.'];
% other cases and corresponding modified msg here
end
throw(MException(ME.identifier, msg));
end
end
However i'm not sure if it affects the speed ... And if you use it as matproduct(matproduct(a, b), c) for a * b * c for example, then name of the 1st input cannot be displayed.

issue with surface with MATLAB

a = 10:100
b = 10:100
c = power(a,b)
surf(a,b,c)
=> Error using surf (line 78)
Z must be a matrix, not a scalar or vector
any clue ?
Here's a vectorized way using bsxfun:
a = 10:100;
b = 1:.1:10; %// changed b to avoid very large numbers
c = bsxfun(#power, a, b.');
surf(a,b,c)
c=power(a,b) does not give you the combinations of all a power b, unfortunately.
Here there is a way of doing it (though most likely there is a vectorizedd way of doing it)
a = 10:100;
b = linspace(1,10,length(a));
% I changed the values of b, because 100^100 is that a big number that Matlab will not plot it, it is too big for storing in a double
%loop and save
for ii=1:length(b)
c(ii,:)=a.^(b(ii));
end
surf(a,b,c)

Calculating Errors of the Trapezoidal Rule in MATLAB

I'm trying to calculate how the errors depend on the step, h, for the trapezoidal rule. The errors should get smaller with a smaller value of h, but for me this doesn't happen. This is my code:
Iref is a reference value calculated and verified with Simpson's method and the MATLAB function quad, respectively
for h = 0.01:0.1:1
x = a:h:b;
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref)
end
I think there's something wrong with the way I'm using h, because the trapezoidal rule works for known integrals. I would be really happy if someone could help me with this, because I can't understand why the errors are "jumping around" the way the do.
I wonder if maybe part of the problem is that not all intervals - for each step size h - have the same a and b just because of the way that x is constructed. Try the following with the additional fprintf statement:
for h = 0.01:0.1:1
x = a:h:b;
fprintf('a=%f b=%f\n',x(1),x(end));
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref);
end
Depending upon your a and b (I chose a=0 and b=5) all the a values were identical (as expected) but the b varied from 4.55 to 5.0.
I think that you always want to keep the interval [a,b] the same for each step size that you choose in order to get a better comparison between each iteration. So rather than iterating over the step size, you could instead iterate over the n, the number of equally spaced sub-intervals within [a,b].
Rather than
for h = 0.01:0.1:1
x = a:h:b;
you could do something more like
% iterate over each value of n, chosen so that the step size
% is similar to what you had before
for n = [501 46 24 17 13 10 9 8 7 6]
% create an equally spaced vector of n numbers between a and b
x = linspace(a,b,n);
% get the step delta
h = x(2)-x(1);
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref);
fprintf('a=%f b=%f len=%d h=%f Error=%f\n',x(1),x(end),length(x),h,Error);
end
When you evaluate the above code, you will notice that a and b are consistent for each iteration, h is roughly what you chose before, and the Error does increase as the step size increases.
Try the above and see what happens!

Trouble iterating a function with one input and two outputs on Matlab

I've created a function (name it MyFunction) which, given a matrix A, outputs two matrices B and C i.e. [B C] = MyFunction(A).
I'm trying to create another function which, when given a matrix A, will calculate MyFunction(A) and then calculate MyFunction(B) = [D E] and MyFunction(C) = [F G], and then calculate MyFunction(D), MyFunction(E), MyFunction(F) and MyFunction(G), and so on, until the matrices it outputs start to repeat. I know this process necessarily terminates.
I'm really having difficulty constructing this code. Any advice would be really appreciated.
I think what you're trying to do is binary tree recursion. It's hard to give a good solution without knowing more about the problem, especially without knowing what you want as the output of this process.
I whipped this up to give an example of how you could do this. It's not necessarily the most efficient because it stores all of the results at every step. Given an input matrix A, it calculates a 2-output function [B, C] = MyFunction(A) and looks for either isequal(A, B) or isequal(A, C). When that occurs, it outputs the depth of the tree at that point, i.e. how many iterations had to occur before there was a repetition. The bit with global variables is just so that I could do a simple example with an easy fixed point (the k'th iteration is just A^k). It will iterate a maximum of 10 times.
function depth = myRecursor(A)
global A_orig;
A_orig = A;
depth = 1;
max_depth = 10;
pvs_level = cell(1);
pvs_level{1} = A;
while depth < max_depth,
this_level = cell(2*length(pvs_level), 1);
for ix = 1 : length(pvs_level),
[B, C] = MyFunction(pvs_level{ix})
if isequal(B, A) || isequal(C, A),
return;
end
this_level{2*ix - 1} = B;
this_level{2*ix} = C;
end
depth = depth + 1;
pvs_level = this_level;
end
function [B, C] = MyFunction(A)
global A_orig;
B = A_orig*A;
C = 2*A;
So, for example myRecursor(eye(2)) gives 1 (duh) and myRecursor([0 1; 1 0]) gives 2.
EDIT: rewritten wrong alg
function [list] = newFunction(A) % returns all matrix generated matrix
list{1}=A;
done=0;
ii = 1;
while(~done)
[B C] = myFunction(list{ii});
list = list{list{:}, B, C};
for jj=1:numel(list)-2
if(all(all(list{jj}==B)) || all(all(list{jj}==C)))
done = 1;
end
end
ii=ii+1;
end
end
UPDATE: a more general way to handle an unknown number of outputs is to modify myFunction so that it outputs all matrices within a single cell vector. This way you can concatenate list this way:
[newMat] = myFunctions(list{ii}); % where newMat={B,C,...}
list = {list{:}, newMat{:}}; % or list=cat(2,list,newMat)
for jj=1:numel(list)-numel(newMat)
for nn=1:numel(newMat) % checking for repetitions
if(all(all(list{jj}==newMat{nn})))
done=1;
end
end
end
I think you should use cells:
function [B]=Myfunction(A)
B=cell(1,numel(A)*2);
for n=1:numel(A)
B{n}=func1(A{n}) %%% put some processing here
B{numel(A)+n}=func2(A{n}) %%% put some other processing here
end
end