1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022016 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 


22  using System;


23  using System.Collections.Generic;


24  using System.Linq;


25  using HeuristicLab.Common;


26  using HeuristicLab.Core;


27  using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;


28 


29  namespace HeuristicLab.Algorithms.DataAnalysis {


30 


31  /// <summary>


32  /// The angular distance as defined as a normalized distance measure dependent on the angle between two vectors.


33  /// </summary>


34  [StorableClass]


35  [Item("CosineDistance", "The angular distance as defined as a normalized distance measure dependent on the angle between two vectors.")]


36  public class CosineDistance : DistanceBase<IEnumerable<double>> {


37 


38  #region HLConstructors & Cloning


39  [StorableConstructor]


40  protected CosineDistance(bool deserializing) : base(deserializing) { }


41  protected CosineDistance(CosineDistance original, Cloner cloner)


42  : base(original, cloner) { }


43  public CosineDistance() { }


44  public override IDeepCloneable Clone(Cloner cloner) {


45  return new CosineDistance(this, cloner);


46  }


47  #endregion


48 


49  #region statics


50  public static double GetDistance(IReadOnlyList<double> point1, IReadOnlyList<double> point2) {


51  if (point1.Count != point2.Count) throw new ArgumentException("Cosine distance not defined on vectors of different length");


52  var innerprod = 0.0;


53  var length1 = 0.0;


54  var length2 = 0.0;


55 


56  for (var i = 0; i < point1.Count; i++) {


57  double d1 = point1[i], d2 = point2[i];


58  innerprod += d1 * d2;


59  length1 += d1 * d1;


60  length2 += d2 * d2;


61  }


62  var l = Math.Sqrt(length1 * length2);


63  if (l.IsAlmost(0)) throw new ArgumentException("Cosine distance is not defined on vectors of length 0");


64  return 1  innerprod / l;


65  }


66  #endregion


67  public override double Get(IEnumerable<double> a, IEnumerable<double> b) {


68  return GetDistance(a.ToArray(), b.ToArray());


69  }


70  }


71  }

