Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Alba/Creators/AlbaPushForwardInsertionCreator.cs @ 3938

Last change on this file since 3938 was 3938, checked in by svonolfe, 14 years ago

Added CVRP implementation using the Alba encoding (#1039)

File size: 11.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 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
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Operators;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Parameters;
30using HeuristicLab.Encodings.PermutationEncoding;
31using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
32using HeuristicLab.Common;
33using HeuristicLab.Optimization;
34
35namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
36  [Item("AlbaPushForwardCreator", "An operator which creates a new alba VRP representation using the push forward insertion heuristic.")]
37  [StorableClass]
38  public sealed class AlbaPushForwardCreator : VRPCreator, IStochasticOperator {
39    #region IStochasticOperator Members
40    public ILookupParameter<IRandom> RandomParameter {
41      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
42    }
43    #endregion
44
45    public IValueParameter<DoubleValue> Alpha {
46      get { return (IValueParameter<DoubleValue>)Parameters["Alpha"]; }
47    }
48    public IValueParameter<DoubleValue> AlphaVariance {
49      get { return (IValueParameter<DoubleValue>)Parameters["AlphaVariance"]; }
50    }
51    public IValueParameter<DoubleValue> Beta {
52      get { return (IValueParameter<DoubleValue>)Parameters["Beta"]; }
53    }
54    public IValueParameter<DoubleValue> BetaVariance {
55      get { return (IValueParameter<DoubleValue>)Parameters["BetaVariance"]; }
56    }
57    public IValueParameter<DoubleValue> Gamma {
58      get { return (IValueParameter<DoubleValue>)Parameters["Gamma"]; }
59    }
60    public IValueParameter<DoubleValue> GammaVariance {
61      get { return (IValueParameter<DoubleValue>)Parameters["GammaVariance"]; }
62    }
63
64    public AlbaPushForwardCreator()
65      : base() {
66      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
67      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", "The alpha value.", new DoubleValue(0.7)));
68      Parameters.Add(new ValueParameter<DoubleValue>("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
69      Parameters.Add(new ValueParameter<DoubleValue>("Beta", "The beta value.", new DoubleValue(0.1)));
70      Parameters.Add(new ValueParameter<DoubleValue>("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
71      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", "The gamma value.", new DoubleValue(0.2)));
72      Parameters.Add(new ValueParameter<DoubleValue>("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
73    }
74
75    public override IOperation Apply() {
76      VRPSolutionParameter.ActualValue = new AlbaEncoding(CreateSolution(), CitiesParameter.ActualValue.Value);
77
78      return base.Apply();
79    }
80
81    // use the Box-Mueller transform in the polar form to generate a N(0,1) random variable out of two uniformly distributed random variables
82    private double Gauss(IRandom random) {
83      double u = 0.0, v = 0.0, s = 0.0;
84      do {
85        u = (random.NextDouble() * 2) - 1;
86        v = (random.NextDouble() * 2) - 1;
87        s = Math.Sqrt(u * u + v * v);
88      } while (s < Double.Epsilon || s > 1);
89      return u * Math.Sqrt((-2.0 * Math.Log(s)) / s);
90    }
91
92    private double N(double mu, double sigma, IRandom random) {
93      return mu + (sigma * Gauss(random)); // transform the random variable sampled from N(0,1) to N(mu,sigma)
94    }
95
96    private double CalculateDistance(int start, int end) {
97      double distance = 0.0;
98      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
99
100      distance =
101          Math.Sqrt(
102            Math.Pow(coordinates[start, 0] - coordinates[end, 0], 2) +
103            Math.Pow(coordinates[start, 1] - coordinates[end, 1], 2));
104
105      return distance;
106    }
107
108    private DoubleMatrix CreateDistanceMatrix() {
109      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
110      DoubleMatrix distanceMatrix = new DoubleMatrix(coordinates.Rows, coordinates.Rows);
111
112      for (int i = 0; i < distanceMatrix.Rows; i++) {
113        for (int j = i; j < distanceMatrix.Columns; j++) {
114          double distance = CalculateDistance(i, j);
115
116          distanceMatrix[i, j] = distance;
117          distanceMatrix[j, i] = distance;
118        }
119      }
120
121      return distanceMatrix;
122    }
123
124    private double Distance(int start, int end) {
125      double distance = 0.0;
126
127      if (UseDistanceMatrixParameter.ActualValue.Value) {
128        if (DistanceMatrixParameter.ActualValue == null) {
129          DistanceMatrixParameter.ActualValue = CreateDistanceMatrix();
130        }
131
132        distance = DistanceMatrixParameter.ActualValue[start, end];
133      } else {
134        distance = CalculateDistance(start, end);
135      }
136
137      return distance;
138    }
139
140    private double TravelDistance(List<int> route, int begin) {
141      double distance = 0;
142      for (int i = begin; i < route.Count - 1 && (i == begin || route[i] != 0); i++) {
143        distance += Distance(route[i], route[i + 1]);
144      }
145      return distance;
146    }
147
148    private bool SubrouteConstraintsOK(List<int> route, int begin) {
149      double t = 0.0, o = 0.0;
150      for (int i = begin + 1; i < route.Count; i++) {
151        t += Distance(route[i - 1], route[i]);
152        if (route[i] == 0) return (t < DueTimeParameter.ActualValue[0]); // violation on capacity constraint is handled below
153        else {
154          if (t > DueTimeParameter.ActualValue[route[i]]) return false;
155          t = Math.Max(ReadyTimeParameter.ActualValue[route[i]], t);
156          t += ServiceTimeParameter.ActualValue[route[i]];
157          o += DemandParameter.ActualValue[route[i]];
158          if (o > CapacityParameter.ActualValue.Value) return false; // premature exit on capacity constraint violation
159        }
160      }
161      return true;
162    }
163
164    private bool SubrouteTardinessOK(List<int> route, int begin) {
165      double t = 0.0;
166      for (int i = begin + 1; i < route.Count; i++) {
167        t += Distance(route[i - 1], route[i]);
168        if (route[i] == 0) {
169          if (t < DueTimeParameter.ActualValue[0]) return true;
170          else return false;
171        } else {
172          if (t > DueTimeParameter.ActualValue[route[i]]) return false;
173          t = Math.Max(ReadyTimeParameter.ActualValue[route[i]], t);
174          t += ServiceTimeParameter.ActualValue[route[i]];
175        }
176      }
177      return true;
178    }
179
180    private bool SubrouteLoadOK(List<int> route, int begin) {
181      double o = 0.0;
182      for (int i = begin + 1; i < route.Count; i++) {
183        if (route[i] == 0) return (o < CapacityParameter.ActualValue.Value);
184        else {
185          o += DemandParameter.ActualValue[route[i]];
186        }
187      }
188      return (o < CapacityParameter.ActualValue.Value);
189    }
190
191    private Permutation CreateSolution() {
192      double alpha, beta, gamma;
193      alpha = N(Alpha.Value.Value, Math.Sqrt(AlphaVariance.Value.Value), RandomParameter.ActualValue);
194      beta = N(Beta.Value.Value, Math.Sqrt(BetaVariance.Value.Value), RandomParameter.ActualValue);
195      gamma = N(Gamma.Value.Value, Math.Sqrt(GammaVariance.Value.Value), RandomParameter.ActualValue);
196
197      double x0 = CoordinatesParameter.ActualValue[0,0];
198      double y0 = CoordinatesParameter.ActualValue[0,1];
199      double distance = 0;
200      double cost = 0;
201      double minimumCost = double.MaxValue;
202      List<int> unroutedList = new List<int>();
203      List<double> costList = new List<double>();
204      int index;
205      int indexOfMinimumCost = -1;
206      int indexOfCustomer = -1;
207
208      /*-----------------------------------------------------------------------------
209       * generate cost list
210       *-----------------------------------------------------------------------------
211       */
212      for (int i = 1; i <= CitiesParameter.ActualValue.Value; i++) {
213        distance = Distance(i, 0);
214        if (CoordinatesParameter.ActualValue[i,0] < x0) distance = -distance;
215        cost = -alpha * distance + // distance 0 <-> City[i]
216                 beta * (DueTimeParameter.ActualValue[i]) + // latest arrival time
217                 gamma * (Math.Asin((CoordinatesParameter.ActualValue[i,1] - y0) / distance) / 360 * distance); // polar angle
218
219        index = 0;
220        while (index < costList.Count && costList[index] < cost) index++;
221        costList.Insert(index, cost);
222        unroutedList.Insert(index, i);
223      }
224
225      /*------------------------------------------------------------------------------
226       * route customers according to cost list
227       *------------------------------------------------------------------------------
228       */
229      int routeIndex = 0;
230      int currentRoute = 0;
231      int c;
232      int customer = -1;
233      int subTourCount = 1;
234      List<int> route = new List<int>(CitiesParameter.ActualValue.Value + VehiclesParameter.ActualValue.Value - 1);
235      minimumCost = double.MaxValue;
236      indexOfMinimumCost = -1;
237      route.Add(0);
238      route.Add(0);
239      route.Insert(1, unroutedList[0]);
240      unroutedList.RemoveAt(0);
241      currentRoute = routeIndex;
242      routeIndex++;
243
244      do {
245        for (c = 0; c < unroutedList.Count; c++) {
246          for (int i = currentRoute + 1; i < route.Count; i++) {
247            route.Insert(i, (int)unroutedList[c]);
248            if (route[currentRoute] != 0) { throw new Exception("currentRoute not depot"); }
249            cost = TravelDistance(route, currentRoute);
250            if (cost < minimumCost && SubrouteConstraintsOK(route, currentRoute)) {
251              minimumCost = cost;
252              indexOfMinimumCost = i;
253              customer = (int)unroutedList[c];
254              indexOfCustomer = c;
255            }
256            route.RemoveAt(i);
257          }
258        }
259        // insert customer if found
260        if (indexOfMinimumCost != -1) {
261          route.Insert(indexOfMinimumCost, customer);
262          routeIndex++;
263          unroutedList.RemoveAt(indexOfCustomer);
264          costList.RemoveAt(indexOfCustomer);
265        } else { // no feasible customer found
266          routeIndex++;
267          route.Insert(routeIndex, 0);
268          currentRoute = routeIndex;
269          route.Insert(route.Count - 1, (int)unroutedList[0]);
270          unroutedList.RemoveAt(0);
271          routeIndex++;
272          subTourCount++;
273        }
274        // reset minimum   
275        minimumCost = double.MaxValue;
276        indexOfMinimumCost = -1;
277        indexOfCustomer = -1;
278        customer = -1;
279      } while (unroutedList.Count > 0);
280      while (route.Count < CitiesParameter.ActualValue.Value + VehiclesParameter.ActualValue.Value - 1)
281        route.Add(0);
282
283      int vehicle = CitiesParameter.ActualValue.Value;
284      for (int i = 0; i < route.Count; i++) {
285        if (route[i] == 0) {
286          route[i] = vehicle;
287          vehicle++;
288        } else {
289          route[i] = route[i] - 1;
290        }
291      }
292
293      return new Permutation(PermutationTypes.RelativeDirected, route.ToArray());
294    }
295  }
296}
Note: See TracBrowser for help on using the repository browser.