source: branches/1614_GeneralizedQAP/HeuristicLab.OptimizationExpertSystem.Common/3.3/Recommenders/KNearestNeighborModel.cs @ 15736

Last change on this file since 15736 was 15736, checked in by abeham, 20 months ago

#1614: updates from last night ...

File size: 4.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Collections;
26using HeuristicLab.Common;
27using HeuristicLab.Optimization;
28
29namespace HeuristicLab.OptimizationExpertSystem.Common {
30  public class KNearestNeighborModel : IRecommendationModel {
31    private readonly int K;
32    private readonly string[] characteristics;
33    private readonly Dictionary<IRun, Dictionary<IAlgorithm, double>> performance;
34    private readonly BidirectionalDictionary<int, IRun> problemInstanceMap; 
35    private readonly double[] medianValues;
36
37    public KNearestNeighborModel(int k, Dictionary<IRun, Dictionary<IAlgorithm, double>> perfData, string[] characteristics) {
38      this.K = k;
39      this.performance = perfData;
40      this.characteristics = characteristics;
41      problemInstanceMap = new BidirectionalDictionary<int, IRun>();
42      var i = 0;
43      foreach (var pi in perfData.Keys) {
44        problemInstanceMap.Add(i++, pi);
45      }
46      this.medianValues = KnowledgeCenter.GetMedianValues(perfData.Keys.OrderBy(problemInstanceMap.GetBySecond).ToArray(), characteristics);
47    }
48
49    public IEnumerable<KeyValuePair<IAlgorithm, double>> GetRanking(IRun problemInstance) {
50      double[] means, sdevs;
51      var features = KnowledgeCenter.GetFeaturesStandardized(performance.Keys.OrderBy(problemInstanceMap.GetBySecond).ToArray(), characteristics, out means, out sdevs, medianValues);
52      var feature = KnowledgeCenter.GetFeatures(new [] { problemInstance }, characteristics, medianValues)[0];
53      for (var f = 0; f < feature.Length; f++) {
54        if (sdevs[f].IsAlmost(0)) feature[f] = 0;
55        else feature[f] = (feature[f] - means[f]) / sdevs[f];
56      }
57      var dist = features.Select((f, i) => Math.Sqrt(f.Select((g, j) => Math.Sqrt((g - feature[j]) * (g - feature[j]))).Sum())).ToList();
58      var nearestK = features.Select((f, i) => new { ProblemInstanceIndex = i, Feature = f })
59                             .OrderBy(x => dist[x.ProblemInstanceIndex]);
60     
61      var performances = new Dictionary<IAlgorithm, Performance>();
62
63      var k = 0;
64      foreach (var next in nearestK) {
65        if (k >= K) break;
66        var perfs = performance[problemInstanceMap.GetByFirst(next.ProblemInstanceIndex)];
67        if (perfs.Count == 0) continue;
68       
69        foreach (var p in perfs) {
70          var ert = Math.Pow(10, p.Value);
71          Performance perf;
72          if (!performances.TryGetValue(p.Key, out perf)) {
73            perf = new Performance();
74            performances[p.Key] = perf;
75          }
76          perf.Add(ert);
77        }
78
79        k++;
80      }
81
82      return performances.Select(x => new { Alg = x.Key, Perf = x.Value.ExpectedRuntime() })
83                         .OrderBy(x => x.Perf)
84                         .Select(x => new KeyValuePair<IAlgorithm, double>(x.Alg, x.Perf));
85    }
86
87    private class Performance {
88      private readonly List<double> successful;
89      private int runs;
90      public int Fails { get { return runs - successful.Count; } }
91
92      public Performance() {
93        successful = new List<double>();
94      }
95
96      public void Add(double ert) {
97        if (!double.IsInfinity(ert)) successful.Add(ert);
98        runs++;
99      }
100
101      public double ExpectedRuntime() {
102        if (successful.Count == 0) return int.MaxValue;
103        return successful.Average() / (successful.Count / (double)runs);
104      }
105    }
106  }
107}
Note: See TracBrowser for help on using the repository browser.