source: branches/2936_GQAPIntegration/HeuristicLab.Problems.GeneralizedQuadraticAssignment/3.3/Operators/Crossovers/DiscreteLocationCrossover.cs @ 16077

Last change on this file since 16077 was 16077, checked in by abeham, 12 months ago

#2936: Added integration branch

File size: 4.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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 System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Encodings.IntegerVectorEncoding;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Random;
31
32namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
33  [Item("DiscreteLocationCrossover", "Combines the assignment to locations from various parents.")]
34  [StorableClass]
35  public class DiscreteLocationCrossover : GQAPCrossover {
36
37    [StorableConstructor]
38    protected DiscreteLocationCrossover(bool deserializing) : base(deserializing) { }
39    protected DiscreteLocationCrossover(DiscreteLocationCrossover original, Cloner cloner)
40      : base(original, cloner) { }
41    public DiscreteLocationCrossover()
42      : base() {
43    }
44
45    public override IDeepCloneable Clone(Cloner cloner) {
46      return new DiscreteLocationCrossover(this, cloner);
47    }
48
49    public static IntegerVector Apply(IRandom random, ItemArray<IntegerVector> parents, DoubleArray demands, DoubleArray capacities) {
50      var locations = capacities.Length;
51      var cap = Math.Max(parents[0].Length / locations, 1);
52      var lookup = new List<int>[parents.Length][];
53      for (var p = 0; p < parents.Length; p++) {
54        lookup[p] = new List<int>[locations];
55        var assign = parents[p];
56        for (var e = 0; e < parents[p].Length; e++) {
57          var loc = assign[e];
58          if (lookup[p][loc] == null) lookup[p][loc] = new List<int>(cap);
59          lookup[p][loc].Add(e);
60        }
61      }
62
63      var slack = capacities.ToArray();
64      IntegerVector child = new IntegerVector(parents[0].Length);
65      var takenEquip = new bool[child.Length];
66      foreach (var loc in Enumerable.Range(0, locations).Shuffle(random)) {
67        int parent = random.Next(parents.Length);
68        if (lookup[parent][loc] == null) {
69          int tmp = parent;
70          do {
71            tmp = (tmp + 1) % parents.Length;
72          } while (tmp != parent && lookup[tmp][loc] == null);
73          if (parent == tmp) continue;
74          else parent = tmp;
75        }
76        foreach (var equip in lookup[parent][loc]) {
77          if (!takenEquip[equip]) {
78            child[equip] = loc;
79            takenEquip[equip] = true;
80            slack[loc] -= demands[equip];
81          }
82        }
83      }
84
85      var order = Enumerable.Range(0, takenEquip.Length)
86        .Where(x => !takenEquip[x])
87        .Shuffle(random); // avoid bias
88      foreach (var e in order) {
89        var assigned = false;
90        // try 1: find a parent where equipment can be assigned feasibly
91        var fallback = -1;
92        var count = 1;
93        foreach (var p in parents.Shuffle(random)) {
94          if (slack[p[e]] >= demands[e]) {
95            child[e] = p[e];
96            slack[child[e]] -= demands[e];
97            assigned = true;
98            break;
99          } else if (random.NextDouble() < 1.0 / count) {
100            fallback = p[e];
101          }
102          count++;
103        }
104        // try 2: find a random feasible location
105        if (!assigned) {
106          var possible = Enumerable.Range(0, locations).Where(x => slack[x] >= demands[e]).ToList();
107          if (possible.Count > 0) {
108            var loc = possible.SampleRandom(random);
109            child[e] = loc;
110            slack[loc] -= demands[e];
111          } else {
112            // otherwise: fallback
113            child[e] = fallback;
114            slack[child[e]] -= demands[e];
115          }
116        }
117      }
118
119      return child;
120    }
121
122    protected override IntegerVector Cross(IRandom random, ItemArray<IntegerVector> parents,
123      GQAPInstance problemInstance) {
124      return Apply(random, parents, problemInstance.Demands, problemInstance.Capacities);
125    }
126  }
127}
Note: See TracBrowser for help on using the repository browser.