MATLAB Curve Fitting with Slopes - matlab

Background
I am currently working on a lecture for my Engineering in MATLAB course and stumbled upon a problem I would like to present to the class. I have made many different attempts to solve this problem, but my graphs keep coming out incorrect. I will describe the problem below and all the steps I took to try to solve this problem.
Problem
Find the coefficients of the fourth-degree polynomial
P(x) = ax^4 + bx^3 + cx^2 + dx + e
whose graph goes through the points (0, 1), (1, 1), (-1,3), and
whose slopes at x = -1 is 20 and at x = 1 is 9.
Check your answer visually.
Attempt
I began by creating a matrix of the above x-values that I have derived as follows:
A = [0^4 0^3 0^2 0 1; 1^4 1^3 1^2 1 1; (-1)^4 (-1)^3 (-1)^2 -1 1];
A = [0 0 0 0 1; 1 1 1 1 1; 1 -1 1 -1 1];
This creates a 5 column by 3 row matrix that I may use to plot the polynomial.
My issue is that I am unable to get the last row of x-values, since each row is an equation in the system of equations and there must be as many equations as there are unknowns (4: a, b, c, and d are unknown, but e always equals 1 as you can see).
Ignoring this issue for a moment, I can continue to create a vertical matrix of y-values so that I may solve the system of equations. These y values are already given, so all I have to do is type this code in:
y = [1 1 3]';
Once again, there should be a fourth y-value to go along with the system of equations, but I have been unable to derive it using just the slopes of the points at x = -1 and x = 1.
Once both the x-values and the y-values are derived, we can proceed to using the backslash operator (/) to solve the system of linear equations A*x = y.
p = A\y;
mldivide is more info on the mldivide function for anyone who needs reference.
From here on out, the following code which creates a polynomial from this system of equations and graphs it, should stay the same.
u = -1:.01:1;
v = polyval(p, u);
plot(u,v);
In this code, u is the domain of x-values from -1 to 1 with a 0.01 interval. This is needed by us to use the polyval function, which creates a polynomial from a system of equations we derived at p on the interval u.
Lastly, plot simply graphs our derived polynomial using MATLAB's GUI on the interval u.
As you can see, the only missing pieces I have are one more row of x-values in my matrix A and one y-value in matrix y that I need to find the four unknowns a, b, c, and d. I believe you must use the two slopes given in the problem to find each point. I have tried using the polyder function to get the derivative of the matrix p by doing,
q = polyder(p);
but I am still confused as to how to continue from there. Any help will be greatly appreciated.

I would calculate the derivative of the polynomial:
dP(x) = 4ax^3 + 3bx^2 + 2cx + d
Now, you know that dP(-1)=20 and dP(1)=9 so you have 5 equations with 5 unknowns:
e = 1
a + b + c + d + e = 1
a - b + c - d + e = 3
-4*a + 3*b - 2*c + d = 20
4*a + 3*b + 2*c + d = 9
So you can construct a 5x5 matrix and solve the system, as you did with A\y.
The code to construct this 5x5 matrix is:
A = [0 0 0 0 1 ; 1 1 1 1 1 ; 1 -1 1 -1 1 ; -4 3 -2 1 0 ; 4 3 2 1 0];
y = [1 1 3 20 9]';
You can then check the results on a plot:
p=A\y;
u = -1:.01:1;
v = polyval(p, u);
data_pts = [0, 1; 1, 1;-1, 3]
plot(u,v,data_pts(:,1),data_pts(:,2),'rx')
which gives the following plot:
You can do the same with the derivative and checks it goes through the points (-1,20) and (1,9).

Related

How to zero out the centre k by k matrix in an input matrix with odd number of columns and rows

I am trying to solve this problem:
Write a function called cancel_middle that takes A, an n-by-m
matrix, as an input where both n and m are odd numbers and k, a positive
odd integer that is smaller than both m and n (the function does not have to
check the input). The function returns the input matrix with its center k-by-k
matrix zeroed out.
Check out the following run:
>> cancel_middle(ones(5),3)
ans =
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
My code works only when k=3. How can I generalize it for all odd values of k? Here's what I have so far:
function test(n,m,k)
A = ones(n,m);
B = zeros(k);
A((end+1)/2,(end+1)/2)=B((end+1)/2,(end+1)/2);
A(((end+1)/2)-1,((end+1)/2)-1)= B(1,1);
A(((end+1)/2)-1,((end+1)/2))= B(1,2);
A(((end+1)/2)-1,((end+1)/2)+1)= B(1,3);
A(((end+1)/2),((end+1)/2)-1)= B(2,1);
A(((end+1)/2),((end+1)/2)+1)= B(2,3);
A(((end+1)/2)+1,((end+1)/2)-1)= B(3,1);
A(((end+1)/2)+1,((end+1)/2))= B(3,2);
A((end+1)/2+1,(end+1)/2+1)=B(3,3)
end
You can simplify your code. Please have a look at
Matrix Indexing in MATLAB. "one or both of the row and column subscripts can be vectors", i.e. you can define a submatrix. Then you simply need to do the indexing correct: as you have odd numbers just subtract m-k and n-k and you have the number of elements left from your old matrix A. If you divide it by 2 you get the padding on the left/right, top/bottom. And another +1/-1 because of Matlab indexing.
% Generate test data
n = 13;
m = 11;
A = reshape( 1:m*n, n, m )
k = 3;
% Do the calculations
start_row = (n-k)/2 + 1
start_col = (m-k)/2 + 1
A( start_row:start_row+k-1, start_col:start_col+k-1 ) = zeros( k )
function b = cancel_middle(a,k)
[n,m] = size(a);
start_row = (n-k)/2 + 1;
start_column = (m-k)/2 + 1;
end_row = (n-k)/2 + k;
end_column = (m-k)/2 + k;
a(start_row:end_row,start_column:end_column) = 0;
b = a;
end
I have made a function in an m file called cancel_middle and it basically converts the central k by k matrix as a zero matrix with the same dimensions i.e. k by k.
the rest of the matrix remains the same. It is a general function and you'll need to give 2 inputs i.e the matrix you want to convert and the order of submatrix, which is k.

Gcd of polynomials modulo k

I want to ask Matlab to tell me, for example, the greatest common divisor of polynomials of x^4+x^3+2x+2 and x^3+x^2+x+1 over fields like Z_3[x] (where an answer is x+1) and Z_5[x] (where an answer is x^2-x+2).
Any ideas how I would implement this?
Here's a simple implementation. The polynomials are encoded as arrays of coefficients, starting from the lowest degree: so, x^4+x^3+2x+2 is [2 2 0 1 1]. The function takes two polynomials p, q and the modulus k (which should be prime for the algorithm to work property).
Examples:
gcdpolyff([2 2 0 1 1], [1 1 1 1], 3) returns [1 1] meaning 1+x.
gcdpolyff([2 2 0 1 1], [1 1 1 1], 5) returns [1 3 2] meaning 1+3x+2x^2; this disagrees with your answer but I hand-checked and it seems that yours is wrong.
The function first pads arrays to be of the same length. As long as they are not equal, is identifies the higher-degree polynomial and subtracts from it the lower-degree polynomial multiplied by an appropriate power of x. That's all.
function g = gcdpolyff(p, q, k)
p = [p, zeros(1, numel(q)-numel(p))];
q = [q, zeros(1, numel(p)-numel(q))];
while nnz(mod(p-q,k))>0
dp = find(p,1,'last');
dq = find(q,1,'last');
if (dp>=dq)
p(dp-dq+1:dp) = mod(p(1+dp-dq:dp) - q(1:dq), k);
else
q(dq-dp+1:dq) = mod(q(dq-dp+1:dq) - p(1:dp), k);
end
end
g = p(1:find(p,1,'last'));
end
The names of the variables dp and dq are slightly misleading: they are not degrees of p and q, but rather degrees + 1.

two ways of using symbolic solve in matlab

Why can Matlab solve the following system of equations that way:
eq1 = 'x1+x2+x4=1';
eq2 = 'x3+x4 = 2';
eq3 = '2*x1+3*x2+1*x3+4*x4=3';
eq4 = '3*x1+4*x2+2*x3+6*x4=p';
[p a b c d] = solve(eq1,eq2,eq3,eq4,p,x1,x2,x3,x4);
but not if I use the following code?
A = sym([1 1 0 1; 0 0 1 1; 2 3 1 4; 3 4 2 6]);
x = [x1 x2 x3 x4].';
b = sym([1 2 3 p].');
[p a b c d] = solve(A(1,:)*x==b(1),A(2,:)*x==b(2),A(3,:)*x==b(3),A(4,:)*x==b(4),p,x)
The first thing gives a value for p, and x1 to x4, while the second does not find any solution.
Thanks for an answer!
In R2012b neither of those work. One obtains warnings and, if anything, only parametrized solutions. You should check what you entered.
Why? First, rank(A) returns three, which means that you don't have four independent equations for your four-dimensional system. Second, even if you had four equations, you're trying to solve for five unknowns (p as well). You may need another constraint. Also note that the output of your calls to solve overwrites your symbolic variable p.
If you're trying to solve systems of symbolic equations, don't use solve, look into linsolve. Or, you can solve for p and a subset of x with your non-full rank system:
x = sym('x',[4 1]);
syms p;
A = sym([1 1 0 1; 0 0 1 1; 2 3 1 4; 3 4 2 6]);
b = sym([1 2 3 p].');
[p_ x1 x2 x3] = solve(A*x==b,p,x(1),x(2),x(3)) % results will be function of x4

How can i plot the sum of two discrete signal?

I have a discrete signal
x = [ 1 2 3 4 5 6 ]
with
n = [ -2 -1 0 1 2 3 ]
How can i plot y[n] = x[n-1] + x[n-2] + x[n] ?
Thanks.
You can do the following:
y = x(1:end-2) + x(2:end-1) + x(3:end);
plot(n(3:end), y)
This looks like a filter... You should consider using the filter function to calculate y:
x = [...whatever...];
% Filter coefficients from your difference equation.
b = [1 1 1];
a = 1;
y = filter(b, a, x);
plot(n, y);
This will handle initial conditions more appropriately than naive approaches, so you will get a 6-element vector out with your given input (although note that your data is liable to be partly garbage for the first three samples).

Matlab - Not getting the expected result

I have written a function that is supposed to do the following:
Take as an input two sets
Take the distance between the two sets using pdist2 which code is shown here.
It will take the distance between the two sets at the beginning. Then, for the second set, at each iteration, it will set the (i,j) location to 0 and calculate the distance with this change. An, when it goes to the next iteration, it should change the next location value to '0' while at the same time return the preceding value which was set to '0' to its original value.
Note that the result from pdist2 originally return as a matrix, but for the comparison, I sum up the matrix values to use them for comparison.
Based on that, I have written the following function (note that you can use the pdist2.m function from the link here):
function m = pixel_minimize_distance(x,y)
sum1=0;
sum2=0;
[r c] = size(y);
d1 = pdist2(x,y);
[r1 c1] = size(d1);
for i=1:r1
for j=1:c1
sum1=sum1+d1(i,j);
end
end
maximum = sum1;
for i=1:r
for j=1:c
o = y(i,j)
y(i,j) = 0;
d2 = pdist2(x,y);
[r2 c2] = size(d2);
for i=1:r2
for j=1:c2
sum2=sum2+d2(i,j);
end
end
if sum2 >= maximum
if o ~= 0
maximum = sum2;
m = o;
end
end
if sum2 <= maximum
maximum = maximum;
end
y(i,j)=o;
end
end
end
Now, this is what I have run as a test:
>> A=[1 2 3; 6 5 4];
>> B=[4 5 3; 7 8 1];
>> pixel_minimize_distance(A,B)
o =
4
o =
4
o =
1
o =
7
o =
7
o =
0
ans =
7
See the the answer here is 7 (scroll down if you cannot see it), while the expected value when I calculate this manually should be 3, as since when we set it to 0 the sum of the distance will be 142.
Any idea what could be wrong in the code? I think it would be in the location in the code of setting o = y(i,j) where o denotes original value, but really couldn't figure a way of solving that.
Thanks.
I think you have many redundant commands in your code. I just removed them, nothing else. I am getting value of m as 3. I used MATLAB's pdist2 function with squared euclidean distance (since that is the default in the function you provided). I did not get 142 as the distance.
Here is the code:
function m = pixel_minimize_distance(x,y)
[r c] = size(y);
maximum = (sum(sum(pdist2(x,y)))).^2; %explained below
for i=1:r
for j=1:c
o = y(i,j);
y(i,j) = 0
sum2 = (sum(sum(pdist2(x,y)))).^2;
if sum2 >= maximum
if o ~= 0
maximum = sum2;
m = o;
end
end
y(i,j)=o;
end
end
end
and output is:
y =
0 5 3
7 8 1
y =
4 0 3
7 8 1
y =
4 5 0
7 8 1
y =
4 5 3
0 8 1
y =
4 5 3
7 0 1
y =
4 5 3
7 8 0
m =
3
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Explanation:
You have written the following snippet of code:
d2 = pdist2(x,y);
[r2 c2] = size(d2);
for i=1:r2
for j=1:c2
sum2=sum2+d2(i,j);
end
end
what this simply does is calculates the distance between two sets using pdist2 and sums up the entire distance matrix to come up with one value stored in sum2 in your case.
Lets look at the my code:
sum2 = (sum(sum(pdist2(x,y)))).^2;
pdist2 will give the distance. First sum command will sum along the rows and then the second one will sum along the columns to give you a total of all values in the matrix (This is what you did with two for loops). Now, the reason behind .^2 is:
In the original pdist2 function in the link which you have provided, you can see from the following snippet of code:
if( nargin<3 || isempty(metric) ); metric=0; end;
switch metric
case {0,'sqeuclidean'}
that squared Euclidean is the default distance, whereas in MATLAB, Euclidean distance is default. Therefore, I have squared the term.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%