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