public static double PearsonCoefficient(GenericVector a, GenericVector b)
        {
            if (a.Dimensions != b.Dimensions)
            {
                throw new Exception("Distance can't be computed of vectors with different dimensions");
            }

            var n             = a.Dimensions;
            var sigmaA        = 0.0;
            var sigmaB        = 0.0;
            var sigmaATimesB  = 0.0;
            var sigmaASquared = 0.0;
            var sigmaBSquared = 0.0;

            for (var i = 0; i < a.Dimensions; i++)
            {
                if (float.IsNaN(a[i]) || float.IsNaN(b[i]))
                {
                    n--;
                    continue;
                }

                sigmaA        += a[i];
                sigmaB        += b[i];
                sigmaATimesB  += a[i] * b[i];
                sigmaASquared += Math.Pow(a[i], 2);
                sigmaBSquared += Math.Pow(b[i], 2);
            }

            return((sigmaATimesB - (sigmaA * sigmaB) / n) /
                   (Math.Sqrt(sigmaASquared - Math.Pow(sigmaA, 2) / n) *
                    Math.Sqrt(sigmaBSquared - Math.Pow(sigmaB, 2) / n)));
        }
        public static double CosineSimilarity(GenericVector a, GenericVector b)
        {
            if (a.Dimensions != b.Dimensions)
            {
                throw new Exception("Distance can't be computed of vectors with different dimensions");
            }

            var sigmaATimesB = 0.0;
            var lengthA      = 0.0;
            var lengthB      = 0.0;

            for (var i = 0; i < a.Dimensions; i++)
            {
                var A = a[i];
                var B = b[i];

                if (float.IsNaN(A))
                {
                    A = 0;
                }
                if (float.IsNaN(B))
                {
                    B = 0;
                }

                sigmaATimesB += A * B;
                lengthA      += Math.Pow(A, 2);
                lengthB      += Math.Pow(B, 2);
            }

            return(sigmaATimesB / (Math.Sqrt(lengthA) * Math.Sqrt(lengthB)));
        }
 private static bool HasAdditionalItems(GenericVector potentialNeighbour, GenericVector target)
 {
     for (int i = 0; i < target.Dimensions; i++)
     {
         if (float.IsNaN(target[i]) && !float.IsNaN(potentialNeighbour[i]))
         {
             return(true);
         }
     }
     return(false);
 }
        public static double ManhattanDistanceSimilarity(GenericVector a, GenericVector b)
        {
            if (a.Dimensions != b.Dimensions)
            {
                throw new Exception("Distance can't be computed of vectors with different dimensions");
            }
            var sigmaAb = 0.0;

            for (var i = 0; i < a.Dimensions; i++)
            {
                if (!float.IsNaN(a[i]) && !float.IsNaN(b[i]))
                {
                    sigmaAb += Math.Abs(a[i] - b[i]);
                }
            }
            return(1 / (1 + sigmaAb));
        }
        public static Dictionary <int, double> GetNeighbours(Matrix <float> points, int targetId, int k,
                                                             double treshold, Func <GenericVector, GenericVector, double> similarity)
        {
            var lowest     = treshold;
            var neighbours = new Dictionary <int, double>();
            var target     = new GenericVector(points[targetId]);

            foreach (var point in points)
            {
//                Console.WriteLine($"point: {point.Key} with target {targetId}");
                if (point.Key == targetId)
                {
                    continue;
                }

                var vector = new GenericVector(point.Value);

                var similar = similarity(vector, target);
                if (!(similar > lowest && HasAdditionalItems(vector, target)))
                {
                    continue;
                }

                if (neighbours.Count >= k)
                {
                    var smallest = Min(neighbours);

                    if (similar > smallest.Value)
                    {
                        neighbours.Remove(smallest.Key);
                        neighbours.Add(point.Key, similar);
                    }

                    lowest = Min(neighbours).Value;
                    continue;
                }

                neighbours.Add(point.Key, similar);
            }

            return(neighbours);
        }