Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
07/17/11 22:51:11 (13 years ago)
Author:
abeham
Message:

#1541

  • updated to latest trunk version
Location:
branches/QAPAlgorithms
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • branches/QAPAlgorithms

  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting

  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Crossovers/PotvinCrossover.cs

    r5445 r6569  
    2626using HeuristicLab.Parameters;
    2727using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     28using HeuristicLab.Data;
    2829
    2930namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    3334    public ILookupParameter<IRandom> RandomParameter {
    3435      get { return (LookupParameter<IRandom>)Parameters["Random"]; }
     36    }
     37
     38    public IValueParameter<BoolValue> AllowInfeasibleSolutions {
     39      get { return (IValueParameter<BoolValue>)Parameters["AllowInfeasibleSolutions"]; }
     40    }
     41
     42    [StorableHook(HookType.AfterDeserialization)]
     43    private void AfterDeserialization() {
     44      // BackwardsCompatibility3.3
     45      #region Backwards compatible code (remove with 3.4)
     46      if (!Parameters.ContainsKey("AllowInfeasibleSolutions")) {
     47        Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
     48      }
     49      #endregion
    3550    }
    3651
     
    4358    public PotvinCrossover() {
    4459      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
     60      Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
    4561    }
    4662
    4763    protected abstract PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2);
    4864
    49     protected bool FindInsertionPlace(PotvinEncoding individual, int city, out int route, out int place) {
     65    protected static bool FindInsertionPlace(PotvinEncoding individual, int city,
     66      DoubleArray dueTime, DoubleArray serviceTime, DoubleArray readyTime, DoubleArray demand,
     67      DoubleValue capacity, DistanceMatrix distMatrix, bool allowInfeasible,
     68      out int route, out int place) {
    5069      return individual.FindInsertionPlace(
    51         DueTimeParameter.ActualValue, ServiceTimeParameter.ActualValue, ReadyTimeParameter.ActualValue,
    52         DemandParameter.ActualValue, CapacityParameter.ActualValue, CoordinatesParameter.ActualValue,
    53         DistanceMatrixParameter, UseDistanceMatrixParameter.ActualValue,
    54         city, -1, out route, out place);
     70        dueTime, serviceTime, readyTime,
     71        demand, capacity, distMatrix,
     72        city, -1, allowInfeasible,
     73        out route, out place);
    5574    }
    5675
     
    6887    }
    6988
    70     protected bool Repair(IRandom random, PotvinEncoding solution, Tour newTour) {
     89    protected static bool RouteUnrouted(PotvinEncoding solution, DistanceMatrix distMatrix,
     90      DoubleArray dueTime, DoubleArray readyTime, DoubleArray serviceTime, DoubleArray demand, DoubleValue capacity, bool allowInfeasible) {
     91      bool success = true;
     92      int index = 0;
     93      while (index < solution.Unrouted.Count && success) {
     94        int unrouted = solution.Unrouted[index];
     95
     96        int route, place;
     97        if (FindInsertionPlace(solution, unrouted,
     98          dueTime, serviceTime, readyTime, demand, capacity,
     99          distMatrix, allowInfeasible,
     100          out route, out place)) {
     101          solution.Tours[route].Cities.Insert(place, unrouted);
     102        } else {
     103          success = false;
     104        }
     105
     106        index++;
     107      }
     108
     109      for (int i = 0; i < index; i++)
     110        solution.Unrouted.RemoveAt(0);
     111
     112      return success;
     113    }
     114
     115    protected static bool Repair(IRandom random, PotvinEncoding solution, Tour newTour, DistanceMatrix distmatrix,
     116      DoubleArray dueTime, DoubleArray readyTime, DoubleArray serviceTime, DoubleArray demand, DoubleValue capacity,
     117      bool allowInfeasible) {
    71118      bool success = true;
    72119
     
    104151      }
    105152
     153      if (!allowInfeasible && !newTour.Feasible(
     154        dueTime, serviceTime, readyTime, demand, capacity, distmatrix))
     155        return false;
     156
    106157      //route unrouted vehicles
    107       int index = 0;
    108       while (index < solution.Unrouted.Count && success) {
    109         int unrouted = solution.Unrouted[index];
    110 
    111         int route, place;
    112         if (FindInsertionPlace(solution, unrouted, out route, out place)) {
    113           solution.Tours[route].Cities.Insert(place, unrouted);
    114         } else {
    115           success = false;
    116         }
    117 
    118         index++;
    119       }
    120 
    121       for (int i = 0; i < index; i++)
    122         solution.Unrouted.RemoveAt(0);
     158      success = RouteUnrouted(solution, distmatrix, dueTime, readyTime, serviceTime, demand, capacity, allowInfeasible);
    123159
    124160      return success;
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Crossovers/PotvinRouteBasedCrossover.cs

    r5445 r6569  
    2323using HeuristicLab.Core;
    2424using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     25using HeuristicLab.Data;
    2526
    2627namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    4041
    4142    protected override PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2) {
     43      BoolValue useDistanceMatrix = UseDistanceMatrixParameter.ActualValue;
     44      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
     45      DistanceMatrix distMatrix = VRPUtilities.GetDistanceMatrix(coordinates, DistanceMatrixParameter, useDistanceMatrix);
     46      DoubleArray dueTime = DueTimeParameter.ActualValue;
     47      DoubleArray readyTime = ReadyTimeParameter.ActualValue;
     48      DoubleArray serviceTime = ServiceTimeParameter.ActualValue;
     49      DoubleArray demand = DemandParameter.ActualValue;
     50      DoubleValue capacity = CapacityParameter.ActualValue;
     51
     52      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
     53
    4254      PotvinEncoding child = parent2.Clone() as PotvinEncoding;
    4355
     
    5567          child.Unrouted.Add(city);
    5668
    57       if (Repair(random, child, replacing))
     69      if (Repair(random, child, replacing, distMatrix, dueTime, readyTime, serviceTime, demand, capacity, allowInfeasible) || allowInfeasible)
    5870        return child;
    5971      else {
     
    6173          return parent1.Clone() as PotvinEncoding;
    6274        else
    63           return parent2.Clone() as PotvinEncoding;
     75          return parent2.Clone() as PotvinEncoding;   
    6476      }
    6577    }
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Crossovers/PotvinSequenceBasedCrossover.cs

    r5445 r6569  
    2323using HeuristicLab.Core;
    2424using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     25using HeuristicLab.Data;
    2526
    2627namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    4142
    4243    protected override PotvinEncoding Crossover(IRandom random, PotvinEncoding parent1, PotvinEncoding parent2) {
     44      BoolValue useDistanceMatrix = UseDistanceMatrixParameter.ActualValue;
     45      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
     46      DistanceMatrix distMatrix = VRPUtilities.GetDistanceMatrix(coordinates, DistanceMatrixParameter, useDistanceMatrix);
     47      DoubleArray dueTime = DueTimeParameter.ActualValue;
     48      DoubleArray readyTime = ReadyTimeParameter.ActualValue;
     49      DoubleArray serviceTime = ServiceTimeParameter.ActualValue;
     50      DoubleArray demand = DemandParameter.ActualValue;
     51      DoubleValue capacity = CapacityParameter.ActualValue;
     52
     53      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
     54
    4355      PotvinEncoding child = parent1.Clone() as PotvinEncoding;
    4456      Tour newTour = new Tour();
     
    6981          child.Unrouted.Add(city);
    7082
    71       if (Feasible(newTour) &&
    72           Repair(random, child, newTour)) {
     83      if (Repair(random, child, newTour, distMatrix, dueTime, readyTime, serviceTime, demand, capacity, allowInfeasible) || allowInfeasible) {
    7384        return child;
    7485      } else {
    75         if (random.NextDouble() < 0.5)
     86         if (random.NextDouble() < 0.5)
    7687          return parent1.Clone() as PotvinEncoding;
    7788        else
    78           return parent2.Clone() as PotvinEncoding;
     89          return parent2.Clone() as PotvinEncoding;   
    7990      }
    8091    }
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Manipulators/PotvinLocalSearchManipulator.cs

    r5445 r6569  
    4949
    5050    private bool FindBetterInsertionPlace(
    51       PotvinEncoding individual, int tour, int city, int length,
     51      PotvinEncoding individual, 
     52      DoubleArray dueTime, DoubleArray readyTime, DoubleArray serviceTime, DoubleArray demand,
     53      DoubleValue capacity, DistanceMatrix distMatrix,
     54      int tour, int city, int length,
    5255      out int insertionTour, out int insertionPlace) {
    5356      bool insertionFound = false;
     
    5659
    5760      List<int> toBeDeleted = individual.Tours[tour].Cities.GetRange(city, length);
    58       double distance = GetLength(individual.Tours[tour]);
     61      double distance = individual.Tours[tour].GetLength(distMatrix);
    5962      individual.Tours[tour].Cities.RemoveRange(city, length);
    60       double removalBenefit = distance - GetLength(individual.Tours[tour]);
     63      double removalBenefit = distance - individual.Tours[tour].GetLength(distMatrix);
    6164
    6265      int currentTour = 0;
     
    6467        int currentCity = 0;
    6568        while (currentCity <= individual.Tours[currentTour].Cities.Count && !insertionFound) {
    66           distance = GetLength(individual.Tours[currentTour]);
     69          distance = individual.Tours[currentTour].GetLength(distMatrix);
    6770          individual.Tours[currentTour].Cities.InsertRange(currentCity, toBeDeleted);
    68           if (Feasible(individual.Tours[currentTour])) {
     71          if (individual.Tours[currentTour].Feasible(dueTime, serviceTime, readyTime, demand, capacity, distMatrix)) {
    6972            double lengthIncrease =
    70               GetLength(individual.Tours[currentTour]) - distance;
     73              individual.Tours[currentTour].GetLength(distMatrix) - distance;
    7174            if (removalBenefit > lengthIncrease) {
    7275              insertionTour = currentTour;
     
    8386      }
    8487
    85       individual.Tours[tour].Cities.InsertRange(city, toBeDeleted);
     88      individual.Tours[tour].Cities.InsertRange(city, toBeDeleted); 
    8689
    8790      return insertionFound;
     
    8992
    9093    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
     94      BoolValue useDistanceMatrix = UseDistanceMatrixParameter.ActualValue;
     95      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
     96      DistanceMatrix distMatrix = VRPUtilities.GetDistanceMatrix(coordinates, DistanceMatrixParameter, useDistanceMatrix);
     97      DoubleArray dueTime = DueTimeParameter.ActualValue;
     98      DoubleArray readyTime = ReadyTimeParameter.ActualValue;
     99      DoubleArray serviceTime = ServiceTimeParameter.ActualValue;
     100      DoubleArray demand = DemandParameter.ActualValue;
     101      DoubleValue capacity = CapacityParameter.ActualValue;
     102     
    91103      //only apply to feasible individuals
    92       if (Feasible(individual)) {
     104      bool feasible = true;
     105
     106      foreach (Tour tour in individual.Tours) {
     107        if (!tour.Feasible(dueTime, serviceTime, readyTime, demand, capacity, distMatrix)) {
     108          feasible = false;
     109          break;
     110        }
     111      }
     112
     113      if (feasible) {
    93114        bool insertionFound;
    94115        int iterations = 0;
     
    103124              while (city <= individual.Tours[tour].Cities.Count - length && !insertionFound) {
    104125                int insertionTour, insertionPlace;
    105                 if (FindBetterInsertionPlace(individual, tour, city, length,
     126                if (FindBetterInsertionPlace(individual, dueTime, readyTime, serviceTime, demand, capacity, distMatrix,
     127                  tour, city, length,
    106128                 out insertionTour, out insertionPlace)) {
    107129                  insertionFound = true;
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Manipulators/PotvinManipulator.cs

    r5445 r6569  
    2525using HeuristicLab.Parameters;
    2626using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     27using HeuristicLab.Data;
    2728
    2829namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    3435    }
    3536
     37    public IValueParameter<BoolValue> AllowInfeasibleSolutions {
     38      get { return (IValueParameter<BoolValue>)Parameters["AllowInfeasibleSolutions"]; }
     39    }
     40
     41    [StorableHook(HookType.AfterDeserialization)]
     42    private void AfterDeserialization() {
     43      // BackwardsCompatibility3.3
     44      #region Backwards compatible code (remove with 3.4)
     45      if (!Parameters.ContainsKey("AllowInfeasibleSolutions")) {
     46        Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
     47      }
     48      #endregion
     49    }
     50
    3651    [StorableConstructor]
    3752    protected PotvinManipulator(bool deserializing) : base(deserializing) { }
     
    4156    public PotvinManipulator() {
    4257      Parameters.Add(new LookupParameter<IRandom>("Random", "The pseudo random number generator which should be used for stochastic manipulation operators."));
     58      Parameters.Add(new ValueParameter<BoolValue>("AllowInfeasibleSolutions", "Indicates if infeasible solutions should be allowed.", new BoolValue(false)));
    4359    }
    4460
    4561    protected abstract void Manipulate(IRandom random, PotvinEncoding individual);
    4662
    47     protected int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual) {
     63    protected static int SelectRandomTourBiasedByLength(IRandom random, PotvinEncoding individual) {
    4864      int tourIndex = -1;
    4965
     
    5167      double[] probabilities = new double[individual.Tours.Count];
    5268      for (int i = 0; i < individual.Tours.Count; i++) {
    53         probabilities[i] = 1.0 / ((double)individual.Tours[i].Cities.Count / (double)Cities);
     69        probabilities[i] = 1.0 / ((double)individual.Tours[i].Cities.Count / (double)individual.Cities);
    5470        sum += probabilities[i];
    5571      }
     
    7288    }
    7389
    74     protected bool FindInsertionPlace(PotvinEncoding individual, int city, int routeToAvoid, out int route, out int place) {
     90    protected static bool FindInsertionPlace(PotvinEncoding individual, int city, int routeToAvoid,
     91      DoubleArray dueTime, DoubleArray serviceTime, DoubleArray readyTime, DoubleArray demand,
     92      DoubleValue capacity, DistanceMatrix distMatrix,  bool allowInfeasible,
     93      out int route, out int place) {
    7594      return individual.FindInsertionPlace(
    76         DueTimeParameter.ActualValue, ServiceTimeParameter.ActualValue, ReadyTimeParameter.ActualValue,
    77         DemandParameter.ActualValue, CapacityParameter.ActualValue, CoordinatesParameter.ActualValue,
    78         DistanceMatrixParameter, UseDistanceMatrixParameter.ActualValue,
    79         city, routeToAvoid, out route, out place);
     95        dueTime, serviceTime, readyTime,
     96        demand, capacity, distMatrix,
     97        city, routeToAvoid, allowInfeasible,
     98        out route, out place);
    8099    }
     100     
    81101
    82102    public override IOperation Apply() {
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Manipulators/PotvinOneLevelExchangeManipulator.cs

    r5445 r6569  
    2424using HeuristicLab.Core;
    2525using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     26using HeuristicLab.Data;
    2627
    2728namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    3940    public PotvinOneLevelExchangeMainpulator() : base() { }
    4041
    41     protected override void Manipulate(IRandom random, PotvinEncoding individual) {
     42    public static void Apply(IRandom random, PotvinEncoding individual,
     43     DoubleArray dueTime, DoubleArray readyTime, DoubleArray serviceTime, DoubleArray demand,
     44      DoubleValue capacity, DistanceMatrix distMatrix, bool allowInfeasible) {
    4245      int selectedIndex = SelectRandomTourBiasedByLength(random, individual);
    4346      Tour route1 =
     
    4851        int insertedRoute, insertedPlace;
    4952
    50         if (FindInsertionPlace(individual, route1.Cities[i], selectedIndex, out insertedRoute, out insertedPlace)) {
     53        if (FindInsertionPlace(individual, route1.Cities[i], selectedIndex,
     54          dueTime, serviceTime, readyTime, demand, capacity,
     55          distMatrix, allowInfeasible,
     56          out insertedRoute, out insertedPlace)) {
    5157          individual.Tours[insertedRoute].Cities.Insert(insertedPlace, route1.Cities[i]);
    5258          replaced.Add(route1.Cities[i]);
     
    6571        individual.Tours.Remove(route1);
    6672    }
     73
     74    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
     75      BoolValue useDistanceMatrix = UseDistanceMatrixParameter.ActualValue;
     76      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
     77      DistanceMatrix distMatrix = VRPUtilities.GetDistanceMatrix(coordinates, DistanceMatrixParameter, useDistanceMatrix);
     78      DoubleArray dueTime = DueTimeParameter.ActualValue;
     79      DoubleArray readyTime = ReadyTimeParameter.ActualValue;
     80      DoubleArray serviceTime = ServiceTimeParameter.ActualValue;
     81      DoubleArray demand = DemandParameter.ActualValue;
     82      DoubleValue capacity = CapacityParameter.ActualValue;
     83
     84      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
     85
     86      Apply(random, individual, dueTime, readyTime, serviceTime, demand, capacity, distMatrix, allowInfeasible);
     87    }
    6788  }
    6889}
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/Manipulators/PotvinTwoLevelExchangeManipulator.cs

    r5445 r6569  
    2323using HeuristicLab.Core;
    2424using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     25using HeuristicLab.Data;
    2526
    2627namespace HeuristicLab.Problems.VehicleRouting.Encodings.Potvin {
     
    3637    public PotvinTwoLevelExchangeManipulator() : base() { }
    3738
    38     protected override void Manipulate(IRandom random, PotvinEncoding individual) {
     39    public static void Apply(IRandom random, PotvinEncoding individual,
     40      DoubleArray dueTime, DoubleArray readyTime, DoubleArray serviceTime, DoubleArray demand,
     41      DoubleValue capacity, DistanceMatrix distMatrix, bool allowInfeasible) {
    3942      int selectedIndex = SelectRandomTourBiasedByLength(random, individual);
    40       Tour route1 = individual.Tours[selectedIndex]; 
     43      Tour route1 = individual.Tours[selectedIndex];
    4144
    4245      bool performed = false;
     
    5356              //customer1 can be feasibly inserted at the location of customer2
    5457              tour.Cities[customer2Position] = customer1;
    55               if (Feasible(tour)) {
     58              if (tour.Feasible(dueTime, serviceTime, readyTime, demand, capacity, distMatrix)) {
    5659                int routeIdx, place;
    5760                if (FindInsertionPlace(individual,
    58                   customer2, selectedIndex, out routeIdx, out place)) {
    59                     individual.Tours[routeIdx].Cities.Insert(place, customer2);
    60                     route1.Cities.RemoveAt(customer1Position);
     61                  customer2, selectedIndex,
     62                  dueTime, serviceTime, readyTime, demand, capacity,
     63                  distMatrix, allowInfeasible,
     64                  out routeIdx, out place)) {
     65                  individual.Tours[routeIdx].Cities.Insert(place, customer2);
     66                  route1.Cities.RemoveAt(customer1Position);
    6167
    62                     if (route1.Cities.Count == 0)
     68                  if (route1.Cities.Count == 0)
    6369                    individual.Tours.Remove(route1);
    6470
     
    8389      }
    8490    }
     91
     92    protected override void Manipulate(IRandom random, PotvinEncoding individual) {
     93      BoolValue useDistanceMatrix = UseDistanceMatrixParameter.ActualValue;
     94      DoubleMatrix coordinates = CoordinatesParameter.ActualValue;
     95      DistanceMatrix distMatrix = VRPUtilities.GetDistanceMatrix(coordinates, DistanceMatrixParameter, useDistanceMatrix);
     96      DoubleArray dueTime = DueTimeParameter.ActualValue;
     97      DoubleArray readyTime = ReadyTimeParameter.ActualValue;
     98      DoubleArray serviceTime = ServiceTimeParameter.ActualValue;
     99      DoubleArray demand = DemandParameter.ActualValue;
     100      DoubleValue capacity = CapacityParameter.ActualValue;
     101
     102      bool allowInfeasible = AllowInfeasibleSolutions.Value.Value;
     103
     104      Apply(random, individual, dueTime, readyTime, serviceTime, demand, capacity, distMatrix, allowInfeasible);
     105    }
    85106  }
    86107}
  • branches/QAPAlgorithms/HeuristicLab.Problems.VehicleRouting/3.3/Encodings/Potvin/PotvinEncoding.cs

    r5445 r6569  
    6969      DoubleArray dueTimeArray,
    7070      DoubleArray serviceTimeArray, DoubleArray readyTimeArray, DoubleArray demandArray, DoubleValue capacity,
    71       DoubleMatrix coordinates, ILookupParameter<DoubleMatrix> distanceMatrix, BoolValue useDistanceMatrix,
    72       int city, int routeToAvoid, out int route, out int place) {
     71      DistanceMatrix distMatrix,
     72      int city, int routeToAvoid, bool allowInfeasible,
     73      out int route, out int place) {
    7374      route = -1;
    7475      place = -1;
     76      bool bestFeasible = false;
    7577      double minDetour = 0;
    7678
     
    7880        if (tour != routeToAvoid) {
    7981          for (int i = 0; i <= Tours[tour].Cities.Count; i++) {
    80             double length = Tours[tour].GetLength(coordinates, distanceMatrix, useDistanceMatrix);
     82            double length = Tours[tour].GetLength(distMatrix);
    8183
    8284            Tours[tour].Cities.Insert(i, city);
    8385
    84             if (Tours[tour].Feasible(dueTimeArray, serviceTimeArray, readyTimeArray, demandArray,
    85               capacity, coordinates, distanceMatrix, useDistanceMatrix)) {
    86               double newLength = Tours[tour].GetLength(coordinates, distanceMatrix, useDistanceMatrix);
     86            bool feasible = Tours[tour].Feasible(dueTimeArray, serviceTimeArray, readyTimeArray, demandArray,
     87              capacity, distMatrix);
    8788
     89            if ((!allowInfeasible && feasible) || (allowInfeasible && (!bestFeasible || feasible))) {
     90              double newLength = Tours[tour].GetLength(distMatrix);
    8891              double detour = newLength - length;
    8992
    90               if (route <= 0 || detour < minDetour) {
     93              if (route <= 0 || detour < minDetour ||
     94                (allowInfeasible && ((!(bestFeasible && !feasible)) && detour < minDetour || (feasible && !bestFeasible)))) {
    9195                route = tour;
    9296                place = i;
    9397                minDetour = detour;
     98
     99                if (feasible)
     100                  bestFeasible = true;
    94101              }
    95102            }
Note: See TracChangeset for help on using the changeset viewer.