I have a system of three equations that I'd like to solve via MATLAB, and I'm a bit confused on how to go about doing it.
I have three equations:
A = R*P1
B = R*P2
C = R*P3
A, B, C, and P1, P2, and P3 are 3x1 matrices, while R is a 3x3 matrix. R is the same for all three equations.
I need to find R, and am given A, B, C, and the P's.
I wanted to use fsolve, but it seems that fsolve doesn't work when the variables are matrices. What is an alternative method that you would recommend using?
Just making up some numbers to work with:
P1 = [1;1;1];
P2 = [2;3;4];
P3 = [5;4;3];
R = [2 4 5; 1 5 4; 1 2 3];
Which would mean that:
A = [11;10;6];
B = [36;33;20];
C = [41;37;22];
If A, B, C, P1, P2, P3 are all numerical, why don't you simply use the ldivide or \ operator? This will allow you to solve your linear system directly. I can see that you have the following relationships:
R*P1 = A
R*P2 = B
R*P3 = C
You can see that each matrix equation yields three constraints. What you can do is create one system that encapsulates all matrix equations together thus yielding 9 constraints. As such, you'll need to reformulate this to be able to solve for your coefficients in your matrix R differently. To do this, we need to reshape your matrix R such that it becomes a 9-element vector. In other words, we can then reformulate your system like so:
[P1 0 0 0 0 0 0] [R1] [ ]
[0 0 0 P1 0 0 0] [R2] [ A ]
[0 0 0 0 0 0 P1] [R3] [ ]
[P2 0 0 0 0 0 0] [R4] [ ]
[0 0 0 P2 0 0 0] * [R5] = [ B ]
[0 0 0 0 0 0 P2] [R6] [ ]
[P3 0 0 0 0 0 0] [R7] [ ]
[0 0 0 P3 0 0 0] [R8] [ C ]
[0 0 0 0 0 0 P3] [R9] [ ]
P * R = D
You'll see that we have a 9 x 9 matrix called P, our matrix R which is reshaped into a vector so that we can solve for the coefficients and D are A,B,C concatenated together into one vector. R1 to R9 are the coefficients of the matrix R that are read from left to right and top to bottom.
Therefore, to find your coefficients in your matrix, simply do:
R = P^{-1}*D
As such, simply construct the matrix P and vector D like so:
P = [P1.' zeros(1,6); zeros(1,3) P1.' zeros(1,3); zeros(1,6) P1.'; ...
P2.' zeros(1,6); zeros(1,3) P2.' zeros(1,3); zeros(1,6) P2.'; ...
P3.' zeros(1,6); zeros(1,3) P3.' zeros(1,3); zeros(1,6) P3.'];
D = [A; B; C];
Now, simply solve for R and reshape it back into a 3 x 3 matrix. Therefore:
R = P \ D;
R = reshape(R, 3, 3).';
reshape turns our vector into a 3 x 3 matrix, but it constructs the matrix in column-major format, so you need to transpose the result after you call reshape. With your example, this is what we get. I construct P1, P2, P3, A, B, C, then use the code I had from before:
P1 = [1;1;1];
P2 = [2;3;4];
P3 = [5;4;3];
A = [11;10;6];
B = [36;33;20];
C = [41;37;22];
P = [P1.' zeros(1,6); zeros(1,3) P1.' zeros(1,3); zeros(1,6) P1.'; ...
P2.' zeros(1,6); zeros(1,3) P2.' zeros(1,3); zeros(1,6) P2.'; ...
P3.' zeros(1,6); zeros(1,3) P3.' zeros(1,3); zeros(1,6) P3.'];
D = [A; B; C];
R = P \ D;
R = reshape(R, 3, 3).';
To verify that R is correct, do:
A1 = R*P1;
B1 = R*P2;
C1 = R*P3;
We get for each:
A1 =
11
10
6
B1 =
36
33
20
C1 =
41
37
22
This matches up with your example. However, note that you may get a warning that R is ill-conditioned. This is because you may not have enough constraints to properly find a unique inverse. You may have to add more constraints to get a unique inverse, but if you can't, then use this with caution.
Have you tried to flatten out the matrices inside of the solve function? There is a collect function in MATLAB that collects coefficients, but you need to check if it works with supplying a row matrix, as opposed to a sum. (maybe sum(row matrix) - if it also combines like terms)
Something like:
[x,y,x] = solve(sum(R*P1)==A, sum(R*P2)==B, sum(R*P3)==C, x,y,z)
or the fsolve function
Related
Given this objective function:
Minimize:
f = (Ax + By)' * G * (Ax + By)
subject to some equalities and inequalities.
where x and y are real-valued vectors (decision variables) with p and q elements, respectively. A of size m * p, B of size m * q, G is a symmetric matrix of size m * m.
My question is how to write f in the form v' * G * v, such that it can be easily be used in quadprog. In other words, how to mix A, B and G?
This looks incompletely specified!
It seems, for whatever reason, you want to model in terms of two variable components. Now you did not specify how they interact with each other.
As most optimizers work on a single variable-vector, you need to concatenate yours.
As you did not show G, i'm assuming you got one G for x and one for y, let's call it H.
(Remark: not a matlab user; don't take example-syntax for granted!)
z = [x y]
P = blkdiag(G,H)
assuming x and y independent in regards to quadratic-term
e.g. no x0*y1 like terms
Solve: for z` P z
Example:
x = [x0 x1 x2]
y = [y0 y1]
G = [6 2 1; 2 5 2; 1 2 4]
H = [8 2; 2 10]
# G
6 2 1
2 5 2
1 2 4
# H
8 2
2 8
z = [x0 x1 x2 y0 y1]
P = [6 2 1 0 0; 2 5 2 0 0; 1 2 4 0 0; 0 0 0 8 2; 0 0 0 2 8]
# P
6 2 1 0 0
2 5 2 0 0
1 2 4 0 0
0 0 0 8 2
0 0 0 2 8
i have a vector and a scalar as input in a problem , the problem is to compute the largest product of n consecutive number of the vector and output the product and the index of the element of the vector that is the first term of the product.
E.g vector =[ 1 2 3 4 5 6] , n=3
I'm supposed to get '3' (i e n) consecutive number of vector whose product is the largest .
in this case it will be 4*5*6
so output will be 120 and 4 as the index.
now if vector has fewer than 'n' elements, the function outputon returns 0 and -1 as the output.
please i need ideas on how to achieve this
You can make a simple implementation with loops:
a = [1 2 3 4 5 6]
w = 3
n = length(a)
maximum = -1
for i = 1:n-w
p = prod(a(i:i+w))
if (p > maximum)
maximum = p
end
end
maximum
Or, you can use the nlfilter from the image processing palette.
a = []
w = 3
if (length(a) >= w)
products = nlfilter(a, [1 w], #(x) prod(x))
res = max(products)
else
res = -1
end
You can create the moving window from the answer of raryeng for the question Matrix with sliding window elements and then appyl cumprod on the columns and take the max with its index.
myvec = [1 2 2 1 3 1];
n = 3;
ind = bsxfun(#plus, 1:n, (0:1:length(myvec)-n).')';
M = cumprod(myvec(ind));
[val,its_ind] = max(M(end,:));
You can encapsulate this with an if condition checking whether the length of myvec is larger than
You can compute the element-wise logarithm of your vector, so multiplication becomes addition; and sliding addition is just convolution with a window of ones:
function [m, p] = f(v, n)
if numel(v) < n
m = -1;
p = 0;
else
c = conv(log(v(:)), ones(n,1), 'valid'); % convolution with vector of n ones
[~, m] = max(c); % starting index of maximizing window
p = prod(v(m+(0:n-1))); % corresponding product
end
Examples:
>> v = [1 2 3 4 5 6]; n = 3;
>> [m, p] = f(v,n)
m =
4
p =
120
>> v = [1 2 3 4 5 6]; n = 7;
>> [m, p] = f(v,n)
m =
-1
p =
0
>> v = [1 4 6 2 5 3]; n = 3;
>> [m, p] = f(v,n)
m =
3
p =
60
I have 2 sequences in a cell-array :
Input_cell= {'ABC','ACB'}
S1= 'ABC' % which means A<B<C
S2= 'ACB' % which means A<C<B
I want to convert each of the strings in the Input_cell into a matrix M[i,j] which has to satisfy those conditions :
M[i,j] , M[j,i] are random
M[i,i] =0.5
M[i,j] + M[j,i] = 1
M[i,j] < M[j,i] % For example: if A<B then M[A,B] < M[B,A]
%// For example: if we have S1 = 'ABC' (which means `A<B<C`), the M1 matrix will be expected as follows:
A B C
A 0.5 0 0
B 1 0.5 0
C 1 1 0.5
%// If we have S2 = 'ACB' (which means `A<C<B`), the M2 matrix will be expected as follows:
A B C
A 0.5 0 0
B 1 0.5 1
C 1 0 0.5
How to create that kind of above matrices from a given cell-array of sequences?
%get the ordering, where '312' would mean that A is largest, then C, then B
[~,k]=sort(S2);
%compare each pair
bsxfun(#(a,b)(a<b)+0.5*(a==b),k,k')
I'm trying to create a diagonal matrix using the following matrix as the diagonal
base = [a b c d e f 0;
0 g h i j k l];
I need the resulting matrix to look like this...
[a b c d e f 0 0 0;
0 g h i j k l 0 0;
0 0 a b c d e f 0;
0 0 0 g h i j k l];
except it needs to be "n" elements tall
I have tried using the kron function, but it shifts each consecutive row too many elements to the right.
How can I accomplish what I need in a way where I can select n arbitrarily?
You can do it pretty fast with a 2D convolution:
n = 4; %// desired number of rows in result. Should be a multiple of size(base,1)
T = eye(n-1);
T(2:size(base,1):end,:) = 0;
result = conv2(base,T);
Example: with
base =
0.7497 0.3782 0.4470 0.5118 0.6698 0.3329 0
0 0.9850 0.5638 0.9895 0.4362 0.4545 0.8578
and n=4 the result is
result =
0.7497 0.3782 0.4470 0.5118 0.6698 0.3329 0 0 0
0 0.9850 0.5638 0.9895 0.4362 0.4545 0.8578 0 0
0 0 0.7497 0.3782 0.4470 0.5118 0.6698 0.3329 0
0 0 0 0.9850 0.5638 0.9895 0.4362 0.4545 0.8578
The easy way is to use repeated out-of-bounds assignment. MATLAB will automatically pad any missing entries with 0 in those cases. Here's how:
%// Some test variables
a = rand; g = rand;
b = rand; h = rand;
c = rand; i = rand;
d = rand; j = rand;
e = rand; k = rand;
f = rand; l = rand;
%// base matrix
base = [
a b c d e f 0;
0 g h i j k l];
%// use out-of-bounds assignment
n = 3;
output = base;
for ii = 1:n
output(end+1:end+size(base,1), size(base,1)*ii+1:end+size(base,1)) = base;
end
The hard way is the faster way (relevant for when n is large and/or you need to repeat this very often). Figure out the pattern behind which indices would be filled in the final matrix by which values in the original matrix, then generate a list of those indices and assign those values to those indices:
[b1,b2] = size(base);
[ii,jj,vv] = find(base);
inds = bsxfun(#plus, (ii + (n+1)*b1*(jj-1)).', (0:n).'*b1*(1 + (n+1)*b1));
output = zeros( (n+1)*b1, b2+n*b1 );
output(inds) = repmat(vv.', n+1, 1)
I'll leave it as an exercise for you to figure out what happens here exactly :)
I have two diagonal matrices. I am trying to build a larger block diagonal matrix from them. For example if I had this:
D = diag(zeros(3,1)+1)
D =
1 0 0
0 1 0
0 0 1
and...
E = diag(zeros(2,1)+2, -1) + diag(zeros(2,1)+2, +1) + diag(zeros(3,1)+4)
E =
4 2 0
2 4 2
0 2 4
I have an equation that says A*U = X
Where A is
[E D 0
D E D
0 D E]
This is for 3x3. 5x5 would look like this:
A =
[E D 0 0 0
D E D 0 0
0 D E D 0
0 0 D E D
0 0 0 D E]
A would be another diagonal matrix consisting of these matrices. I need to produce a 40x40 and it would take a VERY LONG TIME to do manually, of course.
How can I define that? I haven't figured out how to use blkdiag to construct.
I solved this on my own manually because I could never find a Matlab function to help me.
for n = 1:Distance_Resolution
A(((n-1)*Distance_Resolution +1):n*Distance_Resolution, ((n-1)*Distance_Resolution +1):n*Distance_Resolution) = A1;
if n == Distance_Resolution
else
A((n*Distance_Resolution+1):(n+1)*(Distance_Resolution), ((n-1)*Distance_Resolution+1:n*Distance_Resolution)) = A2;
A((n-1)*Distance_Resolution+1:n*Distance_Resolution, (n*Distance_Resolution+1):(n+1)*(Distance_Resolution)) = A2;
end
end
This will produce a block matrix that has the above specified demands and is of length Distance_Resolution x Distance_Resolution x Distance_Resolution. I defined A1 and A2 through help from above poster (Fo is just a constant here):
vector = zeros(Distance_Resolution,1) - Fo;
A2 = diag(vector);
A1 = toeplitz([1+4*Fo, -Fo, zeros(1,Distance_Resolution-2)]);
This is a workable code snippet, but I am still looking for a smarter way to code it.