private void _BuildDissimilarityMatrixParallel()
        {
            _dissimilarityMatrix = new DissimilarityMatrix();

            Parallel.ForEach(_ClusterPairCollection(), clusterPair =>
            {
                double distanceBetweenTwoClusters = 0;
                if (clusterPair.Cluster1.QuantityOfPatterns() == 1 && clusterPair.Cluster2.QuantityOfPatterns() == 1)
                {
                    distanceBetweenTwoClusters = _distanceFunction(
                        clusterPair.Cluster1.GetPattern(0).GetAttributes(),
                        clusterPair.Cluster2.GetPattern(0).GetAttributes());
                }

                _dissimilarityMatrix.AddClusterPairAndDistance(clusterPair, distanceBetweenTwoClusters);
            });
        }
        private double ComputeDistance(Cluster cluster1, Cluster cluster2, DissimilarityMatrix dissimilarityMatrix, ClusterDistanceStrategy strategy)
        {
            var distance1 = dissimilarityMatrix.ReturnClusterPairDistance(new ClusterPair(cluster1, cluster2.GetSubCluster(0)));
            var distance2 = dissimilarityMatrix.ReturnClusterPairDistance(new ClusterPair(cluster1, cluster2.GetSubCluster(1)));

            switch (strategy)
            {
            case ClusterDistanceStrategy.SingleLinkage: return(distance1 < distance2 ? distance1 : distance2);

            case ClusterDistanceStrategy.CompleteLinkage: return(distance1 > distance2 ? distance1 : distance2);

            case ClusterDistanceStrategy.AverageWeightedPairGroupMethodArithmeticMean: return((distance1 + distance2) / 2);

            case ClusterDistanceStrategy.AverageUnweightedPairGroupMethodArithmeticMean:
                return(((cluster2.GetSubCluster(0).TotalQuantityOfPatterns *distance1) / cluster2.TotalQuantityOfPatterns) +
                       ((cluster2.GetSubCluster(1).TotalQuantityOfPatterns *distance2) / cluster2.TotalQuantityOfPatterns));

            default: return(0);
            }
        }