C#调用CPLEX求解最短路问题

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

  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
粒子群优化(Particle Swarm Optimization, PSO)是一种常用的优化算法,可用于路径规划问题。在C#求解粒子群路径规划可以按照以下步骤进行: 1. 定义问题:首先需要明确路径规划问题的具体定义,包括起始点、目标点、路径约束等。 2. 初始化粒子群:随机生成一组粒子,并初始化它们的位置和速度。 3. 计算适应度:根据每个粒子的位置计算适应度值,即路径的质量评价指标。适应度函数可根据具体问题进行定义,如路径长度、能耗等。 4. 更新速度和位置:根据粒子的当前位置、速度和历史最佳位置,以及整个群体的最佳位置,更新粒子的速度和位置。 5. 重复迭代:重复步骤3和步骤4,直到达到预定的终止条件,如达到最大迭代次数或找到满意的解。 6. 输出结果:输出收敛后的最佳路径及其适应度值。 以下是一个简单的C#代码示例,用于求解粒子群路径规划问题: ```csharp // 粒子类 class Particle { public double[] Position { get; set; } public double[] Velocity { get; set; } public double[] BestPosition { get; set; } public double BestFitness { get; set; } } class PSO { private Particle[] particles; private double[] globalBestPosition; private double globalBestFitness; public PSO(int particleCount) { particles = new Particle[particleCount]; // 初始化粒子群 // ... } public void Solve() { int maxIterations = 100; int currentIteration = 0; while (currentIteration < maxIterations) { foreach (Particle particle in particles) { // 计算粒子适应度 // ... if (particle.BestFitness > globalBestFitness) { globalBestFitness = particle.BestFitness; globalBestPosition = (double[])particle.BestPosition.Clone(); } // 更新粒子速度和位置 // ... } currentIteration++; } // 输出结果 // ... } } // 使用示例 class Program { static void Main(string[] args) { int particleCount = 50; PSO pso = new PSO(particleCount); pso.Solve(); // 输出最佳路径 // ... } } ``` 请注意,上述代码只是一个简单示例,实际应用中还需要根据具体问题进行适应度函数的定义、速度和位置的更新等。另外,在实际应用中,可能需要考虑一些限制条件,如避障等。希望以上信息对您有所帮助!如有任何问题,请随时提问。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值