#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.Drawing;
using System.Linq;
using HeuristicLab.Analysis;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.BinaryVectorEncoding;
using HeuristicLab.Encodings.IntegerVectorEncoding;
using HeuristicLab.Encodings.ParameterVectorEncoding;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Encodings.RealVectorEncoding;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Problems.Programmable {
[Item("Programmable Problem (single-objective)", "Represents a single-objective problem that can be programmed.")]
[Creatable("Problems")]
[StorableClass]
public sealed class SingleObjectiveProgrammableProblem : SingleObjectiveHeuristicOptimizationProblem, IStorableContent {
public string Filename { get; set; }
public static new Image StaticItemImage {
get { return HeuristicLab.Common.Resources.VSImageLibrary.Script; }
}
public IValueParameter ScriptParameter {
get { return (IValueParameter)Parameters["Script"]; }
}
private IValueParameter BinaryVectorLengthParameter {
get { return (IValueParameter)Parameters["BinaryVectorLength"]; }
}
private IValueParameter IntegerVectorLengthParameter {
get { return (IValueParameter)Parameters["IntegerVectorLength"]; }
}
private IValueParameter IntegerVectorBoundsParameter {
get { return (IValueParameter)Parameters["IntegerVectorBounds"]; }
}
private IValueParameter RealVectorLengthParameter {
get { return (IValueParameter)Parameters["RealVectorLength"]; }
}
private IValueParameter RealVectorBoundsParameter {
get { return (IValueParameter)Parameters["RealVectorBounds"]; }
}
private IValueParameter PermutationLengthParameter {
get { return (IValueParameter)Parameters["PermutationLength"]; }
}
private IValueParameter PermutationTypeParameter {
get { return (IValueParameter)Parameters["PermutationType"]; }
}
[Storable]
private ParameterVectorCrossover Crossover { get; set; }
[Storable]
private ParameterVectorManipulator Manipulator { get; set; }
[StorableConstructor]
private SingleObjectiveProgrammableProblem(bool deserializing) : base(deserializing) { }
private SingleObjectiveProgrammableProblem(SingleObjectiveProgrammableProblem original, Cloner cloner)
: base(original, cloner) {
Crossover = cloner.Clone(original.Crossover);
Manipulator = cloner.Clone(original.Manipulator);
RegisterEventHandlers();
}
public SingleObjectiveProgrammableProblem()
: base(new SingleObjectiveEvaluator(), new ParameterVectorCreater()) {
Parameters.Add(new ValueParameter("Script", "Defines the problem.", new SingleObjectiveScript() { Name = ItemName }));
Parameters.Add(new OptionalValueParameter("BinaryVectorLength", "The length of the binary vector."));
Parameters.Add(new OptionalValueParameter("IntegerVectorLength", "The length of the integer vector."));
Parameters.Add(new OptionalValueParameter("IntegerVectorBounds", "The bounds of the integer vector."));
Parameters.Add(new OptionalValueParameter("RealVectorLength", "The length of the real vector."));
Parameters.Add(new OptionalValueParameter("RealVectorBounds", "The bounds of the real vector."));
Parameters.Add(new OptionalValueParameter("PermutationLength", "The length of the permutation."));
Parameters.Add(new OptionalValueParameter("PermutationType", "The type of the permutation."));
Crossover = new ParameterVectorCrossover();
Manipulator = new ParameterVectorManipulator();
Operators.Add(new BestScopeSolutionAnalyzer());
Operators.Add(Evaluator);
Operators.Add(SolutionCreator);
Operators.Add(Crossover);
Operators.Add(Manipulator);
RegisterEventHandlers();
}
public override IDeepCloneable Clone(Cloner cloner) {
return new SingleObjectiveProgrammableProblem(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
RegisterEventHandlers();
}
private void RegisterEventHandlers() {
ScriptParameter.ValueChanged += ScriptParameterOnValueChanged;
Crossover.BeforeExecutionOperators.CollectionReset += CrossoverBeforeExecutionOperatorsOnChanged;
Crossover.BeforeExecutionOperators.ItemsAdded += CrossoverBeforeExecutionOperatorsOnChanged;
Crossover.BeforeExecutionOperators.ItemsReplaced += CrossoverBeforeExecutionOperatorsOnChanged;
Manipulator.BeforeExecutionOperators.CollectionReset += ManipulatroBeforeExecutionOperatorsOnChanged;
Manipulator.BeforeExecutionOperators.ItemsAdded += ManipulatroBeforeExecutionOperatorsOnChanged;
Manipulator.BeforeExecutionOperators.ItemsReplaced += ManipulatroBeforeExecutionOperatorsOnChanged;
RegisterScriptInstanceChanges();
}
private void ScriptParameterOnValueChanged(object sender, EventArgs eventArgs) {
RegisterScriptInstanceChanges();
}
private void CrossoverBeforeExecutionOperatorsOnChanged(object sender, EventArgs e) {
ParameterizeCrossover();
}
private void ManipulatroBeforeExecutionOperatorsOnChanged(object sender, EventArgs e) {
ParameterizeManipulator();
}
private void RegisterScriptInstanceChanges() {
ScriptParameter.Value.InstanceChanged += ScriptOnInstanceChanged;
ScriptParameter.Value.NameChanged += ScriptOnNameChanged;
}
private void ScriptOnNameChanged(object sender, EventArgs eventArgs) {
if (sender != ScriptParameter.Value) return;
if (Name != ScriptParameter.Value.Name)
Name = ScriptParameter.Value.Name;
}
protected override void OnNameChanged() {
base.OnNameChanged();
if (ScriptParameter.Value.Name != Name)
ScriptParameter.Value.Name = Name;
}
private void ScriptOnInstanceChanged(object sender, EventArgs eventArgs) {
var instance = ScriptParameter.Value.Instance;
if (instance == null) return;
Maximization.Value = instance.IsMaximizationProblem;
var vector = instance.GetParametersToOptimize();
BinaryVectorLengthParameter.Value = vector.BooleanParameters != null ? new IntValue(vector.BooleanParameters.Length) : null;
IntegerVectorLengthParameter.Value = vector.IntegerParameters != null ? new IntValue(vector.IntegerParameters.Length) : null;
IntegerVectorBoundsParameter.Value = vector.IntegerBounds;
RealVectorLengthParameter.Value = vector.RealParameters != null ? new IntValue(vector.RealParameters.Length) : null;
RealVectorBoundsParameter.Value = vector.RealBounds;
PermutationLengthParameter.Value = vector.PermutationParameter != null ? new IntValue(vector.PermutationParameter.Length) : null;
PermutationTypeParameter.Value = vector.PermutationParameter != null ? new PermutationType(vector.PermutationParameter.PermutationType) : null;
((IBinaryVectorCreator)SolutionCreator).LengthParameter.ActualName = BinaryVectorLengthParameter.Name;
((IIntegerVectorCreator)SolutionCreator).LengthParameter.ActualName = IntegerVectorLengthParameter.Name;
((IIntegerVectorCreator)SolutionCreator).BoundsParameter.ActualName = IntegerVectorBoundsParameter.Name;
((IRealVectorCreator)SolutionCreator).LengthParameter.ActualName = RealVectorLengthParameter.Name;
((IRealVectorCreator)SolutionCreator).BoundsParameter.ActualName = RealVectorBoundsParameter.Name;
((IPermutationCreator)SolutionCreator).LengthParameter.ActualName = PermutationLengthParameter.Name;
((IPermutationCreator)SolutionCreator).PermutationTypeParameter.Value = new PermutationType(vector.PermutationParameter != null ? vector.PermutationParameter.PermutationType : PermutationTypes.Absolute);
if (vector.BooleanParameters != null) {
if (!Crossover.BeforeExecutionOperators.Any(x => x is IBinaryVectorCrossover))
Crossover.BeforeExecutionOperators.Add(new Encodings.BinaryVectorEncoding.SinglePointCrossover());
if (!Manipulator.BeforeExecutionOperators.Any(x => x is IBinaryVectorManipulator))
Manipulator.BeforeExecutionOperators.Add(new Encodings.BinaryVectorEncoding.SinglePositionBitflipManipulator());
} else {
Crossover.BeforeExecutionOperators.RemoveAll(x => x is IBinaryVectorCrossover);
Manipulator.BeforeExecutionOperators.RemoveAll(x => x is IBinaryVectorManipulator);
}
if (vector.IntegerParameters != null) {
if (!Crossover.BeforeExecutionOperators.Any(x => x is IIntegerVectorCrossover))
Crossover.BeforeExecutionOperators.Add(new Encodings.IntegerVectorEncoding.SinglePointCrossover());
if (!Manipulator.BeforeExecutionOperators.Any(x => x is IIntegerVectorManipulator))
Manipulator.BeforeExecutionOperators.Add(new Encodings.IntegerVectorEncoding.UniformOnePositionManipulator());
} else {
Crossover.BeforeExecutionOperators.RemoveAll(x => x is IIntegerVectorCrossover);
Manipulator.BeforeExecutionOperators.RemoveAll(x => x is IIntegerVectorManipulator);
}
if (vector.RealParameters != null) {
if (!Crossover.BeforeExecutionOperators.Any(x => x is IRealVectorCrossover))
Crossover.BeforeExecutionOperators.Add(new Encodings.RealVectorEncoding.SinglePointCrossover());
if (!Manipulator.BeforeExecutionOperators.Any(x => x is IRealVectorManipulator))
Manipulator.BeforeExecutionOperators.Add(new Encodings.RealVectorEncoding.BreederGeneticAlgorithmManipulator());
} else {
Crossover.BeforeExecutionOperators.RemoveAll(x => x is IRealVectorCrossover);
Manipulator.BeforeExecutionOperators.RemoveAll(x => x is IRealVectorManipulator);
}
if (vector.PermutationParameter != null) {
if (!Crossover.BeforeExecutionOperators.Any(x => x is IPermutationCrossover))
Crossover.BeforeExecutionOperators.Add(new Encodings.PermutationEncoding.OrderCrossover2());
if (!Manipulator.BeforeExecutionOperators.Any(x => x is IPermutationManipulator))
Manipulator.BeforeExecutionOperators.Add(new Encodings.PermutationEncoding.Swap2Manipulator());
} else {
Crossover.BeforeExecutionOperators.RemoveAll(x => x is IPermutationCrossover);
Manipulator.BeforeExecutionOperators.RemoveAll(x => x is IPermutationManipulator);
}
ParameterizeCrossover();
ParameterizeManipulator();
}
private void ParameterizeCrossover() {
Crossover.ChildParameter.ActualName = SolutionCreator.ParameterVectorParameter.ActualName;
Crossover.ParentsParameter.ActualName = SolutionCreator.ParameterVectorParameter.ActualName;
foreach (var xo in Crossover.BeforeExecutionOperators.OfType()) {
xo.ChildParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
xo.ParentsParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
}
foreach (var xo in Crossover.BeforeExecutionOperators.OfType()) {
xo.ChildParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName;
xo.ParentsParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName;
var bxo = xo as IBoundedIntegerVectorOperator;
if (bxo != null) bxo.BoundsParameter.ActualName = IntegerVectorBoundsParameter.Name;
}
foreach (var xo in Crossover.BeforeExecutionOperators.OfType()) {
xo.ChildParameter.ActualName = SolutionCreator.RealVectorParameter.ActualName;
xo.ParentsParameter.ActualName = SolutionCreator.RealVectorParameter.ActualName;
xo.BoundsParameter.ActualName = RealVectorBoundsParameter.Name;
}
foreach (var xo in Crossover.BeforeExecutionOperators.OfType()) {
xo.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
xo.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
}
}
private void ParameterizeManipulator() {
foreach (var ma in Manipulator.BeforeExecutionOperators.OfType()) {
ma.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
}
foreach (var ma in Manipulator.BeforeExecutionOperators.OfType()) {
ma.IntegerVectorParameter.ActualName = SolutionCreator.IntegerVectorParameter.ActualName;
var bma = ma as IBoundedIntegerVectorOperator;
if (bma != null) bma.BoundsParameter.ActualName = IntegerVectorBoundsParameter.Name;
}
foreach (var ma in Manipulator.BeforeExecutionOperators.OfType()) {
ma.RealVectorParameter.ActualName = SolutionCreator.RealVectorParameter.ActualName;
ma.BoundsParameter.ActualName = RealVectorBoundsParameter.Name;
}
foreach (var ma in Manipulator.BeforeExecutionOperators.OfType()) {
ma.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
}
}
}
}