#region License Information
/* HeuristicLab
* Copyright (C) 2002-2011 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.Core;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Common;
using HeuristicLab.PDPSimulation.DomainModel;
using System.Threading;
using HeuristicLab.Problems.VehicleRouting.Interfaces;
using HeuristicLab.Problems.VehicleRouting;
using HeuristicLab.Problems.VehicleRouting.Variants;
using HeuristicLab.Problems.VehicleRouting.ProblemInstances;
using HeuristicLab.PDPSimulation.Operators;
using HeuristicLab.Parameters;
using HeuristicLab.Data;
using System.Threading.Tasks;
using HeuristicLab.Problems.VehicleRouting.Encodings.Potvin;
namespace HeuristicLab.PDPSimulation {
[Item("PFIHReoptimization", "A pickup and delivery PFIH optimization.")]
[StorableClass]
public class PFIHReoptimization : DynamicPDPOptimization {
public IValueParameter Alpha {
get { return (IValueParameter)Parameters["Alpha"]; }
}
public IValueParameter AlphaVariance {
get { return (IValueParameter)Parameters["AlphaVariance"]; }
}
public IValueParameter Beta {
get { return (IValueParameter)Parameters["Beta"]; }
}
public IValueParameter BetaVariance {
get { return (IValueParameter)Parameters["BetaVariance"]; }
}
public IValueParameter Gamma {
get { return (IValueParameter)Parameters["Gamma"]; }
}
public IValueParameter GammaVariance {
get { return (IValueParameter)Parameters["GammaVariance"]; }
}
public ValueParameter SampleSizeParameter {
get { return (ValueParameter)Parameters["SampleSize"]; }
}
public ValueParameter ComputeInParallelParameter {
get { return (ValueParameter)Parameters["ComputeInParallel"]; }
}
public PFIHReoptimization(): base() {
Parameters.Add(new ValueParameter("Alpha", "The alpha value.", new DoubleValue(0.7)));
Parameters.Add(new ValueParameter("AlphaVariance", "The alpha variance.", new DoubleValue(0.5)));
Parameters.Add(new ValueParameter("Beta", "The beta value.", new DoubleValue(0.1)));
Parameters.Add(new ValueParameter("BetaVariance", "The beta variance.", new DoubleValue(0.07)));
Parameters.Add(new ValueParameter("Gamma", "The gamma value.", new DoubleValue(0.2)));
Parameters.Add(new ValueParameter("GammaVariance", "The gamma variance.", new DoubleValue(0.14)));
Parameters.Add(new ValueParameter("SampleSize", "The sample size.", new IntValue(10)));
Parameters.Add(new ValueParameter("ComputeInParallel", "Indicates if the samples should be computed in parallel.", new BoolValue(true)));
}
[StorableConstructor]
private PFIHReoptimization(bool deserializing) : base(deserializing) {
}
private PFIHReoptimization(PFIHReoptimization original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new PFIHReoptimization(this, cloner);
}
class PFIHResult {
public PFIHResult() {
bestFeasible = false;
bestQuality = double.MaxValue;
bestSolution = null;
}
public bool bestFeasible;
public double bestQuality;
public IVRPEncoding bestSolution;
}
private IVRPEncoding Optimize(DynamicPDProblemInstance instance) {
List vehicleUsed = new List();
for (int i = 0; i < instance.StaticInstance.Vehicles.Value; i++) {
Vehicle vehicle = GetVehicle(instance.GetVehicle(i));
vehicleUsed.Add(vehicle.Distance > 0);
}
int sampleSize = SampleSizeParameter.Value.Value;
PFIHResult bestResult = new PFIHResult();
var options = new ParallelOptions();
if (ComputeInParallelParameter.Value.Value)
options.MaxDegreeOfParallelism = Math.Max(Environment.ProcessorCount - 1, 1);
else
options.MaxDegreeOfParallelism = 1;
IRandom random = new HeuristicLab.Random.MersenneTwister(1234);
Parallel.For(0, sampleSize, options,
() => new PFIHResult(),
(i, loop, result) => {
IVRPEncoding current = DynPushForwardInsertionCreator.CreateSolution(instance.StaticInstance,
random, vehicleUsed,
Alpha.Value.Value, Beta.Value.Value, Gamma.Value.Value,
AlphaVariance.Value.Value, BetaVariance.Value.Value, GammaVariance.Value.Value);
VRPEvaluation eval = instance.StaticInstance.Evaluate(current);
double quality = eval.Quality;
bool feasible = instance.StaticInstance.Feasible(eval);
if ((feasible && !result.bestFeasible) || (feasible == result.bestFeasible && quality < result.bestQuality)) {
result.bestQuality = quality;
result.bestSolution = current;
result.bestFeasible = feasible;
}
return result;
},
(result) => {
lock (bestResult) {
if ((result.bestFeasible && !bestResult.bestFeasible) || (result.bestFeasible == bestResult.bestFeasible && result.bestQuality < bestResult.bestQuality)) {
bestResult.bestQuality = result.bestQuality;
bestResult.bestSolution = result.bestSolution;
bestResult.bestFeasible = result.bestFeasible;
}
}
}
);
//Recourse
if (!bestResult.bestFeasible) {
PotvinEncoding currentPlan = (instance.StaticInstance as DynPDPProblemInstance).CurrentPlan;
BestInsertion.RouteUnrouted(instance.StaticInstance, currentPlan);
bestResult.bestSolution = currentPlan;
}
return bestResult.bestSolution;
}
protected override bool PerformOptimization(DynamicPDProblemInstance instance, ChangeInformation changeInformation) {
IVRPEncoding solution = Optimize(instance);
PerformPlan(solution);
return true;
}
}
}