#region License Information /* HeuristicLab * Copyright (C) 2002-2019 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.Drawing; using System.Linq; using System.Threading; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Parameters; using HEAL.Attic; using HeuristicLab.PluginInfrastructure; namespace HeuristicLab.Optimization { /// /// A problem which can be defined by the user. /// [Item("User-Defined Problem", "A problem which can be defined by the user.")] [Creatable(CreatableAttribute.Categories.Problems, Priority = 120)] [StorableType("9F18A098-A8B8-4F70-93CF-79FF1496AC8A")] public sealed class UserDefinedProblem : ParameterizedNamedItem, ISingleObjectiveHeuristicOptimizationProblem, IStorableContent { public string Filename { get; set; } public static new Image StaticItemImage { get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; } } public new ParameterCollection Parameters { get { return base.Parameters; } } IKeyedItemCollection IParameterizedItem.Parameters { get { return Parameters; } } #region Parameters public IValueParameter EvaluatorParameter { get { return (IValueParameter)Parameters["Evaluator"]; } } public ValueParameter MaximizationParameter { get { return (ValueParameter)Parameters["Maximization"]; } } IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter { get { return MaximizationParameter; } } public ValueParameter SolutionCreatorParameter { get { return (ValueParameter)Parameters["SolutionCreator"]; } } IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter { get { return SolutionCreatorParameter; } } IParameter IHeuristicOptimizationProblem.EvaluatorParameter { get { return EvaluatorParameter; } } public OptionalValueParameter BestKnownQualityParameter { get { return (OptionalValueParameter)Parameters["BestKnownQuality"]; } } IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter { get { return BestKnownQualityParameter; } } public OptionalValueParameter BestKnownSolutionParameter { get { return (OptionalValueParameter)Parameters["BestKnownSolution"]; } } public ValueParameter> OperatorsParameter { get { return (ValueParameter>)Parameters["Operators"]; } } #endregion #region Properties public BoolValue Maximization { get { return MaximizationParameter.Value; } set { MaximizationParameter.Value = value; } } public ISolutionCreator SolutionCreator { get { return SolutionCreatorParameter.Value; } set { SolutionCreatorParameter.Value = value; } } ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator { get { return SolutionCreatorParameter.Value; } } public ISingleObjectiveEvaluator Evaluator { get { return EvaluatorParameter.Value; } set { EvaluatorParameter.Value = value; } } ISingleObjectiveEvaluator ISingleObjectiveHeuristicOptimizationProblem.Evaluator { get { return EvaluatorParameter.Value; } } IEvaluator IHeuristicOptimizationProblem.Evaluator { get { return EvaluatorParameter.Value; } } public DoubleValue BestKnownQuality { get { return BestKnownQualityParameter.Value; } set { BestKnownQualityParameter.Value = value; } } public IEnumerable Operators { get { return OperatorsParameter.Value; } } public IEnumerable ExecutionContextItems { get { yield return this; } } #endregion [StorableConstructor] private UserDefinedProblem(StorableConstructorFlag _) : base(_) { } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { // BackwardsCompatibility3.3 #region Backwards compatible code, remove with 3.4 if (Parameters.ContainsKey("Operators") && Parameters["Operators"] is ValueParameter>) { ItemList tmp = ((ValueParameter>)Parameters["Operators"]).Value; Parameters.Remove("Operators"); Parameters.Add(new ValueParameter>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList(tmp), false)); } #endregion RegisterEventHandlers(); } public UserDefinedProblem() : base() { Parameters.Add(new ValueParameter("Evaluator", "The evaluator that collects the values to exchange.", new EmptyUserDefinedProblemEvaluator())); Parameters.Add(new ValueParameter("SolutionCreator", "An operator to create the solution components.")); Parameters.Add(new ValueParameter("Maximization", "Set to false as most test functions are minimization problems.", new BoolValue(false))); Parameters.Add(new OptionalValueParameter("BestKnownQuality", "The quality of the best known solution of this problem.")); Parameters.Add(new OptionalValueParameter("BestKnownSolution", "The best known solution for this external evaluation problem.")); Parameters.Add(new ValueParameter>("Operators", "The operators and items that the problem provides to the algorithms.", new ItemList())); RegisterEventHandlers(); } private UserDefinedProblem(UserDefinedProblem original, Cloner cloner) : base(original, cloner) { RegisterEventHandlers(); } public override IDeepCloneable Clone(Cloner cloner) { return new UserDefinedProblem(this, cloner); } #region Events public event EventHandler SolutionCreatorChanged; private void OnSolutionCreatorChanged() { EventHandler handler = SolutionCreatorChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler EvaluatorChanged; private void OnEvaluatorChanged() { EventHandler handler = EvaluatorChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler OperatorsChanged; private void OnOperatorsChanged() { EventHandler handler = OperatorsChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Reset; private void OnReset() { EventHandler handler = Reset; if (handler != null) handler(this, EventArgs.Empty); } #endregion #region Event handlers private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) { OnSolutionCreatorChanged(); } private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) { if (Evaluator != null) Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged); ParameterizeOperators(); OnEvaluatorChanged(); } private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) { ParameterizeOperators(); } private void OperatorsParameter_ValueChanged(object sender, EventArgs e) { OnOperatorsChanged(); } private void OperatorsParameter_Value_ItemsAdded(object sender, EventArgs e) { OnOperatorsChanged(); } private void OperatorsParameter_Value_ItemsRemoved(object sender, EventArgs e) { OnOperatorsChanged(); } private void OperatorsParameter_Value_CollectionReset(object sender, EventArgs e) { OnOperatorsChanged(); } #endregion #region Helpers private void RegisterEventHandlers() { SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged); EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged); if (Evaluator != null) Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged); OperatorsParameter.ValueChanged += new EventHandler(OperatorsParameter_ValueChanged); OperatorsParameter.Value.ItemsAdded += new CollectionItemsChangedEventHandler>(OperatorsParameter_Value_ItemsAdded); OperatorsParameter.Value.ItemsRemoved += new CollectionItemsChangedEventHandler>(OperatorsParameter_Value_ItemsRemoved); OperatorsParameter.Value.CollectionReset += new CollectionItemsChangedEventHandler>(OperatorsParameter_Value_CollectionReset); } private void ParameterizeOperators() { // A best effort approach to wiring if (Evaluator != null) { string qualityName = Evaluator.QualityParameter.ActualName; foreach (IOperator op in OperatorsParameter.Value.OfType()) { foreach (ILookupParameter param in op.Parameters.OfType>()) { if (param.Name.Equals("Quality")) param.ActualName = qualityName; } foreach (IScopeTreeLookupParameter param in op.Parameters.OfType>()) { if (param.Name.Equals("Quality")) param.ActualName = qualityName; } } } } #endregion [Item("EmptyUserDefinedProblemEvaluator", "A dummy evaluator that will throw an exception when executed.")] [StorableType("E27E4145-6D44-4A9D-B15A-B0E0528ECD0D")] [NonDiscoverableType] private sealed class EmptyUserDefinedProblemEvaluator : ParameterizedNamedItem, ISingleObjectiveEvaluator { [StorableConstructor] private EmptyUserDefinedProblemEvaluator(StorableConstructorFlag _) : base(_) { } private EmptyUserDefinedProblemEvaluator(EmptyUserDefinedProblemEvaluator original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new EmptyUserDefinedProblemEvaluator(this, cloner); } #region ISingleObjectiveEvaluator Members public ILookupParameter QualityParameter { get { return (ILookupParameter)Parameters["Quality"]; } } #endregion public EmptyUserDefinedProblemEvaluator() { Parameters.Add(new LookupParameter("Quality", "The solution quality.")); } #region IOperator Members public bool Breakpoint { get; set; } public IOperation Execute(IExecutionContext context, CancellationToken cancellationToken) { throw new InvalidOperationException("Please choose an appropriate evaluation operator."); } #pragma warning disable 67 public event EventHandler BreakpointChanged; public event EventHandler Executed; #pragma warning restore 67 #endregion public static new Image StaticItemImage { get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; } } } } }