#region License Information
/* HeuristicLab
* Copyright (C) 2002-2014 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.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.PluginInfrastructure;
using HeuristicLab.Problems.Instances;
using HeuristicLab.Problems.Programmable;
namespace HeuristicLab.Problems.TestFunctions {
[Item("Test Function", "Test function with real valued inputs and a single objective.")]
[StorableClass]
[Creatable("Problems")]
public sealed class TestFunctionProblem : SingleObjectiveHeuristicOptimizationProblem, IStorableContent, IProblemInstanceConsumer {
public string Filename { get; set; }
[Storable]
private RealEncoding encoding;
public RealEncoding Encoding {
get { return encoding; }
}
#region Parameter Properties
public ValueParameter BoundsParameter {
get { return (ValueParameter)Parameters["Bounds"]; }
}
public IFixedValueParameter ProblemSizeParameter {
get { return (IFixedValueParameter)Parameters["ProblemSize"]; }
}
public OptionalValueParameter BestKnownSolutionParameter {
get { return (OptionalValueParameter)Parameters["BestKnownSolution"]; }
}
#endregion
#region Properties
public DoubleMatrix Bounds {
get { return BoundsParameter.Value; }
set { BoundsParameter.Value = value; }
}
public int ProblemSize {
get { return ProblemSizeParameter.Value.Value; }
set { ProblemSizeParameter.Value.Value = value; }
}
private BestSingleObjectiveTestFunctionSolutionAnalyzer BestSingleObjectiveTestFunctionSolutionAnalyzer {
get { return Operators.OfType().FirstOrDefault(); }
}
private SingleObjectivePopulationDiversityAnalyzer SingleObjectivePopulationDiversityAnalyzer {
get { return Operators.OfType().FirstOrDefault(); }
}
#endregion
[StorableConstructor]
private TestFunctionProblem(bool deserializing) : base(deserializing) { }
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
RegisterEventHandlers();
}
private TestFunctionProblem(TestFunctionProblem original, Cloner cloner)
: base(original, cloner) {
encoding = cloner.Clone(original.encoding);
RegisterEventHandlers();
}
public override IDeepCloneable Clone(Cloner cloner) { return new TestFunctionProblem(this, cloner); }
public TestFunctionProblem()
: base(new AckleyEvaluator(), new UniformRandomRealVectorCreator()) {
encoding = new RealEncoding("Point", 2, Evaluator.Bounds[0, 0], Evaluator.Bounds[0, 1]);
Parameters.Add(new ValueParameter("Bounds", "The lower and upper bounds in each dimension.", Evaluator.Bounds));
Parameters.Add(new FixedValueParameter("ProblemSize", "The dimension of the problem.", new IntValue(2)));
Parameters.Add(new OptionalValueParameter("BestKnownSolution", "The best known solution for this test function instance."));
encoding.BoundsParameter = BoundsParameter;
encoding.LengthParameter = ProblemSizeParameter;
encoding.SolutionCreator = SolutionCreator;
Maximization.Value = Evaluator.Maximization;
BestKnownQuality = new DoubleValue(Evaluator.BestKnownQuality);
Operators.Add(new SingleObjectiveTestFunctionImprovementOperator());
Operators.Add(new SingleObjectiveTestFunctionPathRelinker());
Operators.Add(new SingleObjectiveTestFunctionSimilarityCalculator());
Operators.Add(new BestSingleObjectiveTestFunctionSolutionAnalyzer());
Operators.Add(new SingleObjectivePopulationDiversityAnalyzer());
ConfigureOperators();
UpdateMoveEvaluators();
RegisterEventHandlers();
}
protected override IEnumerable GetOperators() {
return Operators.Concat(Encoding.Operators.Except(Operators, new TypeEqualityComparer()));
}
#region Events
private void RegisterEventHandlers() {
ProblemSizeParameter.Value.ValueChanged += new EventHandler(ProblemSize_Changed);
BoundsParameter.ValueChanged += new EventHandler(BoundsParameter_ValueChanged);
Bounds.ToStringChanged += new EventHandler(Bounds_ToStringChanged);
Bounds.ItemChanged += new EventHandler>(Bounds_ItemChanged);
Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
}
protected override void OnSolutionCreatorChanged() {
base.OnSolutionCreatorChanged();
Encoding.SolutionCreator = SolutionCreator;
ConfigureOperators();
}
protected override void OnEvaluatorChanged() {
base.OnEvaluatorChanged();
ProblemSize = Math.Max(Evaluator.MinimumProblemSize, Math.Min(ProblemSize, Evaluator.MaximumProblemSize));
UpdateMoveEvaluators();
Maximization.Value = Evaluator.Maximization;
BoundsParameter.Value = Evaluator.Bounds;
BestKnownQuality = new DoubleValue(Evaluator.BestKnownQuality);
Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
ConfigureOperators();
OnReset();
}
private void ProblemSize_Changed(object sender, EventArgs e) {
if (ProblemSize < 1) ProblemSize = 1;
ConfigureEvaluator();
OnReset();
}
private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
ConfigureOperators();
}
private void BoundsParameter_ValueChanged(object sender, EventArgs e) {
Bounds.ToStringChanged += new EventHandler(Bounds_ToStringChanged);
Bounds_ToStringChanged(null, EventArgs.Empty);
}
private void Bounds_ToStringChanged(object sender, EventArgs e) {
if (Bounds.Columns != 2 || Bounds.Rows < 1)
Bounds = new DoubleMatrix(1, 2);
}
private void Bounds_ItemChanged(object sender, EventArgs e) {
if (e.Value2 == 0 && Bounds[e.Value, 1] <= Bounds[e.Value, 0])
Bounds[e.Value, 1] = Bounds[e.Value, 0] + 0.1;
if (e.Value2 == 1 && Bounds[e.Value, 0] >= Bounds[e.Value, 1])
Bounds[e.Value, 0] = Bounds[e.Value, 1] - 0.1;
}
#endregion
#region Helpers
private void UpdateMoveEvaluators() {
foreach (ISingleObjectiveTestFunctionMoveEvaluator op in Operators.OfType().ToList())
Operators.Remove(op);
foreach (ISingleObjectiveTestFunctionMoveEvaluator op in ApplicationManager.Manager.GetInstances())
if (op.EvaluatorType == Evaluator.GetType()) {
Operators.Add(op);
#region Synchronize evaluator specific parameters with the parameters of the corresponding move evaluators
if (op is ISphereMoveEvaluator) {
SphereEvaluator e = (Evaluator as SphereEvaluator);
e.AlphaParameter.ValueChanged += new EventHandler(SphereEvaluator_Parameter_ValueChanged);
e.CParameter.ValueChanged += new EventHandler(SphereEvaluator_Parameter_ValueChanged);
ISphereMoveEvaluator em = (op as ISphereMoveEvaluator);
em.C = e.C;
em.Alpha = e.Alpha;
} else if (op is IRastriginMoveEvaluator) {
RastriginEvaluator e = (Evaluator as RastriginEvaluator);
e.AParameter.ValueChanged += new EventHandler(RastriginEvaluator_Parameter_ValueChanged);
IRastriginMoveEvaluator em = (op as IRastriginMoveEvaluator);
em.A = e.A;
}
#endregion
}
ConfigureOperators();
OnOperatorsChanged();
}
private void SphereEvaluator_Parameter_ValueChanged(object sender, EventArgs e) {
SphereEvaluator eval = (Evaluator as SphereEvaluator);
if (eval != null) {
foreach (ISphereMoveEvaluator op in Operators.OfType()) {
op.C = eval.C;
op.Alpha = eval.Alpha;
}
}
}
private void RastriginEvaluator_Parameter_ValueChanged(object sender, EventArgs e) {
RastriginEvaluator eval = (Evaluator as RastriginEvaluator);
if (eval != null) {
foreach (IRastriginMoveEvaluator op in Operators.OfType()) {
op.A = eval.A;
}
}
}
private void ConfigureOperators() {
Encoding.ConfigureOperators(Operators.OfType());
foreach (var op in Operators.OfType()) {
op.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
}
foreach (var op in Operators.OfType()) {
op.MaximizationParameter.ActualName = MaximizationParameter.Name;
}
foreach (var op in Operators.OfType()) {
op.SolutionParameter.ActualName = Encoding.Name;
}
foreach (var op in Operators.OfType()) {
op.ParentsParameter.ActualName = Encoding.Name;
}
foreach (var op in Operators.OfType()) {
op.SolutionVariableName = Encoding.Name;
op.QualityVariableName = Evaluator.QualityParameter.ActualName;
op.Bounds = Encoding.Bounds;
}
ConfigureEvaluator();
ConfigureAnalyzers();
}
private void ConfigureEvaluator() {
Evaluator.PointParameter.ActualName = Encoding.Name;
try {
BestKnownSolutionParameter.Value = Evaluator.GetBestKnownSolution(ProblemSize);
}
catch (ArgumentException e) {
ErrorHandling.ShowErrorDialog(e);
ProblemSize = Evaluator.MinimumProblemSize;
}
}
private void ConfigureAnalyzers() {
if (BestSingleObjectiveTestFunctionSolutionAnalyzer != null) {
BestSingleObjectiveTestFunctionSolutionAnalyzer.RealVectorParameter.ActualName = Encoding.Name;
BestSingleObjectiveTestFunctionSolutionAnalyzer.ResultsParameter.ActualName = "Results";
BestSingleObjectiveTestFunctionSolutionAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
BestSingleObjectiveTestFunctionSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
BestSingleObjectiveTestFunctionSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
BestSingleObjectiveTestFunctionSolutionAnalyzer.EvaluatorParameter.ActualName = EvaluatorParameter.Name;
BestSingleObjectiveTestFunctionSolutionAnalyzer.BoundsParameter.ActualName = BoundsParameter.Name;
}
if (SingleObjectivePopulationDiversityAnalyzer != null) {
SingleObjectivePopulationDiversityAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
SingleObjectivePopulationDiversityAnalyzer.QualityParameter.ActualName = Evaluator.QualityParameter.ActualName;
SingleObjectivePopulationDiversityAnalyzer.ResultsParameter.ActualName = "Results";
SingleObjectivePopulationDiversityAnalyzer.SimilarityCalculator = Operators.OfType().SingleOrDefault();
}
}
#endregion
public void Load(SOTFData data) {
Name = data.Name;
Description = data.Description;
Evaluator = data.Evaluator;
}
}
}