#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 } }