1<?php 2 3namespace Rubix\ML\Other\Strategies; 4 5use Rubix\ML\DataType; 6use Rubix\ML\Other\Helpers\Stats; 7use Rubix\ML\Exceptions\InvalidArgumentException; 8use Rubix\ML\Exceptions\RuntimeException; 9 10/** 11 * Percentile 12 * 13 * A strategy that always guesses the p-th percentile of the fitted data. 14 * 15 * @category Machine Learning 16 * @package Rubix/ML 17 * @author Andrew DalPino 18 */ 19class Percentile implements Strategy 20{ 21 /** 22 * The percentile of the fitted data to use as a guess. 23 * 24 * @var float 25 */ 26 protected $p; 27 28 /** 29 * The pth percentile of the fitted data. 30 * 31 * @var float|null 32 */ 33 protected $percentile; 34 35 /** 36 * @param float $p 37 * @throws \Rubix\ML\Exceptions\InvalidArgumentException 38 */ 39 public function __construct(float $p = 50.0) 40 { 41 if ($p < 0.0 or $p > 100.0) { 42 throw new InvalidArgumentException('Percentile must be' 43 . " between 0 and 100, $p given."); 44 } 45 46 $this->p = $p; 47 } 48 49 /** 50 * Return the data type the strategy handles. 51 * 52 * @return \Rubix\ML\DataType 53 */ 54 public function type() : DataType 55 { 56 return DataType::continuous(); 57 } 58 59 /** 60 * Has the strategy been fitted? 61 * 62 * @internal 63 * 64 * @return bool 65 */ 66 public function fitted() : bool 67 { 68 return isset($this->percentile); 69 } 70 71 /** 72 * Fit the guessing strategy to a set of values. 73 * 74 * @internal 75 * 76 * @param list<int|float> $values 77 * @throws \Rubix\ML\Exceptions\InvalidArgumentException 78 */ 79 public function fit(array $values) : void 80 { 81 if (empty($values)) { 82 throw new InvalidArgumentException('Strategy must be fitted' 83 . ' to at least 1 value.'); 84 } 85 86 $q = $this->p / 100.0; 87 88 $this->percentile = Stats::quantile($values, $q); 89 } 90 91 /** 92 * Make a guess. 93 * 94 * @internal 95 * 96 * @throws \Rubix\ML\Exceptions\RuntimeException 97 * @return float 98 */ 99 public function guess() : float 100 { 101 if ($this->percentile === null) { 102 throw new RuntimeException('Strategy has not been fitted.'); 103 } 104 105 return $this->percentile; 106 } 107 108 /** 109 * Return the string representation of the object. 110 * 111 * @return string 112 */ 113 public function __toString() : string 114 { 115 return "Percentile (p: {$this->p})"; 116 } 117} 118