c++ - Cplex C++,求和 IloNumVarArray 并创建 SOS2

标签 c++ linear-programming cplex

我正在尝试实现本书第 179 页的示例 9.8:link

我正在使用带有 C++ 接口(interface)的 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 和 k 的 lamda 之和(行和列)。或者换句话说,对于网格的每一行,第 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”也为非零。您可以看到权重是自动生成的。

关于c++ - Cplex C++,求和 IloNumVarArray 并创建 SOS2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39252319/

相关文章:

c++ - MPI发送和接收的通信成本

java - 从 Eclipse 中的文本文件读取按列数据

c - 如何在我的代码中使用 CPLEX 时间限制?

c++ - 如何检查 vector 是否指向 C++ 中二维 vector 中的空 vector ?

c++ - C++中使用智能指针分配和删除内存的有效方法

algorithm - 线性规划:我可以制定一个目标来一次最大化多个变量吗?

mathematical-optimization - 在整数规划中使用最小/最大运算符

c - 最小化 C 语言的线性规划系统

c++ - QT - 从 .ui 文件创建布局