#region License Information /* HeuristicLab * Copyright (C) 2002-2012 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.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Optimization.Operators.LCS { [StorableClass] [Item("MDLCalculator", "")] public class MDLCalculator : Item { [Storable] private int activationIteration; [Storable] private bool activated; [Storable] private bool fixedWeight; [Storable] private double theoryWeight; [Storable] private double initialTheoryLengthRatio; [Storable] private double weightRelaxFactor; [Storable] private IList accuracyStatistic; [Storable] private int iterationsSinceBest; [Storable] private double bestFitness; [Storable] private int weightAdaptionIterations; [StorableConstructor] protected MDLCalculator(bool deserializing) : base(deserializing) { } protected MDLCalculator(MDLCalculator original, Cloner cloner) : base(original, cloner) { } public MDLCalculator(int activationIteration, double initialTheoryLengthRatio, double weightRelaxFactor, int weightAdaptionIterations) : base() { this.activationIteration = activationIteration; this.initialTheoryLengthRatio = initialTheoryLengthRatio; this.weightRelaxFactor = weightRelaxFactor; this.weightAdaptionIterations = weightAdaptionIterations; activated = false; fixedWeight = false; accuracyStatistic = new List(); iterationsSinceBest = 0; } public override IDeepCloneable Clone(Cloner cloner) { return new MDLCalculator(this, cloner); } public void StartNewIteration(IGAssistSolution bestSolution, int currentIteration) { if (currentIteration == activationIteration) { activated = true; double error = bestSolution.TrainingExceptionsLength; double tl = (bestSolution.TrainingTheoryLength * bestSolution.Classes) / bestSolution.TrainingNumberOfAliveRules; if (tl.IsAlmost(0.0)) { //as done in the original implementation tl = 0.00000001; } theoryWeight = (initialTheoryLengthRatio / (1.0 - initialTheoryLengthRatio)) * (error / tl); iterationsSinceBest = 0; } if (activated && !fixedWeight && GetLastIterationsAccuracyAverage(weightAdaptionIterations).IsAlmost(1.0)) { fixedWeight = true; } if (activated && !fixedWeight) { if (bestSolution.TrainingAccuracy.IsAlmost(1.0)) { if (iterationsSinceBest == weightAdaptionIterations) { theoryWeight *= weightRelaxFactor; iterationsSinceBest = 0; } } } UpdateStatistic(bestSolution.TrainingAccuracy); } private void UpdateStatistic(double accuracy) { if (iterationsSinceBest == 0) { bestFitness = accuracy; iterationsSinceBest++; } else if (accuracy > bestFitness) { bestFitness = accuracy; iterationsSinceBest = 1; } else { iterationsSinceBest++; } } private double GetLastIterationsAccuracyAverage(int iterations) { int startAt = accuracyStatistic.Count - iterations; startAt = startAt > 0 ? startAt : 0; return accuracyStatistic.Skip(startAt).Sum() / (accuracyStatistic.Count - startAt); } public double CalculateFitness(IGAssistSolution dls) { double fitness = 0; if (activated) { fitness = dls.TrainingTheoryLength * theoryWeight; } fitness += 105.0 - dls.TrainingAccuracy * 100.0; return fitness; } public double CalculateFitness(double theoryLength, double accuracy) { double fitness = 0; if (activated) { fitness = theoryLength * theoryWeight; } fitness += 105.0 - accuracy * 100.0; return fitness; } } }