Free cookie consent management tool by TermsFeed Policy Generator

source: branches/MemPRAlgorithm/HeuristicLab.Algorithms.MemPR/3.3/LinearLinkage/LocalSearch/StaticAPI/ExhaustiveLocalSearch.cs @ 14477

Last change on this file since 14477 was 14477, checked in by abeham, 7 years ago

#2701:

  • Added TryGetBy(First|Second) method to BidirectionalDictionary
  • Updated linear linkage encoding
    • Added move generator and moves for shift, merge, split, and extract moves
    • Added unit test (Apply/Undo)
  • Updated MemPR (linear linkage)
    • Added basic tabu walk
  • Fixed bug in MemPR (permutation)
  • Updated Tests project
File size: 8.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Linq;
24using System.Threading;
25using HeuristicLab.Algorithms.MemPR.Util;
26using HeuristicLab.Collections;
27using HeuristicLab.Core;
28
29namespace HeuristicLab.Algorithms.MemPR.LinearLinkage.LocalSearch {
30  public static class ExhaustiveLocalSearch {
31    public static Tuple<int, int> Optimize(IRandom random, Encodings.LinearLinkageEncoding.LinearLinkage solution, ref double quality, bool maximization, Func<Encodings.LinearLinkageEncoding.LinearLinkage, IRandom, double> eval, CancellationToken token, bool[] subspace = null) {
32      var evaluations = 0;
33      var current = solution;
34      if (double.IsNaN(quality)) {
35        quality = eval(current, random);
36        evaluations++;
37      }
38      var steps = 0;
39      // this dictionary holds the last relevant links
40      var links = new BidirectionalDictionary<int, int>();
41      for (var iter = 0; iter < int.MaxValue; iter++) {
42        var change = false;
43        // clear the dictionary before a new pass through the array is made
44        links.Clear();
45        for (var i = 0; i < current.Length; i++) {
46          if (subspace != null && !subspace[i]) {
47            links.RemoveBySecond(i);
48            links.Add(i, current[i]);
49            continue;
50          }
51          var pred = -1;
52          var isFirst = !links.TryGetBySecond(i, out pred);
53          var keepLink = false;
54          if (!isFirst) {
55            keepLink = subspace != null && !subspace[pred];
56          }
57          var next = current[i];
58          var isLast = next == i;
59
60          if (!keepLink) {
61            // try to insert current into each previous group
62            // first remove i from its group
63            var linksList = links.Where(x => x.Value != i).ToList();
64            if (linksList.Count > 0 && !isFirst) current[pred] = isLast ? pred : next;
65            for (var k = 0; k < linksList.Count; k++) {
66              var l = linksList[k];
67              current[l.Key] = i;
68              current[i] = Math.Max(i, l.Value);
69              var moveF = eval(current, random);
70              evaluations++;
71              if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
72                steps++;
73                quality = moveF;
74                change = true;
75                links.RemoveBySecond(i);
76                links.SetByFirst(l.Key, i); // otherwise the link won't be removed
77                if (!isFirst) links.SetByFirst(pred, isLast ? pred : next);
78                next = current[i];
79                if (next == i) { isLast = true; }
80                pred = l.Key;
81                isFirst = false;
82                break;
83              } else { // undo
84                current[l.Key] = l.Value;
85                if (k == linksList.Count - 1) {
86                  // all attempts unsuccessful
87                  if (!isFirst) current[pred] = i; // undo - readd i to its group
88                  current[i] = next;
89                }
90              }
91            }
92          }
93
94          if (!isLast) {
95            // try to split group at this point
96            // this is safe even if keepLink was true
97            current[i] = i;
98            var moveF = eval(current, random);
99            evaluations++;
100            if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
101              steps++;
102              quality = moveF;
103              change = true;
104              isLast = true;
105              next = i;
106              links.SetBySecond(i, i);
107              continue;
108            } else current[i] = next; // undo
109          }
110
111          if (isFirst && !isLast) {
112            // try merge with all terminated groups
113            foreach (var l in links.Where(x => x.Key == x.Value && (subspace == null || subspace[x.Key]))) {
114              current[l.Key] = i;
115              var moveF = eval(current, random);
116              evaluations++;
117              if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
118                steps++;
119                quality = moveF;
120                change = true;
121                isFirst = false;
122                pred = l.Key;
123                links.SetByFirst(l.Key, i);
124                break;
125              } else {
126                current[l.Key] = l.Value;
127              }
128            }
129          } else if (!isFirst && !keepLink) {
130            // try to extract current into own group
131            current[pred] = isLast ? pred : next;
132            current[i] = i;
133            var moveF = eval(current, random);
134            evaluations++;
135            if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
136              steps++;
137              links.SetByFirst(pred, current[pred]);
138              quality = moveF;
139              change = true;
140            } else { // undo
141              current[pred] = i;
142              current[i] = next;
143            }
144          }
145          links.RemoveBySecond(i);
146          links.Add(i, current[i]);
147          if (token.IsCancellationRequested) break;
148        }
149        if (!change || token.IsCancellationRequested) break;
150      }
151
152      return Tuple.Create(evaluations, steps);
153    }
154
155    public static Tuple<int, int> OptimizeSwapOnly(IRandom random, Encodings.LinearLinkageEncoding.LinearLinkage solution, ref double quality, bool maximization, Func<Encodings.LinearLinkageEncoding.LinearLinkage, IRandom, double> eval, CancellationToken token) {
156      var evaluations = 0;
157      var current = solution;
158      if (double.IsNaN(quality)) {
159        quality = eval(current, random);
160        evaluations++;
161      }
162      var groups = current.GetGroups().ToList();
163      var exclude = new bool[groups.Count, groups.Count];
164      var steps = 0;
165      for (var iter = 0; iter < int.MaxValue; iter++) {
166        var change = false;
167        for (var i = 0; i < groups.Count - 1; i++) {
168          for (var j = i + 1; j < groups.Count; j++) {
169            if (exclude[i, j]) continue;
170            var groupsChanged = false;
171            if (groups[i].Count == 1 && groups[j].Count == 1) continue; // groups are anonymous, swap has no effect
172            for (var x = 0; x < groups[i].Count; x++) {
173              for (var y = 0; y < groups[j].Count; y++) {
174                var a = groups[i][x];
175                var b = groups[j][y];
176                groups[i][x] = b;
177                groups[j][y] = a;
178                current.SetGroups(groups);
179                var moveF = eval(current, random);
180                evaluations++;
181                if (FitnessComparer.IsBetter(maximization, moveF, quality)) {
182                  steps++;
183                  quality = moveF;
184                  groupsChanged = true;
185                } else {
186                  // undo
187                  groups[i][x] = a;
188                  groups[j][y] = b;
189                  current.SetGroups(groups);
190                }
191              }
192            }
193            if (!groupsChanged) {
194              exclude[i, j] = true;
195            } else {
196              change = true;
197              for (var k = 0; k < groups.Count; k++) {
198                exclude[k, j] = false;
199                exclude[i, k] = false;
200              }
201            }
202            if (token.IsCancellationRequested) break;
203          }
204          if (token.IsCancellationRequested) break;
205        }
206        if (!change || token.IsCancellationRequested) break;
207      }
208      return Tuple.Create(evaluations, steps);
209    }
210  }
211}
Note: See TracBrowser for help on using the repository browser.