#region License Information
/* HeuristicLab
* Copyright (C) 2002-2014 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;
namespace HeuristicLab.EvolutionTracking {
[StorableClass]
[Item("AfterCrossoverOperator", "A generic operator that can record genealogical relationships between crossover parents and children.")]
public class BeforeCrossoverOperator : EvolutionTrackingOperator, ICrossoverOperator where T : class,IItem {
private const string ParentsParameterName = "Parents";
private const string ChildParameterName = "Child";
public IScopeTreeLookupParameter ParentsParameter {
get { return (IScopeTreeLookupParameter)Parameters[ParentsParameterName]; }
}
public ILookupParameter ChildParameter {
get { return (ILookupParameter)Parameters[ChildParameterName]; }
}
protected BeforeCrossoverOperator(BeforeCrossoverOperator original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new BeforeCrossoverOperator(this, cloner);
}
public BeforeCrossoverOperator() {
Parameters.Add(new ScopeTreeLookupParameter(ParentsParameterName));
Parameters.Add(new LookupParameter(ChildParameterName));
}
protected List> CurrentGeneration {
get {
if (GenealogyGraph.Ranks.ContainsKey(Generations.Value))
return GenealogyGraph.Ranks[Generations.Value].Cast>().ToList();
return null;
}
}
private readonly Func getScopeId = s => ((StringValue)s.Variables["Id"].Value).Value;
public override IOperation Apply() {
if (CurrentGeneration == null) throw new Exception();
var subScopes = ExecutionContext.Scope.SubScopes;
var parentVertices = subScopes.Select(x => (GenealogyGraphNode)GenealogyGraph.GetVertex(getScopeId(x))).ToList();
var parents = ParentsParameter.ActualValue.ToList();
var childVertex = new GenealogyGraphNode {
// the child parameter does not have a value yet (it will be assigned after crossover),
// but the first parent is actually the future child so we use this
Content = parents[0],
Rank = parentVertices[0].Rank + 1
};
GenealogyGraph.AddVertex(childVertex);
foreach (var parentVertex in parentVertices) {
GenealogyGraph.AddArc(parentVertex, childVertex);
}
ExecutionContext.Scope.Variables.Add(new Variable("Id", new StringValue(childVertex.Id)));
return base.Apply();
}
}
}