#region License Information /* HeuristicLab * Copyright (C) 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.Threading; using HEAL.Attic; using HeuristicLab.Analysis; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Problems.Instances; namespace HeuristicLab.Problems.TestFunctions.MultiObjective { [StorableType("AB0C6A73-C432-46FD-AE3B-9841EAB2478C")] [Creatable(CreatableAttribute.Categories.Problems, Priority = 95)] [Item("Test Function (multi-objective)", "Test functions with real valued inputs and multiple objectives.")] public class MultiObjectiveTestFunctionProblem : RealVectorMultiObjectiveProblem, IProblemInstanceConsumer, IMultiObjectiveProblemDefinition { #region Parameter Properties public IFixedValueParameter ProblemSizeParameter { get { return (IFixedValueParameter)Parameters["ProblemSize"]; } } public IFixedValueParameter ObjectivesParameter { get { return (IFixedValueParameter)Parameters["Objectives"]; } } public IValueParameter BoundsParameter { get { return (IValueParameter)Parameters["Bounds"]; } } 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 new int Objectives { get { return ObjectivesParameter.Value.Value; } set { ObjectivesParameter.Value.Value = value; } } public DoubleMatrix Bounds { get { return BoundsParameter.Value; } set { BoundsParameter.Value = value; } } public IMultiObjectiveTestFunction TestFunction { get { return TestFunctionParameter.Value; } set { TestFunctionParameter.Value = value; } } #endregion [StorableConstructor] protected MultiObjectiveTestFunctionProblem(StorableConstructorFlag _) : base(_) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { RegisterEventHandlers(); } protected MultiObjectiveTestFunctionProblem(MultiObjectiveTestFunctionProblem original, Cloner cloner) : base(original, cloner) { RegisterEventHandlers(); } public override IDeepCloneable Clone(Cloner cloner) { return new MultiObjectiveTestFunctionProblem(this, cloner); } public MultiObjectiveTestFunctionProblem() : base() { Parameters.Add(new FixedValueParameter("ProblemSize", "The dimensionality of the problem instance (number of variables in the function).", new IntValue(2))); Parameters.Add(new FixedValueParameter("Objectives", "The dimensionality of the solution vector (number of objectives).", 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[,] { { -4, 4 } }))); Parameters.Add(new ValueParameter("TestFunction", "The function that is to be optimized.", new Fonseca())); Encoding.LengthParameter = ProblemSizeParameter; Encoding.BoundsParameter = BoundsParameter; BestKnownFrontParameter.Hidden = true; UpdateParameterValues(); InitializeOperators(); RegisterEventHandlers(); } private void RegisterEventHandlers() { TestFunctionParameter.ValueChanged += TestFunctionParameterOnValueChanged; ProblemSizeParameter.Value.ValueChanged += ProblemSizeOnValueChanged; ObjectivesParameter.Value.ValueChanged += ObjectivesOnValueChanged; } public override void Analyze(RealVector[] solutions, double[][] qualities, ResultCollection results, IRandom random) { base.Analyze(solutions, qualities, results, random); if (results.ContainsKey("Pareto Front")) ((DoubleMatrix)results["Pareto Front"].Value).SortableView = true; } /// /// Checks whether a given solution violates the contraints of this function. /// /// /// a double array that holds the distances that describe how much every contraint is violated (0 is not violated). If the current TestFunction does not have constraints an array of length 0 is returned public double[] CheckContraints(RealVector individual) { var constrainedTestFunction = (IConstrainedTestFunction)TestFunction; return constrainedTestFunction != null ? constrainedTestFunction.CheckConstraints(individual, Objectives) : new double[0]; } public override double[] Evaluate(RealVector solution, IRandom random, CancellationToken cancellationToken) { return TestFunction.Evaluate(solution, Objectives); } public void Load(MOTFData data) { TestFunction = data.TestFunction; } #region Events private void UpdateParameterValues() { Maximization = TestFunction.Maximization(Objectives); Parameters.Remove(BestKnownFrontParameterName); var front = TestFunction.OptimalParetoFront(Objectives); var bkf = front != null ? (DoubleMatrix)Utilities.ToMatrix(front).AsReadOnly() : null; Parameters.Add(new FixedValueParameter(BestKnownFrontParameterName, "A double matrix representing the best known qualities for this problem (aka points on the Pareto front). Points are to be given in a row-wise fashion.", bkf)); Parameters.Remove(ReferencePointParameterName); Parameters.Add(new FixedValueParameter(ReferencePointParameterName, "The reference point for hypervolume calculations on this problem", new DoubleArray(TestFunction.ReferencePoint(Objectives)))); BoundsParameter.Value = new DoubleMatrix(TestFunction.Bounds(Objectives)); } protected override void OnEncodingChanged() { base.OnEncodingChanged(); UpdateParameterValues(); } protected override void OnEvaluatorChanged() { base.OnEvaluatorChanged(); UpdateParameterValues(); } private void TestFunctionParameterOnValueChanged(object sender, EventArgs eventArgs) { ProblemSize = Math.Max(TestFunction.MinimumSolutionLength, Math.Min(ProblemSize, TestFunction.MaximumSolutionLength)); Objectives = Math.Max(TestFunction.MinimumObjectives, Math.Min(Objectives, TestFunction.MaximumObjectives)); Parameters.Remove(ReferencePointParameterName); Parameters.Add(new FixedValueParameter(ReferencePointParameterName, "The reference point for hypervolume calculations on this problem", new DoubleArray(TestFunction.ReferencePoint(Objectives)))); UpdateParameterValues(); OnReset(); } private void ProblemSizeOnValueChanged(object sender, EventArgs eventArgs) { ProblemSize = Math.Min(TestFunction.MaximumSolutionLength, Math.Max(TestFunction.MinimumSolutionLength, ProblemSize)); UpdateParameterValues(); } private void ObjectivesOnValueChanged(object sender, EventArgs eventArgs) { Objectives = Math.Min(TestFunction.MaximumObjectives, Math.Max(TestFunction.MinimumObjectives, Objectives)); UpdateParameterValues(); } #endregion #region Helpers private void InitializeOperators() { Operators.Add(new CrowdingAnalyzer()); Operators.Add(new GenerationalDistanceAnalyzer()); Operators.Add(new InvertedGenerationalDistanceAnalyzer()); Operators.Add(new HypervolumeAnalyzer()); Operators.Add(new SpacingAnalyzer()); Operators.Add(new TimelineAnalyzer()); } #endregion } }