Inline static constructors of exceptions (#250)

This commit is contained in:
Yuji Uchiyama 2018-03-04 00:03:53 +09:00 committed by Arkadiusz Kondas
parent af9ccfe722
commit cbd9f5fde1
36 changed files with 66 additions and 214 deletions

View File

@ -17,7 +17,9 @@ class MLPClassifier extends MultilayerPerceptron implements Classifier
public function getTargetClass($target): int
{
if (!in_array($target, $this->classes, true)) {
throw InvalidArgumentException::invalidTarget($target);
throw new InvalidArgumentException(
sprintf('Target with value "%s" is not part of the accepted classes', $target)
);
}
return array_search($target, $this->classes, true);

View File

@ -63,7 +63,7 @@ class FuzzyCMeans implements Clusterer
public function __construct(int $clustersNumber, float $fuzziness = 2.0, float $epsilon = 1e-2, int $maxIterations = 100)
{
if ($clustersNumber <= 0) {
throw InvalidArgumentException::invalidClustersNumber();
throw new InvalidArgumentException('Invalid clusters number');
}
$this->clustersNumber = $clustersNumber;

View File

@ -26,7 +26,7 @@ class KMeans implements Clusterer
public function __construct(int $clustersNumber, int $initialization = self::INIT_KMEANS_PLUS_PLUS)
{
if ($clustersNumber <= 0) {
throw InvalidArgumentException::invalidClustersNumber();
throw new InvalidArgumentException('Invalid clusters number');
}
$this->clustersNumber = $clustersNumber;

View File

@ -32,7 +32,7 @@ abstract class Split
public function __construct(Dataset $dataset, float $testSize = 0.3, ?int $seed = null)
{
if ($testSize <= 0 || $testSize >= 1) {
throw InvalidArgumentException::percentNotInRange('testSize');
throw new InvalidArgumentException('testsize must be between 0.0 and 1.0');
}
$this->seedGenerator($seed);

View File

@ -24,7 +24,7 @@ class ArrayDataset implements Dataset
public function __construct(array $samples, array $targets)
{
if (count($samples) != count($targets)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$this->samples = $samples;

View File

@ -19,12 +19,12 @@ class CsvDataset extends ArrayDataset
public function __construct(string $filepath, int $features, bool $headingRow = true, string $delimiter = ',', int $maxLineLength = 0)
{
if (!file_exists($filepath)) {
throw FileException::missingFile(basename($filepath));
throw new FileException(sprintf('File "%s" missing.', basename($filepath)));
}
$handle = fopen($filepath, 'rb');
if ($handle === false) {
throw FileException::cantOpenFile(basename($filepath));
throw new FileException(sprintf('File "%s" can\'t be open.', basename($filepath)));
}
if ($headingRow) {

View File

@ -11,7 +11,7 @@ class FilesDataset extends ArrayDataset
public function __construct(string $rootPath)
{
if (!is_dir($rootPath)) {
throw DatasetException::missingFolder($rootPath);
throw new DatasetException(sprintf('Dataset root folder "%s" missing.', $rootPath));
}
$this->scanRootPath($rootPath);

View File

@ -41,12 +41,12 @@ class SvmDataset extends ArrayDataset
private static function openFile(string $filePath)
{
if (!file_exists($filePath)) {
throw FileException::missingFile(basename($filePath));
throw new FileException(sprintf('File "%s" missing.', basename($filePath)));
}
$handle = fopen($filePath, 'rb');
if ($handle === false) {
throw FileException::cantOpenFile(basename($filePath));
throw new FileException(sprintf('File "%s" can\'t be open.', basename($filePath)));
}
return $handle;
@ -87,7 +87,7 @@ class SvmDataset extends ArrayDataset
private static function parseTargetColumn(string $column): float
{
if (!is_numeric($column)) {
throw DatasetException::invalidTarget($column);
throw new DatasetException(sprintf('Invalid target "%s".', $column));
}
return (float) $column;
@ -97,7 +97,7 @@ class SvmDataset extends ArrayDataset
{
$feature = explode(':', $column, 2);
if (count($feature) != 2) {
throw DatasetException::invalidValue($column);
throw new DatasetException(sprintf('Invalid value "%s".', $column));
}
$index = self::parseFeatureIndex($feature[0]);
@ -109,11 +109,11 @@ class SvmDataset extends ArrayDataset
private static function parseFeatureIndex(string $index): int
{
if (!is_numeric($index) || !ctype_digit($index)) {
throw DatasetException::invalidIndex($index);
throw new DatasetException(sprintf('Invalid index "%s".', $index));
}
if ((int) $index < 1) {
throw DatasetException::invalidIndex($index);
throw new DatasetException(sprintf('Invalid index "%s".', $index));
}
return (int) $index - 1;
@ -122,7 +122,7 @@ class SvmDataset extends ArrayDataset
private static function parseFeatureValue(string $value): float
{
if (!is_numeric($value)) {
throw DatasetException::invalidValue($value);
throw new DatasetException(sprintf('Invalid value "%s".', $value));
}
return (float) $value;

View File

@ -8,23 +8,4 @@ use Exception;
class DatasetException extends Exception
{
public static function missingFolder(string $path): self
{
return new self(sprintf('Dataset root folder "%s" missing.', $path));
}
public static function invalidTarget(string $target): self
{
return new self(sprintf('Invalid target "%s".', $target));
}
public static function invalidIndex(string $index): self
{
return new self(sprintf('Invalid index "%s".', $index));
}
public static function invalidValue(string $value): self
{
return new self(sprintf('Invalid value "%s".', $value));
}
}

View File

@ -8,18 +8,4 @@ use Exception;
class FileException extends Exception
{
public static function missingFile(string $filepath): self
{
return new self(sprintf('File "%s" missing.', $filepath));
}
public static function cantOpenFile(string $filepath): self
{
return new self(sprintf('File "%s" can\'t be open.', $filepath));
}
public static function cantSaveFile(string $filepath): self
{
return new self(sprintf('File "%s" can\'t be saved.', $filepath));
}
}

View File

@ -8,96 +8,4 @@ use Exception;
class InvalidArgumentException extends Exception
{
public static function arraySizeNotMatch(): self
{
return new self('Size of given arrays does not match');
}
public static function percentNotInRange($name): self
{
return new self(sprintf('%s must be between 0.0 and 1.0', $name));
}
public static function arrayCantBeEmpty(): self
{
return new self('The array has zero elements');
}
public static function arraySizeTooSmall(int $minimumSize = 2): self
{
return new self(sprintf('The array must have at least %d elements', $minimumSize));
}
public static function matrixDimensionsDidNotMatch(): self
{
return new self('Matrix dimensions did not match');
}
public static function inconsistentMatrixSupplied(): self
{
return new self('Inconsistent matrix supplied');
}
public static function invalidClustersNumber(): self
{
return new self('Invalid clusters number');
}
/**
* @param mixed $target
*/
public static function invalidTarget($target): self
{
return new self(sprintf('Target with value "%s" is not part of the accepted classes', $target));
}
public static function invalidStopWordsLanguage(string $language): self
{
return new self(sprintf('Can\'t find "%s" language for StopWords', $language));
}
public static function invalidLayerNodeClass(): self
{
return new self('Layer node class must implement Node interface');
}
public static function invalidLayersNumber(): self
{
return new self('Provide at least 1 hidden layer');
}
public static function invalidClassesNumber(): self
{
return new self('Provide at least 2 different classes');
}
public static function inconsistentClasses(): self
{
return new self('The provided classes don\'t match the classes provided in the constructor');
}
public static function fileNotFound(string $file): self
{
return new self(sprintf('File "%s" not found', $file));
}
public static function fileNotExecutable(string $file): self
{
return new self(sprintf('File "%s" is not executable', $file));
}
public static function pathNotFound(string $path): self
{
return new self(sprintf('The specified path "%s" does not exist', $path));
}
public static function pathNotWritable(string $path): self
{
return new self(sprintf('The specified path "%s" is not writable', $path));
}
public static function invalidOperator(string $operator): self
{
return new self(sprintf('Invalid operator "%s" provided', $operator));
}
}

View File

@ -8,8 +8,4 @@ use Exception;
class LibsvmCommandException extends Exception
{
public static function failedToRun(string $command, string $reason): self
{
return new self(sprintf('Failed running libsvm command: "%s" with reason: "%s"', $command, $reason));
}
}

View File

@ -8,18 +8,4 @@ use Exception;
class MatrixException extends Exception
{
public static function notSquareMatrix(): self
{
return new self('Matrix is not square matrix');
}
public static function columnOutOfRange(): self
{
return new self('Column out of range');
}
public static function singularMatrix(): self
{
return new self('Matrix is singular');
}
}

View File

@ -8,8 +8,4 @@ use Exception;
class NormalizerException extends Exception
{
public static function unknownNorm(): self
{
return new self('Unknown norm supplied.');
}
}

View File

@ -8,13 +8,4 @@ use Exception;
class SerializeException extends Exception
{
public static function cantUnserialize(string $filepath): self
{
return new self(sprintf('"%s" can not be unserialized.', $filepath));
}
public static function cantSerialize(string $classname): self
{
return new self(sprintf('Class "%s" can not be serialized.', $classname));
}
}

View File

@ -28,7 +28,7 @@ class StopWords
$className = __NAMESPACE__."\\StopWords\\${language}";
if (!class_exists($className)) {
throw InvalidArgumentException::invalidStopWordsLanguage($language);
throw new InvalidArgumentException(sprintf('Can\'t find "%s" language for StopWords', $language));
}
return new $className();

View File

@ -44,7 +44,7 @@ final class SelectKBest implements Transformer
public function fit(array $samples, ?array $targets = null): void
{
if ($targets === null || empty($targets)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
$this->scores = $sorted = $this->scoringFunction->score($samples, $targets);

View File

@ -33,7 +33,7 @@ class Comparison
case '!==':
return $a !== $b;
default:
throw InvalidArgumentException::invalidOperator($operator);
throw new InvalidArgumentException(sprintf('Invalid operator "%s" provided', $operator));
}
}
}

View File

@ -15,7 +15,7 @@ class Chebyshev implements Distance
public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$differences = [];

View File

@ -15,7 +15,7 @@ class Euclidean implements Distance
public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$distance = 0;

View File

@ -15,7 +15,7 @@ class Manhattan implements Distance
public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
return array_sum(array_map(function ($m, $n) {

View File

@ -25,7 +25,7 @@ class Minkowski implements Distance
public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$distance = 0;

View File

@ -81,7 +81,7 @@ class LUDecomposition
public function __construct(Matrix $A)
{
if ($A->getRows() != $A->getColumns()) {
throw MatrixException::notSquareMatrix();
throw new MatrixException('Matrix is not square matrix');
}
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
@ -247,11 +247,11 @@ class LUDecomposition
public function solve(Matrix $B): array
{
if ($B->getRows() != $this->m) {
throw MatrixException::notSquareMatrix();
throw new MatrixException('Matrix is not square matrix');
}
if (!$this->isNonsingular()) {
throw MatrixException::singularMatrix();
throw new MatrixException('Matrix is singular');
}
// Copy right hand side with pivoting

View File

@ -48,7 +48,7 @@ class Matrix
if ($validate) {
for ($i = 0; $i < $this->rows; ++$i) {
if (count($matrix[$i]) !== $this->columns) {
throw InvalidArgumentException::matrixDimensionsDidNotMatch();
throw new InvalidArgumentException('Matrix dimensions did not match');
}
}
}
@ -92,7 +92,7 @@ class Matrix
public function getColumnValues($column): array
{
if ($column >= $this->columns) {
throw MatrixException::columnOutOfRange();
throw new MatrixException('Column out of range');
}
return array_column($this->matrix, $column);
@ -110,7 +110,7 @@ class Matrix
}
if (!$this->isSquare()) {
throw MatrixException::notSquareMatrix();
throw new MatrixException('Matrix is not square matrix');
}
$lu = new LUDecomposition($this);
@ -139,7 +139,7 @@ class Matrix
public function multiply(self $matrix): self
{
if ($this->columns != $matrix->getRows()) {
throw InvalidArgumentException::inconsistentMatrixSupplied();
throw new InvalidArgumentException('Inconsistent matrix supplied');
}
$product = [];
@ -200,7 +200,7 @@ class Matrix
public function inverse(): self
{
if (!$this->isSquare()) {
throw MatrixException::notSquareMatrix();
throw new MatrixException('Matrix is not square matrix');
}
$LU = new LUDecomposition($this);

View File

@ -25,7 +25,7 @@ final class ANOVA
{
$classes = count($samples);
if ($classes < 2) {
throw InvalidArgumentException::arraySizeTooSmall(2);
throw new InvalidArgumentException('The array must have at least 2 elements');
}
$samplesPerClass = array_map(function (array $class): int {

View File

@ -17,7 +17,7 @@ class Correlation
public static function pearson(array $x, array $y): float
{
if (count($x) !== count($y)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$count = count($x);

View File

@ -16,12 +16,12 @@ class Covariance
public static function fromXYArrays(array $x, array $y, bool $sample = true, ?float $meanX = null, ?float $meanY = null): float
{
if (empty($x) || empty($y)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
$n = count($x);
if ($sample && $n === 1) {
throw InvalidArgumentException::arraySizeTooSmall(2);
throw new InvalidArgumentException('The array must have at least 2 elements');
}
if ($meanX === null) {
@ -54,12 +54,12 @@ class Covariance
public static function fromDataset(array $data, int $i, int $k, bool $sample = true, ?float $meanX = null, ?float $meanY = null): float
{
if (empty($data)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
$n = count($data);
if ($sample && $n === 1) {
throw InvalidArgumentException::arraySizeTooSmall(2);
throw new InvalidArgumentException('The array must have at least 2 elements');
}
if ($i < 0 || $k < 0 || $i >= $n || $k >= $n) {

View File

@ -59,7 +59,7 @@ class Mean
private static function checkArrayLength(array $array): void
{
if (empty($array)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
}
}

View File

@ -14,13 +14,13 @@ class StandardDeviation
public static function population(array $numbers, bool $sample = true): float
{
if (empty($numbers)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
$n = count($numbers);
if ($sample && $n === 1) {
throw InvalidArgumentException::arraySizeTooSmall(2);
throw new InvalidArgumentException('The array must have at least 2 elements');
}
$mean = Mean::arithmetic($numbers);
@ -45,7 +45,7 @@ class StandardDeviation
public static function sumOfSquares(array $numbers): float
{
if (empty($numbers)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
$mean = Mean::arithmetic($numbers);

View File

@ -16,7 +16,7 @@ class Accuracy
public static function score(array $actualLabels, array $predictedLabels, bool $normalize = true)
{
if (count($actualLabels) != count($predictedLabels)) {
throw InvalidArgumentException::arraySizeNotMatch();
throw new InvalidArgumentException('Size of given arrays does not match');
}
$score = 0;

View File

@ -12,29 +12,29 @@ class ModelManager
public function saveToFile(Estimator $estimator, string $filepath): void
{
if (!is_writable(dirname($filepath))) {
throw FileException::cantSaveFile(basename($filepath));
throw new FileException(sprintf('File "%s" can\'t be saved.', basename($filepath)));
}
$serialized = serialize($estimator);
if (empty($serialized)) {
throw SerializeException::cantSerialize(gettype($estimator));
throw new SerializeException(sprintf('Class "%s" can not be serialized.', gettype($estimator)));
}
$result = file_put_contents($filepath, $serialized, LOCK_EX);
if ($result === false) {
throw FileException::cantSaveFile(basename($filepath));
throw new FileException(sprintf('File "%s" can\'t be saved.', basename($filepath)));
}
}
public function restoreFromFile(string $filepath): Estimator
{
if (!file_exists($filepath) || !is_readable($filepath)) {
throw FileException::cantOpenFile(basename($filepath));
throw new FileException(sprintf('File "%s" can\'t be open.', basename($filepath)));
}
$object = unserialize(file_get_contents($filepath));
if ($object === false) {
throw SerializeException::cantUnserialize(basename($filepath));
throw new SerializeException(sprintf('"%s" can not be unserialized.', basename($filepath)));
}
return $object;

View File

@ -20,7 +20,7 @@ class Layer
public function __construct(int $nodesNumber = 0, string $nodeClass = Neuron::class, ?ActivationFunction $activationFunction = null)
{
if (!in_array(Node::class, class_implements($nodeClass), true)) {
throw InvalidArgumentException::invalidLayerNodeClass();
throw new InvalidArgumentException('Layer node class must implement Node interface');
}
for ($i = 0; $i < $nodesNumber; ++$i) {

View File

@ -62,11 +62,11 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
public function __construct(int $inputLayerFeatures, array $hiddenLayers, array $classes, int $iterations = 10000, ?ActivationFunction $activationFunction = null, float $learningRate = 1)
{
if (empty($hiddenLayers)) {
throw InvalidArgumentException::invalidLayersNumber();
throw new InvalidArgumentException('Provide at least 1 hidden layer');
}
if (count($classes) < 2) {
throw InvalidArgumentException::invalidClassesNumber();
throw new InvalidArgumentException('Provide at least 2 different classes');
}
$this->classes = array_values($classes);
@ -93,7 +93,9 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
{
if (!empty($classes) && array_values($classes) !== $this->classes) {
// We require the list of classes in the constructor.
throw InvalidArgumentException::inconsistentClasses();
throw new InvalidArgumentException(
'The provided classes don\'t match the classes provided in the constructor'
);
}
for ($i = 0; $i < $this->iterations; ++$i) {

View File

@ -42,7 +42,7 @@ class Normalizer implements Preprocessor
public function __construct(int $norm = self::NORM_L2)
{
if (!in_array($norm, [self::NORM_L1, self::NORM_L2, self::NORM_STD], true)) {
throw NormalizerException::unknownNorm();
throw new NormalizerException('Unknown norm supplied.');
}
$this->norm = $norm;

View File

@ -27,7 +27,7 @@ class DataTransformer
public static function testSet(array $samples): string
{
if (empty($samples)) {
throw InvalidArgumentException::arrayCantBeEmpty();
throw new InvalidArgumentException('The array has zero elements');
}
if (!is_array($samples[0])) {

View File

@ -137,7 +137,7 @@ class SupportVectorMachine
public function setVarPath(string $varPath): void
{
if (!is_writable($varPath)) {
throw InvalidArgumentException::pathNotWritable($varPath);
throw new InvalidArgumentException(sprintf('The specified path "%s" is not writable', $varPath));
}
$this->ensureDirectorySeparator($varPath);
@ -160,7 +160,9 @@ class SupportVectorMachine
unlink($trainingSetFileName);
if ($return !== 0) {
throw LibsvmCommandException::failedToRun($command, array_pop($output));
throw new LibsvmCommandException(
sprintf('Failed running libsvm command: "%s" with reason: "%s"', $command, array_pop($output))
);
}
$this->model = file_get_contents($modelFileName);
@ -244,7 +246,9 @@ class SupportVectorMachine
unlink($outputFileName);
if ($return !== 0) {
throw LibsvmCommandException::failedToRun($command, array_pop($output));
throw new LibsvmCommandException(
sprintf('Failed running libsvm command: "%s" with reason: "%s"', $command, array_pop($output))
);
}
return $predictions;
@ -312,18 +316,18 @@ class SupportVectorMachine
private function verifyBinPath(string $path): void
{
if (!is_dir($path)) {
throw InvalidArgumentException::pathNotFound($path);
throw new InvalidArgumentException(sprintf('The specified path "%s" does not exist', $path));
}
$osExtension = $this->getOSExtension();
foreach (['svm-predict', 'svm-scale', 'svm-train'] as $filename) {
$filePath = $path.$filename.$osExtension;
if (!file_exists($filePath)) {
throw InvalidArgumentException::fileNotFound($filePath);
throw new InvalidArgumentException(sprintf('File "%s" not found', $filePath));
}
if (!is_executable($filePath)) {
throw InvalidArgumentException::fileNotExecutable($filePath);
throw new InvalidArgumentException(sprintf('File "%s" is not executable', $filePath));
}
}
}