How to pass a symbolic equation to constraints when using fmincon - matlab

I have the following problem: When using fmincon I need to supply it with constraints. The constrain .M file looks like this:
function [c,ceq]=podmienky_L(qL)
global podmL zL
c=[podmL+0.0001-zL]
ceq=[];
zL is a constant while podmL is a symbolic variable that contains this expression:
(22.1*cos(qL(4))(sin(qL(3))(0.35*sin(qL(1))
When I try to run fmincon I get an error: User function returned a complex value when evaluated;
But when I replace the variable podmL with (22.1*cos(qL(4))(sin(qL(3))(0.35*sin(qL(1)) everything works fine.
The equation in podmL is supplied by another script and can wary from use to use and can attain hideous proportions, so it is very impractical for me to simply hardwrite it into the constraints function. Does anybody have any ideas?
Thanks

Related

Excel solver function equivalent in Matlab

I am looking optimisation method in Matlab, where I can apply constraints on a parameter which is a function of another constrained parameter.
The error function to minimise is:
errfun = Ltrue - Lref(x1,x2) - Lemm(x1,x2,x3)
The optimisation parameters are x1,x2,x3 with their respective lower and upper bounds. Ltrue, Lref, Lemm are vectors of size 8. Ltrue is the vector containging the constant "true" values which are already defined. I am currently using the Matlab function "lsqnonlin".
However, the problem is that I also require a constraint on the value of Lemm(8).
In excel solver, this is easy to do since I can just add a specific constraint to the cell containing Lemm(8). I can't find any equivalent in any of the Matlab optimsation functions though. Is there any function I am not aware of which can do this, or some workaround to make use of existing Matlab functions?

Using fzero to solve eqn in MatLab

I hope this is the right area. I'm trying to get this code to work in MatLab.
function y=test(x)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
I then jump to the command value and type this:
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
I then try to find the zeros of the first equation by typing this and I get errors:
solution=fzero(#test,5000000)
I'm getting the following error:
Error: File: test.m Line: 5 Column: 1 This statement is not
inside any function. (It follows the END that terminates the
definition of the function "test".)
New error
Error using fzero (line 289)
FZERO cannot continue because user supplied function_handle ==> #(x)
(test(x,B,b,a,r,p))
failed with the error below.
Subscript indices must either be real positive integers or logicals.
I would guess that this is a problem of scoping, you are defining variables (B, b, etc...) in the command line but trying to use them inside your test function where they are out of scope. You should alter your test function to take these in as parameters and then use an anonymous function so that your call to test in fsolve still only takes a single parameter:
function y=test(x, B, b, r, a, p)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
and
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
solution=fzero(#(x)(test(x,B,b,a,r,p)),5000000)
As an aside, unless you really do mean matrix multiplication, I would suggest that you replace all your *s and /s in test with the element-wise operators .* and ./. If you are dealing with scalars, it doesn't matter now, but it makes a big difference if you later want to scale your project and need a vectorized solution.
Regarding the errors you have added to your question:
You can't put code after the end in your function file. (With the exception of local functions). Your objective function should be an .m-file containing the code for one single function.
This is because in your test function you have ...b((1-(b/x)^(B-1))... which in MATLAB means you are trying to index the variable b in which case the value of (1-(b/x)^(B-1) has to be a positive integer. I'm guess you are missing a *
Your
function y=test(x)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
cannot access variables in your workspace. You need to pass the values in somehow. You could do something like:
function y=test(x,B,b,a,r,p)
y=-x+(B/(B-1))*(r-a)*p+(B/(B-1))*(r-a)*(b((1-(b/x)^(B-1))/r- a)+p* ((b/x)^B))/(1-(b/x)^B);
end
and then you can create an implicit wrapper function:
B=3.0515;
b=1.18632*10^5;
a=.017;
r=.054;
p=5931617;
solution = fzero(#(x) test(x,B,b,a,r,p),5000000)
I haven't tested whether fzero returns sensible results, but this code shouldn't give an error.

Error regarding inlineeval in MATLAB

As part of a group project we have a system of 2 non linear differential equations and we have to draw the S=S(t) , I=I(t) graphic using the midpoint method.
And I'm getting the following error when trying to insert the matrix with the corresponding differential equations:
"Error in inline expression ==> matrix([[-(IS)/1000], [(IS)/1000 - (3*I)/10]])
Undefined function 'matrix' for input arguments of type 'double'.
Error in inline/subsref (line 23)
INLINE_OUT_ = inlineeval(INLINE_INPUTS_, INLINE_OBJ_.inputExpr, INLINE_OBJ_.expr);"
The code I have done is the following:
syms I S
u=[S;I];
F=[-0.001*S*I;0.001*S*I-0.3*I];
F1=inline(char(F),'I','S');
h=100; %Valores aleatórios
T=100000;
ni=(T/h);
u0=[799;1];
f=zeros(1,2);
k=zeros(1,2);
i=1;
while i<=ni
f(1)=F1(u0(1));
f(2)=F1(u0(2));
dx=h*f;
k(1)=F1((u0(1)+h*(1/2)),(u0(2)+h*(1/2)));
k(2)=F1((u0(1)+h*(1/2)),(u0(2)+h*(1/2)));
u1=u0+h*k;
disp('i:'),disp(i)
disp('u= '),disp(u1)
u0=u1;
i=i+1;
end
I'm new to this so the algorithm it's very likely to be wrong but if someone could help me with that error I'd apreciate it. Thank you!
The problem that specifically creates the error is that you are putting two symbolic functions into a matrix and then calling char (which outputs matrix([[-(IS)/1000], [(IS)/1000 - (3*I)/10]]) rather than converting nicely to string).
The secondary problem is that you are trying to pass two functions simultaneously to inline. inline creates a single function from a string (and using anonymous functions instead of inline is preferred anyway). You cannot put multiple functions in it.
You don't need sym here. In fact, avoid it (more trouble than it's worth) if you don't need to manipulate the equations at all. A common method is to create a cell array:
F{1} = #(I,S) -0.001*S*I;
F{2} = #(I,S) 0.001*S*I-0.3*I;
You can then pass in I and S as so:
F{1}(500,500)
Note that both your functions include both I and S, so they are always necessary. Reconsider what you were expecting when passing only one variable like this: f(1)=F1(u0(1));, because that will also give an error.

How to define a variable without assign any value to it

vo is the upper limit of an integration expression and this is the variable that I want to predefine as a variable without value since it is the variable I am trying to solve for.
Everything else is defined.
%//a object's velocity is changing as a function of sine, the full cycle is 0=>speed=>0
vt=-((speed/2)*cos((2*pi/t0)*t)-(speed/2)))
%//integrate vt function so I can get distance which has given
distance=int(vt,t,0,t0)
%//the last step is I need to find how long does it takes the object to finish a full cycle of movement
time=solve(eqn,t0)
Try using the syms command in MATLAB. The syms is part of the symbolic math toolbox and you can predefine "variables" without explicitly solving for them. They form a part of the mathematics expression that you want.
Once you formulate the equation you want, you can use solve (as you have already used in your post) to solve the variable for you.

In Matlab, how to solve an equation originating in a function?

How do I easiest solve an equation=0 with a function as a parameter?
My function with one input variable is called potd(angle), with one output variable, potNRGderiv. I tried:
syms x
solve(potd(x))
This gave me error: Undefined function 'sind' for input arguments of type 'sym'.
Have you got any ideas? Thanks in advance.
solve is the wrong avenue here, unless your function can be rewritten as a simple equation. solve uses muPAD functions which is why you can do solve(sin(x)) but not solve(sind(x)). You can, of course, just do the conversion yourself.
If your function is more complicated or you'd rather not rewrite it, look into fsolve:
x = fsolve(#myfun,x0)
Where x0 is your initial guess - i.e. myfun(x0) is close to 0 - and myfun is a function which takes x and returns a single output. Depending on what your function does, you may have to adjust the options using optimoptions (tolerance, step size, etc) to get a good result.