using System.Linq;
using HeuristicLab.Analysis;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Algorithms.IslandALPS {
///
/// An Operator which creates a Subscope and then copies the layers from each island grouped by Layernumber into the new
/// scope. Then the operator executes the specified Operator on each group and afterwards deletes the created scope.
/// G newScope - G
/// /|\ /\ /|\
/// I I I => L1 L2 I I I
/// / \ / \
/// L1 L2 L1 L2
///
[Item("GroupedLayerOperator", "")]
[StorableClass]
public class GroupedLayerOperator : InstrumentedOperator {
[StorableConstructor]
public GroupedLayerOperator(bool deserializing) : base(deserializing) {}
public GroupedLayerOperator(GroupedLayerOperator original, Cloner cloner) : base(original, cloner) {}
public GroupedLayerOperator() {
Parameters.Add(new ScopeParameter("CurrentScope", "The current scope where the operator gets executed."));
Parameters.Add(new OperatorParameter("Operator", "The operator which should be applied on all grouped scopes."));
//add results colletion to save the list of group result in
}
private ScopeParameter CurrentScopeParameter {
get { return (ScopeParameter) Parameters["CurrentScope"]; }
}
private OperatorParameter OperatorParameter {
get { return (OperatorParameter) Parameters["Operator"]; }
}
public IScope CurrentScope {
get { return CurrentScopeParameter.ActualValue; }
}
public IOperator Operator {
get { return OperatorParameter.Value; }
set { OperatorParameter.Value = value; }
}
private IScope GroupScope {
get {
if (CurrentScope.Variables.ContainsKey("GroupScope")) {
return CurrentScope.Variables["GroupScope"].Value as IScope;
}
var scope = new Scope();
CurrentScope.Variables.Add(new Variable("GroupScope", scope));
return scope;
}
}
public override IDeepCloneable Clone(Cloner cloner) {
return new GroupedLayerOperator(this, cloner);
}
public override IOperation InstrumentedApply() {
//create the subscope where the individuals get copied to.
var scope = GroupScope;
//descend to find the scope with individuals to copy
foreach (var islandScope in CurrentScope.SubScopes) {
var numScope = 0;
foreach (var layerScope in islandScope.SubScopes) {
//copy the individuals to the apropriate group (based on order in the ScopeTree, e.g. first layer into first group)
IScope analyzerScope;
if (scope.SubScopes.Count <= numScope) {
if (!scope.SubScopes.Any()) {
analyzerScope = new Scope();
var rc = new ResultCollection();
analyzerScope.Variables.Add(new Variable("GroupResults", rc));
analyzerScope.Variables.Add(new Variable("LayerNumber", new IntValue(numScope)));
}
else {
analyzerScope = scope.SubScopes.First().Clone() as IScope;
var rc = (ResultCollection) analyzerScope.Variables["GroupResults"].Value;
ClearHistoryRecursively(rc);
analyzerScope.Variables["LayerNumber"].Value = new IntValue(numScope);
//TODO: let a result collector update the lookups ?
}
scope.SubScopes.Add(analyzerScope);
}
else {
analyzerScope = scope.SubScopes[numScope];
}
//delete old individuals
analyzerScope.SubScopes.Clear();
foreach (var individual in layerScope.SubScopes) {
analyzerScope.SubScopes.Add(individual.Clone() as IScope);
}
numScope++;
}
}
//execute the operator on each grouped scope
var next = new OperationCollection(base.InstrumentedApply());
foreach (var scopeGroup in scope.SubScopes) {
var inner = new OperationCollection();
inner.Add(ExecutionContext.CreateOperation(Operator, scopeGroup));
next.Insert(0, inner);
}
return next;
}
//TODO: HL-INTEGRATION :Copied from ResultsHistoryWiper, When integrate create static apply method and delete this
private static void ClearHistoryRecursively(ResultCollection results) {
var values = results.Select(r => r.Value);
// Reset all values within results in results
foreach (var resultsCollection in values.OfType())
ClearHistoryRecursively(resultsCollection);
// Reset values
foreach (var dataTable in values.OfType()) {
foreach (var row in dataTable.Rows)
for (var i = 0; i < row.Values.Count; i++)
row.Values[i] = double.NaN;
}
}
}
}