[3869] | 1 | using System;
|
---|
| 2 | using System.Collections.Generic;
|
---|
| 3 | using System.Linq;
|
---|
| 4 | using System.Text;
|
---|
| 5 | using HeuristicLab.Data;
|
---|
| 6 | using HeuristicLab.Encodings.RealVectorEncoding;
|
---|
| 7 | using System.Diagnostics;
|
---|
| 8 | using HeuristicLab.Core;
|
---|
| 9 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
| 10 | using HeuristicLab.Parameters;
|
---|
| 11 |
|
---|
| 12 | namespace HeuristicLab.Problems.TestFunctions.Evaluators {
|
---|
| 13 | [Item("MultinormalFunction", "Evaluates a random multinormal function on a given point.")]
|
---|
| 14 | [StorableClass]
|
---|
| 15 | public class MultinormalEvaluator : SingleObjectiveTestFunctionProblemEvaluator {
|
---|
| 16 |
|
---|
| 17 | private ItemList<RealVector> centers {
|
---|
| 18 | get { return (ItemList<RealVector>)Parameters["Centers"].ActualValue; }
|
---|
| 19 | set { Parameters["Centers"].ActualValue = value; }
|
---|
| 20 | }
|
---|
| 21 | private RealVector s_2s {
|
---|
| 22 | get { return (RealVector)Parameters["s^2s"].ActualValue; }
|
---|
| 23 | set { Parameters["s^2s"].ActualValue = value; }
|
---|
[3912] | 24 | }
|
---|
| 25 | private static Random Random = new Random();
|
---|
[3869] | 26 |
|
---|
| 27 | [StorableConstructor]
|
---|
| 28 | public MultinormalEvaluator(bool deserializing) { }
|
---|
[3912] | 29 |
|
---|
| 30 | private Dictionary<int, List<RealVector>> stdCenters;
|
---|
| 31 | public IEnumerable<RealVector> Centers(int nDim) {
|
---|
| 32 | if (stdCenters == null)
|
---|
| 33 | stdCenters = new Dictionary<int, List<RealVector>>();
|
---|
| 34 | if (!stdCenters.ContainsKey(nDim))
|
---|
| 35 | stdCenters[nDim] = GetCenters(nDim).ToList();
|
---|
| 36 | return stdCenters[nDim];
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | private IEnumerable<RealVector> GetCenters(int nDim) {
|
---|
| 40 | RealVector r0 = new RealVector(nDim);
|
---|
| 41 | for (int i = 0; i < r0.Length; i++)
|
---|
| 42 | r0[i] = 5;
|
---|
| 43 | yield return r0;
|
---|
| 44 | for (int i = 1; i < 1 << nDim; i++) {
|
---|
| 45 | RealVector r = new RealVector(nDim);
|
---|
| 46 | for (int j = 0; j < nDim; j++) {
|
---|
| 47 | r[j] = (i >> j) % 2 == 0 ? Random.NextDouble() + 4.5 : Random.NextDouble() + 14.5;
|
---|
| 48 | }
|
---|
| 49 | yield return r;
|
---|
| 50 | }
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | private Dictionary<int, List<double>> stdSigma_2s;
|
---|
| 54 | public IEnumerable<double> Sigma_2s(int nDim) {
|
---|
| 55 | if (stdSigma_2s == null)
|
---|
| 56 | stdSigma_2s = new Dictionary<int, List<double>>();
|
---|
| 57 | if (!stdSigma_2s.ContainsKey(nDim))
|
---|
| 58 | stdSigma_2s[nDim] = GetSigma_2s(nDim).ToList();
|
---|
| 59 | return stdSigma_2s[nDim];
|
---|
| 60 | }
|
---|
| 61 | private IEnumerable<double> GetSigma_2s(int nDim) {
|
---|
| 62 | yield return 0.2;
|
---|
| 63 | for (int i = 1; i < (1 << nDim)-1; i++) {
|
---|
| 64 | yield return Random.NextDouble() * 0.5 + 0.75;
|
---|
| 65 | }
|
---|
| 66 | yield return 2;
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | public MultinormalEvaluator() {
|
---|
[3869] | 70 | Parameters.Add(new ValueParameter<ItemList<RealVector>>("Centers", "Centers of normal distributions"));
|
---|
| 71 | Parameters.Add(new ValueParameter<RealVector>("s^2s", "sigma^2 of normal distributions"));
|
---|
[3912] | 72 | Parameters.Add(new LookupParameter<IRandom>("Random", "Random number generator"));
|
---|
| 73 | centers = new ItemList<RealVector>();
|
---|
| 74 | s_2s = new RealVector();
|
---|
[3869] | 75 | }
|
---|
| 76 |
|
---|
| 77 | private double FastFindOptimum(out RealVector bestSolution) {
|
---|
| 78 | var optima = centers.Select((c, i) => new { f = EvaluateFunction(c), i }).OrderBy(v => v.f).ToList();
|
---|
| 79 | if (optima.Count == 0) {
|
---|
| 80 | bestSolution = new RealVector();
|
---|
| 81 | return 0;
|
---|
| 82 | } else {
|
---|
| 83 | var best = optima.First();
|
---|
| 84 | bestSolution = centers[best.i];
|
---|
| 85 | return best.f;
|
---|
| 86 | }
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | public static double N(RealVector x, RealVector x0, double s_2) {
|
---|
| 90 | Debug.Assert(x.Length == x0.Length);
|
---|
| 91 | double d = 0;
|
---|
| 92 | for (int i = 0; i < x.Length; i++) {
|
---|
| 93 | d += (x[i] - x0[i]) * (x[i] - x0[i]);
|
---|
| 94 | }
|
---|
| 95 | return Math.Exp(-d / (2 * s_2)) / (2 * Math.PI * s_2);
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | public override bool Maximization {
|
---|
| 99 | get { return false; }
|
---|
| 100 | }
|
---|
| 101 |
|
---|
| 102 | public override DoubleMatrix Bounds {
|
---|
[3912] | 103 | get { return new DoubleMatrix(new double[,] { { 0, 20 } }); }
|
---|
[3869] | 104 | }
|
---|
| 105 |
|
---|
| 106 | public override double BestKnownQuality {
|
---|
| 107 | get {
|
---|
[3912] | 108 | if (centers.Count == 0) {
|
---|
| 109 | return - 1 / (2 * Math.PI * 0.2);
|
---|
| 110 | } else {
|
---|
| 111 | RealVector bestSolution;
|
---|
| 112 | return FastFindOptimum(out bestSolution);
|
---|
| 113 | }
|
---|
[3869] | 114 | }
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | public override int MinimumProblemSize { get { return 1; } }
|
---|
| 118 |
|
---|
[3912] | 119 | public override int MaximumProblemSize { get { return 100; } }
|
---|
[3869] | 120 |
|
---|
| 121 | private RealVector Shorten(RealVector x, int dimensions) {
|
---|
[3912] | 122 | return new RealVector(x.Take(dimensions).ToArray());
|
---|
[3869] | 123 | }
|
---|
| 124 |
|
---|
| 125 | public override RealVector GetBestKnownSolution(int dimension) {
|
---|
[3912] | 126 | if (centers.Count == 0) {
|
---|
| 127 | RealVector r = new RealVector(dimension);
|
---|
| 128 | for (int i = 0; i < r.Length; i++)
|
---|
| 129 | r[i] = 5;
|
---|
| 130 | return r;
|
---|
| 131 | } else {
|
---|
| 132 | RealVector bestSolution;
|
---|
| 133 | FastFindOptimum(out bestSolution);
|
---|
| 134 | return Shorten(bestSolution, dimension);
|
---|
| 135 | }
|
---|
[3869] | 136 | }
|
---|
| 137 |
|
---|
| 138 | public double Evaluate(RealVector point) {
|
---|
| 139 | return EvaluateFunction(point);
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | protected override double EvaluateFunction(RealVector point) {
|
---|
| 143 | double value = 0;
|
---|
[3912] | 144 | if (centers.Count == 0) {
|
---|
| 145 | var c = Centers(point.Length).GetEnumerator();
|
---|
| 146 | var s = Sigma_2s(point.Length).GetEnumerator();
|
---|
| 147 | while (c.MoveNext() && s.MoveNext()) {
|
---|
| 148 | value -= N(point, c.Current, s.Current);
|
---|
| 149 | }
|
---|
| 150 | } else {
|
---|
| 151 | for (int i = 0; i < centers.Count; i++) {
|
---|
| 152 | value -= N(point, centers[i], s_2s[i]);
|
---|
| 153 | }
|
---|
[3869] | 154 | }
|
---|
| 155 | return value;
|
---|
| 156 | }
|
---|
| 157 | }
|
---|
| 158 | }
|
---|