#region License Information /* HeuristicLab * Copyright (C) 2002-2008 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.Xml; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.DataAnalysis; using HeuristicLab.Evolutionary; using HeuristicLab.GP.Interfaces; using HeuristicLab.Logging; using HeuristicLab.Modeling; using HeuristicLab.Operators; using HeuristicLab.Random; using HeuristicLab.Selection; namespace HeuristicLab.GP.StructureIdentification { public abstract class AlgorithmBase : ItemBase, IAlgorithm, IStochasticAlgorithm { public virtual string Name { get { return "GP"; } } public virtual string Description { get { return "TODO"; } } public abstract Dataset Dataset { get; set; } public abstract int TargetVariable { get; set; } public virtual double MutationRate { get { return GetVariableInjector().GetVariable("MutationRate").GetValue().Data; } set { GetVariableInjector().GetVariable("MutationRate").GetValue().Data = value; } } public virtual int PopulationSize { get { return GetVariableInjector().GetVariable("PopulationSize").GetValue().Data; } set { GetVariableInjector().GetVariable("PopulationSize").GetValue().Data = value; } } public virtual bool SetSeedRandomly { get { return GetRandomInjector().GetVariable("SetSeedRandomly").GetValue().Data; } set { GetRandomInjector().GetVariable("SetSeedRandomly").GetValue().Data = value; } } public virtual int RandomSeed { get { return GetRandomInjector().GetVariable("Seed").GetValue().Data; } set { GetRandomInjector().GetVariable("Seed").GetValue().Data = value; } } public virtual IOperator ProblemInjector { get { return algorithm.SubOperators[1]; } set { value.Name = "ProblemInjector"; algorithm.RemoveSubOperator(1); algorithm.AddSubOperator(value, 1); } } private IModel model; public virtual IModel Model { get { if (!engine.Terminated) throw new InvalidOperationException("The algorithm is still running. Wait until the algorithm is terminated to retrieve the result."); if (model == null) { IScope bestModelScope = engine.GlobalScope.GetVariableValue("BestValidationSolution", false); model = CreateGPModel(bestModelScope); } return model; } } public virtual int Elites { get { return GetVariableInjector().GetVariable("Elites").GetValue().Data; } set { GetVariableInjector().GetVariable("Elites").GetValue().Data = value; } } public virtual int MaxTreeSize { get { return GetVariableInjector().GetVariable("MaxTreeSize").GetValue().Data; } set { GetVariableInjector().GetVariable("MaxTreeSize").GetValue().Data = value; } } public virtual int MaxTreeHeight { get { return GetVariableInjector().GetVariable("MaxTreeHeight").GetValue().Data; } set { GetVariableInjector().GetVariable("MaxTreeHeight").GetValue().Data = value; } } public virtual int Parents { get { return GetVariableInjector().GetVariable("Parents").GetValue().Data; } set { GetVariableInjector().GetVariable("Parents").GetValue().Data = value; } } public virtual double PunishmentFactor { get { return GetVariableInjector().GetVariable("PunishmentFactor").GetValue().Data; } set { GetVariableInjector().GetVariable("PunishmentFactor").GetValue().Data = value; } } public virtual bool UseEstimatedTargetValue { get { return GetVariableInjector().GetVariable("UseEstimatedTargetValue").GetValue().Data; } set { GetVariableInjector().GetVariable("UseEstimatedTargetValue").GetValue().Data = value; } } private IOperator algorithm; private SequentialEngine.SequentialEngine engine; public IEngine Engine { get { return engine; } protected set { engine = (SequentialEngine.SequentialEngine)value; } } public AlgorithmBase() { engine = new SequentialEngine.SequentialEngine(); CombinedOperator algo = CreateAlgorithm(); engine.OperatorGraph.AddOperator(algo); engine.OperatorGraph.InitialOperator = algo; SetSeedRandomly = true; Elites = 1; MutationRate = 0.15; PopulationSize = 1000; MaxTreeSize = 100; MaxTreeHeight = 10; Parents = 2000; PunishmentFactor = 10; UseEstimatedTargetValue = false; } protected internal virtual CombinedOperator CreateAlgorithm() { CombinedOperator algo = new CombinedOperator(); algo.Name = "GP"; SequentialProcessor seq = new SequentialProcessor(); IOperator problemInjector = CreateProblemInjector(); RandomInjector randomInjector = new RandomInjector(); randomInjector.Name = "Random Injector"; IOperator globalInjector = CreateGlobalInjector(); IOperator initialization = CreateInitialization(); IOperator funLibInjector = CreateFunctionLibraryInjector(); IOperator mainLoop = CreateMainLoop(); mainLoop.Name = "Main loop"; IOperator treeCreator = CreateTreeCreator(); MeanSquaredErrorEvaluator evaluator = new MeanSquaredErrorEvaluator(); evaluator.GetVariableInfo("MSE").ActualName = "Quality"; evaluator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart"; evaluator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd"; evaluator.Name = "Evaluator"; IOperator crossover = CreateCrossover(); IOperator manipulator = CreateManipulator(); IOperator selector = CreateSelector(); LeftReducer cleanUp = new LeftReducer(); seq.AddSubOperator(randomInjector); seq.AddSubOperator(problemInjector); seq.AddSubOperator(globalInjector); seq.AddSubOperator(funLibInjector); seq.AddSubOperator(initialization); seq.AddSubOperator(mainLoop); seq.AddSubOperator(cleanUp); initialization.AddSubOperator(treeCreator); initialization.AddSubOperator(evaluator); mainLoop.AddSubOperator(selector); mainLoop.AddSubOperator(crossover); mainLoop.AddSubOperator(manipulator); mainLoop.AddSubOperator(evaluator); algo.OperatorGraph.AddOperator(seq); algo.OperatorGraph.InitialOperator = seq; this.algorithm = seq; return algo; } protected internal virtual IOperator CreateProblemInjector() { return new EmptyOperator(); } protected internal abstract IOperator CreateSelector(); protected internal abstract IOperator CreateCrossover(); protected internal abstract IOperator CreateTreeCreator(); protected internal abstract IOperator CreateFunctionLibraryInjector(); protected internal virtual IOperator CreateGlobalInjector() { VariableInjector injector = new VariableInjector(); injector.Name = "Global Injector"; injector.AddVariable(new HeuristicLab.Core.Variable("Generations", new IntData(0))); injector.AddVariable(new HeuristicLab.Core.Variable("MutationRate", new DoubleData())); injector.AddVariable(new HeuristicLab.Core.Variable("PopulationSize", new IntData())); injector.AddVariable(new HeuristicLab.Core.Variable("Elites", new IntData())); injector.AddVariable(new HeuristicLab.Core.Variable("Maximization", new BoolData(false))); injector.AddVariable(new HeuristicLab.Core.Variable("MaxTreeHeight", new IntData())); injector.AddVariable(new HeuristicLab.Core.Variable("MaxTreeSize", new IntData())); injector.AddVariable(new HeuristicLab.Core.Variable("EvaluatedSolutions", new IntData(0))); injector.AddVariable(new HeuristicLab.Core.Variable("TotalEvaluatedNodes", new DoubleData(0))); injector.AddVariable(new HeuristicLab.Core.Variable("Parents", new IntData())); injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData())); injector.AddVariable(new HeuristicLab.Core.Variable("UseEstimatedTargetValue", new BoolData())); injector.AddVariable(new HeuristicLab.Core.Variable("TreeEvaluator", new HL2TreeEvaluator())); return injector; } protected internal abstract IOperator CreateManipulator(); protected internal virtual IOperator CreateInitialization() { CombinedOperator init = new CombinedOperator(); init.Name = "Initialization"; SequentialProcessor seq = new SequentialProcessor(); SubScopesCreater subScopesCreater = new SubScopesCreater(); subScopesCreater.GetVariableInfo("SubScopes").ActualName = "PopulationSize"; UniformSequentialSubScopesProcessor subScopesProc = new UniformSequentialSubScopesProcessor(); SequentialProcessor individualSeq = new SequentialProcessor(); OperatorExtractor treeCreater = new OperatorExtractor(); treeCreater.Name = "Tree generator (extr.)"; treeCreater.GetVariableInfo("Operator").ActualName = "Tree generator"; OperatorExtractor evaluator = new OperatorExtractor(); evaluator.Name = "Evaluator (extr.)"; evaluator.GetVariableInfo("Operator").ActualName = "Evaluator"; MeanSquaredErrorEvaluator validationEvaluator = new MeanSquaredErrorEvaluator(); validationEvaluator.GetVariableInfo("MSE").ActualName = "ValidationQuality"; validationEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart"; validationEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd"; Counter evalCounter = new Counter(); evalCounter.GetVariableInfo("Value").ActualName = "EvaluatedSolutions"; Sorter sorter = new Sorter(); sorter.GetVariableInfo("Descending").ActualName = "Maximization"; sorter.GetVariableInfo("Value").ActualName = "Quality"; seq.AddSubOperator(subScopesCreater); seq.AddSubOperator(subScopesProc); seq.AddSubOperator(sorter); subScopesProc.AddSubOperator(individualSeq); individualSeq.AddSubOperator(treeCreater); individualSeq.AddSubOperator(evaluator); individualSeq.AddSubOperator(validationEvaluator); individualSeq.AddSubOperator(evalCounter); init.OperatorGraph.AddOperator(seq); init.OperatorGraph.InitialOperator = seq; return init; } protected internal virtual IOperator CreateMainLoop() { CombinedOperator main = new CombinedOperator(); SequentialProcessor seq = new SequentialProcessor(); IOperator childCreater = CreateChildCreater(); IOperator replacement = CreateReplacement(); BestSolutionStorer solutionStorer = new BestSolutionStorer(); solutionStorer.GetVariableInfo("Quality").ActualName = "ValidationQuality"; solutionStorer.GetVariableInfo("BestSolution").ActualName = "BestValidationSolution"; solutionStorer.AddSubOperator(CreateBestSolutionProcessor()); BestAverageWorstQualityCalculator qualityCalculator = new BestAverageWorstQualityCalculator(); BestAverageWorstQualityCalculator validationQualityCalculator = new BestAverageWorstQualityCalculator(); validationQualityCalculator.Name = "BestAverageWorstValidationQualityCalculator"; validationQualityCalculator.GetVariableInfo("Quality").ActualName = "ValidationQuality"; validationQualityCalculator.GetVariableInfo("BestQuality").ActualName = "BestValidationQuality"; validationQualityCalculator.GetVariableInfo("AverageQuality").ActualName = "AverageValidationQuality"; validationQualityCalculator.GetVariableInfo("WorstQuality").ActualName = "WorstValidationQuality"; IOperator loggingOperator = CreateLoggingOperator(); Counter counter = new Counter(); counter.GetVariableInfo("Value").ActualName = "Generations"; IOperator loopCondition = CreateLoopCondition(seq); seq.AddSubOperator(childCreater); seq.AddSubOperator(replacement); seq.AddSubOperator(solutionStorer); seq.AddSubOperator(qualityCalculator); seq.AddSubOperator(validationQualityCalculator); seq.AddSubOperator(loggingOperator); seq.AddSubOperator(counter); seq.AddSubOperator(loopCondition); main.OperatorGraph.AddOperator(seq); main.OperatorGraph.InitialOperator = seq; return main; } protected internal virtual IOperator CreateLoggingOperator() { return new EmptyOperator(); } protected internal virtual IOperator CreateLoopCondition(IOperator loop) { SequentialProcessor seq = new SequentialProcessor(); seq.Name = "Loop Condition"; LessThanComparator comparator = new LessThanComparator(); comparator.GetVariableInfo("LeftSide").ActualName = "Generations"; comparator.GetVariableInfo("RightSide").ActualName = "MaxGenerations"; comparator.GetVariableInfo("Result").ActualName = "GenerationsCondition"; ConditionalBranch cond = new ConditionalBranch(); cond.GetVariableInfo("Condition").ActualName = "GenerationsCondition"; seq.AddSubOperator(comparator); seq.AddSubOperator(cond); cond.AddSubOperator(loop); return seq; } protected internal virtual IOperator CreateBestSolutionProcessor() { return new EmptyOperator(); } protected internal virtual IOperator CreateReplacement() { CombinedOperator replacement = new CombinedOperator(); replacement.Name = "Replacement"; SequentialProcessor seq = new SequentialProcessor(); SequentialSubScopesProcessor seqScopeProc = new SequentialSubScopesProcessor(); SequentialProcessor selectedProc = new SequentialProcessor(); LeftSelector leftSelector = new LeftSelector(); leftSelector.GetVariableInfo("Selected").ActualName = "Elites"; RightReducer rightReducer = new RightReducer(); SequentialProcessor remainingProc = new SequentialProcessor(); RightSelector rightSelector = new RightSelector(); rightSelector.GetVariableInfo("Selected").ActualName = "Elites"; LeftReducer leftReducer = new LeftReducer(); MergingReducer mergingReducer = new MergingReducer(); Sorter sorter = new Sorter(); sorter.GetVariableInfo("Descending").ActualName = "Maximization"; sorter.GetVariableInfo("Value").ActualName = "Quality"; seq.AddSubOperator(seqScopeProc); seqScopeProc.AddSubOperator(selectedProc); selectedProc.AddSubOperator(leftSelector); selectedProc.AddSubOperator(rightReducer); seqScopeProc.AddSubOperator(remainingProc); remainingProc.AddSubOperator(rightSelector); remainingProc.AddSubOperator(leftReducer); seq.AddSubOperator(mergingReducer); seq.AddSubOperator(sorter); replacement.OperatorGraph.AddOperator(seq); replacement.OperatorGraph.InitialOperator = seq; return replacement; } protected internal virtual IOperator CreateChildCreater() { CombinedOperator childCreater = new CombinedOperator(); childCreater.Name = "Create children"; SequentialProcessor seq = new SequentialProcessor(); OperatorExtractor selector = new OperatorExtractor(); selector.Name = "Selector (extr.)"; selector.GetVariableInfo("Operator").ActualName = "Selector"; SequentialSubScopesProcessor seqScopesProc = new SequentialSubScopesProcessor(); EmptyOperator emptyOpt = new EmptyOperator(); SequentialProcessor selectedProc = new SequentialProcessor(); ChildrenInitializer childInitializer = new ChildrenInitializer(); ((IntData)childInitializer.GetVariable("ParentsPerChild").Value).Data = 2; OperatorExtractor crossover = new OperatorExtractor(); crossover.Name = "Crossover (extr.)"; crossover.GetVariableInfo("Operator").ActualName = "Crossover"; UniformSequentialSubScopesProcessor individualProc = new UniformSequentialSubScopesProcessor(); SequentialProcessor individualSeqProc = new SequentialProcessor(); StochasticBranch cond = new StochasticBranch(); cond.GetVariableInfo("Probability").ActualName = "MutationRate"; OperatorExtractor manipulator = new OperatorExtractor(); manipulator.Name = "Manipulator (extr.)"; manipulator.GetVariableInfo("Operator").ActualName = "Manipulator"; OperatorExtractor evaluator = new OperatorExtractor(); evaluator.Name = "Evaluator (extr.)"; evaluator.GetVariableInfo("Operator").ActualName = "Evaluator"; MeanSquaredErrorEvaluator validationEvaluator = new MeanSquaredErrorEvaluator(); validationEvaluator.GetVariableInfo("MSE").ActualName = "ValidationQuality"; validationEvaluator.GetVariableInfo("SamplesStart").ActualName = "ValidationSamplesStart"; validationEvaluator.GetVariableInfo("SamplesEnd").ActualName = "ValidationSamplesEnd"; Counter evalCounter = new Counter(); evalCounter.GetVariableInfo("Value").ActualName = "EvaluatedSolutions"; SubScopesRemover parentRefRemover = new SubScopesRemover(); Sorter sorter = new Sorter(); sorter.GetVariableInfo("Descending").ActualName = "Maximization"; sorter.GetVariableInfo("Value").ActualName = "Quality"; seq.AddSubOperator(selector); seq.AddSubOperator(seqScopesProc); seqScopesProc.AddSubOperator(emptyOpt); seqScopesProc.AddSubOperator(selectedProc); selectedProc.AddSubOperator(childInitializer); selectedProc.AddSubOperator(individualProc); individualProc.AddSubOperator(individualSeqProc); individualSeqProc.AddSubOperator(crossover); individualSeqProc.AddSubOperator(cond); cond.AddSubOperator(manipulator); individualSeqProc.AddSubOperator(evaluator); individualSeqProc.AddSubOperator(validationEvaluator); individualSeqProc.AddSubOperator(evalCounter); individualSeqProc.AddSubOperator(parentRefRemover); selectedProc.AddSubOperator(sorter); childCreater.OperatorGraph.AddOperator(seq); childCreater.OperatorGraph.InitialOperator = seq; return childCreater; } protected internal virtual Model CreateGPModel(IScope bestModelScope) { Engine.GlobalScope.AddSubScope(bestModelScope); Model model = new Model(); Dataset ds = bestModelScope.GetVariableValue("Dataset", true); model.Data = bestModelScope.GetVariableValue("FunctionTree", false); model.Dataset = ds; model.TargetVariable = ds.GetVariableName(bestModelScope.GetVariableValue("TargetVariable", true).Data); model.TrainingSamplesStart = bestModelScope.GetVariableValue("TrainingSamplesStart", true).Data; model.TrainingSamplesEnd = bestModelScope.GetVariableValue("TrainingSamplesEnd", true).Data; model.ValidationSamplesStart = bestModelScope.GetVariableValue("ValidationSamplesStart", true).Data; model.ValidationSamplesEnd = bestModelScope.GetVariableValue("ValidationSamplesEnd", true).Data; model.TestSamplesStart = bestModelScope.GetVariableValue("TestSamplesStart", true).Data; model.TestSamplesEnd = bestModelScope.GetVariableValue("TestSamplesEnd", true).Data; model.TrainingMeanSquaredError = bestModelScope.GetVariableValue("Quality", false).Data; model.ValidationMeanSquaredError = bestModelScope.GetVariableValue("ValidationQuality", false).Data; // calculate and set variable impacts VariableEvaluationImpactCalculator evaluationImpactCalculator = new VariableEvaluationImpactCalculator(); evaluationImpactCalculator.GetVariableInfo("TrainingSamplesStart").ActualName = "ActualTrainingSamplesStart"; evaluationImpactCalculator.GetVariableInfo("TrainingSamplesEnd").ActualName = "ActualTrainingSamplesEnd"; VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator(); qualityImpactCalculator.GetVariableInfo("TrainingSamplesStart").ActualName = "ActualTrainingSamplesStart"; qualityImpactCalculator.GetVariableInfo("TrainingSamplesEnd").ActualName = "ActualTrainingSamplesEnd"; evaluationImpactCalculator.Apply(bestModelScope); qualityImpactCalculator.Apply(bestModelScope); ItemList evaluationImpacts = bestModelScope.GetVariableValue("VariableEvaluationImpacts", false); ItemList qualityImpacts = bestModelScope.GetVariableValue("VariableQualityImpacts", false); foreach (ItemList row in evaluationImpacts) { string variableName = ((StringData)row[0]).Data; double impact = ((DoubleData)row[1]).Data; model.SetVariableEvaluationImpact(variableName, impact); model.AddInputVariables(variableName); } foreach (ItemList row in qualityImpacts) { string variableName = ((StringData)row[0]).Data; double impact = ((DoubleData)row[1]).Data; model.SetVariableQualityImpact(variableName, impact); model.AddInputVariables(variableName); } Engine.GlobalScope.RemoveSubScope(bestModelScope); return model; } public override object Clone(IDictionary clonedObjects) { AlgorithmBase clone = (AlgorithmBase)base.Clone(clonedObjects); clonedObjects.Add(Guid, clone); clone.engine = (SequentialEngine.SequentialEngine)Auxiliary.Clone(Engine, clonedObjects); return clone; } protected VariableInjector GetVariableInjector() { CombinedOperator co1 = (CombinedOperator)Engine.OperatorGraph.InitialOperator; // SequentialProcessor in GP algorithm = (SequentialProcessor)co1.OperatorGraph.InitialOperator; return (VariableInjector)algorithm.SubOperators[2]; } protected RandomInjector GetRandomInjector() { CombinedOperator co1 = (CombinedOperator)Engine.OperatorGraph.InitialOperator; // SequentialProcessor in GP algorithm = (SequentialProcessor)co1.OperatorGraph.InitialOperator; return (RandomInjector)algorithm.SubOperators[0]; } #region Persistence Methods public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary persistedObjects) { XmlNode node = base.GetXmlNode(name, document, persistedObjects); node.AppendChild(PersistenceManager.Persist("Engine", Engine, document, persistedObjects)); return node; } public override void Populate(XmlNode node, IDictionary restoredObjects) { base.Populate(node, restoredObjects); engine = (SequentialEngine.SequentialEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects); } #endregion } }