Indexing of Matrices in Matlab - matlab

How can I merge this two commands in one in Matlab?
Temp = diag(diag(A));
X = Temp(:)
Something like
X = diag(diag(A))(:)
does not work.

If you really want to, you can do:
X = reshape(diag(diag(A)),[],1)
I'm not sure you gain much by doing that though!

Related

Using spfun with two identically ordered sparse matrices

I got two sparse matrices A and B, which have identical sparsity pattern (all nonzeros are at exactly the same locations):
i = randi(1000,[50,1]);
j = randi(1000,[50,1]);
a = rand(50,1);
b = rand(50,1);
A = sparse(i,j,a,1000,1000);
B = sparse(i,j,b,1000,1000);
I would like to calculate efficiently exp(A-B) only for the nonzeros, and save it back into A.
I tried to use spfun for that task:
f = #(x,y) exp(x-y);
A = spfun(f,A,B);
but I got an error in spfun saying: "Too many input arguments."
Can anyone suggest an efficient way to calculate it?
It should be calculated many times.
Thanks!
Edit: mikkola suggested A = spfun(#f,A-B) which solves the problem, but the question remains how to do it with a function of two variables that can't be solved using the same trick. For example:
g = #(x,y) x.*cos(y);
A = spfun(#g,A,B);
You can't use
A = spfun(#exp, A-B);
because for entries where A an B are equal you will get 0 instead of 1.
To solve that, you can compute the vector of exponentials at the nonzero components, and then build a sparse matrix from that:
A = sparse(i,j,exp(nonzeros(A)-nonzeros(B))); %// if you have i, j stored
or
A(find(A)) = exp(nonzeros(A)-nonzeros(B));
Edit
According to the documentation, spfun can take only two inputs: a function and one sparse matrix.
So you cannot do directly what you want to do. The best solution is probably what has been suggested in the comments, i.e.:
res = spfun(#exp, A-B);
Best,

MATLAB travelling grids

I want to built a "travelling grid" MATLAB. Actually, I had to choose another MATLAB command instead of linspace to built my grid for any k. Is it possible with a MATLAB command?
for k=1:5
a=0;
b(k)=k.*3;
x=linspace(0,b(k),10);
y=linspace(0,30,10);
for z=1:length(x)
for t=1:length(y)
A(z,t,k)=x(z).*exp(-y(t));
end
end
end
Thanks for any help,
X = linspace(0,3,10);
XX(1,:,:) = bsxfun(#times,X,(1:5)')';
Y = exp(-linspace(0,30,10));
B = bsxfun(#times,Y',XX);
B = permute(B,[2,1,3]);
Your current code is working fine, so I'm not sure what the question is... Here is a slightly simpler implementation:
b = (1:5).*3;
A = zeros(10,10,5);
for k=1:5
[X,Y] = ndgrid(linspace(0,b(k),10), linspace(0,30,10));
A(:,:,k) = X.*exp(-Y);
end
If you also want the y-limits to change as well, the process is similar; you would have two loops and the result A being a 4D matrix

Tabulated values's management in MATLAB

I have to build a function from tabulated values (two columns) which are written in a text file. The process to make it is the following:
Use the command importdata to read the data file
Xp = importdata('Xp.dat','\t',1);
Store each column in a variable
x = Xp(1:18304,1);
y = Xp(1:18304,2);
Make a curve fitting with both variables
ft = fittype('linearinterp');
datos.f_Xp = fit(x,y,ft);
However, when I am profiling the code I have found out that my bottleneck are the built-in functions fittype.fittype, fittype.evaluate, cfit.feval, ppval and cfit.subsref
which are related to the curve fitting. So I ask myself how I should manage the tabulated values for improving my code.
you're trying to fit 18304 data points to a curve. Also, you're using linearinterp... which means a routine is being run in a piecewise fashion. if you want to make the code faster use less datapoints.
Or perhaps try:
ft = fittype('poly1');
Not sure is it will be the answer you need as I don't have access to the data
May be "Eval" function could work in your case,
some simple example :
A = '1+4'; eval(A)
ans =
5
P = 'pwd'; eval(P)
ans =
/home/myname
and a bit more advanced!
for n = 1:12
eval(['M',int2str(n),' = magic(n)'])
end
Also, it has a sister name "feval"
guess, what does it do !
[V,D] = feval('eig',A)
[V,D] = eig(A)
and here
function plotf(fun,x)
y = feval(fun,x);
plot(x,y)
You are right ! all are equivalent,
check out here and find more relevant function

Vectorizing the creation of a matrix of successive powers

Let x=1:100 and N=1:10. I would like to create a matrix x^N so that the ith column contains the entries [1 i i^2 ... i^N].
I can easily do this using for loops. But is there a way to do this using vectorized code?
I'd go for:
x = 1:100;
N = 1:10;
Solution = repmat(x,[length(N)+1 1]).^repmat(([0 N])',[1 length(x)]);
Another solution (probably much more efficient):
Solution = [ones(size(x)); cumprod(repmat(x,[length(N) 1]),1)];
Or even:
Solution = bsxfun(#power,x,[0 N]');
Hope this helps.
Sounds like a Vandermonde matrix. So use vander:
A = vander(1:100);
A = A(1:10, :);
Since your matrices aren't that big, the most straight-forward way to do this would be to use MESHGRID and the element-wise power operator .^:
[x,N] = meshgrid(1:100,0:10);
x = x.^N;
This creates an 11-by-100 matrix where each column i contains [i^0; i^1; i^2; ... i^10].
Not sure if it really fits your question.
bsxfun(#power, cumsum(ones(100,10),2), cumsum(ones(100,10),1))
EDIT:
As pointed out by Adrien, my first attempt was not compliant with the OP question.
xn = 100;
N=10;
solution = [ones(1,xn); bsxfun(#power, cumsum(ones(N,xn),2), cumsum(ones(N,xn),1))];
Why not use an easy to understand for loop?
c = [1:10]'; %count to 100 for full scale problem
for i = 1:4; %loop to 10 for full scale problem
M(:,i) = c.^(i-1)
end
It takes more thinking to understand the clever vectorized versions of this code that people have shown. Mine is more of a barbarian way of doing things, but anyone reading it will understand it.
I prefer easy to understand code.
(yes, I could have pre-allocated. Not worth the lowered clarity for small cases like this.)

Storing Results of a Operation in a Matrix

Let's say I want to take the sin of 1 through 100 (in degrees).
I come from a C background so my instinct is to loop 1 through 100 in a for loop (something I can do in Matlab). In a matrix/vector/array I would store sin(x) where x is the counter of the for loop.
I cannot figure out how to do this in Matlab. Do I create a array like
x = [1 .. 100];
And then do
x[offset] = numberHere;
I know the "correct" way. For operations like addition you use .+ instead of + and with a function like sin I'm pretty sure you just do
resultArray = sin(x);
I just want to know that I could do it the C way in case that ever came up, thus my question here on SO. :)
% vectorized
x = sin((1:100)*pi/180);
or
% nonvectorized
x=[];
for i = 1:100
x(i) = sin(i*pi/180);
end
I beleive this can actually be done as a one liner in MatLab:
x = sind(1:100);
Note that you use sind() instead of sin(). Sin() takes radians as arguments.
As others have already pointed out there are for-loops in MATLAB as well.
help for
should give you everything you need about how it works. The difference from C is that the loop can go over objects and not only an integer:
objects = struct('Name', {'obj1', 'obj2'}, 'Field1', {'Value1','Value2'});
for x = objects
disp(sprintf('Object %s Field1 = %d', x.Name, x.Field1))
end
That example will output:
Object obj1 Field1 = Value1
Object obj2 field1 = Value2
This could have been done as
for i=1:length(objects)
x = objects(i);
disp(sprintf('Object %s Field1 = %d', x.Name, x.Field1))
end
And now to what I really wanted to say: If you ever write a for loop in MATLAB, stop and think!. For most tasks you can vectorize the code so that it uses matrix operations and builtin functions instead of looping over the data. This usually gives a huge speed gain. It is not uncommon that vectorized code executes 100x faster than looping code. Recent versions of MATLAB has JIT compilation which makes it less dramatic than before, but still: Always vectorize if you can.
#Daniel Fath
I think you'll need the final line to read
resultArray(i) = sin(x(i)) (rather than x(1))
I think you can also do:
for i = x
...
though that will behave differently if x is not a simple 1-100 vector
Hmm, if understand correctly you want a loop like structure
resultArray = zeros(1,length(x)) %% initialization aint necessary I just forgot how you dynamically add members :x
for i = 1:length(x) %% starts with 1 instead of zero
resultArray(i) = sin(x(i))
end
Warning I didn't test this but it should be about right.