trouble with fmincon in MATLAB - matlab

I'm trying to use fmincon in MATLAB and not quite sure what the heck the problem is. My function is:
function f = myfun(x4)
f = (C * x4 - d) .^ 2;
end
and I call it like this:
lb = zeros(3, 1);
x0 = [10; 10; 10];
[x4, fvalx4, exitflagx4, outputx4, lambdax4] = fmincon(#myfun,x0,[],[],[],[],lb,[]);
but when I run it I get
??? Error using ==> mtimes
Inner matrix dimensions must agree.
However, I checked and C is 112x3, and d is 112x1, and x4 is not initialized at all because that's what I'm trying to solve for. If I create a "dummy" x4 I can run
(C * x4 - d) .^ 2
without a problem.
Any thoughts? I realize this is the same as using lsqr or rather lsqlin with a lb of 0, which is also equivalent to lsqnonneg, but that's the point: I'm trying to verify results from those methods in different ways.

There are several issues here.
First, you need to learn how to pass in those parameters that are not optimized. The function myfun cannot see C and d, as functions have their own workspaces, unless they are nested functions.
Next, since you are computing a linear least squares subject to constraints, you need to return a sum of squares. fmincon needs a scalar objective. It does not understand what to do when you return a vector.
Personally, I would not even bother defining an explicit m-file. Define this using a function handle. So perhaps you might try this objective:
myfun = #(x4) norm(C*x4 - d);
lb = zeros(3, 1);
x0 = [10; 10; 10];
[x4, fvalx4, exitflagx4, outputx4, lambdax4] = fmincon(myfun,x0,[],[],[],[],lb,[]);
The function handle can see the value of C and d, so once the handle is created, those variables are carried along inside the function handle workspace.
Notice that I used norm to compute the sum of squares, in fact, here a sqrt of a sum of squares. But where the sum of squares is minimized, then so is the sqrt of that number. Its a bit cleaner looking with norm.
Another option is to use a version of myfun that explicitly passes in the value of C and d. Here I've given myfun arguments, then essentially created a function handle wrapper around myfun. You could have done that with an m-file version of myfun too.
myfun = #(x4,C,d) norm(C*x4 - d);
lb = zeros(3, 1);
x0 = [10; 10; 10];
[x4, fvalx4, exitflagx4, outputx4, lambdax4] = fmincon(#(x4) myfun(x4,C,d),x0,[],[],[],[],lb,[]);

The function that you pass to fmincon should return a scalar value. In your function it returns a 112-by-1 vector. Maybe you need to change
f = (C * x4 - d) .^ 2;
to
f = sum((C * x4 - d) .^ 2);

Related

Integral piecewise function matlab

I am trying to integrate a function F which is defined as:
function F
x = -3:0.1:3;
F = zeros(1, length(x));
for i = 1:length(x)
if (1.4<= x(i)) && (x(i) <= 1.6)
F(i) = x(i).^2;
else
F(i) = 2;
end
end
end
but the integral function gives me an error saying that there are too many arguments. I think the problem that the function is defined as a points?
The problem with your function, is that integral has no way to pass the arguments you supply to your function F. The function doesn't know that it can just pull certain elements from the vector you created. If you rewrite your function such that for an input (or x value), the output of F is returned, then integral will work as you need given two values to integrate between.

differentiate a function in matlab

how can I differentiate a function in matlab? I tried with:
syms x;
f = 3x^2 + 2;
A = diff(f);
disp(A);
My problem is now I want to give x a value after (for example A(x = 1) and I don't know how.
First, there's an error in your code, you can't imply multiplication, you need to write 3*x^2 rather than 3x^2.
Also, in case you feed the function a vector rather than scalar, you should use element-wise operations (including a . before powers, multiplication etc.) so this becomes 3*x.^2.
Other than that, 2 options:
syms x;
f = 3*x.^2 + 2;
1) define A like you did and use subs to substitute x for, say, 1.
A = diff(f);
subs(A,x,1);
2) define A as an anonymous function and call it more easily.
A = #(y) subs(diff(f),x,y)
Now A can be easily called with different values
A(1)
ans = 6
A(2)
ans = 12
Links to documentation on element-wise ops, subs and anonymous functions:
https://uk.mathworks.com/help/matlab/matlab_prog/array-vs-matrix-operations.html
https://uk.mathworks.com/help/symbolic/subs.html
https://uk.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html
Modify your code like this:
syms x;
f = 3*x^2 + 2; % You missed a * here
A(x) = diff(f); % This creates a symfun
A(1) % This gives the value of A at x=1
You need the matlabfunction function.
matlabFunction Generate a MATLAB file or anonymous function from a sym

Errors when using the Integral2 function in MATLAB

As far as I can tell, no one has asked this.
I've been asked to compute the double integral of a function, and also the same double integral but with the order of integration swapped (i.e: first integrate for dydx, then dxdy). Here is my code:
%Define function to be integrated
f = #(x,y) y^2*cos(x);
%First case. Integration order: dydx
ymin = #(x) cos(x);
I = integral2(f,ymin,1,0,2*pi)
%Second case. Integration order: dxdy
xmin = #(y) asin(y)+2*pi/2;
xmax = #(y) asin(y)-pi/2;
B = integral2(f,xmin,xmax,-1,1)
The error I'm getting is this:
Error using integral2 (line 71)
XMIN must be a floating point scalar.
Error in EngMathsA1Q1c (line 5)
I = integral2(f,ymin,1,0,2*pi)
I'm sure my mistake is something simple, but I've never used Integral2 before and I'm lost for answers. Thank you.
Per the integral2 documentation, the variable limits are given as the second pair of limits. So your first integral should be
% Define function to be integrated
f = #(x,y) y.^2.*cos(x);
% First case. Integration order: dydx
ymin = #(x) cos(x);
I = integral2(f,0,2*pi,ymin,1);
The set of constant limits always goes first, and Matlab assumes the first argument of f is associated with the first set of limits while the second argument of f is associated with the second set of limits, which may be a function of the first argument.
I point out that second part because if you wish to switch the order of integration, you also need to switch the order of the inputs of f accordingly. Consider the following example:
fun = #(x,y) 1./( sqrt(2*x + y) .* (1 + 2*x + y).^2 )
A nice little function that is not symmetric in its arguments (i.e., fun(x,y) ~= fun(y,x)). Let's integrate this over an elongated triangle in the first quadrant with vertices at (0,0), (2,0), and (0,1). Then integrating with dA == dy dx, we have
>> format('long');
>> ymax = #(x) 1 - x/2;
>> q = integral2(fun,0,2,0,ymax)
q =
0.220241017339352
Cool. Now let's integrate with dA == dx dy:
>> xmax = #(y) 2*(1-y);
>> q = integral2(fun,0,1,0,xmax)
q =
0.241956050772765
Oops, that's not equal to the first calculation! That's because fun is defined with x as the first argument and y as the second, but the previous call to integral2 is implying that y is the first argument to fun, and it has constant limits of 0 and 1. How do we fix this? Simply define a new function that flips the arguments:
>> fun2 = #(y,x) fun(x,y);
>> q = integral2(fun2,0,1,0,xmax)
q =
0.220241017706984
And all's right with the world. (Although you may notice small differences between the two correct answers due to the error tolerances of integral2, which can be adjusted via options per the documentation.)
The error states that you can't pass in a function for the limits of integration. You need to specify a scalar value for each limit of integration. Also, there are some errors in the dimensions/operations of the function. Try this:
%Define function to be integrated
f = #(x,y) y.^2.*cos(x);%changed to .^ and .*
%First case. Integration order: dydx
%ymin = #(x) cos(x);
I = integral2(f,-1,1,0,2*pi)%use scalar values for limits of integration
%Second case. Integration order: dxdy
%xmin = #(y) asin(y)+2*pi/2;
%xmax = #(y) asin(y)-pi/2;
B = integral2(f,0,2*pi,-1,1)% same issue, must use scalars

Get coefficients of symbolic polynomial in Matlab

I have a Matlab function that returns a polynomial of the form:
poly = ax^2 + bx*y + cy^2
where a, b, and c are constants, and x and y are symbolic (class sym).
I want to get the coefficients of the polynomial in the form [a b c], but I'm running into the following problem. If the function returns poly = y^2, then coeffs(poly) = 1. I don't want this – I want it to return [0 0 1].
How can I create a function that will give me the coefficients of a symbolic polynomial in the form that I want?
You can use sym2poly if your polynomial is a function of a single variable like your example y^2:
syms y
p = 2*y^2+3*y+4;
c = sym2poly(p)
which returns
c =
2 3 4
Use fliplr(c) if you really want the coefficients in the other order. If you're going to be working with polynomials it would probably also be a good idea not to create a variable called poly, which is the name of a function you might want to use.
If you actually need to handle polynomials in multiple variables, you can use MuPAD functions from within Matlab. Here is how you can use MuPAD's coeff to get the coefficients in terms of the order of variable they precede (x or y):
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
c = eval(feval(symengine,'coeff',p,v))
If you want to extract all of the information from the polynomial, the poly2list function is quite helpful:
syms x y
p = 2*x^2+3*x*y+4*y;
v = symvar(p);
m = eval(feval(symengine,'poly2list',p,v));
c = m(:,1); % Coefficients
degs = m(:,2:end); % Degree of each variable in each term
The polynomial can then be reconstructed via:
sum(c.*prod(repmat(v,[size(m,1) 1]).^degs,2))
By the way, good choice on where you go to school. :-)
There is also an alternative to this problem. For a given degree, this function returns a polynomial of that degree and its coefficients altogether.
function [polynomial, coefficeint] = makePoly(degree)
syms x y
previous = 0 ;
for i=0:degree
current = expand((x+y)^i);
previous= current + previous ;
end
[~,poly] = coeffs(previous);
for j= 1:length(poly)
coefficeint(j) = sym(strcat('a', int2str(j)) );
end
polynomial = fliplr(coefficeint)* poly.' ;
end
Hope this helps.

Numerically integrate in Matlab without requiring vector input

The following is a generalisation of my problem
function E = FunctionIntegration(S)
I = #(f) log(det(4 * S(f)));
E = integral(I, -pi, pi)
S is a function handle that takes scalar input f and returns a matrix. When I try and run this function I get a Inner matrix dimensions must agree error.
I understand that integral requires the function I to take vector input and that's where the problem lies but in this case I don't see a way of accommodating that as I must then pass this vector to function S which returns a matrix. Is there a way around this?
Note an example of S could be:
S = #(f) [f 0; 0 1]
Obviously in this case the integral is easy to do analytically but the function S can be any scalar to matrix transformation.
Your problem is that integral passes an array of values to I. But your I only expects a scalar. Try this:
function E = functionIntegration(S)
I = #(x) arrayfun(#(f) log(det(4 * S(f))), x);
E = integral(I, -pi, pi);
end
I've wrapped your integrand into a call to arrayfun which will loop over the array passed in by integral and calculates the integrand for each entry:
>> S = #(x) x * eye(3, 3);
>> functionIntegration(S)
ans =
28.8591 + 9.8696i