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