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).
Related
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
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).
I know that MATLAB works better when most or everything is vectorized. I have two set of vectors X and T. For every vector x in X I want to compute:
this is because I want to compute:
which can be easily expressed as MATLAB linear algebra operations as I wrote above with a dot product. I am hoping that I can speed this up by having those vectors, instead of computing each f(x) with a for loop. Ideally I could have it all vectorized and compute:
I've been think about this for some time now, but it doesn't seem to be a a nice way were a function takes two vectors and computes the norm between each one of them, with out me having to explicitly write the for loop.
i.e. I've implemented the trivial code:
function [ f ] = f_start( x, c, t )
% Computes f^*(x) = sum_i c_i exp( - || x_i - t_i ||^2)
% Inputs:
% x = data point (D x 1)
% c = weights (K x 1)
% t = centers (D x K)
% Outputs:
% f = f^*(x) = sum_k c_k exp( - || x - t_k ||^2)
[~, K] = size(t);
f = 0;
for k=1:K
c_k = c(k);
t_k = t(:, k);
norm_squared = norm(x - t_k, 2)^2;
f = f + c_k * exp( -1 * norm_squared );
end
end
but I was hoping there was a less naive way to do this!
I think you want pdist2 (Statistics Toolbox):
X = [1 2 3;
4 5 6];
T = [1 2 3;
1 2 4;
7 8 9];
result = pdist2(X,T);
gives
result =
0 1.0000 10.3923
5.1962 4.6904 5.1962
Equivalently, if you don't have that toolbox, use bsxfun as follows:
result = squeeze(sqrt(sum(bsxfun(#minus, X, permute(T, [3 2 1])).^2, 2)));
Another method just for kicks
X = [1 2 3;
4 5 6].';
T = [1 2 3;
1 2 4;
7 8 9].';
tT = repmat(T,[1,size(X,2)]);
tX = reshape(repmat(X,[size(T,2),1]),size(tT));
res=reshape(sqrt(sum((tT-tX).^2)).',[size(T,2),size(X,2)]).'
Consider a difference equation with its initial conditions.
5y(n) + y(n-1) - 3y(n-2) = (1/5^n) u(n), n>=0
y(n-1) = 2, y(n-2) = 0
How can I determine y(n) in Matlab?
Use an approach similar to this (using filter), but specifying initial conditions as done here (using filtic).
I'm assuming your initial conditions are: y(-1)=2, y(-2)=0.
num = 1; %// numerator of transfer function (from difference equation)
den = [5 1 -3]; %// denominator of transfer function (from difference equation)
n = 0:100; %// choose as desired
x = (1/5).^n; %// n is >= 0, so u(n) is 1
y = filter(num, den, x, filtic(num, den, [2 0], [0 0]));
%// [2 0] reflects initial conditions on y, and [0 0] those on x.
Here's a plot of the result, obtained with stem(n,y).
The second line of your code does not give initial conditions, because it refers to the index variable n. Since Matlab only allows positive integer indices, I'll assume that you mean y(1) = 0 and y(2) = 2.
You can get an iteration rule out of your first equation by simple algebra:
y(n) = ( (1/5^n) u(n) - y(n-1) + 3y(n-2) ) / 5
Code to apply this rule in Matlab:
n_max = 100;
y = nan(n_max, 1);
y(1) = 0;
y(2) = 2;
for n = 3 : n_max
y(n) = ( (1/5^n) * u(n) - y(n-1) + 3 * y(n-2) ) / 5;
end
This code assumes that the array u is already defined. n_max specifies how many elements of y to compute.
f1 = 1 ;
N = 1024 ;
fs = 200 ;
ts = 1/fs ;
t = -(N/(2*fs)):ts:(N/(2*fs)) ;
theta=rand(0:2*pi);
X = sin(2*pi*f1*t+theta) ;
plot(t,x)
grid
Error using +
Matrix dimensions must agree.
And how can i calculate the autocorrelation of x function Rxx(n) ?
Replace the theta line by
theta = 2*pi*rand; %// generates a random number between 0 and 2*pi
and the plot line by
plot(t, X); %// capital "X", as you have defined previously
For the autocorrelation, you can use conv (correlation for real signals is equivalent to convolution with a time-reversal):
c = conv(X,fliplr(X));
plot(-(N/fs):ts:(N/fs), c)
To add to what Luis Mendo has answered, the reason for the error message is that:
>> size(t)
ans =
1 1025
>> size(theta)
ans =
0 1 2 3 4 5 6
So you are trying to add two things which are not the same dimension in X = sin(2*pi*f1*t+theta), hence the error message.
Use Luis's suggestions to fix your code.