This question fairly easy doing it manually however, I am struggling to have this written in code.
There is a quartic polynomial:
P(x)=ax^4+bx^3+cx^2+dx+e
There is also a given matrix M:
5 0 -1 2 9
-2 -1 0 1 2
Which the first row gives P(x) and the second row gives the value of x.
Using the information in matrix M, find the coefficients:
a, b, c, d, e
I would know how to work this manually, subbing each column and solve simultaneously with the other columns to obtain a value for each coefficient or put it in a matrix.
I have an idea of what to do, but I don't know how to code it.
I do believe the last line would be linearsolve(M(,1),M(,2)) and thus be able to obtain each coefficient but I have no idea how to get to that line.
Welcome J Cheong
% Values of y and x (note: in your post you had 2 values at x = 1, I assumed that was an accident)
M = [5 0 -1 2 9 ; -2 -1 0 1 2];
% Separate for clarity
y = M(1,:);
x = M(2,:);
% Fit to highest order polynomial model
f = fit(x',y',['poly', num2str(length(y)-1)])
% Extract coefficients
coeff = coeffvalues(f);
% Plotting
X = linspace(min(x)-1, max(x) + 1, 1000) ;
plot(x,y,'.',X,f(X))
Edit
Sorry, I'm using Matlab. Looking at the Octave documentation. You should be able to get the coefficients using
p = polyfit(x,y,length(y)-1)';
Then to display the coefficients the way you specified try this
strcat(cellstr(char(96+(1:length(p))')), { ' = ' } , cellstr(num2str(p)))
y=[5 0 -1 2 9];
x=[-2 -1 0 1 2];
P=polyfit(x,y,2)
gives
P =
2.0000 1.0000 -1.0000
these are your coefficients for c,d,e the others are zero. You can check the result:
polyval(P, x)
ans =
5.0000e+00 2.2204e-16 -1.0000e+00 2.0000e+00 9.0000e+00
which gives you y
Btw, you can solve this very fast just inside your head without calculator because the function values for x=0 and x=+/-1 are very easy to calculate.
Related
I need to understand a part of the GMRES algorithm written in these languages. What makes me a problem is the following piece:
y = H(1:k,1:k) \ beta(1:k);
x = x + Q(:,1:k)*y;
Can someone explain what does it mean in extended form.
Thank you in advance.
For what concerns the first equation:
H(1:k,1:k) = sub-matrix of matrix H that you obtain by taking rows from 1 (beginning) to k and columns from 1 (beginning) to k
beta(1:k) = sub-vector of vector beta that you obtain by taking elements from 1 (beginning) to k
y = is a matrix obtained by solving a symbolic matrix left division between sub-matrix of H and the sub-vector of beta
For what concerns the second equation:
Q(:,1:k) = sub-matrix of matrix Q with all the rows and columns from 1 (beginning) to k
x = a matrix that is obtained by adding to it's previous value the result of the multiplication between the sub-matrix of matrix Q and y
Indexing in Matlab is 1-based, not 0-based. So index 1 corresponds to the first element of whatever you are working with. Example of sub-matrix by indexing:
A = [
2 3 4;
1 2 3;
3 4 4
];
B = A(1:2,1:2);
B is then equal to:
[
2 3;
1 2
];
C = A(:,1:2);
C is then equal to:
[
2 3;
1 2;
3 4
];
That weird division symbol represents a matrix left division (for more information: mathworks.com/help/symbolic/mldivide.html): X = A\B solves the symbolic system of linear equations in matrix form: A*X = B for X.
Lets assume we have some code. In Matlab editor:
x = zeros(1,10);
x(1,1) = 2;
for k = 1: 9
x(k+1) = 10 * x(k);
end
Is it possible to write the equation without the for loop?
Try this:
x = 2 * 10.^(0:9);
Hope that helps.
Check out the logspace function:
x=2*logspace(0,9,10)
You have an error because it is contrary to the rules of matrix multiplication.
My solution below, I used the free analogue of Matlab - Octave, which has a similar syntax:
X=randint(2) % Matrix of size 2 by 2
X =
1 0
0 0
Y=2 * 10.^X(:)
Y =
20
2
2
2
You have a right to multiply the matrix only this type:
M x N on N x P
The result is a matrix of the following dimensions:
M x P
See also:
Element-wise multiplication
Element-wise power
I hope this helped
Could anyone help me build and correct my code which aims to only save the non-zero elements of an arbitrary square matrix and its index? Basically I need to write a script that does the same function as 'sparse' in MATLAB.
`%Consider a 3x3 matrix
A=[ 0 0 9 ;-1 8 0;0 -5 0 ];
n=3; %size of matrix
%initialise following arrays:
RI= zeros(n,1); %row index
CI = zeros(n,1); %column index
V = zeros(n,1); %value in the matrix
for k = 1:n %row 1 to n
for j = 1:n %column 1 to n
if A(k,j)~=0
RI(k)=k;
CI(j)=j;
V(k,j)=A(k,j);
end
end
end`
You could use the find function to find all the non-zero elements.
So,
[RI, CI, V] = find(A);
% 2 1 -1
% 2 2 8
% 3 2 -5
% 1 3 9
EDIT :
I realize from your comments that your goal was to learn coding in Matlab and you might be wondering why your code didn't work as expected. So let me try to explain the issue along with an example code that is similar to yours.
% Given:
A=[ 0 0 9 ;-1 8 0;0 -5 0 ];
Firstly, instead of manually specifying the size as n = 3, I'd recommend using the built-in size function.
sz = size(A);
% note that this contains 2 elements:
% [number of rows, number of columns]
Next, to initialize the arrays RI, CI and V we would like to know their sizes. Since we do not know the number of non-zero elements to start with, we
have two options: (1) choose a large number that is guaranteed to be equal to or greater than the number of non-zero elements, for example prod(sz). (Why is that true?). (2) Do not initialize it at all and let Matlab dynamically allocate memory as required. I'd follow the second option in the code below.
% we'll keep a count of non-zero elements as we find them
numNZ = 0; % this will increment every time a non-zero element is found
for iCol = 1:sz(2) %column 1 to end
for iRow = 1:sz(1) %row 1 to end
if A(iRow,iCol)~=0
numNZ = numNZ + 1;
RI(numNZ) = iRow;
CI(numNZ) = iCol;
V(numNZ) = A(iRow,iCol);
end
end
end
disp([RI, CI, V])
% 2 1 -1
% 2 2 8
% 3 2 -5
% 1 3 9
Makes sense?
So I think we've established that the point of this is to learn an unfamiliar programming language. The simplest solution is to use sparse itself but that gives you no insight into programming. Nor does find, which can be used similarly.
Now, we could go the same route you've started using: procedural for and if over each row and each column. Could be almost any programming language, but for a few quirks of punctuation. But what you'll find, even if you do correct the mistakes (like the fact that n should be the number of non-zero entries, not the number of rows) is that this is a very slow way of doing numerical work in Matlab.
Here's another (still inefficient, but less so) way which will hopefully provide some insight into the "vectorized" way of doing things, which is one of the things that makes Matlab as powerful as it is:
function [RI, CI, V] = mysparse(A) % first: use functions!
[nRows, nCols] = size(A);
[allRowIndices, allColIndices] = ndgrid(1:nRows, 1:nCols) % let's leave the semicolon off so you can see for yourself what it does.
% It's very similar to `meshgrid` which you'll see more often (it's heavily used in Matlab graphics)
% but `ndgrid` is "simpler" in that it's more in tune with the fundamental conventions of Matlab (rows, then columns)
isNonZero = A ~= 0; % this gives you a "logical array" which is a very powerful thing: it can be used as a subscript to select elements from another array, in one shot...
RI = allRowIndices(isNonZero); % like this
CI = allColIndices(isNonZero); % or this
V = A(isNonZero); % or even this
RI = RI(:); % have to do this explicitly, because the lines above will reshape the values into a single long string under some circumstances but not others
CI = CI(:);
V = V(:);
I will go with a N x 3 matrix where N are the number of non-zero elements in the matrix.
% Define a matrix A as follows:
A = randi([0 1],[4 4])
for i=1:16
if A(i) ~= 0
A(i) = rand;
end
end
[row,col] = find(A);
elms = A(A~=0); % MATLAB always works in column-major order and is consistent,
% so no need to use sub2ind to access elements given by find
newSparse_A = [row col elms];
Output:
newSparse_A =
1.0000 1.0000 0.9027
2.0000 1.0000 0.9448
3.0000 1.0000 0.4909
1.0000 2.0000 0.4893
2.0000 2.0000 0.3377
4.0000 2.0000 0.9001
>> sparse(A)
ans =
(1,1) 0.9027
(2,1) 0.9448
(3,1) 0.4909
(1,2) 0.4893
(2,2) 0.3377
(4,2) 0.9001
Problem: Create the function mylinecheck(a,b,c,d,e,f) which takes six inputs:
a,b,c,d,e,f which are real numbers, and a,c,e are not equal. The function must check if the three points (a,b), (c,d), and (e,f) all lie on the same line. If so, return a 1. If not, return a 0.
I think what I want to do is tell MATLAB to check if coordinates (c,d) and (e,f) are multiples of (a,b), and then if not I will return a 0. If so, I will return a 1. If this is the right thought process, I'm not sure how to command MATLAB to do so. Any advice would be greatly appreciated.
The points (x1,y1), (x2,y2), and (x3,y3) lie on the same line if and only if they satisfy
a x + b y + c = 0
for fixed values of a, b, and c (I cannot get over your notation; sorry for the "confusion"), where a or b are nonzero. Hence they lie on the same line if and only if
a x1 + b y1 + c = 0 [x1 y1 1][a] [0]
a x2 + b y2 + c = 0 <=> [x2 y2 1][b] = [0]
a x3 + b y3 + c = 0 [x3 y3 1][c] [0],
that is, the homogeneous linear system with the matrix
[x1 y1 1]
X = [x2 y2 1]
[x3 y3 1]
has a nonzero solution. This is possible only if X is singular. By eliminating the last column of X you can find that X is singular if and only if the matrix
Y = [x2-x1 y2-y1]
[x3-x1 y3-y1]
is singular.
To reliably check for the singularity of a matrix in Matlab, you can use SVD or, equivalently, the function rank. Hence your function could be implemented as follows:
function [result] = mylinecheck(x1,y1,x2,y2,x3,y3)
result = rank([x2-x1, y2-y1; x3-x1, y3-y1]) < 2;
If you want to check if points all fall on the same line (or are collinear), one of the classic methods would be to assume that each point forms a vertex in a triangle. If the three points make the triangle such that the area is equal to 0, then the points would be collinear or form a line. This can be done by checking the determinant of the following matrix:
[a b 1]
[c d 1]
[e f 1]
You can read the article on collinearity on Wolfram Mathworld here: http://mathworld.wolfram.com/Collinear.html (I also linked it above).
As such, your function simply needs to be:
function [out] = mylinecheck(a,b,c,d,e,f)
D = [a b 1; c d 1; e f 1];
out = det(D) == 0;
However, due to numerical imprecision, you may provide floating point numbers where the points are indeed collinear, but you may get a determinant that isn't equal to 0 (actually, perhaps a small number). As such, one thing I can suggest is check to see if the determinant is less than a small number. Something like:
function [out] = mylinecheck(a,b,c,d,e,f)
D = [a b 1; c d 1; e f 1];
out = abs(det(D)) < 1e-10;
1e-10 is a small number which is 10^{-10}. We take the abs to account for both positive and negative determinants, so you would be checking collinearity and is true if:
-10^{-10} < det(D) < 10^{-10}
However, with the comments made by Pavel, if points fall along the same line, if we decide to scale the coordinates, the determinant value will also increase in value as well. One suggestion I have is to perhaps be more liberal with the threshold. Make it larger.... perhaps something like 0.1.
How to calculate this kind of matrix :
A = [ 1 3 4
4 5 7
10 8 6]
X= [x1
x2
x3]
Y= A*X=0
we can change it into :
1x1+3x2+4x3=0
4x1+5x2+7x3=0
10x1+8x2+6x3=0
How to do elimination in Matlab to get the x1, x2 and x3??
I'm not 100% sure what you're asking.
I suppose you want a way to solve a SLE. There are few way to this, the one that I personally find more straightforward is
x=A\b
where in your case:
b=zeros(3,1)
Note that you don't need the vector you're calling X as MATLAB will automatically consider the values in A as coefficient of different variables
My guess is you created an example for this question, but didn't really check if it would produce the desired result. For Ax = 0 to have a non-zero solution, the determinant det(A) must be zero. As the determinant of your A matrix is 40, the only solution is x = [0; 0; 0].
Now, assuming you picked a better example, such as:
A = [1 2 3;2 4 6;1 1 1];
Now, det(A) = 0.
Using regular linsolve, you will still only get x = [0; 0; 0] as a solution. However, there are clearly (infinitely) many other non-trivial solutions. You can achieve one such solution using null like this:
x = null(A)
x =
0.4082
-0.8165
0.4082
A*x
ans =
1.0e-014 *
0.1110
0.2220
0.0944
Which is practically zero (inaccuracies are due to floating point precision).
You can also use Singular value decomposition, svd to get the same results:
[U S V] = svd(A);
x = V(:,end)
x =
0.4082
-0.8165
0.4082
A*x
ans =
1.0e-014 *
0.1110
0.2220
0.0944