#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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 System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Selection; namespace HeuristicLab.Optimization.Operators.LCS { [Item("NichingTournamentSelector", "Description missing")] [StorableClass] public class NichingTournamentSelector : StochasticSingleObjectiveSelector, INichingSingleObjectiveSelector { #region Parameter Properties public ValueLookupParameter GroupSizeParameter { get { return (ValueLookupParameter)Parameters["GroupSize"]; } } public ILookupParameter GAssistNichesProblemDataParameter { get { return (LookupParameter)Parameters["GAssistNichesProblemData"]; } } public ILookupParameter NichingParameter { get { return (LookupParameter)Parameters["Niching"]; } } public IValueLookupParameter ParentsPerChildParameter { get { return (IValueLookupParameter)Parameters["ParentsPerChild"]; } } public ILookupParameter> IndividualParameter { get { return (ILookupParameter>)Parameters["Individual"]; } } #endregion [StorableConstructor] protected NichingTournamentSelector(bool deserializing) : base(deserializing) { } protected NichingTournamentSelector(NichingTournamentSelector original, Cloner cloner) : base(original, cloner) { } public NichingTournamentSelector() : base() { Parameters.Add(new ValueLookupParameter("GroupSize", "The size of the tournament group.", new IntValue(2))); Parameters.Add(new LookupParameter("GAssistNichesProblemData", "")); Parameters.Add(new LookupParameter("Niching", "")); Parameters.Add(new ValueLookupParameter("ParentsPerChild", "")); Parameters.Add(new ScopeTreeLookupParameter("Individual", "")); } public override IDeepCloneable Clone(Cloner cloner) { return new NichingTournamentSelector(this, cloner); } protected override IScope[] Select(List scopes) { int count = NumberOfSelectedSubScopesParameter.ActualValue.Value; bool copy = CopySelectedParameter.Value.Value; IRandom random = RandomParameter.ActualValue; bool maximization = MaximizationParameter.ActualValue.Value; List qualities = QualityParameter.ActualValue.Where(x => IsValidQuality(x.Value)).Select(x => x.Value).ToList(); List individuals = IndividualParameter.ActualValue.ToList(); int groupSize = GroupSizeParameter.ActualValue.Value; IScope[] selected = new IScope[count]; bool doNiching = NichingParameter.ActualValue.Value; //check if list with indexes is as long as the original scope list //otherwise invalid quality values were filtered if (qualities.Count != scopes.Count || individuals.Count != scopes.Count) { throw new ArgumentException("The scopes contain invalid quality values (either infinity or double.NaN) on which the selector cannot operate."); } int parentsPerChild = ParentsPerChildParameter.ActualValue.Value; var nicheComparer = GAssistNichesProblemDataParameter.ActualValue.GetPossibleNiches().First().Comparer; var selectPerNiche = new Dictionary(nicheComparer); var nicheScope = new Dictionary>(nicheComparer); for (int i = 0; i < individuals.Count; i++) { if (!nicheScope.ContainsKey(individuals[i].Niche)) { nicheScope.Add(individuals[i].Niche, new List()); } nicheScope[individuals[i].Niche].Add(i); } var possibleNiches = nicheScope.Keys.ToList(); foreach (var niche in possibleNiches) { selectPerNiche.Add(niche, count / possibleNiches.Count); } int curCount = 0; while (curCount < count) { IGAssistNiche niche = null; int best = -1; if (doNiching) { niche = GetNiche(random, selectPerNiche, possibleNiches); } else { best = random.Next(scopes.Count); } for (int i = 0; i < parentsPerChild; i++) { int index; if (doNiching) { best = nicheScope[niche][random.Next(nicheScope[niche].Count)]; } for (int j = 1; j < groupSize; j++) { if (niche != null) { index = nicheScope[niche][random.Next(nicheScope[niche].Count)]; } else { index = random.Next(scopes.Count); } if (((maximization) && (qualities[index] > qualities[best])) || ((!maximization) && (qualities[index] < qualities[best]))) { best = index; } } niche = individuals[best].Niche; if (copy) selected[curCount] = (IScope)scopes[best].Clone(); else { selected[curCount] = scopes[best]; scopes.RemoveAt(best); qualities.RemoveAt(best); } selectPerNiche[niche]--; curCount++; } } return selected; } private IGAssistNiche GetNiche(IRandom random, Dictionary selectPerNiche, List possibleNiches) { int sum = selectPerNiche.Values.Sum(); if (sum <= 0) { return possibleNiches[random.Next(possibleNiches.Count)]; } int pos = random.Next(sum); int total = 0; IGAssistNiche niche = selectPerNiche.Keys.First(); foreach (var item in selectPerNiche) { total += item.Value; niche = item.Key; if (pos < total) { return niche; } } throw new ArgumentException("error in code"); } } }