#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
}
}