#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 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 System.Text;
using HeuristicLab.Problems.BinPacking.Interfaces;
using HeuristicLab.Problems.BinPacking.Shapes;
using HeuristicLab.Optimization;
using HeuristicLab.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Common;
using HeuristicLab.Parameters;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Problems.BinPacking.Evaluators;
using HeuristicLab.Problems.BinPacking.Decoders;
using HeuristicLab.PluginInfrastructure;
using HeuristicLab.Data;
using HeuristicLab.Encodings.PackingEncoding.PackingPlan;
using HeuristicLab.Problems.BinPacking.Analyzers;
using HeuristicLab.Encodings.PackingEncoding.PackingSequence;
using HeuristicLab.Encodings.PackingEncoding.Interfaces;
using HeuristicLab.Encodings.PackingEncoding.GroupingVector;
using HeuristicLab.Problems.Instances;
using HeuristicLab.Encodings.PackingEncoding.MultiComponentVector;
using HeuristicLab.Problems.BinPacking.Dimensions;
namespace HeuristicLab.Problems.BinPacking.Problem {
[Item("RegularIdenticalBinPackingProblem", "Represents a bin-packing problem-instance using only bins with identical measures and bins/items with regular shapes (e.g. rectangle, cuboid).")]
[StorableClass]
public abstract class RegularIdenticalBinPackingProblem : BinPackingProblem, IProblemInstanceConsumer, IProblemInstanceExporter
where D : class, IPackingDimensions
where B : PackingShape, IPackingBin, IRegularPackingShape, new()
where I : PackingShape, IPackingItem, IRegularPackingShape, new() {
#region Parameter Properties
public ValueParameter PackingBinMeasuresParameter {
get { return (ValueParameter)Parameters["PackingBinMeasures"]; }
}
public ConstrainedValueParameter PackingSolutionDecoderParameter {
get { return (ConstrainedValueParameter)Parameters["PackingSolutionDecoder"]; }
}
#endregion
#region Properties
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 RegularIdenticalBinPackingProblem(bool deserializing) : base(deserializing) { }
protected RegularIdenticalBinPackingProblem(RegularIdenticalBinPackingProblem original, Cloner cloner)
: base(original, cloner) {
InitializeEventHandlers();
}
protected RegularIdenticalBinPackingProblem(IPackingPlanEvaluationAlgorithm e) : this(e, new MultiComponentVectorRandomCreator()) { }
protected RegularIdenticalBinPackingProblem(IPackingPlanEvaluationAlgorithm e, IPackingSolutionCreator c)
: base(e, c) {
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();
}
#region Helpers
protected override void InitializeProblemInstance() {
InitializeProblemData();
ApplyHorizontalOrientation();
SortItems();
RemoveTooBigItems();
PackingItemsParameter.Value.Value = PackingItemMeasures.Count;
LowerBoundParameter.Value.Value = CalculateLowerBound();
}
protected abstract void RemoveTooBigItems();
protected abstract void InitializeProblemData();
protected abstract IPackingPlanEvaluator CreateDefaultEvaluator();
private void ApplyHorizontalOrientation() {
PackingBinMeasures.ApplyHorizontalOrientation();
foreach (IRegularPackingShape shape in PackingItemMeasures) {
shape.ApplyHorizontalOrientation();
}
}
private void SortItems() {
PackingItemMeasures.Sort((x, y) => y.CompareTo(x));
}
private 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.MultipliedMeasures).Sum();
int bin = PackingBinMeasures.MultipliedMeasures;
return (items + bin - 1)/(bin);
}
protected override void InitializeOperators() {
Operators.Clear();
Operators.Add(new BestBinPackingSolutionAnalyzer());
ApplyEncoding();
ParameterizeOperators();
}
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;
}
}
}
protected override 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;
}
#endregion
#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
#region Problem instance handling
public virtual void Load(BPPData data) {
var realData = data as RealBPPData;
var binData = new B();
binData.InitializeFromMeasures (data.BinMeasures);
var itemData = new ItemList(data.Items);
for (int j = 0; j < data.Items; j++) {
var item = new I();
item.InitializeFromMeasures(data.ItemMeasures[j]);
item.AddTargetBinMeasures(data.BinMeasures);
if (realData != null) {
item.Weight = realData.ItemWeights[j];
item.Material = realData.ItemMaterials[j];
}
itemData.Add(item);
}
BestKnownQuality = data.BestKnownQuality.HasValue ? new DoubleValue(data.BestKnownQuality.Value) : null;
PackingBinMeasures = binData;
//PackingItemsParameter.Value.Value = data.Items;
PackingItemMeasures = itemData;
ApplyHorizontalOrientation();
SortItems();
PackingItemsParameter.Value.Value = PackingItemMeasures.Count;
LowerBoundParameter.Value.Value = CalculateLowerBound();
}
public BPPData Export() {
var result = new BPPData{
Name = Name,
Description = Description,
Items = PackingItemsParameter.Value.Value,
BinMeasures = PackingBinMeasures.ToArray()
};
var itemMeasures = new int[result.Items][];
int i = 0;
foreach (var item in PackingItemMeasures) {
itemMeasures[i] = item.ToArray();
i++;
}
result.ItemMeasures = itemMeasures;
return result;
}
#endregion
}
}