Free cookie consent management tool by TermsFeed Policy Generator

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

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

Merged relevant changes from the trunk into the branch (cloning,...) (#1177)

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