一個CPLEX簡單程序的註釋

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章