Insert a root node into the tree and recursively split the training data
until a terminating condition is met.

@param \Rubix\ML\Datasets\Labeled $dataset
163943
public function grow(Labeled $dataset) : void
    {
        $this->featureCount = $dataset->numColumns();

        $depth = 1;

        $this->root = $this->split($dataset);

        $stack = [[$this->root, $depth]];

        while ($stack) {
            [$current, $depth] = array_pop($stack) ?? [];

            [$left, $right] = $current->groups();

            $current->cleanup();

            $depth++;

            if ($left->empty() or $right->empty()) {
                $node = $this->terminate($left->append($right));
    
                $current->attachLeft($node);
                $current->attachRight($node);

                continue 1;
            }
    
            if ($depth >= $this->maxDepth) {
                $current->attachLeft($this->terminate($left));
                $current->attachRight($this->terminate($right));
                
                continue 1;
            }

            if ($left->numRows() > $this->maxLeafSize) {
                $node = $this->split($left);

                if ($node->purityIncrease() + self::BETA > $this->minPurityIncrease) {
                    $current->attachLeft($node);

                    $stack[] = [$node, $depth];
                } else {
                    $current->attachLeft($this->terminate($left));
                }
            } else {
                $current->attachLeft($this->terminate($left));
            }
    
            if ($right->numRows() > $this->maxLeafSize) {
                $node = $this->split($right);
    
                if ($node->purityIncrease() + self::BETA > $this->minPurityIncrease) {
                    $current->attachRight($node);

                    $stack[] = [$node, $depth];
                } else {
                    $current->attachRight($this->terminate($right));
                }
            } else {
                $current->attachRight($this->terminate($right));
            }
        }
    }
897113
public function execute(DataSetInterface $dataSet)
    {
        $companyUnitAddressLabelToCompanyUnitAddressEntity = SpyCompanyUnitAddressLabelToCompanyUnitAddressQuery::create()
            ->filterByFkCompanyUnitAddress($dataSet[CompanyUnitAddressLabelRelationDataSet::ID_COMPANY_UNIT_ADDRESS])
            ->filterByFkCompanyUnitAddressLabel($dataSet[CompanyUnitAddressLabelRelationDataSet::ID_COMPANY_UNIT_ADDRESS_LABEL])
            ->findOneOrCreate();

        $companyUnitAddressLabelToCompanyUnitAddressEntity->save();
    }
1209964
public function fit(Dataset $dataset) : void
    {
        $this->strategies = [];

        foreach ($dataset->types() as $column => $type) {
            $values = [];

            foreach ($dataset->column($column) as $value) {
                if ($value !== $this->placeholder) {
                    $values[] = $value;
                }
            }

            switch ($type) {
                case DataType::CATEGORICAL:
                    $strategy = clone $this->categorical;
                    break 1;

                case DataType::CONTINUOUS:
                    $strategy = clone $this->continuous;
                    break 1;

                default:
                    throw new InvalidArgumentException('This transformer'
                        . ' only handles categorical and continuous'
                        . ' features, ' . DataType::TYPES[$type]
                        . ' found.');
            }

            $strategy->fit($values);

            $this->strategies[$column] = $strategy;
        }
    }
418536
public function grow(Dataset $dataset) : void
    {
        $depth = 1;

        $this->root = Isolator::split($dataset);

        $stack = [[$this->root, $depth]];

        while ($stack) {
            [$current, $depth] = array_pop($stack) ?? [];

            [$left, $right] = $current->groups();

            $depth++;

            if ($depth >= $this->maxDepth) {
                $current->attachLeft(Cell::terminate($left, $depth));
                $current->attachRight(Cell::terminate($right, $depth));
    
                continue 1;
            }
    
            if ($left->numRows() > $this->maxLeafSize) {
                $node = Isolator::split($left);
    
                $current->attachLeft($node);
    
                $stack[] = [$node, $depth];
            } else {
                $current->attachLeft(Cell::terminate($left, $depth));
            }
    
            if ($right->numRows() > $this->maxLeafSize) {
                $node = Isolator::split($right);
    
                $current->attachRight($node);
    
                $stack[] = [$node, $depth];
            } else {
                $current->attachRight(Cell::terminate($right, $depth));
            }

            $current->cleanup();
        }
    }
27849
public static function split(Dataset $dataset) : self
    {
        $column = rand(0, $dataset->numColumns() - 1);

        $sample = $dataset[rand(0, count($dataset) - 1)];

        $value = $sample[$column];

        $groups = $dataset->partition($column, $value);

        return new self($column, $value, $groups);
    }
741987
public function create($dataset)
    {
        // Event
        $this->triggerEvent(
            'onBefore' . ucfirst(__FUNCTION__),
            [
                'dataset' => &$dataset,
            ]
        );

        if (!($dataset instanceof \Traversable) && !is_array($dataset)) {
            throw new \InvalidArgumentException('DataSet object should be instance of a Traversable');
        }

        $result = $this->doCreate($dataset);

        // Event
        $this->triggerEvent(
            'onAfter' . ucfirst(__FUNCTION__),
            [
                'result' => &$result,
            ]
        );

        return $result;
    }
380019
public function train(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This estimator requires a'
                . ' labeled training set.');
        }

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

        $this->classes = $dataset->possibleOutcomes();

        $mapping = array_flip($this->classes);

        $labels = $dataset->labels();

        $data = [];

        foreach ($dataset as $i => $sample) {
            $data[] = array_merge([$mapping[$labels[$i]]], $sample);
        }

        $this->model = $this->svm->train($data);
    }
626779
public function train(Dataset $dataset) : void
    {
        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        [$m, $n] = $dataset->shape();

        $this->r = Matrix::gaussian($n, $this->estimators);

        if ($n >= self::MIN_SPARSE_DIMENSIONS) {
            $mask = Matrix::rand($n, $this->estimators)
                ->less(sqrt($n) / $n);

            $this->r = $this->r->multiply($mask);
        }

        $z = Matrix::quick($dataset->samples())
            ->matmul($this->r)
            ->transpose();

        foreach ($z as $values) {
            $min = min($values) - EPSILON;
            $max = max($values) + EPSILON;

            $edges = Vector::linspace($min, $max, $this->bins + 1)->asArray();

            $edges[] = INF;

            $counts = array_fill(0, $this->bins + 2, 0);

            $interior = array_slice($edges, 1, $this->bins);

            foreach ($values as $value) {
                foreach ($interior as $k => $edge) {
                    if ($value < $edge) {
                        $counts[$k]++;

                        continue 2;
                    }
                }

                $counts[$this->bins]++;
            }

            $densities = [];

            foreach ($counts as $count) {
                $densities[] = $count > 0
                    ? -log($count / $m)
                    : -LOG_EPSILON;
            }

            $this->histograms[] = [$edges, $counts, $densities];
        }

        $this->n = $m;
    }
354996
public function predict(Dataset $dataset) : array
    {
        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $n = $dataset->numRows();

        $dataset = Labeled::quick($dataset->samples(), range(0, $n - 1));

        $tree = new BallTree($this->maxLeafSize, $this->kernel);

        $tree->grow($dataset);
        
        $cluster = self::START_CLUSTER;

        $predictions = [];

        foreach ($dataset as $i => $sample) {
            if (isset($predictions[$i])) {
                continue 1;
            }

            [$samples, $neighbors, $distances] = $tree->range($sample, $this->radius);

            if (count($neighbors) < $this->minDensity) {
                $predictions[$i] = self::NOISE;

                continue 1;
            }

            $predictions[$i] = $cluster;

            while ($neighbors) {
                $index = array_pop($neighbors);

                if (isset($predictions[$index])) {
                    if ($predictions[$index] === self::NOISE) {
                        $predictions[$index] = $cluster;
                    }

                    continue 1;
                }

                $predictions[$index] = $cluster;

                $neighbor = $dataset[$index];

                [$samples, $seeds, $distances] = $tree->range($neighbor, $this->radius);

                if (count($seeds) >= $this->minDensity) {
                    $neighbors = array_unique(array_merge($neighbors, $seeds));
                }
            }

            $cluster++;
        }

        return $predictions;
    }
664596
public function train(Dataset $dataset) : void
    {
        if ($this->type() === self::CLASSIFIER or $this->type() === self::REGRESSOR) {
            if (!$dataset instanceof Labeled) {
                throw new InvalidArgumentException('This estimator requires a'
                    . ' labeled training set.');
            }
        }

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

        $p = (int) round($this->ratio * $dataset->numRows());

        $this->ensemble = [];

        Loop::run(function () use ($dataset, $p) {
            $pool = new DefaultPool($this->workers);

            $coroutines = [];

            for ($i = 0; $i < $this->estimators; $i++) {
                $estimator = clone $this->base;

                $subset = $dataset->randomSubsetWithReplacement($p);

                $task = new CallableTask(
                    [$this, '_train'],
                    [$estimator, $subset]
                );

                $coroutines[] = call(function () use ($pool, $task) {
                    return yield $pool->enqueue($task);
                });
            }

            $this->ensemble = yield all($coroutines);
            
            return yield $pool->shutdown();
        });
    }
518590
public function prepend(Dataset $dataset) : Dataset
    {
        return self::quick(array_merge($dataset->samples(), $this->samples));
    }
1006364
public static function toNQuads($dataset) {
    $quads = array();
    foreach($dataset as $graph_name => $triples) {
      foreach($triples as $triple) {
        if($graph_name === '@default') {
          $graph_name = null;
        }
        $quads[] = self::toNQuad($triple, $graph_name);
      }
    }
    sort($quads);
    return implode($quads);
  }
914906
public function train(Dataset $dataset) : void
    {
        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $samples = $dataset->samples();

        $dataset = Labeled::quick($samples, array_keys($samples));

        $this->tree->grow($dataset);

        $this->kdistances = $this->lrds = [];

        $indices = $distances = [];

        foreach ($dataset as $sample) {
            [$iHat, $dHat] = $this->tree->nearest($sample, $this->k);

            $distances[] = $dHat;
            $indices[] = $iHat;
            
            $this->kdistances[] = end($dHat);
        }

        foreach ($distances as $i => $row) {
            $this->lrds[] = $this->localReachabilityDensity($indices[$i], $row);
        }

        $lofs = [];

        foreach ($dataset as $sample) {
            $lofs[] = $this->localOutlierFactor($sample);
        }

        $shift = Stats::percentile($lofs, 100. * $this->contamination);
        
        $this->offset = self::THRESHOLD + $shift;
    }
358402
public function update(Dataset $dataset) : void
    {
        if ($this->maxabs === null) {
            $this->fit($dataset);
            
            return;
        }

        foreach ($this->maxabs as $column => $oldMax) {
            $values = $dataset->column($column);

            $max = max(array_map('abs', $values));

            $max = max($oldMax, $max);

            $this->maxabs[$column] = $max ?: EPSILON;
        }
    }
442803
public function predict(Dataset $dataset) : array
    {
        if (empty($this->ensemble) or empty($this->influences)) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }
        
        return array_map('Rubix\ML\argmax', $this->score($dataset));
    }
281042
public function train(Dataset $dataset) : void
    {
        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        $columns = $dataset->columns();

        $this->medians = $this->mads = [];

        foreach ($columns as $column => $values) {
            [$median, $mad] = Stats::medMad($values);

            $this->medians[$column] = $median;
            $this->mads[$column] = $mad;
        }
    }
802855
public function rank(Dataset $dataset) : array
    {
        if ($this->tree->bare()) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }
        
        DatasetIsCompatibleWithEstimator::check($dataset, $this);

        return array_map([self::class, 'localOutlierFactor'], $dataset->samples());
    }