1<?php
2
3namespace Rubix\ML;
4
5use Rubix\ML\Exceptions\InvalidArgumentException;
6use Stringable;
7
8use function in_array;
9
10/**
11 * Estimator Type
12 *
13 * Estimator type enum.
14 *
15 * @internal
16 *
17 * @category    Machine Learning
18 * @package     Rubix/ML
19 * @author      Andrew DalPino
20 */
21class EstimatorType implements Stringable
22{
23    /**
24     * The classifier estimator type code.
25     *
26     * @var int
27     */
28    public const CLASSIFIER = 1;
29
30    /**
31     * The regressor estimator type code.
32     *
33     * @var int
34     */
35    public const REGRESSOR = 2;
36
37    /**
38     * The clusterer estimator type code.
39     *
40     * @var int
41     */
42    public const CLUSTERER = 3;
43
44    /**
45     * The anomaly detector estimator type code.
46     *
47     * @var int
48     */
49    public const ANOMALY_DETECTOR = 4;
50
51    /**
52     * An array of human-readable string representations of the estimator types.
53     *
54     * @var int
55     */
56    protected const TYPE_STRINGS = [
57        self::CLASSIFIER => 'classifier',
58        self::REGRESSOR => 'regressor',
59        self::CLUSTERER => 'clusterer',
60        self::ANOMALY_DETECTOR => 'anomaly detector',
61    ];
62
63    /**
64     * An array of all the estimator type codes.
65     *
66     * @var list<int>
67     */
68    protected const ALL = [
69        self::CLASSIFIER,
70        self::REGRESSOR,
71        self::CLUSTERER,
72        self::ANOMALY_DETECTOR,
73    ];
74
75    /**
76     * The integer-encoded estimator type.
77     *
78     * @var int
79     */
80    protected $code;
81
82    /**
83     * Build a new estimator type object.
84     *
85     * @param int $code
86     */
87    public static function build(int $code) : self
88    {
89        return new self($code);
90    }
91
92    /**
93     * Build a classifier type.
94     *
95     * @return self
96     */
97    public static function classifier() : self
98    {
99        return new self(self::CLASSIFIER);
100    }
101
102    /**
103     * Build a regressor type.
104     *
105     * @return self
106     */
107    public static function regressor() : self
108    {
109        return new self(self::REGRESSOR);
110    }
111
112    /**
113     * Build a clusterer type.
114     *
115     * @return self
116     */
117    public static function clusterer() : self
118    {
119        return new self(self::CLUSTERER);
120    }
121
122    /**
123     * Build an anomaly detector type.
124     *
125     * @return self
126     */
127    public static function anomalyDetector() : self
128    {
129        return new self(self::ANOMALY_DETECTOR);
130    }
131
132    /**
133     * @param int $code
134     * @throws \Rubix\ML\Exceptions\InvalidArgumentException
135     */
136    public function __construct(int $code)
137    {
138        if (!in_array($code, self::ALL)) {
139            throw new InvalidArgumentException('Invalid type code.');
140        }
141
142        $this->code = $code;
143    }
144
145    /**
146     * Return the integer-encoded estimator type.
147     *
148     * @return int
149     */
150    public function code() : int
151    {
152        return $this->code;
153    }
154
155    /**
156     * Is the estimator type supervised?
157     */
158    public function isSupervised() : bool
159    {
160        return $this->isClassifier() or $this->isRegressor();
161    }
162
163    /**
164     * Is it a classifier?
165     *
166     * @return bool
167     */
168    public function isClassifier() : bool
169    {
170        return $this->code === self::CLASSIFIER;
171    }
172
173    /**
174     * Is it a regressor?
175     *
176     * @return bool
177     */
178    public function isRegressor() : bool
179    {
180        return $this->code === self::REGRESSOR;
181    }
182
183    /**
184     * Is it a clusterer?
185     *
186     * @return bool
187     */
188    public function isClusterer() : bool
189    {
190        return $this->code === self::CLUSTERER;
191    }
192
193    /**
194     * Is it an anomaly detector?
195     *
196     * @return bool
197     */
198    public function isAnomalyDetector() : bool
199    {
200        return $this->code === self::ANOMALY_DETECTOR;
201    }
202
203    /**
204     * Return the estimator type as a string.
205     *
206     * @return string
207     */
208    public function __toString() : string
209    {
210        return self::TYPE_STRINGS[$this->code];
211    }
212}
213