How to use fmincon on piecewise functions?(Find minimum of piecewise linear functions)
28 views (last 30 days)
Show older comments
The following code was intended to use fmincon to find minimum at given equality constraint: Two piecewise linear functions are involved, but I failed to define them into a singular function as a proper "fun" :
e.g. fun = @(x)100*(x(2)-x(1)^2)^2 + (1-x(1))^2;
Examples can be found here:https://www.mathworks.com/help/optim/ug/fmincon.html
Instead I involved two syms functions in "fun" definition, and it went wrong:
---------------------------------------------------------------------------------------------------------------------------------------------------
syms g(x) h(y)
g=piecewise(0<=x<100,11.2,100<=x<200,0.0192*x+9.28,200<=x<300,0.0112*x+10.88,x>300,0.0336*x+4.16)
h=piecewise(0<=y<150,15.75,150<=y<275,0.00336*y+15.246,275<=y<390,0.073043478*y+14.161304,y>390,0.014*y+11.15)
fun=@(x,y)g*x+h*y; %ERROR: Not enough input arguments
lb = [0,0];
ub = [500,500];
x0 = [300,200]; %starting point
A = [];
b = []; %no inequality conctraints
Aeq = [1,1];
beq = 500; %equality constriaint; P1+P2=workload
z = fmincon(fun,x0,A,b,Aeq,beq,lb,ub) %ERROR: Failure in initial objective function evaluation. FMINCON cannot continue.
----------------------------------------------------------------------------------------------------------------------------------------------------
As MATLAB compiler pointed out, there were likely grammar errors, but I can't find a way to fix. Replacing all [x,y] variable with [x(1), x(2)] then the syms functions fail to recoginze those as variables. Is there a way to define fun with those piecewise functions? Or another programming solver is required?
2 Comments
Bruno Luong
on 23 Oct 2020
Edited: Bruno Luong
on 23 Oct 2020
Numerical piecewise polynomial (including linear) functions can be defined with pp structure (see function ppval or spline).
If you have 1D function that is piecewise linear and continuous, the minimum is juts at thet knots or at the ends of interval definition. Just evaluate function at the knots.
(If not continuous then separate the left/right limits as values).
Then your 2D function x*f+y*g such that x+y=1 is just another 1D piecewise h = x*f + (1-x)*g, parametrized by x. You can compute the relation of values at the knots and x of h, depending on the sign of the first order coefficients. The the minimum can be derived (symbolically).
No need to use big hammer as FMINCON
Answers (1)
Walter Roberson
on 23 Oct 2020
Edited: Walter Roberson
on 23 Oct 2020
Your g was not defined for x == 300 exactly only for < 300 and > 300.
Also you only need a single variable.
You also cannot use piecewise on numeric values, only symbolic values, so you need to translate the piecewise() expression into code using matlabFunction. There is a catch to doing that, though: you have to tell it to write to a file, in which case the code generated is non-vectorized but takes care of the piecewise() using if/elseif. If you look carefully you might notice I also turned off optimization for matlabFunction: I did that because in recent releases, optimized code generated by matlabFunction is sometimes quite wrong.
You can get something that fmincon will produce some solution for.
However... using piecewise is fundamentally incompatible with fmincon. fmincon requires that the function be continuous over the variables, and that the first derivative also be continuous, but you really have to put some care into designing piecewise functions in order to get the derivative to be continuous.
Unless you are very careful, you should be using an optimizer that does not depend upon continuity, such as ga() or sa() [simulated annealing], or patternsearch().
syms g(x) h(y)
g = piecewise(0<=x<100,11.2,100<=x<200,0.0192*x+9.28,200<=x<300,0.0112*x+10.88,x>=300,0.0336*x+4.16)
h = piecewise(0<=y<150,15.75,150<=y<275,0.00336*y+15.246,275<=y<390,0.073043478*y+14.161304,y>390,0.014*y+11.15)
%fun = matlabFunction(fun_expr, 'vars', {[x, y]}, 'file', 'fun.m', 'optimize', false);
lb = [0,0];
ub = [500,500];
x0 = [300,200]; %starting point
A = [];
b = []; %no inequality conctraints
Aeq = [1,1];
beq = 500; %equality constriaint; P1+P2=workload
fun_expr = g*x + h*y;
Y = beq - Aeq(2)*x;
fun_1var = simplify(subs(fun_expr, y, Y))
fun = matlabFunction(fun_1var, 'Vars', x, 'file', 'fun.m', 'optimize', false);
z = fmincon(fun,x0(1),A,b,[],[],lb(1),ub(1))
See Also
Categories
Find more on Nonlinear Optimization in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!