#region License Information /* HeuristicLab * Copyright (C) 2002-2015 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.Linq; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Optimization.Operators; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.Instances; namespace HeuristicLab.Problems.TestFunctions { [Item("Test Function (single-objective)", "Test function with real valued inputs and a single objective.")] [StorableClass] [Creatable(CreatableAttribute.Categories.Problems, Priority = 90)] public sealed class SingleObjectiveTestFunctionProblem : SingleObjectiveProblem, IProblemInstanceConsumer { public override bool Maximization { get { return Parameters.ContainsKey("TestFunction") && TestFunction.Maximization; } } #region Parameter Properties private IFixedValueParameter ProblemSizeParameter { get { return (IFixedValueParameter)Parameters["ProblemSize"]; } } private IValueParameter BoundsParameter { get { return (IValueParameter)Parameters["Bounds"]; } } public OptionalValueParameter BestKnownSolutionParameter { get { return (OptionalValueParameter)Parameters["BestKnownSolution"]; } } public IValueParameter TestFunctionParameter { get { return (IValueParameter)Parameters["TestFunction"]; } } #endregion #region Properties public int ProblemSize { get { return ProblemSizeParameter.Value.Value; } set { ProblemSizeParameter.Value.Value = value; } } public DoubleMatrix Bounds { get { return BoundsParameter.Value; } set { BoundsParameter.Value = value; } } public ISingleObjectiveTestFunction TestFunction { get { return TestFunctionParameter.Value; } set { TestFunctionParameter.Value = value; } } private BestSingleObjectiveTestFunctionSolutionAnalyzer BestSingleObjectiveTestFunctionSolutionAnalyzer { get { return Operators.OfType().FirstOrDefault(); } } #endregion [StorableConstructor] private SingleObjectiveTestFunctionProblem(bool deserializing) : base(deserializing) { } private SingleObjectiveTestFunctionProblem(SingleObjectiveTestFunctionProblem original, Cloner cloner) : base(original, cloner) { RegisterEventHandlers(); } public SingleObjectiveTestFunctionProblem() : base(new RealVectorEncoding("Point")) { Parameters.Add(new FixedValueParameter("ProblemSize", "The dimensionality of the problem instance (number of variables in the function).", new IntValue(2))); Parameters.Add(new ValueParameter("Bounds", "The bounds of the solution given as either one line for all variables or a line for each variable. The first column specifies lower bound, the second upper bound.", new DoubleMatrix(new double[,] { { -100, 100 } }))); Parameters.Add(new OptionalValueParameter("BestKnownSolution", "The best known solution for this test function instance.")); Parameters.Add(new ValueParameter("TestFunction", "The function that is to be optimized.", new Ackley())); Encoding.LengthParameter = ProblemSizeParameter; Encoding.BoundsParameter = BoundsParameter; BestKnownQuality = TestFunction.BestKnownQuality; InitializeOperators(); RegisterEventHandlers(); } public override IDeepCloneable Clone(Cloner cloner) { return new SingleObjectiveTestFunctionProblem(this, cloner); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { RegisterEventHandlers(); } private void RegisterEventHandlers() { Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged; TestFunctionParameter.ValueChanged += TestFunctionParameterOnValueChanged; ProblemSizeParameter.Value.ValueChanged += ProblemSizeOnValueChanged; BoundsParameter.ValueChanged += BoundsParameterOnValueChanged; } public override double Evaluate(RealVector individual, IRandom random) { return TestFunction.Evaluate(individual); } #region Events protected override void OnEncodingChanged() { base.OnEncodingChanged(); Parameterize(); } protected override void OnEvaluatorChanged() { base.OnEvaluatorChanged(); Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged; Parameterize(); } private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) { Parameterize(); } private void TestFunctionParameterOnValueChanged(object sender, EventArgs eventArgs) { var problemSizeChange = ProblemSize < TestFunction.MinimumProblemSize || ProblemSize > TestFunction.MaximumProblemSize; if (problemSizeChange) { ProblemSize = Math.Max(TestFunction.MinimumProblemSize, Math.Min(ProblemSize, TestFunction.MaximumProblemSize)); } BestKnownQuality = TestFunction.BestKnownQuality; Bounds = (DoubleMatrix)TestFunction.Bounds.Clone(); var bestSolution = TestFunction.GetBestKnownSolution(ProblemSize); BestKnownSolutionParameter.Value = bestSolution; OnReset(); } private void ProblemSizeOnValueChanged(object sender, EventArgs eventArgs) { if (ProblemSize < TestFunction.MinimumProblemSize || ProblemSize > TestFunction.MaximumProblemSize) ProblemSize = Math.Min(TestFunction.MaximumProblemSize, Math.Max(TestFunction.MinimumProblemSize, ProblemSize)); } private void BoundsParameterOnValueChanged(object sender, EventArgs eventArgs) { Parameterize(); } #endregion #region Helpers private void InitializeOperators() { Operators.Add(new SingleObjectiveTestFunctionImprovementOperator()); Operators.Add(new SingleObjectiveTestFunctionPathRelinker()); Operators.Add(new SingleObjectiveTestFunctionSimilarityCalculator()); Operators.Add(new QualitySimilarityCalculator()); Operators.Add(new NoSimilarityCalculator()); Operators.Add(new AdditiveMoveEvaluator()); Operators.Add(new BestSingleObjectiveTestFunctionSolutionAnalyzer()); Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType())); Parameterize(); } private void Parameterize() { var operators = new List(); if (BestSingleObjectiveTestFunctionSolutionAnalyzer != null) { operators.Add(BestSingleObjectiveTestFunctionSolutionAnalyzer); BestSingleObjectiveTestFunctionSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName; BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name; BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name; BestSingleObjectiveTestFunctionSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name; BestSingleObjectiveTestFunctionSolutionAnalyzer.TestFunctionParameter.ActualName = TestFunctionParameter.Name; } foreach (var op in Operators.OfType()) { operators.Add(op); op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName; op.QualityParameter.Hidden = true; foreach (var movOp in Encoding.Operators.OfType()) movOp.MoveQualityParameter.ActualName = op.MoveQualityParameter.ActualName; } foreach (var op in Operators.OfType()) { op.MaximizationParameter.ActualName = MaximizationParameter.Name; op.MaximizationParameter.Hidden = true; } foreach (var op in Operators.OfType()) { operators.Add(op); op.SolutionParameter.ActualName = Encoding.Name; op.SolutionParameter.Hidden = true; } foreach (var op in Operators.OfType()) { operators.Add(op); op.SolutionVariableName = Encoding.Name; op.QualityVariableName = Evaluator.QualityParameter.ActualName; op.Bounds = Bounds; } if (operators.Count > 0) Encoding.ConfigureOperators(operators); } #endregion public void Load(SOTFData data) { Name = data.Name; Description = data.Description; TestFunction = data.TestFunction; } } }