I am working with MATLAB_R2016a, and am currently trying to find the right matrix fraction description of a MIMO system. Suppose I have a matrix of the form:
[s^2+3s+1, s+1, s^3+2s; s^3+3, s^2-6, s-5];
Is there a simple way to generate submatrixes of coefficients for each degree of s? Like so:
[0, 0, 1; 1, 0, 0] s^3 + [0, 0, 0 ; 0, 1, 0] s^2 + [3, 1, 2; 0, 0, 1] s + [1,1,0;3,-6,-5];
I figure it can be done with a loop and extracting the degree of each polynomial element, but wanted to know if people had found easier work-arounds?
I suppose you use symbolic toolbox to work on polynomials. So, as #10a commented you can use coeffs function.
You just need to made some workaround to get final result.
For arbitrary polynomials you can use the next code:
syms x
% find all coefficients for each polynomial. Results are of different sizes!
% because of different degrees of polinomils
coef = arrayfun( #(y) coeffs(y, 'All') , [2*x^2 + 3*x + 5, x^2+3; x^3, x + 7] ,...
'UniformOutput' , false)
% find max degree
max_size = cellfun( #(x) size(x,2), coef)
max_size = max(max_size(:))
% and finally fill with zeros all surplus places in arrays to get unified size
result = cellfun( #(x) [zeros(1, max_size - size(x,2)) x], coef, 'UniformOutput', false)
Related
The polyfit function expects a scalar value for the polynomial degree n, e.g.
P = polyfit(X, Y, 3)
which suggests a for loop should be used to determine a range of polynomials (say degree 2 to degree 4) fitting the same curve:
% Fit a given curve with a series of polynomials
% of given degrees
X = 1:6; % Range of x in the sample
Y0 = [10, 11, 21, 2, 3, 7]; % Sample
DEG = 2:6; % Degrees to use for polynomials
plot(X, Y0) % Plot sample for reference
for n = DEG
hold on
P = polyfit(X, Y0, n); % Fitting polynomial, degree n
Y = polyval(P, X); % Compute y for this polynomial
plot(X, Y)
endfor
Is there a way to simplify this code and turn it into 'all array' by using the range DEG directly in the function? I tried several variation around polyfit(X, Y0, DEG), but Octave keeps telling me:
error: polyfit: N must be a non-negative integer
Any help appreciated.
This is what arrayfun is for:
octave:1> X = 1:6;
octave:2> Y0 = [10, 11, 21, 2, 3, 7];
octave:3> DEG = 2:6;
octave:4> arrayfun (#(n) polyfit (X, Y0, n), DEG, "UniformOutput", false)
ans =
{
[1,1] =
-0.37500 0.96786 11.30000
[1,2] =
1.0833 -11.7500 35.3095 -16.0000
[1,3] =
0.43750 -5.04167 17.43750 -18.94048 15.50000
[1,4] =
-1.2750 22.7500 -150.9583 456.2500 -612.7667 296.0000
[1,5] =
-0.31438 5.32693 -32.26604 80.10905 -54.29889 -58.20494 69.64828
}
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
I need to calculate the integral of a function on some discrete data points in Matlab. I have the absolute coordinate of each point:
x=[1,2.65,3.25,3.33,15.65]
y=[10,31,15,-6,1]
I was trying to use trapz(x,y) function but there x must be the spacing between data points, not the x coordinate of data points.
What is the easiest way to calculate such an integration?
With integral you can specify way points as option in 1D. With integral2 for 2D integration, it seems you cannot.
It also seems you have a 2D rectangular grid of integration points?
In that case just calculate weights according to the mean interval lengths (via diff) and then sum up. Since your integration grid is fixed, the precision of the numerical integration will anyway not be controllable and will depend on the function you'll integrate.
% get grid
x = [1, 3, 7, 15]';
y = [3, 6, 8];
[xi, yi] = ndgrid(x, y);
% get weights
h = diff(x, [], 1);
wx = ([h; 1] + [1; h]) / 2;
h = diff(y, [], 2);
wy = ([h, 1] + [1, h]) / 2;
w = wx * wy;
% calculate function
f = func(xi, yi);
% integration is weighted summation
int = sum(f(:) .* w(:));
Borders will have to be treated carefully. Also, your list of coordinates needs to be sorted.
I am interested to plot the L0-norm penalty function in matlab.
In fact, I know that the L0-norm of a vector x, ||x||_0, returns a value which designates the total number of nonzero elements in x. In other terms, ||x||_0 = #(i | xi !=0).
For example, for the L1-norm of x, it returns the sum of the absolute values of the elements in x. The matlab code to plot the L_1 norm penalty function is:
clear all;
clc;
x = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
penal = zeros (length(x),1);
lambda = 2; % the tuning parameter
for ii = 1 : length(x)
penal(ii) = lambda*abs(x(ii));
end
figure
plot(x(:), penal(:), 'r');
But now what about the L_0 norm??
Any help will be very appreciated!
Replace the line inside the for loop with the following:
penal(ii) = lambda*(x(ii) ~= 0);
This assigns a penalty of lambda for all non-zero values in the vector x.
I want to use Gurobi solver in Matlab, but I don't know how to calculate the required matrices (qrow and qcol).
For your reference I am copying the example provided in documentation.
0.5 x^2 - xy + y^2 - 2x - 6y
subject to
x + y <= 2
-x + 2y <= 2, 2x + y <= 3, x >= 0, y >= 0
c = [-2 -6]; % objective linear term
objtype = 1; % minimization
A = sparse([1 1; -1 2; 2 1]); % constraint coefficients
b = [2; 2; 3]; % constraint right-hand side
lb = []; % [ ] means 0 lower bound
ub = []; % [ ] means inf upper bound
contypes = '$<<
vtypes = [ ]; % [ ] means all variables are continuous
QP.qrow = int32([0 0 1]); % indices of x, x, y as in (0.5 x^2 - xy + y^2); use int64 if sizeof(int) is 8 for you system
QP.qcol = int32([0 1 1]); % indices of x, y, y as in (0.5 x^2 - xy + y^2); use int64 if sizeof(int) is 8 for you system
QP.qval = [0.5 -1 1]; % coefficients of (0.5 x^2 - xy + y^2)
Does it mean that if I have 4 decision variables than i should use 0,1,2,3 as indices for my decision variables x_1, x_2, x_3, x_4.?
Thanks
Note: I tried to use mathurl.com but I don't get how to write in proper format show that it will appear as latex text. Sorry for the notation.
This seems to be your reference. However your question seems to relate different example. You may need to show that one.
Anyway according Gurobi documentation:
The quadratic terms in the objective function should be specified by opts.QP.qrow, opts.QP.qcol, and opts.QP.qval, which correspond to the input arguments qrow, qcol, and qval of function GRBaddqpterms. They are all 1D arrays. The first two arguments, qrow and qcol, specify the row and column indices (starting from 0) of 2nd-order terms such as and . The third argument, qval, gives their coefficients.
So the answer is yes use indicies [0 1 2 3] for your decision variables x0, x1, x2, x3.