1 问题描述
来源:孙晚华等著《ILOG CPLEX 与铁道运输优化》
2 模型
3 C#代码
using System;
using ILOG.Concert;
using ILOG.CPLEX;
using System.Collections.Generic;
/*
* 调用CPLEX求解一个9节点15条弧的最短路模型
*/
namespace tryCPLEX_List
{
class Program
{
static void Main(string[] args)
{
try
{
char[,] Arcs = new char[,]{{ 'A','B'}, { 'A','C'}, { 'A','D'}, { 'B','E'}, { 'B','F'}, { 'C','E'}, { 'C','F'},
{ 'D','E'}, { 'D','F'}, { 'E','G'}, { 'E','H'}, { 'F','G'}, { 'F','H'}, { 'G','I'}, { 'H','I'}};
char[] nodes = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I' }; //节点数组
string[] deVarName = new string[Arcs.GetLength(0)]; //决策变量名称
for(int i = 0;i < Arcs.GetLength(0); i++)
{
deVarName[i] = "x" + "_" + Arcs[i, 0].ToString() + "_" + Arcs[i, 1].ToString();
}
double[] lb = new double[deVarName.Length]; //决策变量下界
double[] ub = new double[deVarName.Length]; //决策变量上界
NumVarType[] xtype = new NumVarType[deVarName.Length]; //决策变量类型数组
for (int i = 0; i < deVarName.Length; i++)
{
lb[i] = 0;
ub[i] = double.MaxValue;
xtype[i] = NumVarType.Bool;
}
//实例化一个空模型
Cplex cplexModel = new Cplex();
//生成决策变量并约束范围
INumVar[][] deVar = new INumVar[1][];//交叉数组用于存储决策变量
INumVar[] x = cplexModel.NumVarArray(deVarName.Length, lb, ub, xtype, deVarName); //生成决策变量,InumVar类型的一维数组
deVar[0] = x;
//生成目标函数
double[] objCoef = { 6, 3, 3, 6, 5, 8, 6, 7, 4, 6, 7, 8, 9, 5, 6 };//目标函数系数(object coefficient) 弧长
cplexModel.AddMinimize(cplexModel.ScalProd(x, objCoef));//数量相乘(scalar product) 数组的数量积
// 生成约束条件
IRange[][] rng = new IRange[1][]; //存放约束
List<INumVar> deVarAL = new List<INumVar>(); //以A为起点的弧集合
List<INumVar> deVarIL = new List<INumVar>(); //以I为终点的弧集合
for(int i = 0; i < x.Length; i++)
{
if(Arcs[i,0] == 'A')
{
deVarAL.Add(x[i]);
}
if(Arcs[i,1] == 'I')
{
deVarIL.Add(x[i]);
}
}
INumVar[] deVarA = deVarAL.ToArray(); //将列表转化为数组
INumVar[] deVarI = deVarIL.ToArray();
int[] deVarAnum = new int[deVarA.Length]; //约束条件1的系数数组
int[] deVarInum = new int[deVarI.Length]; //约束条件2的系数数组
for(int i = 0; i < deVarA.Length; i++)
{
deVarAnum[i] = 1;
//Console.WriteLine(deVarAnum[i]);
}
for(int i = 0; i < deVarI.Length; i++)
{
deVarInum[i] = 1;
}
rng[0] = new IRange[1+1+nodes.Length-2];
//addle为<=,addge为>=,addeq为=
rng[0][0] = cplexModel.AddEq(cplexModel.ScalProd(deVarA, deVarAnum), 1, "c1"); //从A点发出的弧只有一条被选择
rng[0][1] = cplexModel.AddEq(cplexModel.ScalProd(deVarI, deVarInum), 1, "c2"); //流入I点的弧只有一条被选择
foreach(char nodesM in nodes)
{
int i = 2;
if(nodesM != 'A' && nodesM != 'I')
{
List<INumVar> deVarinList = new List<INumVar>();
List<INumVar> deVaroutList = new List<INumVar>();
for(int j = 0; j < x.Length; j++)
{
if(Arcs[j,1] == nodesM)
{
deVarinList.Add(x[j]);
}
if(Arcs[j,0] == nodesM)
{
deVaroutList.Add(x[j]);
}
}
INumVar[] deVarin = deVarinList.ToArray();
INumVar[] deVarout = deVaroutList.ToArray();
int[] devarinnum = new int[deVarin.Length];
int[] deVaroutnum = new int[deVarout.Length];
for(int j = 0; j < deVarin.Length; j++)
{
devarinnum[j] = 1;
}
for(int j = 0; j < deVarout.Length; j++)
{
deVaroutnum[j] = -1;
}
string cn = "c" + i.ToString(); //约束条件名称
rng[0][i] = cplexModel.AddEq(cplexModel.Sum( cplexModel.ScalProd(deVarin, devarinnum),
cplexModel.ScalProd(deVarout,deVaroutnum) ), 0, cn); //以中间节点为终点的弧和以其为起点的弧的数量相等
i++;
}
}
if (cplexModel.Solve())
{
int nvars = cplexModel.GetValues(deVar[0]).Length;
for (int j = 0; j < nvars; ++j)
{
cplexModel.Output().WriteLine("Variable " + deVarName[j] + " = " + cplexModel.GetValues(deVar[0])[j]);
}
Console.WriteLine("\nObjvalue = " + cplexModel.ObjValue); //输出最优目标函数值
}
cplexModel.ExportModel("lpex1.lp");
cplexModel.End();
}
catch (ILOG.Concert.Exception e)
{
System.Console.WriteLine("Concert exception '" + e + "' caught");
}
}
}
}
4 求解结果
Root node processing (before b&c):
Real time = 0.11 sec. (0.03 ticks)
Parallel b&c, 8 threads:
Real time = 0.00 sec. (0.00 ticks)
Sync time (average) = 0.00 sec.
Wait time (average) = 0.00 sec.
------------
Total (root+branch&cut) = 0.11 sec. (0.03 ticks)
Variable x_A_B = 0
Variable x_A_C = 0
Variable x_A_D = 1
Variable x_B_E = 0
Variable x_B_F = 0
Variable x_C_E = 0
Variable x_C_F = 0
Variable x_D_E = 0
Variable x_D_F = 1
Variable x_E_G = 0
Variable x_E_H = 0
Variable x_F_G = 1
Variable x_F_H = 0
Variable x_G_I = 1
Variable x_H_I = 0
Objvalue = 20