Aida Bitaraf
Aida Bitaraf

Reputation: 1

multiplication of two continuous variables - How to code in CPLEX opl?

I have a constraint in which two continuous variables are being multiplied (price and time) and as a method for linearizing my problem I want to convert price to a discete variable and then doing some linearizing techniques. However, the values of price variable has up to 4 or 5 decimals. I was wondering how I should do this and also how I should code this problem in the cplex.

this constraint looks like this:

price * time >= Ub

I would appreciate it if anyone could help me with this problem.

p.s. I was trying to write a constraint in opl to let me get the floor of this continuous variable but I wasn't successful.

I was trying to use this technique:

price = sum (2^n-1) * p

Upvotes: 0

Views: 104

Answers (1)

Alex Fleischer
Alex Fleischer

Reputation: 10059

First in OPL CPLEX you can use some quadratic constraints:

See example qcpex1.mod

range R = 0..2;
dvar float x[R] in 0..40;


maximize
  x[0] + 2 * x[1] + 3 * x[2]
  - 0.5 * ( 33 * x[0]^2 + 22 * x[1]^2 + 11 * x[2]^2 
          - 12 * x[0] * x[1] - 23 *x [1] * x[2] );

subject to {
  ct1:  - x[0] +     x[1] + x[2] <= 20;
  ct2:    x[0] - 3 * x[1] + x[2] <= 30;
  ct3:    x[0]^2 + x[1]^2 + x[2]^2 <= 1.0;
}

tuple xSolutionT{ 
    int R; 
    float value; 
};
{xSolutionT} xSolution = {<i0,x[i0]> | i0 in R};
execute{ 
    writeln(xSolution);
}

You can also linearize the product as can be seen at https://github.com/AlexFleischerParis/howtowithopl/blob/master/multiply2float.mod

    int sampleSize=10000;
    float s=0;
    float e=100;

    float x[i in 0..sampleSize]=s+(e-s)*i/sampleSize;

    int nbSegments=20;

    float x2[i in 0..nbSegments]=(s)+(e-s)*i/nbSegments;
    float y2[i in 0..nbSegments]=x2[i]*x2[i];

    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) f(b.x)==b.y;
     
     float maxError=max (i in 0..sampleSize) abs(x[i]*x[i]-f(x[i]));
     float averageError=1/(sampleSize+1)*sum (i in 0..sampleSize) abs(x[i]*x[i]-f(x[i]));
     
     execute
    {
    writeln("maxError = ",maxError);
    writeln("averageError = ",averageError);
    }

    dvar float a in 0..10;
    dvar float b in 0..10;
    dvar float squareaplusb;
    dvar float squareaminusb;

    maximize a+b;
    dvar float ab;
    subject to
    {
        ab<=10;
        ab==1/4*(squareaplusb-squareaminusb);
        
        squareaplusb==f(a+b);
        squareaminusb==f(a-b);
    }

if you manage to turn one of the float decision variables into a discrete decision variable you may simply use https://github.com/AlexFleischerParis/howtowithopl/blob/master/multiplyintegerdecisionvariablebydecisionvariable.mod

range r=1..100;
dvar int x in r;;
dvar int y in r;
dvar int xy;

subject to
{
xy==169;

forall(pos in r) (x==pos) => (xy==pos*y);
}

Upvotes: 0

Related Questions