views:

111

answers:

5

Let x=1:100 and N=1:10 I would like to create 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?

+1  A: 

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))];
zellus
The first line of the computex matrix should be one, in your case it is `1:100`
Adrien
+6  A: 

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.

Adrien
+1 for bsxfun + function pointer + simple arguments. If you can express the rule compactly, chances are that combination will let you express it in MATLAB...
Alex Feinman
+1 for bsxfun() voodoo. @Adrien, I think there is a typo: N = 1:10; instead of N = 1:0;
zellus
@zellus: true, typo corrected
Adrien
bsxfun() is the nicest. Thanks.
alext87
+4  A: 

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].

gnovice
nice meshgrid usage. My only problem with this method and the similar ones proposed here is that they do not use the i^th line to compute line i+1 at a low cost. The cumprod variant does it but there is some aesthetics missing.
Adrien
@Adrien: For large matrices, you are right that it would probably be faster to compute values by successive multiplication by the base value. For relatively small matrices like the example here, it seems a reasonable trade-off to go with something easy to read and understand but slightly less efficient. ;)
gnovice
I like this method... In my actual programming I'm create 10000 by 10000. So maybe I should use the more efficient approaches. Good to know this way though. Thank you!
alext87
@alext87: Those are *very* large matrices, and you're likely to run into [memory problems](http://www.mathworks.com/support/tech-notes/1100/1106.html). In fact, they're so big that when I create a matrix of that size, there's not enough memory left to even perform basic operations on it. For example, `clear all; V=ones(10000); V=V.';` gives me an out-of-memory error. In addition, there's pretty much no point in raising numbers to such large powers. Even just `2^1000` results in `1.0715e+301`, just shy of the [maximum value for doubles](http://www.mathworks.com/help/techdoc/ref/realmax.html).
gnovice
@Adrien: Actually, the function [VANDER](http://www.mathworks.com/help/techdoc/ref/vander.html) which was [suggested by Oli Charlesworth](http://stackoverflow.com/questions/3921725/matlab-vectorisation-problem/3925669#3925669) takes advantage of the efficient computation you mention. You can see the code by typing `type vander` in the MATLAB Command Window.
gnovice
+4  A: 

Sounds like a Vandermonde matrix. So use vander:

A = vander(1:100);
A = A(1:10, :);
Oli Charlesworth
The only problem is that VANDER creates square matrices, so you do quite a bit of extra work.
gnovice
@gnovice: Not a very tricky problem to work around, see code above.
Oli Charlesworth
Actually, since the OP mentioned working with square matrices in a comment, this function looks like a good choice. The only change you'd have to make would be to rotate it using [ROT90](http://www.mathworks.com/help/techdoc/ref/rot90.html) so that column `i` contains powers of `i`: `A = rot90(vander(1:N));`
gnovice
A: 

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.)

MatlabDoug
If you go for a loop, then you should fill the matrix line by line and not use the .^ operator. Instead fill the first line with ones and then create each new line by multiplying the previous one with `[1:100]`. You have then both readability and efficiency.
Adrien
Adrien's suggestion yields a 12% speed increase. For the scale of problem being discussed here, it was imperceptible. I had to run this 100,000 times to get the whole thing to take 2.8 vs 2.5 seconds. To me, my version is simpler to read since there is no initiation step for M, but no accounting for taste! :)
MatlabDoug

related questions