Performs normalization on the given RDF dataset.

@param stdClass $dataset the RDF dataset to normalize.
@param assoc $options the normalization options.

@return mixed the normalized output.
760249
protected function _normalize($dataset, $options) {
    // create quads and map bnodes to their associated quads
    $quads = array();
    $bnodes = new stdClass();
    foreach($dataset as $graph_name => $triples) {
      if($graph_name === '@default') {
        $graph_name = null;
      }
      foreach($triples as $triple) {
        $quad = $triple;
        if($graph_name !== null) {
          if(strpos($graph_name, '_:') === 0) {
            $quad->name = (object)array(
              'type' => 'blank node', 'value' => $graph_name);
          } else {
            $quad->name = (object)array(
              'type' => 'IRI', 'value' => $graph_name);
          }
        }
        $quads[] = $quad;

        foreach(array('subject', 'object', 'name') as $attr) {
          if(property_exists($quad, $attr) &&
            $quad->{$attr}->type === 'blank node') {
            $id = $quad->{$attr}->value;
            if(property_exists($bnodes, $id)) {
              $bnodes->{$id}->quads[] = $quad;
            } else {
              $bnodes->{$id} = (object)array('quads' => array($quad));
            }
          }
        }
      }
    }

    // mapping complete, start canonical naming
    $namer = new UniqueNamer('_:c14n');

    // continue to hash bnode quads while bnodes are assigned names
    $unnamed = null;
    $nextUnnamed = array_keys((array)$bnodes);
    $duplicates = null;
    do {
      $unnamed = $nextUnnamed;
      $nextUnnamed = array();
      $duplicates = new stdClass();
      $unique = new stdClass();
      foreach($unnamed as $bnode) {
        // hash quads for each unnamed bnode
        $hash = $this->_hashQuads($bnode, $bnodes, $namer);

        // store hash as unique or a duplicate
        if(property_exists($duplicates, $hash)) {
          $duplicates->{$hash}[] = $bnode;
          $nextUnnamed[] = $bnode;
        } else if(property_exists($unique, $hash)) {
          $duplicates->{$hash} = array($unique->{$hash}, $bnode);
          $nextUnnamed[] = $unique->{$hash};
          $nextUnnamed[] = $bnode;
          unset($unique->{$hash});
        } else {
          $unique->{$hash} = $bnode;
        }
      }

      // name unique bnodes in sorted hash order
      $hashes = array_keys((array)$unique);
      sort($hashes);
      foreach($hashes as $hash) {
        $namer->getName($unique->{$hash});
      }
    }
    while(count($unnamed) > count($nextUnnamed));

    // enumerate duplicate hash groups in sorted order
    $hashes = array_keys((array)$duplicates);
    sort($hashes);
    foreach($hashes as $hash) {
      // process group
      $group = $duplicates->{$hash};
      $results = array();
      foreach($group as $bnode) {
        // skip already-named bnodes
        if($namer->isNamed($bnode)) {
          continue;
        }

        // hash bnode paths
        $path_namer = new UniqueNamer('_:b');
        $path_namer->getName($bnode);
        $results[] = $this->_hashPaths($bnode, $bnodes, $namer, $path_namer);
      }

      // name bnodes in hash order
      usort($results, function($a, $b) {
        $a = $a->hash;
        $b = $b->hash;
        return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
      });
      foreach($results as $result) {
        // name all bnodes in path namer in key-entry order
        foreach($result->pathNamer->order as $bnode) {
          $namer->getName($bnode);
        }
      }
    }

    // create normalized array
    $normalized = array();

    /* Note: At this point all bnodes in the set of RDF quads have been
     assigned canonical names, which have been stored in the 'namer' object.
     Here each quad is updated by assigning each of its bnodes its new name
     via the 'namer' object. */

    // update bnode names in each quad and serialize
    foreach($quads as $quad) {
      foreach(array('subject', 'object', 'name') as $attr) {
        if(property_exists($quad, $attr) &&
          $quad->{$attr}->type === 'blank node' &&
          strpos($quad->{$attr}->value, '_:c14n') !== 0) {
          $quad->{$attr}->value = $namer->getName($quad->{$attr}->value);
        }
      }
      $normalized[] = $this->toNQuad($quad, property_exists($quad, 'name') ?
        $quad->name->value : null);
    }

    // sort normalized output
    sort($normalized);

    // handle output format
    if(isset($options['format']) && $options['format']) {
      if($options['format'] === 'application/nquads') {
        return implode($normalized);
      }
      throw new JsonLdException(
        'Unknown output format.',
        'jsonld.UnknownFormat', null, array('format' => $options['format']));
    }

    // return RDF dataset
    return $this->parseNQuads(implode($normalized));
  }
719504
public static function terminate(Labeled $dataset) : self
    {
        $samples = $dataset->samples();
        $labels = $dataset->labels();

        $min = $max = [];

        foreach ($dataset->columns() as $values) {
            $min[] = min($values);
            $max[] = max($values);
        }

        return new self($samples, $labels, $min, $max);
    }
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;
        }
    }
898529
public function train(Dataset $dataset) : void
    {
        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This estimator requires a'
                . ' labeled training set.');
        }
        
        $k = (int) round($this->ratio * $dataset->numRows());

        $this->forest = [];

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

            $coroutines = [];

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

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

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

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

            $this->forest = yield all($coroutines);
            
            return yield $pool->shutdown();
        });

        $this->classes = $dataset->possibleOutcomes();
        $this->featureCount = $dataset->numColumns();
    }
133725
public function getNormalizedMacParams(Dataset $dataset, $service)
    {
        $params = $this->getParamMacOrderDefinition();
        if (!isset($params[$service])) {
            throw new Exception("Cannot normalize MAC params, unknown service: $service");
        }
        $currentOrder = $params[$service];

        $normalizedMacParams = array();
        // reorder mac params
        foreach ($currentOrder as $param) {
            if ($dataset->offsetExists($param)) {
                $normalizedMacParams[$param] = $dataset->getParam($param);
            }
        }

        return $normalizedMacParams;
    }
952709
public function proba(Dataset $dataset) : array
    {
        if (empty($this->samples) or empty($this->labels)) {
            throw new RuntimeException('The learner has not'
                . ' been trained.');
        }

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

        $template = array_fill_keys($this->classes, 0.);

        $probabilities = [];

        foreach ($dataset as $sample) {
            [$labels, $distances] = $this->nearest($sample);

            if ($this->weighted) {
                $weights = array_fill_keys($labels, 0.);

                foreach ($labels as $i => $label) {
                    $weights[$label] += 1. / (1. + $distances[$i]);
                }
            } else {
                $weights = array_count_values($labels);
            }

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

            $dist = $template;

            foreach ($weights as $class => $weight) {
                $dist[$class] = $weight / $total;
            }

            $probabilities[] = $dist;
        }

        return $probabilities;
    }
1365923
public function addCommonParams(Dataset $dataset)
    {
        $dataset
            ->setParam('VK_SERVICE', $this->getConfParam('VK_SERVICE', '1011'))
            ->setParam('VK_VERSION', '008')
            ->setParam('VK_SND_ID', $this->getConfParam('VK_SND_ID'))
            ->setParam('VK_ACC', $this->getConfParam('VK_ACC'))
            ->setParam('VK_NAME', $this->getConfParam('VK_NAME'))
            ->setParam('VK_RETURN', $this->getReturnUrl())
            ->setParam('VK_CANCEL', $this->getCancelUrl())
            ->setParam('VK_ENCODING', $this->getConfParam('VK_ENCODING', 'UTF-8'))
            ->setParam('VK_DATETIME', date(DATE_ISO8601))
        ;
    }
1078749
protected function split(Labeled $dataset) : Decision
    {
        $bestVariance = INF;
        $bestColumn = $bestValue = null;
        $bestGroups = [];

        shuffle($this->columns);

        foreach (array_slice($this->columns, 0, $this->maxFeatures) as $column) {
            $values = array_unique($dataset->column($column));

            foreach ($values as $value) {
                $groups = $dataset->partition($column, $value);

                $variance = $this->splitImpurity($groups);

                if ($variance < $bestVariance) {
                    $bestColumn = $column;
                    $bestValue = $value;
                    $bestGroups = $groups;
                    $bestVariance = $variance;
                }

                if ($variance <= $this->tolerance) {
                    break 2;
                }
            }
        }

        return new Decision($bestColumn, $bestValue, $bestGroups, $bestVariance);
    }
1366403
public function partial(Dataset $dataset) : void
    {
        if (empty($this->weights) or empty($this->means) or empty($this->variances)) {
            $this->train($dataset);

            return;
        }

        if (!$dataset instanceof Labeled) {
            throw new InvalidArgumentException('This Estimator requires a'
                . ' Labeled training set.');
        }

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

        foreach ($dataset->stratify() as $class => $stratum) {
            $means = $this->means[$class];
            $variances = $this->variances[$class];

            $oldWeight = $this->weights[$class];
            $oldMeans = $this->means[$class];
            $oldVariances = $this->variances[$class];

            $n = $stratum->numRows();

            foreach ($stratum->columns() as $column => $values) {
                [$mean, $variance] = Stats::meanVar($values);

                $means[$column] = (($n * $mean)
                    + ($oldWeight * $oldMeans[$column]))
                    / ($oldWeight + $n);

                $vHat = ($oldWeight
                    * $oldVariances[$column] + ($n * $variance)
                    + ($oldWeight / ($n * ($oldWeight + $n)))
                    * ($n * $oldMeans[$column] - $n * $mean) ** 2)
                    / ($oldWeight + $n);

                $variances[$column] = $vHat ?: EPSILON;
            }

            $this->means[$class] = $means;
            $this->variances[$class] = $variances;
            
            $this->weights[$class] += $n;
        }

        if ($this->fitPriors) {
            $total = array_sum($this->weights) ?: EPSILON;

            foreach ($this->weights as $class => $weight) {
                $this->priors[$class] = log($weight / $total);
            }
        }
    }
623429
protected function processBrowserData(DataSet $dataSet)
    {
        // Get properties and filter them
        $pattern = $dataSet->getPattern();
        $propertiesOriginal = $dataSet->getProperties();
        $properties = $propertiesOriginal;
        $propertyFilter = $this->getPropertyFilter();
        foreach ($properties as $propertyName => $propertyValue) {
            if ($propertyFilter->isFiltered($propertyName)) {
                unset($properties[$propertyName]);
            }
        }
        $browserId = $this->getNextId('browser');

        // Check for placeholders
        $hasBrowscapPlaceholders = (strpos($pattern, '*') !== false || strpos($pattern, '?') !== false);

        // Parent patterns do not contain browscap placeholders, so we only need to save some of them for referencing.
        // (Use unmodified pattern here to find them later.)
        if ($hasBrowscapPlaceholders === false) {
            $this->addParentPattern($pattern, $browserId);
        }

        // Get parent id
        $parentId = $this->getParentPatternId($propertiesOriginal);

        // Get property ids (and generate new entries for new properties)
        $propertyIds = $this->getIdsForProperties($properties);

        // Filter the keywords from the pattern (all strings containing of the characters a-z,
        // with at least 4 characters) and count them to check for the most important keywords
        // later.
        $this->extractKeywordsFromPattern($pattern);

        // Save browser entry
        $this->statements['browser']->execute(['id' => $browserId, 'parent' => $parentId, 'pattern' => $pattern]);

        // Removed 'optimization': Previously patterns without a browscap placeholder like '*' were
        // ignored, assuming that these are only used as parents, but there are about 20 'real'
        // patterns without palceholders.
        //
        // We use the GLOB function in Sqlite, but this is case-sensitive. So we lower-case the pattern here
        // (and later, when searching for it).
        $this->statements['search']->execute([
            'id' => $browserId,
            'length' => strlen(str_replace('*', '', $pattern)),
            'pattern' => strtolower($pattern)]
        );

        // Save all properties for the current pattern
        foreach ($propertyIds as $keyId => $valueId) {
            $this->statements['property']->execute(['id' => $browserId, 'key' => $keyId, 'value' => $valueId]);
        }
    }
923334
public function fit(Dataset $dataset) : void
    {
        $columns = $dataset->columnsByType(DataType::CATEGORICAL);

        $this->vocabulary = [];

        foreach ($columns as $column => $values) {
            $tfs = $dfs = [];

            foreach ($values as $text) {
                $tokens = $this->tokenizer->tokenize($text);

                $counts = array_count_values($tokens);

                foreach ($counts as $token => $count) {
                    if (isset($tfs[$token])) {
                        $tfs[$token] += $count;
                        $dfs[$token] += 1;
                    } else {
                        $tfs[$token] = $count;
                        $dfs[$token] = 1;
                    }
                }
            }

            if ($this->minDocumentFrequency > 1) {
                foreach ($dfs as $token => $frequency) {
                    if ($frequency < $this->minDocumentFrequency) {
                        unset($tfs[$token]);
                    }
                }
            }

            if (count($tfs) > $this->maxVocabulary) {
                arsort($tfs);
    
                $tfs = array_slice($tfs, 0, $this->maxVocabulary, true);
            }
    
            $this->vocabulary[$column] = array_combine(
                array_keys($tfs),
                range(0, count($tfs) - 1)
            ) ?: [];
        }
    }
940252
private function buildMedian(Dataset $dataset): self
    {
        $this->median = new Quartile(median(...$dataset->ordinates()));

        return $this;
    }
867679
public function proba(Dataset $dataset) : array
    {
        $base = $this->base();

        if ($base instanceof Probabilistic) {
            $this->preprocess($dataset);
            
            return $base->proba($dataset);
        }

        throw new RuntimeException('Base estimator must'
            . ' implement the probabilistic interface.');
    }
471127
public function train(Dataset $dataset) : void
    {
        $this->fit($dataset);

        if ($this->estimator instanceof Learner) {
            $this->estimator->train($dataset);
        }

        $this->fitted = true;
    }
1248273
private function buildMax(Dataset $dataset): self
    {
        $this->max = new Quartile(max(...$dataset->ordinates()));

        return $this;
    }
949010
protected function normalizeAmount(DataSetInterface $dataSet): DataSetInterface
    {
        $isVariable = $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_IS_VARIABLE];
        $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_IS_VARIABLE] = $isVariable;

        $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_DEFAULT_AMOUNT] = (int)$dataSet[ProductPackagingUnitDataSetInterface::COLUMN_DEFAULT_AMOUNT];
        $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MIN] = (int)$dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MIN];
        $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MAX] = (int)$dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MAX];
        $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL] = (int)$dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL];

        if ($isVariable && $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL] === 0) {
            $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL] = 1;
        }

        if ($isVariable && $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MIN] === 0) {
            $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MIN] = $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL];
        }

        if (!$isVariable) {
            $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MIN] = null;
            $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_MAX] = null;
            $dataSet[ProductPackagingUnitDataSetInterface::COLUMN_AMOUNT_INTERVAL] = null;
        }

        return $dataSet;
    }
964517
protected function getIso2Code(DataSetInterface $dataSet)
    {
        if (isset($dataSet[CompanyUnitAddressDataSet::COUNTRY_ISO_2_CODE]) && !empty($dataSet[CompanyUnitAddressDataSet::COUNTRY_ISO_2_CODE])) {
            return $dataSet[CompanyUnitAddressDataSet::COUNTRY_ISO_2_CODE];
        }

        return null;
    }