I created a 3x3 matrix in MATLAB, where each element of the matrix is an column vector. I am facing some difficulties when I try to access the element of one of the column vectors within the matrix.
syms a b c real
Cube = sym('K', [3,3])
K1_1 = [a; b; c];
K1_2 = [a; b; c];
K1_3 = [a; b; c];
K2_1 = [a; b; c];
K2_2 = [a; b; c];
K2_3 = [a; b; c];
K3_1 = [a; b; c];
K3_2 = [a; b; c];
K3_3 = [a; b; c];
for i = 1:3
for j = 1:3
x = Cube(i,j);
K1_1(3,1) % this does not give an error
x
x(3,1) % this gives an error
end
end
Here is the output of the code above:
Cube =
[ K1_1, K1_2, K1_3]
[ K2_1, K2_2, K2_3]
[ K3_1, K3_2, K3_3]
ans =
c
x =
K1_1
Error using sub2ind (line 52)
Out of range subscript.
Error in sym/subsref (line 766)
R_tilde = sub2ind(size(L), Idx.subs{:});
Error in MainSimFile2 (line 22)
x(3,1)
I successfully set x equal to an element of the matrix which is a column vector. However, I get an error when I try to access an element of the column vector.
How can I set up this matrix?
As written in the document
Cube = sym('K', [3,3]) creates an 3-by-3 symbolic matrix filled with automatically generated elements. The generated elements do not appear in the MATLAB workspace.
For example,
>> clear all
>> Cube = sym('K', [3,3])
Cube =
[K1_1, K1_2, K1_3]
[K2_1, K2_2, K2_3]
[K3_1, K3_2, K3_3]
>> whos
Name Size Bytes Class Attributes
Cube 3x3 8 sym
In other words, K1_1 assigned by
K1_1 = [a; b; c];
is not the same K1_1 as either in
Cube =
[ K1_1, K1_2, K1_3]
[ K2_1, K2_2, K2_3]
[ K3_1, K3_2, K3_3]
or the one assigned to x by
x = Cube(i,j);
Therefore, this line is actually declaring a new variable K1_1.
K1_1 = [a; b; c];
Also see this answer.
Related
If I have two sequences A and B containing the elements a1, a2, ... and b1,b2, ... where a_i and b_i are of dimension 1xn and 1xm, respectively, then I want to make a new sequence C which contains: a_i(1)*b_i, a_i(2)*b_i, ... , a_i(n)*b_i. So for the ith element of C, I want to have the Kronecker product of the elements a_i and b_i. I want to code this in Matlab, but without a for-loop. For the case when b_i are scalars, the desired result is achieved with
C = A.*B
However, this does not work for non-scalar b_i's. So what I do now is for sequences of length L:
C = [];
for ii = 1:L
C = [C; kron(A(ii,:),B(ii,:))];
end
But I have the idea that this must be possible without a for loop. Here is my code using the symbolic toolbox:
clc; clear;
L = 5;
syms('a1',[L,1]);
syms('a2',[L,1]);
syms('b1',[L,1]);
syms('b2',[L,1]);
A = [a1,a2];
B = [b1,b2];
C1 = A.*B % only for size(B,2)=1
C2 = [];
for ii = 1:L
C2 = [C2;kron(A(ii,:),B(ii,:))];
end
C2
C3 = kron(A,B) % does not work
Here reshape and implicit expansion are used to compute the result:
C = reshape(B .* reshape (A, L, 1, []), L, []);
In my code I have a slow part of which the idea can be summarized in the following short example:
A = randi(10,5); %Random 5×5 matrix containing integers ranging from 0 to 10
B = rand(10,1); %Random 10×1 vector containing values ranging from 0 to 1
C = B(A); %New 5×5 matrix consisting of elements from B, indexed using A
In my case, the matrix A is sized 1000×1000, B is a 500×1 vector and C is also 1000×1000. Given that this 3rd line is in a for loop, where A is constant and B is updated every iteration, how can I further improve speed performance? According to the profile viewer 75% of code execution is at this single line. As expected, using a for loop for this operation is much slower (10x for a 1000×1000 matrix):
AA = A(:); %Convert matrix to vector
for k=1:length(AA) %Loop through this vector and use it as index
D(k) = B(AA(k));
end
E = reshape(D,5,5); %Reshape vector to matrix of 5x5
Any ideas to optimize this?
Edit: Script used to measure performance:
N = 1500;
A = randi(500,N);
AA = A(:);
D = zeros(N,N);
B = rand(500,1);
f1 = #() VectorIndex(A,B);
timeit(f1,1)
f2 = #() LoopIndex(AA,B,N);
timeit(f2,1)
function C = VectorIndex(A,B)
C = B(A);
end
function D = LoopIndex(AA,B,N)
D = zeros(N,N);
for k=1:length(AA)
D(k) = B(AA(k));
end
D = reshape(D,N,N);
end
I want to convert a 2x2 cell into a simple 2x2 matrix in the code shown below. In doing so, I am facing the error mentioned in the title. The code is given below.
clc
close all
clear all
A = [0 1;-2 1];
B = [0;1];
Q = [2 6;6 5];
R = 0.25;
%x0 = [2;-3];
X0 = [1; 1; 1; 1];
Tf = 5;
tm = 0:0.1:Tf;
[T X] = ode45(#(t,X)mRiccati(t, X, A, B, Q, R), [0 Tf], X0)
[m n] = size(X);
P = mat2cell(X, ones(m,1), n);
fh_reshape = #(x)reshape(x,size(A));
P = cellfun(fh_reshape,P,'UniformOutput',false);
K= reshape(cat(1,P{:}),size(P))
function dXdt = mRiccati(t, X, A, B, Q, R)
X = reshape(X, size(A)); %Convert from "n^2"-by-1 to "n"-by-"n"
dXdt = A.'*X + X*A - X*B*inv(R)*B.'*X + Q; %Determine derivative
dXdt = dXdt(:); %Convert from "n"-by-"n" to "n^2"-by-1
end
The error is due to the line "K= reshape(cat(1,P{:}),size(P))". What is wrong here ?
Suppose I have the n x m matrices A,B,C. I want to make a "3 x 1" block-matrix Y, such that
Y(1,1) = A, Y(2,1) = B, Y(3,1) = C. Is that possible in MATLAB?
As an alternative to storing the three n x m matrices in a cell vector, consider storing them in a three-dimensional array of size n x m x 3. You can use the cat command to concatenate the matrices along the third dimension, for example:
>> n = 2; m = 3;
>> A = rand(n, m); B = rand(n, m); C = rand(n, m);
>> Y = cat(3, A, B, C)
Y(:,:,1) =
0.792207329559554 0.655740699156587 0.849129305868777
0.959492426392903 0.0357116785741896 0.933993247757551
Y(:,:,2) =
0.678735154857773 0.743132468124916 0.655477890177557
0.757740130578333 0.392227019534168 0.171186687811562
Y(:,:,3) =
0.706046088019609 0.27692298496089 0.0971317812358475
0.0318328463774207 0.0461713906311539 0.823457828327293
This can also be accomplished by indexing, for example:
>> Y(:,:,1) = A; Y(:,:,2) = B; Y(:,:,3) = C;
>> Y
Y(:,:,1) =
0.792207329559554 0.655740699156587 0.849129305868777
0.959492426392903 0.0357116785741896 0.933993247757551
Y(:,:,2) =
0.678735154857773 0.743132468124916 0.655477890177557
0.757740130578333 0.392227019534168 0.171186687811562
Y(:,:,3) =
0.706046088019609 0.27692298496089 0.0971317812358475
0.0318328463774207 0.0461713906311539 0.823457828327293
Yes, this is available using cell arrays.
if you have as stated three matrices A,B,C of size n x m.
to assign them to Y your code should be.
Y{1,1} = A;
Y{2,1} = B;
Y{3,1} = C;
As you see cell arrays use {} instead of ().
For more information about cell arrays visit Matlab help
I have a 30-vector, x where each element of x follows a standardised normal distribution.
So in Matlab,
I have:
for i=1:30;
x(i)=randn;
end;
Now I want to create 30*30=900 elements from vector, x to make a 900-vector, C defined as follows:
I am unable to do the loop for two variables (k and l) properly. I have:
for k=1:30,l=1:30;
C(k,l)=(1/30)*symsum((x(i))*(x(i-abs(k-l))),1,30+abs(k-l));
end
It says '??? Undefined function or method 'symsum' for input arguments of type
'double'.'
I hope to gain from this a 900-vector, C which I will then rewrite as a matrix. The reason I have using two indices k and l instead of one is because I eventually want these indices to denote the (k,l)-entry of such a matrix so it is important that that my 900-vector will be in the form of C = [ row 1 row 2 row 3 ... row 30 ] so I can use the reshape tool i.e.
C'=reshape(C,30,30)
Could anyone help me with the code for the summation and getting such a 900 vector.
Let's try to make this a bit efficient.
n = 30;
x = randn(n,1);
%# preassign C for speed
C = zeros(n);
%# fill only one half of C, since it's symmetric
for k = 2:n
for l = 1:k-1
%# shift the x-vector by |k-l| and sum it up
delta = k-l; %# k is always larger than l
C(k,l) = sum( x(1:end-delta).*x(1+delta:end) );
end
end
%# fill in the other half of C
C = C + C';
%# add the diagonal (where delta is 0, and thus each
%# element of x is multiplied with itself
C(1:n+1:end) = sum(x.^2);
It seems to me that you want a matrix C of 30x30 elements.
Given the formula that you provided I would do
x = randn(1,30)
C = zeros(30,30)
for k=1:30
for l=1:30
v = abs(k-l);
for i =1:30-v
C(k,l) = C(k,l) + x(i)*x(i+v);
end
end
end
if you actually need the vector you can obtain it from the matrix.