#region License Information /* HeuristicLab * Copyright (C) 2002-2018 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 HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.IntegerVectorEncoding; using HeuristicLab.Encodings.RealVectorEncoding; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.Scheduling.MRCPSP { [Item("Feasibility Improvement Method (FIM) Improver", "Improves a solution by calling GetNeighbors and Evaluate of the corresponding problem definition.")] [StorableClass] public abstract class BasicMrcpspImprover : SingleSuccessorOperator, IImprovementOperator, IStochasticOperator { public MultiModeResourceConstrainedProjectSchedulingProblem Problem { get; set; } public ILookupParameter RandomParameter => (ILookupParameter)Parameters["Random"]; public ILookupParameter EncodingParameter => (ILookupParameter)Parameters["Encoding"]; public ILookupParameter QualityParameter => (ILookupParameter)Parameters["Quality"]; public ILookupParameter MaximizationParameter => (ILookupParameter)Parameters["Maximization"]; public IValueLookupParameter ImprovementAttemptsParameter => (IValueLookupParameter)Parameters["ImprovementAttempts"]; public IValueLookupParameter SampleSizeParameter => (IValueLookupParameter)Parameters["SampleSize"]; public ILookupParameter LocalEvaluatedSolutionsParameter => (ILookupParameter)Parameters["LocalEvaluatedSolutions"]; public Func EvaluateFunc { get; set; } [StorableConstructor] protected BasicMrcpspImprover(bool deserializing) : base(deserializing) { } protected BasicMrcpspImprover(BasicMrcpspImprover original, Cloner cloner) : base(original, cloner) { Problem = cloner.Clone(original.Problem); } protected BasicMrcpspImprover() { Parameters.Add(new LookupParameter("Random", "The random number generator to use.")); Parameters.Add(new LookupParameter("Encoding", "An item that holds the problem's encoding.")); Parameters.Add(new LookupParameter("Quality", "The quality of the parameter vector.")); Parameters.Add(new LookupParameter("Maximization", "Whether the problem should be minimized or maximized.")); Parameters.Add(new ValueLookupParameter("ImprovementAttempts", "The number of improvement attempts the operator should perform.", new IntValue(100))); Parameters.Add(new ValueLookupParameter("SampleSize", "The number of samples to draw from the neighborhood function at maximum.", new IntValue(300))); Parameters.Add(new LookupParameter("LocalEvaluatedSolutions", "The number of solution evaluations that have been performed.")); } public override IOperation Apply() { var random = RandomParameter.ActualValue; var encoding = EncodingParameter.ActualValue; var maximize = MaximizationParameter.ActualValue.Value; var maxAttempts = ImprovementAttemptsParameter.ActualValue.Value; var sampleSize = SampleSizeParameter.ActualValue.Value; var individual = encoding.GetIndividual(ExecutionContext.Scope); //var quality = QualityParameter.ActualValue?.Value ?? EvaluateFunc(individual, random); var count = 0; //for (var i = 0; i < maxAttempts; i++) { // Individual best = null; // var bestQuality = quality; // foreach (var neighbor in GetNeighborsFunc(individual, random).Take(sampleSize)) { // var q = EvaluateFunc(neighbor, random); // count++; // if (maximize && bestQuality > q || !maximize && bestQuality < q) continue; // best = neighbor; // bestQuality = q; // } // if (best == null) break; // individual = best; // quality = bestQuality; //} if (Problem.CalculateERR(individual) <= 0) return base.Apply(); var randomKey = individual.RealVector("RandomKey"); var modeList = individual.IntegerVector("ModeList"); var activities = Problem.Activities.Skip(1).Reverse().Skip(1).Reverse().ToList(); var delta = new Dictionary>(); var index = 0; foreach (var a in activities) { delta[a.Number] = new Dictionary(); foreach (var m in a.Modes) { var ml = new IntegerVector(modeList) { [index] = m.Number }; delta[a.Number][m.Number] = Measure(randomKey, ml); count++; } index++; } var totalDelta = delta.Sum(a => a.Value.Sum(m => m.Value)); var deltas = new List>(); foreach (var a in delta.Keys) { foreach (var m in delta[a].Keys) { deltas.Add(Tuple.Create(delta[a][m], a, m)); } } var selectedQuality = random.NextDouble() * totalDelta; index = 0; var currentQuality = deltas[index].Item1; while (currentQuality < selectedQuality) { index++; currentQuality += deltas[index].Item1; } individual.IntegerVector("ModeList")[activities.FindIndex(a => a.Number == deltas[index].Item2)] = deltas[index].Item3; var quality = Problem.Evaluate(individual, random); LocalEvaluatedSolutionsParameter.ActualValue = new IntValue(count); QualityParameter.ActualValue = new DoubleValue(quality); //individual.CopyToScope(ExecutionContext.Scope); foreach (var val in individual.Values) SetScopeValue(val.Key, ExecutionContext.Scope, val.Value); return base.Apply(); } protected abstract int Measure(RealVector randomKey, IntegerVector modeList); private static void SetScopeValue(string name, IScope scope, IItem value) { if (scope == null) throw new ArgumentNullException(nameof(scope)); if (value == null) throw new ArgumentNullException(nameof(value)); if (!scope.Variables.ContainsKey(name)) scope.Variables.Add(new Variable(name, value)); else scope.Variables[name].Value = value; } } }