简体   繁体   English

我正在寻找在 CPLEX OPL 中解决的车辆路线问题的代码

[英]I am looking for an code for the vehicle routing problem solved in the CPLEX OPL

I need to create a simple VRP model in CPLEX, I would be so grateful if someone could help me out.我需要在 CPLEX 中创建一个简单的 VRP 模型,如果有人可以帮助我,我将不胜感激。 I want to know which vehicle is serving which customer?我想知道哪辆车为哪位客户服务?

Here are the details: depot: 1 vehicles: 15 vehicle capacity: 17 Customers: 56 Customers demand: 2详情如下: 车厂:1 车辆:15 车辆容量:17 客户:56 客户需求:2

here is what I have tried so far:这是我到目前为止所尝试的:

.mod: .mod:

{string} k = ...;  // vehicles
{string} i = ...;  // nodes
{string} j = ...; // depot


int demand[i]= ...; // demand at node i
int cap[k]= ...; // capacity of the vehicle
int dist[i][j]=...; //distance from node i to j

dvar float x[i][j];


minimize 
    sum(nodes in i, depot in j)
      dist[i][j];
      
      
subject to {
  

forall (nodes in i)
      demand_must_be_met:
      sum(vehicle in k)
        x[k][i]==demand[i];
}  

.dat: .dat:

k = {k1,k2,k3,k4,k5,k6,k7,k8,k9,k10,k11,k12,k13,k14,k15};

i = {Taubenmarkt,Landstrasse,LLenaupark,LLandstrasse,Industriezeile,LentiaCity,LLeonding,LInterspar,KarlSteigerStrasse,Kornstrasse,Traunerkreuzung,PlusKaufStrasse,FMZ,Haid,Marchtrenk,EferdingPupping,Walding,Rohrbach,BadLeonfelden,LAltenbergerstrasse,Gallneukirchen,Unterweitersdorf,FMZNord,Mauthausen,Furnpark,FMZEnnspark,NaarerStrasse,Steyr,SteyrResthofstrasse,SteyrHaagerStrasse,Sierning,LHartheimeerstrasse,BadHall,Micheldorf,Vorchdorf,WelsBäckergasse,Dalistrasse,WelsOberfeldstrasse,MaxCenter,GrieskirchenSchlüsselberg,DruckereistrasseSEP,Laakirchen,Schwanenstadt,Ampflwang,RiedTumeltshamFMZ,Weberzeile,Schärding,BadIschlFMZ,BadIschlZentrum,VöcklabruchZentrum,Varena,FMZTimelkam,StGeorgen,Mondsee,CityCenter,Mattighofen
};

j = {Enns};

cap = [17,17,17,17,17,17,17,17,17,17,17,17,17,17,17];

demand = [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
];

dist = [23,22,22,24,12,24,19,18,22,23,23,16,20,33,41,35,68,52,28,37,42,63,10,4,3,17,22,21,21,28,11,36,63,52,43,37,38,43,55,75,64,64,90,82,81,106,111,108,77,76,80,87,110,123,117
];

thank you so much for your help in advance!非常感谢您提前提供的帮助!

you could start with the TSP example in How to with OPL您可以从如何使用 OPL中的TSP 示例开始

VRP

using CP;

tuple Node {
    key string nodeID;
    int x;
    int y;
}
{Node} nodes = ...; 

tuple Visit { 
            key int visitID;
            string nodeID; 
            int quantity; 
            int minTime; 
            int maxTime; 
            int dropTime; 
              };
{Visit} clientVisits = ...;   

tuple Vehicle {
                key string vehicleID;   
                string firstVisitID;
                string lastVisitID;
                int capacity;
                int start;
                int end;
            }   
{Vehicle} vehicles = ...;                               

int firstDepotVisitID = min(v in clientVisits) v.visitID - 1;
int lastDepotVisitID = max(v in clientVisits) v.visitID + 1;
Visit firstDepotVisit = <firstDepotVisitID,"depot",0,0,230,0>;
Visit lastDepotVisit = <lastDepotVisitID,"depot",0,0,230,0>;
{Visit} allVisits = clientVisits union
            // Needs to be generalized for multiple depots
            {firstDepotVisit, lastDepotVisit };
            
int xPerVisit[i in allVisits]=item(nodes,<i.nodeID>).x; 
int yPerVisit[i in allVisits]=item(nodes,<i.nodeID>).y; 

int horizon = max (v in allVisits) v.maxTime;

// Create transition distance
tuple triplet { int c1; int c2; int d; };
{triplet} Dist = { 
    
        <ord(allVisits,v1), ord(allVisits,v2), 
        ftoi(round(sqrt(pow(n2.x-n1.x,2)+pow(n2.y-n1.y,2))))> 
           | v1,v2 in allVisits, n1, n2 in nodes : v1.nodeID == n1.nodeID && v2.nodeID == n2.nodeID }; 
  
dvar interval visitInterval[v in clientVisits] in v.minTime..(v.maxTime+v.dropTime) size v.dropTime;
dvar interval wtvisitInterval [v in clientVisits] size v.dropTime..horizon;
dvar interval tvisitInterval  [v in allVisits][veh in vehicles] 
                  optional(v.visitID!=firstDepotVisitID && v.visitID!=lastDepotVisitID);
dvar sequence route[veh in vehicles] in all(v in allVisits) tvisitInterval[v][veh] 
                                  types all(v in allVisits) ord(allVisits,v); 
dvar interval truck [veh in vehicles] optional;
 
execute {
  cp.param.TimeLimit               = 10
}

dexpr int nonTravelTime = sum(v in clientVisits) sizeOf(wtvisitInterval[v]);
dexpr float travelTime = sum(veh in vehicles) endOf(tvisitInterval[lastDepotVisit][veh]) - nonTravelTime;
dexpr int nbUsed = sum(veh in vehicles) presenceOf(truck[veh]);
dexpr int load[veh in vehicles] = sum(v in clientVisits) presenceOf(tvisitInterval[v][veh])*v.quantity;

minimize staticLex(nbUsed,travelTime); 
subject to  {

  forall(v in clientVisits ) {
    endAtEnd(wtvisitInterval[v], visitInterval[v]);
    startBeforeStart(wtvisitInterval[v], visitInterval[v]);
  }
  forall(veh in vehicles) {
    span (truck[veh], all(v in clientVisits) tvisitInterval[v][veh]);
    noOverlap(route[veh], Dist);          // Travel time
    startOf(tvisitInterval[firstDepotVisit][veh])==0;     // Truck t starts at time 0 from depot
    last (route[veh],tvisitInterval[lastDepotVisit] [veh]); // Truck t returns at depot
    load[veh] <= veh.capacity;                       // Truck capacity
  }
  forall(v in clientVisits)
    alternative(wtvisitInterval[v], all(t in vehicles) tvisitInterval[v][t]); // Truck selection
}
 
execute {
  writeln(nbUsed + " vehicles are used");
  writeln("Total travelled distance is " + travelTime); 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM