fn _initialize_clusters<P: DataPoint>(k: usize, mut datapoints: Vec<P>) -> Vec<Cluster<P>> {
    /// Returns one of the `centers` is closest to `point`.
    fn shortest_center_distance<P: DataPoint>(centers: &[P], point: &P) -> f64 {
        centers.iter()
            // calculate the distances between each center and `point`
            .map(|c| c.dist(point))
            // take the minimum of those distances
            .fold(f64::INFINITY, f64::min)
    }

    /// Selects a point using a weighted distribution based on `shortest_center_distance` squared.
    fn select_point(distribution: &[f64]) -> usize {
        // Generate the selection criterion for each point.
        // We'll generate a random number and select the point whose selection criterion is less
        // than that number, but whose following point's is greater than that number.
        // Like throwing a dart at a number line and seeing what range of values it falls in.
        let distr_sum = distribution.iter().fold(0.0, f64::add);
        let mut selection_criteria = Vec::with_capacity(distribution.len());
        for i in 0..distribution.len() {
            let sum = distribution[0..i].iter().fold(0.0, f64::add);
            selection_criteria.push(distribution[i] + sum);
        }
        let rn: f64 = thread_rng().gen_range(0.0, distr_sum);

        let mut selection = 0;
        for i in 1..(selection_criteria.len() - 1) {
            if rn > selection_criteria[i] {
                selection = i;
            }

            if rn <= selection_criteria[i] {
                break;
            }
        }

        selection
    }

    let mut clusters = Vec::with_capacity(k);
    // First centroid is selected with a uniform distribution
    let first_point = datapoints.remove(thread_rng().gen_range(0, datapoints.len()));
    let mut distribution: Vec<f64> = datapoints.iter()
        .map(|p| first_point.dist(p).powi(2))
        .collect();

    // Keep selecting unique points until we have `k` centroids
    while clusters.len() < k {
        let point = datapoints.remove(select_point(&distribution));
        clusters.push(Cluster::new(&point));
        let centroids = Cluster::centroids(&clusters);
        distribution = datapoints.iter()
            .map(|p| shortest_center_distance(&centroids, p).powi(2))
            .collect()
    }

    clusters
}
/// Initializes the clusters using an initialization algorithm based on [k-means++].
///
/// [k-means++]: https://en.wikipedia.org/wiki/K-means%2B%2B#Improved_initialization_algorithm
Initializes the clusters using an initialization algorithm based on [k-means++].
Initializes the clusters using an initialization algorithm based on [ k - means ++ ] .
fn _initialize_clusters<P: DataPoint>(k: usize, mut datapoints: Vec<P>) -> Vec<Cluster<P>> {
    /// Returns one of the `centers` is closest to `point`.
    fn shortest_center_distance<P: DataPoint>(centers: &[P], point: &P) -> f64 {
        centers.iter()
            // calculate the distances between each center and `point`
            .map(|c| c.dist(point))
            // take the minimum of those distances
            .fold(f64::INFINITY, f64::min)
    }
    /// Selects a point using a weighted distribution based on `shortest_center_distance` squared.
    fn select_point(distribution: &[f64]) -> usize {
        // Generate the selection criterion for each point.
        // We'll generate a random number and select the point whose selection criterion is less
        // than that number, but whose following point's is greater than that number.
        // Like throwing a dart at a number line and seeing what range of values it falls in.
        let distr_sum = distribution.iter().fold(0.0, f64::add);
        let mut selection_criteria = Vec::with_capacity(distribution.len());
        for i in 0..distribution.len() {
            let sum = distribution[0..i].iter().fold(0.0, f64::add);
            selection_criteria.push(distribution[i] + sum);
        }
        let rn: f64 = thread_rng().gen_range(0.0, distr_sum);
        let mut selection = 0;
        for i in 1..(selection_criteria.len() - 1) {
            if rn > selection_criteria[i] {
                selection = i;
            }
            if rn <= selection_criteria[i] {
                break;
            }
        }
        selection
    }
    let mut clusters = Vec::with_capacity(k);
    // First centroid is selected with a uniform distribution
    let first_point = datapoints.remove(thread_rng().gen_range(0, datapoints.len()));
    let mut distribution: Vec<f64> = datapoints.iter()
        .map(|p| first_point.dist(p).powi(2))
        .collect();
    // Keep selecting unique points until we have `k` centroids
    while clusters.len() < k {
        let point = datapoints.remove(select_point(&distribution));
        clusters.push(Cluster::new(&point));
        let centroids = Cluster::centroids(&clusters);
        distribution = datapoints.iter()
            .map(|p| shortest_center_distance(&centroids, p).powi(2))
            .collect()
    }
    clusters
}
fn _initialize_clusters < P : DataPoint > ( k : usize , mut datapoints : Vec < P > ) -> Vec < Cluster < P > > { /// Returns one of the `centers` is closest to `point`. fn shortest_center_distance < P : DataPoint > ( centers : & [ P ] , point : & P ) -> f64 { centers . iter ( ) // calculate the distances between each center and `point` . map ( | c | c . dist ( point ) ) // take the minimum of those distances . fold ( f64 :: INFINITY , f64 :: min ) } /// Selects a point using a weighted distribution based on `shortest_center_distance` squared. fn select_point ( distribution : & [ f64 ] ) -> usize { // Generate the selection criterion for each point. // We'll generate a random number and select the point whose selection criterion is less // than that number, but whose following point's is greater than that number. // Like throwing a dart at a number line and seeing what range of values it falls in. let distr_sum = distribution . iter ( ) . fold ( 0.0 , f64 :: add ) ; let mut selection_criteria = Vec :: with_capacity ( distribution . len ( ) ) ; for i in 0 .. distribution . len ( ) { let sum = distribution [ 0 .. i ] . iter ( ) . fold ( 0.0 , f64 :: add ) ; selection_criteria . push ( distribution [ i ] + sum ) ; } let rn : f64 = thread_rng ( ) . gen_range ( 0.0 , distr_sum ) ; let mut selection = 0 ; for i in 1 .. ( selection_criteria . len ( ) - 1 ) { if rn > selection_criteria [ i ] { selection = i ; } if rn <= selection_criteria [ i ] { break ; } } selection } let mut clusters = Vec :: with_capacity ( k ) ; // First centroid is selected with a uniform distribution let first_point = datapoints . remove ( thread_rng ( ) . gen_range ( 0 , datapoints . len ( ) ) ) ; let mut distribution : Vec < f64 > = datapoints . iter ( ) . map ( | p | first_point . dist ( p ) . powi ( 2 ) ) . collect ( ) ; // Keep selecting unique points until we have `k` centroids while clusters . len ( ) < k { let point = datapoints . remove ( select_point ( & distribution ) ) ; clusters . push ( Cluster :: new ( & point ) ) ; let centroids = Cluster :: centroids ( & clusters ) ; distribution = datapoints . iter ( ) . map ( | p | shortest_center_distance ( & centroids , p ) . powi ( 2 ) ) . collect ( ) } clusters }
Initializes the clusters using an initialization algorithm based on [k-means++].
Initializes the clusters using an initialization algorithm based on [ k - means ++ ] .
k
usize
datapoints
Vec<P>
k
usize
datapoints
Vec<P>