简而言之,我们现在正在尝试将IQP更改为ILP。旧的实现花了大约2天才完成,现在使用线性工具 - 它应该加速。基本上问题是最大化(大约50个二进制变量):
$$ \ sum_ {g = 1} ^ {5} sum_ {p = 1} ^ {10}(S [p] x [g] [p] -Tiredness [g] [p] -Sleepness [g ] [p])$$
更新
我认为大卫走在正确的轨道上但是当我尝试用奖励变量来最大化表达时,它们每次都为零,为什么?在某些代码下方,分数可能类似于S[1..10]=[1,2,3,4,5,6,7,8,9,10];
。
int S[1..10] = ...; // Scores per player =s
dvar int x1[1..10] in 0..1;
dvar int x2[1..10] in 0..1;
dvar int x3[1..10] in 0..1;
dvar int x4[1..10] in 0..1;
dvar int x5[1..10] in 0..1;
dvar int b1[1..10] in 0..100;
dvar int b2[1..10] in 0..100;
//ERR: the values of b1 and b2 should be maximized...
// WHY not here so?
maximize
sum(i in 1..10)
(
S[i] *
(
(x1[i]+x2[i]+x3[i]+x4[i]+x5[i])
- 1/10 * ( b1 +b2)
)
);
subject to
{
//We must play in 5 games.
//It means that there are 5 players in each game.
sum(i in 1..10) x1[i]==5;
sum(i in 1..10) x2[i]==5;
sum(i in 1..10) x3[i]==5;
sum(i in 1..10) x4[i]==5;
sum(i in 1..10) x5[i]==5;
// IQP problem into ILP -problem
forall (i in 1..10)
{
//ERROR HERE!
//it returns zero for b1 and b2, they should be maximized...
//I am trying to use the tip by David here, see his answer.
// EQ1: x2[i] * (x1[i]+x3[i])
b1 <= 2*x2[i];
b1 <= x1[i]+x3[i];
// EQ2: x4[i] * (x3[i]+x5[i]+x1[i])
b2 <= 3*x4[i];
b2 <= x3[i]+x5[i]+x1[i];
}
};
答案 0 :(得分:1)
表达式
x1 * x2
如果x1,x2都是变量,则是二次的。你有一个50变量的整数二次规划问题。此外,您的目标函数不是凹的,因此CPLEX将会特别困难 但是,由于您拥有所有0-1变量,您可以通过为具有正系数和惩罚的表达式添加额外变量(例如 bonus )将其转换为线性问题具有负系数的那些,将它们放在目标函数中而不是二次项并添加以下约束
bonus <= x1
bonus <= x2
或在负系数的情况下
penalty >= x1 + x2 - 1
由于您正在最大化,cplex将在最佳解决方案中强制奖励或惩罚到正确的值。 惩罚和奖金变量应宣布为非负面
dvar float+ penalty;
dvar float+ bonus;
为所有二次表达式执行此操作,您的问题将成为线性整数问题,并且解决得更快。