public function nearest(array $sample, int $k = 1) : array
    {
        if ($k < 1) {
            throw new InvalidArgumentException('The number of nearest'
                . " neighbors must be greater than 0, $k given.");
        }

        $neighborhood = $this->search($sample);

        if (!$neighborhood) {
            return [[], []];
        }

        $distances = $labels = [];

        $visited = new SplObjectStorage();

        $stack = [$neighborhood];

        while ($stack) {
            $current = array_pop($stack);

            if ($visited->contains($current)) {
                continue 1;
            }

            $visited->attach($current);

            $parent = $current->parent();

            if ($parent) {
                $stack[] = $parent;
            }

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

                $labels = array_merge($labels, $current->labels());

                array_multisort($distances, $labels);

                continue 1;
            }

            $target = $distances[$k - 1] ?? INF;

            foreach ($current->children() as $child) {
                if ($visited->contains($child)) {
                    continue 1;
                }

                if ($child instanceof Box) {
                    foreach ($child->sides() as $side) {
                        $distance = $this->kernel->compute($sample, $side);

                        if ($distance < $target) {
                            $stack[] = $child;

                            continue 2;
                        }
                    }
                }

                $visited->attach($child);
            }
        }

        $distances = array_slice($distances, 0, $k);
        $labels = array_slice($labels, 0, $k);

        return [$labels, $distances];
    }
public function nearest(array $sample, int $k = 1) : array
    {
        if ($k < 1) {
            throw new InvalidArgumentException('The number of nearest'
                . " neighbors must be greater than 0, $k given.");
        }

        $neighborhood = $this->search($sample);

        if (!$neighborhood) {
            return [[], []];
        }

        $distances = $labels = [];

        $visited = new SplObjectStorage();

        $stack = [$neighborhood];

        while ($stack) {
            $current = array_pop($stack);

            if ($visited->contains($current)) {
                continue 1;
            }

            $visited->attach($current);

            $parent = $current->parent();

            if ($parent) {
                $stack[] = $parent;
            }

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

                $labels = array_merge($labels, $current->labels());

                array_multisort($distances, $labels);

                continue 1;
            }

            $target = $distances[$k - 1] ?? INF;

            foreach ($current->children() as $child) {
                if ($visited->contains($child)) {
                    continue 1;
                }

                if ($child instanceof Box) {
                    foreach ($child->sides() as $side) {
                        $distance = $this->kernel->compute($sample, $side);

                        if ($distance < $target) {
                            $stack[] = $child;

                            continue 2;
                        }
                    }
                }

                $visited->attach($child);
            }
        }

        $distances = array_slice($distances, 0, $k);
        $labels = array_slice($labels, 0, $k);

        return [$labels, $distances];
    }
public function nearest ( array $ sample , int $ k = 1 ) : array { if ( $ k < 1 ) { throw new InvalidArgumentException ( 'The number of nearest' . " neighbors must be greater than 0, $k given." ) ; } $ neighborhood = $ this -> search ( $ sample ) ; if ( ! $ neighborhood ) { return [ [ ] , [ ] ] ; } $ distances = $ labels = [ ] ; $ visited = new SplObjectStorage ( ) ; $ stack = [ $ neighborhood ] ; while ( $ stack ) { $ current = array_pop ( $ stack ) ; if ( $ visited -> contains ( $ current ) ) { continue 1 ; } $ visited -> attach ( $ current ) ; $ parent = $ current -> parent ( ) ; if ( $ parent ) { $ stack [ ] = $ parent ; } if ( $ current instanceof Neighborhood ) { foreach ( $ current -> samples ( ) as $ neighbor ) { $ distances [ ] = $ this -> kernel -> compute ( $ sample , $ neighbor ) ; } $ labels = array_merge ( $ labels , $ current -> labels ( ) ) ; array_multisort ( $ distances , $ labels ) ; continue 1 ; } $ target = $ distances [ $ k - 1 ] ?? INF ; foreach ( $ current -> children ( ) as $ child ) { if ( $ visited -> contains ( $ child ) ) { continue 1 ; } if ( $ child instanceof Box ) { foreach ( $ child -> sides ( ) as $ side ) { $ distance = $ this -> kernel -> compute ( $ sample , $ side ) ; if ( $ distance < $ target ) { $ stack [ ] = $ child ; continue 2 ; } } } $ visited -> attach ( $ child ) ; } } $ distances = array_slice ( $ distances , 0 , $ k ) ; $ labels = array_slice ( $ labels , 0 , $ k ) ; return [ $ labels , $ distances ] ; }
Run a k nearest neighbors search of every neighborhood and return
the labels and distances in a 2-tuple.

@param array $sample
@param int $k
@throws \InvalidArgumentException
@return array[]
Run a k nearest neighbors search of every neighborhood and return the labels and distances in a 2 - tuple .