#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.Algorithms.GeneticAlgorithm; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis.Symbolic; namespace HeuristicLab.Algorithms.DataAnalysis.Symbolic { [Item("Symbolic Data Analysis Island Genetic Algorithm", "A symbolic data analysis island genetic algorithm.")] [Creatable("Data Analysis")] [StorableClass] public sealed class SymbolicDataAnalysisIslandGeneticAlgorithm : IslandGeneticAlgorithm { private const string FixedSamplesParameterName = "NumberOfFixedSamples"; private const string FixedSamplesPartitionParameterName = "FixedSamplesPartition"; private const string FixedSamplesPartitionsParameterName = "FixedSamplesPartitions"; private const string EvaluatorParameterName = "IslandEvaluator"; private const string IslandIndexParameterName = "IslandIndex"; private const string ProblemEvaluatorParameterName = "ProblemEvaluator"; #region Problem Properties public override Type ProblemType { get { return typeof(ISymbolicDataAnalysisSingleObjectiveProblem); } } public new ISymbolicDataAnalysisSingleObjectiveProblem Problem { get { return (ISymbolicDataAnalysisSingleObjectiveProblem)base.Problem; } set { base.Problem = value; } } #endregion #region parameters public IFixedValueParameter FixedSamplesParameter { get { return (IFixedValueParameter)Parameters[FixedSamplesParameterName]; } } public IValueParameter> FixedSamplesPartitionsParameter { get { return (IValueParameter>)Parameters[FixedSamplesPartitionsParameterName]; } } public IValueParameter EvaluatorParameter { get { return (IValueParameter)Parameters[EvaluatorParameterName]; } } private ILookupParameter ProblemEvaluatorParameter { get { return (ILookupParameter)Parameters[ProblemEvaluatorParameterName]; } } #endregion #region properties public double FixedSamples { get { return FixedSamplesParameter.Value.Value; } set { FixedSamplesParameter.Value.Value = value; } } public ItemArray FixedSamplesPartitions { get { return FixedSamplesPartitionsParameter.Value; } set { FixedSamplesPartitionsParameter.Value = value; } } private readonly ScopeTreeAssigner islandIndexAssigner; #endregion [StorableConstructor] private SymbolicDataAnalysisIslandGeneticAlgorithm(bool deserializing) : base(deserializing) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { RegisterParameterEvents(); } private SymbolicDataAnalysisIslandGeneticAlgorithm(SymbolicDataAnalysisIslandGeneticAlgorithm original, Cloner cloner) : base(original, cloner) { RegisterParameterEvents(); } public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicDataAnalysisIslandGeneticAlgorithm(this, cloner); } public SymbolicDataAnalysisIslandGeneticAlgorithm() : base() { Parameters.Add(new FixedValueParameter(FixedSamplesParameterName, "The number of fixed samples used for fitness calculation in each island.", new PercentValue(0.2))); Parameters.Add(new ValueParameter>(FixedSamplesPartitionsParameterName, "The fixed samples partitions used for fitness calculation for every island.")); Parameters.Add(new OptionalValueParameter(EvaluatorParameterName, "The evaluator of the algorithm.")); Parameters.Add(new LookupParameter(ProblemEvaluatorParameterName, "Internal parameter for name translation", "Evaluator")); islandIndexAssigner = new ScopeTreeAssigner(); islandIndexAssigner.Name = "Insert island index"; islandIndexAssigner.LeftSideParameter.ActualName = IslandIndexParameterName; var readonlyIslandIndexes = Enumerable.Range(0, NumberOfIslands.Value).Select(x => (IntValue)new IntValue(x).AsReadOnly()); islandIndexAssigner.RightSideParameter.Value = new ItemArray(readonlyIslandIndexes); ScopeTreeAssigner fixedSamplesPartitionCreator = new ScopeTreeAssigner(); fixedSamplesPartitionCreator.Name = "Create fixed evaluation partition"; fixedSamplesPartitionCreator.LeftSideParameter.ActualName = FixedSamplesPartitionParameterName; fixedSamplesPartitionCreator.RightSideParameter.ActualName = FixedSamplesPartitionsParameterName; SubScopesCreator insertionPoint = OperatorGraph.Iterate().OfType().First(); islandIndexAssigner.Successor = fixedSamplesPartitionCreator; fixedSamplesPartitionCreator.Successor = insertionPoint.Successor; insertionPoint.Successor = islandIndexAssigner; ReevaluateImmigrants = true; ReevaluteElites = true; RegisterParameterEvents(); RecalculateFixedSamplesPartitions(); } private void RegisterParameterEvents() { if (Problem != null) Problem.FitnessCalculationPartition.ValueChanged += Problem_Reset; NumberOfIslandsParameter.ValueChanged += NumberOfIslandsParameter_ValueChanged; NumberOfIslandsParameter.Value.ValueChanged += (o, ev) => NumberOfIslandsParameterValue_Changed(); FixedSamplesParameter.Value.ValueChanged += (o, e) => { RecalculateFixedSamplesPartitions(); ReevaluateImmigrants = FixedSamples < Problem.FitnessCalculationPartition.Size; }; Analyzer.Operators.PropertyChanged += (o, e) => ParameterizeAnalyzers(); EvaluatorParameter.ValueChanged += (o, e) => ParameterizeEvaluator(); } protected override void ParameterizeSolutionsCreator() { base.ParameterizeSolutionsCreator(); SolutionsCreator.EvaluatorParameter.ActualName = EvaluatorParameterName; } protected override void ParameterizeMainLoop() { base.ParameterizeMainLoop(); MainLoop.EvaluatorParameter.ActualName = EvaluatorParameterName; MainLoop.QualityParameter.ActualName = EvaluatorParameter.Value.QualityParameter.ActualName; } protected override void ParameterizeAnalyzers() { base.ParameterizeAnalyzers(); foreach (var analyzer in Analyzer.Operators.OfType()) { IParameter evaluatorParameter; if (analyzer.Parameters.TryGetValue("Evaluator", out evaluatorParameter)) { ILookupParameter param = evaluatorParameter as ILookupParameter; if (evaluatorParameter != null) param.ActualName = ProblemEvaluatorParameterName; } } } private void ParameterizeEvaluator() { var evaluator = EvaluatorParameter.Value; evaluator.IterationsParameter.ActualName = "Generations"; evaluator.MaximumIterationsParameter.ActualName = MaximumGenerationsParameter.Name; evaluator.DataMigrationIntervalParameter.ActualName = MigrationIntervalParameter.Name; ParameterizeStochasticOperatorForIsland(evaluator); } private void NumberOfIslandsParameter_ValueChanged(object sender, EventArgs e) { NumberOfIslands.ValueChanged += (o, ev) => NumberOfIslandsParameterValue_Changed(); NumberOfIslandsParameterValue_Changed(); } private void NumberOfIslandsParameterValue_Changed() { var readonlyIslandIndexes = Enumerable.Range(0, NumberOfIslands.Value).Select(x => (IntValue)new IntValue(x).AsReadOnly()); islandIndexAssigner.RightSideParameter.Value = new ItemArray(readonlyIslandIndexes); RecalculateFixedSamplesPartitions(); } protected override void Problem_Reset(object sender, EventArgs e) { base.Problem_Reset(sender, e); RecalculateFixedSamplesPartitions(); } protected override void OnProblemChanged() { Problem.FitnessCalculationPartition.ValueChanged += Problem_Reset; if (Problem != null && EvaluatorParameter.Value == null) { EvaluatorParameter.Value = new RandomSamplesEvaluator(); } else if (Problem == null) EvaluatorParameter.Value = null; ParameterizeStochasticOperator(EvaluatorParameter.Value); RecalculateFixedSamplesPartitions(); base.OnProblemChanged(); } private void RecalculateFixedSamplesPartitions() { if (Problem == null) { FixedSamplesPartitions = new ItemArray(Enumerable.Repeat(new IntRange(), NumberOfIslands.Value)); return; } var samplesStart = Problem.FitnessCalculationPartition.Start; var samplesEnd = Problem.FitnessCalculationPartition.End; var totalSamples = Problem.FitnessCalculationPartition.Size; var fixedSamples = (int)(FixedSamples * totalSamples); var islands = NumberOfIslands.Value; double shift = (double)((totalSamples - fixedSamples)) / (islands - 1); int offset = (int)Math.Floor(shift); double remainder = shift - offset; List partitions = new List(); for (int i = 0; i < islands; i++) { var partitionStart = samplesStart + offset * i + (int)(remainder * i); partitions.Add(new IntRange(partitionStart, partitionStart + fixedSamples)); } //if the last partitions exceeds the allowed samples move the last partition forward. int exceedsSamples = partitions[partitions.Count - 1].End - samplesEnd; if (exceedsSamples > 0) { partitions[partitions.Count - 1].Start -= exceedsSamples; partitions[partitions.Count - 1].End -= exceedsSamples; } FixedSamplesPartitions = new ItemArray(partitions); } } }