1 | #region License Information
|
---|
2 | /* HeuristicLab
|
---|
3 | * Copyright (C) 2002-2017 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
|
---|
4 | *
|
---|
5 | * This file is part of HeuristicLab.
|
---|
6 | *
|
---|
7 | * HeuristicLab is free software: you can redistribute it and/or modify
|
---|
8 | * it under the terms of the GNU General Public License as published by
|
---|
9 | * the Free Software Foundation, either version 3 of the License, or
|
---|
10 | * (at your option) any later version.
|
---|
11 | *
|
---|
12 | * HeuristicLab is distributed in the hope that it will be useful,
|
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | * GNU General Public License for more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU General Public License
|
---|
18 | * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
|
---|
19 | */
|
---|
20 | #endregion
|
---|
21 |
|
---|
22 | using System;
|
---|
23 | using System.Collections.Generic;
|
---|
24 | using System.Linq;
|
---|
25 | using System.Text.RegularExpressions;
|
---|
26 | using HeuristicLab.Common;
|
---|
27 | using HeuristicLab.Core;
|
---|
28 | using HeuristicLab.Core.Networks;
|
---|
29 | using HeuristicLab.Data;
|
---|
30 | using HeuristicLab.Encodings.IntegerVectorEncoding;
|
---|
31 | using HeuristicLab.Encodings.RealVectorEncoding;
|
---|
32 | using HeuristicLab.Optimization;
|
---|
33 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
34 | using HeuristicLab.Problems.FacilityLocation;
|
---|
35 | using HeuristicLab.Problems.VehicleRouting;
|
---|
36 | using HeuristicLab.Problems.VehicleRouting.Encodings.General;
|
---|
37 | using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
|
---|
38 |
|
---|
39 | namespace HeuristicLab.Networks.IntegratedOptimization.LocationRouting {
|
---|
40 | [Item("LrpOrchestratorNode3", "Orchestrator for LRP optimization network version 3.")]
|
---|
41 | [StorableClass]
|
---|
42 | public sealed class LrpOrchestratorNode3 : LrpOrchestratorNode {
|
---|
43 | [StorableConstructor]
|
---|
44 | private LrpOrchestratorNode3(bool deserializing) : base(deserializing) { }
|
---|
45 | private LrpOrchestratorNode3(LrpOrchestratorNode3 original, Cloner cloner) : base(original, cloner) { }
|
---|
46 | public LrpOrchestratorNode3() : this("LrpOrchestratorNode3") { }
|
---|
47 | public LrpOrchestratorNode3(string name) : base(name) {
|
---|
48 | MetaSolverOrchestrationPort = CreateOrchestrationPort<MinimizationVariegationProblem<RealVectorEncoding>>(MetaSolverName + OrchestrationPortNameSuffix);
|
---|
49 | MetaSolverEvaluationPort = CreateEvaluationPort<RealVector>(MetaSolverName + EvaluationPortNameSuffix, "RealVector", "Quality");
|
---|
50 | FlpSolverOrchestrationPort = CreateOrchestrationPort<FacilityLocationProblem>(FlpSolverName + OrchestrationPortNameSuffix);
|
---|
51 | VrpSolverOrchestrationPort = CreateOrchestrationPort<VehicleRoutingProblem>(VrpSolverName + OrchestrationPortNameSuffix);
|
---|
52 |
|
---|
53 | VrpParameter.Value.ProblemInstance = new MDCVRPProblemInstance();
|
---|
54 | }
|
---|
55 |
|
---|
56 | public override IDeepCloneable Clone(Cloner cloner) {
|
---|
57 | return new LrpOrchestratorNode3(this, cloner);
|
---|
58 | }
|
---|
59 |
|
---|
60 | protected override void InstanceParameter_Value_ToStringChanged(object sender, EventArgs e) {
|
---|
61 | string filePath = InstanceParameter.Value.Value;
|
---|
62 | LrpUtils.Import(filePath, out nrOfDepots, out nrOfCustomers,
|
---|
63 | out depotCoordinates, out customerCoordinates,
|
---|
64 | out distanceType,
|
---|
65 | out depotCapacities, out customerDemands, out depotCosts,
|
---|
66 | out vehicleCapacity, out vehicleCost);
|
---|
67 |
|
---|
68 | var flp = FlpParameter.Value;
|
---|
69 | flp.CustomerDemandsParameter.Value = new DoubleArray(customerDemands);
|
---|
70 | flp.DeliveryCostsParameter.Value = new DoubleMatrix(LrpUtils.GetFlpDeliveryCosts(depotCoordinates, customerCoordinates, distanceType));
|
---|
71 | flp.DepotCapacitiesParameter.Value = new DoubleArray(depotCapacities);
|
---|
72 | flp.Encoding.Length = nrOfCustomers;
|
---|
73 | flp.OpeningCostsParameter.Value = new DoubleArray(depotCosts);
|
---|
74 |
|
---|
75 | var vrpInstance = (MDCVRPProblemInstance)VrpParameter.Value.ProblemInstance;
|
---|
76 | vrpInstance.Demand = new DoubleArray(customerDemands);
|
---|
77 | vrpInstance.FleetUsageFactor.Value = vehicleCost;
|
---|
78 | vrpInstance.OverloadPenalty.Value = vehicleCost * 1000.0;
|
---|
79 |
|
---|
80 | var crossover = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionCrossover>().Single(x => x.Name == "MultiVRPSolutionCrossover");
|
---|
81 | foreach (var c in crossover.Operators)
|
---|
82 | crossover.Operators.SetItemCheckedState(c, c.Name.StartsWith("Potvin"));
|
---|
83 | var mutator = VrpParameter.Value.OperatorsParameter.Value.OfType<MultiVRPSolutionManipulator>().Single(x => x.Name == "MultiVRPSolutionManipulator");
|
---|
84 | foreach (var m in mutator.Operators)
|
---|
85 | mutator.Operators.SetItemCheckedState(m, Regex.IsMatch(m.Name, @"Potvin(One|Two).*"));
|
---|
86 |
|
---|
87 | Prepare();
|
---|
88 | }
|
---|
89 |
|
---|
90 | public override void Prepare(bool clearRuns = false) {
|
---|
91 | base.Prepare(clearRuns);
|
---|
92 |
|
---|
93 | var metaMsg = MetaSolverOrchestrationPort.PrepareMessage();
|
---|
94 | var msgFlags = OrchestrationMessage.Prepare | OrchestrationMessage.SetEvalHook;
|
---|
95 | if (clearRuns) msgFlags |= OrchestrationMessage.ClearRuns;
|
---|
96 | metaMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(msgFlags);
|
---|
97 | var problem = new MinimizationVariegationProblem<RealVectorEncoding>();
|
---|
98 | problem.Encoding.Length = nrOfDepots;
|
---|
99 | problem.Encoding.Bounds = new DoubleMatrix(new[,] { { -1.0, 1.0 } });
|
---|
100 | metaMsg["Problem"] = problem;
|
---|
101 | MetaSolverOrchestrationPort.SendMessage(metaMsg);
|
---|
102 | }
|
---|
103 |
|
---|
104 | #region MetaSolver Message Handling
|
---|
105 | protected override void MetaSolverEvaluationPortMessage(IMessage message) {
|
---|
106 | var factors = (RealVector)message["RealVector"];
|
---|
107 |
|
---|
108 | var flp = (FacilityLocationProblem)FlpParameter.Value.Clone();
|
---|
109 | var dc = (double[])depotCosts.Clone();
|
---|
110 | for (int i = 0; i < nrOfDepots; i++)
|
---|
111 | dc[i] = dc[i] * factors[i];
|
---|
112 | flp.OpeningCostsParameter.Value = new DoubleArray(dc);
|
---|
113 |
|
---|
114 | var flpMsg = FlpSolverOrchestrationPort.PrepareMessage();
|
---|
115 | flpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Prepare | OrchestrationMessage.ClearRuns | OrchestrationMessage.Start);
|
---|
116 | flpMsg["Problem"] = flp;
|
---|
117 | FlpSolverOrchestrationPort.SendMessage(flpMsg);
|
---|
118 | cts.Token.ThrowIfCancellationRequested();
|
---|
119 |
|
---|
120 | var flpResults = (ResultCollection)flpMsg["Results"];
|
---|
121 | var bestFlpSolution = (IntegerVector)flpResults["Best Solution"].Value;
|
---|
122 | var flpSolution = FlpParameter.Value.GetSolution(bestFlpSolution);
|
---|
123 |
|
---|
124 | var depots = new HashSet<int>(bestFlpSolution).OrderBy(x => x).ToArray();
|
---|
125 | var customers = Enumerable.Range(0, bestFlpSolution.Length).ToArray();
|
---|
126 |
|
---|
127 | var vrp = (VehicleRoutingProblem)VrpParameter.Value.Clone();
|
---|
128 | var vrpInstance = (MDCVRPProblemInstance)vrp.ProblemInstance;
|
---|
129 | var coordinates = LrpUtils.GetVrpCoordinates(depotCoordinates, customerCoordinates, depots, customers);
|
---|
130 | var distances = LrpUtils.GetVrpDistances(coordinates, distanceType);
|
---|
131 |
|
---|
132 | var capacities = new Dictionary<int, double[]>();
|
---|
133 | for (int i = 0; i < depots.Length; i++) {
|
---|
134 | double depotCapacity = depotCapacities[depots[i]];
|
---|
135 | double nrOfVehicles = depotCapacity / vehicleCapacity;
|
---|
136 | int nrOfTotalVehicles = (int)Math.Ceiling(nrOfVehicles);
|
---|
137 | int nrOfFullVehicles = (int)Math.Floor(nrOfVehicles);
|
---|
138 | double[] vehicleCapacities = Enumerable.Repeat(vehicleCapacity, nrOfTotalVehicles).ToArray();
|
---|
139 | if (nrOfFullVehicles < nrOfTotalVehicles)
|
---|
140 | vehicleCapacities[nrOfTotalVehicles - 1] = depotCapacity - nrOfFullVehicles * vehicleCapacity;
|
---|
141 | capacities.Add(i, vehicleCapacities);
|
---|
142 | }
|
---|
143 |
|
---|
144 | vrpInstance.Capacity = new DoubleArray(capacities.OrderBy(x => x.Key).SelectMany(x => x.Value).ToArray());
|
---|
145 | vrpInstance.Coordinates = new DoubleMatrix(coordinates);
|
---|
146 | vrpInstance.Depots.Value = depots.Length;
|
---|
147 | vrpInstance.DistanceMatrix = new DoubleMatrix(distances);
|
---|
148 | vrpInstance.VehicleDepotAssignment = new IntArray(capacities.OrderBy(x => x.Key).SelectMany((x, i) => Enumerable.Repeat(i, x.Value.Length)).ToArray());
|
---|
149 | vrpInstance.Vehicles.Value = vrpInstance.VehicleDepotAssignment.Length;
|
---|
150 |
|
---|
151 | var vrpMsg = VrpSolverOrchestrationPort.PrepareMessage();
|
---|
152 | vrpMsg["OrchestrationMessage"] = new EnumValue<OrchestrationMessage>(OrchestrationMessage.Prepare | OrchestrationMessage.ClearRuns | OrchestrationMessage.Start);
|
---|
153 | vrpMsg["Problem"] = vrp;
|
---|
154 | VrpSolverOrchestrationPort.SendMessage(vrpMsg);
|
---|
155 | cts.Token.ThrowIfCancellationRequested();
|
---|
156 |
|
---|
157 | var vrpResults = (ResultCollection)vrpMsg["Results"];
|
---|
158 | IResult bestVrpSolutionResult;
|
---|
159 | if (!vrpResults.TryGetValue("Best valid VRP Solution", out bestVrpSolutionResult)
|
---|
160 | && !vrpResults.TryGetValue("Best VRP Solution", out bestVrpSolutionResult)) {
|
---|
161 | // no best solution found ... throw?
|
---|
162 | }
|
---|
163 | var vrpSolution = (VRPSolution)bestVrpSolutionResult.Value.Clone();
|
---|
164 |
|
---|
165 | #region Analyze
|
---|
166 | double objectiveValue = LrpUtils.Evaluate(flpSolution, new[] { vrpSolution });
|
---|
167 | bool[] usedDepots = new bool[depots.Length];
|
---|
168 | foreach (var tour in vrpSolution.Solution.GetTours()) {
|
---|
169 | int tourIdx = vrpSolution.Solution.GetTourIndex(tour);
|
---|
170 | int vehicleIdx = vrpSolution.Solution.GetVehicleAssignment(tourIdx);
|
---|
171 | int depotIdx = vrpInstance.VehicleDepotAssignment[vehicleIdx];
|
---|
172 | usedDepots[depotIdx] = true;
|
---|
173 | }
|
---|
174 | for (int i = 0; i < usedDepots.Length; i++)
|
---|
175 | if (!usedDepots[i]) objectiveValue -= flpSolution.OpeningCosts[depots[i]];
|
---|
176 | ((DoubleValue)message["Quality"]).Value = objectiveValue;
|
---|
177 |
|
---|
178 | IResult bestQuality;
|
---|
179 | if (!Results.TryGetValue("Best LRP Quality", out bestQuality)) {
|
---|
180 | Results.Add(new Result("Best LRP Quality", new DoubleValue(objectiveValue)));
|
---|
181 | Results.Add(new Result("Best FLP Solution", flpSolution));
|
---|
182 | Results.Add(new Result("Best VRP Solution", vrpSolution));
|
---|
183 | } else if (objectiveValue < ((DoubleValue)bestQuality.Value).Value) {
|
---|
184 | ((DoubleValue)bestQuality.Value).Value = objectiveValue;
|
---|
185 | Results["Best FLP Solution"].Value = flpSolution;
|
---|
186 | Results["Best VRP Solution"].Value = vrpSolution;
|
---|
187 | }
|
---|
188 | #endregion
|
---|
189 | }
|
---|
190 | #endregion
|
---|
191 | }
|
---|
192 | }
|
---|