最近在用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";
}
}
}