编译c++, Sum IloNumVarArray并创建SOS2

Cplex C++, Sum IloNumVarArray and create SOS2

本文关键字:创建 SOS2 IloNumVarArray Sum c++ 编译      更新时间:2023-10-16

我正在尝试实现本书第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)的网格,并将非负权重关联到每个点(即lambda [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

那么为了使用紧密相关的点,我们需要保证最多有四个相邻的[s][k]不为零。这可以通过以下约束来实现:

C[s] = sum_k lamda[s][k] for all s
B[k] = sum_k lamda[s][k] for all k

where C {C_1, C_2,…C_s}和B {B_1, B_2,…取B_k}为SOS2。也就是说,相邻的行和列最多只能为非零

我提供的代码是为最后两个约束,我要做的是,例如设置C[s] (C的第s个实例)等于λ/s和k(行和列)的和。换句话说,对于网格的每一行,第一行变量的和,应该进到C[1],第二行变量的和应该进到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"answers"x_1_1"最多也非零。您可以看到权重是自动生成的。

我想出了一个解决方案,感谢@rkersh,他让我朝正确的方向思考。对于感兴趣的读者,以下是我的解决方法:

    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));