#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; using HeuristicLab.Problems.DataAnalysis.Symbolic; using HeuristicLab.Random; using HeuristicLab.Selection; namespace HeuristicLab.Algorithms.DataAnalysis.Symbolic { [Item("Symbolic DataAnalysis 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 RandomSamplesParameterName = "NumberOfRandomSamples"; private const string EvaluatorParameterName = "IslandEvaluator"; 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 IFixedValueParameter RandomSamplesParameter { get { return (IFixedValueParameter)Parameters[RandomSamplesParameterName]; } } public IValueParameter EvaluatorParameter { get { return (IValueParameter)Parameters[EvaluatorParameterName]; } } private ILookupParameter ProblemEvaluatorParameter { get { return (ILookupParameter)Parameters[ProblemEvaluatorParameterName]; } } #endregion #region properties public int FixedSamples { get { return FixedSamplesParameter.Value.Value; } set { FixedSamplesParameter.Value.Value = value; } } public ItemArray FixedSamplesPartitions { get { return FixedSamplesPartitionsParameter.Value; } set { FixedSamplesPartitionsParameter.Value = value; } } public int RandomSamples { get { return RandomSamplesParameter.Value.Value; } set { RandomSamplesParameter.Value.Value = value; } } #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 IntValue(0))); Parameters.Add(new ValueParameter>(FixedSamplesPartitionsParameterName, "The fixed samples partitions used for fitness calculation for every island.")); Parameters.Add(new FixedValueParameter(RandomSamplesParameterName, "The number of random samples used for fitness calculation in each island.", new IntValue(0))); Parameters.Add(new OptionalValueParameter(EvaluatorParameterName, "The evaluator of the algorithm.")); Parameters.Add(new LookupParameter(ProblemEvaluatorParameterName, "Internal parameter for name translation", "Evaluator")); Elites.Value = 0; ElitesParameter.Hidden = true; ScopeTreeAssigner fixedSamplesPartitionCreator = new ScopeTreeAssigner(); fixedSamplesPartitionCreator.LeftSideParameter.ActualName = FixedSamplesPartitionParameterName; fixedSamplesPartitionCreator.RightSideParameter.ActualName = FixedSamplesPartitionsParameterName; RandomCreator insertionPoint = OperatorGraph.Iterate().OfType().Skip(1).First(); fixedSamplesPartitionCreator.Successor = insertionPoint.Successor; insertionPoint.Successor = fixedSamplesPartitionCreator; //necessary to reevaluate elites var evaluatorPlaceHolder = new Placeholder(); evaluatorPlaceHolder.OperatorParameter.ActualName = "Evaluator"; UniformSubScopesProcessor subScopesProcessor = new UniformSubScopesProcessor(); subScopesProcessor.Name = "Reevaluate elites"; subScopesProcessor.Parallel.Value = true; subScopesProcessor.Operator = evaluatorPlaceHolder; OperatorGraph.Iterate().OfType().First().Successor = subScopesProcessor; RegisterParameterEvents(); RecalculateFixedSamplesPartitions(); } private void RegisterParameterEvents() { if (Problem != null) Problem.FitnessCalculationPartition.ValueChanged += Problem_Reset; NumberOfIslandsParameter.ValueChanged += NumberOfIslandsParameter_ValueChanged; NumberOfIslandsParameter.Value.ValueChanged += (o, ev) => RecalculateFixedSamplesPartitions(); FixedSamplesParameter.Value.ValueChanged += (o, e) => RecalculateFixedSamplesPartitions(); Analyzer.Operators.PropertyChanged += (o, e) => ParameterizeAnalyzers(); } protected override void Problem_EvaluatorChanged(object sender, EventArgs e) { ParameterizeProblemEvaluator(); base.Problem_EvaluatorChanged(sender, e); } private void ParameterizeProblemEvaluator() { var regresssionEvaluator = Problem.Evaluator as ISymbolicDataAnalysisEvaluator; if (regresssionEvaluator != null) { regresssionEvaluator.EvaluationPartitionParameter.ActualName = FixedSamplesPartitionParameterName; } var classificationEvaluator = Problem.Evaluator as ISymbolicDataAnalysisEvaluator; if (classificationEvaluator != null) { classificationEvaluator.EvaluationPartitionParameter.ActualName = FixedSamplesPartitionParameterName; } } 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; } private void 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 NumberOfIslandsParameter_ValueChanged(object sender, EventArgs e) { NumberOfIslands.ValueChanged += (o, ev) => RecalculateFixedSamplesPartitions(); RecalculateFixedSamplesPartitions(); } protected override void Problem_Reset(object sender, EventArgs e) { FixedSamples = Problem.FitnessCalculationPartition.Size / NumberOfIslands.Value; RandomSamples = Problem.FitnessCalculationPartition.Size / NumberOfIslands.Value; RecalculateFixedSamplesPartitions(); ParameterizeProblemEvaluator(); base.Problem_Reset(sender, e); } protected override void OnProblemChanged() { Problem.FitnessCalculationPartition.ValueChanged += Problem_Reset; FixedSamples = Problem.FitnessCalculationPartition.Size / NumberOfIslands.Value; RandomSamples = Problem.FitnessCalculationPartition.Size / NumberOfIslands.Value; if (Problem is IRegressionProblem) { var evaluator = new SymbolicDataAnalysisIslandGAEvaluator(); evaluator.RandomSamplesParameter.ActualName = RandomSamplesParameterName; EvaluatorParameter.Value = evaluator; } else if (Problem is IClassificationProblem) { var evaluator = new SymbolicDataAnalysisIslandGAEvaluator(); evaluator.RandomSamplesParameter.ActualName = RandomSamplesParameterName; EvaluatorParameter.Value = evaluator; } else EvaluatorParameter.Value = null; ParameterizeProblemEvaluator(); ParameterizeStochasticOperatorForIsland(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 = FixedSamples; var islands = NumberOfIslands.Value; int offset = 0; //fixed samples partition do not overlap if (((double)totalSamples) / fixedSamples <= islands) { offset = totalSamples / islands; } else { offset = (totalSamples - fixedSamples) / (islands - 1); } List partitions = new List(); for (int i = 0; i < islands; i++) { var partitionStart = samplesStart + offset * i; partitions.Add(new IntRange(partitionStart, partitionStart + fixedSamples)); } //it can be the case that 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); } } }