最近在用CPLEX解决优化问题,由于找不到很多关于CPLEX的程序,因此在对照官方文档看的基础上,对一些相关点进行了理解和注解。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ILOG.Concert;
using ILOG.CPLEX;
namespace LPex1
{
class Program
{
internal static void Usage()
{
System.Console.WriteLine("usage: LPex1 <option>");
System.Console.WriteLine("options: -r build model row by row");
System.Console.WriteLine("options: -c build model column by column");
System.Console.WriteLine("options: -n build model nonzero by nonzero");
}
static void Main(string[] args)
{
if (args.Length != 1 || args[0].ToCharArray()[0] != '-')
{
Usage();
return;
}
try
{
Cplex cplex = new Cplex();//创建一个空的Cplex实例,然后再后面添加相关的目标函数与约束条件
INumVar[][] var = new INumVar[1][];
IRange[][] rng = new IRange[1][];
switch (args[0].ToCharArray()[1])
{
case 'r':
PopulateByRow(cplex, var, rng);
break;
case 'c':
PopulateByColumn(cplex, var, rng);
break;
case 'n':
PopulateByNonzero(cplex, var, rng);
break;
default:
Usage();
return;
}
//write model to file
cplex.ExportModel("lpex1.lp");//保存模型
//调用解决方法Solve,计算cplex模型并显示相关的参数
if (cplex.Solve())
{
double[] x = cplex.GetValues(var[0]);//得到模型的变量的参数
double[] dj = cplex.GetReducedCosts(var[0]);
double[] pi = cplex.GetDuals(rng[0]);
double[] slack = cplex.GetSlacks(rng[0]);
cplex.Output().WriteLine("Solution status =" + cplex.GetStatus());
cplex.Output().WriteLine("Solution get value=" + cplex.ObjValue);
int nvars = x.Length;
for (int j = 0; j < nvars; j++)
{
cplex.Output().WriteLine("Variable " + j +
": Value = " + x[j] +
" Reduced cost = " + dj[j]);
}
int ncons = slack.Length;
for (int i = 0; i < ncons; ++i)
{
cplex.Output().WriteLine("Constraint " + i +
": Slack = " + slack[i] +
" Pi = " + pi[i]);
}
cplex.End();
}
}
catch (ILOG.Concert.Exception e)
{
System.Console.WriteLine("Concert exception '" + e + "' caught");
}
}
// The following methods all populate the problem with data for the following
// linear program:
//
// Maximize
// x1 + 2 x2 + 3 x3
// Subject To
// - x1 + x2 + x3 <= 20
// x1 - 3 x2 + x3 <= 30
// Bounds
// 0 <= x1 <= 40
// End
//
// using the IMPModeler API
internal static void PopulateByRow(IMPModeler model,
INumVar[][] var,
IRange[][] rng)//按照行生成的模式构建目标函数以及目标函数的相关约束
{
double[] lb = { 0.0, 0.0, 0.0 };//构建double类型的下边界
double[] ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };//构建double类型的上边界
string[] varname = { "x1", "x2", "x3" };//创建变量名
INumVar[] x = model.NumVarArray(3, lb, ub, varname);//通过IMPModeler中的NumVarArray函数将模型的下边界,上边界以及模型的变量名赋给X
var[0] = x;//将X传递给模型的数值变量类型var,并按照行生成,第一行是变量的属性参数。
double[] objvals = { 1.0, 2.0, 3.0 };//目标函数的参数
model.AddMaximize(model.ScalProd(x, objvals));//指明模型是求取最大值,并用ScalProd返回给定标量乘积的线性表达式。
rng[0] = new IRange[2];//产生一个两列的约束函数参数
rng[0][0] = model.AddLe(model.Sum(model.Prod(-1.0, x[0]),
model.Prod(1.0, x[1]),
model.Prod(1.0, x[2])), 20.0, "c1");//其中第一列为约束函数1,通过Sum函数以求和的形式返。Prod函数指明第一个约束条件的参数值,并知名其在矩阵中存储的位置
rng[0][1] = model.AddLe(model.Sum(model.Prod(1.0, x[0]),
model.Prod(-3.0, x[1]),
model.Prod(1.0, x[2])), 30.0, "c2");
}
internal static void PopulateByColumn(IMPModeler model,
INumVar[][] var,
IRange[][] rng)
{
IObjective obj = model.AddMaximize();
rng[0] = new IRange[2];
rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0, "c1");
rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0, "c2");
IRange r0 = rng[0][0];
IRange r1 = rng[0][1];
var[0] = new INumVar[3];
var[0][0] = model.NumVar(model.Column(obj, 1.0).And(
model.Column(r0, -1.0).And(
model.Column(r1, 1.0))),
0.0, 40.0, "x1");
var[0][1] = model.NumVar(model.Column(obj, 2.0).And(
model.Column(r0, 1.0).And(
model.Column(r1, -3.0))),
0.0, System.Double.MaxValue, "x2");
var[0][2] = model.NumVar(model.Column(obj, 3.0).And(
model.Column(r0, 1.0).And(
model.Column(r1, 1.0))),
0.0, System.Double.MaxValue, "x3");
}
internal static void PopulateByNonzero(IMPModeler model,
INumVar[][] var,
IRange[][] rng)
{
double[] lb = { 0.0, 0.0, 0.0 };
double[] ub = { 40.0, System.Double.MaxValue, System.Double.MaxValue };
INumVar[] x = model.NumVarArray(3, lb, ub);
var[0] = x;
double[] objvals = { 1.0, 2.0, 3.0 };
model.Add(model.Maximize(model.ScalProd(x, objvals)));
rng[0] = new IRange[2];
rng[0][0] = model.AddRange(-System.Double.MaxValue, 20.0);
rng[0][1] = model.AddRange(-System.Double.MaxValue, 30.0);
rng[0][0].Expr = model.Sum(model.Prod(-1.0, x[0]),
model.Prod(1.0, x[1]),
model.Prod(1.0, x[2]));
rng[0][1].Expr = model.Sum(model.Prod(1.0, x[0]),
model.Prod(-3.0, x[1]),
model.Prod(1.0, x[2]));
x[0].Name = "x1";
x[1].Name = "x2";
x[2].Name = "x3";
rng[0][0].Name = "c1";
rng[0][0].Name = "c2";
}
}
}