How to use fmincon on piecewise functions?(Find minimum of piecewise linear functions)

28 views (last 30 days)
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;
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
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
Yu Chen
Yu Chen on 23 Oct 2020
Both piecewise functions are continous, and supposedly by splitting x & y ranges into cases will yield several minimums at knots, and/or convex minimums that is easily identifiable once x*g+y*h is specified at given range (fixed g & h). Will be kinda messy for larger x+y values, but certainly viable since there were only 4 segements for each piecewise function. Good point.

Sign in to comment.

Answers (1)

Walter Roberson
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)
g = 
56512x625+232257x625+2722521x625+10425 if  x[0,100) if  x[100,200) if  x[200,300) if  300x
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)
h = 
63421y6250+7623500328958580302645y4503599627370496+79721054271850395629499534213127y500+22320 if  y[0,150) if  y[150,275) if  y[275,390) if  390<y
%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_1var = 
7x2500279x20+9075259642308217599077x2281474976710656000068543363120727951x879609302220800+713300417402508787528147497671065683x225001587x100+907591x262503863x500+8463237124310080746597x2281474976710656000067135988237174671x879609302220800+713300417402508787528147497671065621x26251159x100+7875231x262507223x500+8463 if  x[0,100) if  x(110,200) if  x[100,110) if  x(225,300) if  x[200,225] if  x(350,500] if  x[300,350]
fun = matlabFunction(fun_1var, 'Vars', x, 'file', 'fun.m', 'optimize', false);
z = fmincon(fun,x0(1),A,b,[],[],lb(1),ub(1))
Local minimum found that satisfies the constraints. Optimization completed because the objective function is non-decreasing in feasible directions, to within the value of the optimality tolerance, and constraints are satisfied to within the value of the constraint tolerance.
z = 265.3159
  1 Comment
Yu Chen
Yu Chen on 23 Oct 2020
Ouch that was careless of me.
As you said, this could only work when the first deroavotave is continuous, which isn't easy to come by. I will look into the optimizers you mentioned earilier. Thanks for the help :)

Sign in to comment.

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!