Decision Optimization

Decision Optimization

Delivers prescriptive analytics capabilities and decision intelligence to improve decision-making.


#Analytics
#DecisionOptimization
#DecisionOptimization
 View Only
  • 1.  Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/06/14 02:16 PM

    Originally posted by: TRLC


    Hello CPLEX forum! 

    I have often found help in old posts here, but not this time. 

    I am writing a program in C++ that uses the function IloPiecewiseLinear, but are having troubles. My program compiles and runs, but the optimal solution returned seems to be incorrect. I am verifying the optimal solution by no less than two other models (one without using IloPiecewiseLinear and a homemade Branch-Cut-and-Price), so I think the problem is in my usage of the function IloPiecewiseLinear.

    Therefore, I would like some help on understanding how the IloPiecewiseLinear function works.

    What I want to model is a left-continuous, non-decreasing, piecewise linear function used in a transportation problem (see the attached file PiecewiseLinearFigure.pdf). As the use is in a transporation problem I will only be considering x-values that are non-negative (x>=0). Maybe not so clear from the figure I want f(0) = 0. Also, note that the function is undefined for x>8 (or infinite in this case). 

    From the CPLEX documentation there are two ways of passing such a function and I have chosen to define the function by its (x,f(x)) values at the break points (jumps). 

    What I have done is to define an array with breakpoints and an array with the function values at the break points, with the first break point at zero, like so 

     

    breakpoints[0] =  0.0;
    functionvals[0] = 0.0; //f(0) = 0
                 breakpoints[1] =  0.0; 
                 functionvals[1] = 5;  //Just an arbitrary example

    I then continue to add more segments like

    breakpoints[2] =  10;
    functionvals[2] = 10;
                 
                 breakpoints[3] =  10;
                 functionvals[3] = 14;
     
    And when the last segment with a finite cost has been defined I would add a "dummy" segment with high cost 
         
                 breakpoints[4] =  15;
                 functionvals[4] = 26;
         
                 breakpoints[5] =  15;
                 functionvals[5] = 100000000; //Sufficiently high costs

    In the end I would then called something like 

    model.add(costvar[i][j] == IloPiecewiseLinear(flowvar[i][j], 0.0, //slope of the preceding the first breakpoint (which is the segment from -infty to 0)
                                                    breakpoints,
                                                    functionvals,
                                                    1000.0   //Slope of the last segment (which is the undefined part so the slope is sufficiently high)
                                                   ));

    Hence, the example shown here consists of two "real" segments, (0,10] and (10,15]. 

    Some random thoughts on why my costs are incorrect

    1. CPLEX probably assumes that the function is right-continuous, such that f(0)=5. I couldn't find it in the manual (and yes, the problem is a minimization problem).
    2. If 1) is true, then it should be possible to shift the breakpoints by adding some \epsilon >0. However, this yields some weird behavior by CPLEX, e.g. \epsilon = 0.01 yields z^* = 100, \epsilon = 0.001 yields z^* = 80, \epsilon = 0.0001 yields z^* = 120. I would think it should converges, but maybe this leads to numerical troubles instead.
    3. In optimal solution I get several edges with a positive flow equal to some break point, but the cost contribution is 0. The error could possibly be related to to me in some way creating isolated points on the function (which is not supported by CPLEX)? However, I do not receive any errors.     
    4. If it is of any use, then there always exists an optimal solution which is integer. This yields the possibility of other ways of formulation the problem, but that another story/paper (which has already been done).

    I hope this makes sense. At least I tried to make the problem understandable, but it is somewhat technical. 

     

    Thanks in advance!


    #CPLEXOptimizers
    #DecisionOptimization


  • 2.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/10/14 10:10 AM

    Just to be sure: did you read piecewise linear functions in the user manual? In particular the subsections about discontinuous functions and isolated points? Isolated points are not supported. They are ignored (a warning should be issued but no error will occur). If a function is discontinuous and has a step at breakpoint p with value l on the left and r on the right, then both points (p,l) and (p,r) are admissable. If I understand your description correctly then you don't want (p,r) to be admissable. To get that you will have to use some sort of epsilon.

    Using (very) small epsilon values may introduce numerical problems but whether your results for z^* are related to this really depends on your problem data. It could also be that different values for epsilon just result in different optimal solutions. I don't see why in general z^* should converge for epsilon=1e-3, 1e-4, 1e-5 in the way you expect. It will eventually converge for (very) small values of epsilon but maybe they are much smaller than 1e-5?


    #CPLEXOptimizers
    #DecisionOptimization


  • 3.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/16/14 06:02 AM

    Originally posted by: TRLC


    Thanks for your input!

    I did read the manual. Several times to try and figure out what exactly CPLEX does in the case of discontinuous piecewise linear functions, but there there are some questions unanswered by the manual. In particular it states that two values can be defined for the same argument, say f(2)= 2 and f(2) = 3 which indicates that x=2 is a jump point in the funciton. It does not state which value will be used by CPLEX, or if this is dependt on if we are minimising or maximising. 

     

    Also, I should not be generating isolated points and I am not getting any warnings. 

     

    I also think the small epsilon causes numerical troubles. In my case I am shifting the function to the right, so the optimal values should, theoretically, increase when going from a higher value of epsilon to a smaller one. Because of the numerical instability I don't think this approach would work anyhow. 

     

    Please keep the input coming!


    #CPLEXOptimizers
    #DecisionOptimization


  • 4.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/16/14 04:34 PM

    At a jump discontinuity, I think you will find f() taking whichever value results in a better objective value. So it does depend on the direction of the objective, but you may not be able to infer right-closure v. left-closure on a particular segment just from the objective direction (unless the model is quite simple).

    Paul

     


    #CPLEXOptimizers
    #DecisionOptimization


  • 5.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/18/14 06:40 AM

    Originally posted by: TRLC


    Hi Paul!

     

    I thought I would find that too, but the objective value seems to be much higher, which leads to be believe that f(0) = first-jump-intercept-with-yaxis. I will recheck the code for errors again, but I feel rather confident that it is correct. 

    It is really frustrating that the manual does not give a straight answer to this part, as it is rather important. Also, I would like to use this function at the request from a referee, but I don't think it is an efficient representation for most uses at it is based on SOS (at least that is my understanding). 

     

    PS: Good up the exceptional good work on your blog Paul. It is a joy to follow. 

     

    Cheers,

     

    Tue


    #CPLEXOptimizers
    #DecisionOptimization


  • 6.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/18/14 10:38 AM

    Tue,

    I'm not sure what more the manual could say. Most mathematical programming methods (including LP) require a continuous objective function on a closed, convex feasible region. When you introduce piecewise linear functions, whether in the objective or the constraints, you implicitly decompose the feasible region into subsets on which the PWL functions reduce to linear functions. You need each of those subsets to be closed, which means that the solver (whether it is CPLEX or something else) needs to treat the corresponding segment of each PWL function as closed at both ends (both left- and right-continuous). Thus, at breakpoints, either value will be considered legitimate, and the solver will take whichever one produces the superior solution (whether that solution satisfies the intent of the PWL function or not). None of this is specific to CPLEX.

    Are you saying that you think CPLEX, in picking the value of f(0), made a suboptimal choice? That would be quite unlikely.

    I'm not sure whether CPLEX handles this by modifying the branching algorithm, by introducing an SOS2 for each PWL function, or by implicitly introducing binary variables to dictate which segment applies. My understanding for If-then constraints, which may be faulty, is that CPLEX uses some internal logic to choose between modified branching or introducing a "big M" representation using binary variables. It's possible that CPLEX may make a similar choice among modified branching, SOS2 and binary variables (possibly an SOS1?) for each PWL constraint. If so, the precise logic behind the choice is probably a trade secret.

    As to the referee, are you saying that the referee wanted a PWL function where you prefer not to use one, or that the referee specifically said to use IloPiecewiseLinear where you prefer to use an explicit representation of the PWL function? I'm just curious; the answer really does not matter since, like the rest of us, you are at the mercy of the referee. :-) You might try it both ways (your way and the referee's). If your way is better, you can present the results in the cover letter of your next submission, as justification for not taking the referee's advice. I've done that in the past, with some success.

    Paul

    PS: Thanks for the kind words about the blog.


    #CPLEXOptimizers
    #DecisionOptimization


  • 7.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/24/14 03:03 AM

    Originally posted by: TRLC


    Hi Paul. 

    I am not sure what else the manual could say either, but what it does say is, appearently, not enough for me to figure out how it works. Seeing myself as the average CPLEX user one could argue that something, at least, is missing or not explained enough. On the other hand I am using the academic license, so I should not complain (too much). 

    Just to recap. Everything seems to work, except the objective function value is way off.

    The output tells me a lot of SOS-constraints are generated, which is not the case when using formulations that does not involve IloPiecewiseLinear, so I guess the function converts it into SOS2. It would then make sense that the solution time is much worse than the other formulations I have tried, since this has already been observed by others. Of course since the reported optimal solution is wrong compared to what the other formulations report it cannot be completely disregarded. It would appear that CPLEX does a suboptimal choice with respect to the objective function value, but I would need to test some more before being (I am very short on time, as always). 

    In the end I will figure something out and present that with the referee. His/her point is valid, but should I get the IloPiecewiseLinear to fully work then I am certain it would still prove ineffecient. 

    Thanks for your effort!


    #CPLEXOptimizers
    #DecisionOptimization


  • 8.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/24/14 11:02 AM

    Hi,

    What I meant about the manual was that there is no way the authors can be specific about which endpoint you'll get at a jump discontinuity, other than to say it will be whatever yields the better overall result.

    When you say the objective function is way off, is it (a) correct given the values obtained for the variables and (b) better than the true optimum? That would be consistent with the jump discontinuity problem. A negative answer to either would imply either a bug in CPLEX or a formulation error on your part.

    If you are getting a superoptimal solution, have you tried introducing small gaps in the PWL functions at jump points (Daniel's epsilon)? The epsilon offset essentially means that at a jump discontinuity x = p, you rule out either x between p-epsilon and p or x between p and p + epsilon. Since you know the optimum from your other formulation, you should be able to find a safe epsilon (meaning that you can be sure the optimal solution won't fall into whichever gap you create). That fudge will at least let you evaluate the use of the PWL functions (and hopefully pacify the AE, if not the reviewer).

    Paul


    #CPLEXOptimizers
    #DecisionOptimization


  • 9.  Re: Modeling a discontinuous piecewise linear function with CPLEX (version 12.x, C++)

    Posted 01/27/14 08:45 AM

    Originally posted by: TRLC


    HI Paul,

     

    I will have to recheck the part regarding the solution. 

    Adding an epsilon yielded a very different solution, and what seems like numerical troubles for CPLEX. I also think that this could be the solution, but maybe I have to be more careful when selecting my epsilon. 

    In the absence of anything better I have accepted your solution, since it gives me something to work on. 

    I will reply back when I had time to further test the code.

    Best regards


    #CPLEXOptimizers
    #DecisionOptimization