dimensions(); $k = count($generators); foreach ($generators as $generator) { if ($generator->dimensions() !== $dimensions) { throw new InvalidArgumentException('Agglomerate must contain' . ' Generators that produce samples of the same' . " dimensionality, $dimensions expected but " . " {$generator->dimensions()} given."); } } if (is_array($weights)) { if (count($weights) !== $k) { throw new InvalidArgumentException('The number of weights' . " and Generators must be equal, $k expected but " . count($weights) . ' given.'); } foreach ($weights as $weight) { if ($weight < 0) { throw new InvalidArgumentException('Weights must be' . " positive, $weight given."); } } $total = array_sum($weights); if ($total == 0) { throw new InvalidArgumentException('Total weight must' . ' not be equal to 0.'); } foreach ($weights as &$weight) { $weight /= $total; } } else { $weights = array_fill(0, $k, 1.0 / $k); } $this->generators = $generators; $this->weights = array_combine(array_keys($generators), $weights); $this->dimensions = $dimensions; } /** * Return the normalized weights of each generator in the agglomerate. * * @return (int|float)[] */ public function weights() : array { return $this->weights; } /** * Return the dimensionality of the data this generates. * * @internal * * @return int */ public function dimensions() : int { return $this->dimensions; } /** * Generate n data points. * * @param int $n * @return Labeled */ public function generate(int $n) : Labeled { $samples = $labels = []; foreach ($this->generators as $label => $generator) { $p = (int) round($this->weights[$label] * $n); if ($p < 1) { continue; } $samples[] = $generator->generate($p)->samples(); $labels[] = array_fill(0, $p, $label); } return Labeled::quick( $samples ? array_merge(...$samples) : [], $labels ? array_merge(...$labels) : [] ); } }