1 | using System;
|
---|
2 | using System.Collections.Generic;
|
---|
3 | using System.Linq;
|
---|
4 | using System.Text;
|
---|
5 | using HeuristicLab.Core;
|
---|
6 | using HeuristicLab.Data;
|
---|
7 | using HeuristicLab.Problems.DataAnalysis.Evaluators;
|
---|
8 | using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
|
---|
9 | using HeuristicLab.Parameters;
|
---|
10 |
|
---|
11 | namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Evaluators {
|
---|
12 | public class OnlineMeanMahalanobisDistanceEvaluator : IMultiVariateOnlineEvaluator {
|
---|
13 | private int n;
|
---|
14 | private double distance;
|
---|
15 | private double[,] covMatrix;
|
---|
16 | public double MeanMahalanobisDistance {
|
---|
17 | get {
|
---|
18 | if (n == 0) throw new InvalidOperationException("no elements");
|
---|
19 | else
|
---|
20 | return Math.Sqrt(distance) / n;
|
---|
21 | }
|
---|
22 | }
|
---|
23 |
|
---|
24 | public double MeanGeneralizedSquaredInterpointDistance {
|
---|
25 | get {
|
---|
26 | if (n == 0) throw new InvalidOperationException("no elements");
|
---|
27 | else
|
---|
28 | return distance / n;
|
---|
29 | }
|
---|
30 | }
|
---|
31 |
|
---|
32 | public OnlineMeanMahalanobisDistanceEvaluator() {
|
---|
33 | Reset();
|
---|
34 | }
|
---|
35 |
|
---|
36 | #region IMultiVariateOnlineEvaluator Members
|
---|
37 | public double Value {
|
---|
38 | get { return MeanMahalanobisDistance; }
|
---|
39 | }
|
---|
40 |
|
---|
41 | public void Add(double[] original, double[] estimated) {
|
---|
42 | if (original.Length != estimated.Length) throw new ArgumentException("Number of elements of original and estimated doesn't match.");
|
---|
43 | if (original.Length != covMatrix.GetLength(0)) throw new ArgumentException("Original and estimated is not compatible with covariance matrix.");
|
---|
44 |
|
---|
45 | double[] diff = new double[original.Length];
|
---|
46 | for (int i = 0; i < diff.Length; i++) {
|
---|
47 | diff[i] = original[i] - estimated[i];
|
---|
48 | }
|
---|
49 | double[] target = new double[original.Length];
|
---|
50 |
|
---|
51 | alglib.ablas.rmatrixmv(covMatrix.GetLength(0), covMatrix.GetLength(1), ref covMatrix, 0, 0, 0, ref diff, 0, ref target, 0);
|
---|
52 |
|
---|
53 | double sum = 0.0;
|
---|
54 | for (int i = 0; i < original.Length; i++) {
|
---|
55 | sum += diff[i] * target[i];
|
---|
56 | }
|
---|
57 | distance += sum;
|
---|
58 | n++;
|
---|
59 | }
|
---|
60 |
|
---|
61 | public void Reset() {
|
---|
62 | n = 0;
|
---|
63 | distance = 0.0;
|
---|
64 | }
|
---|
65 |
|
---|
66 | #endregion
|
---|
67 |
|
---|
68 | public void InitializeCovarianceMatrixFromSamples(params IEnumerable<double>[] samples) {
|
---|
69 | covMatrix = new double[samples.Length, samples.Length];
|
---|
70 | OnlineCovarianceEvaluator covEvaluator = new OnlineCovarianceEvaluator();
|
---|
71 | for (int i = 0; i < samples.Length; i++) {
|
---|
72 | for (int j = i; j < samples.Length; j++) {
|
---|
73 | var xEnumerator = samples[i].GetEnumerator();
|
---|
74 | var yEnumerator = samples[j].GetEnumerator();
|
---|
75 | covEvaluator.Reset();
|
---|
76 | while (xEnumerator.MoveNext() & yEnumerator.MoveNext()) {
|
---|
77 | covEvaluator.Add(xEnumerator.Current, yEnumerator.Current);
|
---|
78 | }
|
---|
79 | if (xEnumerator.MoveNext() | yEnumerator.MoveNext()) {
|
---|
80 | throw new ArgumentException("Number of elements must be the same in all enumerations.");
|
---|
81 | }
|
---|
82 | covMatrix[i, j] = covEvaluator.Covariance;
|
---|
83 | covMatrix[j, i] = covEvaluator.Covariance;
|
---|
84 | }
|
---|
85 | }
|
---|
86 | int info = 0;
|
---|
87 | alglib.matinv.matinvreport report = new alglib.matinv.matinvreport();
|
---|
88 | alglib.matinv.rmatrixinverse(ref covMatrix, covMatrix.GetLength(0), ref info, ref report);
|
---|
89 | if (info != 1) throw new InvalidOperationException("Can't invert covariance matrix.");
|
---|
90 | }
|
---|
91 | }
|
---|
92 | }
|
---|