Free cookie consent management tool by TermsFeed Policy Generator

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

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

Fixed problem in the PFIH (#1177)

File size: 9.6 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;
33
34namespace HeuristicLab.Problems.VehicleRouting.Encodings.Alba {
35  [Item("PushForwardCreator", "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.")]
36  [StorableClass]
37  public sealed class PushForwardCreator : DefaultRepresentationCreator, IStochasticOperator, ITimeWindowedOperator {
38    #region IStochasticOperator Members
39    public ILookupParameter<IRandom> RandomParameter {
40      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
41    }
42    #endregion
43
44    public IValueParameter<DoubleValue> Alpha {
45      get { return (IValueParameter<DoubleValue>)Parameters["Alpha"]; }
46    }
47    public IValueParameter<DoubleValue> AlphaVariance {
48      get { return (IValueParameter<DoubleValue>)Parameters["AlphaVariance"]; }
49    }
50    public IValueParameter<DoubleValue> Beta {
51      get { return (IValueParameter<DoubleValue>)Parameters["Beta"]; }
52    }
53    public IValueParameter<DoubleValue> BetaVariance {
54      get { return (IValueParameter<DoubleValue>)Parameters["BetaVariance"]; }
55    }
56    public IValueParameter<DoubleValue> Gamma {
57      get { return (IValueParameter<DoubleValue>)Parameters["Gamma"]; }
58    }
59    public IValueParameter<DoubleValue> GammaVariance {
60      get { return (IValueParameter<DoubleValue>)Parameters["GammaVariance"]; }
61    }
62
63    [StorableConstructor]
64    private PushForwardCreator(bool deserializing) : base(deserializing) { }
65
66    public PushForwardCreator()
67      : base() {
68      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator."));
69      Parameters.Add(new ValueParameter<DoubleValue>("Alpha", "The alpha value.", new DoubleValue(0.7)));
70      Parameters.Add(new ValueParameter<DoubleValue>("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
71      Parameters.Add(new ValueParameter<DoubleValue>("Beta", "The beta value.", new DoubleValue(0.1)));
72      Parameters.Add(new ValueParameter<DoubleValue>("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
73      Parameters.Add(new ValueParameter<DoubleValue>("Gamma", "The gamma value.", new DoubleValue(0.2)));
74      Parameters.Add(new ValueParameter<DoubleValue>("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
75    }
76
77    public override IDeepCloneable Clone(Cloner cloner) {
78      return new PushForwardCreator(this, cloner);
79    }
80
81    private PushForwardCreator(PushForwardCreator original, Cloner cloner)
82      : base(original, cloner) {
83    }
84
85    // use the Box-Mueller transform in the polar form to generate a N(0,1) random variable out of two uniformly distributed random variables
86    private static double Gauss(IRandom random) {
87      double u = 0.0, v = 0.0, s = 0.0;
88      do {
89        u = (random.NextDouble() * 2) - 1;
90        v = (random.NextDouble() * 2) - 1;
91        s = Math.Sqrt(u * u + v * v);
92      } while (s < Double.Epsilon || s > 1);
93      return u * Math.Sqrt((-2.0 * Math.Log(s)) / s);
94    }
95
96    private static double N(double mu, double sigma, IRandom random) {
97      return mu + (sigma * Gauss(random)); // transform the random variable sampled from N(0,1) to N(mu,sigma)
98    }
99
100    private static double Distance(IVRPProblemInstance problemInstance, int start, int end) {
101      return problemInstance.GetDistance(start, end);
102    }
103
104    private static double TravelDistance(IVRPProblemInstance problemInstance, List<int> route, int begin) {
105      double distance = 0;
106      for (int i = begin; i < route.Count - 1 && (i == begin || route[i] != 0); i++) {
107        distance += Distance(problemInstance, route[i], route[i + 1]);
108      }
109      return distance;
110    }
111
112    private static bool SubrouteConstraintsOK(IVRPProblemInstance problemInstance, List<int> route, int begin) {
113      AlbaEncoding solution = AlbaEncoding.ConvertFrom(route, problemInstance);
114
115      return problemInstance.Feasible(solution);
116    }
117
118    public static List<int> CreateSolution(IVRPProblemInstance problemInstance, IRandom random,
119      double alphaValue = 0.7, double betaValue = 0.1, double gammaValue = 0.2,
120      double alphaVariance = 0.5, double betaVariance = 0.07, double gammaVariance = 0.14) {
121      double alpha, beta, gamma;
122      alpha = N(alphaValue, Math.Sqrt(alphaVariance), random);
123      beta = N(betaValue, Math.Sqrt(betaVariance), random);
124      gamma = N(gammaValue, Math.Sqrt(gammaVariance), random);
125
126      double x0 = problemInstance.Coordinates[0, 0];
127      double y0 = problemInstance.Coordinates[0, 1];
128      double distance = 0;
129      double cost = 0;
130      double minimumCost = double.MaxValue;
131      List<int> unroutedList = new List<int>();
132      List<double> costList = new List<double>();
133      int index;
134      int indexOfMinimumCost = -1;
135      int indexOfCustomer = -1;
136
137      /*-----------------------------------------------------------------------------
138       * generate cost list
139       *-----------------------------------------------------------------------------
140       */
141      for (int i = 1; i <= problemInstance.Cities.Value; i++) {
142        distance = Distance(problemInstance, i, 0);
143        if (problemInstance.Coordinates[i, 0] < x0) distance = -distance;
144
145        cost = -alpha * distance + // distance 0 <-> City[i]
146               beta * (problemInstance as ITimeWindowedProblemInstance).DueTime[i] + // latest arrival time
147               gamma * (Math.Asin((problemInstance.Coordinates[i, 1] - y0) / distance) / 360 * distance); // polar angle
148
149        index = 0;
150        while (index < costList.Count && costList[index] < cost) index++;
151        costList.Insert(index, cost);
152        unroutedList.Insert(index, i);
153      }
154
155      /*------------------------------------------------------------------------------
156       * route customers according to cost list
157       *------------------------------------------------------------------------------
158       */
159      int routeIndex = 0;
160      int currentRoute = 0;
161      int c;
162      int customer = -1;
163      int subTourCount = 1;
164      List<int> route = new List<int>(problemInstance.Cities.Value + problemInstance.Vehicles.Value - 1);
165      minimumCost = double.MaxValue;
166      indexOfMinimumCost = -1;
167      route.Add(0);
168      route.Add(0);
169      route.Insert(1, unroutedList[0]);
170      unroutedList.RemoveAt(0);
171      currentRoute = routeIndex;
172      routeIndex++;
173
174      while (unroutedList.Count > 0) {
175        for (c = 0; c < unroutedList.Count; c++) {
176          for (int i = currentRoute + 1; i < route.Count; i++) {
177            route.Insert(i, (int)unroutedList[c]);
178            if (route[currentRoute] != 0) { throw new Exception("currentRoute not depot"); }
179            cost = TravelDistance(problemInstance, route, currentRoute);
180            if (cost < minimumCost && SubrouteConstraintsOK(problemInstance, route, currentRoute)) {
181              minimumCost = cost;
182              indexOfMinimumCost = i;
183              customer = (int)unroutedList[c];
184              indexOfCustomer = c;
185            }
186            route.RemoveAt(i);
187          }
188        }
189        // insert customer if found
190        if (indexOfMinimumCost != -1) {
191          route.Insert(indexOfMinimumCost, customer);
192          routeIndex++;
193          unroutedList.RemoveAt(indexOfCustomer);
194          costList.RemoveAt(indexOfCustomer);
195        } else { // no feasible customer found
196          routeIndex++;
197          route.Insert(routeIndex, 0);
198          currentRoute = routeIndex;
199          route.Insert(route.Count - 1, (int)unroutedList[0]);
200          unroutedList.RemoveAt(0);
201          routeIndex++;
202          subTourCount++;
203        }
204        // reset minimum   
205        minimumCost = double.MaxValue;
206        indexOfMinimumCost = -1;
207        indexOfCustomer = -1;
208        customer = -1;
209      }
210      while (route.Count < problemInstance.Cities.Value + problemInstance.Vehicles.Value)
211        route.Add(0);
212
213      return route;
214    }
215
216    protected override List<int> CreateSolution() {
217      return CreateSolution(ProblemInstance, RandomParameter.ActualValue,
218        Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
219        AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
220    }
221  }
222}
Note: See TracBrowser for help on using the repository browser.