Cplex C++,求和 IloNumVarArray 并创建 SOS2
Cplex C++, Sum IloNumVarArray and create SOS2
我正在尝试实现本书第 179 页的示例 9.8:link
我正在使用带有 C++ 接口的 Cplex。
我无法正确初始化 SOS2。这是我初始化 SOS2 的代码片段:
IloNumArray Cval(env, S);
IloNumVarArray C(env,S);
for (int s = 0; s < S; s++)
{
for (int k = 0; k < K; k++)
{
C[s] = IloNumVar(env, 0, 1);
C[s] += lamda[s][k];
}
Cval[s] = s;
}
model.add(IloSOS2(env, C, Cvals));
IloNumArray Bval(env, K);
IloNumVarArray B(env,K);
for (int k = 0; k < K; k++)
{
for (int s = 0; s < S; s++)
{
B[s] = IloNumVar(env, 0, 1);
B[k] += lamda[s][k];
}
Bval[k] = k;
}
model.add(IloSOS2(env, B, Bval));enter code here
我收到以下错误:
SOS2Test.cpp: In function ‘int main()’:
SOS2Test.cpp:74:16: error: no match for ‘operator+=’ (operand types
are ‘IloNumVar’ and ‘IloNumVar’)
sosvars[s] += lamda[s][k];
^
SOS2Test.cpp:87:16: error: no match for ‘operator+=’ (operand types
are ‘IloNumVar’ and ‘IloNumVar’)
sosvark[k] += lamda[s][k];
^
这当然很清楚了。该类型未实现运算符“+=”。但是,我想不出任何其他方法,我很确定这确实是我想做的。
任何人都可以帮助我或指出正确的方向吗?
提前致谢!
编辑:
这是我正在尝试做的事情:
我正在尝试逼近两个变量 z = f(x,y) 的非线性函数。我已经定义了一个值网格 (x,y) 和每个点的相关非负权重(即 lamda[s][k])。那么如果将网格点处的(x,y)的值记为(X[s], Y[s]),则函数可以近似为如下关系:
x = Sum_s Sum_k X[s] * lamda[s][k]
y = Sum_s Sum_k Y[k] * lamda[s][k]
z = Sum_s Sum_k Z[s][k] * lamda[s][k]
1 = Sum_s Sum_k Z[s][k] lamda[s][k]
哪里
s = rows
k = columns
然后为了使用紧密相关的点,我们需要强制最多四个相邻的lamda[s][k]可以是非零的。这可以通过以下约束施加:
C[s] = sum_k lamda[s][k] for all s
B[k] = sum_k lamda[s][k] for all k
其中 C {C_1, C_2, .. C_s} 和 B {B_1, B_2, .. B_k } 被视为 SOS2。这规定最多两个相邻的行和两个相邻的列可以是非零的。
我提供的代码是针对最后两个约束的,我想做的是例如将 C[s](C 的第 s 个实例)设置为等于 s 上的 lamda 之和和 k(行和列)。或者换句话说,对于网格的每一行,第 1 行中变量的总和应该进入 C[1],第 2 行中变量的总和应该进入 C[2] 等。对于每一列,第 1 列中变量的总和,应进入 B[1] 等
所以在 CPLEX 术语中。我想总结一组 IloNumVars 并将其设置为等于 IloNumVarArray 中的位置,然后将该 IloNumVarArray 用作 SOS2
我希望这能澄清一点。
我认为 lamda
的每一行和每一列都需要一个 SOS2 约束,如下所示:
for (int s = 0; s < S; s++) {
model.add(IloSOS2(env, lamda[s]));
}
IloNumVarArray B[K];
for (int k = 0; k < K; k++) {
B[k] = IloNumVarArray(env, S);
for (int s = 0; s < S; s++) {
B[k][s] = lamda[s][k];
}
model.add(IloSOS2(env, B[k]));
}
例如,对于 4x4 矩阵,这将产生以下 LP 格式的 SOS2 约束:
SOS
s1: S2 :: x_0_0 : 1 x_0_1 : 2 x_0_2 : 3 x_0_3 : 4
s2: S2 :: x_1_0 : 1 x_1_1 : 2 x_1_2 : 3 x_1_3 : 4
s3: S2 :: x_2_0 : 1 x_2_1 : 2 x_2_2 : 3 x_2_3 : 4
s4: S2 :: x_3_0 : 1 x_3_1 : 2 x_3_2 : 3 x_3_3 : 4
s5: S2 :: x_0_0 : 1 x_1_0 : 2 x_2_0 : 3 x_3_0 : 4
s6: S2 :: x_0_1 : 1 x_1_1 : 2 x_2_1 : 3 x_3_1 : 4
s7: S2 :: x_0_2 : 1 x_1_2 : 2 x_2_2 : 3 x_3_2 : 4
s8: S2 :: x_0_3 : 1 x_1_3 : 2 x_2_3 : 3 x_3_3 : 4
因此,如果 "x_0_0" 不为零,那么至多 "x_0_1"、"x_1_0" 和 "x_1_1" 也为非零。可以看到权重是自动生成的
我找到了一个解决方案,感谢@rkersh,他让我朝着正确的方向思考。有兴趣的reader,我是这样解决的:
IloNumVarArray B(env, S);
IloNumArray Bval(env, S);
for (int s = 0; s < S; s++)
{
B[s] = IloNumVar(env, 0, 1);
Bval[s] = s;
IloExpr l(env);
for (int k = 0; k < K; k++)
{
l += lamda[s][k];
}
model.add(B[s] == l);
}
model.add(IloSOS2(env, B, Bval));
IloNumVarArray C(env, K);
IloNumArray Cval(env, K);
for (int k = 0; k < K; k++)
{
Cval[k] = k;
C[k] = IloNumVar(env, 0, 1);
IloExpr l(env);
for (int s = 0; s < S; s++)
{
l += lamda[s][k];
}
model.add(C[k] == l);
}
model.add(IloSOS2(env, C, Cval));
我正在尝试实现本书第 179 页的示例 9.8:link
我正在使用带有 C++ 接口的 Cplex。
我无法正确初始化 SOS2。这是我初始化 SOS2 的代码片段:
IloNumArray Cval(env, S);
IloNumVarArray C(env,S);
for (int s = 0; s < S; s++)
{
for (int k = 0; k < K; k++)
{
C[s] = IloNumVar(env, 0, 1);
C[s] += lamda[s][k];
}
Cval[s] = s;
}
model.add(IloSOS2(env, C, Cvals));
IloNumArray Bval(env, K);
IloNumVarArray B(env,K);
for (int k = 0; k < K; k++)
{
for (int s = 0; s < S; s++)
{
B[s] = IloNumVar(env, 0, 1);
B[k] += lamda[s][k];
}
Bval[k] = k;
}
model.add(IloSOS2(env, B, Bval));enter code here
我收到以下错误:
SOS2Test.cpp: In function ‘int main()’:
SOS2Test.cpp:74:16: error: no match for ‘operator+=’ (operand types
are ‘IloNumVar’ and ‘IloNumVar’)
sosvars[s] += lamda[s][k];
^
SOS2Test.cpp:87:16: error: no match for ‘operator+=’ (operand types
are ‘IloNumVar’ and ‘IloNumVar’)
sosvark[k] += lamda[s][k];
^
这当然很清楚了。该类型未实现运算符“+=”。但是,我想不出任何其他方法,我很确定这确实是我想做的。
任何人都可以帮助我或指出正确的方向吗?
提前致谢!
编辑:
这是我正在尝试做的事情:
我正在尝试逼近两个变量 z = f(x,y) 的非线性函数。我已经定义了一个值网格 (x,y) 和每个点的相关非负权重(即 lamda[s][k])。那么如果将网格点处的(x,y)的值记为(X[s], Y[s]),则函数可以近似为如下关系:
x = Sum_s Sum_k X[s] * lamda[s][k]
y = Sum_s Sum_k Y[k] * lamda[s][k]
z = Sum_s Sum_k Z[s][k] * lamda[s][k]
1 = Sum_s Sum_k Z[s][k] lamda[s][k]
哪里
s = rows
k = columns
然后为了使用紧密相关的点,我们需要强制最多四个相邻的lamda[s][k]可以是非零的。这可以通过以下约束施加:
C[s] = sum_k lamda[s][k] for all s
B[k] = sum_k lamda[s][k] for all k
其中 C {C_1, C_2, .. C_s} 和 B {B_1, B_2, .. B_k } 被视为 SOS2。这规定最多两个相邻的行和两个相邻的列可以是非零的。
我提供的代码是针对最后两个约束的,我想做的是例如将 C[s](C 的第 s 个实例)设置为等于 s 上的 lamda 之和和 k(行和列)。或者换句话说,对于网格的每一行,第 1 行中变量的总和应该进入 C[1],第 2 行中变量的总和应该进入 C[2] 等。对于每一列,第 1 列中变量的总和,应进入 B[1] 等
所以在 CPLEX 术语中。我想总结一组 IloNumVars 并将其设置为等于 IloNumVarArray 中的位置,然后将该 IloNumVarArray 用作 SOS2
我希望这能澄清一点。
我认为 lamda
的每一行和每一列都需要一个 SOS2 约束,如下所示:
for (int s = 0; s < S; s++) {
model.add(IloSOS2(env, lamda[s]));
}
IloNumVarArray B[K];
for (int k = 0; k < K; k++) {
B[k] = IloNumVarArray(env, S);
for (int s = 0; s < S; s++) {
B[k][s] = lamda[s][k];
}
model.add(IloSOS2(env, B[k]));
}
例如,对于 4x4 矩阵,这将产生以下 LP 格式的 SOS2 约束:
SOS
s1: S2 :: x_0_0 : 1 x_0_1 : 2 x_0_2 : 3 x_0_3 : 4
s2: S2 :: x_1_0 : 1 x_1_1 : 2 x_1_2 : 3 x_1_3 : 4
s3: S2 :: x_2_0 : 1 x_2_1 : 2 x_2_2 : 3 x_2_3 : 4
s4: S2 :: x_3_0 : 1 x_3_1 : 2 x_3_2 : 3 x_3_3 : 4
s5: S2 :: x_0_0 : 1 x_1_0 : 2 x_2_0 : 3 x_3_0 : 4
s6: S2 :: x_0_1 : 1 x_1_1 : 2 x_2_1 : 3 x_3_1 : 4
s7: S2 :: x_0_2 : 1 x_1_2 : 2 x_2_2 : 3 x_3_2 : 4
s8: S2 :: x_0_3 : 1 x_1_3 : 2 x_2_3 : 3 x_3_3 : 4
因此,如果 "x_0_0" 不为零,那么至多 "x_0_1"、"x_1_0" 和 "x_1_1" 也为非零。可以看到权重是自动生成的
我找到了一个解决方案,感谢@rkersh,他让我朝着正确的方向思考。有兴趣的reader,我是这样解决的:
IloNumVarArray B(env, S);
IloNumArray Bval(env, S);
for (int s = 0; s < S; s++)
{
B[s] = IloNumVar(env, 0, 1);
Bval[s] = s;
IloExpr l(env);
for (int k = 0; k < K; k++)
{
l += lamda[s][k];
}
model.add(B[s] == l);
}
model.add(IloSOS2(env, B, Bval));
IloNumVarArray C(env, K);
IloNumArray Cval(env, K);
for (int k = 0; k < K; k++)
{
Cval[k] = k;
C[k] = IloNumVar(env, 0, 1);
IloExpr l(env);
for (int s = 0; s < S; s++)
{
l += lamda[s][k];
}
model.add(C[k] == l);
}
model.add(IloSOS2(env, C, Cval));