Appending a row/column of different size to an array. - matlab

Recently, I came across this behaviour in Matlab and I am curious as to know why this happens.
a(1,:) = rand(4,1);
a(2,:) = rand(5,1);
This throws me Subscripted assignment dimension mismatch. error whereas
a(1,:) = rand(4,1);
a(2,1:5) = rand(5,1);
adjusts the array to the max column size and appends zero to the shorter ones.
My question is: Why the former code snippet doesn't do what the latter does(which seems very logical to me)? I don't see any reason as to why the former code snippet should work the way it does. Or am I missing something?

With a(2,:) = rand(5,1);, you are attempting to assign a 5x1 vector to a 4x1 matrix column. Hence the error.
With a(2,1:5) = rand(5,1);, you are explicitly referencing a 5th row, which tells the Matlab engine to expand the matrix accordingly before attempting the assignment operation. Hence, this will succeed.
The way I see it, trying to put 5 values into a 4 row vector likely comes from an error in the code, so the user has to explicitly state that this is what he intends to do. Of course, I can only infer on the intent of Mathworks developers when they specifiy the behavior of their language.

Related

Why does Octave print "dimensions mismatch" whereas MATLAB does not?

I am trying to run a MATLAB code in Octave but got stuck at the following point:
I is an empty matrix, dimensions 0x4,
a = 2;
The command, belonging to a for-loop, is:
I = [I a];
MATLAB output: I = 2
Octave output: "horizontal dimensions mismatch (0x4 vs 1x1)"
I have found a way to work around this error but I would also like to understand: Why does MATLAB accept those different dimensions whereas Octave prints an error?
Is there a different definition regarding empty matrices and extending those? (Specially because it is not a "normal" empty matrix but a 0x4 empty matrix?)
Matlab issues a warning, alerting you to the fact that this will become an error in future releases:
>> I = magic(4);
>> I(1:4,:) = []
I =
Empty matrix: 0-by-4
>> [I 2]
Warning: This concatenation operation includes an empty array with an incorrect number of rows.
Concatenation including empty arrays will require all arrays to have the same number of rows in a future release.
ans =
2
Same code on Octave:
>> I = magic(4);
>> I(1:4,:)=[]
I = [](0x4)
>> [I 2]
error: horizontal dimensions mismatch (0x4 vs 1x1)
So essentially it's the same issue, except Matlab allows it with a warning for the time being, and is being slightly more informative as to which dimension is actually at fault here, whereas octave is stricter about it and hopes you figure out what it meant 😛. But in essence the behaviour is the same.
It is also very reasonable behaviour, since attempting to concatenate two matrices of different sizes / dimensions is more likely to have come from a bug rather than intended behaviour, even if one of the arrays has become empty in the process, so matlab is wise to go down the octave path here (so to speak).
PS. Note that in this scenario, something like [I;2 2 2 2] is perfectly valid and correct code on both interpreters: i.e. you're concatenating vertically a 4-column matrix with one row to a 4-column matrix with no rows, hence the number of columns is consistent.

Creating functions in Matlab

Hi, I am trying to write a function as per the question. I have tried to create four sub-matrices which are the reverse of each other and then multiply to give the products demanded by the question. My attempt:
function T = custom_blocksT(n,m)
T(1:end,end-1:1);
T(1:end,end:-1:1)*2;
T(1:end,end:-1:1)*3;
T(1:end,end:-1:1)*4;
What I'm unsure of is
(i) What do the the indivual sub-matrices(T(1:end,end-1:1);)need to be equal to? I was thinking of(1:3)?
(ii) I tried to create a generic sub-matrix which can take any size matrix input using end was this correct or can't you do that? I keep getting this error
Undefined function or variable 'T'.
Error in custom_blocksT (line 2)
T(1:end,end-1:1);
I have searched the Matlab documentation and stacked overflow, but the problem is I'm not quite sure what I'm supposed to be looking for in terms of solving this question.
If someone could help me I would be very thankfull.
There are many problems with your function:
function T = custom_blocksT(n,m)
T(1:end,end-1:1);
T(1:end,end:-1:1)*2;
T(1:end,end:-1:1)*3;
T(1:end,end:-1:1)*4;
end
This is an extremely basic question, I highly recommend you find and work through some very basic MATLAB tutorials before continuing, even before reading this answer to be honest.
That said here is what you should have done and a bit of what you did wrong:
First, you are getting the error that T dos not exist because it doesn't. The only variables that exist in your function are those that you create in the function or those that are passed in as parameters. You should have passed in T as a parameter, but instead you passed in n and m which you don't use.
In the question, they call the function using the example:
custom_blocks([1:3;3:-1:1])
So you can see that they are only passing in one variable, your function takes two and that's already a problem. The one variable is the matrix, not it's dimensions. And the matrix they are passing in is [1:3;3:-1:1] which if you type in the command line you will see gives you
[1 2 3
3 2 1]
So for your first line to take in one argument which is that matrix it should rather read
function TOut = custom_blocks(TIn)
Now what they are asking you to do is create a matrix, TOut, which is just different multiples of TIn concatenated.
What you've done with say TIn(1:end,end-1:1)*2; is just ask MATLAB to multiple TIn by 2 (that's the only correct bit) but then do nothing with it. Furthermore, indexing the rows by 1:end will do what you want (i.e. request all the rows) but in MATLAB you can actually just use : for that. Indexing the columns by end-1:1 will also call all the columns, but in reverse order. So in effect you are flipping your matrix left-to-right which I'm sure is not what you wanted. So you could have just written TIn(:,:) but since that's just requesting the entire matrix unchanged you could actually just write TIn.
So now to multiply and concatenate (i.e. stick together) you do this
TOut = [TIn, TIn*2; TIn*3, TIn*4]
The [] is like a concatenate operation where , is for horizontal and ; is for vertical concatenation.
Putting it all together:
function TOut = custom_blocks(TIn)
TOut = [TIn, TIn*2; TIn*3, TIn*4];
end

Subscripted assignment dimension mismatch

here is the code listing and i got the above mentiond error at line nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c))); please let me now what is wrong with my code as i m new to matlab
for r = 1:numb_of_nest % for each particle
for c = 1:4
u=randn(size(nests(r,c)))*sigma;
v=randn(size(nests(r,c)));
step=u./abs(v).^(1/beta);
nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c)));
% Apply simple bounds/limits
ns_tmp=nests(r,c);
I=ns_tmp<Lb(c);
ns_tmp(I)=Lb(I);
% Apply the upper bounds
J=ns_tmp>Ub(c);
ns_tmp(J)=Ub(J);
% Update this new move
nests(r,c)=ns_tmp;
end
end
This error happens when you assign a value of some dimension m x n to a subscripted variable of different dimension.
In your case, assuming nests has no third dimension, you're assigning to a scalar (1x1) variable. This only works if the value you're trying to assign also is a scalar. Since you get the error, it probably isn't. The only place where your dimensions can be non-scalar is stepsize, so to fix this error, make sure stepsize is a scalar value.
According to the definition you gave in an earlier comment (stepsize=0.01*step.*(nests(r,c)-best);), this problem translates to make sure best is a scalar value. Possibly by subscripting, I can't tell you exactly how since I don't know what best is.
step=u./abs(v).^(1/beta);
nests(r,c)=nests(r,c)+stepsize.*randn(size(nests(r,c)));
Here you're assigning a value to the variable step, but then using a different variable called stepsize that hasn't been assigned a value anywhere in this code. Is this intentional? If not, stepsize is probably some leftover variable from previous code which is messing up the dimensions and giving you this error.
In addition to the above, is nests an ordinary two-dimensional matrix in your code? If so, taking size(nests(r,c)) every time is unnecessary - since you're giving two subscripts, the result is only going to be 1 all the time. Or is nests a cell array perhaps? In that case, you might want to index using curly braces { } instead of ordinary parantheses, to get the size of the matrix that's sitting inside the cell.

Unable to replace values in a matrix

I'm currently working on a cellular automata but i keep running into this problem. I have a matrix idxR which contains zero's and/or ones, depending on a probability process:
idxR = ((rRecr>rEmpty)&(rRecr>rAlgae)&(rRecr>rCoral));
Now i want to replace all ones in idxR with unique values and assign it to the variable colonies. I came up with the following:
colonies = idxR;
no = sum(colonies(:)==1)
maxvalue = max(colonies(:));
replace = [1:no]+maxvalue;
ret = reshape(replace,no,1);
colonies(colonies==1) = colonies(colonies==1).*ret;
When i output colonies it gives me a matrix with just ones and zeros and not a matrix where all ones have been replaced with incremental values. I tried this code in a new file and assigned a matrix with random ones and zeros to idxR and then it seems to work. So i guess to problem lies with the matrix idxR in my automata. It might be worth mentioning that idxR is contained in a for loop.
Can somebody tell me how to fix this?
You got the entire logic correct, except one minor flaw. You have idxR as a logical matrix. Hence colonies is a logical matrix too. Therefore, you get the expected output till the second-last line. Problem occurs on the last line, when you try to assign an array of numbers in which each number is greater than 1 (colonies(colonies==1).*ret;) to a logical matrix.
Elements greater than 1 are clipped to one and thus you see only zeros and ones. There is a simple workaround. Change the first line to
colonies = double(idxR);
P.S. The answer was right in front of you, you just didn't spot it. You had written:
I tried this code in a new file and assigned a matrix with random ones and zeros to idxR and then it seems to work.
The idxR matrix must have been of double datatype, if you used randi.
Parag got it right. You have the solution there.
You can use the following code if you are looking for a more "organized" way to get to 'colonies' -
colonies = double(idxR);
maxvalue = max(colonies(:));
ind1 = find(idxR==1);
colonies(ind1)=maxvalue + (1:numel(ind1));

How do I calculate result for every value in a matrix in MATLAB

Keeping simple, take a matrix of ones i.e.
U_iso = ones(72,37)
and some parameters
ThDeg = 0:5:180;
dtheta = 5*pi/180;
dphi = 5*pi/180;
Th = ThDeg*pi/180;
Now the code is
omega_iso = 0;
for i = 1:72
for j=1:37
omega_iso = omega_iso + U_iso(i,j)*sin(Th(j))*dphi*dtheta;
end
end
and
D_iso = (4 * pi)/omega_iso
This code is fine. It take a matrix with dimension 72*37. The loop is an approximation of the integral which is further divided by 4pi to get ONE value of directivity of antenna.
Now this code gives one value which will be around 1.002.
My problem is I dont need 1 value. I need a 72*37 matrix as my answer where the above integral approximation is implemented on each cell of the 72 * 37 matrix. and thus the Directviity 'D' also results in a matrix of same size with each cell giving the same value.
So all we have to do is instead of getting 1 value, we need value at each cell.
Can anyone please help.
You talk about creating a result that is a function essentially of the elements of U. However, in no place is that code dependent on the elements of U. Look carefully at what you have written. While you do use the variable U_iso, never is any element of U employed anywhere in that code as you have written it.
So while you talk about defining this for a matrix U, that definition is meaningless. So far, it appears that a call to repmat at the very end would create a matrix of the desired size, and clearly that is not what you are looking for.
Perhaps you tried to make the problem simple for ease of explanation. But what you did was to over-simplify, not leaving us with something that even made any sense. Please explain your problem more clearly and show code that is consistent with your explanation, for a better answer than I can provide so far.
(Note: One option MIGHT be to use arrayfun. Or the answer to this question might be more trivial, using simple vectorized operations. I cannot know at this point.)
EDIT:
Your question is still unanswerable. This loop creates a single scalar result, essentially summing over the entire array. You don't say what you mean for the integral to be computed for each element of U_iso, since you are already summing over the entire array. Please learn to be accurate in your questions, otherwise we are just guessing as to what you mean.
My best guess at the moment is that you might wish to compute a cumulative integral, in two dimensions. cumtrapz can help you there, IF that is your goal. But I'm not sure it is your goal, since your explanation is so incomplete.
You say that you wish to get the same value in each cell of the result. If that is what you wish, then a call to repmat at the end will do what you wish.