#region License Information
/* HeuristicLab
* Copyright (C) 2002-2015 Joseph Helm and 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 HeuristicLab.Optimization;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Common;
using HeuristicLab.Parameters;
using HeuristicLab.Data;
using HeuristicLab.Encodings.PackingEncoding.MultiComponentVector;
using HeuristicLab.PluginInfrastructure;
using System.Linq;
using System;
using HeuristicLab.Encodings.PackingEncoding.PackingSequence;
using HeuristicLab.Encodings.PackingEncoding.GroupingVector;
using HeuristicLab.Encodings.PackingEncoding;
namespace HeuristicLab.Problems.BinPacking {
[StorableClass]
public abstract class Problem : SingleObjectiveHeuristicOptimizationProblem
where D : class, IPackingPosition
where B : PackingShape, new()
where I : PackingShape, IPackingItem, new () {
#region Parameter Properties
public OptionalValueParameter> BestKnownSolutionParameter {
get { return (OptionalValueParameter>)Parameters["BestKnownSolution"]; }
}
public ValueParameter> PackingItemMeasuresParameter {
get { return (ValueParameter>)Parameters["PackingItemMeasures"]; }
}
public IFixedValueParameter PackingItemsParameter {
get { return (IFixedValueParameter)Parameters["PackingItems"]; }
}
public IFixedValueParameter LowerBoundParameter {
get { return (IFixedValueParameter)Parameters["LowerBound"]; }
}
public ValueParameter PackingPlanEvaluatorParameter {
get { return (ValueParameter)Parameters["PackingPlanEvaluator"]; }
}
public IValueParameter PackingBinMeasuresParameter {
get { return (IValueParameter)Parameters["PackingBinMeasures"]; }
}
public IConstrainedValueParameter PackingSolutionDecoderParameter {
get { return (IConstrainedValueParameter)Parameters["PackingSolutionDecoder"]; }
}
#endregion
#region Properties
public PackingPlan BestKnownSolution {
get { return BestKnownSolutionParameter.Value; }
set { BestKnownSolutionParameter.Value = value; }
}
public ItemList PackingItemMeasures {
get { return PackingItemMeasuresParameter.Value; }
set { PackingItemMeasuresParameter.Value = value; }
}
public IEvaluator PackingPlanEvaluator {
get { return PackingPlanEvaluatorParameter.Value; }
set { PackingPlanEvaluatorParameter.Value = value; }
}
public B PackingBinMeasures {
get { return PackingBinMeasuresParameter.Value; }
set { PackingBinMeasuresParameter.Value = value; }
}
public PackingSolutionDecoder PackingSolutionDecoder {
get { return PackingSolutionDecoderParameter.Value as PackingSolutionDecoder; }
set { PackingSolutionDecoderParameter.Value = value; }
}
#endregion
[StorableConstructor]
protected Problem(bool deserializing) : base(deserializing) { }
protected Problem(Problem original, Cloner cloner)
: base(original, cloner) {
InitializeEventHandlers();
}
protected Problem(IPackingPlanEvaluationAlgorithm e) : this(e, new MultiComponentVectorRandomCreator()) { }
protected Problem(IPackingPlanEvaluationAlgorithm e, IPackingSolutionCreator c) : base (e, c){
Parameters.Add(new OptionalValueParameter>("BestKnownSolution", "The best known solution of this bin-packing instance."));
Parameters.Add(new ValueParameter>("PackingItemMeasures", "Packing-item data defining the measures of the different items that need to be packed.", new ItemList()));
Parameters.Add(new FixedValueParameter("PackingItems", "The number of packing-items used in this bin packing instance.", new IntValue()));
Parameters.Add(new FixedValueParameter("LowerBound", "The lower possible number of bins needed to solve this problem (taken from Dell'Amico, Martello and Vigo; 2002)", new IntValue()));
Parameters.Add(new ValueParameter("PackingBinMeasures", "Packing-bin data defining the measures of the used bins.", new B()));
Parameters.Add(new ValueParameter("PackingPlanEvaluator", "The evaluator is used to determine the quality of a solution.", CreateDefaultEvaluator()));
Parameters.Add(new ConstrainedValueParameter("PackingSolutionDecoder", "The operator that decodes the representation and creates a packing plan."));
this.Maximization.Value = true;
InitializeProblemInstance();
InitializeOperators();
InitializeEventHandlers();
}
protected abstract void InitializeDecoder();
protected virtual void InitializeProblemInstance() {
InitializeProblemData();
ApplyHorizontalOrientation();
SortItems();
RemoveTooBigItems();
PackingItemsParameter.Value.Value = PackingItemMeasures.Count;
LowerBoundParameter.Value.Value = CalculateLowerBound();
}
protected virtual void InitializeOperators() {
Operators.Clear();
Operators.Add(new BestBinPackingSolutionAnalyzer());
ApplyEncoding();
ParameterizeOperators();
}
protected virtual void InitializeEventHandlers() {
PackingPlanEvaluatorParameter.ValueChanged += PackingPlanEvaluatorParameter_ValueChanged;
PackingPlanEvaluator.QualityParameter.ActualNameChanged += PackingPlanEvaluator_QualityParameter_ActualNameChanged;
SolutionCreatorParameter.ValueChanged += SolutionCreatorParameter_ValueChanged;
SolutionCreator.EncodedSolutionParameter.ActualNameChanged += SolutionCreator_EncodedSolutionParameter_ActualNameChanged;
PackingSolutionDecoderParameter.ValueChanged += PackingSolutionDecoderParameter_ValueChanged;
if (PackingSolutionDecoder != null) PackingSolutionDecoder.PackingPlanParameter.ActualNameChanged += PackingSolutionDecoder_PackingPlanParameter_ActualNameChanged;
}
protected abstract void RemoveTooBigItems();
protected abstract void InitializeProblemData();
protected abstract IEvaluator CreateDefaultEvaluator();
protected void ApplyHorizontalOrientation() {
PackingBinMeasures.ApplyHorizontalOrientation();
foreach (IPackingShape shape in PackingItemMeasures) {
shape.ApplyHorizontalOrientation();
}
}
protected void SortItems() {
PackingItemMeasures.Sort((x, y) => y.CompareTo(x));
}
protected int CalculateLowerBound() {
//This is the obvious continuous lower bound calculation; Martello and Vigo proposed a better way but it has not been implemented yet;
int items = PackingItemMeasures.Select(x => x.Volume).Sum();
int bin = PackingBinMeasures.Volume;
return (items + bin - 1) / (bin);
}
private void ApplyEncoding() {
if (SolutionCreator.GetType() == typeof(PackingSequenceRandomCreator)) {
Operators.AddRange(ApplicationManager.Manager.GetInstances());
InitializeDecoder();
} else if (SolutionCreator.GetType() == typeof(GroupingVectorRandomCreator)) {
Operators.AddRange(ApplicationManager.Manager.GetInstances());
InitializeDecoder();
} else if (SolutionCreator.GetType() == typeof(MultiComponentVectorRandomCreator)) {
Operators.AddRange(ApplicationManager.Manager.GetInstances());
InitializeDecoder();
}
}
private void ParameterizeOperators() {
foreach (var op in Operators.OfType>()) {
op.QualityParameter.ActualName = PackingPlanEvaluator.QualityParameter.ActualName;
}
Evaluator.PackingSolutionDecoderParameter.ActualName = PackingSolutionDecoderParameter.Name;
Evaluator.PackingSolutionDecoderParameter.Hidden = true;
Evaluator.PackingPlanEvaluatorParameter.ActualName = PackingPlanEvaluatorParameter.Name;
Evaluator.PackingPlanEvaluatorParameter.Hidden = true;
Evaluator.QualityParameter.ActualName = PackingPlanEvaluator.QualityParameter.ActualName;
Evaluator.QualityParameter.Hidden = true;
if (PackingSolutionDecoder != null)
PackingSolutionDecoder.EncodedSolutionParameter.ActualName = SolutionCreator.EncodedSolutionParameter.ActualName;
if (PackingSolutionDecoder != null) {
PackingPlanEvaluator.PackingPlanParameter.ActualName = PackingSolutionDecoder.PackingPlanParameter.ActualName;
PackingPlanEvaluator.PackingPlanParameter.Hidden = true;
} else {
PackingPlanEvaluator.PackingPlanParameter.ActualName = PackingPlanEvaluator.PackingPlanParameter.Name;
PackingPlanEvaluator.PackingPlanParameter.Hidden = false;
}
foreach (var op in Operators.OfType()) {
op.EncodedSolutionParameter.ActualName = SolutionCreator.EncodedSolutionParameter.ActualName;
op.EncodedSolutionParameter.Hidden = true;
}
foreach (var op in Operators.OfType()) {
op.ChildParameter.ActualName = SolutionCreator.EncodedSolutionParameter.ActualName;
op.ChildParameter.Hidden = true;
op.ParentsParameter.ActualName = SolutionCreator.EncodedSolutionParameter.ActualName;
op.ParentsParameter.Hidden = true;
}
foreach (var op in Operators.OfType>()) {
op.QualityParameter.ActualName = PackingPlanEvaluator.QualityParameter.ActualName;
if (PackingSolutionDecoder != null) {
op.PackingPlanParameter.ActualName = PackingSolutionDecoder.PackingPlanParameter.ActualName;
op.PackingPlanParameter.Hidden = true;
} else {
op.PackingPlanParameter.ActualName = op.PackingPlanParameter.Name;
op.PackingPlanParameter.Hidden = false;
}
}
}
#region Events
protected override void OnSolutionCreatorChanged() {
InitializeOperators();
}
protected override void OnEvaluatorChanged() {
base.OnEvaluatorChanged();
ParameterizeOperators();
}
private void PackingPlanEvaluatorParameter_ValueChanged(object sender, EventArgs eventArgs) {
PackingPlanEvaluator.QualityParameter.ActualNameChanged += PackingPlanEvaluator_QualityParameter_ActualNameChanged;
ParameterizeOperators();
}
private void PackingPlanEvaluator_QualityParameter_ActualNameChanged(object sender, EventArgs eventArgs) {
ParameterizeOperators();
}
private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs eventArgs) {
SolutionCreator.EncodedSolutionParameter.ActualNameChanged += SolutionCreator_EncodedSolutionParameter_ActualNameChanged;
ParameterizeOperators();
}
private void SolutionCreator_EncodedSolutionParameter_ActualNameChanged(object sender, EventArgs eventArgs) {
ParameterizeOperators();
}
private void PackingSolutionDecoderParameter_ValueChanged(object sender, EventArgs eventArgs) {
if (PackingSolutionDecoder != null) PackingSolutionDecoder.PackingPlanParameter.ActualNameChanged += PackingSolutionDecoder_PackingPlanParameter_ActualNameChanged;
ParameterizeOperators();
}
private void PackingSolutionDecoder_PackingPlanParameter_ActualNameChanged(object sender, EventArgs eventArgs) {
ParameterizeOperators();
}
#endregion
}
}