How to solve simple linear algebra equations using symbolic objects? - matlab

This is probably very simple but I'm having trouble setting up matrices to solve two linear equations using symbolic objects.
The equations are on the form:
(1) a11*x1 + a12*x2 + b1 = 0
(2) a21*x1 + a22*x2 + b2 = 0
So I have a vector {E}:
[ a11*x1 + a12*x2 + b1 ]
{E} = [ a21*x1 + a22*x2 + b2 ]
I want to get a matrix [A] and a vector {B} so I can solve the equations, i.e.
[A]*{X} + {B} = 0 => {X} = -[A]{B}.
Where
[ x1 ]
{X} = [ x2 ]
[ a11 a12 ]
[A] = [ a21 a22 ]
[ b1 ]
{B} = [ b2 ]
Matrix [A] is just the Jacobian matrix of {E} but what operation do I have to perform on {E} to get {B}, i.e. the terms that don't include an x?
This is what I have done:
x = sym('x', [2 1]);
a = sym('a', [2 2]);
b = sym('b', [2 1]);
E = a*x + b;
A = jacobian(E,x);
n = length(E);
B = -E;
for i = 1:n
for j = 1:n
B(i) = subs(B(i), x(j), 0);
end
end
X = A\B
I'm thinking there must be some function that does this in one line.
So basically my question is: what can I do instead of those for loops?
(I realize this is something very simple and easily found by searching. The problem is I don't know what this is called so I don't know what to look for.)

It is just B = subs(B,x,[0 0])

Related

Matlab - Solving a system of 2 matricial equations : building each element of matrix solution

With Matlab, I have a matrix solution to find from 2 matricial equations (size matrix is 7x7). Here the 2 equations to solve with "a" and "b" are the unknow matrices and where F1, F2, P1 and P2, D, D2, D are known. Solving "a" and "b" would allow me to build a new matrix P = a . P1 + b . P2 . (remark : D matrix is equal to : D = a.a.D1 + b.b.D2 with D1and D2 diagonal matrices) :
a.a + a.P1.b.P2^T + b.P2.a.P1^T + b.b - Id = 0 (equation 1)
F1.a.P1 + F1.b.P2 + F2.a.P1 + F2.b.P2 − (a.P1 + b.P2).D = 0 (equation 2)
Question 1) Is there a solver in Matlab that would allow to directly find matrices "a" and "b" ?
Question 2) If there is no directly solving, I think that I have to solve each solution a(i,j) and b(i,j) by using a double loop on i and j indices and call fsolve in inner loop.
The problem is that I have to respect the order in matricial product and it is difficult to not make errors when I implement the code.
Here the 2 equations that I must solve on "a" and "b" unknown :
equation(1)
equation(2)
So I tried to implement the solving of each matrix element, i.e a(i,j) and b(i,j)
For this, I am using a symbolic array x[7 7 2] and did :
% eigenv_sp = P1
% eigenv_xc = P2
% FISH_sp = F1
% FISH_xc = F2
% FISH_eigen_sp = D1
% FISH_eigen_xc = D2
% Fisher matrices
F1 = FISH_sp;
F2 = FISH_xc;
% Transposed matrix
transp_eigenv_sp = eigenv_sp'
transp_eigenv_xc = eigenv_xc'
% Symbolic variables
x = sym([7 7 2]);
aP1 = sym([7 7]);
aP1T = sym([7 7]);
bP2 = sym([7 7]);
bP2T = sym([7 7]);
d1 = sym([7 7]);
d2 = sym([7 7]);
d = sym([7 7]);
ad1 = sym([7 7]);
bd2 = sym([7 7]);
for k=1:7
for l=1:7
aP1(k,l) = sum(x(k,1:7,1).*eigenv_sp(1:7,l));
bP2(k,l) = sum(x(k,1:7,2).*eigenv_xc(1:7,l));
aP1T(k,l) = sum(x(k,1:7,1).*transp_egeinv_sp(1:7,l));
bP2T(k,l) = sum(x(k,1:7,2).*transp_egeinv_xc(1:7,l));
a2(k,l) = sum(x(k,1:7,1).*x(1:7,l,1));
b2(k,l) = sum(x(k,1:7,2).*x(1:7,l,2));
d1(k,l) = FkSH_ekgen_sp(k,l);
d2(k,l) = FkSH_ekgen_xc(k,l);
d(k,l) = d1(k,l) + d2(k,l);
ad1(k,l) = sum(x(k,1:7,1).d1(1:7,l));
bd2(k,l) = sum(x(k,1:7,2).d2(1:7,l));
end
end
% Function that represents `(a,b)(i,j)` unknown element represented by `(y(i,j,1),y(i,j,2))`
myfun=#(x,i,j) [
% First equation
sum(x(i,1:7,1).*x(1:7,j)) + sum(aP1(i,1:7).*bP2T(1:7,j)) + sum(bP2(i,1:7).*aP1T(1:7,j)) + sum(x(i,1:7).*x(1:7,2)) - eq(i,j);
% second equation
sum(F1(i,1:7).*aP1(1:7,j)) + sum(F1(i,1:7).*bP2(1:7,j)) + sum(F2(i,1:7).*aP1(1:7,j)) + sum(F2(i,1:7).*bP2(1:7,j)) - ...
sum(aP1(i,1:7).*ad1(1:7,j)) + sum(bP2(i,1:7).*ad1(1:7,j)) + sum(adP1(i,1:7).*dP2(1:7,j)) + sum(bP2(i,1:7).*dP2(1:7,j));
]
% Solution of system of non linear equations with loop
y = zeros(7, 7, 2);
for i=1:7
for j=1:7
a0 = 1e7;
b0 = 1e7;
x0 = [ a0 b0];
y(i,j,:) = fsolve(#(x)myfun(x,i,j),x0)
end
end
But at the execution, I have the following error :
Index exceeds matrix dimensions.
Error in sym/subsref (line 814)
R_tilde = builtin('subsref',L_tilde,Idx);
Error in compute_solving_Matricial_Equations_dev (line 60)
aP1(k,l) = sum(x(k,1:7,1).*eigenv_sp(1:7,l));
I don't understand where is the issue, I only iterate on index 1:7, if someone could see what's wrong ?
Update 1
I wonder if I have the right to use for a given index i the symbolic expression x(1:7,i,1) whereas this array is not known numerically but defined only from a symbolic point of view.
Update 2
Maybe I have a clue.
If I do an expand of the symbolic array x (of size (7,7,2)), I get :
>> expand(sum(x(1,1:7).*x(1:7,1)))
Index exceeds matrix dimensions.
Error in sym/subsref (line 814)
R_tilde = builtin('subsref',L_tilde,Idx);
So, the only thing to done I think is to explicitly write the 7x7 equations
with 7x7 = 49 couples unknown x(i,j,1) and x(i,j,2) which corresponds to a(i,j) and b(i,j) matrices.
Update 3
I think the key point is to put into function myfun the 2 matrical equations but with taking into account of the 49 (7x7) couples (a(i,j) and b(i,j)) unknown that I defined previously as symbolic variables with array x[7 7 2].
And second point, I must to "make understand" to fsolve that we are searching for each iteration (double loop on (i,j)) the value of a(i,j) and b(i,j) given the whole 49 equations. Maybe it would be necessary to expand for example the expression of x(i,1:7) or x(1:7,j) in myfun function but I don't know how to proceed.

Finding Cubic Polynomials

I have an equation: y=ax^3 + bx^2 + cx + d and the list of values x = 1, 2, 3, 4 when y = 3, 4, 3, -6 respectively. In Octave, I want to:
(a) Set up a system of four equations involving a, b, c and d. For example, substituting (x, y) = (1,3) into the polynomial gives the equation 3 = a + b + c + d.
(b) Solve the system in (a).
I've been trying to find how to do this for three hours and found nothing. Any help would be appreciated
Thanks.
pstscrpt - I have to do everything in Octave, even though I could find it by hand
Written without any ; at end of assignements so you can see what is going on.
You problem is basically a linear system in the variables [a,b,c,d]'=z
So you need to build a system A*z=y, where A is a matrix 4x4, y and z are column vector size 4
x=[1,2,3,4]'
y=[3,4,3,-6]'
A=zeros(4,4)
for i=1:4
A(i,:)= [ x(i)^3, x(i)^2, x(i), 1]
endfor
z=A\y
the outcome will be
z =
-1.00000
5.00000
-7.00000
6.00000
In Matlab: start by just substituting the different values of x and y you wrote in the expression a*x^3 + b*x^2 + c*x + d = y as:
syms a b c d
eqn1 = a*1^3 + b*1^2 + c*1^1 +d == 3 ;
eqn2 = a*2^3 + b*2^2 + c*2^1 +d == 4 ;
eqn3 = a*3^3 + b*3^2 + c*3^1 +d == 3 ;
eqn4 = a*4^3 + b*4^2 + c*4^1 +d == -6 ;
Then Use equationsToMatrix to convert the equations into the form AX = B. The second input to equationsToMatrix specifies the independent variables in the equations.:
[A,B] = equationsToMatrix([eqn1, eqn2, eqn3, eqn4], [a, b, c,d ])
and the solution for a,b,c,d is:
X = linsolve(A,B)
you can also use if you want
sol = solve([eqn1, eqn2, eqn3, eqn4], [a, b, c,d ])

How to code a vectorized expression that depends on other vectorized expression?

If for example I have three expressions: A, B and C as follows:
A(i+1) = A(i) + C(i).k
B(i+1) = B(i) + A(i).h
C(i+1) = A(i) + B(i)
where k and h are some constants and m and n is the desired size of C. i is the previous obtained value, i+1 is the next value. Now, if I use for loop, then I can code it as:
A(1)= 2;
B(1)= 5;
C(1)= 3;
for i=1:10
A(i+1) = A(i) + C(i)*2;
B(i+1) = B(i) + A(i)*3;
C(i+1) = A(i) + B(i);
end
And it works just fine. But I want to code it in a vector form, as in without having to use a loop. But the problem is I do not know how to get around the dependency of:
A on its previous value and previous C value
B on it previous values and previous C value of A
C on the previous values of A and B
Here's a matrix-based way to obtain the n-th value of the [A;B;C] vector. I wouldn't exactly call it vectorization, but this could speed things up considerably for you:
[A,B,C] = deal(zeros(11,1));
A(1)= 2;
B(1)= 5;
C(1)= 3;
%% // Original method
for k=1:10
A(k+1) = A(k) + C(k)*2;
B(k+1) = B(k) + A(k)*3;
C(k+1) = A(k) + B(k);
end
%% // Matrix method:
%// [ A ] [1 0 2][ A ]
%// | B | = |3 1 0|| B |
%// [ C ] [1 1 0][ C ]
%// i+1 i
%//
%// [ A ] [1 0 2][ A ] [1 0 2] ( [1 0 2][ A ] )
%// | B | = |3 1 0|| B | = |3 1 0| * ( |3 1 0|| B | )
%// [ C ] [1 1 0][ C ] [1 1 0] ( [1 1 0][ C ] )
%// i+2 i+1 i
%// Thus, this coefficient matrix taken to the n-th power, multiplied by the input
%// vector will yield the values of A(n+1), B(n+1), and C(n+1):
M = [1 0 2
3 1 0
1 1 0];
isequal(M^10*[A(1);B(1);C(1)],[A(11);B(11);C(11)])
In reality you can use M to the appropriate power (positive or negative) to obtain any [A,B,C]n from any [A,B,C]k ...
First, forgive me for abusing Matlab syntax for expressing mathematical stuff.
Consider following code, where we do exactly the same as in your example. Note that A,B,C are the rows of X.
X = zeros(3,N+1);
X(:,1) = [2,5,3];
M= [1,0,2;3,1,0;1,1,0];
for i=1:N
X(:,i+1) = M*X(:,i);
end
This is just a matrix vector notation of the above code. I think it is even slower. Note that we could also compute: X(:,i+1) = M^i * X(:,1) which is even slower.
Notice that we can use the eigenvalue decomposition:
[V,D] = eigs(M);
X(:,i+1) = [V*D*inv(V)]^i * X;
Therefore
X(:,i+1) = V*D^i*inv(V) * X;
So V*D^i*inv(V) is an explicit formula for the i+1th term of X. I suggest computing those analytically, and plug the formula you get into your code again.
EDIT: I wrote some code that should be close to analyitcally solving the system, you can compare the runtimes. It seems in the end preallocation with your first method is still the fastest IF you need ALL the terms. If you only need one of them, my suggested method is certainly quicker.
clear;clc
N = 10000000;
tic
A(1)= 2;
B(1)= 5;
C(1)= 3;
A = zeros(1,N+1);
B=A;C=A;
for i=1:N
A(i+1) = A(i) + C(i)*2;
B(i+1) = B(i) + A(i)*3;
C(i+1) = A(i) + B(i);
end
toc
tic
X = zeros(3,N+1);
X(:,1) = [2,5,3];
M= [1,0,2;3,1,0;1,1,0];
for i=1:N
X(:,i+1) = M*X(:,i);
end
toc
tic
M= [1,0,2;3,1,0;1,1,0];
[V,D]=eig(M);
v=0:N;
d=diag(D);
B=bsxfun(#power,repmat(d,1,N+1),v);
Y=bsxfun(#times,V * B, V \[2;5;3]);
toc
tic
M= [1,0,2;3,1,0;1,1,0];
[V,D]=eig(M);
v=0:N;
d=diag(D);
Y = ones(3,N+1);
for i=1:N
Y(:,i+1) = d.*Y(:,i);
end
Y=bsxfun(#times,V * B, V \[2;5;3]);
toc

solve linear programming by simplex on MATLAB

I have A, b, f matrices as follows :
A = [ 2 1
1 2 ]
B = [ 4; 3 ]
F = [ 1; 1 ]
LB = [ 0; 0 ]
[X, fval, exitflag, output, lambda] = linprog(F, A, B, [], [], LB)
After that, the solution provided by the MATLAB is surprising. It says the value of fval is 1.2169e-013. This is not the solution. Can you help me by identifying the fault?

Use zero based matrix in MATLAB

Could the following equation be possible in MATLAB?
Suppose we have given data of length N, and we want to consider a linear equation among the some L nubmers and find coefficients ai. Is this possible? Because if yes, then coefficients can be solved by
a = pinv(D)*d
where D is a given matrix and d is a left vector.
The above equation comes from the following linear models
k = L, L+1, L+2, N-1
I have tested this code with some fixed f.
unction [a] = find_coeficient(y,N,L)
Lp = L + 1;
Np = N + 1;
d = y(L:N-1);
D=[];
for ii=Lp:(Np-1)
% Index into the y vector for each row of D
D = vertcat(D, y(ii:-1:(ii-Lp+1))');
end
a = D\d;
end
Is it correct?
This is absolutely possible in MATLAB. However, 0 indexes are not natively supported. You will need to do a "change of variables" by letting the index in each element be index+1. Here's a bit of an example:
% Generate some data
N = 40;
y = 10 * randn(N,1);
% Select an L value
L = N - 4 + 1;
d = y(L:N);
D = reshape(y,4,10);
% Solve the equation using the '\' rather than the pseudo inverse
b = D\d
For more information on the divide operator, see Systems of Linear Equations.
OK, I've thought through this a bit more. Part of the confusion here is the change of variable limits. The substitution applies to the indexing variable, not the size of the data, so L and N are unchanged, but the index is adjusted to keep it from falling off the edge of the array. So in the formula, just add 1 to every element index.
y[L] = [ y[L-1] y[L-2] ... y[0] ] * a1
.
.
y[N-1] = [ y[N-2] y[N-3] ... y[N-L-1] ] * aL
becomes:
y[L+1] = [ y[L-1+1] y[L-2+1] ... y[0+1] ] * a1
.
.
y[N-1+1] = [ y[N-2+1] y[N-3+1] ... y[N-L-1+1] ] * aL
=
y[L+1] = [ y[L] y[L-1] ... y[1] ] * a1
.
.
y[N] = [ y[N-1] y[N-2] ... y[N-L] ] * aL
Which we can then use to complete our script:
function a = find_coeficient(y,N,L)
d = y((L+1):N);
D=[];
for ii=L:(N-1)
% index into the y vector for each row of D
D = vertcat(D, y(ii:-1:(ii-L+1))');
end
a = D\d;
end