How can I partition a matrix into several smaller matrices to find unknown variables?
For example, given:
how can solve this problem by partitioning (splitting) a matrix 3x3 into smaller matrices (1x1 or other) to find the values of x, y, z and u?
Your matrix dimensions dont agree, or am I missing something?
Edit:
The code from Jeff E will work fine on smaller matrices.
For bigger matrices you will need to use backward substitution or some other algorithm, mainly because matrix inversion is a memory intensive task.
In the new image, you isolate for the unknown matrix using some identities:
A * X = B
(inv(A)) * A * X = (inv(A)) * B
I * X = (inv(A)) * B
X = (inv(A)) * B
In Matlab:
A = [1, 2; 0, 1]
B = [4, 7; 4, 6]
X = inv(A) * B
Output:
ans =
-4 -5
4 6
To solve an equation of the form A*X=B, you should use the backslash operator, since explicitly taking the inverse should be avoided if possible
A = [1, 2; 0, 1];
B = [4, 7; 4, 6];
X = A\B
X =
-4 -5
4 6
Related
Trying to replicate a calculation from Matlab in Julia but am having trouble converting a single column complex array into a sparse diagonalized array for matrix multiplication.
Here is the Matlab code I am trying to replicate in Julia:
x*diag(sparse(y))
where x is of size 60,600000 and is of type: double, and y is size 600000,1 and is of type: complex double.
You can use Diagonal for that:
using LinearAlgebra
x=rand(6,60)
y=rand(Complex{Float64},60,1)
x*Diagonal(view(y,:))
I have used view(y,:) to convert y to a Vector - this is here a dimension drop operator you can also use shorter form vec(y) instead. Depending on what you want to do you might explicitly say that you want first column by view(y,:,1).
Note that Diagonal is just a sparse representation of a matrix.
julia> Diagonal(1:4)
4×4 Diagonal{Int64,UnitRange{Int64}}:
1 ⋅ ⋅ ⋅
⋅ 2 ⋅ ⋅
⋅ ⋅ 3 ⋅
⋅ ⋅ ⋅ 4
Another option that might cover more use case scenarios are BandedMatrices:
using BandedMatrices
x*BandedMatrix(0=>view(y,:))
Note that BandedMatrix uses set of pairs for bands, where band 0 is actually the diagonal.
I guess you don't mean it like this, but one can also interpret the question in the way that y is a sparse vector in the Julia sense, and you want to construct a sparse diagonal matrix out of it. In that case you can do the following:
julia> y = sprand(10, 0.2)
10-element SparseVector{Float64,Int64} with 2 stored entries:
[4 ] = 0.389682
[5 ] = 0.232429
julia> I, V = findnz(y)
([4, 5], [0.3896822408908356, 0.2324294021548845])
julia> sparse(I, I, V)
5×5 SparseMatrixCSC{Float64,Int64} with 2 stored entries:
[4, 4] = 0.389682
[5, 5] = 0.232429
Unfortunately, spdiagm does not preserve structural zeros for a sparse input:
julia> spdiagm(0 => y)
10×10 SparseMatrixCSC{Float64,Int64} with 10 stored entries:
[1 , 1] = 0.0
[2 , 2] = 0.0
[3 , 3] = 0.0
[4 , 4] = 0.389682
[5 , 5] = 0.232429
[6 , 6] = 0.0
[7 , 7] = 0.0
[8 , 8] = 0.0
[9 , 9] = 0.0
[10, 10] = 0.0
I don't know whether this is intentional, but I filed an issue about this behaviour.
I am asked to use the least squares method to fit the parameters α and β in y = α*exp(-β*x),
given the points:
x = [1 2 3 4 5 6 7]
y = [9 6 4 2 4 6 9]
I am having trouble determining what my matrix should look like. I know I should take the natural logarithm of both sides of the function in order to get rid of the exponential, and also obtain the natural logarithm of the y-values, which are:
ln_y = [2.19 1.79 1.39 0.69 1.39 1.79 2.19]
However what should my matrix look like, because what I am left with is
ln(y) = ln(α) - β*x?
So the -β column consists of ones and the x column will be my x values, but what should the α column contain?
This is what I assume I should get:
A = [1 1 1 1 1 1 1; 1 2 3 4 5 6 7]
Am I thinking correctly?
The first thing we can do is to take the natural logarithm ln (log in Matlab)) on both sides of the equation:
y = α * e^(-β * x)
becomes:
ln(y) = ln(α * e^(-β * x))
// Law of logarithms
ln(x * y) = ln(x) + ln(y)
// thus:
ln(y) = ln(α) + ln(e^(-β * x))
Simplifying:
ln(y) = -β * x + ln(α)
Now we have ln(y) as a linear function of x and the problem reduces to finding the linear regression in the least square sense. Let's define lny = log(y), and A = ln(α) and we can rewrite the problem as
lny = -β * x + A
Where
x = [1 2 3 4 5 6 7]
lny = [2.19 1.79 1.39 0.69 1.39 1.79 2.19]
For each x_i in x we can evaluate lny as follows (rewritten in ascending power of x):
lny(x1) = A - β * x1
lny(x2) = A - β * x2
...
lny(xn) = A - β * xn
In matrix form
LNY = X * [A β]'
Or,
X * [A β]' = LNY
// let Coefs = [A β]'
Coefs = X^-1 * LNY
In Matlab
x = [1 2 3 4 5 6 7];
y = [9 6 4 2 4 6 9];
lny = log(y);
X = [ones(length(y), 1), -x']; % design matrix
coefs = X\lny'
% A = coefs(1) and β = coefs(2)
% ln(α) = A thus α = exp(A)
alpha = exp(coefs(1));
beta = coefs(2)
You almost had it. The second row should be -x.
x = [1 2 3 4 5 6 7]
y = [9 6 4 2 4 6 9]
logy = log(y)
n = length(x);
A = [ones(1,n); -x]
c = logy/A; %Solve for coefficients
alpha = exp(c(1))
beta = c(2);
In this example, deriving the least squares estimator is a good idea. The other answers take this approach.
There is quick and dirty approach that is flexible and handy.
Just to it numerically. You can use fminsearch to get the job done.
% MATLAB R2019a
x = [1 2 3 4 5 6 7];
y = [9 6 4 2 4 6 9];
% Create anonymous function (your supposed model to fit)
fh =#(params) params(1).*exp(-params(2).*x);
% Create anonymous function for Least Squares Error with single input
SSEh =#(params) sum((fh(params)-y).^2); % Sum of Squared Error (SSE)
p0 = [1 0.5]; % Initial guess for [alpha, beta]
[p, SSE] = fminsearch(SSEh,p0);
alpha = p(1); % 5.7143
beta = p(2); % 1.2366e-08 (AKA zero)
It is always a good idea to plot the results as a sanity check (I screw up often and this saves me time and time again).
yhath=#(params,xval) params(1).*exp(-params(2).*xval);
Xrng = min(x)-1:.2:max(x)+1;
figure, hold on, box on
plot(Xrng,p(1).*exp(-p(2).*Xrng),'r--','DisplayName','Fit')
plot(x,y,'ks','DisplayName','Data')
legend('show')
A Note on Nonlinearity:
This works fine with linear models due to convexity. If your error function is nonlinear but convex, as Sum of Squared Error (SSE), then this also returns the global optimum.
Note that a non-convex function would require multiple start points to attempt to capture many local optima, then taking the best one would still carry no guarantees of optimality. Adding constraints to the solution would require penalty functions or switching to the constrained solver since fminsearch solves the unconstrained problem (unless you penalize it properly).
Easy to Modify:
It is easy to modify the model and the error function. For example, if you wanted to minimize the sum of the absolute error instead, it is straightforward using abs.
% Create anonymous function for Least Absolute Error with single input
SAEh =#(params) sum(abs(fh(params)-y)); % Sum of Absolute Error
How Do i solve this summation in MATLAB without using for/while loop?
Here C is a vector(1*N matrix), n=length(c) and x is scalar.
c(1)*x^1+c(2)*x^2+c()*x^3+....+c(n)*x^n.
Or can i Create a matrix with all element equal to x but with increasing power, like x, x^2,x^3....?
There are several ways:
result = polyval(fliplr([0 c]), x);
result = sum(c.*x.^(1:numel(c)));
result = sum(c.*cumprod(repmat(x, 1, numel(c))));
As an example, for
c = [3 4 -5 2 3];
x = 9;
any of the above gives
result =
186975
Check:
>> c(1)*x^1+c(2)*x^2+c(3)*x^3+c(4)*x^4+c(5)*x^5
ans =
186975
I have a list of formula stored in a cell array, and I solve the unknowns within the matrix.
For example, consider a 2*2 matrix:
[2x+y, 4q+z; 3x+0.5y, 2q+12z ]
How to solve q,x,y,z by setting each cell equals 20? (i.e., q= 4, x =5, y = 10, z=1)
You're asking to solve a linear system. The canonical way to write a linear system is as A*x = b where A is a matrix, x is the vector to solve for, and b is also a vector. Writing your problem (in math) using matrices, the system is:
[0 2 1 0 [q [20
4 0 0 1 * x = 20
0 3 .5 0 y 20
2 0 0 12] z] 20]
To solve the system numerically in MATLAB:
A = [0, 2, 1, 0; 4, 0, 0, 1;, 0, 3, .5, 0; 2, 0, 0, 12];
b = [20; 20; 20; 20];
xsol = linsolve(A, b);
You could also do xsol = A \ b. A point of caution: both linsolve and \ will solve the system in the least squares sense if the system is overdetermined (typically, system is overdetermined if A is m by n where m > n).
xsol(1) will give the value for q, xsol(2) will give value for x, etc...
Solution is [4.7826; 5.0000; 10.0000; 0.8696]
One way to achieve what you are looking for is to use the Symbolic Toolbox. Here is an example code to solve for q, x, y, and z.
syms q x y z
A = [2*x+y==20, 4*q+z==20; 3*x+0.5*y==20, 2*q+12*z==20];
S = solve(A,[q x y z]);
disp([S.q S.x S.y S.z]);
Output:
[110/23, 5, 10, 20/23]
I have two matrices A and B. A is N-by-L matrix and B is L-by-N matrix.
A = [1 2 3;
4 5 6];
B = [ 7 8;
9 10;
11 12];
I would like to multiply the each row of the first matrix by the corresponding column of the second matrix. After the multiplication I would have a (Nx1) vector. The result would be
C = [ 1*7 + 2*9 + 3*11,
4*8 + 5*10 + 6*12];
I can perform the multiplication with a for loop, but it is not efficient for large matrices.
ASize = size(A);
for i = 1:ASize(1),
C(i) = A(i,:) * B(:,i);
end
Is there a better way to do this?
I think this should do the trick:
C = sum(A.*B', 2);
I think this will work better and is simple
C=diag(A*B);