How to go from a symbolic expression to a vector in MATLAB - matlab

I am working on a function that will generate polynomial interpolants for a given set of ordered pairs. You currently input the indexes of the node points in one vector, and the values of the function to be interpolated in a second vector. I then generate a symbolic expression for the Lagrange polynomial that interpolates that set of points. I would like to be able to go from this symbolic form to a vector form for comparison with test functions and such. That is, I have something that generates some polynomial P(x) in terms of some symbolic variable x. I would like to then sample this polynomial to a vector, and get values for the polynomial over (for example) linspace(-1,1,1000). If this is possible, how do I do it?
I guess I'll include the code that I have so far:
function l_poly = lpoly(x,f)
% Returns the polynomial interpolant as computed by lagrange's formula
syms a
n=size(x,2);
l_poly_vec = 1;
l_poly=0;
for k=1:n,
for l=1:n,
if (k ~= l)
l_poly_vec=l_poly_vec*(a-x(l))/(x(k)-x(l));
end
end
l_poly=l_poly+f(k)*l_poly_vec;
l_poly_vec = 1;
end
I plan on adding a third (or possibly fourth) input depending on how I can solve this issue. I'm guessing I would just need the length of the vector I want to sample to and the endpoints.

If I understand you correctly, you've constructed a Lagrange interpolating polynomial using the symbolic toolbox and now wish to evaluate it over a vector of values. One way to do this is to use the function sym2poly to extract the coefficients of the symbolic polynomial, and then use polyval to evaluate it. Alternatively, you could use matlabFunction to convert your symbolic expression into a regular Matlab function; or use subs to substitute in a numeric value for 'x'.
However, you would probably be better off avoiding the symbolic toolbox altogether and directly constructing the coefficients of the Lagrange interpolating polynomial, or, better yet, use a different interpolation scheme altogether. The function interp1 might be a good place to start.

Related

How to compute symbolic computation of transfer function matrix?

Here I've a transfer function matrix with size of (3*7):
G = [G11,G12,G13,G14,G15,G16,G17;
G21,G22,G23,G24,G25,G26,G27;
G31,G32,G33,G34,G35,G36,G37]
Is it possible to get A = [G*(G^(-1))T] symbolically in Matlab:
Where :
G^(-1) = inv(G) and (G^(-1))T = transpose of (inv(G))
Yeah it's possible but it may take a lot of time, and also it's possible that your computer runs out of memory. Matlab's symbolic operations are not very good, but here's the solution. First define the elements of your matrix as symbolic variables. syms G11 defines G11 as symbolic. than define your G matrix and go on. Than you can find the A matrix.
I should also mention that since your matrix is 3*7, I don't know if matlab have inverse command for non-square matrix, but you can have pseudo inverse. And if you want to do symbolic computations, Maple and mathematica are so much better. But matlab is better in Numerical computations .

For loop equation into Octave / Matlab code

I'm using octave 3.8.1 which works like matlab.
I have an array of thousands of values I've only included three groupings as an example below:
(amp1=0.2; freq1=3; phase1=1; is an example of one grouping)
t=0;
amp1=0.2; freq1=3; phase1=1; %1st grouping
amp2=1.4; freq2=2; phase2=1.7; %2nd grouping
amp3=0.8; freq3=5; phase3=1.5; %3rd grouping
The Octave / Matlab code below solves for Y so I can plug it back into the equation to check values along with calculating values not located in the array.
clear all
t=0;
Y=0;
a1=[.2,3,1;1.4,2,1.7;.8,5,1.5]
for kk=1:1:length(a1)
Y=Y+a1(kk,1)*cos ((a1(kk,2))*t+a1(kk,3))
kk
end
Y
PS: I'm not trying to solve for Y since it's already solved for I'm trying to solve for Phase
The formulas located below are used to calculate Phase but I'm not sure how to put it into a for loop that will work in an array of n groupings:
How would I write the equation / for loop for finding the phase if I want to find freq=2.5 and amp=.23 and the phase is unknown I've looked online and it may require writing non linear equations which I'm not sure how to convert what I'm trying to do into such an equation.
phase1_test=acos(Y/amp1-amp3*cos(2*freq3*pi*t+phase3)/amp1-amp2*cos(2*freq2*pi*t+phase2)/amp1)-2*freq1*pi*t
phase2_test=acos(Y/amp2-amp3*cos(2*freq3*pi*t+phase3)/amp2-amp1*cos(2*freq1*pi*t+phase1)/amp2)-2*freq2*pi*t
phase3_test=acos(Y/amp3-amp2*cos(2*freq2*pi*t+phase2)/amp3-amp1*cos(2*freq1*pi*t+phase1)/amp3)-2*freq2*pi*t
Image of formula below:
I would like to do a check / calculate phases if given a freq and amp values.
I know I have to do a for loop but how do I convert the phase equation into a for loop so it will work on n groupings in an array and calculate different values not found in the array?
Basically I would be given an array of n groupings and freq=2.5 and amp=.23 and use the formula to calculate phase. Note: freq will not always be in the array hence why I'm trying to calculate the phase using a formula.
Ok, I think I finally understand your question:
you are trying to find a set of phase1, phase2,..., phaseN, such that equations like the ones you describe are satisfied
You know how to find y, and you supply values for freq and amp.
In Matlab, such a problem would be solved using, for example fsolve, but let's look at your problem step by step.
For simplicity, let me re-write your equations for phase1, phase2, and phase3. For example, your first equation, the one for phase1, would read
amp1*cos(phase1 + 2 freq1 pi t) + amp2*cos(2 freq2 pi t + phase2) + amp3*cos(2 freq3 pi t + phase3) - y = 0
Note that ampX (X is a placeholder for 1, 2, 3) are given, pi is a constant, t is given via Y (I think), freqX are given.
Hence, you are, in fact, dealing with a non-linear vector equation of the form
F(phase) = 0
where F is a multi-dimensional (vector) function taking a multi-dimensional (vector) input variable phase (comprised of phase1, phase2,..., phaseN). And you are looking for the set of phaseX, where all of the components of your vector function F are zero. N.B. F is a shorthand for your functions. Therefore, the first component of F, called f1, for example, is
f1 = amp1*cos(phase1+...) + amp2*cos(phase2+...) + amp3*cos(phase3+...) - y = 0.
Hence, f1 is a one-dimensional function of phase1, phase2, and phase3.
The technical term for what you are trying to do is find a zero of a non-linear vector function, or find a solution of a non-linear vector function. In Matlab, there are different approaches.
For a one-dimensional function, you can use fzero, which is explained at http://www.mathworks.com/help/matlab/ref/fzero.html?refresh=true
For a multi-dimensional (vector) function as yours, I would look into using fsolve, which is part of Matlab's optimization toolbox (which means I don't know how to do this in Octave). The function fsolve is explained at http://www.mathworks.com/help/optim/ug/fsolve.html
If you know an approximate solution for your phases, you may also look into iterative, local methods.
In particular, I would recommend you look into the Newton's Method, which allows you to find a solution to your system of equations F. Wikipedia has a good explanation of Newton's Method at https://en.wikipedia.org/wiki/Newton%27s_method . Newton iterations are very simple to implement and you should find a lot of resources online. You will have to compute the derivative of your function F with respect to each of your variables phaseX, which is very simple to compute since you're only dealing with cos() functions. For starters, have a look at the one-dimensional Newton iteration method in Matlab at http://www.math.colostate.edu/~gerhard/classes/331/lab/newton.html .
Finally, if you want to dig deeper, I found a textbook on this topic from the society for industrial and applied math: https://www.siam.org/books/textbooks/fr16_book.pdf .
As you can see, this is a very large field; Newton's method should be able to help you out, though.
Good luck!

MATLAB complicated integration

I have an integration function which does not have indefinite integral expression.
Specifically, the function is f(y)=h(y)+integral(#(x) exp(-x-1/x),0,y) where h(y) is a simple function.
Matlab numerically computes f(y) well, but I want to compute the following function.
g(w)=w*integral(1-f(y).^(1/w),0,inf) where w is a real number in [0,1].
The problem for computing g(w) is handling f(y).^(1/w) numerically.
How can I calculate g(w) with MATLAB? Is it impossible?
Expressions containing e^(-1/x) are generally difficult to compute near x = 0. Actually, I am surprised that Matlab computes f(y) well in the first place. I'd suggest trying to compute g(w)=w*integral(1-f(y).^(1/w),epsilon,inf) for epsilon greater than zero, then gradually decreasing epsilon toward 0 to check if you can get numerical convergence at all. Convergence is certainly not guaranteed!
You can calculate g(w) using the functions you have, but you need to add the (ArrayValued,true) name-value pair.
The option allows you to specify a vector-valued w and allows the nested integral call to receive a vector of y values, which is how integral naturally works.
f = #(y) h(y)+integral(#(x) exp(-x-1/x),0,y,'ArrayValued',true);
g = #(w) w .* integral(1-f(y).^(1./w),0,Inf,'ArrayValued',true);
At least, that works on my R2014b installation.
Note: While h(y) may be simple, if it's integral over the positive real line does not converge, g(w) will more than likely not converge (I don't think I need to qualify that, but I'll hedge my bets).

Find approximation of sine using least squares

I am doing a project where i find an approximation of the Sine function, using the Least Squares method. Also i can use 12 values of my own choice.Since i couldn't figure out how to solve it i thought of using Taylor's series for Sine and then solving it as a polynomial of order 5. Here is my code :
%% Find the sine of the 12 known values
x=[0,pi/8,pi/4,7*pi/2,3*pi/4,pi,4*pi/11,3*pi/2,2*pi,5*pi/4,3*pi/8,12*pi/20];
y=zeros(12,1);
for i=1:12
y=sin(x);
end
n=12;
j=5;
%% Find the sums to populate the matrix A and matrix B
s1=sum(x);s2=sum(x.^2);
s3=sum(x.^3);s4=sum(x.^4);
s5=sum(x.^5);s6=sum(x.^6);
s7=sum(x.^7);s8=sum(x.^8);
s9=sum(x.^9);s10=sum(x.^10);
sy=sum(y);
sxy=sum(x.*y);
sxy2=sum( (x.^2).*y);
sxy3=sum( (x.^3).*y);
sxy4=sum( (x.^4).*y);
sxy5=sum( (x.^5).*y);
A=[n,s1,s2,s3,s4,s5;s1,s2,s3,s4,s5,s6;s2,s3,s4,s5,s6,s7;
s3,s4,s5,s6,s7,s8;s4,s5,s6,s7,s8,s9;s5,s6,s7,s8,s9,s10];
B=[sy;sxy;sxy2;sxy3;sxy4;sxy5];
Then at matlab i get this result
>> a=A^-1*B
a =
-0.0248
1.2203
-0.2351
-0.1408
0.0364
-0.0021
However when i try to replace the values of a in the taylor series and solve f.e t=pi/2 i get wrong results
>> t=pi/2;
fun=t-t^3*a(4)+a(6)*t^5
fun =
2.0967
I am doing something wrong when i replace the values of a matrix in the Taylor series or is my initial thought flawed ?
Note: i can't use any built-in function
If you need a least-squares approximation, simply decide on a fixed interval that you want to approximate on and generate some x abscissae on that interval (possibly equally spaced abscissae using linspace - or non-uniformly spaced as you have in your example). Then evaluate your sine function at each point such that you have
y = sin(x)
Then simply use the polyfit function (documented here) to obtain least squares parameters
b = polyfit(x,y,n)
where n is the degree of the polynomial you want to approximate. You can then use polyval (documented here) to obtain the values of your approximation at other values of x.
EDIT: As you can't use polyfit you can generate the Vandermonde matrix for the least-squares approximation directly (the below assumes x is a row vector).
A = ones(length(x),1);
x = x';
for i=1:n
A = [A x.^i];
end
then simply obtain the least squares parameters using
b = A\y;
You can clearly optimise the clumsy Vandermonde generation loop above I have just written to illustrate the concept. For better numerical stability you would also be better to use a nice orthogonal polynomial system like Chebyshev polynomials of the first kind. If you are not even allowed to use the matrix divide \ function then you will need to code up your own implementation of a QR factorisation and solve the system that way (or some other numerically stable method).

Matrix dimension error while calling mldivide in MATLAB

I am getting this error while running my code:
Error using ==> mldivide Matrix dimensions must agree.
Here is my code :
%make the plots of phase and group velocity vs discreteness of the grid
c=1;
a=input('Please enter the ratio cdt/dx : ')
figure(1)
R=2:40;
plot(R,phase_vel(R,a)/c)
xlabel('R=l/dx')
ylabel('u_phase/c')
%figure(2)
%plot(group_vel(R,a),R,0,40)
%xlabel('R=l/dx')
%ylabel('u_group/c')
and here are my functions :
function phase_velocity = phase_vel(R,a)
%numerical phase velocity of the discrete wave
c=1;
phase_velocity=(2*pi*c)/(R*knum(R,a));
end
function group_velocity =group_vel(R,a )
%numerical group velocity of the discrete wave
c=1;
group_velocity=(a*sin(knum(R,a)))/(sin(2*pi*a/R))
end
function knumber = knum(R,a)
%This is the k wave number
knumber=acos((1/a)^2*(cos(2*pi*a/R)-1)+1);
end
How can I resolve this error?
EDIT: I used . operator in every equation and i changed the limits of R=4:40
If your goal is to apply your formulas to each individual value in the vector R then you should be performing all of your computations using the element-wise arithmetic operators .*, ./, and .^ instead of the matrix operators *, /, and ^.
Your error is probably occurring in the first call to your function knum, specifically when you try to compute 2*pi*a/R. Since 2*pi*a is a single scalar value, you get an error when trying to perform matrix right division / using the row vector R. The really weird thing is the error message:
??? Error using ==> mldivide
Matrix dimensions must agree.
which implies you are using the matrix left division operator \, which you clearly aren't. I tested this in MATLAB R2010b and I get the same incorrect function name appearing in my message. I think this may just be a typo in the error message, and I've dropped a note to the MATLAB folks to take a look at it and clear it up.
I don't have the Symbolic Math Toolbox, but your problem seems to be that you are using plot, a function which can deal with arrays of numbers, and feeding it the result of a symbolic calculation. Have a look at the Matlab Help, where the Topic Creating Plots of Symbolic Functions suggests using ezplot(). Alternatively you need to evaluate your symbolic expression for certain input values to create an array of numbers that plot can deal with - but you can't use double() for that since it wouldn't know what numbers to plug into your variables.