#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; } } }