How to write this matlab code without a for loop - matlab

I have the following matlab code:
messages_llr_matrix = sparse(ROW_NUM, COL_NUM);
for index = 1 : length(II)
messages_llr_matrix(II(index), JJ(index)) = ...
code_word_aprior_prob(JJ(index));
end
This code takes a vector and copies it, to a sparse matrix rows if the element in the matrix is not zero.
matlab tells me not to use indexing in the previous matlab code, because it makes it very slow.
I want to build the messages_llr_matrix matrix in the following manner:
messages_llr_matrix = sparse(II,JJ,code_word_aprior_prob,ROW_NUM,COL_NUM);
This is not a solution that works.

The problem seems to be that in your latter code II(ind), JJ(ind) and code_word_aprior_prob(ind) should go together, but in your convention you need code_word_aprior_prob(JJ(ind)).
Try calling
messages_llr_matrix = sparse(II,JJ,code_word_aprior_prob(JJ),ROW_NUM,COL_NUM);

Related

Simplify the code to flatten arrays in matlab

Suppose I have a 1000x2x10x10 matrix, and currently I put them into two cell arrays by the following code,
for i=1:1000
tmp = seqs(i,1,:);
patterns{i} = tmp(:);
tmp = seqs(i,2,:);
labels{i} = tmp(:);
end
The purpose of patterns{i} = tmp(:) and labels{i} = tmp(:) is to flatten the matrix. My question is that, is it possible to simplify the code like patterns{i}=seqs(i,1,:)(:)? I tried this one but Matlab does not allow this, and that's why I currently have to use a temporary variable tmp.
I'll just give you 3 ways to do this. All of which work.
The first is the one I normally use is to have a function on my computer called vec
function out = vec(in)
out = in(:);
end
and then you can use it via
patterns{i} = vec(seqs(i,1,:));
Then you can call this function and it allows for more streamlined code. The second is reshape mentioned in the comments
patterns{i}=reshape(seqs(i,1,:),[],1);
I typically don't recommend reshape for these types of problems because it tends to fail if you aren't careful. The last is to use squeeze and transpose.
patterns{i} = squeeze(seqs(i,1,:))';
Personally, I prefer the first because it makes my code look nicer.

Matlab coder reallocation

I have some code like this in my matlab function:
for i = init:end
a= [a, char(zeros(size(a))]
a= func(a)
a = a(a~=0)
end
So, in each step of the loop, you first double the size of a, apply some random function to it, and then remove everything that is a zero.
Now, I want to run coder on this to eventually make it into c code. Of course, it gives me allocation errors.
Allowing dynamically allocated arrays doesn't help. I can't simply use different names for my variables either because it is in a for loop.
This may come a year late however something like:
function a = foobar(init,ub)
coder.varsize('a',[1,Inf]);
a = 1;
for i = init:ub
a = [a, ones(size(a))];
a = sin(a);
a = a(a~=0);
end
>> codegen foobar -args {1,1} -report
works for me in R2014a.
When you are trying to grow an array, it may be necessary to use coder.varsize in order to tell MATLAB Coder that the array is going to change size. In many cases MATLAB Coder can figure this out without using coder.varsize so it is best to try without it first and then add it in if errors are encountered.

loop over all possible combinations

I would like to include a loop in my script which finds the correlation of every possible combination of the data. This can be done manually by the following code:
clear all
%generate fake data
LName={'Name1','Name2','Name3'};
Data={rand(12,1),rand(12,1),rand(12,1)};
%place in a structure
d = [LName;Data];
Data = struct(d{:});
%find the correlation
[R,P] = corrcoef(Data.Name1,Data.Name2);
[R2,P2] = corrcoef(Data.Name1,Data.Name3);
[R3,P3] = corrcoef(Data.Name2,Data.Name3);
However, I would like to do this in a loop, I have started but have failed at the first hurdle. My attempted loop, which doesn't work is shown below:
SNames=fieldnames(Data);
for i=1:numel(SNames);
[R{i},P{i}] = corrcoef(Data.(SNames{i}),Data.(SNames{i+1}));
end
I'm struggling on knowing how to tell matlab to loop over a different combination of values with every iteration.
Any help provided would be much appreciated.
Try something like this:
pairs = combnk (1:3,2) % all combinations of 2 elements taken out of the vector [1,2,3]
for i = 1 : size (pairs,1)
[R{i},P{i}] = corrcoef(Data.(SNames{pairs(i,1)}),Data.(SNames{pairs(i,2)}));
end
#ItamarKatz answer is a good one. However, if you don't have the statistics toolbox, you can not use the combnk command.
In that case, you can download combinations generator from here.

matlab matrices and fold list

i have two problems in mathematica and want to do them in matlab:
measure := RandomReal[] - 0.5
m = 10000;
data = Table[measure, {m}];
fig1 = ListPlot[data, PlotStyle -> {PointSize[0.015]}]
Histogram[data]
matlab:
measure =# (m) rand(1,m)-0.5
m=10000;
for i=1:m
data(:,i)=measure(:,i);
end
figure(1)
plot(data,'b.','MarkerSize',0.015)
figure(2)
hist(data)
And it gives me :
??? The following error occurred
converting from function_handle to
double: Error using ==> double
If i do :
measure =rand()-0.5
m=10000;
data=rand(1,m)-0.5
then, i get the right results in plot1 but in plot 2 the y=axis is wrong.
Also, if i have this in mathematica :
steps[m_] := Table[2 RandomInteger[] - 1, {m}]
steps[20]
Walk1D[n_] := FoldList[Plus, 0, steps[n]]
LastPoint1D[n_] := Fold[Plus, 0, steps[n]]
ListPlot[Walk1D[10^4]]
I did this :
steps = # (m) 2*randint(1,m,2)-1;
steps(20)
Walk1D =# (n) cumsum(0:steps(n)) --> this is ok i think
LastPointold1D= # (n) cumsum(0:steps(n))
LastPoint1D= # (n) LastPointold1D(end)-->but here i now i must take the last "folding"
Walk1D(10)
LastPoint1D(10000)
plot(Walk1D(10000),'b')
and i get an empty matrix and no plot..
Since #Itamar essentially answered your first question, here is a comment on the second one. You did it almost right. You need to define
Walk1D = # (n) cumsum(steps(n));
since cumsum is a direct analog of FoldList[Plus,0,your-list]. Then, the plot in your code works fine. Also, notice that, either in your Mathematica or Matlab code, it is not necessary to define LastPoint1D separately - in both cases, it is the last point of your generated list (vector) steps.
EDIT:
Expanding a bit on LastPoint1D: my guess is that you want it to be a last point of the walk computed by Walk1D. Therefore, it would IMO make sense to just make it a function of a generated walk (vector), that returns its last point. For example:
lastPoint1D = #(walk) (walk(end));
Then, you use it as:
walk = Walk1D(10000);
lastPoint1D(walk)
HTH
You have a few errors/mistakes translating your code to Matlab:
If I am not wrong, the line data = Table[measure, {m}]; creates m copies of measure, which in your case will create a random vector of size (1,m). If that is true, in Matlab it would simply be data = measure(m);
The function you define gets a single argument m, therefor it makes no sense using a matrix notation (the :) when calling it.
Just as a side-note, if you insert data into a matrix inside a for loop, it will run much faster if you allocate the matrix in advance, otherwise Matlab will re-allocate memory to resize the matrix in each iteration. You do this by data = zeros(1,m);.
What do you mean by "in plot 2 the y=axis is wrong"? What do you expect it to be?
EDIT
Regarding your 2nd question, it would be easier to help you if you describe in words what you want to achieve, rather than trying to read your (error producing) code. One thing which is clearly wrong is using expression like 0:steps(n), since you use m:n with two scalars m and n to produce a vector, but steps(n) produces a vector, not a scalar. You probably get an empty matrix since the first value in the vector returned by steps(n) might be -1, and 0:-1 produces an empty vector.

What's the best way to iterate through columns of a matrix?

I want to apply a function to all columns in a matrix with MATLAB. For example, I'd like to be able to call smooth on every column of a matrix, instead of having smooth treat the matrix as a vector (which is the default behaviour if you call smooth(matrix)).
I'm sure there must be a more idiomatic way to do this, but I can't find it, so I've defined a map_column function:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
which I can call with:
smoothed = map_column(input, #(c) (smooth(c, 9)));
Is there anything wrong with this code? How could I improve it?
The MATLAB "for" statement actually loops over the columns of whatever's supplied - normally, this just results in a sequence of scalars since the vector passed into for (as in your example above) is a row vector. This means that you can rewrite the above code like this:
function result = map_column(m, func)
result = [];
for m_col = m
result = horzcat(result, func(m_col));
end
If func does not return a column vector, then you can add something like
f = func(m_col);
result = horzcat(result, f(:));
to force it into a column.
Your solution is fine.
Note that horizcat exacts a substantial performance penalty for large matrices. It makes the code be O(N^2) instead of O(N). For a 100x10,000 matrix, your implementation takes 2.6s on my machine, the horizcat one takes 64.5s. For a 100x5000 matrix, the horizcat implementation takes 15.7s.
If you wanted, you could generalize your function a little and make it be able to iterate over the final dimension or even over arbitrary dimensions (not just columns).
Maybe you could always transform the matrix with the ' operator and then transform the result back.
smoothed = smooth(input', 9)';
That at least works with the fft function.
A way to cause an implicit loop across the columns of a matrix is to use cellfun. That is, you must first convert the matrix to a cell array, each cell will hold one column. Then call cellfun. For example:
A = randn(10,5);
See that here I've computed the standard deviation for each column.
cellfun(#std,mat2cell(A,size(A,1),ones(1,size(A,2))))
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Of course, many functions in MATLAB are already set up to work on rows or columns of an array as the user indicates. This is true of std of course, but this is a convenient way to test that cellfun worked successfully.
std(A,[],1)
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Don't forget to preallocate the result matrix if you are dealing with large matrices. Otherwise your CPU will spend lots of cycles repeatedly re-allocating the matrix every time it adds a new row/column.
If this is a common use-case for your function, it would perhaps be a good idea to make the function iterate through the columns automatically if the input is not a vector.
This doesn't exactly solve your problem but it would simplify the functions' usage. In that case, the output should be a matrix, too.
You can also transform the matrix to one long column by using m(:,:) = m(:). However, it depends on your function if this would make sense.