using System; using System.Linq; using System.Threading; using HeuristicLab.Algorithms.GrammaticalOptimization; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Optimization; using HeuristicLab.Problems.GrammaticalOptimization; using HeuristicLab.Selection; using HeuristicLab.Algorithms.GeneticAlgorithm; namespace HeuristicLab.Algorithms.GeneticProgramming { public class StandardGP : SolverBase { public int PopulationSize { get; set; } public double MutationRate { get; set; } public int TournamentGroupSize { get; set; } public int MaxSolutionSize { get; set; } public int MaxSolutionDepth { get; set; } private readonly ISymbolicExpressionTreeProblem problem; private readonly Random random; public StandardGP(ISymbolicExpressionTreeProblem problem, Random random) { this.problem = problem; this.random = random; // default parameter values PopulationSize = 1000; TournamentGroupSize = 7; MutationRate = 0.15; MaxSolutionSize = 100; MaxSolutionDepth = 17; } public override void Run(int maxEvaluations) { var hlProblem = new GenericSymbExprProblem(problem); var onEvalLocker = new object(); hlProblem.Evaluator.SolutionEvaluated += (sentence, quality) => { // raise solution evaluated event for each GP solution, don't scale quality to 0..1 // need to synchronize in case we are using a parallel engine lock (onEvalLocker) { OnSolutionEvaluated(sentence, quality); } }; hlProblem.MaximumSymbolicExpressionTreeLength.Value = MaxSolutionSize; hlProblem.MaximumSymbolicExpressionTreeDepth.Value = MaxSolutionDepth; using (var wh = new AutoResetEvent(false)) { var ga = new GeneticAlgorithm.GeneticAlgorithm(); ga.Engine = new ParallelEngine.ParallelEngine(); ga.ExceptionOccurred += (sender, args) => { Console.WriteLine(args.Value.Message); wh.Set(); }; ga.Stopped += (sender, args) => { wh.Set(); }; ga.Problem = hlProblem; var mutator = (MultiSymbolicExpressionTreeManipulator)ga.MutatorParameter.ValidValues.Single(op => op.Name == "MultiSymbolicExpressionTreeManipulator"); foreach (var op in mutator.Operators) { if (op.Name == "ChangeNodeTypeManipulation" || op.Name == "ReplaceBranchManipulation") mutator.Operators.SetItemCheckedState(op, true); else mutator.Operators.SetItemCheckedState(op, false); } ga.Mutator = mutator; ga.Crossover = ga.CrossoverParameter.ValidValues.Single(op => op.Name == "SubtreeSwappingCrossover"); var selector = (TournamentSelector)ga.SelectorParameter.ValidValues.Single(op => op.Name == "TournamentSelector"); selector.GroupSizeParameter.Value = new IntValue(TournamentGroupSize); ga.Selector = selector; ga.PopulationSize.Value = PopulationSize; ga.MaximumGenerations.Value = maxEvaluations / PopulationSize + 1; // one extra generation in case maxEvaluations is not a multiple of PopulationSize ga.MutationProbability.Value = MutationRate; ga.SetSeedRandomly = new BoolValue(false); ga.Seed = new IntValue(random.Next()); ga.Prepare(); ga.Start(); wh.WaitOne(); } } } }