1 | #region License Information
|
---|
2 | /* HeuristicLab
|
---|
3 | * Copyright (C) 2002-2010 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;
|
---|
23 | using System.Collections.Generic;
|
---|
24 | using HeuristicLab.Core;
|
---|
25 | using HeuristicLab.Data;
|
---|
26 | using HeuristicLab.Operators;
|
---|
27 | using HeuristicLab.Parameters;
|
---|
28 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
29 | using HeuristicLab.Selection;
|
---|
30 |
|
---|
31 | namespace HeuristicLab.Algorithms.TS {
|
---|
32 | /// <summary>
|
---|
33 | /// The tabu selector is a selection operator that separates the best n moves that are either not tabu or satisfy the default aspiration criterion from the rest. It expects the move subscopes to be sorted.
|
---|
34 | /// </summary>
|
---|
35 | /// <remarks>
|
---|
36 | /// For different aspiration criteria a new operator should be implemented.
|
---|
37 | /// </remarks>
|
---|
38 | [Item("TabuSelector", "An operator that selects the best move that is either not tabu or satisfies the aspiration criterion. It expects the move subscopes to be sorted.")]
|
---|
39 | [StorableClass]
|
---|
40 | public class TabuSelector : Selector {
|
---|
41 | /// <summary>
|
---|
42 | /// The best found quality so far.
|
---|
43 | /// </summary>
|
---|
44 | public LookupParameter<DoubleData> BestQualityParameter {
|
---|
45 | get { return (LookupParameter<DoubleData>)Parameters["BestQuality"]; }
|
---|
46 | }
|
---|
47 | /// <summary>
|
---|
48 | /// Whether to use the default aspiration criteria or not.
|
---|
49 | /// </summary>
|
---|
50 | public ValueLookupParameter<BoolData> AspirationParameter {
|
---|
51 | get { return (ValueLookupParameter<BoolData>)Parameters["Aspiration"]; }
|
---|
52 | }
|
---|
53 | /// <summary>
|
---|
54 | /// Whether the problem is a maximization problem or not.
|
---|
55 | /// </summary>
|
---|
56 | public IValueLookupParameter<BoolData> MaximizationParameter {
|
---|
57 | get { return (IValueLookupParameter<BoolData>)Parameters["Maximization"]; }
|
---|
58 | }
|
---|
59 | /// <summary>
|
---|
60 | /// The parameter for the move qualities.
|
---|
61 | /// </summary>
|
---|
62 | public ILookupParameter<ItemArray<DoubleData>> MoveQualityParameter {
|
---|
63 | get { return (ILookupParameter<ItemArray<DoubleData>>)Parameters["MoveQuality"]; }
|
---|
64 | }
|
---|
65 | /// <summary>
|
---|
66 | /// The parameter for the tabu status of the moves.
|
---|
67 | /// </summary>
|
---|
68 | public ILookupParameter<ItemArray<BoolData>> MoveTabuParameter {
|
---|
69 | get { return (ILookupParameter<ItemArray<BoolData>>)Parameters["MoveTabu"]; }
|
---|
70 | }
|
---|
71 |
|
---|
72 | public IntData NumberOfSelectedSubScopes {
|
---|
73 | set { NumberOfSelectedSubScopesParameter.Value = value; }
|
---|
74 | }
|
---|
75 |
|
---|
76 | /// <summary>
|
---|
77 | /// Initializes a new intsance with 6 parameters (<c>Quality</c>, <c>BestQuality</c>,
|
---|
78 | /// <c>Aspiration</c>, <c>Maximization</c>, <c>MoveQuality</c>, and <c>MoveTabu</c>).
|
---|
79 | /// </summary>
|
---|
80 | public TabuSelector()
|
---|
81 | : base() {
|
---|
82 | Parameters.Add(new LookupParameter<DoubleData>("BestQuality", "The best found quality so far."));
|
---|
83 | Parameters.Add(new ValueLookupParameter<BoolData>("Aspiration", "Whether the default aspiration criterion should be used or not. The default aspiration criterion accepts a tabu move if it results in a better solution than the best solution found so far.", new BoolData(true)));
|
---|
84 | Parameters.Add(new ValueLookupParameter<BoolData>("Maximization", "Whether the problem is a maximization or minimization problem (used to decide whether a solution is better"));
|
---|
85 | Parameters.Add(new SubScopesLookupParameter<DoubleData>("MoveQuality", "The quality of the move."));
|
---|
86 | Parameters.Add(new SubScopesLookupParameter<BoolData>("MoveTabu", "The tabu status of the move."));
|
---|
87 | }
|
---|
88 |
|
---|
89 | /// <summary>
|
---|
90 | /// Implements the tabu selection with the default aspiration criteria (choose a tabu move when it is better than the best so far).
|
---|
91 | /// </summary>
|
---|
92 | /// <param name="scopes">The scopes from which to select.</param>
|
---|
93 | /// <returns>The selected scopes.</returns>
|
---|
94 | protected override IScope[] Select(List<IScope> scopes) {
|
---|
95 | int count = NumberOfSelectedSubScopesParameter.ActualValue.Value;
|
---|
96 | bool copy = CopySelectedParameter.Value.Value;
|
---|
97 | bool aspiration = AspirationParameter.ActualValue.Value;
|
---|
98 | bool maximization = MaximizationParameter.ActualValue.Value;
|
---|
99 | double bestQuality = BestQualityParameter.ActualValue.Value;
|
---|
100 | ItemArray<DoubleData> moveQualities = MoveQualityParameter.ActualValue;
|
---|
101 | ItemArray<BoolData> moveTabus = MoveTabuParameter.ActualValue;
|
---|
102 |
|
---|
103 | IScope[] selected = new IScope[count];
|
---|
104 |
|
---|
105 | // remember scopes that should be removed
|
---|
106 | List<int> scopesToRemove = new List<int>();
|
---|
107 | for (int i = 0; i < scopes.Count; i++) {
|
---|
108 | if (count > 0 && (!moveTabus[i].Value
|
---|
109 | || aspiration && IsBetter(maximization, moveQualities[i].Value, bestQuality))) {
|
---|
110 | scopesToRemove.Add(i);
|
---|
111 | if (copy) selected[selected.Length - count] = (IScope)scopes[i].Clone();
|
---|
112 | else selected[selected.Length - count] = scopes[i];
|
---|
113 | count--;
|
---|
114 | if (count == 0) break;
|
---|
115 | }
|
---|
116 | }
|
---|
117 |
|
---|
118 | if (count > 0) throw new InvalidOperationException("TabuSelector: The neighborhood contained no or too little moves that are not tabu.");
|
---|
119 |
|
---|
120 | // remove from last to first so that the stored indices remain the same
|
---|
121 | if (!copy) {
|
---|
122 | while (scopesToRemove.Count > 0) {
|
---|
123 | scopes.RemoveAt(scopesToRemove[scopesToRemove.Count - 1]);
|
---|
124 | scopesToRemove.RemoveAt(scopesToRemove.Count - 1);
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 | return selected;
|
---|
129 | }
|
---|
130 |
|
---|
131 | private bool IsBetter(bool maximization, double moveQuality, double bestQuality) {
|
---|
132 | return (maximization && moveQuality > bestQuality || !maximization && moveQuality < bestQuality);
|
---|
133 | }
|
---|
134 | }
|
---|
135 | }
|
---|