Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/General/PushForwardInsertionCreator.cs @ 4150

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

Refactored VRP, added Potvin encoding (WIP) (#1039)

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