Пример #1
0
    /// <summary>
    /// Populate empty species with a single genome.
    /// </summary>
    /// <typeparam name="T">Connection weight data type.</typeparam>
    /// <param name="distanceMetric">Distance metric.</param>
    /// <param name="emptySpeciesArr">An array of empty species that are to be populated.</param>
    /// <param name="speciesArr">An array of all species.</param>
    public static void PopulateEmptySpecies <T>(
        IDistanceMetric <T> distanceMetric,
        Species <T>[] emptySpeciesArr,
        Species <T>[] speciesArr)
        where T : struct
    {
        // TODO: Select the required genomes all together, rather than one at a time per empty species.

        // Create a temporary, reusable, working list.
        var tmpPointList = new List <ConnectionGenes <T> >();

        foreach (Species <T> emptySpecies in emptySpeciesArr)
        {
            // Get and remove a genome from a species with many genomes.
            var genome = GetGenomeForEmptySpecies(distanceMetric, speciesArr, tmpPointList);

            // Add the genome to the empty species.
            emptySpecies.GenomeById.Add(genome.Id, genome);

            // Update the centroid. There's only one genome so it is the centroid.
            emptySpecies.Centroid = genome.ConnectionGenes;
        }

        tmpPointList.Clear();
    }
Пример #2
0
 /// <summary>
 /// Creates a new HAC object that uses single-linkage as fusion function and the Jaccard index as distance metric 
 /// to cluster the specified elements.
 /// </summary>
 /// <param name="elements"></param>
 public HacStart(Element[] elements)
 {
     setElements(elements);
     this.fusion = new SingleLinkage();
     this.metric = new JaccardDistance();
     this.fusion.Metric = metric;
 }
Пример #3
0
        /// <summary>
        /// Calculates a centroid by comparing each coordinate with every other
        /// coordinate. The coord with the lowest average distance from all
        /// other coords is the most central coord (the centroid). This method
        /// uses an inefficient N*N comparison of coords to find a centroid. It
        /// is provided only as a last resort for distance metrics for which no
        /// means exist to calculate a centroid more directly.
        /// </summary>
        public static CoordinateVector CalculateCentroid(IDistanceMetric distanceMetric,
                                                         IList <CoordinateVector> coordList)
        {
            // Test special case - one coord therefore it is the centroid..
            if (1 == coordList.Count)
            {
                return(new CoordinateVector(coordList[0].CoordArray));
            }

            // Find coord that is most central.
            // First element as provisional choice.
            double centroidDistance = CalculateMeanDistanceFromCoords(distanceMetric, coordList, 0);
            int    centroidIdx      = 0;
            int    count            = coordList.Count;

            for (int i = 1; i < count; i++)
            {
                double distance = CalculateMeanDistanceFromCoords(distanceMetric, coordList, i);
                if (distance < centroidDistance)
                {   // We have a new centroid candidate.
                    centroidDistance = distance;
                    centroidIdx      = i;
                }
            }

            // We make a copy of the element to avoid any problems
            // (CoordinateVector is intended to used as an immutable type but
            // it isn't actually immutable)
            return(new CoordinateVector(coordList[centroidIdx].CoordArray));
        }
Пример #4
0
        public static void ValidationTests(
            Species <double>[] speciesArr,
            IDistanceMetric <double> distanceMetric,
            int speciesCountExpected,
            List <NeatGenome <double> > fullGenomeList,
            bool validateNearestSpecies)
        {
            // Confirm correct number of species.
            Assert.AreEqual(speciesCountExpected, speciesArr.Length);

            // Confirm no empty species.
            int minSpeciesSize = speciesArr.Select(x => x.GenomeList.Count).Min();

            Assert.IsTrue(minSpeciesSize > 0);

            // Get IDs of all genomes in species.
            var idSet = GetAllGenomeIds(speciesArr);

            // Confirm number of IDs equals number of genomes in main population list.
            Assert.AreEqual(fullGenomeList.Count, idSet.Count);

            // Confirm the genome list IDs match up with the genomes in the species.
            fullGenomeList.ForEach(x => Assert.IsTrue(idSet.Contains(x.Id)));

            // Confirm all species centroids are correct.
            Array.ForEach(speciesArr, x => Assert.AreEqual(0.0, distanceMetric.CalcDistance(x.Centroid, distanceMetric.CalculateCentroid(x.GenomeList.Select(y => y.ConnectionGenes)))));

            if (validateNearestSpecies)
            {
                // Confirm all genomes are in the species with the nearest centroid.
                // Note. If there are two or more species that are equally near then we test that a genome is in one of those.
                Array.ForEach(speciesArr, species => species.GenomeList.ForEach(genome => Assert.IsTrue(GetNearestSpeciesList(genome, speciesArr, distanceMetric).Contains(species))));
            }
        }
Пример #5
0
 /// <summary>
 /// Construct with the provided distance metric and k-means settings.
 /// </summary>
 /// <param name="distanceMetric">Distance metric.</param>
 /// <param name="maxKMeansIters">Maximum number of k-means iterations.</param>
 /// <param name="regularizationConstant">Regularization constant.</param>
 public RegularizedGeneticKMeansSpeciationStrategy(
     IDistanceMetric <T> distanceMetric,
     int maxKMeansIters,
     double regularizationConstant)
     : this(distanceMetric, maxKMeansIters, regularizationConstant, new ParallelOptions())
 {
 }
        /// <summary>
        /// Starts the clustering.
        /// </summary>
        /// <param name="elements"></param>
        /// <param name="fusion"></param>
        /// <param name="metric"></param>
        /// <returns></returns>
        protected internal Cluster[] Cluster(List<Element> elements, Fusion fusion, IDistanceMetric metric)
        {
            HashSet<Cluster> clusters = new HashSet<Cluster>();
            ClusterPairs pairs = new ClusterPairs();

            // 1. Initialize each element as a cluster
            foreach (Element el in elements)
            {
                Cluster cl = new Cluster(fusion);
                cl.AddElement(el);
                clusters.Add(cl);
            }

            // 2. a) Calculate the distances of all clusters to all other clusters
            foreach (Cluster cl1 in clusters)
            {
                foreach (Cluster cl2 in clusters)
                {
                    if (cl1 == cl2)
                        continue;

                    ClusterPair pair = new ClusterPair(cl1, cl2, cl1.CalculateDistance(cl2));

                    pairs.AddPair(pair);
                }
            }

            // 2. b) Initialize the pair with the lowest distance to each other.
            ClusterPair lowestDistancePair = pairs.LowestDistancePair;

            // 3. Merge clusters to new clusters and recalculate distances in a loop until there are only countCluster clusters
            while (!isFinished(clusters, lowestDistancePair))
            {
                // a) Merge: Create a new cluster and add the elements of the two old clusters
                lowestDistancePair = pairs.LowestDistancePair;

                Cluster newCluster = new Cluster(fusion);
                newCluster.AddElements(lowestDistancePair.Cluster1.GetElements());
                newCluster.AddElements(lowestDistancePair.Cluster2.GetElements());

                // b)Remove the two old clusters from clusters
                clusters.Remove(lowestDistancePair.Cluster1);
                clusters.Remove(lowestDistancePair.Cluster2);

                // c) Remove the two old clusters from pairs
                pairs.RemovePairsByOldClusters(lowestDistancePair.Cluster1, lowestDistancePair.Cluster2);

                // d) Calculate the distance of the new cluster to all other clusters and save each as pair
                foreach (Cluster cluster in clusters)
                {
                    ClusterPair pair = new ClusterPair(cluster, newCluster, cluster.CalculateDistance(newCluster));
                    pairs.AddPair(pair);
                }

                // e) Add the new cluster to clusters
                clusters.Add(newCluster);
            }

            return clusters.ToArray<Cluster>();
        }
        /// <summary>
        /// Find medoid by comparing each coordinate with every other coordinate. The coord with the lowest
        /// average distance from all other coords is the most central coord (the medoid).
        /// This method uses an inefficient N*N comparison of coords to find a medoid. It is provided only as a last
        /// resort for distance metrics for which no means exist to calculate a centroid.
        /// </summary>
        /// <param name="distanceMetric">Distance metric.</param>
        /// <param name="pointList">Point list.</param>
        /// <returns>The index of the element in <paramref name="pointList"/> that is the medoid.</returns>
        public static int FindMedoid(
            IDistanceMetric <double> distanceMetric,
            IList <ConnectionGenes <double> > pointList)
        {
            // Special case. One item in list, therefore it is the centroid.
            if (pointList.Count == 1)
            {
                return(0);
            }

            // Find coord that is most central.
            // Handle first coordinate.
            int    medoidIdx      = 0;
            double medoidDistance = CalculateMeanDistanceFromCoords(distanceMetric, pointList, 0);

            // Handle all other coordinates.
            int count = pointList.Count;

            for (int i = 1; i < count; i++)
            {
                double distance = CalculateMeanDistanceFromCoords(distanceMetric, pointList, i);
                if (distance < medoidDistance)
                {
                    // We have a new centroid candidate.
                    medoidDistance = distance;
                    medoidIdx      = i;
                }
            }

            // Return the coord that is the medoid.
            return(medoidIdx);
        }
        /// <summary>
        /// Calculates a centroid by comparing each coordinate with every other coordinate. The coord with the lowest 
        /// average distance from all other coords is the most central coord (the centroid).
        /// This method uses an inefficient N*N comparison of coords to find a centroid. It is provided only as a last
        /// resort for distance metrics for which no means exist to calculate a centroid more directly.
        /// </summary>
        public static CoordinateVector CalculateCentroid(IDistanceMetric distanceMetric, IList<CoordinateVector> coordList)
        {
            // Test special case - one coord therefore it is the centroid..
            if(1 == coordList.Count) {   
                return new CoordinateVector(coordList[0].CoordArray);
            }

            // Find coord that is most central.
            int centroidIdx = 0;
            double centroidDistance = CalculateMeanDistanceFromCoords(distanceMetric, coordList, 0);
            int count = coordList.Count;
            for(int i=1; i<count; i++)
            {
                double distance = CalculateMeanDistanceFromCoords(distanceMetric, coordList, i);
                if(distance < centroidDistance)
                {   // We have a new centroid candidate.
                    centroidDistance = distance;
                    centroidIdx = i;
                }
            }

            // We make a copy of the element to avoid any problems (CoordinateVector is intended to used as
            // an immutable type but it isn't actually immutable)
            return new CoordinateVector(coordList[centroidIdx].CoordArray);
        }
Пример #9
0
        /// <summary>
        /// Gets the species with a centroid closest to the given genome.
        /// If multiple species are equally close then we return all of the those species.
        /// </summary>
        public static List <Species <T> > GetNearestSpeciesList <T>(
            NeatGenome <T> genome,
            Species <T>[] speciesArr,
            IDistanceMetric <T> distanceMetric)
            where T : struct
        {
            var nearestSpeciesList = new List <Species <T> >(4);

            nearestSpeciesList.Add(speciesArr[0]);
            double nearestDistance = distanceMetric.CalcDistance(genome.ConnectionGenes, speciesArr[0].Centroid);

            for (int i = 1; i < speciesArr.Length; i++)
            {
                double distance = distanceMetric.CalcDistance(genome.ConnectionGenes, speciesArr[i].Centroid);
                if (distance < nearestDistance)
                {
                    nearestSpeciesList.Clear();
                    nearestSpeciesList.Add(speciesArr[i]);
                    nearestDistance = distance;
                }
                else if (distance == nearestDistance)
                {
                    nearestSpeciesList.Add(speciesArr[i]);
                }
            }
            return(nearestSpeciesList);
        }
Пример #10
0
 public LeafNode(int index, IEnumerable <int> coords, IDistanceMetric distanceMetric) : base(1, distanceMetric)
 {
     Index      = index;
     Coords     = coords.ToDictionary(coord => coord, _ => 1.0);
     FirstLeaf  = this;
     SecondLeaf = this;
 }
Пример #11
0
 public LeafNode(int index, IEnumerable <float> coords, IDistanceMetric distanceMetric) : base(1, distanceMetric)
 {
     Index      = index;
     Coords     = coords.Select((coord, i) => new { i, coord }).Where(pair => pair.coord > 0).ToDictionary(pair => pair.i, pair => (double)pair.coord);
     FirstLeaf  = this;
     SecondLeaf = this;
 }
Пример #12
0
        private void RunClusteringAndGraph()
        {
            if (chartDataSource != null)
            {
                Cluster cluster;

                distanceMetric = DistanceMetric(currentDistanceMatrix);

                try
                {
                    clusterResult = ClusterCalculate();
                }
                catch (InvalidOperationException)
                {
                    MessageBox.Show("Please try again.");
                    return;
                }


                /* Executing scatterplot */
                foreach (var dataPoint in chartDataSource)
                {
                    cluster = clusterResult.FindCluster(dataPoint.Origin);
                    if (cluster != null)
                    {
                        dataPoint.Group = string.Format("Cluster {0}", cluster.Id);
                    }
                }
                chartDataSource = chartDataSource.OrderBy(item => item.Group).ToList();

                scatterPlotControl1.BuildScatterPlot(chartDataSource);
            }
        }
Пример #13
0
 /// <summary>
 /// Construct with the given distance metric.
 /// </summary>
 /// <param name="distanceMetric">Distance metric.</param>
 /// <param name="parallelOptions">Parallel options.</param>
 public GeneticKMeansSpeciationInit(
     IDistanceMetric <T> distanceMetric,
     ParallelOptions parallelOptions)
 {
     _distanceMetric  = distanceMetric ?? throw new ArgumentNullException(nameof(distanceMetric));
     _parallelOptions = parallelOptions;
 }
Пример #14
0
        public void DistanceMatrixShouldReturnLargerCorrectDistanceMatrix()
        {
            double difference;

            collectionSize = 111;

            distanceMetric          = new EuclideanMetric();
            generatedDataCollection = new GenerateIdentifiableDataPointCollection(collectionSize);
            dataCollection          = generatedDataCollection.Generate();

            distanceMatrix = new DistanceMatrix(dataCollection, distanceMetric);
            expectedMatrix = ExpectedMatrix();

            for (int row = 0; row < distanceMatrix.Rows; row++)
            {
                for (int col = 0; col < distanceMatrix.Columns; col++)
                {
                    difference = distanceMatrix[row, col] - expectedMatrix[row, col];
                    if (!(difference < 0.01 && difference > -0.01 && distanceMatrix[row, col] >= 0))
                    {
                        Assert.Fail("{0}, row = {1}, col = {2}", difference, row, col);
                    }
                }
            }
        }
 public GeneticKMeansSpeciationInit(
     IDistanceMetric <T> distanceMetric,
     IRandomSource rng)
 {
     _distanceMetric = distanceMetric;
     _rng            = rng;
 }
Пример #16
0
 public RobotIndividual(Robot robot, Individual[] parents)
 {
     Robot           = robot;
     Genome          = robot.Genome;
     Parents         = parents;
     _distanceMetric = new EuclideanDistanceMetric();
 }
Пример #17
0
 public PointsDistance(IDistanceMetric gauge)
 {
     if (gauge == null)
     {
         throw new ArgumentNullException(nameof(gauge));
     }
     Gauge = gauge;
 }
 public GeneticKMeansSpeciationInit(
     IDistanceMetric <T> distanceMetric,
     ParallelOptions parallelOptions,
     IRandomSource rng)
 {
     _distanceMetric  = distanceMetric;
     _parallelOptions = parallelOptions;
     _rng             = rng;
 }
 public GeneticKMeansSpeciationStrategy(
     IDistanceMetric <T> distanceMetric,
     int maxKMeansIters,
     IRandomSource rng)
 {
     _distanceMetric = distanceMetric;
     _maxKMeansIters = maxKMeansIters;
     _kmeansInit     = new GeneticKMeansSpeciationInit <T>(distanceMetric, rng);
 }
 /// <summary>
 /// Construct a new instance.
 /// </summary>
 /// <param name="distanceMetric">Distance metric.</param>
 /// <param name="maxKMeansIters">Maximum number of k-means iterations.</param>
 /// <param name="parallelOptions">Parallel execution options.</param>
 public GeneticKMeansSpeciationStrategy(
     IDistanceMetric <T> distanceMetric,
     int maxKMeansIters,
     ParallelOptions parallelOptions)
 {
     _distanceMetric  = distanceMetric;
     _maxKMeansIters  = maxKMeansIters;
     _parallelOptions = parallelOptions;
     _kmeansInit      = new GeneticKMeansSpeciationInit <T>(distanceMetric, parallelOptions);
 }
Пример #21
0
        public DataVisualizationForm(IdentifiableDataPointCollection dataSet)
            : this()
        {
            this.dataSet   = dataSet;
            distanceMetric = DistanceMetric(currentDistanceMatrix);

            dataConversionTask          = new DataConversionTask();
            dataConversionTask.Success += DataConversionTask_Success;
            dataConversionTask.Failure += DataConversionTask_Failure;
        }
 /// <summary>
 /// Construct with the provided distance metric and k-means settings.
 /// </summary>
 /// <param name="distanceMetric">Distance metric.</param>
 /// <param name="maxKMeansIters">Maximum number of k-means iterations.</param>
 /// <param name="regularizationConstant">Regularization constant.</param>
 public RegularizedGeneticKMeansSpeciationStrategy(
     IDistanceMetric <T> distanceMetric,
     int maxKMeansIters,
     double regularizationConstant)
 {
     _distanceMetric         = distanceMetric;
     _maxKMeansIters         = maxKMeansIters;
     _regularizationConstant = regularizationConstant;
     _kmeansInit             = new GeneticKMeansSpeciationInit <T>(distanceMetric);
 }
Пример #23
0
 public DistanceMatrix(IEnumerable <DataPoint> input, IDistanceMetric distanceMetric)
     : base(input.Count(), input.Count())
 {
     if (distanceMetric == null)
     {
         throw new ArgumentNullException("distanceMetric");
     }
     this.distanceMetric = distanceMetric;
     dataPointList       = input.ToList();
     CalculateEntries();
 }
 public RegularizedGeneticKMeansSpeciationStrategy(
     IDistanceMetric <T> distanceMetric,
     int maxKMeansIters,
     double regularizationConstant,
     IRandomSource rng)
 {
     _distanceMetric         = distanceMetric;
     _maxKMeansIters         = maxKMeansIters;
     _regularizationConstant = regularizationConstant;
     _parallelOptions        = new ParallelOptions();
     _kmeansInit             = new GeneticKMeansSpeciationInit <T>(distanceMetric, _parallelOptions, rng);
 }
Пример #25
0
        public NewtonSolver(List <T> ns, IDistanceMetric m)
        {
            metric = m;
            foreach (T n in ns)
            {
                Vector3 p = new Vector3();
                p.x = (float)Eleven.random.NextDouble();
                p.y = (float)Eleven.random.NextDouble();

                n.transform.position = p;
                nodes.Add(new Node(n));
            }
        }
Пример #26
0
        /// <summary>
        /// Starts the task.
        /// </summary>
        /// <param name="dataSet">The list of objects that to be converted.</param>
        /// <param name="distanceMetric">The distance metric used to scale down dimensions.</param>
        public void Start(IdentifiableDataPointCollection dataSet, IDistanceMetric distanceMetric)
        {
            var args = new TaskRunnerArgumentSet {
                Data = dataSet, DistanceMetric = distanceMetric
            };

            var task = Task.Factory.StartNew <DataConversionResult>(TaskRunner, args);

            // Make sure Success and Failure events are run within the caller thread.
            TaskScheduler currentContext = TaskScheduler.FromCurrentSynchronizationContext();

            task.ContinueWith(TaskComplete, currentContext);
            task.ContinueWith(TaskFaulted, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, currentContext);
        }
Пример #27
0
        public static void TestSpeciateAdd(
            int popSize,
            int inputNodeCount,
            int outputNodeCount,
            double connectionsProportion,
            IDistanceMetric <double> distanceMetric,
            ISpeciationStrategy <NeatGenome <double>, double> speciationStrategy,
            IRandomSource rng,
            bool validateNearestSpecies = true)
        {
            // Create population.
            NeatPopulation <double> neatPop = CreateNeatPopulation(popSize, inputNodeCount, outputNodeCount, connectionsProportion);

            // Split the population into three.
            int popSize1 = popSize / 3;
            int popSize2 = popSize / 3;
            int popSize3 = popSize - (popSize1 + popSize2);

            var genomeList1 = neatPop.GenomeList.GetRange(0, popSize1);
            var genomeList2 = neatPop.GenomeList.GetRange(popSize1, popSize2);
            var genomeList3 = neatPop.GenomeList.GetRange(popSize1 + popSize2, popSize3);

            for (int i = 0; i < 6; i++)
            {
                int speciesCount = rng.Next(1, (neatPop.GenomeList.Count / 4) + 1);

                var fullGenomeList = new List <NeatGenome <double> >(genomeList1);

                // Invoke speciation strategy, and run tests
                var speciesArr = speciationStrategy.SpeciateAll(genomeList1, speciesCount, rng);
                ValidationTests(speciesArr, distanceMetric, speciesCount, fullGenomeList, validateNearestSpecies);

                // Add second batch of genomes, and re-run tests.
                speciationStrategy.SpeciateAdd(genomeList2, speciesArr, rng);

                fullGenomeList.AddRange(genomeList2);
                ValidationTests(speciesArr, distanceMetric, speciesCount, fullGenomeList, validateNearestSpecies);

                // Add third batch of genomes, and re-run tests.
                speciationStrategy.SpeciateAdd(genomeList3, speciesArr, rng);

                fullGenomeList.AddRange(genomeList3);
                ValidationTests(speciesArr, distanceMetric, speciesCount, fullGenomeList, validateNearestSpecies);
            }
        }
Пример #28
0
        public KMeans(IdentifiableDataPointCollection dataCollection, int k, IDistanceMetric distanceMetric, int maxIterations = 100)
        {
            if (k < 1)
            {
                throw new ArgumentException("Clusters cannot be generated for less than one centroid");
            }

            this.dataCollection = dataCollection;
            this.maxIterations  = maxIterations;
            this.distanceMetric = distanceMetric;
            this.centroids      = dataCollection
                                  .OrderBy(dataPoint => Guid.NewGuid()) // Random order
                                  .Take(k)
                                  .Select(dataPoint => dataPoint.Clone())
                                  .ToList();

            EnsureDistinctCentroid();
        }
Пример #29
0
        public KMeans(IdentifiableDataPointCollection dataCollection, int[] centroidIndicies, IDistanceMetric distanceMetric, int maxIterations = 100)
        {
            this.dataCollection = dataCollection;
            this.maxIterations  = maxIterations;
            this.distanceMetric = distanceMetric;

            if (centroidIndicies.Length != centroidIndicies.Distinct().Count())
            {
                throw new ArgumentException(
                          "Array contains dublicate indicies, which is not allowed.", "centroidIndicies");
            }

            this.centroids = centroidIndicies
                             .Select(index => this.dataCollection[index].Clone())
                             .ToList();

            EnsureDistinctCentroid();
        }
Пример #30
0
        /// <summary>
        /// Populate empty species with a single genome.
        /// </summary>
        /// <typeparam name="T">Connection weight data type.</typeparam>
        /// <param name="distanceMetric">Distance metric.</param>
        /// <param name="emptySpeciesArr">An array of empty species that are to be populated.</param>
        /// <param name="speciesArr">An array of all species.</param>
        public static void PopulateEmptySpecies <T>(
            IDistanceMetric <T> distanceMetric,
            Species <T>[] emptySpeciesArr,
            Species <T>[] speciesArr)
            where T : struct
        {
            foreach (Species <T> emptySpecies in emptySpeciesArr)
            {
                // Get and remove a genome from a species with many genomes.
                var genome = GetGenomeForEmptySpecies(distanceMetric, speciesArr);

                // Add the genome to the empty species.
                emptySpecies.GenomeById.Add(genome.Id, genome);

                // Update the centroid. There's only one genome so it is the centroid.
                emptySpecies.Centroid = genome.ConnectionGenes;
            }
        }
        /// <summary>
        /// Calculate the mean distance of the specified coord from all of the other coords using
        /// the provided distance metric.
        /// </summary>
        /// <param name="distanceMetric">The distance metric.</param>
        /// <param name="coordList">The list of coordinatres.</param>
        /// <param name="idx">The index of the coordinate to measure distance to.</param>
        private static double CalculateMeanDistanceFromCoords(IDistanceMetric distanceMetric, IList<CoordinateVector> coordList, int idx)
        {
            double totalDistance = 0.0;
            int count = coordList.Count;
            CoordinateVector targetCoord = coordList[idx];

            // Measure distance to all coords before the target one.
            for(int i=0; i<idx; i++) {
                totalDistance += distanceMetric.MeasureDistance(targetCoord, coordList[i]);
            }

            // Measure distance to all coords after the target one.
            for(int i=idx+1; i<count; i++) {
                totalDistance += distanceMetric.MeasureDistance(targetCoord, coordList[i]);
            }

            return totalDistance / (count-1);
        }
Пример #32
0
        public ClusterNode(Node first, Node second, double distance, IDistanceMetric distanceMetric) : base(first.NumChildren + second.NumChildren, distanceMetric)
        {
            Distance = distance;

            // Calculate the pairwise distances between the two sides of each clustered node.
            var distFirstFirst   = first.FirstLeaf.DistanceTo(second.FirstLeaf);
            var distFirstSecond  = second.FirstLeaf == second.SecondLeaf ? distFirstFirst : first.FirstLeaf.DistanceTo(second.SecondLeaf);
            var distSecondFirst  = first.FirstLeaf == first.SecondLeaf ? distFirstFirst : first.SecondLeaf.DistanceTo(second.FirstLeaf);
            var distSecondSecond = second.FirstLeaf == second.SecondLeaf ? distSecondFirst : first.SecondLeaf.DistanceTo(second.SecondLeaf);

            // Order the two nodes so that the minimum distance is between them.
            if (Math.Min(distFirstSecond, distSecondFirst) <= Math.Min(distFirstFirst, distSecondSecond))
            {
                if (distSecondFirst <= distFirstSecond)
                {
                    First  = first;
                    Second = second;
                }
                else
                {
                    First  = second;
                    Second = first;
                }
            }
            else
            {
                if (distSecondSecond <= distFirstFirst)
                {
                    First  = first;
                    Second = second;
                    Second.Reverse();
                }
                else
                {
                    First  = second;
                    Second = first;
                    First.Reverse();
                }
            }
            First.Parent  = this;
            Second.Parent = this;
            FirstLeaf     = First.FirstLeaf;
            SecondLeaf    = Second.SecondLeaf;
        }
Пример #33
0
        /// <summary>
        /// Calculate the mean distance of the specified coord from all of the
        /// other coords using the provided distance metric.
        /// </summary>
        /// <param name="distanceMetric">The distance metric.</param>
        /// <param name="coordList">The list of coordinatres.</param>
        /// <param name="idx">The index of the coordinate to measure distance to.</param>
        private static double CalculateMeanDistanceFromCoords(IDistanceMetric distanceMetric,
                                                              IList <CoordinateVector> coordList, int idx)
        {
            double           totalDistance = 0.0;
            int              count         = coordList.Count;
            CoordinateVector targetCoord   = coordList[idx];

            // Measure distance to all coords before the target one.
            for (int i = 0; i < idx; i++)
            {
                totalDistance += distanceMetric.MeasureDistance(targetCoord, coordList[i]);
            }

            // Measure distance to all coords after the target one.
            for (int i = idx + 1; i < count; i++)
            {
                totalDistance += distanceMetric.MeasureDistance(targetCoord, coordList[i]);
            }
            return(totalDistance / (count - 1));
        }
Пример #34
0
        private static NeatGenome <T> GetGenomeForEmptySpecies <T>(
            IDistanceMetric <T> distanceMetric,
            Species <T>[] speciesArr)
            where T : struct
        {
            // Get the species with the highest number of genomes.
            Species <T> species = speciesArr.Aggregate((x, y) => x.GenomeById.Count > y.GenomeById.Count ?  x : y);

            // Get the genome furthest from the species centroid.
            var genome = species.GenomeById.Values.Aggregate((x, y) => distanceMetric.CalcDistance(species.Centroid, x.ConnectionGenes) > distanceMetric.CalcDistance(species.Centroid, y.ConnectionGenes) ? x : y);

            // Remove the genome from its current species.
            species.GenomeById.Remove(genome.Id);

            // Update the species centroid.
            species.Centroid = distanceMetric.CalculateCentroid(species.GenomeById.Values.Select(x => x.ConnectionGenes));

            // Return the selected genome.
            return(genome);
        }
Пример #35
0
 /// <summary>
 /// Creates a new HAC object to cluster the specified elements with the specified fusion and 
 /// metric function.
 /// </summary>
 /// <param name="elements"></param>
 /// <param name="fusion"></param>
 /// <param name="metric"></param>
 public HacStart(Element[] elements, Fusion fusion, IDistanceMetric metric)
 {
     setElements(elements);
     this.fusion = fusion;
     this.fusion.Metric = metric;
 }