1 | #region License Information |
---|
2 | /* HeuristicLab |
---|
3 | * Copyright (C) 2002-2019 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 | |
---|
22 | using System.Collections.Generic; |
---|
23 | using HeuristicLab.Common; |
---|
24 | using HeuristicLab.Core; |
---|
25 | using HeuristicLab.Data; |
---|
26 | using HeuristicLab.Operators; |
---|
27 | using HeuristicLab.Optimization; |
---|
28 | using HeuristicLab.Parameters; |
---|
29 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; |
---|
30 | |
---|
31 | namespace HeuristicLab.Encodings.PermutationEncoding { |
---|
32 | [Item("Swap2MoveSoftTabuCriterion", @"For relative postion encoded permutations it just prevents readding of previously deleted edges, but allows deleting previously added edges. |
---|
33 | For absolute position encoded permutations it prevents moving a number to a position it has previously occupied. |
---|
34 | |
---|
35 | If the aspiration condition is activated, a move will not be considered tabu against a move in the tabu list if it leads to a better solution than the quality recorded with the move in the tabu list.")] |
---|
36 | [StorableClass] |
---|
37 | public class Swap2MoveSoftTabuCriterion : SingleSuccessorOperator, IPermutationSwap2MoveOperator, ITabuChecker { |
---|
38 | public override bool CanChangeName { |
---|
39 | get { return false; } |
---|
40 | } |
---|
41 | public ILookupParameter<Swap2Move> Swap2MoveParameter { |
---|
42 | get { return (LookupParameter<Swap2Move>)Parameters["Swap2Move"]; } |
---|
43 | } |
---|
44 | public ILookupParameter<Permutation> PermutationParameter { |
---|
45 | get { return (LookupParameter<Permutation>)Parameters["Permutation"]; } |
---|
46 | } |
---|
47 | public ILookupParameter<ItemList<IItem>> TabuListParameter { |
---|
48 | get { return (ILookupParameter<ItemList<IItem>>)Parameters["TabuList"]; } |
---|
49 | } |
---|
50 | public ILookupParameter<BoolValue> MoveTabuParameter { |
---|
51 | get { return (ILookupParameter<BoolValue>)Parameters["MoveTabu"]; } |
---|
52 | } |
---|
53 | public IValueLookupParameter<BoolValue> MaximizationParameter { |
---|
54 | get { return (IValueLookupParameter<BoolValue>)Parameters["Maximization"]; } |
---|
55 | } |
---|
56 | public ILookupParameter<DoubleValue> MoveQualityParameter { |
---|
57 | get { return (ILookupParameter<DoubleValue>)Parameters["MoveQuality"]; } |
---|
58 | } |
---|
59 | public ValueParameter<BoolValue> UseAspirationCriterionParameter { |
---|
60 | get { return (ValueParameter<BoolValue>)Parameters["UseAspirationCriterion"]; } |
---|
61 | } |
---|
62 | |
---|
63 | public BoolValue UseAspirationCriterion { |
---|
64 | get { return UseAspirationCriterionParameter.Value; } |
---|
65 | set { UseAspirationCriterionParameter.Value = value; } |
---|
66 | } |
---|
67 | |
---|
68 | [StorableConstructor] |
---|
69 | protected Swap2MoveSoftTabuCriterion(bool deserializing) : base(deserializing) { } |
---|
70 | protected Swap2MoveSoftTabuCriterion(Swap2MoveSoftTabuCriterion original, Cloner cloner) : base(original, cloner) { } |
---|
71 | public Swap2MoveSoftTabuCriterion() |
---|
72 | : base() { |
---|
73 | Parameters.Add(new LookupParameter<Swap2Move>("Swap2Move", "The move to evaluate.")); |
---|
74 | Parameters.Add(new LookupParameter<BoolValue>("MoveTabu", "The variable to store if a move was tabu.")); |
---|
75 | Parameters.Add(new LookupParameter<Permutation>("Permutation", "The solution as permutation.")); |
---|
76 | Parameters.Add(new LookupParameter<ItemList<IItem>>("TabuList", "The tabu list.")); |
---|
77 | Parameters.Add(new ValueParameter<BoolValue>("UseAspirationCriterion", "Whether to use the aspiration criterion or not.", new BoolValue(true))); |
---|
78 | Parameters.Add(new ValueLookupParameter<BoolValue>("Maximization", "True if the problem is a maximization problem, else if it is a minimization problem.")); |
---|
79 | Parameters.Add(new LookupParameter<DoubleValue>("MoveQuality", "The quality of the current move.")); |
---|
80 | } |
---|
81 | |
---|
82 | public override IDeepCloneable Clone(Cloner cloner) { |
---|
83 | return new Swap2MoveSoftTabuCriterion(this, cloner); |
---|
84 | } |
---|
85 | |
---|
86 | public override IOperation Apply() { |
---|
87 | ItemList<IItem> tabuList = TabuListParameter.ActualValue; |
---|
88 | Swap2Move move = Swap2MoveParameter.ActualValue; |
---|
89 | Permutation permutation = PermutationParameter.ActualValue; |
---|
90 | int length = permutation.Length; |
---|
91 | double moveQuality = MoveQualityParameter.ActualValue.Value; |
---|
92 | bool maximization = MaximizationParameter.ActualValue.Value; |
---|
93 | bool useAspiration = UseAspirationCriterion.Value; |
---|
94 | bool isTabu = false; |
---|
95 | |
---|
96 | if (permutation.PermutationType != PermutationTypes.Absolute) |
---|
97 | isTabu = EvaluateRelativeTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration); |
---|
98 | else isTabu = EvaluateAbsoluteTabuState(tabuList, move, permutation, moveQuality, maximization, useAspiration); |
---|
99 | |
---|
100 | MoveTabuParameter.ActualValue = new BoolValue(isTabu); |
---|
101 | return base.Apply(); |
---|
102 | } |
---|
103 | |
---|
104 | private static bool EvaluateRelativeTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) { |
---|
105 | bool isTabu = false; |
---|
106 | StandardEdgeEqualityComparer eq = new StandardEdgeEqualityComparer(); |
---|
107 | bool bidirectional = permutation.PermutationType == PermutationTypes.RelativeUndirected; |
---|
108 | List<Edge> added = new List<Edge>(); |
---|
109 | added.Add(new Edge(permutation.GetCircular(move.Index1 - 1), permutation[move.Index2], bidirectional)); |
---|
110 | added.Add(new Edge(permutation[move.Index2], permutation.GetCircular(move.Index1 + 1), bidirectional)); |
---|
111 | added.Add(new Edge(permutation.GetCircular(move.Index2 - 1), permutation[move.Index1], bidirectional)); |
---|
112 | added.Add(new Edge(permutation[move.Index1], permutation.GetCircular(move.Index2 + 1), bidirectional)); |
---|
113 | |
---|
114 | foreach (IItem tabuMove in tabuList) { |
---|
115 | Swap2MoveRelativeAttribute relAttrib = (tabuMove as Swap2MoveRelativeAttribute); |
---|
116 | if (relAttrib != null |
---|
117 | && (!useAspiration |
---|
118 | || maximization && moveQuality <= relAttrib.MoveQuality |
---|
119 | || !maximization && moveQuality >= relAttrib.MoveQuality)) { |
---|
120 | for (int i = 0; i < relAttrib.DeletedEdges.Count; i++) { |
---|
121 | isTabu = eq.Equals(relAttrib.DeletedEdges[i], added[0]) |
---|
122 | || eq.Equals(relAttrib.DeletedEdges[i], added[1]) |
---|
123 | || eq.Equals(relAttrib.DeletedEdges[i], added[2]) |
---|
124 | || eq.Equals(relAttrib.DeletedEdges[i], added[3]); |
---|
125 | if (isTabu) break; |
---|
126 | } |
---|
127 | } |
---|
128 | if (isTabu) break; |
---|
129 | } |
---|
130 | return isTabu; |
---|
131 | } |
---|
132 | |
---|
133 | private bool EvaluateAbsoluteTabuState(ItemList<IItem> tabuList, Swap2Move move, Permutation permutation, double moveQuality, bool maximization, bool useAspiration) { |
---|
134 | bool isTabu = false; |
---|
135 | foreach (IItem tabuMove in tabuList) { |
---|
136 | Swap2MoveAbsoluteAttribute attrib = (tabuMove as Swap2MoveAbsoluteAttribute); |
---|
137 | if (attrib != null |
---|
138 | && (!useAspiration |
---|
139 | || maximization && moveQuality <= attrib.MoveQuality |
---|
140 | || !maximization && moveQuality >= attrib.MoveQuality)) { |
---|
141 | int i1 = move.Index1; |
---|
142 | int n1 = permutation[move.Index1]; |
---|
143 | int i2 = move.Index2; |
---|
144 | int n2 = permutation[move.Index2]; |
---|
145 | if ((attrib.Index1 == i1 || attrib.Index1 == i2) && (attrib.Number1 == n1 || attrib.Number1 == n2) |
---|
146 | || (attrib.Index2 == i2 || attrib.Index2 == i1) && (attrib.Number2 == n2 || attrib.Number2 == n1)) |
---|
147 | isTabu = true; |
---|
148 | } |
---|
149 | if (isTabu) break; |
---|
150 | } |
---|
151 | return isTabu; |
---|
152 | } |
---|
153 | } |
---|
154 | } |
---|