Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Weighted TSNE/3.4/TSNE/Distances/WeightedEuclideanDistance.cs @ 15487

Last change on this file since 15487 was 15487, checked in by bwerth, 7 years ago

#2850 reenabled backwards compatibility; fixed distances

File size: 4.4 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;
24using System.Collections.Generic;
25using System.Linq;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Parameters;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31
32namespace HeuristicLab.Algorithms.DataAnalysis {
33  [StorableClass]
34  [Item("WeightedEuclideanDistance", "A weighted norm function that uses Euclidean distance √(Σ(w[i]²*(p1[i]-p2[i])²))")]
35  public class WeightedEuclideanDistance : ParameterizedNamedItem, IDistance<IEnumerable<double>> {
36    public const string WeightsParameterName = "Weights";
37    public IValueParameter<DoubleArray> WeigthsParameter {
38      get { return (IValueParameter<DoubleArray>) Parameters[WeightsParameterName]; }
39    }
40
41    public DoubleArray Weights {
42      get { return WeigthsParameter.Value; }
43      set { WeigthsParameter.Value = value; }
44    }
45
46    #region HLConstructors & Cloning
47    [StorableConstructor]
48    protected WeightedEuclideanDistance(bool deserializing) : base(deserializing) { }
49    private void AfterDeserialization() {
50      RegisterParameterEvents();
51    }
52    protected WeightedEuclideanDistance(WeightedEuclideanDistance original, Cloner cloner) : base(original, cloner) {
53      RegisterParameterEvents();
54    }
55    public override IDeepCloneable Clone(Cloner cloner) {
56      return new WeightedEuclideanDistance(this, cloner);
57    }
58    public WeightedEuclideanDistance() {
59      Parameters.Add(new ValueParameter<DoubleArray>(WeightsParameterName, "The weights used to modify the euclidean distance."));
60      RegisterParameterEvents();
61    }
62    #endregion
63
64    public static double GetDistance(IEnumerable<double> point1, IEnumerable<double> point2, IEnumerable<double> weights) {
65      using (IEnumerator<double> p1Enum = point1.GetEnumerator(), p2Enum = point2.GetEnumerator(), weEnum = weights.GetEnumerator()) {
66        var sum = 0.0;
67        while (p1Enum.MoveNext() & p2Enum.MoveNext() & weEnum.MoveNext()) {
68          var d = p1Enum.Current - p2Enum.Current;
69          var w = weEnum.Current;
70          sum += d * d * w * w;
71        }
72        if (weEnum.MoveNext() || p1Enum.MoveNext() || p2Enum.MoveNext()) throw new ArgumentException("Weighted Euclidean distance not defined on vectors of different length");
73        return Math.Sqrt(sum);
74      }
75    }
76
77    public double Get(IEnumerable<double> a, IEnumerable<double> b) {
78      return GetDistance(a, b, Weights);
79    }
80    public IComparer<IEnumerable<double>> GetDistanceComparer(IEnumerable<double> item) {
81      return new DistanceBase<IEnumerable<double>>.DistanceComparer(item, this);
82    }
83    public double Get(object x, object y) {
84      return Get((IEnumerable<double>) x, (IEnumerable<double>) y);
85    }
86    public IComparer GetDistanceComparer(object item) {
87      return new DistanceBase<IEnumerable<double>>.DistanceComparer((IEnumerable<double>) item, this);
88    }
89
90    private void RegisterParameterEvents() {
91      WeigthsParameter.ValueChanged += OnWeightsArrayChanged;
92      WeigthsParameter.Value.ItemChanged += OnWeightChanged;
93    }
94    private void OnWeightChanged(object sender, EventArgs<int> e) {
95      WeigthsParameter.Value.ItemChanged -= OnWeightChanged;
96      Weights[e.Value] = Math.Max(0, Weights[e.Value]);
97      WeigthsParameter.Value.ItemChanged -= OnWeightChanged;
98    }
99    private void OnWeightsArrayChanged(object sender, EventArgs e) {
100      for (int i = 0; i < Weights.Length; i++)
101        Weights[i] = Math.Max(0, Weights[i]);
102      WeigthsParameter.Value.ItemChanged += OnWeightChanged;
103    }
104  }
105}
Note: See TracBrowser for help on using the repository browser.