using System; using System.Threading; using HeuristicLab.Common; // required for parameters collection using HeuristicLab.Core; // required for parameters collection using HeuristicLab.Data; // IntValue, ... using HeuristicLab.Optimization; // BasicAlgorithm using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; using HeuristicLab.Random; // MersenneTwister namespace EmptyAlgorithm { // each HL item needs to have a name and a description (BasicAlgorithm is an Item) // The name and description of items is shown in the GUI [Item(Name = "Priorizied Grammar Enumeration (PGE)", Description = "Priorizied grammar enumeration algorithm. Worm, T. and Chiu K., 'Prioritized Grammar Enumeration: Symbolic Regression by Dynamic Programming'. GECCO 2013")] // If the algorithm should be shown in the "New..." dialog it must be creatable. Entries in the new dialog are grouped to categories and ordered by priorities [Creatable(Category = CreatableAttribute.Categories.Algorithms, Priority = 999)] [StorableClass] // for persistence (storing your algorithm to a files or transfer to HeuristicLab.Hive) public class PGE : BasicAlgorithm { // This algorithm only works for BinaryProblems. // Overriding the ProblemType property has the effect that only RegressionProblems can be set as problem // for the algorithm in the GUI public override Type ProblemType { get { return typeof(RegressionProblem); } } public new RegressionProblem Problem { get { return (RegressionProblem)base.Problem; } } #region parameters // If an algorithm has parameters then we usually also add properties to access these parameters. // This is not strictly required but considered good shape. private IFixedValueParameter MaxIterationsParameter { get { return (IFixedValueParameter)Parameters["MaxIterations"]; } } public int MaxIterations { get { return MaxIterationsParameter.Value.Value; } set { MaxIterationsParameter.Value.Value = value; } } #endregion // createable items must have a default ctor public PGE() { // algorithm parameters are shown in the GUI Parameters.Add(new FixedValueParameter("MaxIterations", new IntValue(10000))); } // Persistence uses this ctor to improve deserialization efficiency. // If we would use the default ctor instead this would completely initialize the object (e.g. creating parameters) // even though the data is later overwritten by the stored data. [StorableConstructor] public PGE(bool deserializing) : base(deserializing) { } // Each clonable item must have a cloning ctor (deep cloning, the cloner is used to handle cyclic object references) public PGE(PGE original, Cloner cloner) : base(original, cloner) { // Don't forget to call the cloning ctor of the base class // TODO: if this class has fields then they need to be cloned here } public override IDeepCloneable Clone(Cloner cloner) { return new PGE(this, cloner); } protected override void Run(CancellationToken cancellationToken) { int maxIters = MaxIterations; var problem = Problem; var rand = new MersenneTwister(1234); var bestQuality = 0.0; var curItersItem = new IntValue(); var bestQualityItem = new DoubleValue(bestQuality); var curItersResult = new Result("Iteration", curItersItem); var bestQualityResult = new Result("Best quality", bestQualityItem); Results.Add(curItersResult); Results.Add(bestQualityResult); for (int i = 0; i < maxIters; i++) { curItersItem.Value = i; // ----------------------------- // IMPLEMENT YOUR ALGORITHM HERE // ----------------------------- // for a more elaborate algorithm check the source code of "HeuristicLab.Algorithms.ParameterlessPopulationPyramid" var quality = rand.NextDouble(); if (quality > bestQuality) { bestQuality = quality; bestQualityItem.Value = quality; } // check the cancellation token to see if the used clicked "Stop" if (cancellationToken.IsCancellationRequested) break; } Results.Add(new Result("Execution time", new TimeSpanValue(this.ExecutionTime))); } public override bool SupportsPause { get { return false; } } } }