Common way to generate finite geometric series in MATLAB - matlab

Suppose I have some number a, and I want to get vector [ 1 , a , a^2 , ... , a^N ]. I use [ 1 , cumprod( a * ones( 1 , N - 1 ) ) ] code. What is the best (and propably efficient) way to do it?

What about a.^[0:N] ?

ThibThib's answer is absolutely correct, but it doesn't generalize very easily if a happens to a vector. So as a starting point:
> a= 2
a = 2
> n= 3
n = 3
> a.^[0: n]
ans =
1 2 4 8
Now you could also utilize the built-in function vander (although the order is different, but that's easily fixed if needed), to produce:
> vander(a, n+ 1)
ans =
8 4 2 1
And with vector valued a:
> a= [2; 3; 4];
> vander(a, n+ 1)
ans =
8 4 2 1
27 9 3 1
64 16 4 1

Related

Shift rows in matrix with respect to vector values in Octave/MATLAB

Can I shift rows in matrix A with respect to values in vector v?
For instance A and v specified as follows:
A =
1 0 0
1 0 0
1 0 0
v =
0 1 2
In this case I want to get this matrix from A:
A =
1 0 0
0 1 0
0 0 1
Every i-th row in A has been shifted by i-th value in v
Can I do this operation with native functions?
Or should I write it by myself?
I've tried circshift function, but I couldn't figure out how to shift rows separately.
The function circshift does not work as you want and even if you use a vector for the amount of shift, that is interpreted as the amount of shift for each dimension. While it is possible to loop over the rows of your matrix, that will not be very efficient.
More efficient is if you compute the indexing for each row which is actually quite simple:
## First, prepare all your input
octave> A = randi (9, 4, 6)
A =
8 3 2 7 4 5
4 4 7 3 9 1
1 6 3 9 2 3
7 4 1 9 5 5
octave> v = [0 2 0 1];
octave> sz = size (A);
## Compute how much shift per row, the column index (this will not work in Matlab)
octave> c_idx = mod ((0:(sz(2) -1)) .- v(:), sz(2)) +1
c_idx =
1 2 3 4 5 6
5 6 1 2 3 4
1 2 3 4 5 6
6 1 2 3 4 5
## Convert it to linear index
octave> idx = sub2ind (sz, repmat ((1:sz(1))(:), 1, sz(2)) , c_idx);
## All you need is to index
octave> A = A(idx)
A =
8 3 2 7 4 5
9 1 4 4 7 3
1 6 3 9 2 3
5 7 4 1 9 5
% A and v as above. These could be function input arguments
A = [1 0 0; 1 0 0; 1 0 0];
v = [0 1 2];
assert (all (size (v) == [1, size(A, 1)]), ...
'v needs to be a horizontal vector with as many elements as rows of A');
% Calculate shifted indices
[r, c] = size (A);
tmp = mod (repmat (0 : c-1, r, 1) - repmat (v.', 1, c), c) + 1;
Out = A(sub2ind ([r, c], repmat ([1 : r].', 1, c), tmp))
Out =
1 0 0
0 1 0
0 0 1
If performance is an issue, you can replace repmat with an equivalent bsxfun call which is more efficient (I use repmat here for simplicity to demonstrate the approach).
With focus on performance, here's one approach using bsxfun/broadcasting -
[m,n] = size(A);
idx0 = mod(bsxfun(#plus,n-v(:),1:n)-1,n);
out = A(bsxfun(#plus,(idx0*m),(1:m)'))
Sample run -
A =
1 7 5 7 7
4 8 5 7 6
4 2 6 3 2
v =
3 1 2
out =
5 7 7 1 7
6 4 8 5 7
3 2 4 2 6
Equivalent Octave version to use automatic broadcasting would look something like this -
[m,n] = size(A);
idx0 = mod( ((n-v(:)) + (1:n)) -1 ,n);
out = A((idx0*m)+(1:m)')
Shift vector with circshift in loop, iterating row index.

Finding where a set of values lie within a matrix

I have two values (k and j) which I know are within an nx3 matrix (M). I know that they're and on the same row and that j is always to the right of k, so if k is in M(2,1), then j will be in M(2,2). I tested for this earlier in the function, but now I want to know which row that is for a given k and j. I need the row number of their location to proceed. There are no duplicate combinations of k and j in the matrix.
So if I have the matrix
M=
1 4 5
1 5 7
k j 5
4 5 6
2 3 1
Then I want to know that they're in row 3. None of the columns are ordered.
What I have tried:
I used the code below
[row,~] = find(M==k);
I'm not sure how to look for a combination of them. I want to avoid using the find function. I hope to potentially use logical indexing.
How do I go about doing this? I hope this question makes sense.
You can use bsxfun -
find(all(bsxfun(#eq,A(:,1:2),[k,j]),2) | all(bsxfun(#eq,A(:,2:3),[k,j]),2))
Being a relational operation with bsxfun, according to this post on benchmarked results, this should be pretty efficient.
Sample runs
Case #1 :
A =
1 4 5
1 5 7
6 7 1
4 5 6
2 3 1
k =
6
j =
7
>> find(all(bsxfun(#eq,A(:,1:2),[k,j]),2) | all(bsxfun(#eq,A(:,2:3),[k,j]),2))
ans =
3
Case #2 :
A =
1 4 5
1 5 7
1 6 7
4 5 6
2 3 1
k =
6
j =
7
>> find(all(bsxfun(#eq,A(:,1:2),[k,j]),2) | all(bsxfun(#eq,A(:,2:3),[k,j]),2))
ans =
3
Slightly different version on bsxfun. This one doesn't limit the matrix to three columns.
find(sum(((bsxfun(#eq,M,j) + bsxfun(#eq,M,k)) .* M).' ) == j+k >0)
Case 1:
M = [
1 4 5
1 5 7
6 7 1
4 5 6
2 3 1]
k=6;j=7;
ans = 3
Case 2:
M=[
1 4 5
1 5 7
1 6 7
4 5 6
2 3 1
];
k=6;j=7;
ans = 3
Use this:
row = find(((M(:,1) == k ) & ( M(:,2) == j)) | ((M(:,1) == k ) & ( M(:,3) == j)) | ((M(:,2) == k ) & ( M(:,3) == j)) )
Also, logical indexing can only give you a matrix with zeros at all other positions and one at your required position. But to get the index of that position, you will have to use find.

how to make a function that take n as argument and create submatrix in matlab

hi everyone i stuck in a problem.i am going to make a function called quadrants that takes as its input argument a scalar integer named n. The function returns Q, a 2n-by-2n matrix. Q consists of four n-by-n submatrices. The elements of the submatrix in the top left corner are all 1s, the elements of the submatrix at the top right are 2s, the elements in the bottom left are 3s, and the elements in the bottom right are 4s.
thanks in advance for assistance..
One other approach with bsxfun, reshape and permute
function [ out ] = quadrants( n )
out = reshape(permute(reshape(bsxfun(#times,...
ones(n,n,4),permute(1:4,[1 3 2])),n,2*n,[]),[1 3 2]),2*n,[]);
end
Results:
>> quadrants(3)
ans =
1 1 1 2 2 2
1 1 1 2 2 2
1 1 1 2 2 2
3 3 3 4 4 4
3 3 3 4 4 4
3 3 3 4 4 4
As the OP is desperate with for loop here is an alternate loopy approach
function [ out ] = quadrants( n )
out(2*n,2*n) = 0;
count = 1;
for ii = 1:n:2*n
for jj = 1:n:2*n
out(ii:ii+n-1,jj:jj+n-1) = count;
count = count + 1;
end
end
end
Results:
>> quadrants(2)
ans =
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
I think the simplest way to do it (try to avoid multiple "for" loops in matlab, it doesn't like them, try to use as much matrix as possible):
function[r] = Quadrant(n)
a = ones(n);
r = [a 2*a; 3*a 4*a];
end
function [Q]=quadrant(n)
W=zeros(n);
X=ones (n);
Y= ones(n)*3;
Z= ones(n)*4;
V={[W], [X];
[Y], [Z]}
Q=cell2mat(V)
end

How to perform this kind of matrix division in Matlab?

This problem is probably less to do with Matlab and more to do with matrix algebra (which I mostly forget from my college courses). Say I have a m x n matrix X and a m x 1 matrix B. How would I divide the X by B such that all the elements of the ith row of X are piecewise divided by the ith row of B, resulting in another m x n matrix Y?
E.g.
X = [2 4 8; 3 9 27; 4 16 64]
B = [2; 3; 4]
X ? B = [2/2 4/2 8/2; 3/3 9/3 27/3; 4/4 16/4 64/4]
ans =
1 2 4
1 3 9
1 4 16
Better not use repmat - it is slow and allocates additional memory for the workspace. You can use bsxfun, which is an inbuilt function, so it is faster and avoids the extra workspace:
X = [2 4 8; 3 9 27; 4 16 64]
B = [2; 3; 4]
bsxfun(#rdivide, X, B)
ans =
1 2 4
1 3 9
1 4 16
Junuxx's comment pointed me in the right direction. The solution I used to get what I wanted is:
B_prime = repmat(B,1,3)
X ./ B_prime
ans =
1 2 4
1 3 9
1 4 16
I'd still like to know what this kind of operation is called (if it even has a formal name).
X is m x n and B is m x 1
size(X,2) gives the value of n i.e. number of columns
So, you need to do:
X./repmat(B,1,size(X,2))
X = [2 4 8; 3 9 27; 4 16 64]
B = [2; 3; 4]
Result= X./B(:,ones(1,3)) %is faster then repmat
Result =
1 2 4
1 3 9
1 4 16

MATLAB indexing question

I have a matrix, for example
A = [ 1 2 3; 4 5 6; 7 8 9] ;
and a vector of size 1x3 which specifies which element in each row is the one I'm looking for - i.e. If
vector = [ 1 2 1 ]
then the desired output is
[ 1 5 7 ]
since 1 is the 1'st element in the 1'st row, 5 is the 2'nd in the 2'nd row, and 7 is the 1'st element in the 3'rd row.
How do I achieve this? Couldn't find a built in function to do this, which surprised me.
MATLAB provides the SUB2IND function to convert rows/columns subscripts to linear indices:
>> A = [1 2 3; 4 5 6; 7 8 9];
>> idx = sub2ind(size(A),1:3,[1 2 1]); %# rows: [1 2 3], cols: [1 2 1]
>> A(idx)
1 5 7
First of all, the indexes in Matlab go from top to bottom.
So in your case A[1] = 1 , A[2] = 4 , A[3] = 7
That said, it would be easier to work on A' , because its a bit more trivial.
B = A';
B((vector + [0:2].* 3))
It's a bit ugly, but diag(A(1:3,[1 2 1])) will do the trick.
Here's a variation of Yochai's answer but without the transpose (this is also basically what SUB2IND does in Amro's answer):
output = A((1:3)+3.*(vector-1));
Or for an array A of an arbitrary size:
nRows = size(A,1);
output = A((1:nRows)+nRows.*(vector-1));