#region License Information
/* HeuristicLab
* Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections.Generic;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Operators;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Selection;
namespace HeuristicLab.Algorithms.TS {
///
/// 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.
///
///
/// For different aspiration criteria a new operator should be implemented.
///
[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.")]
[EmptyStorableClass]
public class TabuSelector : Selector {
///
/// The quality of the current solution.
///
public LookupParameter QualityParameter {
get { return (LookupParameter)Parameters["Quality"]; }
}
///
/// The best found quality so far.
///
public LookupParameter BestQualityParameter {
get { return (LookupParameter)Parameters["BestQuality"]; }
}
///
/// Whether to use the default aspiration criteria or not.
///
public ValueLookupParameter AspirationParameter {
get { return (ValueLookupParameter)Parameters["Aspiration"]; }
}
///
/// Whether the problem is a maximization problem or not.
///
public IValueLookupParameter MaximizationParameter {
get { return (IValueLookupParameter)Parameters["Maximization"]; }
}
///
/// The parameter for the move qualities.
///
public ILookupParameter> MoveQualityParameter {
get { return (ILookupParameter>)Parameters["MoveQuality"]; }
}
///
/// The parameter for the tabu status of the moves.
///
public ILookupParameter> MoveTabuParameter {
get { return (ILookupParameter>)Parameters["MoveTabu"]; }
}
///
/// Initializes a new intsance with 6 parameters (Quality, BestQuality,
/// Aspiration, Maximization, MoveQuality, and MoveTabu).
///
public TabuSelector()
: base() {
Parameters.Add(new LookupParameter("Quality", "The quality of the current solution."));
Parameters.Add(new LookupParameter("BestQuality", "The best found quality so far."));
Parameters.Add(new ValueLookupParameter("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)));
Parameters.Add(new ValueLookupParameter("Maximization", "Whether the problem is a maximization or minimization problem (used to decide whether a solution is better"));
Parameters.Add(new SubScopesLookupParameter("MoveQuality", "The quality of the move."));
Parameters.Add(new SubScopesLookupParameter("MoveTabu", "The tabu status of the move."));
}
///
/// Implements the tabu selection with the default aspiration criteria (choose a tabu move when it is better than the best so far).
///
/// The scopes from which to select.
/// The selected scopes.
protected override IScope[] Select(List scopes) {
int count = NumberOfSelectedSubScopesParameter.ActualValue.Value;
bool copy = CopySelectedParameter.Value.Value;
bool aspiration = AspirationParameter.ActualValue.Value;
bool maximization = MaximizationParameter.ActualValue.Value;
double bestQuality = BestQualityParameter.ActualValue.Value;
double quality = QualityParameter.ActualValue.Value;
ItemArray moveQualities = MoveQualityParameter.ActualValue;
ItemArray moveTabus = MoveTabuParameter.ActualValue;
IScope[] selected = new IScope[count];
// remember scopes that should be removed
List scopesToRemove = new List();
for (int i = 0; i < scopes.Count; i++) {
if (count > 0 && (!moveTabus[i].Value || aspiration &&
(maximization && moveQualities[i].Value + quality > bestQuality
|| !maximization && moveQualities[i].Value + quality < bestQuality))) {
scopesToRemove.Add(i);
if (copy) selected[selected.Length - count] = (IScope)scopes[i].Clone();
else selected[selected.Length - count] = scopes[i];
count--;
if (count == 0) break;
}
}
if (count > 0) throw new InvalidOperationException("TabuSelector: The neighborhood contained no or too little moves that are not tabu.");
// remove from last to first so that the stored indices remain the same
if (!copy) {
while (scopesToRemove.Count > 0) {
scopes.RemoveAt(scopesToRemove[scopesToRemove.Count - 1]);
scopesToRemove.RemoveAt(scopesToRemove.Count - 1);
}
}
return selected;
}
}
}