#region License Information /* HeuristicLab * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * and the BEACON Center for the Study of Evolution in Action. * * 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.Threading; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.PluginInfrastructure; using HeuristicLab.Random; namespace HeuristicLab.Algorithms.IteratedSymbolicExpressionConstruction { [Item("Iterated Symbolic Expression Construction", "Generates symbolic expression trees iteratively.")] [StorableClass] [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms, Priority = 400)] public class IteratedSymbolicExpressionConstruction : BasicAlgorithm { public override Type ProblemType { get { return typeof(SymbolicExpressionTreeProblem); } } public new SymbolicExpressionTreeProblem Problem { get { return (SymbolicExpressionTreeProblem)base.Problem; } set { base.Problem = value; } } #region ParameterNames private const string MaximumEvaluationsParameterName = "Maximum Evaluations"; private const string SeedParameterName = "Seed"; private const string SetSeedRandomlyParameterName = "SetSeedRandomly"; private const string ResultUpdateIntervalParameterName = "ResultUpdateInterval"; private const string PolicyParameterName = "Policy"; #endregion #region ParameterProperties public IFixedValueParameter MaximumEvaluationsParameter { get { return (IFixedValueParameter)Parameters[MaximumEvaluationsParameterName]; } } public IFixedValueParameter SeedParameter { get { return (IFixedValueParameter)Parameters[SeedParameterName]; } } public IFixedValueParameter SetSeedRandomlyParameter { get { return (IFixedValueParameter)Parameters[SetSeedRandomlyParameterName]; } } public IFixedValueParameter ResultUpdateIntervalParameter { get { return (IFixedValueParameter)Parameters[ResultUpdateIntervalParameterName]; } } public IValueParameter PolicyParameter { get { return (IValueParameter)Parameters[PolicyParameterName]; } } #endregion #region Properties public int MaximumEvaluations { get { return MaximumEvaluationsParameter.Value.Value; } set { MaximumEvaluationsParameter.Value.Value = value; } } public int Seed { get { return SeedParameter.Value.Value; } set { SeedParameter.Value.Value = value; } } public bool SetSeedRandomly { get { return SetSeedRandomlyParameter.Value.Value; } set { SetSeedRandomlyParameter.Value.Value = value; } } public int ResultUpdateInterval { get { return ResultUpdateIntervalParameter.Value.Value; } set { ResultUpdateIntervalParameter.Value.Value = value; } } #endregion #region ResultsProperties public double ResultsBestQuality { get { return ((DoubleValue)Results["Best Quality"].Value).Value; } } public int ResultsBestFoundOnEvaluation { get { return ((IntValue)Results["Evaluation Best Solution Was Found"].Value).Value; } } public int ResultsEvaluations { get { return ((IntValue)Results["Evaluations"].Value).Value; } } public DataTable ResultsQualities { get { return ((DataTable)Results["Qualities"].Value); } } public DataRow ResultsQualitiesBest { get { return ResultsQualities.Rows["Best Quality"]; } } public DataRow ResultQualitiesAverage { get { return ResultsQualities.Rows["Average Quality"]; } } #endregion private readonly IRandom random = new MersenneTwister(); [StorableConstructor] protected IteratedSymbolicExpressionConstruction(bool deserializing) : base(deserializing) { } protected IteratedSymbolicExpressionConstruction(IteratedSymbolicExpressionConstruction original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new IteratedSymbolicExpressionConstruction(this, cloner); } public IteratedSymbolicExpressionConstruction() { Parameters.Add(new FixedValueParameter(MaximumEvaluationsParameterName, "", new IntValue(500000))); Parameters.Add(new FixedValueParameter(ResultUpdateIntervalParameterName, "The update interval for the result values in number of evaluations", new IntValue(100))); Parameters.Add(new FixedValueParameter(SeedParameterName, "The random seed used to initialize the new pseudo random number generator.", new IntValue(0))); Parameters.Add(new FixedValueParameter(SetSeedRandomlyParameterName, "True if the random seed should be set to a random value, otherwise false.", new BoolValue (true))); Parameters.Add(new ValueParameter(PolicyParameterName, "The policy to use for exploring the search tree", new UcbSymbolicExpressionConstructionPolicy())); } protected override void Run(CancellationToken cancellationToken) { // TODO minimization problems if (!Problem.Maximization) throw new NotSupportedException("Minimization problems are not supported"); // Set up the algorithm if (SetSeedRandomly) Seed = new System.Random().Next(); random.Reset(Seed); //var policy = new RandomSymbolicExpressionConstructionPolicy(Problem, random); //var policy = new EpsGreedySymbolicExpressionConstructionPolicy(Problem, random, new TabularMaxQualityFunction(new DefaultStateFunction())); //var policy = new EpsGreedySymbolicExpressionConstructionPolicy(Problem, random, new TabularAvgQualityFunction(new DefaultStateFunction())); //var policy = new EpsGreedySymbolicExpressionConstructionPolicy(Problem, random, new TabularMaxQualityFunction(new ParentChildStateFunction())); //var policy = new EpsGreedySymbolicExpressionConstructionPolicy(Problem, random, new TabularAvgQualityFunction(new ParentChildStateFunction())); //var policy = new UcbSymbolicExpressionConstructionPolicy(Problem, random, new TabularMaxQualityFunction(new DefaultStateFunction())); //var policy = new UcbWithStateAggregationSymbolicExpressionConstructionPolicy(Problem, random, 40); var policy = PolicyParameter.Value; policy.Initialize(Problem, random); IntValue evaluations = new IntValue(0); DoubleValue bestQuality = new DoubleValue(Double.NegativeInfinity); IntValue bestFoundOnEvaluation = new IntValue(0); // Set up the results display Results.Add(new Result("Evaluations", evaluations)); Results.Add(new Result("Best Quality", bestQuality)); Results.Add(new Result("Evaluation Best Solution Was Found", bestFoundOnEvaluation)); var table = new DataTable("Qualities"); var bestQualityRow = new DataRow("Best Quality"); table.Rows.Add(bestQualityRow); var currentQualityRow = new DataRow("Average Quality"); currentQualityRow.VisualProperties.LineStyle = DataRowVisualProperties.DataRowLineStyle.Dot; table.Rows.Add(currentQualityRow); Results.Add(new Result("Qualities", table)); // for problem-specific analyzer ISymbolicExpressionTree[] solutions = new ISymbolicExpressionTree[1]; double[] qualities = new double[1]; // the algorithm // Loop until iteration limit reached or canceled. int evals = 0; double sumQuality = 0; // for average quality calculation int resultUpdateInterval = ResultUpdateInterval; while (evals < MaximumEvaluations) { double quality = double.NaN; ISymbolicExpressionTree tree = null; IEnumerable> actionSequence; tree = policy.Sample(out actionSequence); quality = Problem.Evaluate(tree, random); evals++; sumQuality += quality; policy.Update(actionSequence, quality); // update statistics results in regular update intervals if ((evals - 1) % resultUpdateInterval == resultUpdateInterval - 1) { evaluations.Value = evals; bestQualityRow.Values.Add(bestQuality.Value); currentQualityRow.Values.Add(sumQuality / (double)resultUpdateInterval); sumQuality = 0; } // update best solution results whenever a new better solution is found if (Problem.IsBetter(quality, bestQuality.Value)) { bestQuality.Value = quality; bestFoundOnEvaluation.Value = evals; // for problem-specific analyzer solutions[0] = tree; qualities[0] = quality; } // run problem-specific analyzer in each iteration Problem.Analyze(solutions, qualities, Results, random); cancellationToken.ThrowIfCancellationRequested(); } } } }