#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;
using HeuristicLab.Problems.Instances.Types;
namespace HeuristicLab.Problems.LinearOrdering
{
[Item("Linear Ordering Problem (LOP)", "Represents a Linear Ordering Problem")]
[Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 999)]
[StorableClass]
public sealed class LinearOrderingProblem : SingleObjectiveHeuristicOptimizationProblem, IProblemInstanceConsumer, IProblemInstanceExporter, IStorableContent
{
#region Default Instance
private static readonly LOPData DefaultInstance = new LOPData()
{
Name = "Linaer Ordering Problem (LOP)",
Description = "The default instance of the LOP in HeuristicLab",
Dimension = 4,
Matrix = new double[,] {
{0 ,3, 6 ,6},
{2 ,0, 8 ,4},
{4 ,2, 0 ,4},
{5 ,3, 8 ,0}
}
};
#endregion
public string Filename { get; set; }
#region Parameter Properties
public OptionalValueParameter BestKnownSolutionParameter {
get { return (OptionalValueParameter)Parameters["BestKnownSolution"]; }
}
public OptionalValueParameter MatrixParameter {
get { return (OptionalValueParameter)Parameters["Matrix"]; }
}
#endregion
#region Properties
public Permutation BestKnownSolution {
get { return BestKnownSolutionParameter.Value; }
set {
BestKnownSolutionParameter.Value = value;
if (BestKnownSolutionChanged != null) { OnBestKnownSolutionChanged(); }
}
}
public DoubleMatrix Matrix {
get { return MatrixParameter.Value; }
set { MatrixParameter.Value = value; }
}
#endregion
public event EventHandler BestKnownSolutionChanged;
private void OnBestKnownSolutionChanged()
{
var changed = BestKnownSolutionChanged;
if (changed != null)
changed(this, EventArgs.Empty);
}
// BackwardsCompatibility3.3
#region Backwards compatible code, remove with 3.4
[Obsolete]
[Storable(Name = "operators")]
private IEnumerable oldOperators {
get { return null; }
set {
if (value != null && value.Any())
Operators.AddRange(value);
}
}
#endregion
[StorableConstructor]
private LinearOrderingProblem(bool deserializing) : base(deserializing) { }
private LinearOrderingProblem(LinearOrderingProblem original, Cloner cloner)
: base(original, cloner)
{
RegisterEventHandlers();
}
public LinearOrderingProblem()
: base(new AwesomeTriangulationEvaluator(), new RandomPermutationCreator())
{
Parameters.Add(new OptionalValueParameter("BestKnownSolution", "The best known solution of this LOP instance."));
Parameters.Add(new OptionalValueParameter("Matrix", "The matrix which contains the jobs,machines and duration."));
Load(DefaultInstance);
EvaluatorParameter.GetsCollected = false;
EvaluatorParameter.Hidden = true;
Maximization.Value = true;
MaximizationParameter.Hidden = true;
SolutionCreator.PermutationParameter.ActualName = "PFSPOrder";
Evaluator.QualityParameter.ActualName = "Makespan";
ParameterizeSolutionCreator();
ParameterizeEvaluator();
InitializeOperators();
RegisterEventHandlers();
}
public override IDeepCloneable Clone(Cloner cloner)
{
return new LinearOrderingProblem(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization()
{
RegisterEventHandlers();
}
private void RegisterEventHandlers()
{
SolutionCreator.PermutationParameter.ActualNameChanged += new EventHandler(SolutionCreator_PermutationParameter_ActualNameChanged);
Evaluator.QualityParameter.ActualNameChanged += new EventHandler(Evaluator_QualityParameter_ActualNameChanged);
}
private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e)
{
//Nothing to do ParameterizeAnalyzers();
}
private void SolutionCreator_PermutationParameter_ActualNameChanged(object sender, EventArgs e)
{
ParameterizeEvaluator();
//ParameterizeAnalyzers();
ParameterizeOperators();
}
#region Events
private void ScheduleEvaluator_QualityParameter_ActualNameChanged(object sender, EventArgs eventArgs)
{
ParameterizeOperators();
}
private void SolutionCreator_SchedulingEncodingParameter_ActualNameChanged(object sender, EventArgs eventArgs)
{
ParameterizeOperators();
}
private void ScheduleDecoder_ScheduleParameter_ActualNameChanged(object sender, EventArgs eventArgs)
{
ParameterizeOperators();
}
#endregion
#region Problem Instance Handling
public void Load(LOPData data)
{
BestKnownQuality = data.BestKnownQuality.HasValue ? new DoubleValue(data.BestKnownQuality.Value) : null;
Name = data.Name;
Description = data.Description;
Matrix = new DoubleMatrix(data.Matrix);
if (data.BestKnownPermutation != null)
{
int[] permut = data.BestKnownPermutation;
//Clean up if the first index = 1
if (!permut.Contains(0)) { permut = permut.Select(v => v - 1).ToArray(); }
double bestKnownQuality = MatrixTriangulationEvaluator.Apply(
new AwesomeTriangulationEvaluator(),
new DoubleMatrix(data.Matrix),
new Permutation(PermutationTypes.Absolute, permut)
);
BestKnownSolution = new Permutation(PermutationTypes.Absolute, data.BestKnownPermutation);
BestKnownQuality = new DoubleValue(bestKnownQuality);
}
ParameterizeSolutionCreator();
}
public LOPData Export()
{
var result = new LOPData
{
Name = Name,
Description = Description,
BestKnownQuality = BestKnownQuality.Value,
//BestKnownPermutation = Matrix.row,
//Machines = Matrix.Columns
};
for (int i = 0; i < Matrix.Rows; i++)
{
for (int j = 0; j < Matrix.Columns; j++)
{
//result.ProcessingTimes[i, j] = Matrix[i, j];
}
}
return result;
}
#endregion
#region Helpers
private void InitializeOperators()
{
var operators = new HashSet(new IPermutationOperator[] {
new OrderCrossover2(),
new InversionManipulator(),
new StochasticInversionMultiMoveGenerator()
}, new TypeEqualityComparer());
foreach (var op in ApplicationManager.Manager.GetInstances())
operators.Add(op);
Operators.AddRange(operators);
ParameterizeOperators();
UpdateMoveEvaluators();
}
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;
}
}
#endregion
private void UpdateMoveEvaluators()
{
ParameterizeOperators();
OnOperatorsChanged();
}
private void ParameterizeSolutionCreator()
{
SolutionCreator.LengthParameter.Value = new IntValue(Matrix.Columns); //Jobs
SolutionCreator.LengthParameter.Hidden = SolutionCreator.LengthParameter.Value != null;
SolutionCreator.PermutationTypeParameter.Value = new PermutationType(PermutationTypes.RelativeUndirected);
SolutionCreator.PermutationTypeParameter.Hidden = true;
}
private void ParameterizeEvaluator()
{
if (Evaluator is AwesomeTriangulationEvaluator)
{
IMatrixTriangulationEvaluator evaluator = (IMatrixTriangulationEvaluator)Evaluator;
evaluator.PermutationParameter.ActualName = SolutionCreator.PermutationParameter.ActualName;
evaluator.PermutationParameter.Hidden = true;
}
}
}
}