#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.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.EvolutionTracking {
[StorableClass]
[Item("BeforeCrossoverOperator", "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]; }
}
public IValueParameter ExecutionCountParameter {
get { return (IValueParameter)Parameters["ExecutionCount"]; }
}
protected BeforeCrossoverOperator(BeforeCrossoverOperator original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new BeforeCrossoverOperator(this, cloner);
}
[StorableConstructor]
protected BeforeCrossoverOperator(bool deserializing) : base(deserializing) { }
public BeforeCrossoverOperator() {
Parameters.Add(new ScopeTreeLookupParameter(ParentsParameterName));
Parameters.Add(new LookupParameter(ChildParameterName));
Parameters.Add(new ValueParameter("ExecutionCount", new IntValue(0)));
}
private readonly Func getScopeId = s => ((StringValue)s.Variables["Id"].Value).Value;
public override IOperation Apply() {
ExecutionCountParameter.Value.Value++;
var subScopes = ExecutionContext.Scope.SubScopes;
var parentVertices = subScopes.Select(x => (GenealogyGraphNode)GenealogyGraph.GetById(getScopeId(x))).ToList();
if (!parentVertices.Any())
throw new InvalidOperationException("Could not retrieve parent vertices.");
var parents = ParentsParameter.ActualValue.ToList();
var childVertex = new GenealogyGraphNode(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();
}
}
}