Free cookie consent management tool by TermsFeed Policy Generator

source: branches/VRP/HeuristicLab.Problems.VehicleRouting/3.4/Encodings/Alba/Creators/PushForwardInsertionCreator.cs @ 6759

Last change on this file since 6759 was 6759, checked in by svonolfe, 13 years ago

Adapted creators to support pickup and delivery constraints (#1177)

File size: 10.9 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 HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.Encodings.PermutationEncoding;
27using HeuristicLab.Optimization;
28using HeuristicLab.Parameters;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Problems.VehicleRouting.Variants;
31using HeuristicLab.Common;
32using HeuristicLab.Problems.VehicleRouting.Interfaces;
33using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
34
35namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
36  [Item("PushForwardInsertionCreator", "The push forward insertion heuristic.  It is implemented as described in Sam, and Thangiah, R. (1999). A Hybrid Genetic Algorithms, Simulated Annealing and Tabu Search Heuristic for Vehicle Routing Problems with Time Windows. Practical Handbook of Genetic Algorithms, Volume III, pp 347–381.")]
37  [StorableClass]
38  public sealed class PushForwardInsertionCreator : DefaultRepresentationCreator, IStochasticOperator, ITimeWindowedOperator {
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    [StorableConstructor]
65    private PushForwardInsertionCreator(bool deserializing) : base(deserializing) { }
66
67    public PushForwardInsertionCreator()
68      : base() {
69      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
70      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", "The alpha value.", new DoubleValue(0.7)));
71      Parameters.Add(new ValueParameter<DoubleValue>("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
72      Parameters.Add(new ValueParameter<DoubleValue>("Beta", "The beta value.", new DoubleValue(0.1)));
73      Parameters.Add(new ValueParameter<DoubleValue>("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
74      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", "The gamma value.", new DoubleValue(0.2)));
75      Parameters.Add(new ValueParameter<DoubleValue>("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
76    }
77
78    public override IDeepCloneable Clone(Cloner cloner) {
79      return new PushForwardInsertionCreator(this, cloner);
80    }
81
82    private PushForwardInsertionCreator(PushForwardInsertionCreator original, Cloner cloner)
83      : base(original, cloner) {
84    }
85
86    // use the Box-Mueller transform in the polar form to generate a N(0,1) random variable out of two uniformly distributed random variables
87    private static double Gauss(IRandom random) {
88      double u = 0.0, v = 0.0, s = 0.0;
89      do {
90        u = (random.NextDouble() * 2) - 1;
91        v = (random.NextDouble() * 2) - 1;
92        s = Math.Sqrt(u * u + v * v);
93      } while (s < Double.Epsilon || s > 1);
94      return u * Math.Sqrt((-2.0 * Math.Log(s)) / s);
95    }
96
97    private static double N(double mu, double sigma, IRandom random) {
98      return mu + (sigma * Gauss(random)); // transform the random variable sampled from N(0,1) to N(mu,sigma)
99    }
100
101    private static double Distance(IVRPProblemInstance problemInstance, int start, int end) {
102      return problemInstance.GetDistance(start, end);
103    }
104
105    public static List<int> CreateSolution(IVRPProblemInstance problemInstance, IRandom random,
106      double alphaValue = 0.7, double betaValue = 0.1, double gammaValue = 0.2,
107      double alphaVariance = 0.5, double betaVariance = 0.07, double gammaVariance = 0.14) {
108      double alpha, beta, gamma;
109      alpha = N(alphaValue, Math.Sqrt(alphaVariance), random);
110      beta = N(betaValue, Math.Sqrt(betaVariance), random);
111      gamma = N(gammaValue, Math.Sqrt(gammaVariance), random);
112
113      double x0 = problemInstance.Coordinates[0, 0];
114      double y0 = problemInstance.Coordinates[0, 1];
115      double distance = 0;
116      double cost = 0;
117      double minimumCost = double.MaxValue;
118      List<int> unroutedList = new List<int>();
119      List<double> costList = new List<double>();
120      int index;
121      int indexOfMinimumCost = -1;
122      int indexOfMinimumCost2 = -1;
123      int indexOfCustomer = -1;
124
125      IPickupAndDeliveryProblemInstance pdp = problemInstance as IPickupAndDeliveryProblemInstance;
126
127      /*-----------------------------------------------------------------------------
128       * generate cost list
129       *-----------------------------------------------------------------------------
130       */
131      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
132        //only insert sources
133        if (pdp == null || problemInstance.Demand[i] >= 0) {
134          distance = Distance(problemInstance, i, 0);
135          if (problemInstance.Coordinates[i, 0] < x0) distance = -distance;
136
137          cost = -alpha * distance + // distance 0 <-> City[i]
138                 beta * (problemInstance as ITimeWindowedProblemInstance).DueTime[i] + // latest arrival time
139                 gamma * (Math.Asin((problemInstance.Coordinates[i, 1] - y0) / distance) / 360 * distance); // polar angle
140
141          index = 0;
142          while (index < costList.Count && costList[index] < cost) index++;
143
144          costList.Insert(index, cost);
145
146          unroutedList.Insert(index, i);
147        }
148      }
149
150      /*------------------------------------------------------------------------------
151       * route customers according to cost list
152       *------------------------------------------------------------------------------
153       */
154      int routeIndex = 0;
155      int currentRoute = 0;
156      int c;
157      int customer = -1;
158      int subTourCount = 1;
159      List<int> route = new List<int>(problemInstance.Cities.Value + problemInstance.Vehicles.Value - 1);
160      currentRoute = routeIndex;
161      minimumCost = double.MaxValue;
162      indexOfMinimumCost = -1;
163      indexOfMinimumCost2 = -1;
164      route.Add(0);
165      route.Add(0);
166
167      if (pdp != null) {
168        route.Insert(1, pdp.PickupDeliveryLocation[unroutedList[0]]);
169        routeIndex++;
170      }
171
172      route.Insert(1, unroutedList[0]);
173      routeIndex++;
174
175      unroutedList.RemoveAt(0);
176
177      while (unroutedList.Count > 0) {
178        for (c = 0; c < unroutedList.Count; c++) {
179          Tour tour = new Tour();
180          tour.Stops.AddRange(route.GetRange(currentRoute + 1, route.Count - (currentRoute + 1) - 1));
181          VRPEvaluation eval = problemInstance.Evaluate(tour);
182          double originalCosts = eval.Quality;
183
184          for (int i = currentRoute + 1; i < route.Count; i++) {
185            route.Insert(i, (int)unroutedList[c]);
186            tour = new Tour();
187            tour.Stops.AddRange(route.GetRange(currentRoute+1, route.Count - (currentRoute+1) - 1));
188            eval = problemInstance.Evaluate(tour);
189            double tourCost = eval.Quality - originalCosts;
190
191            if (pdp != null) {
192              for (int j = i - (currentRoute); j <= tour.Stops.Count; j++) {
193                bool feasible;
194                cost = tourCost +
195                  problemInstance.GetInsertionCosts(eval, pdp.PickupDeliveryLocation[unroutedList[c]], 0, j, out feasible);
196                if (cost < minimumCost && feasible) {
197                  minimumCost = cost;
198                  indexOfMinimumCost = i;
199                  indexOfMinimumCost2 = j + currentRoute + 1;
200                  customer = (int)unroutedList[c];
201                  indexOfCustomer = c;
202                }
203              }
204            } else {
205              cost = tourCost;
206              bool feasible = problemInstance.Feasible(eval);
207              if (cost < minimumCost && feasible) {
208                minimumCost = cost;
209                indexOfMinimumCost = i;
210                customer = (int)unroutedList[c];
211                indexOfCustomer = c;
212              }
213            }
214            route.RemoveAt(i);
215          }
216        }
217        // insert customer if found
218        if (indexOfMinimumCost != -1) {
219          route.Insert(indexOfMinimumCost, customer);
220          routeIndex++;
221
222          if (pdp != null) {
223            route.Insert(indexOfMinimumCost2, pdp.PickupDeliveryLocation[customer]);
224            routeIndex++;
225          }
226
227          unroutedList.RemoveAt(indexOfCustomer);
228          costList.RemoveAt(indexOfCustomer);
229        } else { // no feasible customer found
230          routeIndex++;
231          route.Insert(routeIndex, 0);
232          currentRoute = routeIndex;
233          route.Insert(route.Count - 1, (int)unroutedList[0]);
234          routeIndex++;
235          if (pdp != null) {
236            route.Insert(route.Count - 1, (int)pdp.PickupDeliveryLocation[unroutedList[0]]);
237            routeIndex++;
238          }
239          unroutedList.RemoveAt(0);
240          subTourCount++;
241        }
242        // reset minimum   
243        minimumCost = double.MaxValue;
244        indexOfMinimumCost = -1;
245        indexOfMinimumCost2 = -1;
246        indexOfCustomer = -1;
247        customer = -1;
248      }
249      while (route.Count < problemInstance.Cities.Value + problemInstance.Vehicles.Value)
250        route.Add(0);
251
252      return route;
253    }
254
255    protected override List<int> CreateSolution() {
256      return CreateSolution(ProblemInstance, RandomParameter.ActualValue,
257        Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
258        AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
259    }
260  }
261}
Note: See TracBrowser for help on using the repository browser.