Find the K nearest neighbors to the given sample vector using
the brute force method.

@param array $sample
@return array[]
424986
protected function nearest(array $sample) : array
    {
        $distances = [];

        foreach ($this->samples as $neighbor) {
            $distances[] = $this->kernel->compute($sample, $neighbor);
        }

        asort($distances);

        $distances = array_slice($distances, 0, $this->k, true);

        $labels = array_intersect_key($this->labels, $distances);

        return [$labels, $distances];
    }
1135920
public function batch(int $n = 50) : array
    {
        $batches = [];

        $samples = $this->samples;

        foreach (array_chunk($this->samples, $n) as $batch) {
            $batches[] = self::quick($batch);
        }

        return $batches;
    }
679731
protected function resample(): array
    {
        $weights = $this->weights;
        $std = StandardDeviation::population($weights);
        $mean = Mean::arithmetic($weights);
        $min = min($weights);
        $minZ = (int) round(($min - $mean) / $std);

        $samples = [];
        $targets = [];
        foreach ($weights as $index => $weight) {
            $z = (int) round(($weight - $mean) / $std) - $minZ + 1;
            for ($i = 0; $i < $z; ++$i) {
                if (random_int(0, 1) == 0) {
                    continue;
                }

                $samples[] = $this->samples[$index];
                $targets[] = $this->targets[$index];
            }
        }

        return [$samples, $targets];
    }
202903
public static function expandExamples($examples)
    {
        $result = [];
        $m = null;

        $len = \strlen(', …');
        if (\substr($examples, -$len) === ', …') {
            $examples = \substr($examples, 0, \strlen($examples) - $len);
        }

        foreach (\explode(',', \str_replace(' ', '', $examples)) as $range) {
            if (\preg_match('/^\d+$/', $range)) {
                $result[] = (int) $range;
            } elseif (\preg_match('/^(\d+)~(\d+)$/', $range, $m)) {
                $from = (int) $m[1];
                $to = (int) $m[2];
                $delta = $to - $from;
                $step = (int) \max(1, $delta / 100);
                for ($i = $from; $i < $to; $i += $step) {
                    $result[] = $i;
                }
                $result[] = $to;
            } else {
                throw new \InvalidArgumentException("Unhandled test range '$range' in '$examples'");
            }
        }

        if (empty($result)) {
            throw new \InvalidArgumentException("No test numbers from '$examples'");
        }

        return $result;
    }
968295
public function fold(int $k = 10) : array
    {
        if ($k < 2) {
            throw new InvalidArgumentException('Cannot create less than'
                . " 2 folds, $k given.");
        }

        $n = (int) floor($this->numRows() / $k);

        $folds = [];

        for ($i = 0; $i < $k; $i++) {
            $offset = $i * $n;

            $samples = array_slice($this->samples, $offset, $n);
            $labels = array_slice($this->labels, $offset, $n);

            $folds[] = self::quick($samples, $labels);
        }

        return $folds;
    }
1000026
public double[] sample(int numSamples, Random rand)
    {
        double[] samples = new double[numSamples];
        for(int i = 0; i < samples.length; i++)
            samples[i] = invCdf(rand.nextDouble());
        
        return samples;
    }
369150
public function proba(Dataset $dataset) : array
    {
        if (!$this->network or !$this->classes) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $xT = Matrix::quick($dataset->samples())->transpose();

        $y = $this->network->infer($xT)->row(0);

        [$classA, $classB] = $this->classes;

        $probabilities = [];

        foreach ($y as $activation) {
            $probabilities[] = [
                $classA => 1. - $activation,
                $classB => $activation,
            ];
        }

        return $probabilities;
    }
834811
protected function membership(array $sample) : array
    {
        $membership = $distances = [];

        foreach ($this->centroids as $centroid) {
            $distances[] = $this->kernel->compute($sample, $centroid);
        }

        $total = array_sum($distances) ?: EPSILON;

        foreach ($distances as $distance) {
            $membership[] = $distance / $total;
        }

        return $membership;
    }
590575
private function candidates(array $samples) : array
    {
        $candidates = [];

        foreach ($samples as $p) {
            foreach ($samples as $q) {
                if (count(array_merge(array_diff($p, $q), array_diff($q, $p))) != 2) {
                    continue;
                }

                $candidate = array_unique(array_merge($p, $q));

                if ($this->contains($candidates, $candidate)) {
                    continue;
                }

                foreach ((array) $this->samples as $sample) {
                    if ($this->subset($sample, $candidate)) {
                        $candidates[] = $candidate;
                        continue 2;
                    }
                }
            }
        }

        return $candidates;
    }
73140
protected function output(array $sample)
    {
        $sum = 0;
        foreach ($this->weights as $index => $w) {
            if ($index == 0) {
                $sum += $w;
            } else {
                $sum += $w * $sample[$index - 1];
            }
        }

        return $sum;
    }
933648
int[][] findNeighborIndices() {

		// looking at a typical protein case, number of neighbours are from ~10 to ~50, with an average of ~30
		int initialCapacity = 60;

		int[][] nbsIndices = new int[atomCoords.length][];

		for (int k=0; k<atomCoords.length; k++) {
			double radius = radii[k] + probe + probe;

			List<Integer> thisNbIndices = new ArrayList<>(initialCapacity);

			for (int i = 0; i < atomCoords.length; i++) {
				if (i == k) continue;

				double dist = atomCoords[i].distance(atomCoords[k]);

				if (dist < radius + radii[i]) {
					thisNbIndices.add(i);
				}
			}

			int[] indicesArray = new int[thisNbIndices.size()];
			for (int i=0;i<thisNbIndices.size();i++) indicesArray[i] = thisNbIndices.get(i);
			nbsIndices[k] = indicesArray;
		}
		return nbsIndices;
	}
714566
public function transform(array &$samples) : void
    {
        foreach ($samples as &$sample) {
            $norm = array_sum(array_map('abs', $sample)) ?: EPSILON;

            foreach ($sample as &$feature) {
                $feature /= $norm;
            }
        }
    }
895442
public static function fromDataset(array $data, int $i, int $k, bool $sample = true, float $meanX = null, float $meanY = null)
    {
        if (empty($data)) {
            throw InvalidArgumentException::arrayCantBeEmpty();
        }

        $n = count($data);
        if ($sample && $n === 1) {
            throw InvalidArgumentException::arraySizeToSmall(2);
        }

        if ($i < 0 || $k < 0 || $i >= $n || $k >= $n) {
            throw new \Exception("Given indices i and k do not match with the dimensionality of data");
        }

        if ($meanX === null || $meanY === null) {
            $x = array_column($data, $i);
            $y = array_column($data, $k);

            $meanX = Mean::arithmetic($x);
            $meanY = Mean::arithmetic($y);
            $sum = 0.0;
            foreach ($x as $index => $xi) {
                $yi = $y[$index];
                $sum += ($xi - $meanX) * ($yi - $meanY);
            }
        } else {
            // In the case, whole dataset given along with dimension indices, i and k,
            // we would like to avoid getting column data with array_column and operate
            // over this extra copy of column data for memory efficiency purposes.
            //
            // Instead we traverse through the whole data and get what we actually need
            // without copying the data. This way, memory use will be reduced
            // with a slight cost of CPU utilization.
            $sum = 0.0;
            foreach ($data as $row) {
                $val = [];
                foreach ($row as $index => $col) {
                    if ($index == $i) {
                        $val[0] = $col - $meanX;
                    }
                    if ($index == $k) {
                        $val[1] = $col - $meanY;
                    }
                }
                $sum += $val[0] * $val[1];
            }
        }

        if ($sample) {
            --$n;
        }

        return $sum / $n;
    }
549409
public static function population(array $a, $sample = true)
    {
        if (empty($a)) {
            throw InvalidArgumentException::arrayCantBeEmpty();
        }

        $n = count($a);

        if ($sample && $n === 1) {
            throw InvalidArgumentException::arraySizeToSmall(2);
        }

        $mean = Mean::arithmetic($a);
        $carry = 0.0;
        foreach ($a as $val) {
            $d = $val - $mean;
            $carry += $d * $d;
        }

        if ($sample) {
            --$n;
        }

        return sqrt((float) ($carry / $n));
    }
918530
public static function variance($values, $sample = true)
    {
        $numberOfValues = count($values);
        $mean = self::mean($values);

        $squaredDifferences = [];
        foreach ($values as $value) {
            $squaredDifferences[] = self::squaredDifference($value, $mean);
        }
        $sumOfSquaredDifferences = self::sum($squaredDifferences);

        if ($sample) {
            $variance = $sumOfSquaredDifferences / ($numberOfValues - 1);
        } else {
            $variance = $sumOfSquaredDifferences / $numberOfValues;
        }

        return $variance;
    }
159735
public function predict(Dataset $dataset) : array
    {
        if ($this->tree->bare()) {
            throw new RuntimeException('Estimator has not been trainied.');
        }

        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $predictions = [];

        foreach ($dataset as $sample) {
            [$samples, $labels, $distances] = $this->tree->range($sample, $this->radius);

            if (empty($labels)) {
                $predictions[] = self::OUTLIER;

                continue 1;
            }
            
            if ($this->weighted) {
                $weights = [];

                foreach ($distances as $distance) {
                    $weights[] = 1. / (1. + $distance);
                }

                $predictions[] = Stats::weightedMean($labels, $weights);
            } else {
                $predictions[] = Stats::mean($labels);
            }
        }

        return $predictions;
    }
647504
public function search(array $sample) : ?Neighborhood
    {
        $current = $this->root;

        while ($current) {
            if ($current instanceof Coordinate) {
                if ($sample[$current->column()] < $current->value()) {
                    $current = $current->left();
                } else {
                    $current = $current->right();
                }

                continue 1;
            }

            if ($current instanceof Neighborhood) {
                return $current;
            }
        }

        return null;
    }