我有一个约束,其中两个连续变量相乘(价格和时间),作为线性化问题的方法,我想将价格转换为离散变量,然后执行一些线性化技术。然而,价格变量的值最多有 4 或 5 位小数。我想知道我应该如何做到这一点以及我应该如何在 cplex 中编码这个问题。
这个约束看起来像这样:
价格 * 时间 >= Ub
如果有人能帮助我解决这个问题,我将不胜感激。
附注我试图在 opl 中编写一个约束,让我得到这个连续变量的下限,但我没有成功。
我正在尝试使用这种技术:
价格 = 总和 (2^n-1) * p
首先在 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);
}