cplexoplpiecewise

How to generic piecewise function in Cplex?


I would like to ask about how to make a piecewise function allows generic pieces as below: It works manually like this as if 2 steps:

piecewise{2->100; 3->200; 300->200; 2->300; 3->400; 300->400; 2->500; 3}(0,300) units

I would like to get the graph as below:

enter image description here

But I don't know how to generic it.

The graph would look as below: y1=2x+300; y2=3x+200

Thank you for the help!


Solution

  • See interpolate example

    // linearization of f(x)=1/x through a piecewise linear function
    // relying on https://github.com/AlexFleischerParis/howtowithopl/blob/master/pwlwithbreakpoints.mod
    
    // our world is not 100% linear so sometimes it's helpful to turn any non linear function
    // into a piecewise linear approximation 
    int sampleSize=10000;
    float s=1;
    float e=10;
    float x[i in 0..sampleSize]=s+(e-s)*i/sampleSize;
    int nbSegments=5;
    float x2[i in 0..nbSegments]=(s)+(e-s)*i/nbSegments;
    float y2[i in 0..nbSegments]=1/x2[i];  // y=f(x)
    float firstSlope=0;
     float lastSlope=0;
     
     tuple breakpoint // y=f(x)
     {
      key float x;
      float y;
     }
     
     sorted { breakpoint } breakpoints={<x2[i],y2[i]> | i in 0..nbSegments};
     
     float slopesBeforeBreakpoint[b in breakpoints]=
     (b.x==first(breakpoints).x)
     ?firstSlope
     :(b.y-prev(breakpoints,b).y)/(b.x-prev(breakpoints,b).x);
     
     pwlFunction f=piecewise(b in breakpoints)
     { slopesBeforeBreakpoint[b]->b.x; lastSlope } (first(breakpoints).x, first(breakpoints).y);
     
     assert forall(b in breakpoints) abs(f(b.x)-b.y)<=0.001;
     
     float maxError=max (i in 0..sampleSize) abs(1/x[i]-f(x[i]));
     float averageError=1/(sampleSize+1)*sum (i in 0..sampleSize) abs(1/x[i]-f(x[i]));
    

    enter image description here

    and with discontinuous piecewise you can write

    float slope1=(500-300)/100;
    float slope2=(800-500)/100;
    float slope3=5;
    float slope4=7;
    
    
    
    range r=1..4;
    
    float breakpoint[r]=[100,200,300,400];
    float slopes[r]=[slope1,slope2,slope3,slope4];
    
    float slope5=1;
    
    float step2=300;
    
    float steps[r]=[0,step2,0,0];
    
    pwlFunction f=piecewise{slope1->100; slope2->200;step2->200;slope3->300;slope4->400;slope5}(0,300);
    pwlFunction f2=piecewise(i in r,j in 1..2) { 
       ((j==1)?slopes[i]:steps[i]) -> breakpoint[i]; 
       slope5 
    }(0,300);
    
    
    assert f(0)==300;
    assert f(100)==500;
    assert f(200) ==1100;
    assert f(300)==1100+100*slope3;
    
    assert f2(0)==300;
    assert f2(100)==500;
    assert f2(200) ==1100;
    assert f2(300)==1100+100*slope3;