Matlab: Test the system is linear or not - matlab

I have an equation: y(n) = a^x(n).
where x1(n) ={0,1,2,3}, x2(n)={1,2,3,4}, a1=a2=1, a=2.
So, How can i write MATLAB code to test the system is linear or not?

Just apply the definition.
Consider a system S, such that the output to an input signal x(n) is S( x(n) ). S is linear if and only if
S( x1(n) + x2(n) ) = S( x1(n) ) + S( x2(n) ) for any inputs x1, x2 (additivity)
S( b * x1(n) ) = b * S( x1(n) ) for any input x1 and any number b (homogeneity)
In your case it's clear that neither 1 nor 2 hold, so the system y(n) = S( x(n) ) is not linear.
To test it with code: randomly generate many examples of x1, x2 and b and check if the equalities above hold. Note that this way you will never be sure that the system is linear. You can only be sure it isn't, namely when you find x1, x2, b for which either 1 or 2 do not hold.
Example
>> a = 2; n = 3;
>> S = #(x) a*x.^n; %// anonymous function describing your system
>> x1 = 1:4; %// test input signal
>> x2 = 11:14; %// test input signal. Same length
>> S(x1)+S(x2)
ans =
2664 3472 4448 5616
>> S(x1+x2)
ans =
3456 5488 8192 11664
Since the results are different, the system does not satisfy property 1, and therefore it's not linear.

Related

Matrix equation solving in Matlab

Motivation:
I have to iteratively determine transfer functions of a system depending on its parameters. From the block diagram, I know the matrix equations and now have to combine and solve them to obtain the transfer function. The system is not given in any common form, so I can't just apply standard functions as for example ss2f.
Problem:
To test my equation solving script, I started with a problem I know the solution to:
The transfer function G of this system can be directly calculated as follows with s as the Laplace variable:
Now I want to obtain the same solution with the following script that I wrote. Don't worry about the weird numbers of A and B, the system was determined via model linearization. It definitely has a valid transfer function though, as above formula has a valid result. However, the last line of the script gives me:
ans =
struct with fields:
g1: [0×1 sym]
g3: [0×1 sym]
g2: [0×1 sym]
g4: [0×1 sym]
Below is my code. Hope you can help me with that. Thanks in advance!
System matrix: 4x4
A = [-0.868119260443192,38.6220008060345,-3.41464245222828,0;-0.977364157120952,-0.710033524230589,0.0269276394855778,0.576935314629657;4.02838694184468,-15.0624095995407,-31.0586647741313,0;0.0225429037937697,0,1,-3.32771392487994e-30];
% Input Matrix 4x2
B = [-7.66837152645279,-21.1508491865230;-0.0466721502330690,0.198650074689473;-112.758863363750,-2.59747270711686;0,0];
% Output matrix 2x4
C = [0 0 1 0; 0 1 0 0];
% Transfer function
syms g1 g2 g3 g4;
G = [g1 g2; g3 g4];
% System vector and derivative
syms x1 x2 x3 x4 xp1 xp2 xp3 xp4;
x = [x1;x2;x3;x4];
xp = [xp1;xp2;xp3;xp4];
% Input u and output y
syms u1 u2;
u = [u1;u2];
syms y1 y2;
y = [y1;y2];
% System equations
eqn1 = xp == A * x + B * u;
eqn2 = y == C * x;
% Transfer function equation
eqn3 = y == G * u;
% xp is derivative of x
syms s;
eqn4 = s .* x == xp;
solve(eqn1, eqn2, eqn3, eqn4, G)

MATLAB Lsim initial value for RC filter doesnt work

I would simulate an RC (low-pass) filter that has some initial value.
R = 1e3; % 1kOm
C = 100e-6; % 100uF
es = tf('s');
LP1 = 1 / (R*C*es + 1);
Ts = 0.1; % 100ms
sysd = c2d(LP1, Ts);
Initial value means that capacitor is charged to some voltage (lets say 5V) and we apply some voltage to the input (lets say 10V). I would see output voltage / time plot:
x0 = 5; % 5V
input = 10; % 10V
N = 100;
lsim(sysd, ones(1, N)*input, [], x0);
Plot that is showed starts with zero (no initial condition). If i convert tf to ss:
lsim(ss(sysd), ones(1, N)*input, [], x0);
Than plot starts from non zero value but it is NOT 5V that I set as initial value.
What is wrong with it, How to simulate it?
The x0 input to lsim() is only used to define the initial conditions of a state-space system.
In the first example, sysd is a transfer function, so x0 has no effect and a zero initial condition is used.
In the second example, ss(sysd) is a state-space model, so x0 specifies the initial state and not the output as you intended. To understand what is going on, let's take a look at your state-space model:
>> ss(sysd)
ans =
A =
x1
x1 0.3679
B =
u1
x1 1
C =
x1
y1 0.6321
D =
u1
y1 0
Sample time: 0.1 seconds
Discrete-time state-space model.
Per the state-space output equation y = Cx + Du , the initial output is equal to C*x0 = 0.6321*5 = 3.16 which matches the result in your plot. Instead, you should set x0 = y0 / ss(sysd).C where y0 is the desired initial output. For y0 = 5, this means setting x0 = 7.91.

How to fit data with piecewise linear function in matlab with some constraints on slope

I am trying to fit a piecewise linear equation for my (xdata, ydata) data. I have to challenges, the first one is how to convert the equation in the form of the function handle and the second one is how to put a constraint on the slope, for instance, a2>a1 and a2>0 and a1>0.
xdata = 5:0.2:40;
ydata = max(18,xdata) + 0.5*randn(size(xdata));
a1 = (y1-y0)/(x1-x0); a2 = (y2-y1)/(x2-x1);
if x < x1;
f(x) = y0 + a1*(x-x0);
else
f(x) = y0 + a1*(x1-x0) + a2*(x-x1);
end
FU = matlabFunction(f)
x0 = 5; y0 = 16;
x = lsqcurvefit(FU,[x0,y0],xdata,ydata)
The key to creating the piece-wise function is to replace the if condition by a vectorized >. By calling y = x > 1 on some array x, the output y will be an array of the same size as x, with a logical True if the corresponding element in x is larger than 1, and a False otherwise. For example
>> x = [1, 2, 4; 3, 1, 2];
>> y = x > 2
y =
2×3 logical array
0 0 1
1 0 0
You can utilize this to create a piece-wise linear function, as follows:
>> fun = #(theta, xdata) theta(1) + ...
(xdata<=theta(2)) .* theta(3) .* xdata + ...
(xdata>theta(2)) .* (theta(3) * theta(2) + ...
theta(4) .* (xdata-theta(2)))
The parameter vector theta will be 4-dimensional: the first element is a constant offset from zero, the second element is the corner point, and the third and fourth elements are the two slopes.
By multiplying theta(3).*xdata with the result of xdata<=theta(2), you get theta(3).*xdata for each point in xdata which is smaller than theta(2), and 0 for all others.
Then, calling lsqcurvefit is as simple as
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata)
theta =
18.3793
17.9639
-0.0230
0.9943
The lsqcurvefit function also allows you to specify a lower bound lb and an upper bound ub for the variables you want to estimate. For variables where you don't want to specify a bound, you can use e.g. inf as bound. To make sure that your a1 and a2, i.e. theta(3) and theta(4) are positive, we can specify the lower bound to be [-inf, -inf, 0, 0].
However, the lsqcurvefit function doesn't allow you to add the constraint a2 > a1 (or any linear inequality constraints). In the example data, this constraint probably isn't even necessary as this is obvious from the data. Otherwise, a possible solution would be to replace a2 by a1 + da, and use a lower bound of 0 for da. This makes sure that a2 >= a1.
>> fun = #(theta, xdata) theta(1) + ...
(xdata<=theta(2)) .* theta(3) .* xdata + ...
(xdata>theta(2)) .* (theta(3) * theta(2) + ...
(theta(3)+theta(4)) .* (xdata-theta(2)))
>> theta = lsqcurvefit(fun, [0; 15; 0; 1], xdata, ydata, [-Inf, -Inf, 0, 0], [])
theta =
18.1162
18.1159
0.0000
0.9944

Using MATLAB to write a function that implements Newton's method in two dimensions

I am trying to write a function that implements Newton's method in two dimensions and whilst I have done this, I have to now adjust my script so that the input parameters of my function must be f(x) in a column vector, the Jacobian matrix of f(x), the initial guess x0 and the tolerance where the function f(x) and its Jacobian matrix are in separate .m files.
As an example of a script I wrote that implements Newton's method, I have:
n=0; %initialize iteration counter
eps=1; %initialize error
x=[1;1]; %set starting value
%Computation loop
while eps>1e-10&n<100
g=[x(1)^2+x(2)^3-1;x(1)^4-x(2)^4+x(1)*x(2)]; %g(x)
eps=abs(g(1))+abs(g(2)); %error
Jg=[2*x(1),3*x(2)^2;4*x(1)^3+x(2),-4*x(2)^3+x(1)]; %Jacobian
y=x-Jg\g; %iterate
x=y; %update x
n=n+1; %counter+1
end
n,x,eps %display end values
So with this script, I had implemented the function and the Jacobian matrix into the actual script and I am struggling to work out how I can actually create a script with the input parameters required.
Thanks!
If you don't mind, I'd like to restructure your code so that it is more dynamic and more user friendly to read.
Let's start with some preliminaries. If you want to make your script truly dynamic, then I would recommend that you use the Symbolic Math Toolbox. This way, you can use MATLAB to tackle derivatives of functions for you. You first need to use the syms command, followed by any variable you want. This tells MATLAB that you are now going to treat this variable as "symbolic" (i.e. not a constant). Let's start with some basics:
syms x;
y = 2*x^2 + 6*x + 3;
dy = diff(y); % Derivative with respect to x. Should give 4*x + 6;
out = subs(y, 3); % The subs command will substitute all x's in y with the value 3
% This should give 2*(3^2) + 6*3 + 3 = 39
Because this is 2D, we're going to need 2D functions... so let's define x and y as variables. The way you call the subs command will be slightly different:
syms x, y; % Two variables now
z = 2*x*y^2 + 6*y + x;
dzx = diff(z, 'x'); % Differentiate with respect to x - Should give 2*y^2 + 1
dzy = diff(z, 'y'); % Differentiate with respect to y - Should give 4*x*y + 6
out = subs(z, {x, y}, [2, 3]); % For z, with variables x,y, substitute x = 2, y = 3
% Should give 56
One more thing... we can place equations into vectors or matrices and use subs to simultaneously substitute all values of x and y into each equation.
syms x, y;
z1 = 3*x + 6*y + 3;
z2 = 3*y + 4*y + 4;
f = [z1; z2];
out = subs(f, {x,y}, [2, 3]); % Produces a 2 x 1 vector with [27; 25]
We can do the same thing for matrices, but for brevity I won't show you how to do that. I will defer to the code and you can see it then.
Now that we have that established, let's tackle your code one piece at a time to truly make this dynamic. Your function requires the initial guess x0, the function f(x) as a column vector, the Jacobian matrix as a 2 x 2 matrix and the tolerance tol.
Before you run your script, you will need to generate your parameters:
syms x y; % Make x,y symbolic
f1 = x^2 + y^3 - 1; % Make your two equations (from your example)
f2 = x^4 - y^4 + x*y;
f = [f1; f2]; % f(x) vector
% Jacobian matrix
J = [diff(f1, 'x') diff(f1, 'y'); diff(f2, 'x') diff(f2, 'y')];
% Initial vector
x0 = [1; 1];
% Tolerance:
tol = 1e-10;
Now, make your script into a function:
% To run in MATLAB, do:
% [n, xout, tol] = Jacobian2D(f, J, x0, tol);
% disp('n = '); disp(n); disp('x = '); disp(xout); disp('tol = '); disp(tol);
function [n, xout, tol] = Jacobian2D(f, J, x0, tol)
% Just to be sure...
syms x, y;
% Initialize error
ep = 1; % Note: eps is a reserved keyword in MATLAB
% Initialize counter
n = 0;
% For the beginning of the loop
% Must transpose into a row vector as this is required by subs
xout = x0';
% Computation loop
while ep > tol && n < 100
g = subs(f, {x,y}, xout); %g(x)
ep = abs(g(1)) + abs(g(2)); %error
Jg = subs(J, {x,y}, xout); %Jacobian
yout = xout - Jg\g; %iterate
xout = yout; %update x
n = n + 1; %counter+1
end
% Transpose and convert back to number representation
xout = double(xout');
I should probably tell you that when you're doing computation using the Symbolic Math Toolbox, the data type of the numbers as you're calculating them are a sym object. You probably want to convert these back into real numbers and so you can use double to cast them back. However, if you leave them in the sym format, it displays your numbers as neat fractions if that's what you're looking for. Cast to double if you want the decimal point representation.
Now when you run this function, it should give you what you're looking for. I have not tested this code, but I'm pretty sure this will work.
Happy to answer any more questions you may have. Hope this helps.
Cheers!

Symbolic Expression Differentiation using Symbolic Vector

I am trying to differentiate the following symbolic expression using a created symbolic vector but I keep getting errors. That is, I would like df/dx1, df/dx2, and df/dx3. Here is what I have tried:
>> x = sym('x', [3 1])
x =
x1
x2
x3
>> symbolic = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x
symbolic =
x1^2/2 + x1 + x2^2/2 + x2 + x3^2/2 + x3
>> diff(symbolic, x)
Error using mupadmex
Error in MuPAD command: Invalid argument. [contains]
Evaluating: (Dom::Matrix(Dom::ExpressionField()))::_mult1
Error in sym/diff (line 44)
R = mupadmex('symobj::diff', S.s, x.s, int2str(n));
>> diff(symbolic, x.x1)
Error using sym/subsref
Too many output arguments.
Any assistance would be greatly appreciated. Thanks!
You can try one of these two options:
% option 1
x = sym('x', [3 1]);
f = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x;
for i=1:3
Df(1,i) = diff(f, x(i));
end
% I do not like this option because I do not know
% how to evaluate the expressions with numeric values
x(1) = 1;
eval(Df)
I prefer the 'option 2', because it is easier to evaluate expressions.
% option 2
syms x1 x2 x3 real; % 'real' fixes x1 x2 x3 as real numbers (not complex ones)
x = [x1 x2 x3]'; % '
f = 0.5*transpose(x)*eye(1)*x + [1 1 1]*x;
for i=1:3
eval(['Df(1,i) = diff(f,x',num2str(i),');']);
end
% To eval at a certain value
x1 = 1;
x2 = 2;
x3 = 3;
eval(Df)
I think that eval has only the two functions I used above:
To eval symbolic expressions to specific values of the symbolic variables, like when I wrote eval(Df).
You can use eval to evaluate a matlab command written as a string, as if you were writing it as normal code. Try this to see what I mean:
a = 1; % set value of a to 1
eval('a = 2'); % change value of a to 2
eval(['a = ',num2str(5)]); % set value of a to 5;
Hope this helps,