ubuntu下C++使用cplex求解全解

这篇文章主要参考cplex用户手册

求解无权无向图的最小顶点覆盖为例,,用C++语言来演示在ubuntu环境下使用cplex求解最小顶点覆盖的全解

  • 问题描述
    M i n ∑ i = 1 n a i Min\sum_{i=1}^{n}a_i Mini=1nai
    1 ⩽ a i + a j ⩽ 2 1\leqslant a_{i}+a_{j}\leqslant2 1ai+aj2 ( i , j ) (i,j) (i,j) G G G的任意一条边
    0 ⩽ a i ⩽ 1 , ( i = 1 , 2 , . . . n ) 0\leqslant a_{i}\leqslant1,(i=1,2,...n) 0ai1,(i=1,2,...n) a i a_{i} ai是整数
  • 代码实现
#include 
#include "ilcplex/ilocplex.h"
using namespace std;

int SIZE, EdgeNum, EdgeSIZE;

struct Vertex
{
     
   int state;
};
Vertex *vertices;
struct Edge
{
     
   int head, tail;
};
Edge *edges;
void readGraph(char *filename)
{
     
   freopen(filename, "r", stdin);
   scanf("%d %d", &SIZE, &EdgeNum);
   EdgeSIZE = EdgeNum;
   vertices = (Vertex *)malloc(SIZE * sizeof(Vertex));
   edges = (Edge *)malloc(EdgeNum * sizeof(Vertex));
   for(int i = 0; i < EdgeNum; i ++)
   {
     
       int head, tail;
       scanf("%d %d", &head, &tail);
       head --;
       tail --;
       edges[i].head = head;
       edges[i].tail = tail;
   }
}
void VertexCoverLP()
{
     
   IloEnv          env;//定义环境
   IloModel        model(env);//定义模型
   IloIntVar       Ud(env, 0, SIZE);//定义Ud的范围,我这里整形运算
   IloIntVarArray  a(env, SIZE, 0, 1);//定义变量a[1..n],范围[0,1]为整数
   IloRangeArray   constraints(env, EdgeNum, 1, 2);//添加边约束,范围为[1,2]

   model.add(constraints);//添加约束

   IloExpr expr=Ud;//IloExpr 一定要初始化
   for (int i = 0; i < SIZE; i++)
   {
     
       expr += a[i];
   }
   model.add(IloMinimize(env, expr));//添加最小约束
   for (int i = 0; i < EdgeSIZE; i++)  //添加边约束
   {
     
       IloExpr expr = a[edges[i].head] + a[edges[i].tail];
       constraints[i].setExpr(expr);
   }
   IloCplex Solver(model);//定义解题器
   Solver.setOut(env.getNullStream());//不输出求解日志
   Solver.setParam(Solver.SolnPoolAGap, 0.0); //设置解法池的绝对间隙
   Solver.setParam(Solver.SolnPoolIntensity, 4); //设置解法池强度参
   Solver.setParam(Solver.PopulateLim, 2100000000);//设置按填充针对解法池生成的解法的最大数量
   Solver.populate();//调用填充

   //输出所有解的信息
   for(int i = 0; i < Solver.getSolnPoolNsolns(); i ++)
   {
     
       printf("----------------\n");
       printf("sol = %d\n", i + 1);
       Solver.writeSolution("out.sol", i);
       for(int j = 0; j < SIZE; j ++)
       {
     
           if(Solver.getValue(a[j], i) == 1) //获取第i个解中变量j的值
           {
     
               cout << j + 1 << "  ";
           }
       }
       cout << endl;
   }
   env.end();
}
int main(int argc, char *argv[])
{
     
   char *filename;
   filename = argv[1];
   cout << filename << endl;
   readGraph(filename);
   VertexCoverLP();
   return 0;
}
  • 输出结果
//输入数据
3 3
1 2 
2 3
3 1

ubuntu下C++使用cplex求解全解_第1张图片

  • 注意
    即使对于规模较小的图,其全解的个数个能很大,对全解的求解对于时间和空间的消耗是很大。

你可能感兴趣的:(Linux)