Avoid for loop for setting the matrix element in Matlab - matlab

In a matrix, how does one set an adjacent and diagonal element to 1 if the values in these locations are the same avoiding a for loop?
An attempt made with for loop is given
[r,c] = size(mat1);
Sval = zeros(size(mat1));
for i = 1:r
for j = 1:c-1
if(mat1(i,j) == mat1(i,j+1))
Sval(i,j) = 1;
Sval(i,j+1) = 1;
else
Sval(i,j) = 0;
Sval(i,j+1) = 0;
end;
end;
end;

To receive the exact same output without the loops the code is the following. However it is not quite clear what you want to achieve with this code. Please elaborate further if this doesn't answer your question.
Sval = mat1(:,1:c-1) == mat1(:,2:c);
Sval(:,c) = Sval(:,c-1);
If I interpret your sentence right what you actually want is to shift/copy the equal values to the right as well. This could be achived by:
Sval = mat1(:,1:c-1) == mat1(:,2:c);
Sval(:,c) = zeros(r,1);
Sval(:,2:c) = Sval(:,1:c-1) | Sval(:,2:c);

Related

Error of declaration of variable

I have a problem at the beginning of my function. The function is to combine several data column from some objects. Error happens at the beginning of function. It says as follows:
Error in find_by_coor (line 2)
for i = 1:length(obj_ac)
Here is only the declaration of variable and loop, but Matlab somehow returned error. I have no idea so would like someone to help me. I attached my code as follows. Thanks a lot in advance.
function arr = find_by_coor(obj_ac,obj_gps,obj_sen_dir,lat1,long1,lat2,long2)
for i = 1:length(obj_ac)
if eq(obj_sen_dir(i).sensor,4) && strcmp(obj_sen_dir(i).direction,'outbound')
ind = obj_gps(i).save_var_gps(:,1)>lat1;
if isempty(find(ind)) == 1
continue
end
temp = obj_gps(i).save_var_gps(ind,:);
ind = temp(:,1)<lat2;
if isempty(find(ind)) == 1
continue
end
temp2 = temp(ind,:);
ind = temp2(:,2)<long1;
if isempty(find(ind)) == 1
continue
end
temp3 = temp2(ind,:);
ind = temp3(:,2)>long2;
if isempty(find(ind)) == 1
continue
end
temp4 = temp3(ind,:);
mint = min(temp4(:,5))-min(obj_gps(i).save_var_gps(:,5));
maxt = max(temp4(:,5))-min(obj_gps(i).save_var_gps(:,5));
if isempty(mint) == 1 || isempty(maxt) == 1
continue
end
if floor(mint*(1.6516e+03)) == 0 || floor(maxt*(1.6516e+03)) == 0
continue
end
temp5 = obj_ac(i).save_var(floor(mint*(1.6516e+03)):floor(maxt*(1.6516e+03)));
temp6 = abs(fft(temp5));
arr(i,:) = [i objs(i).daten var(temp5) max(temp5) min(temp5) mean(temp5) std(temp5) mode(temp5) var(temp6) max(temp6) min(temp6) mean(temp6) std(temp6) mode(temp6)];
disp(i);
end
end
end
The problem is that when you run the function, the output variable arr is never assigned. In Matlab you must always assign a function output if you choose to have it in the definition. For example
function [a,b] = setAB()
err = 0; % Gives an error if err is true
a = 1;
if ~err
b = 1;
end
The reason is most certainly that for some inputs, all values fall into one of the if statements and you do never reach the point where arr is assigned. A good solution for this is to assign a default value for arr in the beginning. That may for example be nan or -1 or, in your case maybe an array arr = nan(wanted size) or arr = -1*ones(wanted size). If you do not preallocate arr you will likely get a "matrix out of bounds" error instead, should you solve the first issue.
It does not mean that you always need to have an output though.
function [] = noOutput()
disp('Hi, I am a void!');
You may also choose to return as many values as number of outputs.
function varargout = variableArgs()
a = 1;
b = 2;
c = 3;
if (nargout == 1)
varargout{1} = a;
elseif (nargout == 2)
varargout{1} = b;
varargout{2} = c;
else
error('Wrong number of output arguments!');
end
I am not saying which of the approaches you should use or that any of them are good. Normally I use varargout in case I write plotting functions. Then I may want to return nothing in case I do not have an output argument. Then I want to return handles or any extra information. Further as you may have understood there is also a varargin that may be of more use.

faster sparse matric indexing in matlab

I had a question before but it was not as complete as this one! Actually, what I meant was that I have a nested if-for loop which I did not make it very clear before.
So, I have a very long code which is full of the following "if"s and matlab editor gives me a suggestion as follow:
this sparse indexing expression is likely to be slow
Is there any way by which I can make the code faster and do the matlab's suggestion? (The code may not run, because I just picked a few lines and tried to show the issue)
In my previous question, I did not explain that I need to use the i,j as index, so the answer was not convincing. But, as you can see here, I need to use the i and j as index which make the problem a little different from the previous post.
template = rand(200,200);
grid = rand(200,200);
T = size(template);
rws = size(grid,1);
cols = size(grid,2);
ind = "it is a matrix";
A = sparse(rws*cols,rws*cols);
T = sparse(rws*cols,2);
border_grid = 0;
border_template = 0;
template_comp = 0;
grid_comp = 0;
for i = 1:cols
for j = 1:rws
if(ind(j,i)==255)
Asr=grid(j,i,1);
Bsr=template(((j-posy)+1),((i-posx)+1),1);
Snorm= ((Asr-Bsr)^2)^(1/2);
if (( (j+1) > 0) && ((j+1) <= rws))
if ( ind(j+1,i)==0)
T((i-1)*rws+j,1)=100000;
border_grid=border_grid+1;
end
if ( ind(j+1,i)==128)
border_template=border_template+1;
T((i-1)*rws+j,2)=100000;
end
if( (ind(j+1,i)==255))
Atr=grid(j+1,i,1);
Btr=template(((j+1)-posy)+1,(i-posx)+1,1);
Tnorm= ((Atr-Btr)^2)^(1/2);
A((i-1)*rws+j,(i-1)*rws+(j+1))=Snorm+Tnorm;
end
end
end;
**+ some other similar if-loops**
end
end

Avoiding for-loops in matrix operations with cell elements

The dimensions of this problem are: model.nlf = 4. Each {r} of Kuu or KuuGamma are 500x500 matrices of data.
How to suppress the for-loop? my intuition goes toward using cellfun with a function for logdet.
logDetKuu = 0;
for r=1:model.nlf,
if isfield(model, 'gamma') && ~isempty(model.gamma)
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(model.KuuGamma{r});
model.logDetKuu{r} = logdet(model.KuuGamma{r}, model.sqrtKuu{r});
else
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(model.Kuu{r});
model.logDetKuu{r} = logdet(model.Kuu{r}, model.sqrtKuu{r});
end
logDetKuu = logDetKuu + model.logDetKuu{r};
end
Grateful for pointers. Thanks
Follow up question: Can the following type of for-loops on cell elements be vectorized?
nlf = 4; nout = 16; each KuuinvKuy{1,1} are 150x650
for k =1: model.nout,
for r =1: model.nlf,
model.KuuinvKuy{r,k} = model.Kuuinv{r}*model.Kyu{k,r}';
end
end
If all your matrices are so large, and you execute your for-loop only 4 times, then there is no reason to remove the for-loops, since it will not lead to any speedup. My only observation is that the condition of the if seems to be independent of the loop, so it is cleaner to move that if before the loop. Something like this:
if isfield(model, 'gamma') && ~isempty(model.gamma)
myKuu = model.KuuGamma;
else
myKuu = model.Kuu;
end
logDetKuu = 0;
for r=1:model.nlf,
[model.Kuuinv{r}, model.sqrtKuu{r}] = pdinv(myKuu{r});
model.logDetKuu{r} = logdet(myKuu{r}, model.sqrtKuu{r});
logDetKuu = logDetKuu + model.logDetKuu{r};
end

Saving intermediate variable values of a recursive function

I'm trying to code a function calculating difference quotients. I need to this for polynomial interpolation. Given nodes x = linspace(a,b,n+1), function values at the nodes y = func(x) I want to find the values of difference quotients f[x0], f[x_0,x_1], ..., f[x_0,x_1,...,x_n]. To calculate f[x_0,x_1,...,x_n] I will need f[x_0,x_1,...,x_(n-1)], etc., thus it would be a good idea save the intermediate steps on my way to f[x_0,x_1,...,x_n], so that on my way to f[x_0,x_1,...,x_n] I will save the preceding difference quotients as elements of a vector.
Could someone tell me how to correct my code in order to save appropriate difference quotient values? Here's the code:
function [fx, all_fx] = ilo2(a,b,x,y,fx,all_fx)
if a == b
fx(end+1) = y(a);
if a == 1
all_fx(end+1) = fx(end);
end
return
end
a;
b;
[c, all_fx] = ilo2(a+1,b,x,y,fx,all_fx);
[d, all_fx] = ilo2(a,b-1,x,y,fx,all_fx);
fx(end+1) = (c-d)/(b-a);
if a == 1
all_fx(end+1) = fx(end);
end
end
The difference quotients I need are under 'if a == 1' condition.
Ok, I think I fixed it:
function [all_fx,fx] = ilo(a,b,x,y,all_fx,fx)
if a == b
fx(end+1) = y(a);
if a == 1
all_fx(end+1) = fx(end);
end
return
end
[all_fx,c] = ilo(a+1,b,x,y,all_fx,fx);
[all_fx,d] = ilo(a,b-1,x,y,all_fx,fx);
fx(end+1) = (c-d)/(b-a);
if a == 1
all_fx(end+1) = fx(end);
end
end

index out of bounds error because numel

It loops through until the last time and then I get an error "Attempted to access EQ_NUM(8); index out of bounds because
numel(EQ_NUM)=7."
N_NODE=8
N_PRE_DISP=2
DISP_NODE= [2 7]
EQ_NUM = 0;
for i = 1:N_PRE_DISP
NODE=DISP_NODE(i);
EQ_NUM(NODE) = -i;
end
ROW = 0;
for i = 1:N_NODE
if (EQ_NUM(i)==0)
ROW = ROW+1;
EQ_NUM(i)=ROW;
end
end
In this loop
EQ_NUM = 0;
for i = 1:N_PRE_DISP
NODE=DISP_NODE(i);
EQ_NUM(NODE) = -i;
end
you create EQ_NUM with 7 elements; the highest value that NODE takes is the highest value in DISP_NODE(1:2) which is 7.
In this loop
ROW = 0;
for i = 1:N_NODE
if (EQ_NUM(i)==0)
ROW = ROW+1;
EQ_NUM(i)=ROW;
end
end
you loop over i=1:8 and eventually try to execute EQ_NUM(8)==0.
You need to fix something, but I don't know what. Possibly you think that Matlab arrays are indexed from 0, they're not, the first index into a Matlab array is 1.