#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.Linq;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Encodings.IntegerVectorEncoding;
using HeuristicLab.Operators;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Problems.GeneralizedQuadraticAssignment {
[Item("N-Move Evaluator", "Evaluates an N-Move.")]
[StorableClass]
public class GQAPNMoveEvaluator : SingleSuccessorOperator, IGQAPNMoveEvaluator, IAssignmentAwareGQAPOperator,
IQualityAwareGQAPOperator, ITransportationCostsAwareGQAPOperator,
IOverbookedCapacityPenaltyAwareGQAPOperator, IWeightsAwareGQAPOperator, IDistancesAwareGQAPOperator,
IInstallationCostsAwareGQAPOperator, IDemandsAwareGQAPOperator, ICapacitiesAwareGQAPOperator {
#region Parameter Descriptions
public static readonly string MoveQualityDescription = "The quality of the move if it would be applied.";
public static readonly string MoveFlowDistanceQualityDescription = "The quality of the move regarding the flow-distance criteria.";
public static readonly string MoveInstallationQualityDescription = "The quality of the move regarding the installation costs.";
public static readonly string MoveOverbookedCapacityDescription = "The sum of the overbooked capacities of the move relative to the capacity of each location.";
#endregion
#region Parameter Properties
ILookupParameter IQualityAwareGQAPOperator.MaximizationParameter {
get { return MaximizationParameter; }
}
ILookupParameter IGQAPMoveEvaluator.MaximizationParameter {
get { return MaximizationParameter; }
}
public ILookupParameter MaximizationParameter {
get { return (ILookupParameter)Parameters["Maximization"]; }
}
public ILookupParameter MoveQualityParameter {
get { return (ILookupParameter)Parameters["MoveQuality"]; }
}
public ILookupParameter MoveFlowDistanceQualityParameter {
get { return (ILookupParameter)Parameters["MoveFlowDistanceQuality"]; }
}
public ILookupParameter MoveInstallationQualityParameter {
get { return (ILookupParameter)Parameters["MoveInstallationQuality"]; }
}
public ILookupParameter MoveOverbookedCapacityParameter {
get { return (ILookupParameter)Parameters["MoveOverbookedCapacity"]; }
}
public ILookupParameter MoveParameter {
get { return (ILookupParameter)Parameters["Move"]; }
}
public ILookupParameter AssignmentParameter {
get { return (ILookupParameter)Parameters["Assignment"]; }
}
ILookupParameter ISingleObjectiveMoveEvaluator.QualityParameter {
get { return QualityParameter; }
}
ILookupParameter IQualityAwareGQAPOperator.QualityParameter {
get { return QualityParameter; }
}
public ILookupParameter QualityParameter {
get { return (ILookupParameter)Parameters["Quality"]; }
}
public ILookupParameter FlowDistanceQualityParameter {
get { return (ILookupParameter)Parameters["FlowDistanceQuality"]; }
}
public ILookupParameter InstallationQualityParameter {
get { return (ILookupParameter)Parameters["InstallationQuality"]; }
}
public ILookupParameter OverbookedCapacityParameter {
get { return (ILookupParameter)Parameters["OverbookedCapacity"]; }
}
public IValueLookupParameter TransportationCostsParameter {
get { return (IValueLookupParameter)Parameters["TransportationCosts"]; }
}
public IValueLookupParameter OverbookedCapacityPenaltyParameter {
get { return (IValueLookupParameter)Parameters["OverbookedCapacityPenalty"]; }
}
public ILookupParameter WeightsParameter {
get { return (ILookupParameter)Parameters["Weights"]; }
}
public ILookupParameter DistancesParameter {
get { return (ILookupParameter)Parameters["Distances"]; }
}
public ILookupParameter InstallationCostsParameter {
get { return (ILookupParameter)Parameters["InstallationCosts"]; }
}
public ILookupParameter DemandsParameter {
get { return (ILookupParameter)Parameters["Demands"]; }
}
public ILookupParameter CapacitiesParameter {
get { return (ILookupParameter)Parameters["Capacities"]; }
}
#endregion
[StorableConstructor]
protected GQAPNMoveEvaluator(bool deserializing) : base(deserializing) { }
protected GQAPNMoveEvaluator(GQAPNMoveEvaluator original, Cloner cloner) : base(original, cloner) { }
public GQAPNMoveEvaluator()
: base() {
Parameters.Add(new LookupParameter("Assignment", GQAPSolutionCreator.AssignmentDescription));
Parameters.Add(new LookupParameter("Move", GQAPNMoveGenerator.MoveDescription));
Parameters.Add(new LookupParameter("Maximization", GeneralizedQuadraticAssignmentProblem.MaximizationDescription));
Parameters.Add(new LookupParameter("Quality", GQAPEvaluator.QualityDescription));
Parameters.Add(new LookupParameter("FlowDistanceQuality", GQAPEvaluator.FlowDistanceQualityDescription));
Parameters.Add(new LookupParameter("InstallationQuality", GQAPEvaluator.InstallationQualityDescription));
Parameters.Add(new LookupParameter("OverbookedCapacity", GQAPEvaluator.OverbookedCapacityDescription));
Parameters.Add(new LookupParameter("MoveQuality", MoveQualityDescription));
Parameters.Add(new LookupParameter("MoveFlowDistanceQuality", MoveFlowDistanceQualityDescription));
Parameters.Add(new LookupParameter("MoveInstallationQuality", MoveInstallationQualityDescription));
Parameters.Add(new LookupParameter("MoveOverbookedCapacity", MoveOverbookedCapacityDescription));
Parameters.Add(new ValueLookupParameter("OverbookedCapacityPenalty", GeneralizedQuadraticAssignmentProblem.OverbookedCapacityPenaltyDescription));
Parameters.Add(new ValueLookupParameter("TransportationCosts", GeneralizedQuadraticAssignmentProblem.TransportationCostsDescription));
Parameters.Add(new LookupParameter("Weights", GeneralizedQuadraticAssignmentProblem.WeightsDescription));
Parameters.Add(new LookupParameter("Distances", GeneralizedQuadraticAssignmentProblem.DistancesDescription));
Parameters.Add(new LookupParameter("InstallationCosts", GeneralizedQuadraticAssignmentProblem.InstallationCostsDescription));
Parameters.Add(new LookupParameter("Demands", GeneralizedQuadraticAssignmentProblem.DemandsDescription));
Parameters.Add(new LookupParameter("Capacities", GeneralizedQuadraticAssignmentProblem.CapacitiesDescription));
}
public override IDeepCloneable Clone(Cloner cloner) {
return new GQAPNMoveEvaluator(this, cloner);
}
public static double Evaluate(NMove move, IntegerVector assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts,
DoubleArray demands, DoubleArray capacities, DoubleValue transportationCosts, DoubleValue overbookedCapacityPenalty) {
double moveFlowDistanceQuality, moveInstallationQuality, moveOverbookedCapacity;
Evaluate(move, assignment, weights, distances, installationCosts, demands, capacities,
out moveFlowDistanceQuality, out moveInstallationQuality, out moveOverbookedCapacity);
return GQAPEvaluator.GetCombinedQuality(moveFlowDistanceQuality, moveInstallationQuality, moveOverbookedCapacity,
transportationCosts.Value, overbookedCapacityPenalty.Value);
}
public static void Evaluate(NMove move, IntegerVector assignment, DoubleMatrix weights, DoubleMatrix distances, DoubleMatrix installationCosts,
DoubleArray demands, DoubleArray capacities, out double moveFlowDistanceQuality, out double moveInstallationQuality, out double moveOverbookedCapacity) {
moveFlowDistanceQuality = moveInstallationQuality = moveOverbookedCapacity = 0.0;
int moves = move.N;
var slack = (DoubleArray)capacities.Clone();
var oldSlack = (DoubleArray)slack.Clone();
bool first = true;
foreach (var kvp in move.NewAssignments) {
int equip = kvp.Key;
int newLoc = kvp.Value;
moveInstallationQuality -= installationCosts[equip, assignment[equip]];
moveInstallationQuality += installationCosts[equip, newLoc];
for (int j = 0; j < assignment.Length; j++) {
if (!move.NewAssignments.ContainsKey(j)) {
moveFlowDistanceQuality += weights[equip, j] * distances[newLoc, assignment[j]];
moveFlowDistanceQuality -= weights[equip, j] * distances[assignment[equip], assignment[j]];
moveFlowDistanceQuality += weights[j, equip] * distances[assignment[j], newLoc];
moveFlowDistanceQuality -= weights[j, equip] * distances[assignment[j], assignment[equip]];
if (first) { // only once for each untouched equipment deduct the demand from the capacity
slack[assignment[j]] -= demands[j];
oldSlack[assignment[j]] -= demands[j];
}
} else {
moveFlowDistanceQuality += weights[equip, j] * distances[newLoc, move.NewAssignments[j]];
moveFlowDistanceQuality -= weights[equip, j] * distances[assignment[equip], assignment[j]];
}
}
first = false;
slack[newLoc] -= demands[equip];
oldSlack[assignment[equip]] -= demands[equip];
}
moveOverbookedCapacity = slack.Select((v, i) => new { V = v, Index = i }).Where(x => x.V < 0.0).Select(x => -x.V / capacities[x.Index]).Sum()
- oldSlack.Select((v, i) => new { V = v, Index = i }).Where(x => x.V < 0.0).Select(x => -x.V / capacities[x.Index]).Sum();
}
public override IOperation Apply() {
double moveFlowDistanceQuality, moveInstallationQuality, moveOverbookedCapacity;
double quality = QualityParameter.ActualValue.Value;
double transportationCosts = TransportationCostsParameter.ActualValue.Value;
double overbookedCapacityPenalty = OverbookedCapacityPenaltyParameter.ActualValue.Value;
double flowDistanceQuality = FlowDistanceQualityParameter.ActualValue.Value;
double installationQuality = InstallationQualityParameter.ActualValue.Value;
double overbookedCapacity = OverbookedCapacityParameter.ActualValue.Value;
Evaluate(MoveParameter.ActualValue,
AssignmentParameter.ActualValue,
WeightsParameter.ActualValue, DistancesParameter.ActualValue,
InstallationCostsParameter.ActualValue,
DemandsParameter.ActualValue, CapacitiesParameter.ActualValue,
out moveFlowDistanceQuality, out moveInstallationQuality, out moveOverbookedCapacity);
MoveFlowDistanceQualityParameter.ActualValue = new DoubleValue(flowDistanceQuality + moveFlowDistanceQuality);
MoveInstallationQualityParameter.ActualValue = new DoubleValue(installationQuality + moveInstallationQuality);
MoveOverbookedCapacityParameter.ActualValue = new DoubleValue(overbookedCapacity + moveOverbookedCapacity);
MoveQualityParameter.ActualValue = new DoubleValue(GQAPEvaluator.GetCombinedQuality(
flowDistanceQuality + moveFlowDistanceQuality,
installationQuality + moveInstallationQuality,
overbookedCapacity + moveOverbookedCapacity,
transportationCosts,
overbookedCapacityPenalty));
return base.Apply();
}
}
}