#region License Information /* HeuristicLab * Copyright (C) 2002-2015 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.Linq; using HeuristicLab.Algorithms.GeneticAlgorithm; using HeuristicLab.Data; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Optimization.Operators; using HeuristicLab.Parameters; using HeuristicLab.Selection; namespace HeuristicLab.Algorithms.ALPS { public static class AlpsGeneticAlgorithmMainOperator { public static GeneticAlgorithmMainLoop Create() { var mainLoop = new GeneticAlgorithmMainLoop(); var selector = mainLoop.OperatorGraph.Iterate().OfType().First(o => o.OperatorParameter.ActualName == "Selector"); var crossover = mainLoop.OperatorGraph.Iterate().OfType().First(o => o.OperatorParameter.ActualName == "Crossover"); var subScopesCounter = mainLoop.OperatorGraph.Iterate().OfType().First(); var elitesMerger = mainLoop.OperatorGraph.Iterate().OfType().First(); // Operator starts with calculating number of selected scopes base on plus/comma-selection replacement scheme var numberOfSubScopesBranch = new ConditionalBranch() { Name = "PlusSelection?" }; var numberOfSelectedSubScopesPlusCalculator = new ExpressionCalculator() { Name = "NumberOfSelectedSubScopes = PopulationSize * 2" }; var numberOfSelectedSubScopesCalculator = new ExpressionCalculator() { Name = "NumberOfSelectedSubScopes = (PopulationSize - Elites) * 2" }; var replacementBranch = new ConditionalBranch() { Name = "PlusSelection?" }; // Set new initial operator mainLoop.OperatorGraph.InitialOperator = numberOfSubScopesBranch; numberOfSubScopesBranch.ConditionParameter.ActualName = "PlusSelection"; numberOfSubScopesBranch.TrueBranch = numberOfSelectedSubScopesPlusCalculator; numberOfSubScopesBranch.FalseBranch = numberOfSelectedSubScopesCalculator; numberOfSubScopesBranch.Successor = selector; numberOfSelectedSubScopesPlusCalculator.CollectedValues.Add(new LookupParameter("PopulationSize")); numberOfSelectedSubScopesPlusCalculator.ExpressionResultParameter.ActualName = "NumberOfSelectedSubScopes"; numberOfSelectedSubScopesPlusCalculator.ExpressionParameter.Value = new StringValue("PopulationSize 2 * toint"); numberOfSelectedSubScopesCalculator.CollectedValues.Add(new LookupParameter("PopulationSize")); numberOfSelectedSubScopesCalculator.CollectedValues.Add(new LookupParameter("Elites")); numberOfSelectedSubScopesCalculator.ExpressionResultParameter.ActualName = "NumberOfSelectedSubScopes"; numberOfSelectedSubScopesCalculator.ExpressionParameter.Value = new StringValue("PopulationSize Elites - 2 * toint"); // Use Elitism or Plus-Selection as replacement strategy var selectedProcessor = (SubScopesProcessor)selector.Successor; var elitismReplacement = selectedProcessor.Successor; selectedProcessor.Successor = replacementBranch; replacementBranch.ConditionParameter.ActualName = "PlusSelection"; replacementBranch.FalseBranch = elitismReplacement; // Plus selection replacement var replacementMergingReducer = new MergingReducer(); var replacementBestSelector = new BestSelector(); var replacementRightReducer = new RightReducer(); replacementBranch.TrueBranch = replacementMergingReducer; replacementMergingReducer.Successor = replacementBestSelector; replacementBestSelector.NumberOfSelectedSubScopesParameter.ActualName = "PopulationSize"; replacementBestSelector.CopySelected = new BoolValue(false); replacementBestSelector.Successor = replacementRightReducer; replacementRightReducer.Successor = null; // Increment ages of all individuals after replacement var incrementAgeProcessor = new UniformSubScopesProcessor(); var ageIncrementor = new DoubleCounter() { Name = "Increment Age" }; replacementBranch.Successor = incrementAgeProcessor; incrementAgeProcessor.Operator = ageIncrementor; incrementAgeProcessor.Successor = null; ageIncrementor.ValueParameter.ActualName = "Age"; ageIncrementor.Increment = new DoubleValue(1.0); // Insert AgeCalculator between crossover and its successor var crossoverSuccessor = crossover.Successor; var ageCalculator = new WeightingReducer() { Name = "Calculate Age" }; crossover.Successor = ageCalculator; ageCalculator.ParameterToReduce.ActualName = "Age"; ageCalculator.TargetParameter.ActualName = "Age"; ageCalculator.WeightParameter.ActualName = "AgeInheritance"; ageCalculator.Successor = crossoverSuccessor; // When counting the evaluated solutions, write in LayerEvaluatedSolutions subScopesCounter.ValueParameter.ActualName = "LayerEvaluatedSolutions"; subScopesCounter.AccumulateParameter.Value = new BoolValue(false); // Instead of generational loop after merging of elites, stop elitesMerger.Successor = null; // Parameterize foreach (var stochasticOperator in mainLoop.OperatorGraph.Iterate().OfType()) stochasticOperator.RandomParameter.ActualName = "LocalRandom"; foreach (var stochasticBranch in mainLoop.OperatorGraph.Iterate().OfType()) stochasticBranch.RandomParameter.ActualName = "LocalRandom"; // Remove unused operators var usedOperators = mainLoop.OperatorGraph.Iterate(); var unusedOperators = mainLoop.OperatorGraph.Operators.Except(usedOperators); foreach (var op in unusedOperators.ToList()) mainLoop.OperatorGraph.Operators.Remove(op); return mainLoop; } } }