两个连续变量的乘法 - 如何在 CPLEX opl 中编码?

问题描述 投票:0回答:1

我有一个约束,其中两个连续变量相乘(价格和时间),作为线性化问题的方法,我想将价格转换为离散变量,然后执行一些线性化技术。然而,价格变量的值最多有 4 或 5 位小数。我想知道我应该如何做到这一点以及我应该如何在 cplex 中编码这个问题。

这个约束看起来像这样:

价格 * 时间 >= Ub

如果有人能帮助我解决这个问题,我将不胜感激。

附注我试图在 opl 中编写一个约束,让我得到这个连续变量的下限,但我没有成功。

我正在尝试使用这种技术:

价格 = 总和 (2^n-1) * p

variables optimization cplex linearization
1个回答
0
投票

首先在 OPL CPLEX 中,您可以使用一些二次约束:

参见示例 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);
}

您还可以对乘积进行线性化,如 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);
    }

如果您设法将浮点决策变量之一转换为离散决策变量,您可以简单地使用 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.