#region License Information
/* HeuristicLab
* Copyright (C) 2002-2016 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.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.PermutationEncoding;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.PluginInfrastructure;
using HeuristicLab.Problems.Instances;
using HeuristicLab.Optimization;
using System.Collections.Generic;
namespace HeuristicLab.Problems.PFSP
{
[Item("Permutation Flowshop Scheduling Problem (PFSP)", "Represents a Permutation Flowshop Scheduling Problem")]
[Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 999)]
[StorableClass]
public sealed class PermutationFlowshopSchedulingProblem : SingleObjectiveHeuristicOptimizationProblem, IProblemInstanceConsumer, IProblemInstanceExporter, IStorableContent
{
#region Default Instance
private static readonly FSSPData DefaultInstance = new FSSPData()
{
Name = "Permutation Flowshop Scheduling Problem (PFSP)",
Description = "The default instance of the PFSP problem in HeuristicLab",
Jobs = 4,
Machines = 4,
//BestKnownQuality = 328,
ProcessingTimes = new double[,] {
{5 ,3, 6 ,6 },
{2 ,4, 8 ,4},
{4 ,2, 7 ,4},
{5 ,3, 8 ,6}
}
};
#endregion
public string Filename { get; set; }
#region Parameter Properties
public OptionalValueParameter BestKnownSolutionParameter
{
get { return (OptionalValueParameter)Parameters["BestKnownSolution"]; }
}
public OptionalValueParameter JobMatrixParameter
{
get { return (OptionalValueParameter)Parameters["JobMatrix"]; }
}
#endregion
#region Properties
public Permutation BestKnownSolution
{
get { return BestKnownSolutionParameter.Value; }
set
{
BestKnownSolutionParameter.Value = value;
if (BestKnownSolutionChanged != null) { OnBestKnownSolutionChanged(); }
}
}
public JobMatrix JobMatrix
{
get { return JobMatrixParameter.Value; }
set { JobMatrixParameter.Value = value; }
}
#endregion
public event EventHandler BestKnownSolutionChanged;
private void OnBestKnownSolutionChanged()
{
var changed = BestKnownSolutionChanged;
if (changed != null)
changed(this, EventArgs.Empty);
}
[StorableConstructor]
private PermutationFlowshopSchedulingProblem(bool deserializing) : base(deserializing) { }
private PermutationFlowshopSchedulingProblem(PermutationFlowshopSchedulingProblem original, Cloner cloner)
: base(original, cloner)
{
}
public PermutationFlowshopSchedulingProblem()
: base(new CmaxMakeSpanEvaluator(), new RandomPermutationCreator())
{
Parameters.Add(new OptionalValueParameter("BestKnownSolution", "The best known solution of this FSSP instance."));
Parameters.Add(new OptionalValueParameter("JobMatrix", "The matrix which contains the jobs,machines and duration."));
Load(DefaultInstance);
EvaluatorParameter.GetsCollected = false;
EvaluatorParameter.Hidden = true;
Maximization.Value = false;
MaximizationParameter.Hidden = true;
SolutionCreator.PermutationParameter.ActualName = "PFSPOrder";
Evaluator.QualityParameter.ActualName = "Makespan";
ParameterizeSolutionCreator();
ParameterizeEvaluator();
InitializeOperators();
}
public override IDeepCloneable Clone(Cloner cloner)
{
return new PermutationFlowshopSchedulingProblem(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() { }
#region Problem Instance Handling
public void Load(FSSPData data)
{
BestKnownQuality = data.BestKnownQuality.HasValue ? new DoubleValue(data.BestKnownQuality.Value) : null;
Name = data.Name;
Description = data.Description;
JobMatrix = new JobMatrix(data.ProcessingTimes);
if (data.BestKnownSchedule != null)
{
int[] permut = data.BestKnownSchedule;
//Clean up if the first index = 1
if (!permut.Contains(0)) { permut = permut.Select(v => v - 1).ToArray(); }
double bestKnownQuality = MakeSpanEvaluator.Apply(
new CmaxMakeSpanEvaluator(),
new DoubleMatrix(data.ProcessingTimes),
new Permutation(PermutationTypes.Absolute, permut)
);
BestKnownSolution = new Permutation(PermutationTypes.Absolute, data.BestKnownSchedule);
BestKnownQuality = new DoubleValue(bestKnownQuality);
}
ParameterizeSolutionCreator();
}
public FSSPData Export()
{
var result = new FSSPData
{
Name = Name,
Description = Description,
ProcessingTimes = new double[JobMatrix.Rows, JobMatrix.Columns]
};
if (BestKnownQuality != null)
{
result.BestKnownQuality = BestKnownQuality.Value;
}
if (JobMatrix != null)
{
result.Jobs = JobMatrix.Rows;
result.Machines = JobMatrix.Columns;
}
for (int i = 0; i < JobMatrix.Rows; i++)
{
for (int j = 0; j < JobMatrix.Columns; j++)
{
result.ProcessingTimes[i, j] = JobMatrix[i, j];
}
}
result.BestKnownSchedule = BestKnownSolution != null ? (BestKnownSolution as IntArray).ToArray() : null;
return result;
}
#endregion
#region Helpers
private void InitializeOperators()
{
Operators.AddRange(ApplicationManager.Manager.GetInstances());
ParameterizeOperators();
}
private void ParameterizeOperators()
{
foreach (IPermutationCrossover op in Operators.OfType())
{
op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.ParentsParameter.Hidden = true;
op.ChildParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.ChildParameter.Hidden = true;
}
foreach (IPermutationManipulator op in Operators.OfType())
{
op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.PermutationParameter.Hidden = true;
}
foreach (IPermutationMoveOperator op in Operators.OfType())
{
op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.PermutationParameter.Hidden = true;
}
foreach (IPermutationMultiNeighborhoodShakingOperator op in Operators.OfType())
{
op.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.PermutationParameter.Hidden = true;
}
foreach (ISingleObjectiveImprovementOperator op in Operators.OfType())
{
op.SolutionParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.SolutionParameter.Hidden = true;
}
foreach (ISingleObjectivePathRelinker op in Operators.OfType())
{
op.ParentsParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
op.ParentsParameter.Hidden = true;
}
foreach (ISolutionSimilarityCalculator op in Operators.OfType())
{
op.SolutionVariableName = SolutionCreator.PermutationParameter.ActualName;
op.QualityVariableName = Evaluator.QualityParameter.ActualName;
}
}
private void ParameterizeSolutionCreator()
{
SolutionCreator.LengthParameter.Value = new IntValue(JobMatrix.Columns);
SolutionCreator.LengthParameter.Hidden = SolutionCreator.LengthParameter.Value != null;
SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.RelativeUndirected);
SolutionCreator.PermutationTypeParameter.Hidden = true;
}
private void ParameterizeEvaluator()
{
if (Evaluator is CmaxMakeSpanEvaluator)
{
IMakespanEvaluator evaluator = (IMakespanEvaluator)Evaluator;
evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
evaluator.PermutationParameter.Hidden = true;
}
}
#endregion
}
}