Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2457_ExpertSystem/HeuristicLab.Algorithms.MemPR/3.3/Permutation/InversionPathRelinker.cs @ 15728

Last change on this file since 15728 was 14776, checked in by abeham, 8 years ago

#2457: working on MemPR integration

File size: 7.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2017 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 System.Runtime.Remoting.Contexts;
26using System.Threading;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.PermutationEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Optimization.Operators;
33using HeuristicLab.Parameters;
34using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
35
36namespace HeuristicLab.Problems.TravelingSalesman {
37  [Item("InversionPathRelinker", "An operator that relinks solutions.")]
38  [StorableClass]
39  public sealed class InversionPathRelinker : SingleObjectivePathRelinker, IStochasticOperator {
40    public IValueLookupParameter<DoubleMatrix> DistanceMatrixParameter {
41      get { return (IValueLookupParameter<DoubleMatrix>)Parameters["DistanceMatrix"]; }
42    }
43
44    public ILookupParameter<IRandom> RandomParameter {
45      get { return (ILookupParameter<IRandom>) Parameters["Random"]; }
46    }
47    [StorableConstructor]
48    private InversionPathRelinker(bool deserializing) : base(deserializing) { }
49    private InversionPathRelinker(InversionPathRelinker original, Cloner cloner) : base(original, cloner) { }
50
51    public InversionPathRelinker() : base() {
52      Parameters.Add(new ValueLookupParameter<DoubleMatrix>("DistanceMatrix"));
53      Parameters.Add(new LookupParameter<IRandom>("Random"));
54    }
55
56    public override IDeepCloneable Clone(Cloner cloner) {
57      return new InversionPathRelinker(this, cloner);
58    }
59
60    protected override ItemArray<IItem> Relink(ItemArray<IItem> parents, PercentValue n) {
61      if (parents.Length != 2)
62        throw new ArgumentException("The number of parents is not equal to 2.");
63      var random = RandomParameter.ActualValue;
64      var distances = DistanceMatrixParameter.ActualValue;
65      Func<Permutation, double> eval = (p) => {
66        double length = 0;
67        for (int i = 0; i < p.Length - 1; i++)
68          length += distances[p[i], p[i + 1]];
69        length += distances[p[p.Length - 1], p[0]];
70        return length;
71      };
72      return new ItemArray<IItem>(RelinkOpt(random, (Permutation)parents[0],
73        (Permutation)parents[1], eval));
74    }
75
76    public IEnumerable<Permutation> RelinkOpt(IRandom random, Permutation p1, Permutation p2,
77                               Func<Permutation, double> eval) {
78
79      var evaluations = 0;
80      var child = (Permutation)p1.Clone();
81     
82      Permutation bestChild = null;
83
84      var invChild = new int[child.Length];
85      var invP2 = new int[child.Length];
86      for (var i = 0; i < child.Length; i++) {
87        invChild[child[i]] = i;
88        invP2[p2[i]] = i;
89      }
90
91      var bestChange = double.NaN;
92      var moveQueue = new Queue<Tuple<int, int>>();
93      var undoStack = new Stack<Tuple<int, int>>();
94      do {
95        Queue<Tuple<int, int>> bestQueue = null;
96        bestChange = double.NaN;
97        for (var j = 0; j < p2.Length; j++) {
98          if (IsUndirectedEdge(invChild, p2[j], p2.GetCircular(j + 1))) continue;
99
100          var a = invChild[p2[j]];
101          var b = invChild[p2.GetCircular(j + 1)];
102          if (a > b) { var h = a; a = b; b = h; }
103          var aprev = a - 1;
104          var bprev = b - 1;
105          while (IsUndirectedEdge(invP2, child.GetCircular(aprev), child.GetCircular(aprev + 1))) {
106            aprev--;
107          }
108          while (IsUndirectedEdge(invP2, child.GetCircular(bprev), child.GetCircular(bprev + 1))) {
109            bprev--;
110          }
111          var bnext = b + 1;
112          var anext = a + 1;
113          while (IsUndirectedEdge(invP2, child.GetCircular(bnext - 1), child.GetCircular(bnext))) {
114            bnext++;
115          }
116          while (IsUndirectedEdge(invP2, child.GetCircular(anext - 1), child.GetCircular(anext))) {
117            anext++;
118          }
119          aprev++; bprev++; anext--; bnext--;
120
121          if (aprev < a && bnext > b) {
122            if (aprev < 0) {
123              moveQueue.Enqueue(Tuple.Create(a + 1, bnext));
124              moveQueue.Enqueue(Tuple.Create(a + 1, a + 1 + (bnext - b)));
125            } else {
126              moveQueue.Enqueue(Tuple.Create(aprev, b - 1));
127              moveQueue.Enqueue(Tuple.Create(b - 1 - (a - aprev), b - 1));
128            }
129          } else if (aprev < a && bnext == b && bprev == b) {
130            moveQueue.Enqueue(Tuple.Create(a + 1, b));
131          } else if (aprev < a && bprev < b) {
132            moveQueue.Enqueue(Tuple.Create(a + 1, b));
133          } else if (aprev == a && anext == a && bnext > b) {
134            moveQueue.Enqueue(Tuple.Create(a, b - 1));
135          } else if (aprev == a && anext == a && bnext == b && bprev == b) {
136            moveQueue.Enqueue(Tuple.Create(a, b - 1));
137          } else if (aprev == a && anext == a && bprev < b) {
138            moveQueue.Enqueue(Tuple.Create(a + 1, b));
139          } else if (anext > a && bnext > b) {
140            moveQueue.Enqueue(Tuple.Create(a, b - 1));
141          } else if (anext > a && bnext == b && bprev == b) {
142            moveQueue.Enqueue(Tuple.Create(a, b - 1));
143          } else /*if (anext > a && bprev < b)*/ {
144            moveQueue.Enqueue(Tuple.Create(a, bprev - 1));
145            moveQueue.Enqueue(Tuple.Create(bprev, b));
146          }
147
148          while (moveQueue.Count > 0) {
149            var m = moveQueue.Dequeue();
150            Opt(child, m.Item1, m.Item2);
151            undoStack.Push(m);
152          }
153          var moveF = eval(child);
154
155          evaluations++;
156          if (double.IsNaN(bestChange) || moveF < bestChange) {
157            bestChange = moveF;
158            bestQueue = new Queue<Tuple<int, int>>(undoStack.Reverse());
159          }
160          // undo
161          while (undoStack.Count > 0) {
162            var m = undoStack.Pop();
163            Opt(child, m.Item1, m.Item2);
164          }
165        }
166        if (!double.IsNaN(bestChange)) {
167          while (bestQueue.Count > 0) {
168            var m = bestQueue.Dequeue();
169            Opt(child, m.Item1, m.Item2);
170            for (var i = m.Item1; i <= m.Item2; i++) invChild[child[i]] = i;
171          }
172          yield return (Permutation) child.Clone();
173        }
174      } while (!double.IsNaN(bestChange));
175    }
176
177    private static bool IsUndirectedEdge(int[] invP, int a, int b) {
178      var d = Math.Abs(invP[a] - invP[b]);
179      return d == 1 || d == invP.Length - 1;
180    }
181
182    private static void Opt(Permutation child, int from, int to) {
183      if (from > to) child.Reverse(to, from - to + 1);
184      else child.Reverse(from, to - from + 1);
185    }
186  }
187}
Note: See TracBrowser for help on using the repository browser.