Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
03/11/12 20:17:07 (13 years ago)
Author:
abeham
Message:

#1614: updated SlackMinimizationSolutionCreator

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GeneralizedQAP/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/SolutionCreators/SlackMinimizationSolutionCreator.cs

    r7593 r7595  
    4646      get { return (IValueLookupParameter<IntValue>)Parameters["Depth"]; }
    4747    }
     48    public IValueLookupParameter<IntValue> RandomWalkLengthParameter {
     49      get { return (IValueLookupParameter<IntValue>)Parameters["RandomWalkLength"]; }
     50    }
    4851
    4952    [StorableConstructor]
     
    5558      Parameters.Add(new ValueLookupParameter<BoolValue>("CreateMostFeasibleSolution", "If this is set to true the operator will always succeed, and outputs the solution with the least violation instead of throwing an exception.", new BoolValue(false)));
    5659      Parameters.Add(new ValueLookupParameter<IntValue>("Depth", "How deep the algorithm should look forward.", new IntValue(3)));
     60      Parameters.Add(new ValueLookupParameter<IntValue>("RandomWalkLength", "The length of the random walk in the feasible region that is used to diversify the found assignments.", new IntValue(10)));
    5761    }
    5862
     
    6670        Parameters.Add(new ValueLookupParameter<IntValue>("Depth", "How deep the algorithm should look forward.", new IntValue(3)));
    6771      }
     72      if (!Parameters.ContainsKey("RandomWalkLength")) {
     73        Parameters.Add(new ValueLookupParameter<IntValue>("RandomWalkLength", "The length of the random walk in the feasible region that is used to diversify the found assignments.", new IntValue(10)));
     74      }
    6875    }
    6976
    70     public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities, int depth, int maximumTries, bool createMostFeasibleSolution, CancellationToken cancel) {
     77    public static IntegerVector CreateSolution(IRandom random, DoubleArray demands, DoubleArray capacities, int depth, int maximumTries, bool createMostFeasibleSolution, int randomWalkLength, CancellationToken cancel) {
    7178      IntegerVector result = null;
    7279      bool isFeasible = false;
     
    8996        var remainingEquipment = new HashSet<int>(Enumerable.Range(0, demands.Length));
    9097        while (remainingEquipment.Any()) {
    91           var equipment = remainingEquipment.ChooseProportionalRandom(random, 1, x => demands[x], true, true).Single();
    92           remainingEquipment.Remove(equipment);
    93 
    94           var freeLocations = GetLocationsByFillLevel(equipment, demands[equipment], slack);
    95           if (!freeLocations.Any()) break;
    96           double bestSlack = double.MaxValue;
    97           int bestLocation = -1;
    98           int[] additionalEquipment = new int[0];
    99           foreach (var location in freeLocations.Shuffle(random)) {
    100             HashSet<int> newEquipment;
    101             var estimatedSlack = EstimatePotentialSlack(location.Key, location.Value, remainingEquipment, demands, out newEquipment, depth);
    102             if (estimatedSlack < bestSlack || (estimatedSlack == bestSlack && newEquipment.Count < additionalEquipment.Length)) {
    103               bestSlack = estimatedSlack;
    104               bestLocation = location.Key;
    105               additionalEquipment = newEquipment.ToArray();
     98          var minimumDemand = remainingEquipment.Min(x => demands[x]);
     99          var possibleLocations = Enumerable.Range(0, capacities.Length).Where(x => slack[x] >= minimumDemand);
     100          if (!possibleLocations.Any()) break;
     101          foreach (var location in possibleLocations.Shuffle(random)) {
     102            var group = FindBestGroup(location, slack[location], remainingEquipment, demands, depth);
     103            foreach (var eq in group) {
     104              remainingEquipment.Remove(eq);
     105              assignment[eq] = location;
     106              slack[location] -= demands[eq];
    106107            }
    107           }
    108           assignment[equipment] = bestLocation;
    109           slack[bestLocation] -= demands[equipment];
    110           foreach (var eq in additionalEquipment) {
    111             remainingEquipment.Remove(eq);
    112             assignment[eq] = bestLocation;
    113             slack[bestLocation] -= demands[eq];
    114108          }
    115109        }
     
    124118          }
    125119        }
     120        RandomFeasibleWalk(random, assignment, demands, slack, randomWalkLength);
    126121        double violation = GQAPEvaluator.EvaluateOverbooking(slack, capacities);
    127122        isFeasible = violation == 0;
     
    134129    }
    135130
    136     private static double EstimatePotentialSlack(int location, double slack, HashSet<int> remainingEquipment, DoubleArray demands, out HashSet<int> addedEquipment, int depth = 3) {
    137       var feasibleEquipment = remainingEquipment.Where(x => demands[x] < slack).ToArray();
    138       addedEquipment = new HashSet<int>();
     131    private static IEnumerable<int> FindBestGroup(int location, double slack, HashSet<int> remainingEquipment, DoubleArray demands, int depth = 3) {
     132      var feasibleEquipment = remainingEquipment.Where(x => demands[x] <= slack).ToArray();
    139133
    140       if (!feasibleEquipment.Any()) return slack;
     134      if (!feasibleEquipment.Any()) yield break;
    141135      if (depth == 0) {
    142136        var e = feasibleEquipment.ChooseMax(x => demands[x]);
    143         addedEquipment.Add(e);
    144         return slack - demands[e];
     137        yield return e;
     138        yield break;
    145139      }
    146140
    147141      double bestSlack = slack;
    148       int minSlackEquipment = -1;
     142      int bestEquipment = -1;
     143      int[] bestColleagues = new int[0];
    149144      foreach (var e in feasibleEquipment) {
    150145        remainingEquipment.Remove(e);
    151         HashSet<int> childEquipment;
    152         var potentialSlack = EstimatePotentialSlack(location, slack - demands[e], remainingEquipment, demands, out childEquipment, depth - 1);
    153         if (bestSlack > potentialSlack || (bestSlack == potentialSlack && childEquipment.Count < addedEquipment.Count)) {
    154           bestSlack = potentialSlack;
    155           minSlackEquipment = e;
    156           addedEquipment.Clear();
    157           foreach (var child in childEquipment) addedEquipment.Add(child);
     146        var colleagues = FindBestGroup(location, slack - demands[e], remainingEquipment, demands, depth - 1).ToArray();
     147        var slackWithColleagues = slack - demands[e] - colleagues.Sum(x => demands[x]);
     148        if (bestSlack > slackWithColleagues || (bestSlack == slackWithColleagues && colleagues.Length < bestColleagues.Length)) {
     149          bestSlack = slackWithColleagues;
     150          bestEquipment = e;
     151          bestColleagues = colleagues;
    158152        }
    159153        remainingEquipment.Add(e);
    160154      }
    161       if (minSlackEquipment > -1)
    162         addedEquipment.Add(minSlackEquipment);
    163       return bestSlack;
     155      yield return bestEquipment;
     156      foreach (var a in bestColleagues) yield return a;
     157    }
     158
     159    private static void RandomFeasibleWalk(IRandom random, Dictionary<int, int> assignment, DoubleArray demands, DoubleArray slack, int walkLength) {
     160      for (int i = 0; i < walkLength; i++) {
     161        var equipments = Enumerable.Range(0, demands.Length).Shuffle(random);
     162        foreach (var e in equipments) {
     163          var partners = Enumerable.Range(0, demands.Length)
     164            .Where(x => slack[assignment[x]] + demands[x] - demands[e] >= 0
     165                && slack[assignment[e]] + demands[e] - demands[x] >= 0);
     166          if (!partners.Any()) continue;
     167          var f = partners.ChooseUniformRandom(random);
     168          int h = assignment[e];
     169          assignment[e] = assignment[f];
     170          assignment[f] = h;
     171          slack[assignment[e]] += demands[f] - demands[e];
     172          slack[assignment[f]] += demands[e] - demands[f];
     173          break;
     174        }
     175      }
    164176    }
    165177
     
    169181        MaximumTriesParameter.ActualValue.Value,
    170182        CreateMostFeasibleSolutionParameter.ActualValue.Value,
     183        RandomWalkLengthParameter.ActualValue.Value,
    171184        CancellationToken);
    172     }
    173 
    174     private static IEnumerable<KeyValuePair<int, double>> GetLocationsByFillLevel(int equipment, double demand, DoubleArray slack) {
    175       var freeLocations = slack
    176         .Select((v, idx) => new KeyValuePair<int, double>(idx, v))
    177         .Where(x => x.Value >= demand);
    178       if (!freeLocations.Any()) {
    179         return Enumerable.Empty<KeyValuePair<int, double>>();
    180       }
    181       return freeLocations.Select(x => new KeyValuePair<int, double>(x.Key, slack[x.Key] - demand)).OrderBy(x => x.Value);
    182185    }
    183186  }
Note: See TracChangeset for help on using the changeset viewer.