Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2457_ExpertSystem/HeuristicLab.OptimizationExpertSystem.Common/3.3/Recommenders/KNearestNeighborModel.cs @ 16124

Last change on this file since 16124 was 13878, checked in by abeham, 8 years ago

#2457: added standardization of features for recommendation and using log10 of the expected runtime for clustering

File size: 4.2 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 HeuristicLab.Collections;
23using HeuristicLab.Common;
24using HeuristicLab.Optimization;
25using System;
26using System.Collections.Generic;
27using System.Linq;
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 nearestK = features.Select((f, i) => new { ProblemInstanceIndex = i, Feature = f })
58                             .OrderBy(x => x.Feature.Select((f, i) => (f - feature[i]) * (f - feature[i])).Sum());
59     
60      var performances = new Dictionary<IAlgorithm, Performance>();
61
62      var k = 0;
63      foreach (var next in nearestK) {
64        if (k >= K) break;
65        var perfs = performance[problemInstanceMap.GetByFirst(next.ProblemInstanceIndex)];
66        if (perfs.Count == 0) continue;
67       
68        foreach (var p in perfs) {
69          var ert = Math.Pow(10, p.Value);
70          Performance perf;
71          if (!performances.TryGetValue(p.Key, out perf)) {
72            perf = new Performance();
73            performances[p.Key] = perf;
74          }
75          perf.Add(ert);
76        }
77
78        k++;
79      }
80
81      return performances.Select(x => new { Alg = x.Key, Perf = x.Value.ExpectedRuntime() })
82                         .OrderBy(x => x.Perf)
83                         .Select(x => new KeyValuePair<IAlgorithm, double>(x.Alg, x.Perf));
84    }
85
86    private class Performance {
87      private readonly List<double> successful;
88      private int runs;
89      public int Fails { get { return runs - successful.Count; } }
90
91      public Performance() {
92        successful = new List<double>();
93      }
94
95      public void Add(double ert) {
96        if (!double.IsInfinity(ert)) successful.Add(ert);
97        runs++;
98      }
99
100      public double ExpectedRuntime() {
101        if (successful.Count == 0) return int.MaxValue;
102        return successful.Average() / (successful.Count / (double)runs);
103      }
104    }
105  }
106}
Note: See TracBrowser for help on using the repository browser.