#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.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using HeuristicLab.Algorithms.MemPR.Interfaces; using HeuristicLab.Analysis.FitnessLandscape; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Random; using ExecutionContext = HeuristicLab.Core.ExecutionContext; namespace HeuristicLab.Algorithms.MemPR { [Item("MemPRContext", "Abstract base class for MemPR contexts.")] [StorableClass] public abstract class MemPRPopulationContext : ParameterizedNamedItem, IPopulationBasedHeuristicAlgorithmContext, ISolutionModelContext, IEvaluationServiceContext, ILocalSearchPathContext where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem where TSolution : class, IItem where TPopulationContext : MemPRPopulationContext where TSolutionContext : MemPRSolutionContext { private IExecutionContext parent; public IExecutionContext Parent { get { return parent; } set { parent = value; } } [Storable] private IScope scope; public IScope Scope { get { return scope; } private set { scope = value; } } IKeyedItemCollection IExecutionContext.Parameters { get { return Parameters; } } [Storable] private IValueParameter problem; public TProblem Problem { get { return problem.Value; } set { problem.Value = value; } } public bool Maximization { get { return ((IValueParameter)Problem.MaximizationParameter).Value.Value; } } [Storable] private IValueParameter initialized; public bool Initialized { get { return initialized.Value.Value; } set { initialized.Value.Value = value; } } [Storable] private IValueParameter iterations; public int Iterations { get { return iterations.Value.Value; } set { iterations.Value.Value = value; } } [Storable] private IValueParameter evaluatedSolutions; public int EvaluatedSolutions { get { return evaluatedSolutions.Value.Value; } set { evaluatedSolutions.Value.Value = value; } } [Storable] private IValueParameter bestQuality; public double BestQuality { get { return bestQuality.Value.Value; } set { bestQuality.Value.Value = value; } } [Storable] private IValueParameter bestSolution; public TSolution BestSolution { get { return bestSolution.Value; } set { bestSolution.Value = value; } } [Storable] private IValueParameter localSearchEvaluations; public int LocalSearchEvaluations { get { return localSearchEvaluations.Value.Value; } set { localSearchEvaluations.Value.Value = value; } } [Storable] private IValueParameter localOptimaLevel; public double LocalOptimaLevel { get { return localOptimaLevel.Value.Value; } set { localOptimaLevel.Value.Value = value; } } [Storable] private IValueParameter byBreeding; public int ByBreeding { get { return byBreeding.Value.Value; } set { byBreeding.Value.Value = value; } } [Storable] private IValueParameter byRelinking; public int ByRelinking { get { return byRelinking.Value.Value; } set { byRelinking.Value.Value = value; } } [Storable] private IValueParameter byDelinking; public int ByDelinking { get { return byDelinking.Value.Value; } set { byDelinking.Value.Value = value; } } [Storable] private IValueParameter bySampling; public int BySampling { get { return bySampling.Value.Value; } set { bySampling.Value.Value = value; } } [Storable] private IValueParameter byHillclimbing; public int ByHillclimbing { get { return byHillclimbing.Value.Value; } set { byHillclimbing.Value.Value = value; } } [Storable] private IValueParameter byAdaptivewalking; public int ByAdaptivewalking { get { return byAdaptivewalking.Value.Value; } set { byAdaptivewalking.Value.Value = value; } } [Storable] private IValueParameter> relinkedPaths; public DirectedPath RelinkedPaths { get { return relinkedPaths.Value; } set { relinkedPaths.Value = value; } } [Storable] private IValueParameter> localSearchPaths; public DirectedPath LocalSearchPaths { get { return localSearchPaths.Value; } set { localSearchPaths.Value = value; } } [Storable] private IValueParameter random; public IRandom Random { get { return random.Value; } set { random.Value = value; } } public IEnumerable> Population { get { return scope.SubScopes.OfType>(); } } public void AddToPopulation(ISingleObjectiveSolutionScope solScope) { scope.SubScopes.Add(solScope); } public void ReplaceAtPopulation(int index, ISingleObjectiveSolutionScope solScope) { scope.SubScopes[index] = solScope; } public ISingleObjectiveSolutionScope AtPopulation(int index) { return scope.SubScopes[index] as ISingleObjectiveSolutionScope; } public void SortPopulation() { scope.SubScopes.Replace(scope.SubScopes.OfType>().OrderBy(x => Maximization ? -x.Fitness : x.Fitness).ToList()); } public int PopulationCount { get { return scope.SubScopes.Count; } } [Storable] private List> breedingStat; public IEnumerable> BreedingStat { get { return breedingStat; } } [Storable] private List> relinkingStat; public IEnumerable> RelinkingStat { get { return relinkingStat; } } [Storable] private List> delinkingStat; public IEnumerable> DelinkingStat { get { return delinkingStat; } } [Storable] private List> samplingStat; public IEnumerable> SamplingStat { get { return samplingStat; } } [Storable] private List> hillclimbingStat; public IEnumerable> HillclimbingStat { get { return hillclimbingStat; } } [Storable] private List> adaptivewalkingStat; public IEnumerable> AdaptivewalkingStat { get { return adaptivewalkingStat; } } public double AverageQuality { get { return Problem.Parameters.ContainsKey("AverageQuality") ? ((IValueParameter)Problem.Parameters["AverageQuality"]).Value.Value : double.NaN; } } public double LowerBound { get { return Problem.Parameters.ContainsKey("LowerBound") ? ((IValueParameter)Problem.Parameters["LowerBound"]).Value.Value : double.NaN; } } [Storable] public ISolutionModel Model { get; set; } [StorableConstructor] protected MemPRPopulationContext(bool deserializing) : base(deserializing) { } protected MemPRPopulationContext(MemPRPopulationContext original, Cloner cloner) : base(original, cloner) { scope = cloner.Clone(original.scope); problem = cloner.Clone(original.problem); initialized = cloner.Clone(original.initialized); iterations = cloner.Clone(original.iterations); evaluatedSolutions = cloner.Clone(original.evaluatedSolutions); bestQuality = cloner.Clone(original.bestQuality); bestSolution = cloner.Clone(original.bestSolution); localSearchEvaluations = cloner.Clone(original.localSearchEvaluations); localOptimaLevel = cloner.Clone(original.localOptimaLevel); byBreeding = cloner.Clone(original.byBreeding); byRelinking = cloner.Clone(original.byRelinking); byDelinking = cloner.Clone(original.byDelinking); bySampling = cloner.Clone(original.bySampling); byHillclimbing = cloner.Clone(original.byHillclimbing); byAdaptivewalking = cloner.Clone(original.byAdaptivewalking); relinkedPaths = cloner.Clone(original.relinkedPaths); localSearchPaths = cloner.Clone(original.localSearchPaths); random = cloner.Clone(original.random); breedingStat = original.breedingStat.Select(x => Tuple.Create(x.Item1, x.Item2, x.Item3, x.Item4)).ToList(); relinkingStat = original.relinkingStat.Select(x => Tuple.Create(x.Item1, x.Item2, x.Item3, x.Item4)).ToList(); delinkingStat = original.delinkingStat.Select(x => Tuple.Create(x.Item1, x.Item2, x.Item3, x.Item4)).ToList(); samplingStat = original.samplingStat.Select(x => Tuple.Create(x.Item1, x.Item2)).ToList(); hillclimbingStat = original.hillclimbingStat.Select(x => Tuple.Create(x.Item1, x.Item2)).ToList(); adaptivewalkingStat = original.adaptivewalkingStat.Select(x => Tuple.Create(x.Item1, x.Item2)).ToList(); Model = cloner.Clone(original.Model); } public MemPRPopulationContext() : this("MemPRContext") { } public MemPRPopulationContext(string name) : base(name) { scope = new Scope("Global"); Parameters.Add(problem = new ValueParameter("Problem")); Parameters.Add(initialized = new ValueParameter("Initialized", new BoolValue(false))); Parameters.Add(iterations = new ValueParameter("Iterations", new IntValue(0))); Parameters.Add(evaluatedSolutions = new ValueParameter("EvaluatedSolutions", new IntValue(0))); Parameters.Add(bestQuality = new ValueParameter("BestQuality", new DoubleValue(double.NaN))); Parameters.Add(bestSolution = new ValueParameter("BestFoundSolution")); Parameters.Add(localSearchEvaluations = new ValueParameter("LocalSearchEvaluations", new IntValue(0))); Parameters.Add(localOptimaLevel = new ValueParameter("LocalOptimaLevel", new DoubleValue(0))); Parameters.Add(byBreeding = new ValueParameter("ByBreeding", new IntValue(0))); Parameters.Add(byRelinking = new ValueParameter("ByRelinking", new IntValue(0))); Parameters.Add(byDelinking = new ValueParameter("ByDelinking", new IntValue(0))); Parameters.Add(bySampling = new ValueParameter("BySampling", new IntValue(0))); Parameters.Add(byHillclimbing = new ValueParameter("ByHillclimbing", new IntValue(0))); Parameters.Add(byAdaptivewalking = new ValueParameter("ByAdaptivewalking", new IntValue(0))); Parameters.Add(relinkedPaths = new ValueParameter>("RelinkedPaths", new DirectedPath())); Parameters.Add(localSearchPaths = new ValueParameter>("LocalSearchPaths", new DirectedPath())); Parameters.Add(random = new ValueParameter("Random", new MersenneTwister())); breedingStat = new List>(); relinkingStat = new List>(); delinkingStat = new List>(); samplingStat = new List>(); hillclimbingStat = new List>(); adaptivewalkingStat = new List>(); } public abstract ISingleObjectiveSolutionScope ToScope(TSolution code, double fitness = double.NaN); public virtual double Evaluate(TSolution solution, CancellationToken token) { var solScope = ToScope(solution); Evaluate(solScope, token); solScope.Solution = null; return solScope.Fitness; } public virtual void Evaluate(ISingleObjectiveSolutionScope solScope, CancellationToken token) { var pdef = Problem as ISingleObjectiveProblemDefinition; if (pdef != null) { var ind = new SingleEncodingIndividual(pdef.Encoding, solScope); solScope.Fitness = pdef.Evaluate(ind, Random); } else { RunOperator(Problem.Evaluator, solScope, token); } } public abstract TSolutionContext CreateSingleSolutionContext(ISingleObjectiveSolutionScope solution); public void IncrementEvaluatedSolutions(int byEvaluations) { if (byEvaluations < 0) throw new ArgumentException("Can only increment and not decrement evaluated solutions."); EvaluatedSolutions += byEvaluations; } #region Breeding Performance public void AddBreedingResult(ISingleObjectiveSolutionScope a, ISingleObjectiveSolutionScope b, double parentDist, ISingleObjectiveSolutionScope child) { if (IsBetter(a, b)) breedingStat.Add(Tuple.Create(a.Fitness, b.Fitness, parentDist, child.Fitness)); else breedingStat.Add(Tuple.Create(b.Fitness, a.Fitness, parentDist, child.Fitness)); } public bool BreedingSuited(ISingleObjectiveSolutionScope p1, ISingleObjectiveSolutionScope p2, double dist) { return true; } #endregion #region Relinking Performance public void AddRelinkingResult(ISingleObjectiveSolutionScope a, ISingleObjectiveSolutionScope b, double parentDist, ISingleObjectiveSolutionScope child) { if (IsBetter(a, b)) relinkingStat.Add(Tuple.Create(a.Fitness, b.Fitness, parentDist, Maximization ? child.Fitness - a.Fitness : a.Fitness - child.Fitness)); else relinkingStat.Add(Tuple.Create(a.Fitness, b.Fitness, parentDist, Maximization ? child.Fitness - b.Fitness : b.Fitness - child.Fitness)); } public bool RelinkSuited(ISingleObjectiveSolutionScope p1, ISingleObjectiveSolutionScope p2, double dist) { return true; } #endregion #region Delinking Performance public void AddDelinkingResult(ISingleObjectiveSolutionScope a, ISingleObjectiveSolutionScope b, double parentDist, ISingleObjectiveSolutionScope child) { if (IsBetter(a, b)) delinkingStat.Add(Tuple.Create(a.Fitness, b.Fitness, parentDist, Maximization ? child.Fitness - a.Fitness : a.Fitness - child.Fitness)); else delinkingStat.Add(Tuple.Create(a.Fitness, b.Fitness, parentDist, Maximization ? child.Fitness - b.Fitness : b.Fitness - child.Fitness)); } public bool DelinkSuited(ISingleObjectiveSolutionScope p1, ISingleObjectiveSolutionScope p2, double dist) { return true; } #endregion #region Sampling Performance public void AddSamplingResult(ISingleObjectiveSolutionScope sample, double avgDist) { samplingStat.Add(Tuple.Create(avgDist, sample.Fitness)); } public bool SamplingSuited(double avgDist) { return true; } #endregion #region Hillclimbing Performance public void AddHillclimbingResult(ISingleObjectiveSolutionScope input, ISingleObjectiveSolutionScope outcome) { hillclimbingStat.Add(Tuple.Create(input.Fitness, Maximization ? outcome.Fitness - input.Fitness : input.Fitness - outcome.Fitness)); } public bool HillclimbingSuited(double startingFitness) { return true; } #endregion #region Adaptivewalking Performance public void AddAdaptivewalkingResult(ISingleObjectiveSolutionScope input, ISingleObjectiveSolutionScope outcome) { adaptivewalkingStat.Add(Tuple.Create(input.Fitness, Maximization ? outcome.Fitness - input.Fitness : input.Fitness - outcome.Fitness)); } public bool AdaptivewalkingSuited(double startingFitness) { return true; } #endregion [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsBetter(ISingleObjectiveSolutionScope a, ISingleObjectiveSolutionScope b) { return IsBetter(a.Fitness, b.Fitness); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsBetter(double a, double b) { return double.IsNaN(b) && !double.IsNaN(a) || Maximization && a > b || !Maximization && a < b; } #region IExecutionContext members public IAtomicOperation CreateOperation(IOperator op) { return new ExecutionContext(this, op, Scope); } public IAtomicOperation CreateOperation(IOperator op, IScope s) { return new ExecutionContext(this, op, s); } public IAtomicOperation CreateChildOperation(IOperator op) { return new ExecutionContext(this, op, Scope); } public IAtomicOperation CreateChildOperation(IOperator op, IScope s) { return new ExecutionContext(this, op, s); } #endregion #region Engine Helper public void RunOperator(IOperator op, IScope scope, CancellationToken cancellationToken) { var stack = new Stack(); stack.Push(CreateChildOperation(op, scope)); while (stack.Count > 0) { cancellationToken.ThrowIfCancellationRequested(); var next = stack.Pop(); if (next is OperationCollection) { var coll = (OperationCollection)next; for (int i = coll.Count - 1; i >= 0; i--) if (coll[i] != null) stack.Push(coll[i]); } else if (next is IAtomicOperation) { var operation = (IAtomicOperation)next; try { next = operation.Operator.Execute((IExecutionContext)operation, cancellationToken); } catch (Exception ex) { stack.Push(operation); if (ex is OperationCanceledException) throw ex; else throw new OperatorExecutionException(operation.Operator, ex); } if (next != null) stack.Push(next); } } } #endregion } [Item("SingleSolutionMemPRContext", "Abstract base class for single solution MemPR contexts.")] [StorableClass] public abstract class MemPRSolutionContext : ParameterizedNamedItem, ISingleSolutionHeuristicAlgorithmContext, IEvaluationServiceContext where TProblem : class, IItem, ISingleObjectiveHeuristicOptimizationProblem where TSolution : class, IItem where TContext : MemPRPopulationContext where TSolutionContext : MemPRSolutionContext { private TContext parent; protected TContext BaseContext { get { return parent;} } public IExecutionContext Parent { get { return parent; } set { throw new InvalidOperationException("Cannot set the parent of a single-solution context."); } } [Storable] private ISingleObjectiveSolutionScope scope; public IScope Scope { get { return scope; } } IKeyedItemCollection IExecutionContext.Parameters { get { return Parameters; } } public TProblem Problem { get { return parent.Problem; } } public bool Maximization { get { return parent.Maximization; } } public double BestQuality { get { return parent.BestQuality; } set { parent.BestQuality = value; } } public TSolution BestSolution { get { return parent.BestSolution; } set { parent.BestSolution = value; } } public IRandom Random { get { return parent.Random; } } [Storable] private IValueParameter evaluatedSolutions; public int EvaluatedSolutions { get { return evaluatedSolutions.Value.Value; } set { evaluatedSolutions.Value.Value = value; } } [Storable] private IValueParameter iterations; public int Iterations { get { return iterations.Value.Value; } set { iterations.Value.Value = value; } } ISingleObjectiveSolutionScope ISingleSolutionHeuristicAlgorithmContext.Solution { get { return scope; } } [StorableConstructor] protected MemPRSolutionContext(bool deserializing) : base(deserializing) { } protected MemPRSolutionContext(MemPRSolutionContext original, Cloner cloner) : base(original, cloner) { scope = cloner.Clone(original.scope); evaluatedSolutions = cloner.Clone(original.evaluatedSolutions); iterations = cloner.Clone(original.iterations); } public MemPRSolutionContext(TContext baseContext, ISingleObjectiveSolutionScope solution) { parent = baseContext; scope = solution; Parameters.Add(evaluatedSolutions = new ValueParameter("EvaluatedSolutions", new IntValue(0))); Parameters.Add(iterations = new ValueParameter("Iterations", new IntValue(0))); } public void IncrementEvaluatedSolutions(int byEvaluations) { if (byEvaluations < 0) throw new ArgumentException("Can only increment and not decrement evaluated solutions."); EvaluatedSolutions += byEvaluations; } public virtual double Evaluate(TSolution solution, CancellationToken token) { return parent.Evaluate(solution, token); } public virtual void Evaluate(ISingleObjectiveSolutionScope solScope, CancellationToken token) { parent.Evaluate(solScope, token); } #region IExecutionContext members public IAtomicOperation CreateOperation(IOperator op) { return new ExecutionContext(this, op, Scope); } public IAtomicOperation CreateOperation(IOperator op, IScope s) { return new ExecutionContext(this, op, s); } public IAtomicOperation CreateChildOperation(IOperator op) { return new ExecutionContext(this, op, Scope); } public IAtomicOperation CreateChildOperation(IOperator op, IScope s) { return new ExecutionContext(this, op, s); } #endregion } }