diff --git a/.gitignore b/.gitignore
index bed47c4..38ef5a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,4 @@
/vendor/
humbuglog.*
-/bin/phpunit
-.coverage
.php_cs.cache
-/bin/php-cs-fixer
-/bin/coveralls
/build
diff --git a/.travis.yml b/.travis.yml
index 80bd5d8..8f8a68b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ matrix:
include:
- os: linux
php: '7.1'
- env: DISABLE_XDEBUG="true"
+ env: DISABLE_XDEBUG="true" STATIC_ANALYSIS="true"
- os: linux
php: '7.2'
@@ -21,7 +21,7 @@ matrix:
before_install:
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then /usr/bin/env bash bin/prepare_osx_env.sh ; fi
- - if [[ DISABLE_XDEBUG == "true" ]]; then phpenv config-rm xdebug.ini; fi
+ - if [[ $DISABLE_XDEBUG == "true" ]]; then phpenv config-rm xdebug.ini; fi
install:
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then /usr/bin/env bash bin/handle_brew_pkg.sh "${_PHP}" ; fi
@@ -29,10 +29,12 @@ install:
- php composer.phar install --dev --no-interaction --ignore-platform-reqs
script:
- - bin/phpunit $PHPUNIT_FLAGS
+ - vendor/bin/phpunit $PHPUNIT_FLAGS
+ - if [[ $STATIC_ANALYSIS != "" ]]; then vendor/bin/ecs check src tests; fi
after_success:
- |
if [[ $PHPUNIT_FLAGS != "" ]]; then
- php bin/coveralls -v
+ wget https://github.com/satooshi/php-coveralls/releases/download/v1.0.1/coveralls.phar;
+ php coveralls.phar --verbose;
fi
diff --git a/composer.json b/composer.json
index 58e79a6..0563f3f 100644
--- a/composer.json
+++ b/composer.json
@@ -12,8 +12,8 @@
}
],
"autoload": {
- "psr-0": {
- "Phpml": "src/"
+ "psr-4": {
+ "Phpml\\": "src/Phpml"
}
},
"require": {
@@ -22,9 +22,8 @@
"require-dev": {
"phpunit/phpunit": "^6.0",
"friendsofphp/php-cs-fixer": "^2.4",
- "php-coveralls/php-coveralls": "^1.0"
- },
- "config": {
- "bin-dir": "bin"
+ "symplify/easy-coding-standard": "dev-master as 2.5",
+ "symplify/coding-standard": "dev-master as 2.5",
+ "symplify/package-builder": "dev-master#3604bea as 2.5"
}
}
diff --git a/composer.lock b/composer.lock
index 1384e6e..e10b2d8 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,9 +4,71 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "c4d5b319f041c2d65249c7852a7f2fc1",
+ "content-hash": "0b709f785c1e62498755f557e49e1ba4",
"packages": [],
"packages-dev": [
+ {
+ "name": "composer/semver",
+ "version": "1.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
+ "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.5 || ^5.0.5",
+ "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "time": "2016-08-30T16:08:34+00:00"
+ },
{
"name": "doctrine/annotations",
"version": "v1.5.0",
@@ -77,32 +139,32 @@
},
{
"name": "doctrine/instantiator",
- "version": "1.0.5",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/instantiator.git",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+ "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
- "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
+ "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda",
"shasum": ""
},
"require": {
- "php": ">=5.3,<8.0-DEV"
+ "php": "^7.1"
},
"require-dev": {
"athletic/athletic": "~0.1.8",
"ext-pdo": "*",
"ext-phar": "*",
- "phpunit/phpunit": "~4.0",
- "squizlabs/php_codesniffer": "~2.0"
+ "phpunit/phpunit": "^6.2.3",
+ "squizlabs/php_codesniffer": "^3.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0.x-dev"
+ "dev-master": "1.2.x-dev"
}
},
"autoload": {
@@ -127,7 +189,7 @@
"constructor",
"instantiate"
],
- "time": "2015-06-14T21:17:01+00:00"
+ "time": "2017-07-22T11:58:36+00:00"
},
{
"name": "doctrine/lexer",
@@ -185,44 +247,46 @@
},
{
"name": "friendsofphp/php-cs-fixer",
- "version": "v2.4.0",
+ "version": "v2.8.1",
"source": {
"type": "git",
"url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
- "reference": "63661f3add3609e90e4ab8115113e189ae547bb4"
+ "reference": "04f71e56e03ba2627e345e8c949c80dcef0e683e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/63661f3add3609e90e4ab8115113e189ae547bb4",
- "reference": "63661f3add3609e90e4ab8115113e189ae547bb4",
+ "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/04f71e56e03ba2627e345e8c949c80dcef0e683e",
+ "reference": "04f71e56e03ba2627e345e8c949c80dcef0e683e",
"shasum": ""
},
"require": {
+ "composer/semver": "^1.4",
"doctrine/annotations": "^1.2",
"ext-json": "*",
"ext-tokenizer": "*",
- "gecko-packages/gecko-php-unit": "^2.0",
- "php": "^5.6 || >=7.0 <7.2",
- "sebastian/diff": "^1.4",
- "symfony/console": "^3.0",
- "symfony/event-dispatcher": "^3.0",
- "symfony/filesystem": "^3.0",
- "symfony/finder": "^3.0",
- "symfony/options-resolver": "^3.0",
+ "gecko-packages/gecko-php-unit": "^2.0 || ^3.0",
+ "php": "^5.6 || >=7.0 <7.3",
+ "php-cs-fixer/diff": "^1.2",
+ "symfony/console": "^3.2 || ^4.0",
+ "symfony/event-dispatcher": "^3.0 || ^4.0",
+ "symfony/filesystem": "^3.0 || ^4.0",
+ "symfony/finder": "^3.0 || ^4.0",
+ "symfony/options-resolver": "^3.0 || ^4.0",
"symfony/polyfill-php70": "^1.0",
"symfony/polyfill-php72": "^1.4",
- "symfony/process": "^3.0",
- "symfony/stopwatch": "^3.0"
+ "symfony/process": "^3.0 || ^4.0",
+ "symfony/stopwatch": "^3.0 || ^4.0"
},
"conflict": {
"hhvm": "*"
},
"require-dev": {
- "johnkary/phpunit-speedtrap": "^1.1",
+ "johnkary/phpunit-speedtrap": "^1.1 || ^2.0@dev",
"justinrainbow/json-schema": "^5.0",
- "phpunit/phpunit": "^4.8.35 || ^5.4.3",
- "satooshi/php-coveralls": "^1.0",
- "symfony/phpunit-bridge": "^3.2.2"
+ "php-coveralls/php-coveralls": "^1.0.2",
+ "php-cs-fixer/accessible-object": "^1.0",
+ "phpunit/phpunit": "^5.7.23 || ^6.4.3",
+ "symfony/phpunit-bridge": "^3.2.2 || ^4.0"
},
"suggest": {
"ext-mbstring": "For handling non-UTF8 characters in cache signature.",
@@ -232,11 +296,6 @@
"php-cs-fixer"
],
"type": "application",
- "extra": {
- "branch-alias": {
- "dev-master": "2.4-dev"
- }
- },
"autoload": {
"psr-4": {
"PhpCsFixer\\": "src/"
@@ -264,173 +323,93 @@
}
],
"description": "A tool to automatically fix PHP code style",
- "time": "2017-07-18T15:35:40+00:00"
+ "time": "2017-11-09T13:31:39+00:00"
},
{
"name": "gecko-packages/gecko-php-unit",
- "version": "v2.1",
+ "version": "v3.0",
"source": {
"type": "git",
"url": "https://github.com/GeckoPackages/GeckoPHPUnit.git",
- "reference": "5b9e9622c7efd3b22655270b80c03f9e52878a6e"
+ "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/5b9e9622c7efd3b22655270b80c03f9e52878a6e",
- "reference": "5b9e9622c7efd3b22655270b80c03f9e52878a6e",
+ "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/6a866551dffc2154c1b091bae3a7877d39c25ca3",
+ "reference": "6a866551dffc2154c1b091bae3a7877d39c25ca3",
"shasum": ""
},
"require": {
- "php": "^5.3.6 || ^7.0"
+ "php": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.4.3"
+ "phpunit/phpunit": "^6.0"
+ },
+ "suggest": {
+ "ext-dom": "When testing with xml.",
+ "ext-libxml": "When testing with xml.",
+ "phpunit/phpunit": "This is an extension for it so make sure you have it some way."
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
"autoload": {
"psr-4": {
- "GeckoPackages\\PHPUnit\\": "src\\PHPUnit"
+ "GeckoPackages\\PHPUnit\\": "src/PHPUnit"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "Additional PHPUnit tests.",
+ "description": "Additional PHPUnit asserts and constraints.",
"homepage": "https://github.com/GeckoPackages",
"keywords": [
"extension",
"filesystem",
"phpunit"
],
- "time": "2017-06-20T11:22:48+00:00"
- },
- {
- "name": "guzzle/guzzle",
- "version": "v3.8.1",
- "source": {
- "type": "git",
- "url": "https://github.com/guzzle/guzzle.git",
- "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/guzzle/guzzle/zipball/4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
- "reference": "4de0618a01b34aa1c8c33a3f13f396dcd3882eba",
- "shasum": ""
- },
- "require": {
- "ext-curl": "*",
- "php": ">=5.3.3",
- "symfony/event-dispatcher": ">=2.1"
- },
- "replace": {
- "guzzle/batch": "self.version",
- "guzzle/cache": "self.version",
- "guzzle/common": "self.version",
- "guzzle/http": "self.version",
- "guzzle/inflection": "self.version",
- "guzzle/iterator": "self.version",
- "guzzle/log": "self.version",
- "guzzle/parser": "self.version",
- "guzzle/plugin": "self.version",
- "guzzle/plugin-async": "self.version",
- "guzzle/plugin-backoff": "self.version",
- "guzzle/plugin-cache": "self.version",
- "guzzle/plugin-cookie": "self.version",
- "guzzle/plugin-curlauth": "self.version",
- "guzzle/plugin-error-response": "self.version",
- "guzzle/plugin-history": "self.version",
- "guzzle/plugin-log": "self.version",
- "guzzle/plugin-md5": "self.version",
- "guzzle/plugin-mock": "self.version",
- "guzzle/plugin-oauth": "self.version",
- "guzzle/service": "self.version",
- "guzzle/stream": "self.version"
- },
- "require-dev": {
- "doctrine/cache": "*",
- "monolog/monolog": "1.*",
- "phpunit/phpunit": "3.7.*",
- "psr/log": "1.0.*",
- "symfony/class-loader": "*",
- "zendframework/zend-cache": "<2.3",
- "zendframework/zend-log": "<2.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.8-dev"
- }
- },
- "autoload": {
- "psr-0": {
- "Guzzle": "src/",
- "Guzzle\\Tests": "tests/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Michael Dowling",
- "email": "mtdowling@gmail.com",
- "homepage": "https://github.com/mtdowling"
- },
- {
- "name": "Guzzle Community",
- "homepage": "https://github.com/guzzle/guzzle/contributors"
- }
- ],
- "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients",
- "homepage": "http://guzzlephp.org/",
- "keywords": [
- "client",
- "curl",
- "framework",
- "http",
- "http client",
- "rest",
- "web service"
- ],
- "abandoned": "guzzlehttp/guzzle",
- "time": "2014-01-28T22:29:15+00:00"
+ "time": "2017-08-23T07:46:41+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.6.0",
+ "version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe"
+ "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5a5a9fc8025a08d8919be87d6884d5a92520cefe",
- "reference": "5a5a9fc8025a08d8919be87d6884d5a92520cefe",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
+ "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e",
"shasum": ""
},
"require": {
- "php": ">=5.4.0"
+ "php": "^5.6 || ^7.0"
},
"require-dev": {
- "doctrine/collections": "1.*",
- "phpunit/phpunit": "~4.1"
+ "doctrine/collections": "^1.0",
+ "doctrine/common": "^2.6",
+ "phpunit/phpunit": "^4.1"
},
"type": "library",
"autoload": {
"psr-4": {
"DeepCopy\\": "src/DeepCopy/"
- }
+ },
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Create deep copies (clones) of your objects",
- "homepage": "https://github.com/myclabs/DeepCopy",
"keywords": [
"clone",
"copy",
@@ -438,20 +417,474 @@
"object",
"object graph"
],
- "time": "2017-01-26T22:05:40+00:00"
+ "time": "2017-10-19T19:58:43+00:00"
},
{
- "name": "paragonie/random_compat",
- "version": "v2.0.10",
+ "name": "nette/caching",
+ "version": "v2.5.6",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+ "url": "https://github.com/nette/caching.git",
+ "reference": "1231735b5135ca02bd381b70482c052d2a90bdc9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
- "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+ "url": "https://api.github.com/repos/nette/caching/zipball/1231735b5135ca02bd381b70482c052d2a90bdc9",
+ "reference": "1231735b5135ca02bd381b70482c052d2a90bdc9",
+ "shasum": ""
+ },
+ "require": {
+ "nette/finder": "^2.2 || ~3.0.0",
+ "nette/utils": "^2.4 || ~3.0.0",
+ "php": ">=5.6.0"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "latte/latte": "^2.4",
+ "nette/di": "^2.4 || ~3.0.0",
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.4"
+ },
+ "suggest": {
+ "ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.5-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "cache",
+ "journal",
+ "memcached",
+ "nette",
+ "sqlite"
+ ],
+ "time": "2017-08-30T12:12:25+00:00"
+ },
+ {
+ "name": "nette/di",
+ "version": "v2.4.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/di.git",
+ "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/di/zipball/a4b3be935b755f23aebea1ce33d7e3c832cdff98",
+ "reference": "a4b3be935b755f23aebea1ce33d7e3c832cdff98",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "nette/neon": "^2.3.3 || ~3.0.0",
+ "nette/php-generator": "^2.6.1 || ~3.0.0",
+ "nette/utils": "^2.4.3 || ~3.0.0",
+ "php": ">=5.6.0"
+ },
+ "conflict": {
+ "nette/bootstrap": "<2.4",
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "compiled",
+ "di",
+ "dic",
+ "factory",
+ "ioc",
+ "nette",
+ "static"
+ ],
+ "time": "2017-08-31T22:42:00+00:00"
+ },
+ {
+ "name": "nette/finder",
+ "version": "v2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/finder.git",
+ "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/finder/zipball/4d43a66d072c57d585bf08a3ef68d3587f7e9547",
+ "reference": "4d43a66d072c57d585bf08a3ef68d3587f7e9547",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^2.4 || ~3.0.0",
+ "php": ">=5.6.0"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "Nette Finder: Files Searching",
+ "homepage": "https://nette.org",
+ "time": "2017-07-10T23:47:08+00:00"
+ },
+ {
+ "name": "nette/neon",
+ "version": "v2.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/neon.git",
+ "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/neon/zipball/9eacd50553b26b53a3977bfb2fea2166d4331622",
+ "reference": "9eacd50553b26b53a3977bfb2fea2166d4331622",
+ "shasum": ""
+ },
+ "require": {
+ "ext-iconv": "*",
+ "ext-json": "*",
+ "php": ">=5.6.0"
+ },
+ "require-dev": {
+ "nette/tester": "~2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "Nette NEON: parser & generator for Nette Object Notation",
+ "homepage": "http://ne-on.org",
+ "time": "2017-07-11T18:29:08+00:00"
+ },
+ {
+ "name": "nette/php-generator",
+ "version": "v3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/php-generator.git",
+ "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/php-generator/zipball/eb2dbc9c3409e9db40568109ca4994d51373b60c",
+ "reference": "eb2dbc9c3409e9db40568109ca4994d51373b60c",
+ "shasum": ""
+ },
+ "require": {
+ "nette/utils": "^2.4.2 || ~3.0.0",
+ "php": ">=7.0"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.1 features.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "code",
+ "nette",
+ "php",
+ "scaffolding"
+ ],
+ "time": "2017-07-11T19:07:13+00:00"
+ },
+ {
+ "name": "nette/robot-loader",
+ "version": "v3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/robot-loader.git",
+ "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/robot-loader/zipball/b703b4f5955831b0bcaacbd2f6af76021b056826",
+ "reference": "b703b4f5955831b0bcaacbd2f6af76021b056826",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "nette/finder": "^2.3 || ^3.0",
+ "nette/utils": "^2.4 || ^3.0",
+ "php": ">=5.6.0"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "^2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "autoload",
+ "class",
+ "interface",
+ "nette",
+ "trait"
+ ],
+ "time": "2017-07-18T00:09:56+00:00"
+ },
+ {
+ "name": "nette/utils",
+ "version": "v2.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/utils.git",
+ "reference": "f1584033b5af945b470533b466b81a789d532034"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/utils/zipball/f1584033b5af945b470533b466b81a789d532034",
+ "reference": "f1584033b5af945b470533b466b81a789d532034",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.6.0"
+ },
+ "conflict": {
+ "nette/nette": "<2.2"
+ },
+ "require-dev": {
+ "nette/tester": "~2.0",
+ "tracy/tracy": "^2.3"
+ },
+ "suggest": {
+ "ext-gd": "to use Image",
+ "ext-iconv": "to use Strings::webalize() and toAscii()",
+ "ext-intl": "for script transliteration in Strings::webalize() and toAscii()",
+ "ext-json": "to use Nette\\Utils\\Json",
+ "ext-mbstring": "to use Strings::lower() etc...",
+ "ext-xml": "to use Strings::length() etc. when mbstring is not available"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
+ "homepage": "https://nette.org",
+ "keywords": [
+ "array",
+ "core",
+ "datetime",
+ "images",
+ "json",
+ "nette",
+ "paginator",
+ "password",
+ "slugify",
+ "string",
+ "unicode",
+ "utf-8",
+ "utility",
+ "validation"
+ ],
+ "time": "2017-08-20T17:32:29+00:00"
+ },
+ {
+ "name": "paragonie/random_compat",
+ "version": "v2.0.11",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8",
+ "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8",
"shasum": ""
},
"require": {
@@ -486,81 +919,170 @@
"pseudorandom",
"random"
],
- "time": "2017-03-13T16:27:32+00:00"
+ "time": "2017-09-27T21:40:39+00:00"
},
{
- "name": "php-coveralls/php-coveralls",
- "version": "v1.0.2",
+ "name": "phar-io/manifest",
+ "version": "1.0.1",
"source": {
"type": "git",
- "url": "https://github.com/php-coveralls/php-coveralls.git",
- "reference": "9c07b63acbc9709344948b6fd4f63a32b2ef4127"
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-coveralls/php-coveralls/zipball/9c07b63acbc9709344948b6fd4f63a32b2ef4127",
- "reference": "9c07b63acbc9709344948b6fd4f63a32b2ef4127",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0",
+ "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "ext-simplexml": "*",
- "guzzle/guzzle": "^2.8 || ^3.0",
- "php": "^5.3.3 || ^7.0",
- "psr/log": "^1.0",
- "symfony/config": "^2.1 || ^3.0 || ^4.0",
- "symfony/console": "^2.1 || ^3.0 || ^4.0",
- "symfony/stopwatch": "^2.0 || ^3.0 || ^4.0",
- "symfony/yaml": "^2.0 || ^3.0 || ^4.0"
+ "ext-dom": "*",
+ "ext-phar": "*",
+ "phar-io/version": "^1.0.1",
+ "php": "^5.6 || ^7.0"
},
- "require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.4.3 || ^6.0"
- },
- "suggest": {
- "symfony/http-kernel": "Allows Symfony integration"
- },
- "bin": [
- "bin/coveralls"
- ],
"type": "library",
- "autoload": {
- "psr-4": {
- "Satooshi\\": "src/Satooshi/"
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
}
},
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Kitamura Satoshi",
- "email": "with.no.parachute@gmail.com",
- "homepage": "https://www.facebook.com/satooshi.jp"
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
}
],
- "description": "PHP client library for Coveralls API",
- "homepage": "https://github.com/php-coveralls/php-coveralls",
- "keywords": [
- "ci",
- "coverage",
- "github",
- "test"
- ],
- "time": "2017-10-14T23:15:34+00:00"
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "time": "2017-03-05T18:14:27+00:00"
},
{
- "name": "phpdocumentor/reflection-common",
- "version": "1.0",
+ "name": "phar-io/version",
+ "version": "1.0.1",
"source": {
"type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
- "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df",
+ "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "time": "2017-03-05T17:38:23+00:00"
+ },
+ {
+ "name": "php-cs-fixer/diff",
+ "version": "v1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHP-CS-Fixer/diff.git",
+ "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/diff/zipball/f0ef6133d674137e902fdf8a6f2e8e97e14a087b",
+ "reference": "f0ef6133d674137e902fdf8a6f2e8e97e14a087b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.6 || ^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35 || ^5.4.3",
+ "symfony/process": "^3.3"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "authors": [
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "SpacePossum"
+ }
+ ],
+ "description": "sebastian/diff v2 backport support for PHP5.6",
+ "homepage": "https://github.com/PHP-CS-Fixer",
+ "keywords": [
+ "diff"
+ ],
+ "time": "2017-10-19T09:58:18+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
+ "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
"shasum": ""
},
"require": {
@@ -601,26 +1123,26 @@
"reflection",
"static analysis"
],
- "time": "2015-12-27T11:43:31+00:00"
+ "time": "2017-09-11T18:02:19+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "3.1.1",
+ "version": "4.1.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
+ "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
- "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2",
+ "reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2",
"shasum": ""
},
"require": {
- "php": ">=5.5",
+ "php": "^7.0",
"phpdocumentor/reflection-common": "^1.0@dev",
- "phpdocumentor/type-resolver": "^0.2.0",
+ "phpdocumentor/type-resolver": "^0.4.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
@@ -646,24 +1168,24 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2016-09-30T07:12:33+00:00"
+ "time": "2017-08-30T18:51:59+00:00"
},
{
"name": "phpdocumentor/type-resolver",
- "version": "0.2.1",
+ "version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
+ "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
- "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
+ "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
"shasum": ""
},
"require": {
- "php": ">=5.5",
+ "php": "^5.5 || ^7.0",
"phpdocumentor/reflection-common": "^1.0"
},
"require-dev": {
@@ -693,26 +1215,26 @@
"email": "me@mikevanriel.com"
}
],
- "time": "2016-11-25T06:54:22+00:00"
+ "time": "2017-07-14T14:27:02+00:00"
},
{
"name": "phpspec/prophecy",
- "version": "v1.7.0",
+ "version": "v1.7.2",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
+ "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
- "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
+ "reference": "c9b8c6088acd19d769d4cc0ffa60a9fe34344bd6",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
"sebastian/comparator": "^1.1|^2.0",
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
},
@@ -723,7 +1245,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.6.x-dev"
+ "dev-master": "1.7.x-dev"
}
},
"autoload": {
@@ -756,44 +1278,45 @@
"spy",
"stub"
],
- "time": "2017-03-02T20:05:34+00:00"
+ "time": "2017-09-04T11:05:03+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "5.0.2",
+ "version": "5.2.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "531553c4795a1df54114342d68ca337d5d81c8a0"
+ "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/531553c4795a1df54114342d68ca337d5d81c8a0",
- "reference": "531553c4795a1df54114342d68ca337d5d81c8a0",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d",
+ "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xmlwriter": "*",
"php": "^7.0",
- "phpunit/php-file-iterator": "^1.3",
- "phpunit/php-text-template": "^1.2",
- "phpunit/php-token-stream": "^1.4.11 || ^2.0",
- "sebastian/code-unit-reverse-lookup": "^1.0",
- "sebastian/environment": "^2.0",
- "sebastian/version": "^2.0"
+ "phpunit/php-file-iterator": "^1.4.2",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-token-stream": "^2.0",
+ "sebastian/code-unit-reverse-lookup": "^1.0.1",
+ "sebastian/environment": "^3.0",
+ "sebastian/version": "^2.0.1",
+ "theseer/tokenizer": "^1.1"
},
"require-dev": {
"ext-xdebug": "^2.5",
"phpunit/phpunit": "^6.0"
},
"suggest": {
- "ext-xdebug": "^2.5.1"
+ "ext-xdebug": "^2.5.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0.x-dev"
+ "dev-master": "5.2.x-dev"
}
},
"autoload": {
@@ -819,7 +1342,7 @@
"testing",
"xunit"
],
- "time": "2017-03-01T09:14:18+00:00"
+ "time": "2017-11-03T13:47:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -960,29 +1483,29 @@
},
{
"name": "phpunit/php-token-stream",
- "version": "1.4.11",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
+ "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
- "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9a02332089ac48e704c70f6cefed30c224e3c0b0",
+ "reference": "9a02332089ac48e704c70f6cefed30c224e3c0b0",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
- "php": ">=5.3.3"
+ "php": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.2"
+ "phpunit/phpunit": "^6.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -1005,20 +1528,20 @@
"keywords": [
"tokenizer"
],
- "time": "2017-02-27T10:12:30+00:00"
+ "time": "2017-08-20T05:47:52+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "6.0.8",
+ "version": "6.4.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "47ee3fa1bca5c50f1d25105201eb20df777bd7b6"
+ "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/47ee3fa1bca5c50f1d25105201eb20df777bd7b6",
- "reference": "47ee3fa1bca5c50f1d25105201eb20df777bd7b6",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/562f7dc75d46510a4ed5d16189ae57fbe45a9932",
+ "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932",
"shasum": ""
},
"require": {
@@ -1027,22 +1550,24 @@
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-xml": "*",
- "myclabs/deep-copy": "^1.3",
+ "myclabs/deep-copy": "^1.6.1",
+ "phar-io/manifest": "^1.0.1",
+ "phar-io/version": "^1.0",
"php": "^7.0",
- "phpspec/prophecy": "^1.6.2",
- "phpunit/php-code-coverage": "^5.0",
- "phpunit/php-file-iterator": "^1.4",
- "phpunit/php-text-template": "^1.2",
- "phpunit/php-timer": "^1.0.6",
- "phpunit/phpunit-mock-objects": "^4.0",
- "sebastian/comparator": "^1.2.4 || ^2.0",
- "sebastian/diff": "^1.2",
- "sebastian/environment": "^2.0",
- "sebastian/exporter": "^2.0 || ^3.0",
- "sebastian/global-state": "^1.1 || ^2.0",
- "sebastian/object-enumerator": "^2.0 || ^3.0",
+ "phpspec/prophecy": "^1.7",
+ "phpunit/php-code-coverage": "^5.2.2",
+ "phpunit/php-file-iterator": "^1.4.2",
+ "phpunit/php-text-template": "^1.2.1",
+ "phpunit/php-timer": "^1.0.9",
+ "phpunit/phpunit-mock-objects": "^4.0.3",
+ "sebastian/comparator": "^2.0.2",
+ "sebastian/diff": "^2.0",
+ "sebastian/environment": "^3.1",
+ "sebastian/exporter": "^3.1",
+ "sebastian/global-state": "^2.0",
+ "sebastian/object-enumerator": "^3.0.3",
"sebastian/resource-operations": "^1.0",
- "sebastian/version": "^2.0"
+ "sebastian/version": "^2.0.1"
},
"conflict": {
"phpdocumentor/reflection-docblock": "3.0.2",
@@ -1061,7 +1586,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "6.0.x-dev"
+ "dev-master": "6.4.x-dev"
}
},
"autoload": {
@@ -1087,26 +1612,26 @@
"testing",
"xunit"
],
- "time": "2017-03-02T15:24:03+00:00"
+ "time": "2017-11-08T11:26:09+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
- "version": "4.0.1",
+ "version": "4.0.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "eabce450df194817a7d7e27e19013569a903a2bf"
+ "reference": "2f789b59ab89669015ad984afa350c4ec577ade0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/eabce450df194817a7d7e27e19013569a903a2bf",
- "reference": "eabce450df194817a7d7e27e19013569a903a2bf",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/2f789b59ab89669015ad984afa350c4ec577ade0",
+ "reference": "2f789b59ab89669015ad984afa350c4ec577ade0",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.0.2",
+ "doctrine/instantiator": "^1.0.5",
"php": "^7.0",
- "phpunit/php-text-template": "^1.2",
+ "phpunit/php-text-template": "^1.2.1",
"sebastian/exporter": "^3.0"
},
"conflict": {
@@ -1146,7 +1671,56 @@
"mock",
"xunit"
],
- "time": "2017-03-03T06:30:20+00:00"
+ "time": "2017-08-03T14:08:16+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/log",
@@ -1242,30 +1816,30 @@
},
{
"name": "sebastian/comparator",
- "version": "2.0.0",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "20f84f468cb67efee293246e6a09619b891f55f0"
+ "reference": "1174d9018191e93cb9d719edec01257fc05f8158"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/20f84f468cb67efee293246e6a09619b891f55f0",
- "reference": "20f84f468cb67efee293246e6a09619b891f55f0",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158",
+ "reference": "1174d9018191e93cb9d719edec01257fc05f8158",
"shasum": ""
},
"require": {
"php": "^7.0",
- "sebastian/diff": "^1.2",
- "sebastian/exporter": "^3.0"
+ "sebastian/diff": "^2.0",
+ "sebastian/exporter": "^3.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.0"
+ "phpunit/phpunit": "^6.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0.x-dev"
+ "dev-master": "2.1.x-dev"
}
},
"autoload": {
@@ -1296,38 +1870,38 @@
}
],
"description": "Provides the functionality to compare PHP values for equality",
- "homepage": "http://www.github.com/sebastianbergmann/comparator",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
- "time": "2017-03-03T06:26:08+00:00"
+ "time": "2017-11-03T07:16:52+00:00"
},
{
"name": "sebastian/diff",
- "version": "1.4.1",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e"
+ "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e",
- "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd",
+ "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.8"
+ "phpunit/phpunit": "^6.2"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -1354,32 +1928,32 @@
"keywords": [
"diff"
],
- "time": "2015-12-08T07:14:41+00:00"
+ "time": "2017-08-03T08:09:46+00:00"
},
{
"name": "sebastian/environment",
- "version": "2.0.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
+ "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
- "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
+ "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5",
"shasum": ""
},
"require": {
- "php": "^5.6 || ^7.0"
+ "php": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "^5.0"
+ "phpunit/phpunit": "^6.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0.x-dev"
+ "dev-master": "3.1.x-dev"
}
},
"autoload": {
@@ -1404,20 +1978,20 @@
"environment",
"hhvm"
],
- "time": "2016-11-26T07:53:53+00:00"
+ "time": "2017-07-01T08:51:00+00:00"
},
{
"name": "sebastian/exporter",
- "version": "3.0.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "b82d077cb3459e393abcf4867ae8f7230dcb51f6"
+ "reference": "234199f4528de6d12aaa58b612e98f7d36adb937"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/b82d077cb3459e393abcf4867ae8f7230dcb51f6",
- "reference": "b82d077cb3459e393abcf4867ae8f7230dcb51f6",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937",
+ "reference": "234199f4528de6d12aaa58b612e98f7d36adb937",
"shasum": ""
},
"require": {
@@ -1431,7 +2005,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0.x-dev"
+ "dev-master": "3.1.x-dev"
}
},
"autoload": {
@@ -1471,27 +2045,27 @@
"export",
"exporter"
],
- "time": "2017-03-03T06:25:06+00:00"
+ "time": "2017-04-03T13:19:02+00:00"
},
{
"name": "sebastian/global-state",
- "version": "1.1.1",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
- "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
+ "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.2"
+ "phpunit/phpunit": "^6.0"
},
"suggest": {
"ext-uopz": "*"
@@ -1499,7 +2073,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -1522,24 +2096,25 @@
"keywords": [
"global state"
],
- "time": "2015-10-12T03:26:01+00:00"
+ "time": "2017-04-27T15:39:26+00:00"
},
{
"name": "sebastian/object-enumerator",
- "version": "3.0.0",
+ "version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "de6e32f7192dfea2e4bedc892434f4830b5c5794"
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/de6e32f7192dfea2e4bedc892434f4830b5c5794",
- "reference": "de6e32f7192dfea2e4bedc892434f4830b5c5794",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5",
+ "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5",
"shasum": ""
},
"require": {
"php": "^7.0",
+ "sebastian/object-reflector": "^1.1.1",
"sebastian/recursion-context": "^3.0"
},
"require-dev": {
@@ -1568,7 +2143,52 @@
],
"description": "Traverses array structures and object graphs to enumerate all referenced objects",
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
- "time": "2017-03-03T06:21:01+00:00"
+ "time": "2017-08-03T12:35:26+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "1.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be",
+ "reference": "773f97c67f28de00d397be301821b06708fca0be",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "time": "2017-03-29T09:07:27+00:00"
},
{
"name": "sebastian/recursion-context",
@@ -1708,6 +2328,94 @@
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2016-10-03T07:35:21+00:00"
},
+ {
+ "name": "slevomat/coding-standard",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/slevomat/coding-standard.git",
+ "reference": "bab653d0f7f2e3ed13796f7803067d252f00a25a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/bab653d0f7f2e3ed13796f7803067d252f00a25a",
+ "reference": "bab653d0f7f2e3ed13796f7803067d252f00a25a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0",
+ "squizlabs/php_codesniffer": "^3.0.1"
+ },
+ "require-dev": {
+ "jakub-onderka/php-parallel-lint": "0.9.2",
+ "phing/phing": "2.16",
+ "phpstan/phpstan": "0.8.4",
+ "phpunit/phpunit": "6.3.0"
+ },
+ "type": "phpcodesniffer-standard",
+ "autoload": {
+ "psr-4": {
+ "SlevomatCodingStandard\\": "SlevomatCodingStandard"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
+ "time": "2017-09-15T17:47:36+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+ "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d667e245d5dcd4d7bf80f26f2c947d476b66213e",
+ "reference": "d667e245d5dcd4d7bf80f26f2c947d476b66213e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0"
+ },
+ "bin": [
+ "bin/phpcs",
+ "bin/phpcbf"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "lead"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "http://www.squizlabs.com/php-codesniffer",
+ "keywords": [
+ "phpcs",
+ "standards"
+ ],
+ "time": "2017-10-16T22:40:25+00:00"
+ },
{
"name": "symfony/config",
"version": "v3.3.12",
@@ -1772,20 +2480,20 @@
},
{
"name": "symfony/console",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546"
+ "reference": "099302cc53e57cbb7414fd9f3ace40e5e2767c0b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/a97e45d98c59510f085fa05225a1acb74dfe0546",
- "reference": "a97e45d98c59510f085fa05225a1acb74dfe0546",
+ "url": "https://api.github.com/repos/symfony/console/zipball/099302cc53e57cbb7414fd9f3ace40e5e2767c0b",
+ "reference": "099302cc53e57cbb7414fd9f3ace40e5e2767c0b",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": "^5.5.9|>=7.0.8",
"symfony/debug": "~2.8|~3.0",
"symfony/polyfill-mbstring": "~1.0"
},
@@ -1798,7 +2506,6 @@
"symfony/dependency-injection": "~3.3",
"symfony/event-dispatcher": "~2.8|~3.0",
"symfony/filesystem": "~2.8|~3.0",
- "symfony/http-kernel": "~2.8|~3.0",
"symfony/process": "~2.8|~3.0"
},
"suggest": {
@@ -1837,24 +2544,24 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-07-03T13:19:36+00:00"
+ "time": "2017-11-12T16:53:41+00:00"
},
{
"name": "symfony/debug",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "63b85a968486d95ff9542228dc2e4247f16f9743"
+ "reference": "74557880e2846b5c84029faa96b834da37e29810"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/63b85a968486d95ff9542228dc2e4247f16f9743",
- "reference": "63b85a968486d95ff9542228dc2e4247f16f9743",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/74557880e2846b5c84029faa96b834da37e29810",
+ "reference": "74557880e2846b5c84029faa96b834da37e29810",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": "^5.5.9|>=7.0.8",
"psr/log": "~1.0"
},
"conflict": {
@@ -1893,24 +2600,94 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-07-05T13:02:37+00:00"
+ "time": "2017-11-10T16:38:39+00:00"
},
{
- "name": "symfony/event-dispatcher",
- "version": "v3.3.5",
+ "name": "symfony/dependency-injection",
+ "version": "v3.3.12",
"source": {
"type": "git",
- "url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e"
+ "url": "https://github.com/symfony/dependency-injection.git",
+ "reference": "4e84f5af2c2d51ee3dee72df40b7fc08f49b4ab8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67535f1e3fd662bdc68d7ba317c93eecd973617e",
- "reference": "67535f1e3fd662bdc68d7ba317c93eecd973617e",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4e84f5af2c2d51ee3dee72df40b7fc08f49b4ab8",
+ "reference": "4e84f5af2c2d51ee3dee72df40b7fc08f49b4ab8",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8",
+ "psr/container": "^1.0"
+ },
+ "conflict": {
+ "symfony/config": "<3.3.1",
+ "symfony/finder": "<3.3",
+ "symfony/yaml": "<3.3"
+ },
+ "provide": {
+ "psr/container-implementation": "1.0"
+ },
+ "require-dev": {
+ "symfony/config": "~3.3",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/yaml": "~3.3"
+ },
+ "suggest": {
+ "symfony/config": "",
+ "symfony/expression-language": "For using expressions in service container configuration",
+ "symfony/finder": "For using double-star glob patterns or when GLOB_BRACE portability is required",
+ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
+ "symfony/yaml": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\DependencyInjection\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony DependencyInjection Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-13T18:10:32+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v3.3.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/271d8c27c3ec5ecee6e2ac06016232e249d638d9",
+ "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
},
"conflict": {
"symfony/dependency-injection": "<3.3"
@@ -1956,24 +2733,24 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2017-06-09T14:53:08+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "427987eb4eed764c3b6e38d52a0f87989e010676"
+ "reference": "77db266766b54db3ee982fe51868328b887ce15c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/427987eb4eed764c3b6e38d52a0f87989e010676",
- "reference": "427987eb4eed764c3b6e38d52a0f87989e010676",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/77db266766b54db3ee982fe51868328b887ce15c",
+ "reference": "77db266766b54db3ee982fe51868328b887ce15c",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -2005,24 +2782,24 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2017-07-11T07:17:58+00:00"
+ "time": "2017-11-07T14:12:55+00:00"
},
{
"name": "symfony/finder",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4"
+ "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/baea7f66d30854ad32988c11a09d7ffd485810c4",
- "reference": "baea7f66d30854ad32988c11a09d7ffd485810c4",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
+ "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -2054,24 +2831,163 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-06-01T21:01:25+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
- "name": "symfony/options-resolver",
- "version": "v3.3.5",
+ "name": "symfony/http-foundation",
+ "version": "v3.3.12",
"source": {
"type": "git",
- "url": "https://github.com/symfony/options-resolver.git",
- "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0"
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "5943f0f19817a7e05992d20a90729b0dc93faf36"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ff48982d295bcac1fd861f934f041ebc73ae40f0",
- "reference": "ff48982d295bcac1fd861f934f041ebc73ae40f0",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5943f0f19817a7e05992d20a90729b0dc93faf36",
+ "reference": "5943f0f19817a7e05992d20a90729b0dc93faf36",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8",
+ "symfony/polyfill-mbstring": "~1.1"
+ },
+ "require-dev": {
+ "symfony/expression-language": "~2.8|~3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpFoundation Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-13T18:13:16+00:00"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "v3.3.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "371ed63691c1ee8749613a6b48cf0e0cfa2b01e7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/371ed63691c1ee8749613a6b48cf0e0cfa2b01e7",
+ "reference": "371ed63691c1ee8749613a6b48cf0e0cfa2b01e7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8",
+ "psr/log": "~1.0",
+ "symfony/debug": "~2.8|~3.0",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/http-foundation": "^3.3.11"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/var-dumper": "<3.3",
+ "twig/twig": "<1.34|<2.4,>=2"
+ },
+ "require-dev": {
+ "psr/cache": "~1.0",
+ "symfony/browser-kit": "~2.8|~3.0",
+ "symfony/class-loader": "~2.8|~3.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/console": "~2.8|~3.0",
+ "symfony/css-selector": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/dom-crawler": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/finder": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0",
+ "symfony/routing": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0",
+ "symfony/templating": "~2.8|~3.0",
+ "symfony/translation": "~2.8|~3.0",
+ "symfony/var-dumper": "~3.3"
+ },
+ "suggest": {
+ "symfony/browser-kit": "",
+ "symfony/class-loader": "",
+ "symfony/config": "",
+ "symfony/console": "",
+ "symfony/dependency-injection": "",
+ "symfony/finder": "",
+ "symfony/var-dumper": ""
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony HttpKernel Component",
+ "homepage": "https://symfony.com",
+ "time": "2017-11-13T19:37:21+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v3.3.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "623d9c210a137205f7e6e98166105625402cbb2f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/623d9c210a137205f7e6e98166105625402cbb2f",
+ "reference": "623d9c210a137205f7e6e98166105625402cbb2f",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -2108,20 +3024,20 @@
"configuration",
"options"
],
- "time": "2017-04-12T14:14:56+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.4.0",
+ "version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "f29dca382a6485c3cbe6379f0c61230167681937"
+ "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937",
- "reference": "f29dca382a6485c3cbe6379f0c61230167681937",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
+ "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296",
"shasum": ""
},
"require": {
@@ -2133,7 +3049,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.6-dev"
}
},
"autoload": {
@@ -2167,20 +3083,20 @@
"portable",
"shim"
],
- "time": "2017-06-09T14:24:12+00:00"
+ "time": "2017-10-11T12:05:26+00:00"
},
{
"name": "symfony/polyfill-php70",
- "version": "v1.4.0",
+ "version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php70.git",
- "reference": "032fd647d5c11a9ceab8ee8747e13b5448e93874"
+ "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/032fd647d5c11a9ceab8ee8747e13b5448e93874",
- "reference": "032fd647d5c11a9ceab8ee8747e13b5448e93874",
+ "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff",
+ "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff",
"shasum": ""
},
"require": {
@@ -2190,7 +3106,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.6-dev"
}
},
"autoload": {
@@ -2226,20 +3142,20 @@
"portable",
"shim"
],
- "time": "2017-06-09T14:24:12+00:00"
+ "time": "2017-10-11T12:05:26+00:00"
},
{
"name": "symfony/polyfill-php72",
- "version": "v1.4.0",
+ "version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
- "reference": "d3a71580c1e2cab33b6d705f0ec40e9015e14d5c"
+ "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/d3a71580c1e2cab33b6d705f0ec40e9015e14d5c",
- "reference": "d3a71580c1e2cab33b6d705f0ec40e9015e14d5c",
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/6de4f4884b97abbbed9f0a84a95ff2ff77254254",
+ "reference": "6de4f4884b97abbbed9f0a84a95ff2ff77254254",
"shasum": ""
},
"require": {
@@ -2248,7 +3164,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.4-dev"
+ "dev-master": "1.6-dev"
}
},
"autoload": {
@@ -2281,24 +3197,24 @@
"portable",
"shim"
],
- "time": "2017-06-09T08:25:21+00:00"
+ "time": "2017-10-11T12:05:26+00:00"
},
{
"name": "symfony/process",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a"
+ "reference": "a56a3989fb762d7b19a0cf8e7693ee99a6ffb78d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/07432804942b9f6dd7b7377faf9920af5f95d70a",
- "reference": "07432804942b9f6dd7b7377faf9920af5f95d70a",
+ "url": "https://api.github.com/repos/symfony/process/zipball/a56a3989fb762d7b19a0cf8e7693ee99a6ffb78d",
+ "reference": "a56a3989fb762d7b19a0cf8e7693ee99a6ffb78d",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -2330,24 +3246,24 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2017-07-13T13:05:09+00:00"
+ "time": "2017-11-13T15:31:11+00:00"
},
{
"name": "symfony/stopwatch",
- "version": "v3.3.5",
+ "version": "v3.3.12",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "602a15299dc01556013b07167d4f5d3a60e90d15"
+ "reference": "1e93c3139ef6c799831fe03efd0fb1c7aecb3365"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/602a15299dc01556013b07167d4f5d3a60e90d15",
- "reference": "602a15299dc01556013b07167d4f5d3a60e90d15",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/1e93c3139ef6c799831fe03efd0fb1c7aecb3365",
+ "reference": "1e93c3139ef6c799831fe03efd0fb1c7aecb3365",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": "^5.5.9|>=7.0.8"
},
"type": "library",
"extra": {
@@ -2379,7 +3295,7 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
- "time": "2017-04-12T14:14:56+00:00"
+ "time": "2017-11-10T19:02:53+00:00"
},
{
"name": "symfony/yaml",
@@ -2436,6 +3352,259 @@
"homepage": "https://symfony.com",
"time": "2017-11-10T18:26:04+00:00"
},
+ {
+ "name": "symplify/coding-standard",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Symplify/CodingStandard.git",
+ "reference": "309fd562066cdc86b81375ff080b1ee2f900778e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Symplify/CodingStandard/zipball/309fd562066cdc86b81375ff080b1ee2f900778e",
+ "reference": "309fd562066cdc86b81375ff080b1ee2f900778e",
+ "shasum": ""
+ },
+ "require": {
+ "friendsofphp/php-cs-fixer": "^2.8",
+ "nette/finder": "^2.4|^3.0",
+ "nette/utils": "^2.4|^3.0",
+ "php": "^7.1",
+ "slevomat/coding-standard": "^4.0",
+ "squizlabs/php_codesniffer": "^3.1"
+ },
+ "require-dev": {
+ "gecko-packages/gecko-php-unit": "3.0 as 2.2",
+ "nette/application": "^2.4",
+ "phpunit/phpunit": "^6.4",
+ "symplify/easy-coding-standard": "^2.5|^3.0",
+ "symplify/package-builder": "^2.5|^3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symplify\\CodingStandard\\": "src",
+ "Symplify\\CodingStandard\\SniffTokenWrapper\\": "packages/SniffTokenWrapper/src",
+ "Symplify\\CodingStandard\\FixerTokenWrapper\\": "packages/FixerTokenWrapper/src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Set of Symplify rules for PHP_CodeSniffer.",
+ "time": "2017-11-16 00:38:24"
+ },
+ {
+ "name": "symplify/easy-coding-standard",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Symplify/EasyCodingStandard.git",
+ "reference": "4bac5271050f063b4455bd870cc215e0db57ddf8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Symplify/EasyCodingStandard/zipball/4bac5271050f063b4455bd870cc215e0db57ddf8",
+ "reference": "4bac5271050f063b4455bd870cc215e0db57ddf8",
+ "shasum": ""
+ },
+ "require": {
+ "friendsofphp/php-cs-fixer": "^2.8",
+ "nette/caching": "^2.4|^3.0",
+ "nette/di": "^2.4|^3.0",
+ "nette/neon": "^2.4|^3.0",
+ "nette/robot-loader": "^2.4|^3.0.1",
+ "nette/utils": "^2.4|^3.0",
+ "php": "^7.1",
+ "sebastian/diff": "^1.4|^2.0",
+ "slevomat/coding-standard": "^4.0",
+ "squizlabs/php_codesniffer": "^3.1",
+ "symfony/config": "^3.3|^4.0",
+ "symfony/console": "^3.3|^4.0",
+ "symfony/dependency-injection": "^3.3|^4.0",
+ "symfony/finder": "^3.3|^4.0",
+ "symfony/http-kernel": "^3.3|^4.0",
+ "symfony/yaml": "^3.3|^4.0",
+ "symplify/coding-standard": "^2.5|^3.0",
+ "symplify/package-builder": "^2.5|^3.0",
+ "tracy/tracy": "^2.4|^3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.0"
+ },
+ "bin": [
+ "bin/easy-coding-standard",
+ "bin/ecs",
+ "bin/easy-coding-standard.php"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symplify\\EasyCodingStandard\\": "src",
+ "Symplify\\EasyCodingStandard\\ChangedFilesDetector\\": "packages/ChangedFilesDetector/src",
+ "Symplify\\EasyCodingStandard\\Configuration\\": "packages/Configuration/src",
+ "Symplify\\EasyCodingStandard\\FixerRunner\\": "packages/FixerRunner/src",
+ "Symplify\\EasyCodingStandard\\SniffRunner\\": "packages/SniffRunner/src",
+ "Symplify\\EasyCodingStandard\\Performance\\": "packages/Performance/src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.",
+ "time": "2017-11-16 15:36:21"
+ },
+ {
+ "name": "symplify/package-builder",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Symplify/PackageBuilder.git",
+ "reference": "3604beadddfdee295b978d87475a834810a0ffd4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Symplify/PackageBuilder/zipball/3604beadddfdee295b978d87475a834810a0ffd4",
+ "reference": "3604beadddfdee295b978d87475a834810a0ffd4",
+ "shasum": ""
+ },
+ "require": {
+ "nette/di": "^2.4|^3.0",
+ "nette/neon": "^2.4|^3.0",
+ "php": "^7.1",
+ "symfony/config": "^3.3|^4.0",
+ "symfony/console": "^3.3|^4.0",
+ "symfony/dependency-injection": "^3.3|^4.0",
+ "symfony/http-kernel": "^3.3|^4.0",
+ "symfony/yaml": "^3.3|^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^6.4",
+ "tracy/tracy": "^2.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symplify\\PackageBuilder\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Dependency Injection, Console and Kernel toolkit for Symplify packages.",
+ "time": "2017-11-16T01:05:48+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "time": "2017-04-07T12:08:54+00:00"
+ },
+ {
+ "name": "tracy/tracy",
+ "version": "v2.4.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nette/tracy.git",
+ "reference": "5b302790edd71924dfe4ec44f499ef61df3f53a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nette/tracy/zipball/5b302790edd71924dfe4ec44f499ef61df3f53a2",
+ "reference": "5b302790edd71924dfe4ec44f499ef61df3f53a2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-session": "*",
+ "php": ">=5.4.4"
+ },
+ "require-dev": {
+ "nette/di": "~2.3",
+ "nette/tester": "~1.7"
+ },
+ "suggest": {
+ "https://nette.org/donate": "Please support Tracy via a donation"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.4-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src"
+ ],
+ "files": [
+ "src/shortcuts.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause",
+ "GPL-2.0",
+ "GPL-3.0"
+ ],
+ "authors": [
+ {
+ "name": "David Grudl",
+ "homepage": "https://davidgrudl.com"
+ },
+ {
+ "name": "Nette Community",
+ "homepage": "https://nette.org/contributors"
+ }
+ ],
+ "description": "😎 Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.",
+ "homepage": "https://tracy.nette.org",
+ "keywords": [
+ "Xdebug",
+ "debug",
+ "debugger",
+ "nette",
+ "profiler"
+ ],
+ "time": "2017-10-04T18:43:42+00:00"
+ },
{
"name": "webmozart/assert",
"version": "1.2.0",
@@ -2487,9 +3656,32 @@
"time": "2016-11-23T20:04:58+00:00"
}
],
- "aliases": [],
+ "aliases": [
+ {
+ "alias": "2.5",
+ "alias_normalized": "2.5.0.0",
+ "version": "9999999-dev",
+ "package": "symplify/easy-coding-standard"
+ },
+ {
+ "alias": "2.5",
+ "alias_normalized": "2.5.0.0",
+ "version": "9999999-dev",
+ "package": "symplify/coding-standard"
+ },
+ {
+ "alias": "2.5",
+ "alias_normalized": "2.5.0.0",
+ "version": "9999999-dev",
+ "package": "symplify/package-builder"
+ }
+ ],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {
+ "symplify/easy-coding-standard": 20,
+ "symplify/coding-standard": 20,
+ "symplify/package-builder": 20
+ },
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
diff --git a/easy-coding-standard.neon b/easy-coding-standard.neon
new file mode 100644
index 0000000..14d8770
--- /dev/null
+++ b/easy-coding-standard.neon
@@ -0,0 +1,39 @@
+includes:
+ - vendor/symplify/easy-coding-standard/config/psr2.neon
+ - vendor/symplify/easy-coding-standard/config/php70.neon
+ - vendor/symplify/easy-coding-standard/config/clean-code.neon
+ - vendor/symplify/easy-coding-standard/config/common/array.neon
+ - vendor/symplify/easy-coding-standard/config/common/docblock.neon
+ - vendor/symplify/easy-coding-standard/config/common/namespaces.neon
+ - vendor/symplify/easy-coding-standard/config/common/control-structures.neon
+
+ # many errors, need help
+ #- vendor/symplify/easy-coding-standard/config/common/strict.neon
+
+checkers:
+ - Symplify\CodingStandard\Fixer\Import\ImportNamespacedNameFixer
+ - Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer
+ - Symplify\CodingStandard\Fixer\Property\ArrayPropertyDefaultValueFixer
+ - Symplify\CodingStandard\Fixer\ClassNotation\PropertyAndConstantSeparationFixer
+ - Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer
+
+parameters:
+ exclude_checkers:
+ # from strict.neon
+ - PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer
+ skip:
+ PhpCsFixer\Fixer\Alias\RandomApiMigrationFixer:
+ # random_int() breaks code
+ - src/Phpml/CrossValidation/RandomSplit.php
+ SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff:
+ # magic calls
+ - src/Phpml/Preprocessing/Normalizer.php
+
+ skip_codes:
+ # missing typehints
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingParameterTypeHint
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingTraversableParameterTypeHintSpecification
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingReturnTypeHint
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingTraversableReturnTypeHintSpecification
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingPropertyTypeHint
+ - SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff.MissingTraversablePropertyTypeHintSpecification
diff --git a/phpunit.xml b/phpunit.xml
index cbf6c18..455f8bb 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -6,11 +6,9 @@
beStrictAboutTestSize="true"
beStrictAboutChangesToGlobalState="true"
>
-
-
- tests/*
-
-
+
+ tests/*
+
diff --git a/src/Phpml/Association/Apriori.php b/src/Phpml/Association/Apriori.php
index f1398d2..e13f556 100644
--- a/src/Phpml/Association/Apriori.php
+++ b/src/Phpml/Association/Apriori.php
@@ -31,7 +31,7 @@ class Apriori implements Associator
*
* @var mixed[][][]
*/
- private $large;
+ private $large = [];
/**
* Minimum relative frequency of transactions.
@@ -45,7 +45,7 @@ class Apriori implements Associator
*
* @var mixed[][]
*/
- private $rules;
+ private $rules = [];
/**
* Apriori constructor.
@@ -61,7 +61,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- public function getRules() : array
+ public function getRules(): array
{
if (!$this->large) {
$this->large = $this->apriori();
@@ -83,7 +83,7 @@ class Apriori implements Associator
*
* @return mixed[][][]
*/
- public function apriori() : array
+ public function apriori(): array
{
$L = [];
$L[1] = $this->items();
@@ -102,7 +102,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- protected function predictSample(array $sample) : array
+ protected function predictSample(array $sample): array
{
$predicts = array_values(array_filter($this->getRules(), function ($rule) use ($sample) {
return $this->equals($rule[self::ARRAY_KEY_ANTECEDENT], $sample);
@@ -133,7 +133,8 @@ class Apriori implements Associator
private function generateRules(array $frequent): void
{
foreach ($this->antecedents($frequent) as $antecedent) {
- if ($this->confidence <= ($confidence = $this->confidence($frequent, $antecedent))) {
+ $confidence = $this->confidence($frequent, $antecedent);
+ if ($this->confidence <= $confidence) {
$consequent = array_values(array_diff($frequent, $antecedent));
$this->rules[] = [
self::ARRAY_KEY_ANTECEDENT => $antecedent,
@@ -152,7 +153,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- private function powerSet(array $sample) : array
+ private function powerSet(array $sample): array
{
$results = [[]];
foreach ($sample as $item) {
@@ -171,7 +172,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- private function antecedents(array $sample) : array
+ private function antecedents(array $sample): array
{
$cardinality = count($sample);
$antecedents = $this->powerSet($sample);
@@ -186,7 +187,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- private function items() : array
+ private function items(): array
{
$items = [];
@@ -210,7 +211,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- private function frequent(array $samples) : array
+ private function frequent(array $samples): array
{
return array_filter($samples, function ($entry) {
return $this->support($entry) >= $this->support;
@@ -224,7 +225,7 @@ class Apriori implements Associator
*
* @return mixed[][]
*/
- private function candidates(array $samples) : array
+ private function candidates(array $samples): array
{
$candidates = [];
@@ -259,7 +260,7 @@ class Apriori implements Associator
* @param mixed[] $set
* @param mixed[] $subset
*/
- private function confidence(array $set, array $subset) : float
+ private function confidence(array $set, array $subset): float
{
return $this->support($set) / $this->support($subset);
}
@@ -272,7 +273,7 @@ class Apriori implements Associator
*
* @param mixed[] $sample
*/
- private function support(array $sample) : float
+ private function support(array $sample): float
{
return $this->frequency($sample) / count($this->samples);
}
@@ -284,7 +285,7 @@ class Apriori implements Associator
*
* @param mixed[] $sample
*/
- private function frequency(array $sample) : int
+ private function frequency(array $sample): int
{
return count(array_filter($this->samples, function ($entry) use ($sample) {
return $this->subset($entry, $sample);
@@ -299,7 +300,7 @@ class Apriori implements Associator
* @param mixed[][] $system
* @param mixed[] $set
*/
- private function contains(array $system, array $set) : bool
+ private function contains(array $system, array $set): bool
{
return (bool) array_filter($system, function ($entry) use ($set) {
return $this->equals($entry, $set);
@@ -312,7 +313,7 @@ class Apriori implements Associator
* @param mixed[] $set
* @param mixed[] $subset
*/
- private function subset(array $set, array $subset) : bool
+ private function subset(array $set, array $subset): bool
{
return !array_diff($subset, array_intersect($subset, $set));
}
@@ -323,7 +324,7 @@ class Apriori implements Associator
* @param mixed[] $set1
* @param mixed[] $set2
*/
- private function equals(array $set1, array $set2) : bool
+ private function equals(array $set1, array $set2): bool
{
return array_diff($set1, $set2) == array_diff($set2, $set1);
}
diff --git a/src/Phpml/Classification/DecisionTree.php b/src/Phpml/Classification/DecisionTree.php
index 653b1bf..5bb730b 100644
--- a/src/Phpml/Classification/DecisionTree.php
+++ b/src/Phpml/Classification/DecisionTree.php
@@ -15,22 +15,18 @@ class DecisionTree implements Classifier
use Trainable, Predictable;
public const CONTINUOUS = 1;
+
public const NOMINAL = 2;
- /**
- * @var array
- */
- protected $columnTypes;
-
- /**
- * @var array
- */
- private $labels = [];
-
/**
* @var int
*/
- private $featureCount = 0;
+ public $actualDepth = 0;
+
+ /**
+ * @var array
+ */
+ protected $columnTypes = [];
/**
* @var DecisionTreeLeaf
@@ -42,10 +38,15 @@ class DecisionTree implements Classifier
*/
protected $maxDepth;
+ /**
+ * @var array
+ */
+ private $labels = [];
+
/**
* @var int
*/
- public $actualDepth = 0;
+ private $featureCount = 0;
/**
* @var int
@@ -55,7 +56,7 @@ class DecisionTree implements Classifier
/**
* @var array
*/
- private $selectedFeatures;
+ private $selectedFeatures = [];
/**
* @var array
@@ -100,7 +101,7 @@ class DecisionTree implements Classifier
}
}
- public static function getColumnTypes(array $samples) : array
+ public static function getColumnTypes(array $samples): array
{
$types = [];
$featureCount = count($samples[0]);
@@ -113,7 +114,122 @@ class DecisionTree implements Classifier
return $types;
}
- protected function getSplitLeaf(array $records, int $depth = 0) : DecisionTreeLeaf
+ /**
+ * @param mixed $baseValue
+ */
+ public function getGiniIndex($baseValue, array $colValues, array $targets): float
+ {
+ $countMatrix = [];
+ foreach ($this->labels as $label) {
+ $countMatrix[$label] = [0, 0];
+ }
+
+ foreach ($colValues as $index => $value) {
+ $label = $targets[$index];
+ $rowIndex = $value === $baseValue ? 0 : 1;
+ ++$countMatrix[$label][$rowIndex];
+ }
+
+ $giniParts = [0, 0];
+ for ($i = 0; $i <= 1; ++$i) {
+ $part = 0;
+ $sum = array_sum(array_column($countMatrix, $i));
+ if ($sum > 0) {
+ foreach ($this->labels as $label) {
+ $part += pow($countMatrix[$label][$i] / (float) $sum, 2);
+ }
+ }
+
+ $giniParts[$i] = (1 - $part) * $sum;
+ }
+
+ return array_sum($giniParts) / count($colValues);
+ }
+
+ /**
+ * This method is used to set number of columns to be used
+ * when deciding a split at an internal node of the tree.
+ * If the value is given 0, then all features are used (default behaviour),
+ * otherwise the given value will be used as a maximum for number of columns
+ * randomly selected for each split operation.
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException
+ */
+ public function setNumFeatures(int $numFeatures)
+ {
+ if ($numFeatures < 0) {
+ throw new InvalidArgumentException('Selected column count should be greater or equal to zero');
+ }
+
+ $this->numUsableFeatures = $numFeatures;
+
+ return $this;
+ }
+
+ /**
+ * A string array to represent columns. Useful when HTML output or
+ * column importances are desired to be inspected.
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException
+ */
+ public function setColumnNames(array $names)
+ {
+ if ($this->featureCount !== 0 && count($names) !== $this->featureCount) {
+ throw new InvalidArgumentException(sprintf('Length of the given array should be equal to feature count %s', $this->featureCount));
+ }
+
+ $this->columnNames = $names;
+
+ return $this;
+ }
+
+ public function getHtml(): string
+ {
+ return $this->tree->getHTML($this->columnNames);
+ }
+
+ /**
+ * This will return an array including an importance value for
+ * each column in the given dataset. The importance values are
+ * normalized and their total makes 1.
+ */
+ public function getFeatureImportances(): array
+ {
+ if ($this->featureImportances !== null) {
+ return $this->featureImportances;
+ }
+
+ $sampleCount = count($this->samples);
+ $this->featureImportances = [];
+ foreach ($this->columnNames as $column => $columnName) {
+ $nodes = $this->getSplitNodesByColumn($column, $this->tree);
+
+ $importance = 0;
+ foreach ($nodes as $node) {
+ $importance += $node->getNodeImpurityDecrease($sampleCount);
+ }
+
+ $this->featureImportances[$columnName] = $importance;
+ }
+
+ // Normalize & sort the importances
+ $total = array_sum($this->featureImportances);
+ if ($total > 0) {
+ foreach ($this->featureImportances as &$importance) {
+ $importance /= $total;
+ }
+
+ arsort($this->featureImportances);
+ }
+
+ return $this->featureImportances;
+ }
+
+ protected function getSplitLeaf(array $records, int $depth = 0): DecisionTreeLeaf
{
$split = $this->getBestSplit($records);
$split->level = $depth;
@@ -136,6 +252,7 @@ class DecisionTree implements Classifier
if ($prevRecord && $prevRecord != $record) {
$allSame = false;
}
+
$prevRecord = $record;
// According to the split criteron, this record will
@@ -163,6 +280,7 @@ class DecisionTree implements Classifier
if ($leftRecords) {
$split->leftLeaf = $this->getSplitLeaf($leftRecords, $depth + 1);
}
+
if ($rightRecords) {
$split->rightLeaf = $this->getSplitLeaf($rightRecords, $depth + 1);
}
@@ -171,7 +289,7 @@ class DecisionTree implements Classifier
return $split;
}
- protected function getBestSplit(array $records) : DecisionTreeLeaf
+ protected function getBestSplit(array $records): DecisionTreeLeaf
{
$targets = array_intersect_key($this->targets, array_flip($records));
$samples = array_intersect_key($this->samples, array_flip($records));
@@ -184,6 +302,7 @@ class DecisionTree implements Classifier
foreach ($samples as $index => $row) {
$colValues[$index] = $row[$i];
}
+
$counts = array_count_values($colValues);
arsort($counts);
$baseValue = key($counts);
@@ -227,7 +346,7 @@ class DecisionTree implements Classifier
* If any of above methods were not called beforehand, then all features
* are returned by default.
*/
- protected function getSelectedFeatures() : array
+ protected function getSelectedFeatures(): array
{
$allFeatures = range(0, $this->featureCount - 1);
if ($this->numUsableFeatures === 0 && !$this->selectedFeatures) {
@@ -242,6 +361,7 @@ class DecisionTree implements Classifier
if ($numFeatures > $this->featureCount) {
$numFeatures = $this->featureCount;
}
+
shuffle($allFeatures);
$selectedFeatures = array_slice($allFeatures, 0, $numFeatures, false);
sort($selectedFeatures);
@@ -249,39 +369,7 @@ class DecisionTree implements Classifier
return $selectedFeatures;
}
- /**
- * @param mixed $baseValue
- */
- public function getGiniIndex($baseValue, array $colValues, array $targets) : float
- {
- $countMatrix = [];
- foreach ($this->labels as $label) {
- $countMatrix[$label] = [0, 0];
- }
-
- foreach ($colValues as $index => $value) {
- $label = $targets[$index];
- $rowIndex = $value === $baseValue ? 0 : 1;
- ++$countMatrix[$label][$rowIndex];
- }
-
- $giniParts = [0, 0];
- for ($i = 0; $i <= 1; ++$i) {
- $part = 0;
- $sum = array_sum(array_column($countMatrix, $i));
- if ($sum > 0) {
- foreach ($this->labels as $label) {
- $part += pow($countMatrix[$label][$i] / (float) $sum, 2);
- }
- }
-
- $giniParts[$i] = (1 - $part) * $sum;
- }
-
- return array_sum($giniParts) / count($colValues);
- }
-
- protected function preprocess(array $samples) : array
+ protected function preprocess(array $samples): array
{
// Detect and convert continuous data column values into
// discrete values by using the median as a threshold value
@@ -298,14 +386,16 @@ class DecisionTree implements Classifier
}
}
}
+
$columns[] = $values;
}
+
// Below method is a strange yet very simple & efficient method
// to get the transpose of a 2D array
return array_map(null, ...$columns);
}
- protected static function isCategoricalColumn(array $columnValues) : bool
+ protected static function isCategoricalColumn(array $columnValues): bool
{
$count = count($columnValues);
@@ -329,28 +419,6 @@ class DecisionTree implements Classifier
return count($distinctValues) <= $count / 5;
}
- /**
- * This method is used to set number of columns to be used
- * when deciding a split at an internal node of the tree.
- * If the value is given 0, then all features are used (default behaviour),
- * otherwise the given value will be used as a maximum for number of columns
- * randomly selected for each split operation.
- *
- * @return $this
- *
- * @throws InvalidArgumentException
- */
- public function setNumFeatures(int $numFeatures)
- {
- if ($numFeatures < 0) {
- throw new InvalidArgumentException('Selected column count should be greater or equal to zero');
- }
-
- $this->numUsableFeatures = $numFeatures;
-
- return $this;
- }
-
/**
* Used to set predefined features to consider while deciding which column to use for a split
*/
@@ -359,71 +427,11 @@ class DecisionTree implements Classifier
$this->selectedFeatures = $selectedFeatures;
}
- /**
- * A string array to represent columns. Useful when HTML output or
- * column importances are desired to be inspected.
- *
- * @return $this
- *
- * @throws InvalidArgumentException
- */
- public function setColumnNames(array $names)
- {
- if ($this->featureCount !== 0 && count($names) !== $this->featureCount) {
- throw new InvalidArgumentException(sprintf('Length of the given array should be equal to feature count %s', $this->featureCount));
- }
-
- $this->columnNames = $names;
-
- return $this;
- }
-
- public function getHtml() : string
- {
- return $this->tree->getHTML($this->columnNames);
- }
-
- /**
- * This will return an array including an importance value for
- * each column in the given dataset. The importance values are
- * normalized and their total makes 1.
- */
- public function getFeatureImportances() : array
- {
- if ($this->featureImportances !== null) {
- return $this->featureImportances;
- }
-
- $sampleCount = count($this->samples);
- $this->featureImportances = [];
- foreach ($this->columnNames as $column => $columnName) {
- $nodes = $this->getSplitNodesByColumn($column, $this->tree);
-
- $importance = 0;
- foreach ($nodes as $node) {
- $importance += $node->getNodeImpurityDecrease($sampleCount);
- }
-
- $this->featureImportances[$columnName] = $importance;
- }
-
- // Normalize & sort the importances
- $total = array_sum($this->featureImportances);
- if ($total > 0) {
- foreach ($this->featureImportances as &$importance) {
- $importance /= $total;
- }
- arsort($this->featureImportances);
- }
-
- return $this->featureImportances;
- }
-
/**
* Collects and returns an array of internal nodes that use the given
* column as a split criterion
*/
- protected function getSplitNodesByColumn(int $column, DecisionTreeLeaf $node) : array
+ protected function getSplitNodesByColumn(int $column, DecisionTreeLeaf $node): array
{
if (!$node || $node->isTerminal) {
return [];
diff --git a/src/Phpml/Classification/DecisionTree/DecisionTreeLeaf.php b/src/Phpml/Classification/DecisionTree/DecisionTreeLeaf.php
index 2bcc3ac..f3f9449 100644
--- a/src/Phpml/Classification/DecisionTree/DecisionTreeLeaf.php
+++ b/src/Phpml/Classification/DecisionTree/DecisionTreeLeaf.php
@@ -71,7 +71,15 @@ class DecisionTreeLeaf
*/
public $level = 0;
- public function evaluate(array $record) : bool
+ /**
+ * HTML representation of the tree without column names
+ */
+ public function __toString(): string
+ {
+ return $this->getHTML();
+ }
+
+ public function evaluate(array $record): bool
{
$recordField = $record[$this->columnIndex];
@@ -86,7 +94,7 @@ class DecisionTreeLeaf
* Returns Mean Decrease Impurity (MDI) in the node.
* For terminal nodes, this value is equal to 0
*/
- public function getNodeImpurityDecrease(int $parentRecordCount) : float
+ public function getNodeImpurityDecrease(int $parentRecordCount): float
{
if ($this->isTerminal) {
return 0.0;
@@ -111,7 +119,7 @@ class DecisionTreeLeaf
/**
* Returns HTML representation of the node including children nodes
*/
- public function getHTML($columnNames = null) : string
+ public function getHTML($columnNames = null): string
{
if ($this->isTerminal) {
$value = "$this->classValue";
@@ -154,12 +162,4 @@ class DecisionTreeLeaf
return $str;
}
-
- /**
- * HTML representation of the tree without column names
- */
- public function __toString() : string
- {
- return $this->getHTML();
- }
}
diff --git a/src/Phpml/Classification/Ensemble/AdaBoost.php b/src/Phpml/Classification/Ensemble/AdaBoost.php
index 5bdca1b..67f7198 100644
--- a/src/Phpml/Classification/Ensemble/AdaBoost.php
+++ b/src/Phpml/Classification/Ensemble/AdaBoost.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\Classification\Ensemble;
+use Exception;
use Phpml\Classification\Classifier;
use Phpml\Classification\Linear\DecisionStump;
use Phpml\Classification\WeightedClassifier;
@@ -11,6 +12,7 @@ use Phpml\Helper\Predictable;
use Phpml\Helper\Trainable;
use Phpml\Math\Statistic\Mean;
use Phpml\Math\Statistic\StandardDeviation;
+use ReflectionClass;
class AdaBoost implements Classifier
{
@@ -98,11 +100,14 @@ class AdaBoost implements Classifier
// Initialize usual variables
$this->labels = array_keys(array_count_values($targets));
if (count($this->labels) != 2) {
- throw new \Exception('AdaBoost is a binary classifier and can classify between two classes only');
+ throw new Exception('AdaBoost is a binary classifier and can classify between two classes only');
}
// Set all target values to either -1 or 1
- $this->labels = [1 => $this->labels[0], -1 => $this->labels[1]];
+ $this->labels = [
+ 1 => $this->labels[0],
+ -1 => $this->labels[1],
+ ];
foreach ($targets as $target) {
$this->targets[] = $target == $this->labels[1] ? 1 : -1;
}
@@ -132,13 +137,27 @@ class AdaBoost implements Classifier
}
}
+ /**
+ * @return mixed
+ */
+ public function predictSample(array $sample)
+ {
+ $sum = 0;
+ foreach ($this->alpha as $index => $alpha) {
+ $h = $this->classifiers[$index]->predict($sample);
+ $sum += $h * $alpha;
+ }
+
+ return $this->labels[$sum > 0 ? 1 : -1];
+ }
+
/**
* Returns the classifier with the lowest error rate with the
* consideration of current sample weights
*/
- protected function getBestClassifier() : Classifier
+ protected function getBestClassifier(): Classifier
{
- $ref = new \ReflectionClass($this->baseClassifier);
+ $ref = new ReflectionClass($this->baseClassifier);
if ($this->classifierOptions) {
$classifier = $ref->newInstanceArgs($this->classifierOptions);
} else {
@@ -160,7 +179,7 @@ class AdaBoost implements Classifier
* Resamples the dataset in accordance with the weights and
* returns the new dataset
*/
- protected function resample() : array
+ protected function resample(): array
{
$weights = $this->weights;
$std = StandardDeviation::population($weights);
@@ -173,9 +192,10 @@ class AdaBoost implements Classifier
foreach ($weights as $index => $weight) {
$z = (int) round(($weight - $mean) / $std) - $minZ + 1;
for ($i = 0; $i < $z; ++$i) {
- if (rand(0, 1) == 0) {
+ if (random_int(0, 1) == 0) {
continue;
}
+
$samples[] = $this->samples[$index];
$targets[] = $this->targets[$index];
}
@@ -187,7 +207,7 @@ class AdaBoost implements Classifier
/**
* Evaluates the classifier and returns the classification error rate
*/
- protected function evaluateClassifier(Classifier $classifier) : float
+ protected function evaluateClassifier(Classifier $classifier): float
{
$total = (float) array_sum($this->weights);
$wrong = 0;
@@ -204,7 +224,7 @@ class AdaBoost implements Classifier
/**
* Calculates alpha of a classifier
*/
- protected function calculateAlpha(float $errorRate) : float
+ protected function calculateAlpha(float $errorRate): float
{
if ($errorRate == 0) {
$errorRate = 1e-10;
@@ -231,18 +251,4 @@ class AdaBoost implements Classifier
$this->weights = $weightsT1;
}
-
- /**
- * @return mixed
- */
- public function predictSample(array $sample)
- {
- $sum = 0;
- foreach ($this->alpha as $index => $alpha) {
- $h = $this->classifiers[$index]->predict($sample);
- $sum += $h * $alpha;
- }
-
- return $this->labels[$sum > 0 ? 1 : -1];
- }
}
diff --git a/src/Phpml/Classification/Ensemble/Bagging.php b/src/Phpml/Classification/Ensemble/Bagging.php
index 8d2bbf9..6fa1ec8 100644
--- a/src/Phpml/Classification/Ensemble/Bagging.php
+++ b/src/Phpml/Classification/Ensemble/Bagging.php
@@ -4,10 +4,12 @@ declare(strict_types=1);
namespace Phpml\Classification\Ensemble;
+use Exception;
use Phpml\Classification\Classifier;
use Phpml\Classification\DecisionTree;
use Phpml\Helper\Predictable;
use Phpml\Helper\Trainable;
+use ReflectionClass;
class Bagging implements Classifier
{
@@ -18,11 +20,6 @@ class Bagging implements Classifier
*/
protected $numSamples;
- /**
- * @var array
- */
- private $targets = [];
-
/**
* @var int
*/
@@ -46,13 +43,18 @@ class Bagging implements Classifier
/**
* @var array
*/
- protected $classifiers;
+ protected $classifiers = [];
/**
* @var float
*/
protected $subsetRatio = 0.7;
+ /**
+ * @var array
+ */
+ private $targets = [];
+
/**
* @var array
*/
@@ -80,7 +82,7 @@ class Bagging implements Classifier
public function setSubsetRatio(float $ratio)
{
if ($ratio < 0.1 || $ratio > 1.0) {
- throw new \Exception('Subset ratio should be between 0.1 and 1.0');
+ throw new Exception('Subset ratio should be between 0.1 and 1.0');
}
$this->subsetRatio = $ratio;
@@ -123,14 +125,14 @@ class Bagging implements Classifier
}
}
- protected function getRandomSubset(int $index) : array
+ protected function getRandomSubset(int $index): array
{
$samples = [];
$targets = [];
srand($index);
$bootstrapSize = $this->subsetRatio * $this->numSamples;
for ($i = 0; $i < $bootstrapSize; ++$i) {
- $rand = rand(0, $this->numSamples - 1);
+ $rand = random_int(0, $this->numSamples - 1);
$samples[] = $this->samples[$rand];
$targets[] = $this->targets[$rand];
}
@@ -138,11 +140,11 @@ class Bagging implements Classifier
return [$samples, $targets];
}
- protected function initClassifiers() : array
+ protected function initClassifiers(): array
{
$classifiers = [];
for ($i = 0; $i < $this->numClassifier; ++$i) {
- $ref = new \ReflectionClass($this->classifier);
+ $ref = new ReflectionClass($this->classifier);
if ($this->classifierOptions) {
$obj = $ref->newInstanceArgs($this->classifierOptions);
} else {
@@ -155,12 +157,7 @@ class Bagging implements Classifier
return $classifiers;
}
- /**
- * @param Classifier $classifier
- *
- * @return Classifier
- */
- protected function initSingleClassifier($classifier)
+ protected function initSingleClassifier(Classifier $classifier): Classifier
{
return $classifier;
}
diff --git a/src/Phpml/Classification/Ensemble/RandomForest.php b/src/Phpml/Classification/Ensemble/RandomForest.php
index 4928ea5..59f19c1 100644
--- a/src/Phpml/Classification/Ensemble/RandomForest.php
+++ b/src/Phpml/Classification/Ensemble/RandomForest.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Classification\Ensemble;
+use Exception;
+use Phpml\Classification\Classifier;
use Phpml\Classification\DecisionTree;
class RandomForest extends Bagging
@@ -48,11 +50,11 @@ class RandomForest extends Bagging
public function setFeatureSubsetRatio($ratio)
{
if (is_float($ratio) && ($ratio < 0.1 || $ratio > 1.0)) {
- throw new \Exception('When a float given, feature subset ratio should be between 0.1 and 1.0');
+ throw new Exception('When a float given, feature subset ratio should be between 0.1 and 1.0');
}
if (is_string($ratio) && $ratio != 'sqrt' && $ratio != 'log') {
- throw new \Exception("When a string given, feature subset ratio can only be 'sqrt' or 'log' ");
+ throw new Exception("When a string given, feature subset ratio can only be 'sqrt' or 'log' ");
}
$this->featureSubsetRatio = $ratio;
@@ -70,7 +72,7 @@ class RandomForest extends Bagging
public function setClassifer(string $classifier, array $classifierOptions = [])
{
if ($classifier != DecisionTree::class) {
- throw new \Exception('RandomForest can only use DecisionTree as base classifier');
+ throw new Exception('RandomForest can only use DecisionTree as base classifier');
}
return parent::setClassifer($classifier, $classifierOptions);
@@ -81,7 +83,7 @@ class RandomForest extends Bagging
* each column in the given dataset. Importance values for a column
* is the average importance of that column in all trees in the forest
*/
- public function getFeatureImportances() : array
+ public function getFeatureImportances(): array
{
// Traverse each tree and sum importance of the columns
$sum = [];
@@ -127,7 +129,7 @@ class RandomForest extends Bagging
*
* @return DecisionTree
*/
- protected function initSingleClassifier($classifier)
+ protected function initSingleClassifier(Classifier $classifier): Classifier
{
if (is_float($this->featureSubsetRatio)) {
$featureCount = (int) ($this->featureSubsetRatio * $this->featureCount);
diff --git a/src/Phpml/Classification/KNearestNeighbors.php b/src/Phpml/Classification/KNearestNeighbors.php
index a261631..238fc1d 100644
--- a/src/Phpml/Classification/KNearestNeighbors.php
+++ b/src/Phpml/Classification/KNearestNeighbors.php
@@ -28,7 +28,7 @@ class KNearestNeighbors implements Classifier
*/
public function __construct(int $k = 3, ?Distance $distanceMetric = null)
{
- if (null === $distanceMetric) {
+ if ($distanceMetric === null) {
$distanceMetric = new Euclidean();
}
@@ -60,7 +60,7 @@ class KNearestNeighbors implements Classifier
/**
* @throws \Phpml\Exception\InvalidArgumentException
*/
- private function kNeighborsDistances(array $sample) : array
+ private function kNeighborsDistances(array $sample): array
{
$distances = [];
diff --git a/src/Phpml/Classification/Linear/Adaline.php b/src/Phpml/Classification/Linear/Adaline.php
index 64d25a4..cda746f 100644
--- a/src/Phpml/Classification/Linear/Adaline.php
+++ b/src/Phpml/Classification/Linear/Adaline.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
+use Exception;
+
class Adaline extends Perceptron
{
/**
@@ -41,7 +43,7 @@ class Adaline extends Perceptron
int $trainingType = self::BATCH_TRAINING
) {
if (!in_array($trainingType, [self::BATCH_TRAINING, self::ONLINE_TRAINING])) {
- throw new \Exception('Adaline can only be trained with batch and online/stochastic gradient descent algorithm');
+ throw new Exception('Adaline can only be trained with batch and online/stochastic gradient descent algorithm');
}
$this->trainingType = $trainingType;
diff --git a/src/Phpml/Classification/Linear/DecisionStump.php b/src/Phpml/Classification/Linear/DecisionStump.php
index e1486a6..3f6eb58 100644
--- a/src/Phpml/Classification/Linear/DecisionStump.php
+++ b/src/Phpml/Classification/Linear/DecisionStump.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
+use Exception;
use Phpml\Classification\DecisionTree;
use Phpml\Classification\WeightedClassifier;
use Phpml\Helper\OneVsRest;
@@ -24,7 +25,7 @@ class DecisionStump extends WeightedClassifier
/**
* @var array
*/
- protected $binaryLabels;
+ protected $binaryLabels = [];
/**
* Lowest error rate obtained while training/optimizing the model
@@ -51,7 +52,7 @@ class DecisionStump extends WeightedClassifier
/**
* @var array
*/
- protected $columnTypes;
+ protected $columnTypes = [];
/**
* @var int
@@ -68,7 +69,7 @@ class DecisionStump extends WeightedClassifier
*
* @var array
*/
- protected $prob;
+ protected $prob = [];
/**
* A DecisionStump classifier is a one-level deep DecisionTree. It is generally
@@ -83,6 +84,25 @@ class DecisionStump extends WeightedClassifier
$this->givenColumnIndex = $columnIndex;
}
+ public function __toString(): string
+ {
+ return "IF $this->column $this->operator $this->value ".
+ 'THEN '.$this->binaryLabels[0].' '.
+ 'ELSE '.$this->binaryLabels[1];
+ }
+
+ /**
+ * While finding best split point for a numerical valued column,
+ * DecisionStump looks for equally distanced values between minimum and maximum
+ * values in the column. Given $count value determines how many split
+ * points to be probed. The more split counts, the better performance but
+ * worse processing time (Default value is 10.0)
+ */
+ public function setNumericalSplitCount(float $count): void
+ {
+ $this->numSplitCount = $count;
+ }
+
/**
* @throws \Exception
*/
@@ -101,7 +121,7 @@ class DecisionStump extends WeightedClassifier
if ($this->weights) {
$numWeights = count($this->weights);
if ($numWeights != count($samples)) {
- throw new \Exception('Number of sample weights does not match with number of samples');
+ throw new Exception('Number of sample weights does not match with number of samples');
}
} else {
$this->weights = array_fill(0, count($samples), 1);
@@ -118,9 +138,12 @@ class DecisionStump extends WeightedClassifier
}
$bestSplit = [
- 'value' => 0, 'operator' => '',
- 'prob' => [], 'column' => 0,
- 'trainingErrorRate' => 1.0];
+ 'value' => 0,
+ 'operator' => '',
+ 'prob' => [],
+ 'column' => 0,
+ 'trainingErrorRate' => 1.0,
+ ];
foreach ($columns as $col) {
if ($this->columnTypes[$col] == DecisionTree::CONTINUOUS) {
$split = $this->getBestNumericalSplit($samples, $targets, $col);
@@ -139,22 +162,10 @@ class DecisionStump extends WeightedClassifier
}
}
- /**
- * While finding best split point for a numerical valued column,
- * DecisionStump looks for equally distanced values between minimum and maximum
- * values in the column. Given $count value determines how many split
- * points to be probed. The more split counts, the better performance but
- * worse processing time (Default value is 10.0)
- */
- public function setNumericalSplitCount(float $count): void
- {
- $this->numSplitCount = $count;
- }
-
/**
* Determines best split point for the given column
*/
- protected function getBestNumericalSplit(array $samples, array $targets, int $col) : array
+ protected function getBestNumericalSplit(array $samples, array $targets, int $col): array
{
$values = array_column($samples, $col);
// Trying all possible points may be accomplished in two general ways:
@@ -173,9 +184,13 @@ class DecisionStump extends WeightedClassifier
$threshold = array_sum($values) / (float) count($values);
[$errorRate, $prob] = $this->calculateErrorRate($targets, $threshold, $operator, $values);
if ($split == null || $errorRate < $split['trainingErrorRate']) {
- $split = ['value' => $threshold, 'operator' => $operator,
- 'prob' => $prob, 'column' => $col,
- 'trainingErrorRate' => $errorRate];
+ $split = [
+ 'value' => $threshold,
+ 'operator' => $operator,
+ 'prob' => $prob,
+ 'column' => $col,
+ 'trainingErrorRate' => $errorRate,
+ ];
}
// Try other possible points one by one
@@ -183,9 +198,13 @@ class DecisionStump extends WeightedClassifier
$threshold = (float) $step;
[$errorRate, $prob] = $this->calculateErrorRate($targets, $threshold, $operator, $values);
if ($errorRate < $split['trainingErrorRate']) {
- $split = ['value' => $threshold, 'operator' => $operator,
- 'prob' => $prob, 'column' => $col,
- 'trainingErrorRate' => $errorRate];
+ $split = [
+ 'value' => $threshold,
+ 'operator' => $operator,
+ 'prob' => $prob,
+ 'column' => $col,
+ 'trainingErrorRate' => $errorRate,
+ ];
}
}// for
}
@@ -193,7 +212,7 @@ class DecisionStump extends WeightedClassifier
return $split;
}
- protected function getBestNominalSplit(array $samples, array $targets, int $col) : array
+ protected function getBestNominalSplit(array $samples, array $targets, int $col): array
{
$values = array_column($samples, $col);
$valueCounts = array_count_values($values);
@@ -206,9 +225,13 @@ class DecisionStump extends WeightedClassifier
[$errorRate, $prob] = $this->calculateErrorRate($targets, $val, $operator, $values);
if ($split == null || $split['trainingErrorRate'] < $errorRate) {
- $split = ['value' => $val, 'operator' => $operator,
- 'prob' => $prob, 'column' => $col,
- 'trainingErrorRate' => $errorRate];
+ $split = [
+ 'value' => $val,
+ 'operator' => $operator,
+ 'prob' => $prob,
+ 'column' => $col,
+ 'trainingErrorRate' => $errorRate,
+ ];
}
}
}
@@ -220,7 +243,7 @@ class DecisionStump extends WeightedClassifier
* Calculates the ratio of wrong predictions based on the new threshold
* value given as the parameter
*/
- protected function calculateErrorRate(array $targets, float $threshold, string $operator, array $values) : array
+ protected function calculateErrorRate(array $targets, float $threshold, string $operator, array $values): array
{
$wrong = 0.0;
$prob = [];
@@ -242,6 +265,7 @@ class DecisionStump extends WeightedClassifier
if (!isset($prob[$predicted][$target])) {
$prob[$predicted][$target] = 0;
}
+
++$prob[$predicted][$target];
}
@@ -267,7 +291,7 @@ class DecisionStump extends WeightedClassifier
*
* @param mixed $label
*/
- protected function predictProbability(array $sample, $label) : float
+ protected function predictProbability(array $sample, $label): float
{
$predicted = $this->predictSampleBinary($sample);
if ((string) $predicted == (string) $label) {
@@ -292,11 +316,4 @@ class DecisionStump extends WeightedClassifier
protected function resetBinary(): void
{
}
-
- public function __toString() : string
- {
- return "IF $this->column $this->operator $this->value ".
- 'THEN '.$this->binaryLabels[0].' '.
- 'ELSE '.$this->binaryLabels[1];
- }
}
diff --git a/src/Phpml/Classification/Linear/LogisticRegression.php b/src/Phpml/Classification/Linear/LogisticRegression.php
index e8881be..6b8cdd5 100644
--- a/src/Phpml/Classification/Linear/LogisticRegression.php
+++ b/src/Phpml/Classification/Linear/LogisticRegression.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
+use Closure;
+use Exception;
use Phpml\Helper\Optimizer\ConjugateGradient;
class LogisticRegression extends Adaline
@@ -70,18 +72,18 @@ class LogisticRegression extends Adaline
) {
$trainingTypes = range(self::BATCH_TRAINING, self::CONJUGATE_GRAD_TRAINING);
if (!in_array($trainingType, $trainingTypes)) {
- throw new \Exception('Logistic regression can only be trained with '.
+ throw new Exception('Logistic regression can only be trained with '.
'batch (gradient descent), online (stochastic gradient descent) '.
'or conjugate batch (conjugate gradients) algorithms');
}
if (!in_array($cost, ['log', 'sse'])) {
- throw new \Exception("Logistic regression cost function can be one of the following: \n".
+ throw new Exception("Logistic regression cost function can be one of the following: \n".
"'log' for log-likelihood and 'sse' for sum of squared errors");
}
if ($penalty != '' && strtoupper($penalty) !== 'L2') {
- throw new \Exception("Logistic regression supports only 'L2' regularization");
+ throw new Exception("Logistic regression supports only 'L2' regularization");
}
$this->learningRate = 0.001;
@@ -132,14 +134,14 @@ class LogisticRegression extends Adaline
return $this->runConjugateGradient($samples, $targets, $callback);
default:
- throw new \Exception('Logistic regression has invalid training type: %s.', $this->trainingType);
+ throw new Exception('Logistic regression has invalid training type: %s.', $this->trainingType);
}
}
/**
* Executes Conjugate Gradient method to optimize the weights of the LogReg model
*/
- protected function runConjugateGradient(array $samples, array $targets, \Closure $gradientFunc): void
+ protected function runConjugateGradient(array $samples, array $targets, Closure $gradientFunc): void
{
if (empty($this->optimizer)) {
$this->optimizer = (new ConjugateGradient($this->featureCount))
@@ -155,7 +157,7 @@ class LogisticRegression extends Adaline
*
* @throws \Exception
*/
- protected function getCostFunction() : \Closure
+ protected function getCostFunction(): Closure
{
$penalty = 0;
if ($this->penalty == 'L2') {
@@ -183,9 +185,11 @@ class LogisticRegression extends Adaline
if ($hX == 1) {
$hX = 1 - 1e-10;
}
+
if ($hX == 0) {
$hX = 1e-10;
}
+
$error = -$y * log($hX) - (1 - $y) * log(1 - $hX);
$gradient = $hX - $y;
@@ -218,16 +222,14 @@ class LogisticRegression extends Adaline
return $callback;
default:
- throw new \Exception(sprintf('Logistic regression has invalid cost function: %s.', $this->costFunction));
+ throw new Exception(sprintf('Logistic regression has invalid cost function: %s.', $this->costFunction));
}
}
/**
* Returns the output of the network, a float value between 0.0 and 1.0
- *
- * @return float
*/
- protected function output(array $sample)
+ protected function output(array $sample): float
{
$sum = parent::output($sample);
@@ -237,7 +239,7 @@ class LogisticRegression extends Adaline
/**
* Returns the class value (either -1 or 1) for the given input
*/
- protected function outputClass(array $sample) : int
+ protected function outputClass(array $sample): int
{
$output = $this->output($sample);
@@ -253,10 +255,10 @@ class LogisticRegression extends Adaline
*
* The probability is simply taken as the distance of the sample
* to the decision plane.
-
+ *
* @param mixed $label
*/
- protected function predictProbability(array $sample, $label) : float
+ protected function predictProbability(array $sample, $label): float
{
$predicted = $this->predictSampleBinary($sample);
diff --git a/src/Phpml/Classification/Linear/Perceptron.php b/src/Phpml/Classification/Linear/Perceptron.php
index 77eb717..0db7496 100644
--- a/src/Phpml/Classification/Linear/Perceptron.php
+++ b/src/Phpml/Classification/Linear/Perceptron.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Classification\Linear;
+use Closure;
+use Exception;
use Phpml\Classification\Classifier;
use Phpml\Helper\OneVsRest;
use Phpml\Helper\Optimizer\GD;
@@ -34,7 +36,7 @@ class Perceptron implements Classifier, IncrementalEstimator
/**
* @var array
*/
- protected $weights;
+ protected $weights = [];
/**
* @var float
@@ -73,11 +75,11 @@ class Perceptron implements Classifier, IncrementalEstimator
public function __construct(float $learningRate = 0.001, int $maxIterations = 1000, bool $normalizeInputs = true)
{
if ($learningRate <= 0.0 || $learningRate > 1.0) {
- throw new \Exception('Learning rate should be a float value between 0.0(exclusive) and 1.0(inclusive)');
+ throw new Exception('Learning rate should be a float value between 0.0(exclusive) and 1.0(inclusive)');
}
if ($maxIterations <= 0) {
- throw new \Exception('Maximum number of iterations must be an integer greater than 0');
+ throw new Exception('Maximum number of iterations must be an integer greater than 0');
}
if ($normalizeInputs) {
@@ -100,7 +102,10 @@ class Perceptron implements Classifier, IncrementalEstimator
}
// Set all target values to either -1 or 1
- $this->labels = [1 => $labels[0], -1 => $labels[1]];
+ $this->labels = [
+ 1 => $labels[0],
+ -1 => $labels[1],
+ ];
foreach ($targets as $key => $target) {
$targets[$key] = (string) $target == (string) $this->labels[1] ? 1 : -1;
}
@@ -111,15 +116,6 @@ class Perceptron implements Classifier, IncrementalEstimator
$this->runTraining($samples, $targets);
}
- protected function resetBinary(): void
- {
- $this->labels = [];
- $this->optimizer = null;
- $this->featureCount = 0;
- $this->weights = null;
- $this->costValues = [];
- }
-
/**
* Normally enabling early stopping for the optimization procedure may
* help saving processing time while in some cases it may result in
@@ -140,16 +136,23 @@ class Perceptron implements Classifier, IncrementalEstimator
/**
* Returns the cost values obtained during the training.
*/
- public function getCostValues() : array
+ public function getCostValues(): array
{
return $this->costValues;
}
+ protected function resetBinary(): void
+ {
+ $this->labels = [];
+ $this->optimizer = null;
+ $this->featureCount = 0;
+ $this->weights = null;
+ $this->costValues = [];
+ }
+
/**
* Trains the perceptron model with Stochastic Gradient Descent optimization
* to get the correct set of weights
- *
- * @return void|mixed
*/
protected function runTraining(array $samples, array $targets)
{
@@ -171,7 +174,7 @@ class Perceptron implements Classifier, IncrementalEstimator
* Executes a Gradient Descent algorithm for
* the given cost function
*/
- protected function runGradientDescent(array $samples, array $targets, \Closure $gradientFunc, bool $isBatch = false): void
+ protected function runGradientDescent(array $samples, array $targets, Closure $gradientFunc, bool $isBatch = false): void
{
$class = $isBatch ? GD::class : StochasticGD::class;
@@ -191,7 +194,7 @@ class Perceptron implements Classifier, IncrementalEstimator
* Checks if the sample should be normalized and if so, returns the
* normalized sample
*/
- protected function checkNormalizedSample(array $sample) : array
+ protected function checkNormalizedSample(array $sample): array
{
if ($this->normalizer) {
$samples = [$sample];
@@ -205,7 +208,7 @@ class Perceptron implements Classifier, IncrementalEstimator
/**
* Calculates net output of the network as a float value for the given input
*
- * @return int
+ * @return int|float
*/
protected function output(array $sample)
{
@@ -224,7 +227,7 @@ class Perceptron implements Classifier, IncrementalEstimator
/**
* Returns the class value (either -1 or 1) for the given input
*/
- protected function outputClass(array $sample) : int
+ protected function outputClass(array $sample): int
{
return $this->output($sample) > 0 ? 1 : -1;
}
@@ -237,7 +240,7 @@ class Perceptron implements Classifier, IncrementalEstimator
*
* @param mixed $label
*/
- protected function predictProbability(array $sample, $label) : float
+ protected function predictProbability(array $sample, $label): float
{
$predicted = $this->predictSampleBinary($sample);
diff --git a/src/Phpml/Classification/MLPClassifier.php b/src/Phpml/Classification/MLPClassifier.php
index b76091d..b225a64 100644
--- a/src/Phpml/Classification/MLPClassifier.php
+++ b/src/Phpml/Classification/MLPClassifier.php
@@ -14,7 +14,7 @@ class MLPClassifier extends MultilayerPerceptron implements Classifier
*
* @throws InvalidArgumentException
*/
- public function getTargetClass($target) : int
+ public function getTargetClass($target): int
{
if (!in_array($target, $this->classes)) {
throw InvalidArgumentException::invalidTarget($target);
diff --git a/src/Phpml/Classification/NaiveBayes.php b/src/Phpml/Classification/NaiveBayes.php
index 97f734a..a470fd4 100644
--- a/src/Phpml/Classification/NaiveBayes.php
+++ b/src/Phpml/Classification/NaiveBayes.php
@@ -14,7 +14,9 @@ class NaiveBayes implements Classifier
use Trainable, Predictable;
public const CONTINUOS = 1;
+
public const NOMINAL = 2;
+
public const EPSILON = 1e-10;
/**
@@ -73,6 +75,31 @@ class NaiveBayes implements Classifier
}
}
+ /**
+ * @return mixed
+ */
+ protected function predictSample(array $sample)
+ {
+ // Use NaiveBayes assumption for each label using:
+ // P(label|features) = P(label) * P(feature0|label) * P(feature1|label) .... P(featureN|label)
+ // Then compare probability for each class to determine which label is most likely
+ $predictions = [];
+ foreach ($this->labels as $label) {
+ $p = $this->p[$label];
+ for ($i = 0; $i < $this->featureCount; ++$i) {
+ $Plf = $this->sampleProbability($sample, $i, $label);
+ $p += $Plf;
+ }
+
+ $predictions[$label] = $p;
+ }
+
+ arsort($predictions, SORT_NUMERIC);
+ reset($predictions);
+
+ return key($predictions);
+ }
+
/**
* Calculates vital statistics for each label & feature. Stores these
* values in private array in order to avoid repeated calculation
@@ -108,7 +135,7 @@ class NaiveBayes implements Classifier
/**
* Calculates the probability P(label|sample_n)
*/
- private function sampleProbability(array $sample, int $feature, string $label) : float
+ private function sampleProbability(array $sample, int $feature, string $label): float
{
$value = $sample[$feature];
if ($this->dataType[$label][$feature] == self::NOMINAL) {
@@ -119,6 +146,7 @@ class NaiveBayes implements Classifier
return $this->discreteProb[$label][$feature][$value];
}
+
$std = $this->std[$label][$feature] ;
$mean = $this->mean[$label][$feature];
// Calculate the probability density by use of normal/Gaussian distribution
@@ -137,7 +165,7 @@ class NaiveBayes implements Classifier
/**
* Return samples belonging to specific label
*/
- private function getSamplesByLabel(string $label) : array
+ private function getSamplesByLabel(string $label): array
{
$samples = [];
for ($i = 0; $i < $this->sampleCount; ++$i) {
@@ -148,28 +176,4 @@ class NaiveBayes implements Classifier
return $samples;
}
-
- /**
- * @return mixed
- */
- protected function predictSample(array $sample)
- {
- // Use NaiveBayes assumption for each label using:
- // P(label|features) = P(label) * P(feature0|label) * P(feature1|label) .... P(featureN|label)
- // Then compare probability for each class to determine which label is most likely
- $predictions = [];
- foreach ($this->labels as $label) {
- $p = $this->p[$label];
- for ($i = 0; $i < $this->featureCount; ++$i) {
- $Plf = $this->sampleProbability($sample, $i, $label);
- $p += $Plf;
- }
- $predictions[$label] = $p;
- }
-
- arsort($predictions, SORT_NUMERIC);
- reset($predictions);
-
- return key($predictions);
- }
}
diff --git a/src/Phpml/Classification/WeightedClassifier.php b/src/Phpml/Classification/WeightedClassifier.php
index c9b1f97..9834764 100644
--- a/src/Phpml/Classification/WeightedClassifier.php
+++ b/src/Phpml/Classification/WeightedClassifier.php
@@ -9,7 +9,7 @@ abstract class WeightedClassifier implements Classifier
/**
* @var array
*/
- protected $weights;
+ protected $weights = [];
/**
* Sets the array including a weight for each sample
diff --git a/src/Phpml/Clustering/Clusterer.php b/src/Phpml/Clustering/Clusterer.php
index ad24af2..22e65e6 100644
--- a/src/Phpml/Clustering/Clusterer.php
+++ b/src/Phpml/Clustering/Clusterer.php
@@ -6,5 +6,5 @@ namespace Phpml\Clustering;
interface Clusterer
{
- public function cluster(array $samples) : array;
+ public function cluster(array $samples): array;
}
diff --git a/src/Phpml/Clustering/DBSCAN.php b/src/Phpml/Clustering/DBSCAN.php
index 1968b83..3546ebf 100644
--- a/src/Phpml/Clustering/DBSCAN.php
+++ b/src/Phpml/Clustering/DBSCAN.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\Clustering;
+use array_merge;
use Phpml\Math\Distance;
use Phpml\Math\Distance\Euclidean;
@@ -26,7 +27,7 @@ class DBSCAN implements Clusterer
public function __construct(float $epsilon = 0.5, int $minSamples = 3, ?Distance $distanceMetric = null)
{
- if (null === $distanceMetric) {
+ if ($distanceMetric === null) {
$distanceMetric = new Euclidean();
}
@@ -35,7 +36,7 @@ class DBSCAN implements Clusterer
$this->distanceMetric = $distanceMetric;
}
- public function cluster(array $samples) : array
+ public function cluster(array $samples): array
{
$clusters = [];
$visited = [];
@@ -44,6 +45,7 @@ class DBSCAN implements Clusterer
if (isset($visited[$index])) {
continue;
}
+
$visited[$index] = true;
$regionSamples = $this->getSamplesInRegion($sample, $samples);
@@ -55,7 +57,7 @@ class DBSCAN implements Clusterer
return $clusters;
}
- private function getSamplesInRegion(array $localSample, array $samples) : array
+ private function getSamplesInRegion(array $localSample, array $samples): array
{
$region = [];
@@ -68,7 +70,7 @@ class DBSCAN implements Clusterer
return $region;
}
- private function expandCluster(array $samples, array &$visited) : array
+ private function expandCluster(array $samples, array &$visited): array
{
$cluster = [];
@@ -84,7 +86,8 @@ class DBSCAN implements Clusterer
$cluster[$index] = $sample;
}
- $cluster = \array_merge($cluster, ...$clusterMerge);
+
+ $cluster = array_merge($cluster, ...$clusterMerge);
return $cluster;
}
diff --git a/src/Phpml/Clustering/FuzzyCMeans.php b/src/Phpml/Clustering/FuzzyCMeans.php
index 6eccea0..d3be101 100644
--- a/src/Phpml/Clustering/FuzzyCMeans.php
+++ b/src/Phpml/Clustering/FuzzyCMeans.php
@@ -30,7 +30,7 @@ class FuzzyCMeans implements Clusterer
/**
* @var array|float[][]
*/
- private $membership;
+ private $membership = [];
/**
* @var float
@@ -55,7 +55,7 @@ class FuzzyCMeans implements Clusterer
/**
* @var array
*/
- private $samples;
+ private $samples = [];
/**
* @throws InvalidArgumentException
@@ -65,12 +65,63 @@ class FuzzyCMeans implements Clusterer
if ($clustersNumber <= 0) {
throw InvalidArgumentException::invalidClustersNumber();
}
+
$this->clustersNumber = $clustersNumber;
$this->fuzziness = $fuzziness;
$this->epsilon = $epsilon;
$this->maxIterations = $maxIterations;
}
+ public function getMembershipMatrix(): array
+ {
+ return $this->membership;
+ }
+
+ /**
+ * @param array|Point[] $samples
+ */
+ public function cluster(array $samples): array
+ {
+ // Initialize variables, clusters and membership matrix
+ $this->sampleCount = count($samples);
+ $this->samples = &$samples;
+ $this->space = new Space(count($samples[0]));
+ $this->initClusters();
+
+ // Our goal is minimizing the objective value while
+ // executing the clustering steps at a maximum number of iterations
+ $lastObjective = 0.0;
+ $iterations = 0;
+ do {
+ // Update the membership matrix and cluster centers, respectively
+ $this->updateMembershipMatrix();
+ $this->updateClusters();
+
+ // Calculate the new value of the objective function
+ $objectiveVal = $this->getObjective();
+ $difference = abs($lastObjective - $objectiveVal);
+ $lastObjective = $objectiveVal;
+ } while ($difference > $this->epsilon && $iterations++ <= $this->maxIterations);
+
+ // Attach (hard cluster) each data point to the nearest cluster
+ for ($k = 0; $k < $this->sampleCount; ++$k) {
+ $column = array_column($this->membership, $k);
+ arsort($column);
+ reset($column);
+ $i = key($column);
+ $cluster = $this->clusters[$i];
+ $cluster->attach(new Point($this->samples[$k]));
+ }
+
+ // Return grouped samples
+ $grouped = [];
+ foreach ($this->clusters as $cluster) {
+ $grouped[] = $cluster->getPoints();
+ }
+
+ return $grouped;
+ }
+
protected function initClusters(): void
{
// Membership array is a matrix of cluster number by sample counts
@@ -87,7 +138,7 @@ class FuzzyCMeans implements Clusterer
$row = [];
$total = 0.0;
for ($k = 0; $k < $cols; ++$k) {
- $val = rand(1, 5) / 10.0;
+ $val = random_int(1, 5) / 10.0;
$row[] = $val;
$total += $val;
}
@@ -146,13 +197,13 @@ class FuzzyCMeans implements Clusterer
}
}
- protected function getDistanceCalc(int $row, int $col) : float
+ protected function getDistanceCalc(int $row, int $col): float
{
$sum = 0.0;
$distance = new Euclidean();
$dist1 = $distance->distance(
- $this->clusters[$row]->getCoordinates(),
- $this->samples[$col]
+ $this->clusters[$row]->getCoordinates(),
+ $this->samples[$col]
);
for ($j = 0; $j < $this->clustersNumber; ++$j) {
@@ -187,54 +238,4 @@ class FuzzyCMeans implements Clusterer
return $sum;
}
-
- public function getMembershipMatrix() : array
- {
- return $this->membership;
- }
-
- /**
- * @param array|Point[] $samples
- */
- public function cluster(array $samples) : array
- {
- // Initialize variables, clusters and membership matrix
- $this->sampleCount = count($samples);
- $this->samples = &$samples;
- $this->space = new Space(count($samples[0]));
- $this->initClusters();
-
- // Our goal is minimizing the objective value while
- // executing the clustering steps at a maximum number of iterations
- $lastObjective = 0.0;
- $iterations = 0;
- do {
- // Update the membership matrix and cluster centers, respectively
- $this->updateMembershipMatrix();
- $this->updateClusters();
-
- // Calculate the new value of the objective function
- $objectiveVal = $this->getObjective();
- $difference = abs($lastObjective - $objectiveVal);
- $lastObjective = $objectiveVal;
- } while ($difference > $this->epsilon && $iterations++ <= $this->maxIterations);
-
- // Attach (hard cluster) each data point to the nearest cluster
- for ($k = 0; $k < $this->sampleCount; ++$k) {
- $column = array_column($this->membership, $k);
- arsort($column);
- reset($column);
- $i = key($column);
- $cluster = $this->clusters[$i];
- $cluster->attach(new Point($this->samples[$k]));
- }
-
- // Return grouped samples
- $grouped = [];
- foreach ($this->clusters as $cluster) {
- $grouped[] = $cluster->getPoints();
- }
-
- return $grouped;
- }
}
diff --git a/src/Phpml/Clustering/KMeans.php b/src/Phpml/Clustering/KMeans.php
index a4e85bc..78a2e4a 100644
--- a/src/Phpml/Clustering/KMeans.php
+++ b/src/Phpml/Clustering/KMeans.php
@@ -10,6 +10,7 @@ use Phpml\Exception\InvalidArgumentException;
class KMeans implements Clusterer
{
public const INIT_RANDOM = 1;
+
public const INIT_KMEANS_PLUS_PLUS = 2;
/**
@@ -32,7 +33,7 @@ class KMeans implements Clusterer
$this->initialization = $initialization;
}
- public function cluster(array $samples) : array
+ public function cluster(array $samples): array
{
$space = new Space(count($samples[0]));
foreach ($samples as $sample) {
diff --git a/src/Phpml/Clustering/KMeans/Cluster.php b/src/Phpml/Clustering/KMeans/Cluster.php
index 22545b6..fea1ff8 100644
--- a/src/Phpml/Clustering/KMeans/Cluster.php
+++ b/src/Phpml/Clustering/KMeans/Cluster.php
@@ -28,7 +28,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
$this->points = new SplObjectStorage();
}
- public function getPoints() : array
+ public function getPoints(): array
{
$points = [];
foreach ($this->points as $point) {
@@ -38,7 +38,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
return $points;
}
- public function toArray() : array
+ public function toArray(): array
{
return [
'centroid' => parent::toArray(),
@@ -46,7 +46,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
];
}
- public function attach(Point $point) : Point
+ public function attach(Point $point): Point
{
if ($point instanceof self) {
throw new LogicException('cannot attach a cluster to another');
@@ -57,7 +57,7 @@ class Cluster extends Point implements IteratorAggregate, Countable
return $point;
}
- public function detach(Point $point) : Point
+ public function detach(Point $point): Point
{
$this->points->detach($point);
@@ -76,7 +76,8 @@ class Cluster extends Point implements IteratorAggregate, Countable
public function updateCentroid(): void
{
- if (!$count = count($this->points)) {
+ $count = count($this->points);
+ if (!$count) {
return;
}
diff --git a/src/Phpml/Clustering/KMeans/Point.php b/src/Phpml/Clustering/KMeans/Point.php
index f90de8a..6aa40a9 100644
--- a/src/Phpml/Clustering/KMeans/Point.php
+++ b/src/Phpml/Clustering/KMeans/Point.php
@@ -16,7 +16,7 @@ class Point implements ArrayAccess
/**
* @var array
*/
- protected $coordinates;
+ protected $coordinates = [];
public function __construct(array $coordinates)
{
@@ -24,7 +24,7 @@ class Point implements ArrayAccess
$this->coordinates = $coordinates;
}
- public function toArray() : array
+ public function toArray(): array
{
return $this->coordinates;
}
@@ -66,7 +66,7 @@ class Point implements ArrayAccess
return $minPoint;
}
- public function getCoordinates() : array
+ public function getCoordinates(): array
{
return $this->coordinates;
}
diff --git a/src/Phpml/Clustering/KMeans/Space.php b/src/Phpml/Clustering/KMeans/Space.php
index 4412d53..0d4adf5 100644
--- a/src/Phpml/Clustering/KMeans/Space.php
+++ b/src/Phpml/Clustering/KMeans/Space.php
@@ -25,7 +25,7 @@ class Space extends SplObjectStorage
$this->dimension = $dimension;
}
- public function toArray() : array
+ public function toArray(): array
{
$points = [];
foreach ($this as $point) {
@@ -35,7 +35,7 @@ class Space extends SplObjectStorage
return ['points' => $points];
}
- public function newPoint(array $coordinates) : Point
+ public function newPoint(array $coordinates): Point
{
if (count($coordinates) != $this->dimension) {
throw new LogicException('('.implode(',', $coordinates).') is not a point of this space');
@@ -65,7 +65,7 @@ class Space extends SplObjectStorage
parent::attach($point, $data);
}
- public function getDimension() : int
+ public function getDimension(): int
{
return $this->dimension;
}
@@ -92,7 +92,7 @@ class Space extends SplObjectStorage
return [$min, $max];
}
- public function getRandomPoint(Point $min, Point $max) : Point
+ public function getRandomPoint(Point $min, Point $max): Point
{
$point = $this->newPoint(array_fill(0, $this->dimension, null));
@@ -106,7 +106,7 @@ class Space extends SplObjectStorage
/**
* @return array|Cluster[]
*/
- public function cluster(int $clustersNumber, int $initMethod = KMeans::INIT_RANDOM) : array
+ public function cluster(int $clustersNumber, int $initMethod = KMeans::INIT_RANDOM): array
{
$clusters = $this->initializeClusters($clustersNumber, $initMethod);
@@ -119,7 +119,7 @@ class Space extends SplObjectStorage
/**
* @return array|Cluster[]
*/
- protected function initializeClusters(int $clustersNumber, int $initMethod) : array
+ protected function initializeClusters(int $clustersNumber, int $initMethod): array
{
switch ($initMethod) {
case KMeans::INIT_RANDOM:
@@ -139,7 +139,7 @@ class Space extends SplObjectStorage
return $clusters;
}
- protected function iterate($clusters) : bool
+ protected function iterate($clusters): bool
{
$convergence = true;
@@ -177,19 +177,7 @@ class Space extends SplObjectStorage
return $convergence;
}
- private function initializeRandomClusters(int $clustersNumber) : array
- {
- $clusters = [];
- [$min, $max] = $this->getBoundaries();
-
- for ($n = 0; $n < $clustersNumber; ++$n) {
- $clusters[] = new Cluster($this, $this->getRandomPoint($min, $max)->getCoordinates());
- }
-
- return $clusters;
- }
-
- protected function initializeKMPPClusters(int $clustersNumber) : array
+ protected function initializeKMPPClusters(int $clustersNumber): array
{
$clusters = [];
$this->rewind();
@@ -218,4 +206,16 @@ class Space extends SplObjectStorage
return $clusters;
}
+
+ private function initializeRandomClusters(int $clustersNumber): array
+ {
+ $clusters = [];
+ [$min, $max] = $this->getBoundaries();
+
+ for ($n = 0; $n < $clustersNumber; ++$n) {
+ $clusters[] = new Cluster($this, $this->getRandomPoint($min, $max)->getCoordinates());
+ }
+
+ return $clusters;
+ }
}
diff --git a/src/Phpml/CrossValidation/Split.php b/src/Phpml/CrossValidation/Split.php
index e485ffb..96c9019 100644
--- a/src/Phpml/CrossValidation/Split.php
+++ b/src/Phpml/CrossValidation/Split.php
@@ -31,39 +31,40 @@ abstract class Split
public function __construct(Dataset $dataset, float $testSize = 0.3, ?int $seed = null)
{
- if (0 >= $testSize || 1 <= $testSize) {
+ if ($testSize <= 0 || $testSize >= 1) {
throw InvalidArgumentException::percentNotInRange('testSize');
}
+
$this->seedGenerator($seed);
$this->splitDataset($dataset, $testSize);
}
- abstract protected function splitDataset(Dataset $dataset, float $testSize);
-
- public function getTrainSamples() : array
+ public function getTrainSamples(): array
{
return $this->trainSamples;
}
- public function getTestSamples() : array
+ public function getTestSamples(): array
{
return $this->testSamples;
}
- public function getTrainLabels() : array
+ public function getTrainLabels(): array
{
return $this->trainLabels;
}
- public function getTestLabels() : array
+ public function getTestLabels(): array
{
return $this->testLabels;
}
+ abstract protected function splitDataset(Dataset $dataset, float $testSize);
+
protected function seedGenerator(?int $seed = null): void
{
- if (null === $seed) {
+ if ($seed === null) {
mt_srand();
} else {
mt_srand($seed);
diff --git a/src/Phpml/CrossValidation/StratifiedRandomSplit.php b/src/Phpml/CrossValidation/StratifiedRandomSplit.php
index 153cb8f..d450842 100644
--- a/src/Phpml/CrossValidation/StratifiedRandomSplit.php
+++ b/src/Phpml/CrossValidation/StratifiedRandomSplit.php
@@ -21,7 +21,7 @@ class StratifiedRandomSplit extends RandomSplit
/**
* @return Dataset[]|array
*/
- private function splitByTarget(Dataset $dataset) : array
+ private function splitByTarget(Dataset $dataset): array
{
$targets = $dataset->getTargets();
$samples = $dataset->getSamples();
@@ -38,7 +38,7 @@ class StratifiedRandomSplit extends RandomSplit
return $datasets;
}
- private function createDatasets(array $uniqueTargets, array $split) : array
+ private function createDatasets(array $uniqueTargets, array $split): array
{
$datasets = [];
foreach ($uniqueTargets as $target) {
diff --git a/src/Phpml/Dataset/ArrayDataset.php b/src/Phpml/Dataset/ArrayDataset.php
index e27b2e3..7d30b0b 100644
--- a/src/Phpml/Dataset/ArrayDataset.php
+++ b/src/Phpml/Dataset/ArrayDataset.php
@@ -31,12 +31,12 @@ class ArrayDataset implements Dataset
$this->targets = $targets;
}
- public function getSamples() : array
+ public function getSamples(): array
{
return $this->samples;
}
- public function getTargets() : array
+ public function getTargets(): array
{
return $this->targets;
}
diff --git a/src/Phpml/Dataset/CsvDataset.php b/src/Phpml/Dataset/CsvDataset.php
index ef33e2c..f88fe31 100644
--- a/src/Phpml/Dataset/CsvDataset.php
+++ b/src/Phpml/Dataset/CsvDataset.php
@@ -11,7 +11,7 @@ class CsvDataset extends ArrayDataset
/**
* @var array
*/
- protected $columnNames;
+ protected $columnNames = [];
/**
* @throws FileException
@@ -22,7 +22,8 @@ class CsvDataset extends ArrayDataset
throw FileException::missingFile(basename($filepath));
}
- if (false === $handle = fopen($filepath, 'rb')) {
+ $handle = fopen($filepath, 'rb');
+ if ($handle === false) {
throw FileException::cantOpenFile(basename($filepath));
}
@@ -44,7 +45,7 @@ class CsvDataset extends ArrayDataset
parent::__construct($samples, $targets);
}
- public function getColumnNames() : array
+ public function getColumnNames(): array
{
return $this->columnNames;
}
diff --git a/src/Phpml/Dataset/Dataset.php b/src/Phpml/Dataset/Dataset.php
index ce75a8a..f851d85 100644
--- a/src/Phpml/Dataset/Dataset.php
+++ b/src/Phpml/Dataset/Dataset.php
@@ -9,10 +9,10 @@ interface Dataset
/**
* @return array
*/
- public function getSamples() : array;
+ public function getSamples(): array;
/**
* @return array
*/
- public function getTargets() : array;
+ public function getTargets(): array;
}
diff --git a/src/Phpml/DimensionReduction/EigenTransformerBase.php b/src/Phpml/DimensionReduction/EigenTransformerBase.php
index a6352ba..ec64163 100644
--- a/src/Phpml/DimensionReduction/EigenTransformerBase.php
+++ b/src/Phpml/DimensionReduction/EigenTransformerBase.php
@@ -84,7 +84,7 @@ abstract class EigenTransformerBase
/**
* Returns the reduced data
*/
- protected function reduce(array $data) : array
+ protected function reduce(array $data): array
{
$m1 = new Matrix($data);
$m2 = new Matrix($this->eigVectors);
diff --git a/src/Phpml/DimensionReduction/KernelPCA.php b/src/Phpml/DimensionReduction/KernelPCA.php
index d11e1a6..1981cb5 100644
--- a/src/Phpml/DimensionReduction/KernelPCA.php
+++ b/src/Phpml/DimensionReduction/KernelPCA.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\DimensionReduction;
+use Closure;
+use Exception;
use Phpml\Math\Distance\Euclidean;
use Phpml\Math\Distance\Manhattan;
use Phpml\Math\Matrix;
@@ -11,8 +13,11 @@ use Phpml\Math\Matrix;
class KernelPCA extends PCA
{
public const KERNEL_RBF = 1;
+
public const KERNEL_SIGMOID = 2;
+
public const KERNEL_LAPLACIAN = 3;
+
public const KERNEL_LINEAR = 4;
/**
@@ -34,7 +39,7 @@ class KernelPCA extends PCA
*
* @var array
*/
- protected $data;
+ protected $data = [];
/**
* Kernel principal component analysis (KernelPCA) is an extension of PCA using
@@ -54,7 +59,7 @@ class KernelPCA extends PCA
{
$availableKernels = [self::KERNEL_RBF, self::KERNEL_SIGMOID, self::KERNEL_LAPLACIAN, self::KERNEL_LINEAR];
if (!in_array($kernel, $availableKernels)) {
- throw new \Exception('KernelPCA can be initialized with the following kernels only: Linear, RBF, Sigmoid and Laplacian');
+ throw new Exception('KernelPCA can be initialized with the following kernels only: Linear, RBF, Sigmoid and Laplacian');
}
parent::__construct($totalVariance, $numFeatures);
@@ -69,7 +74,7 @@ class KernelPCA extends PCA
* $data is an n-by-m matrix and returned array is
* n-by-k matrix where k <= m
*/
- public function fit(array $data) : array
+ public function fit(array $data): array
{
$numRows = count($data);
$this->data = $data;
@@ -88,11 +93,32 @@ class KernelPCA extends PCA
return Matrix::transposeArray($this->eigVectors);
}
+ /**
+ * Transforms the given sample to a lower dimensional vector by using
+ * the variables obtained during the last run of fit
.
+ *
+ * @throws \Exception
+ */
+ public function transform(array $sample): array
+ {
+ if (!$this->fit) {
+ throw new Exception('KernelPCA has not been fitted with respect to original dataset, please run KernelPCA::fit() first');
+ }
+
+ if (is_array($sample[0])) {
+ throw new Exception('KernelPCA::transform() accepts only one-dimensional arrays');
+ }
+
+ $pairs = $this->getDistancePairs($sample);
+
+ return $this->projectSample($pairs);
+ }
+
/**
* Calculates similarity matrix by use of selected kernel function
* An n-by-m matrix is given and an n-by-n matrix is returned
*/
- protected function calculateKernelMatrix(array $data, int $numRows) : array
+ protected function calculateKernelMatrix(array $data, int $numRows): array
{
$kernelFunc = $this->getKernel();
@@ -116,7 +142,7 @@ class KernelPCA extends PCA
*
* K′ = K − N.K − K.N + N.K.N where N is n-by-n matrix filled with 1/n
*/
- protected function centerMatrix(array $matrix, int $n) : array
+ protected function centerMatrix(array $matrix, int $n): array
{
$N = array_fill(0, $n, array_fill(0, $n, 1.0 / $n));
$N = new Matrix($N, false);
@@ -140,7 +166,7 @@ class KernelPCA extends PCA
*
* @throws \Exception
*/
- protected function getKernel(): \Closure
+ protected function getKernel(): Closure
{
switch ($this->kernel) {
case self::KERNEL_LINEAR:
@@ -173,11 +199,11 @@ class KernelPCA extends PCA
};
default:
- throw new \Exception(sprintf('KernelPCA initialized with invalid kernel: %d', $this->kernel));
+ throw new Exception(sprintf('KernelPCA initialized with invalid kernel: %d', $this->kernel));
}
}
- protected function getDistancePairs(array $sample) : array
+ protected function getDistancePairs(array $sample): array
{
$kernel = $this->getKernel();
@@ -189,7 +215,7 @@ class KernelPCA extends PCA
return $pairs;
}
- protected function projectSample(array $pairs) : array
+ protected function projectSample(array $pairs): array
{
// Normalize eigenvectors by eig = eigVectors / eigValues
$func = function ($eigVal, $eigVect) {
@@ -203,25 +229,4 @@ class KernelPCA extends PCA
// return k.dot(eig)
return Matrix::dot($pairs, $eig);
}
-
- /**
- * Transforms the given sample to a lower dimensional vector by using
- * the variables obtained during the last run of fit
.
- *
- * @throws \Exception
- */
- public function transform(array $sample) : array
- {
- if (!$this->fit) {
- throw new \Exception('KernelPCA has not been fitted with respect to original dataset, please run KernelPCA::fit() first');
- }
-
- if (is_array($sample[0])) {
- throw new \Exception('KernelPCA::transform() accepts only one-dimensional arrays');
- }
-
- $pairs = $this->getDistancePairs($sample);
-
- return $this->projectSample($pairs);
- }
}
diff --git a/src/Phpml/DimensionReduction/LDA.php b/src/Phpml/DimensionReduction/LDA.php
index 26b2324..6400d14 100644
--- a/src/Phpml/DimensionReduction/LDA.php
+++ b/src/Phpml/DimensionReduction/LDA.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\DimensionReduction;
+use Exception;
use Phpml\Math\Matrix;
class LDA extends EigenTransformerBase
@@ -16,22 +17,22 @@ class LDA extends EigenTransformerBase
/**
* @var array
*/
- public $labels;
+ public $labels = [];
/**
* @var array
*/
- public $means;
+ public $means = [];
/**
* @var array
*/
- public $counts;
+ public $counts = [];
/**
* @var float[]
*/
- public $overallMean;
+ public $overallMean = [];
/**
* Linear Discriminant Analysis (LDA) is used to reduce the dimensionality
@@ -50,18 +51,21 @@ class LDA extends EigenTransformerBase
public function __construct(?float $totalVariance = null, ?int $numFeatures = null)
{
if ($totalVariance !== null && ($totalVariance < 0.1 || $totalVariance > 0.99)) {
- throw new \Exception('Total variance can be a value between 0.1 and 0.99');
+ throw new Exception('Total variance can be a value between 0.1 and 0.99');
}
+
if ($numFeatures !== null && $numFeatures <= 0) {
- throw new \Exception('Number of features to be preserved should be greater than 0');
+ throw new Exception('Number of features to be preserved should be greater than 0');
}
+
if ($totalVariance !== null && $numFeatures !== null) {
- throw new \Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
+ throw new Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
}
if ($numFeatures !== null) {
$this->numFeatures = $numFeatures;
}
+
if ($totalVariance !== null) {
$this->totalVariance = $totalVariance;
}
@@ -70,7 +74,7 @@ class LDA extends EigenTransformerBase
/**
* Trains the algorithm to transform the given data to a lower dimensional space.
*/
- public function fit(array $data, array $classes) : array
+ public function fit(array $data, array $classes): array
{
$this->labels = $this->getLabels($classes);
$this->means = $this->calculateMeans($data, $classes);
@@ -86,10 +90,29 @@ class LDA extends EigenTransformerBase
return $this->reduce($data);
}
+ /**
+ * Transforms the given sample to a lower dimensional vector by using
+ * the eigenVectors obtained in the last run of fit
.
+ *
+ * @throws \Exception
+ */
+ public function transform(array $sample): array
+ {
+ if (!$this->fit) {
+ throw new Exception('LDA has not been fitted with respect to original dataset, please run LDA::fit() first');
+ }
+
+ if (!is_array($sample[0])) {
+ $sample = [$sample];
+ }
+
+ return $this->reduce($sample);
+ }
+
/**
* Returns unique labels in the dataset
*/
- protected function getLabels(array $classes) : array
+ protected function getLabels(array $classes): array
{
$counts = array_count_values($classes);
@@ -100,7 +123,7 @@ class LDA extends EigenTransformerBase
* Calculates mean of each column for each class and returns
* n by m matrix where n is number of labels and m is number of columns
*/
- protected function calculateMeans(array $data, array $classes) : array
+ protected function calculateMeans(array $data, array $classes): array
{
$means = [];
$counts = [];
@@ -113,6 +136,7 @@ class LDA extends EigenTransformerBase
if (!isset($means[$label][$col])) {
$means[$label][$col] = 0.0;
}
+
$means[$label][$col] += $val;
$overallMean[$col] += $val;
}
@@ -146,7 +170,7 @@ class LDA extends EigenTransformerBase
* is a n by m matrix where n is number of classes and
* m is number of columns
*/
- protected function calculateClassVar(array $data, array $classes) : Matrix
+ protected function calculateClassVar(array $data, array $classes): Matrix
{
// s is an n (number of classes) by m (number of column) matrix
$s = array_fill(0, count($data[0]), array_fill(0, count($data[0]), 0));
@@ -169,7 +193,7 @@ class LDA extends EigenTransformerBase
* is an n by m matrix where n is number of classes and
* m is number of columns
*/
- protected function calculateClassCov() : Matrix
+ protected function calculateClassCov(): Matrix
{
// s is an n (number of classes) by m (number of column) matrix
$s = array_fill(0, count($this->overallMean), array_fill(0, count($this->overallMean), 0));
@@ -187,7 +211,7 @@ class LDA extends EigenTransformerBase
/**
* Returns the result of the calculation (x - m)T.(x - m)
*/
- protected function calculateVar(array $row, array $means) : Matrix
+ protected function calculateVar(array $row, array $means): Matrix
{
$x = new Matrix($row, false);
$m = new Matrix($means, false);
@@ -195,23 +219,4 @@ class LDA extends EigenTransformerBase
return $diff->transpose()->multiply($diff);
}
-
- /**
- * Transforms the given sample to a lower dimensional vector by using
- * the eigenVectors obtained in the last run of fit
.
- *
- * @throws \Exception
- */
- public function transform(array $sample) : array
- {
- if (!$this->fit) {
- throw new \Exception('LDA has not been fitted with respect to original dataset, please run LDA::fit() first');
- }
-
- if (!is_array($sample[0])) {
- $sample = [$sample];
- }
-
- return $this->reduce($sample);
- }
}
diff --git a/src/Phpml/DimensionReduction/PCA.php b/src/Phpml/DimensionReduction/PCA.php
index 25b7186..18879bb 100644
--- a/src/Phpml/DimensionReduction/PCA.php
+++ b/src/Phpml/DimensionReduction/PCA.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\DimensionReduction;
+use Exception;
use Phpml\Math\Statistic\Covariance;
use Phpml\Math\Statistic\Mean;
@@ -35,18 +36,21 @@ class PCA extends EigenTransformerBase
public function __construct(?float $totalVariance = null, ?int $numFeatures = null)
{
if ($totalVariance !== null && ($totalVariance < 0.1 || $totalVariance > 0.99)) {
- throw new \Exception('Total variance can be a value between 0.1 and 0.99');
+ throw new Exception('Total variance can be a value between 0.1 and 0.99');
}
+
if ($numFeatures !== null && $numFeatures <= 0) {
- throw new \Exception('Number of features to be preserved should be greater than 0');
+ throw new Exception('Number of features to be preserved should be greater than 0');
}
+
if ($totalVariance !== null && $numFeatures !== null) {
- throw new \Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
+ throw new Exception('Either totalVariance or numFeatures should be specified in order to run the algorithm');
}
if ($numFeatures !== null) {
$this->numFeatures = $numFeatures;
}
+
if ($totalVariance !== null) {
$this->totalVariance = $totalVariance;
}
@@ -58,7 +62,7 @@ class PCA extends EigenTransformerBase
* $data is an n-by-m matrix and returned array is
* n-by-k matrix where k <= m
*/
- public function fit(array $data) : array
+ public function fit(array $data): array
{
$n = count($data[0]);
@@ -73,6 +77,27 @@ class PCA extends EigenTransformerBase
return $this->reduce($data);
}
+ /**
+ * Transforms the given sample to a lower dimensional vector by using
+ * the eigenVectors obtained in the last run of fit
.
+ *
+ * @throws \Exception
+ */
+ public function transform(array $sample): array
+ {
+ if (!$this->fit) {
+ throw new Exception('PCA has not been fitted with respect to original dataset, please run PCA::fit() first');
+ }
+
+ if (!is_array($sample[0])) {
+ $sample = [$sample];
+ }
+
+ $sample = $this->normalize($sample, count($sample[0]));
+
+ return $this->reduce($sample);
+ }
+
protected function calculateMeans(array $data, int $n): void
{
// Calculate means for each dimension
@@ -87,7 +112,7 @@ class PCA extends EigenTransformerBase
* Normalization of the data includes subtracting mean from
* each dimension therefore dimensions will be centered to zero
*/
- protected function normalize(array $data, int $n) : array
+ protected function normalize(array $data, int $n): array
{
if (empty($this->means)) {
$this->calculateMeans($data, $n);
@@ -102,25 +127,4 @@ class PCA extends EigenTransformerBase
return $data;
}
-
- /**
- * Transforms the given sample to a lower dimensional vector by using
- * the eigenVectors obtained in the last run of fit
.
- *
- * @throws \Exception
- */
- public function transform(array $sample) : array
- {
- if (!$this->fit) {
- throw new \Exception('PCA has not been fitted with respect to original dataset, please run PCA::fit() first');
- }
-
- if (!is_array($sample[0])) {
- $sample = [$sample];
- }
-
- $sample = $this->normalize($sample, count($sample[0]));
-
- return $this->reduce($sample);
- }
}
diff --git a/src/Phpml/Exception/DatasetException.php b/src/Phpml/Exception/DatasetException.php
index 5d3e0db..8d6d5da 100644
--- a/src/Phpml/Exception/DatasetException.php
+++ b/src/Phpml/Exception/DatasetException.php
@@ -4,9 +4,11 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class DatasetException extends \Exception
+use Exception;
+
+class DatasetException extends Exception
{
- public static function missingFolder(string $path) : DatasetException
+ public static function missingFolder(string $path): self
{
return new self(sprintf('Dataset root folder "%s" missing.', $path));
}
diff --git a/src/Phpml/Exception/FileException.php b/src/Phpml/Exception/FileException.php
index 39b9b03..719c2c2 100644
--- a/src/Phpml/Exception/FileException.php
+++ b/src/Phpml/Exception/FileException.php
@@ -4,19 +4,21 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class FileException extends \Exception
+use Exception;
+
+class FileException extends Exception
{
- public static function missingFile(string $filepath) : FileException
+ public static function missingFile(string $filepath): self
{
return new self(sprintf('File "%s" missing.', $filepath));
}
- public static function cantOpenFile(string $filepath) : FileException
+ public static function cantOpenFile(string $filepath): self
{
return new self(sprintf('File "%s" can\'t be open.', $filepath));
}
- public static function cantSaveFile(string $filepath) : FileException
+ public static function cantSaveFile(string $filepath): self
{
return new self(sprintf('File "%s" can\'t be saved.', $filepath));
}
diff --git a/src/Phpml/Exception/InvalidArgumentException.php b/src/Phpml/Exception/InvalidArgumentException.php
index d96bb33..e02d14d 100644
--- a/src/Phpml/Exception/InvalidArgumentException.php
+++ b/src/Phpml/Exception/InvalidArgumentException.php
@@ -4,39 +4,41 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class InvalidArgumentException extends \Exception
+use Exception;
+
+class InvalidArgumentException extends Exception
{
- public static function arraySizeNotMatch() : InvalidArgumentException
+ public static function arraySizeNotMatch(): self
{
return new self('Size of given arrays does not match');
}
- public static function percentNotInRange($name) : InvalidArgumentException
+ public static function percentNotInRange($name): self
{
return new self(sprintf('%s must be between 0.0 and 1.0', $name));
}
- public static function arrayCantBeEmpty() : InvalidArgumentException
+ public static function arrayCantBeEmpty(): self
{
return new self('The array has zero elements');
}
- public static function arraySizeToSmall(int $minimumSize = 2) : InvalidArgumentException
+ public static function arraySizeToSmall(int $minimumSize = 2): self
{
return new self(sprintf('The array must have at least %d elements', $minimumSize));
}
- public static function matrixDimensionsDidNotMatch() : InvalidArgumentException
+ public static function matrixDimensionsDidNotMatch(): self
{
return new self('Matrix dimensions did not match');
}
- public static function inconsistentMatrixSupplied() : InvalidArgumentException
+ public static function inconsistentMatrixSupplied(): self
{
return new self('Inconsistent matrix supplied');
}
- public static function invalidClustersNumber() : InvalidArgumentException
+ public static function invalidClustersNumber(): self
{
return new self('Invalid clusters number');
}
@@ -44,57 +46,57 @@ class InvalidArgumentException extends \Exception
/**
* @param mixed $target
*/
- public static function invalidTarget($target) : InvalidArgumentException
+ 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) : InvalidArgumentException
+ public static function invalidStopWordsLanguage(string $language): self
{
return new self(sprintf('Can\'t find "%s" language for StopWords', $language));
}
- public static function invalidLayerNodeClass() : InvalidArgumentException
+ public static function invalidLayerNodeClass(): self
{
return new self('Layer node class must implement Node interface');
}
- public static function invalidLayersNumber() : InvalidArgumentException
+ public static function invalidLayersNumber(): self
{
return new self('Provide at least 1 hidden layer');
}
- public static function invalidClassesNumber() : InvalidArgumentException
+ public static function invalidClassesNumber(): self
{
return new self('Provide at least 2 different classes');
}
- public static function inconsistentClasses() : InvalidArgumentException
+ 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) : InvalidArgumentException
+ public static function fileNotFound(string $file): self
{
return new self(sprintf('File "%s" not found', $file));
}
- public static function fileNotExecutable(string $file) : InvalidArgumentException
+ public static function fileNotExecutable(string $file): self
{
return new self(sprintf('File "%s" is not executable', $file));
}
- public static function pathNotFound(string $path) : InvalidArgumentException
+ 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) : InvalidArgumentException
+ 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) : InvalidArgumentException
+ public static function invalidOperator(string $operator): self
{
return new self(sprintf('Invalid operator "%s" provided', $operator));
}
diff --git a/src/Phpml/Exception/MatrixException.php b/src/Phpml/Exception/MatrixException.php
index a52feaa..b309bff 100644
--- a/src/Phpml/Exception/MatrixException.php
+++ b/src/Phpml/Exception/MatrixException.php
@@ -4,19 +4,21 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class MatrixException extends \Exception
+use Exception;
+
+class MatrixException extends Exception
{
- public static function notSquareMatrix() : MatrixException
+ public static function notSquareMatrix(): self
{
return new self('Matrix is not square matrix');
}
- public static function columnOutOfRange() : MatrixException
+ public static function columnOutOfRange(): self
{
return new self('Column out of range');
}
- public static function singularMatrix() : MatrixException
+ public static function singularMatrix(): self
{
return new self('Matrix is singular');
}
diff --git a/src/Phpml/Exception/NormalizerException.php b/src/Phpml/Exception/NormalizerException.php
index a7604e8..282fa1b 100644
--- a/src/Phpml/Exception/NormalizerException.php
+++ b/src/Phpml/Exception/NormalizerException.php
@@ -4,9 +4,11 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class NormalizerException extends \Exception
+use Exception;
+
+class NormalizerException extends Exception
{
- public static function unknownNorm() : NormalizerException
+ public static function unknownNorm(): self
{
return new self('Unknown norm supplied.');
}
diff --git a/src/Phpml/Exception/SerializeException.php b/src/Phpml/Exception/SerializeException.php
index 913667a..6d1abaa 100644
--- a/src/Phpml/Exception/SerializeException.php
+++ b/src/Phpml/Exception/SerializeException.php
@@ -4,14 +4,16 @@ declare(strict_types=1);
namespace Phpml\Exception;
-class SerializeException extends \Exception
+use Exception;
+
+class SerializeException extends Exception
{
- public static function cantUnserialize(string $filepath) : SerializeException
+ public static function cantUnserialize(string $filepath): self
{
return new self(sprintf('"%s" can not be unserialized.', $filepath));
}
- public static function cantSerialize(string $classname) : SerializeException
+ public static function cantSerialize(string $classname): self
{
return new self(sprintf('Class "%s" can not be serialized.', $classname));
}
diff --git a/src/Phpml/FeatureExtraction/StopWords.php b/src/Phpml/FeatureExtraction/StopWords.php
index b6717b9..fdb985f 100644
--- a/src/Phpml/FeatureExtraction/StopWords.php
+++ b/src/Phpml/FeatureExtraction/StopWords.php
@@ -11,19 +11,19 @@ class StopWords
/**
* @var array
*/
- protected $stopWords;
+ protected $stopWords = [];
public function __construct(array $stopWords)
{
$this->stopWords = array_fill_keys($stopWords, true);
}
- public function isStopWord(string $token) : bool
+ public function isStopWord(string $token): bool
{
return isset($this->stopWords[$token]);
}
- public static function factory(string $language = 'English') : StopWords
+ public static function factory(string $language = 'English'): self
{
$className = __NAMESPACE__."\\StopWords\\$language";
diff --git a/src/Phpml/FeatureExtraction/TfIdfTransformer.php b/src/Phpml/FeatureExtraction/TfIdfTransformer.php
index 6efd90f..4b678a4 100644
--- a/src/Phpml/FeatureExtraction/TfIdfTransformer.php
+++ b/src/Phpml/FeatureExtraction/TfIdfTransformer.php
@@ -11,7 +11,7 @@ class TfIdfTransformer implements Transformer
/**
* @var array
*/
- private $idf;
+ private $idf = [];
public function __construct(?array $samples = null)
{
diff --git a/src/Phpml/FeatureExtraction/TokenCountVectorizer.php b/src/Phpml/FeatureExtraction/TokenCountVectorizer.php
index e00fc69..e0bd402 100644
--- a/src/Phpml/FeatureExtraction/TokenCountVectorizer.php
+++ b/src/Phpml/FeatureExtraction/TokenCountVectorizer.php
@@ -27,21 +27,18 @@ class TokenCountVectorizer implements Transformer
/**
* @var array
*/
- private $vocabulary;
+ private $vocabulary = [];
/**
* @var array
*/
- private $frequencies;
+ private $frequencies = [];
public function __construct(Tokenizer $tokenizer, ?StopWords $stopWords = null, float $minDF = 0.0)
{
$this->tokenizer = $tokenizer;
$this->stopWords = $stopWords;
$this->minDF = $minDF;
-
- $this->vocabulary = [];
- $this->frequencies = [];
}
public function fit(array $samples): void
@@ -58,7 +55,7 @@ class TokenCountVectorizer implements Transformer
$this->checkDocumentFrequency($samples);
}
- public function getVocabulary() : array
+ public function getVocabulary(): array
{
return array_flip($this->vocabulary);
}
@@ -80,7 +77,7 @@ class TokenCountVectorizer implements Transformer
foreach ($tokens as $token) {
$index = $this->getTokenIndex($token);
- if (false !== $index) {
+ if ($index !== false) {
$this->updateFrequency($token);
if (!isset($counts[$index])) {
$counts[$index] = 0;
@@ -155,7 +152,7 @@ class TokenCountVectorizer implements Transformer
}
}
- private function getBeyondMinimumIndexes(int $samplesCount) : array
+ private function getBeyondMinimumIndexes(int $samplesCount): array
{
$indexes = [];
foreach ($this->frequencies as $token => $frequency) {
diff --git a/src/Phpml/Helper/OneVsRest.php b/src/Phpml/Helper/OneVsRest.php
index 15d62d8..4f661ba 100644
--- a/src/Phpml/Helper/OneVsRest.php
+++ b/src/Phpml/Helper/OneVsRest.php
@@ -36,6 +36,18 @@ trait OneVsRest
$this->trainBylabel($samples, $targets);
}
+ /**
+ * Resets the classifier and the vars internally used by OneVsRest to create multiple classifiers.
+ */
+ public function reset(): void
+ {
+ $this->classifiers = [];
+ $this->allLabels = [];
+ $this->costValues = [];
+
+ $this->resetBinary();
+ }
+
protected function trainByLabel(array $samples, array $targets, array $allLabels = []): void
{
// Overwrites the current value if it exist. $allLabels must be provided for each partialTrain run.
@@ -44,6 +56,7 @@ trait OneVsRest
} else {
$this->allLabels = array_keys(array_count_values($targets));
}
+
sort($this->allLabels, SORT_STRING);
// If there are only two targets, then there is no need to perform OvR
@@ -77,18 +90,6 @@ trait OneVsRest
}
}
- /**
- * Resets the classifier and the vars internally used by OneVsRest to create multiple classifiers.
- */
- public function reset(): void
- {
- $this->classifiers = [];
- $this->allLabels = [];
- $this->costValues = [];
-
- $this->resetBinary();
- }
-
/**
* Returns an instance of the current class after cleaning up OneVsRest stuff.
*
@@ -105,29 +106,6 @@ trait OneVsRest
return $classifier;
}
- /**
- * Groups all targets into two groups: Targets equal to
- * the given label and the others
- *
- * $targets is not passed by reference nor contains objects so this method
- * changes will not affect the caller $targets array.
- *
- * @param mixed $label
- *
- * @return array Binarized targets and target's labels
- */
- private function binarizeTargets(array $targets, $label) : array
- {
- $notLabel = "not_$label";
- foreach ($targets as $key => $target) {
- $targets[$key] = $target == $label ? $label : $notLabel;
- }
-
- $labels = [$label, $notLabel];
-
- return [$targets, $labels];
- }
-
/**
* @return mixed
*/
@@ -155,8 +133,6 @@ trait OneVsRest
/**
* To be overwritten by OneVsRest classifiers.
- *
- * @return void
*/
abstract protected function resetBinary(): void;
@@ -174,4 +150,27 @@ trait OneVsRest
* @return mixed
*/
abstract protected function predictSampleBinary(array $sample);
+
+ /**
+ * Groups all targets into two groups: Targets equal to
+ * the given label and the others
+ *
+ * $targets is not passed by reference nor contains objects so this method
+ * changes will not affect the caller $targets array.
+ *
+ * @param mixed $label
+ *
+ * @return array Binarized targets and target's labels
+ */
+ private function binarizeTargets(array $targets, $label): array
+ {
+ $notLabel = "not_$label";
+ foreach ($targets as $key => $target) {
+ $targets[$key] = $target == $label ? $label : $notLabel;
+ }
+
+ $labels = [$label, $notLabel];
+
+ return [$targets, $labels];
+ }
}
diff --git a/src/Phpml/Helper/Optimizer/ConjugateGradient.php b/src/Phpml/Helper/Optimizer/ConjugateGradient.php
index c119eae..153ffcb 100644
--- a/src/Phpml/Helper/Optimizer/ConjugateGradient.php
+++ b/src/Phpml/Helper/Optimizer/ConjugateGradient.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Helper\Optimizer;
+use Closure;
+
/**
* Conjugate Gradient method to solve a non-linear f(x) with respect to unknown x
* See https://en.wikipedia.org/wiki/Nonlinear_conjugate_gradient_method)
@@ -17,7 +19,7 @@ namespace Phpml\Helper\Optimizer;
*/
class ConjugateGradient extends GD
{
- public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
+ public function runOptimization(array $samples, array $targets, Closure $gradientCb): array
{
$this->samples = $samples;
$this->targets = $targets;
@@ -25,7 +27,7 @@ class ConjugateGradient extends GD
$this->sampleCount = count($samples);
$this->costValues = [];
- $d = mp::muls($this->gradient($this->theta), -1);
+ $d = MP::muls($this->gradient($this->theta), -1);
for ($i = 0; $i < $this->maxIterations; ++$i) {
// Obtain α that minimizes f(θ + α.d)
@@ -59,7 +61,7 @@ class ConjugateGradient extends GD
* Executes the callback function for the problem and returns
* sum of the gradient for all samples & targets.
*/
- protected function gradient(array $theta) : array
+ protected function gradient(array $theta): array
{
[, $gradient] = parent::gradient($theta);
@@ -69,7 +71,7 @@ class ConjugateGradient extends GD
/**
* Returns the value of f(x) for given solution
*/
- protected function cost(array $theta) : float
+ protected function cost(array $theta): float
{
[$cost] = parent::gradient($theta);
@@ -90,14 +92,14 @@ class ConjugateGradient extends GD
* b-1) If cost function decreases, continue enlarging alpha
* b-2) If cost function increases, take the midpoint and try again
*/
- protected function getAlpha(float $d) : float
+ protected function getAlpha(float $d): float
{
$small = 0.0001 * $d;
$large = 0.01 * $d;
// Obtain θ + α.d for two initial values, x0 and x1
- $x0 = mp::adds($this->theta, $small);
- $x1 = mp::adds($this->theta, $large);
+ $x0 = MP::adds($this->theta, $small);
+ $x1 = MP::adds($this->theta, $large);
$epsilon = 0.0001;
$iteration = 0;
@@ -113,9 +115,9 @@ class ConjugateGradient extends GD
if ($fx1 < $fx0) {
$x0 = $x1;
- $x1 = mp::adds($x1, 0.01); // Enlarge second
+ $x1 = MP::adds($x1, 0.01); // Enlarge second
} else {
- $x1 = mp::divs(mp::add($x1, $x0), 2.0);
+ $x1 = MP::divs(MP::add($x1, $x0), 2.0);
} // Get to the midpoint
$error = $fx1 / $this->dimensions;
@@ -135,7 +137,7 @@ class ConjugateGradient extends GD
*
* θ(k+1) = θ(k) + α.d
*/
- protected function getNewTheta(float $alpha, array $d) : array
+ protected function getNewTheta(float $alpha, array $d): array
{
$theta = $this->theta;
@@ -164,7 +166,7 @@ class ConjugateGradient extends GD
* See:
* R. Fletcher and C. M. Reeves, "Function minimization by conjugate gradients", Comput. J. 7 (1964), 149–154.
*/
- protected function getBeta(array $newTheta) : float
+ protected function getBeta(array $newTheta): float
{
$dNew = array_sum($this->gradient($newTheta));
$dOld = array_sum($this->gradient($this->theta)) + 1e-100;
@@ -177,11 +179,11 @@ class ConjugateGradient extends GD
*
* d(k+1) =–∇f(x(k+1)) + β(k).d(k)
*/
- protected function getNewDirection(array $theta, float $beta, array $d) : array
+ protected function getNewDirection(array $theta, float $beta, array $d): array
{
$grad = $this->gradient($theta);
- return mp::add(mp::muls($grad, -1), mp::muls($d, $beta));
+ return MP::add(MP::muls($grad, -1), MP::muls($d, $beta));
}
}
@@ -189,12 +191,12 @@ class ConjugateGradient extends GD
* Handles element-wise vector operations between vector-vector
* and vector-scalar variables
*/
-class mp
+class MP
{
/**
* Element-wise multiplication of two vectors of the same size
*/
- public static function mul(array $m1, array $m2) : array
+ public static function mul(array $m1, array $m2): array
{
$res = [];
foreach ($m1 as $i => $val) {
@@ -207,7 +209,7 @@ class mp
/**
* Element-wise division of two vectors of the same size
*/
- public static function div(array $m1, array $m2) : array
+ public static function div(array $m1, array $m2): array
{
$res = [];
foreach ($m1 as $i => $val) {
@@ -220,7 +222,7 @@ class mp
/**
* Element-wise addition of two vectors of the same size
*/
- public static function add(array $m1, array $m2, int $mag = 1) : array
+ public static function add(array $m1, array $m2, int $mag = 1): array
{
$res = [];
foreach ($m1 as $i => $val) {
@@ -233,7 +235,7 @@ class mp
/**
* Element-wise subtraction of two vectors of the same size
*/
- public static function sub(array $m1, array $m2) : array
+ public static function sub(array $m1, array $m2): array
{
return self::add($m1, $m2, -1);
}
@@ -241,7 +243,7 @@ class mp
/**
* Element-wise multiplication of a vector with a scalar
*/
- public static function muls(array $m1, float $m2) : array
+ public static function muls(array $m1, float $m2): array
{
$res = [];
foreach ($m1 as $val) {
@@ -254,7 +256,7 @@ class mp
/**
* Element-wise division of a vector with a scalar
*/
- public static function divs(array $m1, float $m2) : array
+ public static function divs(array $m1, float $m2): array
{
$res = [];
foreach ($m1 as $val) {
@@ -267,7 +269,7 @@ class mp
/**
* Element-wise addition of a vector with a scalar
*/
- public static function adds(array $m1, float $m2, int $mag = 1) : array
+ public static function adds(array $m1, float $m2, int $mag = 1): array
{
$res = [];
foreach ($m1 as $val) {
@@ -280,7 +282,7 @@ class mp
/**
* Element-wise subtraction of a vector with a scalar
*/
- public static function subs(array $m1, float $m2) : array
+ public static function subs(array $m1, float $m2): array
{
return self::adds($m1, $m2, -1);
}
diff --git a/src/Phpml/Helper/Optimizer/GD.php b/src/Phpml/Helper/Optimizer/GD.php
index 38b4253..4eadf28 100644
--- a/src/Phpml/Helper/Optimizer/GD.php
+++ b/src/Phpml/Helper/Optimizer/GD.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Helper\Optimizer;
+use Closure;
+
/**
* Batch version of Gradient Descent to optimize the weights
* of a classifier given samples, targets and the objective function to minimize
@@ -17,7 +19,7 @@ class GD extends StochasticGD
*/
protected $sampleCount = null;
- public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
+ public function runOptimization(array $samples, array $targets, Closure $gradientCb): array
{
$this->samples = $samples;
$this->targets = $targets;
@@ -51,7 +53,7 @@ class GD extends StochasticGD
* Calculates gradient, cost function and penalty term for each sample
* then returns them as an array of values
*/
- protected function gradient(array $theta) : array
+ protected function gradient(array $theta): array
{
$costs = [];
$gradient = [];
diff --git a/src/Phpml/Helper/Optimizer/Optimizer.php b/src/Phpml/Helper/Optimizer/Optimizer.php
index ee61321..2b25acd 100644
--- a/src/Phpml/Helper/Optimizer/Optimizer.php
+++ b/src/Phpml/Helper/Optimizer/Optimizer.php
@@ -4,6 +4,9 @@ declare(strict_types=1);
namespace Phpml\Helper\Optimizer;
+use Closure;
+use Exception;
+
abstract class Optimizer
{
/**
@@ -11,7 +14,7 @@ abstract class Optimizer
*
* @var array
*/
- protected $theta;
+ protected $theta = [];
/**
* Number of dimensions
@@ -30,7 +33,7 @@ abstract class Optimizer
// Inits the weights randomly
$this->theta = [];
for ($i = 0; $i < $this->dimensions; ++$i) {
- $this->theta[] = rand() / (float) getrandmax();
+ $this->theta[] = random_int(0, getrandmax()) / (float) getrandmax();
}
}
@@ -44,7 +47,7 @@ abstract class Optimizer
public function setInitialTheta(array $theta)
{
if (count($theta) != $this->dimensions) {
- throw new \Exception("Number of values in the weights array should be $this->dimensions");
+ throw new Exception("Number of values in the weights array should be $this->dimensions");
}
$this->theta = $theta;
@@ -56,5 +59,5 @@ abstract class Optimizer
* Executes the optimization with the given samples & targets
* and returns the weights
*/
- abstract public function runOptimization(array $samples, array $targets, \Closure $gradientCb);
+ abstract public function runOptimization(array $samples, array $targets, Closure $gradientCb);
}
diff --git a/src/Phpml/Helper/Optimizer/StochasticGD.php b/src/Phpml/Helper/Optimizer/StochasticGD.php
index f1b0979..07ad216 100644
--- a/src/Phpml/Helper/Optimizer/StochasticGD.php
+++ b/src/Phpml/Helper/Optimizer/StochasticGD.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Phpml\Helper\Optimizer;
+use Closure;
+
/**
* Stochastic Gradient Descent optimization method
* to find a solution for the equation A.ϴ = y where
@@ -66,6 +68,7 @@ class StochasticGD extends Optimizer
* @var bool
*/
protected $enableEarlyStop = true;
+
/**
* List of values obtained by evaluating the cost function at each iteration
* of the algorithm
@@ -141,7 +144,7 @@ class StochasticGD extends Optimizer
* The cost function to minimize and the gradient of the function are to be
* handled by the callback function provided as the third parameter of the method.
*/
- public function runOptimization(array $samples, array $targets, \Closure $gradientCb) : array
+ public function runOptimization(array $samples, array $targets, Closure $gradientCb): array
{
$this->samples = $samples;
$this->targets = $targets;
@@ -181,7 +184,16 @@ class StochasticGD extends Optimizer
return $this->theta = $bestTheta;
}
- protected function updateTheta() : float
+ /**
+ * Returns the list of cost values for each iteration executed in
+ * last run of the optimization
+ */
+ public function getCostValues(): array
+ {
+ return $this->costValues;
+ }
+
+ protected function updateTheta(): float
{
$jValue = 0.0;
$theta = $this->theta;
@@ -237,15 +249,6 @@ class StochasticGD extends Optimizer
return false;
}
- /**
- * Returns the list of cost values for each iteration executed in
- * last run of the optimization
- */
- public function getCostValues() : array
- {
- return $this->costValues;
- }
-
/**
* Clears the optimizer internal vars after the optimization process.
*/
diff --git a/src/Phpml/Math/Distance.php b/src/Phpml/Math/Distance.php
index 696ee4b..9faa8e0 100644
--- a/src/Phpml/Math/Distance.php
+++ b/src/Phpml/Math/Distance.php
@@ -10,5 +10,5 @@ interface Distance
* @param array $a
* @param array $b
*/
- public function distance(array $a, array $b) : float;
+ public function distance(array $a, array $b): float;
}
diff --git a/src/Phpml/Math/Distance/Chebyshev.php b/src/Phpml/Math/Distance/Chebyshev.php
index 40cdfbc..52e969c 100644
--- a/src/Phpml/Math/Distance/Chebyshev.php
+++ b/src/Phpml/Math/Distance/Chebyshev.php
@@ -12,7 +12,7 @@ class Chebyshev implements Distance
/**
* @throws InvalidArgumentException
*/
- public function distance(array $a, array $b) : float
+ public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
diff --git a/src/Phpml/Math/Distance/Euclidean.php b/src/Phpml/Math/Distance/Euclidean.php
index f6a87cf..4ecc576 100644
--- a/src/Phpml/Math/Distance/Euclidean.php
+++ b/src/Phpml/Math/Distance/Euclidean.php
@@ -12,7 +12,7 @@ class Euclidean implements Distance
/**
* @throws InvalidArgumentException
*/
- public function distance(array $a, array $b) : float
+ public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
@@ -30,7 +30,7 @@ class Euclidean implements Distance
/**
* Square of Euclidean distance
*/
- public function sqDistance(array $a, array $b) : float
+ public function sqDistance(array $a, array $b): float
{
return $this->distance($a, $b) ** 2;
}
diff --git a/src/Phpml/Math/Distance/Manhattan.php b/src/Phpml/Math/Distance/Manhattan.php
index 6d10b71..457333c 100644
--- a/src/Phpml/Math/Distance/Manhattan.php
+++ b/src/Phpml/Math/Distance/Manhattan.php
@@ -12,7 +12,7 @@ class Manhattan implements Distance
/**
* @throws InvalidArgumentException
*/
- public function distance(array $a, array $b) : float
+ public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
diff --git a/src/Phpml/Math/Distance/Minkowski.php b/src/Phpml/Math/Distance/Minkowski.php
index 17df39d..5ff7364 100644
--- a/src/Phpml/Math/Distance/Minkowski.php
+++ b/src/Phpml/Math/Distance/Minkowski.php
@@ -22,7 +22,7 @@ class Minkowski implements Distance
/**
* @throws InvalidArgumentException
*/
- public function distance(array $a, array $b) : float
+ public function distance(array $a, array $b): float
{
if (count($a) !== count($b)) {
throw InvalidArgumentException::arraySizeNotMatch();
diff --git a/src/Phpml/Math/Kernel.php b/src/Phpml/Math/Kernel.php
index 6d1461f..9a2cb97 100644
--- a/src/Phpml/Math/Kernel.php
+++ b/src/Phpml/Math/Kernel.php
@@ -7,10 +7,10 @@ namespace Phpml\Math;
interface Kernel
{
/**
- * @param float $a
- * @param float $b
+ * @param float|array $a
+ * @param float|array $b
*
- * @return float
+ * @return float|array
*/
public function compute($a, $b);
}
diff --git a/src/Phpml/Math/Kernel/RBF.php b/src/Phpml/Math/Kernel/RBF.php
index e47dbb5..4f9cfaf 100644
--- a/src/Phpml/Math/Kernel/RBF.php
+++ b/src/Phpml/Math/Kernel/RBF.php
@@ -23,12 +23,11 @@ class RBF implements Kernel
* @param array $a
* @param array $b
*/
- public function compute($a, $b)
+ public function compute($a, $b): float
{
$score = 2 * Product::scalar($a, $b);
$squares = Product::scalar($a, $a) + Product::scalar($b, $b);
- $result = exp(-$this->gamma * ($squares - $score));
- return $result;
+ return exp(-$this->gamma * ($squares - $score));
}
}
diff --git a/src/Phpml/Math/LinearAlgebra/EigenvalueDecomposition.php b/src/Phpml/Math/LinearAlgebra/EigenvalueDecomposition.php
index 6261d26..4d7f662 100644
--- a/src/Phpml/Math/LinearAlgebra/EigenvalueDecomposition.php
+++ b/src/Phpml/Math/LinearAlgebra/EigenvalueDecomposition.php
@@ -1,6 +1,7 @@
V;
+
+ // Always return the eigenvectors of length 1.0
+ $vectors = new Matrix($vectors);
+ $vectors = array_map(function ($vect) {
+ $sum = 0;
+ for ($i = 0; $i < count($vect); ++$i) {
+ $sum += $vect[$i] ** 2;
+ }
+
+ $sum = sqrt($sum);
+ for ($i = 0; $i < count($vect); ++$i) {
+ $vect[$i] /= $sum;
+ }
+
+ return $vect;
+ }, $vectors->transpose()->toArray());
+
+ return $vectors;
+ }
+
+ /**
+ * Return the real parts of the eigenvalues
+ * d = real(diag(D));
+ */
+ public function getRealEigenvalues(): array
+ {
+ return $this->d;
+ }
+
+ /**
+ * Return the imaginary parts of the eigenvalues
+ * d = imag(diag(D))
+ */
+ public function getImagEigenvalues(): array
+ {
+ return $this->e;
+ }
+
+ /**
+ * Return the block diagonal eigenvalue matrix
+ */
+ public function getDiagonalEigenvalues(): array
+ {
+ $D = [];
+
+ for ($i = 0; $i < $this->n; ++$i) {
+ $D[$i] = array_fill(0, $this->n, 0.0);
+ $D[$i][$i] = $this->d[$i];
+ if ($this->e[$i] == 0) {
+ continue;
+ }
+
+ $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
+ $D[$i][$o] = $this->e[$i];
+ }
+
+ return $D;
+ }
+
/**
* Symmetric Householder reduction to tridiagonal form.
*/
@@ -158,6 +226,7 @@ class EigenvalueDecomposition
for ($j = 0; $j < $i; ++$j) {
$this->e[$j] = 0.0;
}
+
// Apply similarity transformation to remaining columns.
for ($j = 0; $j < $i; ++$j) {
$f = $this->d[$j];
@@ -168,6 +237,7 @@ class EigenvalueDecomposition
$g += $this->V[$k][$j] * $this->d[$k];
$this->e[$k] += $this->V[$k][$j] * $f;
}
+
$this->e[$j] = $g;
}
@@ -185,16 +255,19 @@ class EigenvalueDecomposition
for ($j = 0; $j < $i; ++$j) {
$this->e[$j] -= $hh * $this->d[$j];
}
+
for ($j = 0; $j < $i; ++$j) {
$f = $this->d[$j];
$g = $this->e[$j];
for ($k = $j; $k <= $i_; ++$k) {
$this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]);
}
+
$this->d[$j] = $this->V[$i - 1][$j];
$this->V[$i][$j] = 0.0;
}
}
+
$this->d[$i] = $h;
}
@@ -207,16 +280,19 @@ class EigenvalueDecomposition
for ($k = 0; $k <= $i; ++$k) {
$this->d[$k] = $this->V[$k][$i + 1] / $h;
}
+
for ($j = 0; $j <= $i; ++$j) {
$g = 0.0;
for ($k = 0; $k <= $i; ++$k) {
$g += $this->V[$k][$i + 1] * $this->V[$k][$j];
}
+
for ($k = 0; $k <= $i; ++$k) {
$this->V[$k][$j] -= $g * $this->d[$k];
}
}
}
+
for ($k = 0; $k <= $i; ++$k) {
$this->V[$k][$i + 1] = 0.0;
}
@@ -241,6 +317,7 @@ class EigenvalueDecomposition
for ($i = 1; $i < $this->n; ++$i) {
$this->e[$i - 1] = $this->e[$i];
}
+
$this->e[$this->n - 1] = 0.0;
$f = 0.0;
$tst1 = 0.0;
@@ -254,8 +331,10 @@ class EigenvalueDecomposition
if (abs($this->e[$m]) <= $eps * $tst1) {
break;
}
+
++$m;
}
+
// If m == l, $this->d[l] is an eigenvalue,
// otherwise, iterate.
if ($m > $l) {
@@ -270,6 +349,7 @@ class EigenvalueDecomposition
if ($p < 0) {
$r *= -1;
}
+
$this->d[$l] = $this->e[$l] / ($p + $r);
$this->d[$l + 1] = $this->e[$l] * ($p + $r);
$dl1 = $this->d[$l + 1];
@@ -277,6 +357,7 @@ class EigenvalueDecomposition
for ($i = $l + 2; $i < $this->n; ++$i) {
$this->d[$i] -= $h;
}
+
$f += $h;
// Implicit QL transformation.
$p = $this->d[$m];
@@ -303,12 +384,14 @@ class EigenvalueDecomposition
$this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h;
}
}
+
$p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1;
$this->e[$l] = $s * $p;
$this->d[$l] = $c * $p;
// Check for convergence.
} while (abs($this->e[$l]) > $eps * $tst1);
}
+
$this->d[$l] = $this->d[$l] + $f;
$this->e[$l] = 0.0;
}
@@ -323,6 +406,7 @@ class EigenvalueDecomposition
$p = $this->d[$j];
}
}
+
if ($k != $i) {
$this->d[$k] = $this->d[$i];
$this->d[$i] = $p;
@@ -354,6 +438,7 @@ class EigenvalueDecomposition
for ($i = $m; $i <= $high; ++$i) {
$scale = $scale + abs($this->H[$i][$m - 1]);
}
+
if ($scale != 0.0) {
// Compute Householder transformation.
$h = 0.0;
@@ -361,10 +446,12 @@ class EigenvalueDecomposition
$this->ort[$i] = $this->H[$i][$m - 1] / $scale;
$h += $this->ort[$i] * $this->ort[$i];
}
+
$g = sqrt($h);
if ($this->ort[$m] > 0) {
$g *= -1;
}
+
$h -= $this->ort[$m] * $g;
$this->ort[$m] -= $g;
// Apply Householder similarity transformation
@@ -374,21 +461,25 @@ class EigenvalueDecomposition
for ($i = $high; $i >= $m; --$i) {
$f += $this->ort[$i] * $this->H[$i][$j];
}
+
$f /= $h;
for ($i = $m; $i <= $high; ++$i) {
$this->H[$i][$j] -= $f * $this->ort[$i];
}
}
+
for ($i = 0; $i <= $high; ++$i) {
$f = 0.0;
for ($j = $high; $j >= $m; --$j) {
$f += $this->ort[$j] * $this->H[$i][$j];
}
+
$f = $f / $h;
for ($j = $m; $j <= $high; ++$j) {
$this->H[$i][$j] -= $f * $this->ort[$j];
}
}
+
$this->ort[$m] = $scale * $this->ort[$m];
$this->H[$m][$m - 1] = $scale * $g;
}
@@ -400,16 +491,19 @@ class EigenvalueDecomposition
$this->V[$i][$j] = ($i == $j ? 1.0 : 0.0);
}
}
+
for ($m = $high - 1; $m >= $low + 1; --$m) {
if ($this->H[$m][$m - 1] != 0.0) {
for ($i = $m + 1; $i <= $high; ++$i) {
$this->ort[$i] = $this->H[$i][$m - 1];
}
+
for ($j = $m; $j <= $high; ++$j) {
$g = 0.0;
for ($i = $m; $i <= $high; ++$i) {
$g += $this->ort[$i] * $this->V[$i][$j];
}
+
// Double division avoids possible underflow
$g = ($g / $this->ort[$m]) / $this->H[$m][$m - 1];
for ($i = $m; $i <= $high; ++$i) {
@@ -469,6 +563,7 @@ class EigenvalueDecomposition
$this->d[$i] = $this->H[$i][$i];
$this->e[$i] = 0.0;
}
+
for ($j = max($i - 1, 0); $j < $nn; ++$j) {
$norm = $norm + abs($this->H[$i][$j]);
}
@@ -484,11 +579,14 @@ class EigenvalueDecomposition
if ($s == 0.0) {
$s = $norm;
}
+
if (abs($this->H[$l][$l - 1]) < $eps * $s) {
break;
}
+
--$l;
}
+
// Check for convergence
// One root found
if ($l == $n) {
@@ -513,11 +611,13 @@ class EigenvalueDecomposition
} else {
$z = $p - $z;
}
+
$this->d[$n - 1] = $x + $z;
$this->d[$n] = $this->d[$n - 1];
if ($z != 0.0) {
$this->d[$n] = $x - $w / $z;
}
+
$this->e[$n - 1] = 0.0;
$this->e[$n] = 0.0;
$x = $this->H[$n][$n - 1];
@@ -533,18 +633,21 @@ class EigenvalueDecomposition
$this->H[$n - 1][$j] = $q * $z + $p * $this->H[$n][$j];
$this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z;
}
+
// Column modification
for ($i = 0; $i <= $n; ++$i) {
$z = $this->H[$i][$n - 1];
$this->H[$i][$n - 1] = $q * $z + $p * $this->H[$i][$n];
$this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z;
}
+
// Accumulate transformations
for ($i = $low; $i <= $high; ++$i) {
$z = $this->V[$i][$n - 1];
$this->V[$i][$n - 1] = $q * $z + $p * $this->V[$i][$n];
$this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z;
}
+
// Complex pair
} else {
$this->d[$n - 1] = $x + $p;
@@ -552,6 +655,7 @@ class EigenvalueDecomposition
$this->e[$n - 1] = $z;
$this->e[$n] = -$z;
}
+
$n = $n - 2;
$iter = 0;
// No convergence yet
@@ -564,16 +668,19 @@ class EigenvalueDecomposition
$y = $this->H[$n - 1][$n - 1];
$w = $this->H[$n][$n - 1] * $this->H[$n - 1][$n];
}
+
// Wilkinson's original ad hoc shift
if ($iter == 10) {
$exshift += $x;
for ($i = $low; $i <= $n; ++$i) {
$this->H[$i][$i] -= $x;
}
+
$s = abs($this->H[$n][$n - 1]) + abs($this->H[$n - 1][$n - 2]);
$x = $y = 0.75 * $s;
$w = -0.4375 * $s * $s;
}
+
// MATLAB's new ad hoc shift
if ($iter == 30) {
$s = ($y - $x) / 2.0;
@@ -583,14 +690,17 @@ class EigenvalueDecomposition
if ($y < $x) {
$s = -$s;
}
+
$s = $x - $w / (($y - $x) / 2.0 + $s);
for ($i = $low; $i <= $n; ++$i) {
$this->H[$i][$i] -= $s;
}
+
$exshift += $s;
$x = $y = $w = 0.964;
}
}
+
// Could check iteration count here.
$iter = $iter + 1;
// Look for two consecutive small sub-diagonal elements
@@ -609,18 +719,22 @@ class EigenvalueDecomposition
if ($m == $l) {
break;
}
+
if (abs($this->H[$m][$m - 1]) * (abs($q) + abs($r)) <
$eps * (abs($p) * (abs($this->H[$m - 1][$m - 1]) + abs($z) + abs($this->H[$m + 1][$m + 1])))) {
break;
}
+
--$m;
}
+
for ($i = $m + 2; $i <= $n; ++$i) {
$this->H[$i][$i - 2] = 0.0;
if ($i > $m + 2) {
$this->H[$i][$i - 3] = 0.0;
}
}
+
// Double QR step involving rows l:n and columns m:n
for ($k = $m; $k <= $n - 1; ++$k) {
$notlast = ($k != $n - 1);
@@ -635,19 +749,23 @@ class EigenvalueDecomposition
$r = $r / $x;
}
}
+
if ($x == 0.0) {
break;
}
+
$s = sqrt($p * $p + $q * $q + $r * $r);
if ($p < 0) {
$s = -$s;
}
+
if ($s != 0) {
if ($k != $m) {
$this->H[$k][$k - 1] = -$s * $x;
} elseif ($l != $m) {
$this->H[$k][$k - 1] = -$this->H[$k][$k - 1];
}
+
$p = $p + $s;
$x = $p / $s;
$y = $q / $s;
@@ -661,9 +779,11 @@ class EigenvalueDecomposition
$p = $p + $r * $this->H[$k + 2][$j];
$this->H[$k + 2][$j] = $this->H[$k + 2][$j] - $p * $z;
}
+
$this->H[$k][$j] = $this->H[$k][$j] - $p * $x;
$this->H[$k + 1][$j] = $this->H[$k + 1][$j] - $p * $y;
}
+
// Column modification
for ($i = 0; $i <= min($n, $k + 3); ++$i) {
$p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k + 1];
@@ -671,9 +791,11 @@ class EigenvalueDecomposition
$p = $p + $z * $this->H[$i][$k + 2];
$this->H[$i][$k + 2] = $this->H[$i][$k + 2] - $p * $r;
}
+
$this->H[$i][$k] = $this->H[$i][$k] - $p;
$this->H[$i][$k + 1] = $this->H[$i][$k + 1] - $p * $q;
}
+
// Accumulate transformations
for ($i = $low; $i <= $high; ++$i) {
$p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k + 1];
@@ -681,6 +803,7 @@ class EigenvalueDecomposition
$p = $p + $z * $this->V[$i][$k + 2];
$this->V[$i][$k + 2] = $this->V[$i][$k + 2] - $p * $r;
}
+
$this->V[$i][$k] = $this->V[$i][$k] - $p;
$this->V[$i][$k + 1] = $this->V[$i][$k + 1] - $p * $q;
}
@@ -719,6 +842,7 @@ class EigenvalueDecomposition
} else {
$this->H[$i][$n] = -$r / ($eps * $norm);
}
+
// Solve real equations
} else {
$x = $this->H[$i][$i + 1];
@@ -732,6 +856,7 @@ class EigenvalueDecomposition
$this->H[$i + 1][$n] = (-$s - $y * $t) / $z;
}
}
+
// Overflow control
$t = abs($this->H[$i][$n]);
if (($eps * $t) * $t > 1) {
@@ -741,6 +866,7 @@ class EigenvalueDecomposition
}
}
}
+
// Complex vector
} elseif ($q < 0) {
$l = $n - 1;
@@ -753,6 +879,7 @@ class EigenvalueDecomposition
$this->H[$n - 1][$n - 1] = $this->cdivr;
$this->H[$n - 1][$n] = $this->cdivi;
}
+
$this->H[$n][$n - 1] = 0.0;
$this->H[$n][$n] = 1.0;
for ($i = $n - 2; $i >= 0; --$i) {
@@ -763,6 +890,7 @@ class EigenvalueDecomposition
$ra = $ra + $this->H[$i][$j] * $this->H[$j][$n - 1];
$sa = $sa + $this->H[$i][$j] * $this->H[$j][$n];
}
+
$w = $this->H[$i][$i] - $p;
if ($this->e[$i] < 0.0) {
$z = $w;
@@ -783,6 +911,7 @@ class EigenvalueDecomposition
if ($vr == 0.0 & $vi == 0.0) {
$vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z));
}
+
$this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi);
$this->H[$i][$n - 1] = $this->cdivr;
$this->H[$i][$n] = $this->cdivi;
@@ -795,6 +924,7 @@ class EigenvalueDecomposition
$this->H[$i + 1][$n] = $this->cdivi;
}
}
+
// Overflow control
$t = max(abs($this->H[$i][$n - 1]), abs($this->H[$i][$n]));
if (($eps * $t) * $t > 1) {
@@ -824,81 +954,9 @@ class EigenvalueDecomposition
for ($k = $low; $k <= min($j, $high); ++$k) {
$z = $z + $this->V[$i][$k] * $this->H[$k][$j];
}
+
$this->V[$i][$j] = $z;
}
}
}
-
- /**
- * Return the eigenvector matrix
- *
- * @return array
- */
- public function getEigenvectors()
- {
- $vectors = $this->V;
-
- // Always return the eigenvectors of length 1.0
- $vectors = new Matrix($vectors);
- $vectors = array_map(function ($vect) {
- $sum = 0;
- for ($i = 0; $i < count($vect); ++$i) {
- $sum += $vect[$i] ** 2;
- }
-
- $sum = sqrt($sum);
- for ($i = 0; $i < count($vect); ++$i) {
- $vect[$i] /= $sum;
- }
-
- return $vect;
- }, $vectors->transpose()->toArray());
-
- return $vectors;
- }
-
- /**
- * Return the real parts of the eigenvalues
- * d = real(diag(D));
- *
- * @return array
- */
- public function getRealEigenvalues()
- {
- return $this->d;
- }
-
- /**
- * Return the imaginary parts of the eigenvalues
- * d = imag(diag(D))
- *
- * @return array
- */
- public function getImagEigenvalues()
- {
- return $this->e;
- }
-
- /**
- * Return the block diagonal eigenvalue matrix
- *
- * @return array
- */
- public function getDiagonalEigenvalues()
- {
- $D = [];
-
- for ($i = 0; $i < $this->n; ++$i) {
- $D[$i] = array_fill(0, $this->n, 0.0);
- $D[$i][$i] = $this->d[$i];
- if ($this->e[$i] == 0) {
- continue;
- }
-
- $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1;
- $D[$i][$o] = $this->e[$i];
- }
-
- return $D;
- }
}
diff --git a/src/Phpml/Math/LinearAlgebra/LUDecomposition.php b/src/Phpml/Math/LinearAlgebra/LUDecomposition.php
index 164a72f..6ebd8cb 100644
--- a/src/Phpml/Math/LinearAlgebra/LUDecomposition.php
+++ b/src/Phpml/Math/LinearAlgebra/LUDecomposition.php
@@ -1,6 +1,7 @@
m; ++$i) {
$this->piv[$i] = $i;
}
+
$this->pivsign = 1;
$LUcolj = [];
@@ -99,6 +101,7 @@ class LUDecomposition
for ($i = 0; $i < $this->m; ++$i) {
$LUcolj[$i] = &$this->LU[$i][$j];
}
+
// Apply previous transformations.
for ($i = 0; $i < $this->m; ++$i) {
$LUrowi = $this->LU[$i];
@@ -108,8 +111,10 @@ class LUDecomposition
for ($k = 0; $k < $kmax; ++$k) {
$s += $LUrowi[$k] * $LUcolj[$k];
}
+
$LUrowi[$j] = $LUcolj[$i] -= $s;
}
+
// Find pivot and exchange if necessary.
$p = $j;
for ($i = $j + 1; $i < $this->m; ++$i) {
@@ -117,17 +122,20 @@ class LUDecomposition
$p = $i;
}
}
+
if ($p != $j) {
for ($k = 0; $k < $this->n; ++$k) {
$t = $this->LU[$p][$k];
$this->LU[$p][$k] = $this->LU[$j][$k];
$this->LU[$j][$k] = $t;
}
+
$k = $this->piv[$p];
$this->piv[$p] = $this->piv[$j];
$this->piv[$j] = $k;
$this->pivsign = $this->pivsign * -1;
}
+
// Compute multipliers.
if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) {
for ($i = $j + 1; $i < $this->m; ++$i) {
@@ -142,7 +150,7 @@ class LUDecomposition
*
* @return Matrix Lower triangular factor
*/
- public function getL() : Matrix
+ public function getL(): Matrix
{
$L = [];
for ($i = 0; $i < $this->m; ++$i) {
@@ -165,7 +173,7 @@ class LUDecomposition
*
* @return Matrix Upper triangular factor
*/
- public function getU() : Matrix
+ public function getU(): Matrix
{
$U = [];
for ($i = 0; $i < $this->n; ++$i) {
@@ -186,7 +194,7 @@ class LUDecomposition
*
* @return array Pivot vector
*/
- public function getPivot() : array
+ public function getPivot(): array
{
return $this->piv;
}
@@ -247,7 +255,7 @@ class LUDecomposition
*
* @throws MatrixException
*/
- public function solve(Matrix $B) : array
+ public function solve(Matrix $B): array
{
if ($B->getRows() != $this->m) {
throw MatrixException::notSquareMatrix();
@@ -268,11 +276,13 @@ class LUDecomposition
}
}
}
+
// Solve U*X = Y;
for ($k = $this->n - 1; $k >= 0; --$k) {
for ($j = 0; $j < $nx; ++$j) {
$X[$k][$j] /= $this->LU[$k][$k];
}
+
for ($i = 0; $i < $k; ++$i) {
for ($j = 0; $j < $nx; ++$j) {
$X[$i][$j] -= $X[$k][$j] * $this->LU[$i][$k];
@@ -283,7 +293,7 @@ class LUDecomposition
return $X;
}
- protected function getSubMatrix(array $matrix, array $RL, int $j0, int $jF) : array
+ protected function getSubMatrix(array $matrix, array $RL, int $j0, int $jF): array
{
$m = count($RL);
$n = $jF - $j0;
diff --git a/src/Phpml/Math/Matrix.php b/src/Phpml/Math/Matrix.php
index 6145521..7c1ff3e 100644
--- a/src/Phpml/Math/Matrix.php
+++ b/src/Phpml/Math/Matrix.php
@@ -13,7 +13,7 @@ class Matrix
/**
* @var array
*/
- private $matrix;
+ private $matrix = [];
/**
* @var int
@@ -56,7 +56,7 @@ class Matrix
$this->matrix = $matrix;
}
- public static function fromFlatArray(array $array) : Matrix
+ public static function fromFlatArray(array $array): self
{
$matrix = [];
foreach ($array as $value) {
@@ -66,12 +66,12 @@ class Matrix
return new self($matrix);
}
- public function toArray() : array
+ public function toArray(): array
{
return $this->matrix;
}
- public function toScalar() : float
+ public function toScalar(): float
{
return $this->matrix[0][0];
}
@@ -89,7 +89,7 @@ class Matrix
/**
* @throws MatrixException
*/
- public function getColumnValues($column) : array
+ public function getColumnValues($column): array
{
if ($column >= $this->columns) {
throw MatrixException::columnOutOfRange();
@@ -123,7 +123,7 @@ class Matrix
return $this->columns === $this->rows;
}
- public function transpose() : Matrix
+ public function transpose(): self
{
if ($this->rows == 1) {
$matrix = array_map(function ($el) {
@@ -136,7 +136,7 @@ class Matrix
return new self($matrix, false);
}
- public function multiply(Matrix $matrix) : Matrix
+ public function multiply(self $matrix): self
{
if ($this->columns != $matrix->getRows()) {
throw InvalidArgumentException::inconsistentMatrixSupplied();
@@ -157,7 +157,7 @@ class Matrix
return new self($product, false);
}
- public function divideByScalar($value) : Matrix
+ public function divideByScalar($value): self
{
$newMatrix = [];
for ($i = 0; $i < $this->rows; ++$i) {
@@ -169,7 +169,7 @@ class Matrix
return new self($newMatrix, false);
}
- public function multiplyByScalar($value) : Matrix
+ public function multiplyByScalar($value): self
{
$newMatrix = [];
for ($i = 0; $i < $this->rows; ++$i) {
@@ -184,7 +184,7 @@ class Matrix
/**
* Element-wise addition of the matrix with another one
*/
- public function add(Matrix $other) : Matrix
+ public function add(self $other): self
{
return $this->_add($other);
}
@@ -192,15 +192,74 @@ class Matrix
/**
* Element-wise subtracting of another matrix from this one
*/
- public function subtract(Matrix $other) : Matrix
+ public function subtract(self $other): self
{
return $this->_add($other, -1);
}
+ public function inverse(): self
+ {
+ if (!$this->isSquare()) {
+ throw MatrixException::notSquareMatrix();
+ }
+
+ $LU = new LUDecomposition($this);
+ $identity = $this->getIdentity();
+ $inverse = $LU->solve($identity);
+
+ return new self($inverse, false);
+ }
+
+ public function crossOut(int $row, int $column): self
+ {
+ $newMatrix = [];
+ $r = 0;
+ for ($i = 0; $i < $this->rows; ++$i) {
+ $c = 0;
+ if ($row != $i) {
+ for ($j = 0; $j < $this->columns; ++$j) {
+ if ($column != $j) {
+ $newMatrix[$r][$c] = $this->matrix[$i][$j];
+ ++$c;
+ }
+ }
+
+ ++$r;
+ }
+ }
+
+ return new self($newMatrix, false);
+ }
+
+ public function isSingular(): bool
+ {
+ return $this->getDeterminant() == 0;
+ }
+
+ /**
+ * Returns the transpose of given array
+ */
+ public static function transposeArray(array $array): array
+ {
+ return (new self($array, false))->transpose()->toArray();
+ }
+
+ /**
+ * Returns the dot product of two arrays
+ * Matrix::dot(x, y) ==> x.y'
+ */
+ public static function dot(array $array1, array $array2): array
+ {
+ $m1 = new self($array1, false);
+ $m2 = new self($array2, false);
+
+ return $m1->multiply($m2->transpose())->toArray()[0];
+ }
+
/**
* Element-wise addition or substraction depending on the given sign parameter
*/
- protected function _add(Matrix $other, int $sign = 1) : Matrix
+ protected function _add(self $other, int $sign = 1): self
{
$a1 = $this->toArray();
$a2 = $other->toArray();
@@ -215,23 +274,10 @@ class Matrix
return new self($newMatrix, false);
}
- public function inverse() : Matrix
- {
- if (!$this->isSquare()) {
- throw MatrixException::notSquareMatrix();
- }
-
- $LU = new LUDecomposition($this);
- $identity = $this->getIdentity();
- $inverse = $LU->solve($identity);
-
- return new self($inverse, false);
- }
-
/**
* Returns diagonal identity matrix of the same size of this matrix
*/
- protected function getIdentity() : Matrix
+ protected function getIdentity(): self
{
$array = array_fill(0, $this->rows, array_fill(0, $this->columns, 0));
for ($i = 0; $i < $this->rows; ++$i) {
@@ -240,49 +286,4 @@ class Matrix
return new self($array, false);
}
-
- public function crossOut(int $row, int $column) : Matrix
- {
- $newMatrix = [];
- $r = 0;
- for ($i = 0; $i < $this->rows; ++$i) {
- $c = 0;
- if ($row != $i) {
- for ($j = 0; $j < $this->columns; ++$j) {
- if ($column != $j) {
- $newMatrix[$r][$c] = $this->matrix[$i][$j];
- ++$c;
- }
- }
- ++$r;
- }
- }
-
- return new self($newMatrix, false);
- }
-
- public function isSingular() : bool
- {
- return 0 == $this->getDeterminant();
- }
-
- /**
- * Returns the transpose of given array
- */
- public static function transposeArray(array $array) : array
- {
- return (new self($array, false))->transpose()->toArray();
- }
-
- /**
- * Returns the dot product of two arrays
- * Matrix::dot(x, y) ==> x.y'
- */
- public static function dot(array $array1, array $array2) : array
- {
- $m1 = new self($array1, false);
- $m2 = new self($array2, false);
-
- return $m1->multiply($m2->transpose())->toArray()[0];
- }
}
diff --git a/src/Phpml/Math/Set.php b/src/Phpml/Math/Set.php
index c5c5aa7..a67d5c2 100644
--- a/src/Phpml/Math/Set.php
+++ b/src/Phpml/Math/Set.php
@@ -4,12 +4,15 @@ declare(strict_types=1);
namespace Phpml\Math;
-class Set implements \IteratorAggregate
+use ArrayIterator;
+use IteratorAggregate;
+
+class Set implements IteratorAggregate
{
/**
* @var string[]|int[]|float[]
*/
- private $elements;
+ private $elements = [];
/**
* @param string[]|int[]|float[] $elements
@@ -22,7 +25,7 @@ class Set implements \IteratorAggregate
/**
* Creates the union of A and B.
*/
- public static function union(Set $a, Set $b) : Set
+ public static function union(self $a, self $b): self
{
return new self(array_merge($a->toArray(), $b->toArray()));
}
@@ -30,7 +33,7 @@ class Set implements \IteratorAggregate
/**
* Creates the intersection of A and B.
*/
- public static function intersection(Set $a, Set $b) : Set
+ public static function intersection(self $a, self $b): self
{
return new self(array_intersect($a->toArray(), $b->toArray()));
}
@@ -38,7 +41,7 @@ class Set implements \IteratorAggregate
/**
* Creates the difference of A and B.
*/
- public static function difference(Set $a, Set $b) : Set
+ public static function difference(self $a, self $b): self
{
return new self(array_diff($a->toArray(), $b->toArray()));
}
@@ -48,7 +51,7 @@ class Set implements \IteratorAggregate
*
* @return Set[]
*/
- public static function cartesian(Set $a, Set $b) : array
+ public static function cartesian(self $a, self $b): array
{
$cartesian = [];
@@ -66,7 +69,7 @@ class Set implements \IteratorAggregate
*
* @return Set[]
*/
- public static function power(Set $a) : array
+ public static function power(self $a): array
{
$power = [new self()];
@@ -79,24 +82,10 @@ class Set implements \IteratorAggregate
return $power;
}
- /**
- * Removes duplicates and rewrites index.
- *
- * @param string[]|int[]|float[] $elements
- *
- * @return string[]|int[]|float[]
- */
- private static function sanitize(array $elements) : array
- {
- sort($elements, SORT_ASC);
-
- return array_values(array_unique($elements, SORT_ASC));
- }
-
/**
* @param string|int|float $element
*/
- public function add($element) : Set
+ public function add($element): self
{
return $this->addAll([$element]);
}
@@ -104,7 +93,7 @@ class Set implements \IteratorAggregate
/**
* @param string[]|int[]|float[] $elements
*/
- public function addAll(array $elements) : Set
+ public function addAll(array $elements): self
{
$this->elements = self::sanitize(array_merge($this->elements, $elements));
@@ -114,7 +103,7 @@ class Set implements \IteratorAggregate
/**
* @param string|int|float $element
*/
- public function remove($element) : Set
+ public function remove($element): self
{
return $this->removeAll([$element]);
}
@@ -122,7 +111,7 @@ class Set implements \IteratorAggregate
/**
* @param string[]|int[]|float[] $elements
*/
- public function removeAll(array $elements) : Set
+ public function removeAll(array $elements): self
{
$this->elements = self::sanitize(array_diff($this->elements, $elements));
@@ -132,7 +121,7 @@ class Set implements \IteratorAggregate
/**
* @param string|int|float $element
*/
- public function contains($element) : bool
+ public function contains($element): bool
{
return $this->containsAll([$element]);
}
@@ -140,7 +129,7 @@ class Set implements \IteratorAggregate
/**
* @param string[]|int[]|float[] $elements
*/
- public function containsAll(array $elements) : bool
+ public function containsAll(array $elements): bool
{
return !array_diff($elements, $this->elements);
}
@@ -148,23 +137,37 @@ class Set implements \IteratorAggregate
/**
* @return string[]|int[]|float[]
*/
- public function toArray() : array
+ public function toArray(): array
{
return $this->elements;
}
- public function getIterator() : \ArrayIterator
+ public function getIterator(): ArrayIterator
{
- return new \ArrayIterator($this->elements);
+ return new ArrayIterator($this->elements);
}
- public function isEmpty() : bool
+ public function isEmpty(): bool
{
return $this->cardinality() == 0;
}
- public function cardinality() : int
+ public function cardinality(): int
{
return count($this->elements);
}
+
+ /**
+ * Removes duplicates and rewrites index.
+ *
+ * @param string[]|int[]|float[] $elements
+ *
+ * @return string[]|int[]|float[]
+ */
+ private static function sanitize(array $elements): array
+ {
+ sort($elements, SORT_ASC);
+
+ return array_values(array_unique($elements, SORT_ASC));
+ }
}
diff --git a/src/Phpml/Math/Statistic/Correlation.php b/src/Phpml/Math/Statistic/Correlation.php
index 9bcf271..8803cbf 100644
--- a/src/Phpml/Math/Statistic/Correlation.php
+++ b/src/Phpml/Math/Statistic/Correlation.php
@@ -14,7 +14,7 @@ class Correlation
*
* @throws InvalidArgumentException
*/
- public static function pearson(array $x, array $y) : float
+ public static function pearson(array $x, array $y): float
{
if (count($x) !== count($y)) {
throw InvalidArgumentException::arraySizeNotMatch();
diff --git a/src/Phpml/Math/Statistic/Covariance.php b/src/Phpml/Math/Statistic/Covariance.php
index 627a8a6..a669a7f 100644
--- a/src/Phpml/Math/Statistic/Covariance.php
+++ b/src/Phpml/Math/Statistic/Covariance.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Phpml\Math\Statistic;
+use Exception;
use Phpml\Exception\InvalidArgumentException;
class Covariance
@@ -13,7 +14,7 @@ class Covariance
*
* @throws InvalidArgumentException
*/
- public static function fromXYArrays(array $x, array $y, bool $sample = true, ?float $meanX = null, ?float $meanY = null) : float
+ 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();
@@ -51,7 +52,7 @@ class Covariance
* @throws InvalidArgumentException
* @throws \Exception
*/
- public static function fromDataset(array $data, int $i, int $k, bool $sample = true, ?float $meanX = null, ?float $meanY = null) : float
+ 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();
@@ -63,7 +64,7 @@ class Covariance
}
if ($i < 0 || $k < 0 || $i >= $n || $k >= $n) {
- throw new \Exception('Given indices i and k do not match with the dimensionality of data');
+ throw new Exception('Given indices i and k do not match with the dimensionality of data');
}
if ($meanX === null || $meanY === null) {
@@ -92,10 +93,12 @@ class Covariance
if ($index == $i) {
$val[0] = $col - $meanX;
}
+
if ($index == $k) {
$val[1] = $col - $meanY;
}
}
+
$sum += $val[0] * $val[1];
}
}
@@ -112,7 +115,7 @@ class Covariance
*
* @param array|null $means
*/
- public static function covarianceMatrix(array $data, ?array $means = null) : array
+ public static function covarianceMatrix(array $data, ?array $means = null): array
{
$n = count($data[0]);
diff --git a/src/Phpml/Math/Statistic/Gaussian.php b/src/Phpml/Math/Statistic/Gaussian.php
index bdf8308..24aaeea 100644
--- a/src/Phpml/Math/Statistic/Gaussian.php
+++ b/src/Phpml/Math/Statistic/Gaussian.php
@@ -41,7 +41,7 @@ class Gaussian
* Returns probability density value of the given $value based on
* given standard deviation and the mean
*/
- public static function distributionPdf(float $mean, float $std, float $value) : float
+ public static function distributionPdf(float $mean, float $std, float $value): float
{
$normal = new self($mean, $std);
diff --git a/src/Phpml/Math/Statistic/Mean.php b/src/Phpml/Math/Statistic/Mean.php
index eb1baef..8791a65 100644
--- a/src/Phpml/Math/Statistic/Mean.php
+++ b/src/Phpml/Math/Statistic/Mean.php
@@ -11,7 +11,7 @@ class Mean
/**
* @throws InvalidArgumentException
*/
- public static function arithmetic(array $numbers) : float
+ public static function arithmetic(array $numbers): float
{
self::checkArrayLength($numbers);
@@ -32,7 +32,7 @@ class Mean
sort($numbers, SORT_NUMERIC);
$median = $numbers[$middleIndex];
- if (0 === $count % 2) {
+ if ($count % 2 === 0) {
$median = ($median + $numbers[$middleIndex - 1]) / 2;
}
diff --git a/src/Phpml/Math/Statistic/StandardDeviation.php b/src/Phpml/Math/Statistic/StandardDeviation.php
index 3da8ef5..8a0d241 100644
--- a/src/Phpml/Math/Statistic/StandardDeviation.php
+++ b/src/Phpml/Math/Statistic/StandardDeviation.php
@@ -13,7 +13,7 @@ class StandardDeviation
*
* @throws InvalidArgumentException
*/
- public static function population(array $a, bool $sample = true) : float
+ public static function population(array $a, bool $sample = true): float
{
if (empty($a)) {
throw InvalidArgumentException::arrayCantBeEmpty();
diff --git a/src/Phpml/Metric/ClassificationReport.php b/src/Phpml/Metric/ClassificationReport.php
index ae4c11a..0f27b06 100644
--- a/src/Phpml/Metric/ClassificationReport.php
+++ b/src/Phpml/Metric/ClassificationReport.php
@@ -51,27 +51,27 @@ class ClassificationReport
$this->computeAverage();
}
- public function getPrecision() : array
+ public function getPrecision(): array
{
return $this->precision;
}
- public function getRecall() : array
+ public function getRecall(): array
{
return $this->recall;
}
- public function getF1score() : array
+ public function getF1score(): array
{
return $this->f1score;
}
- public function getSupport() : array
+ public function getSupport(): array
{
return $this->support;
}
- public function getAverage() : array
+ public function getAverage(): array
{
return $this->average;
}
@@ -93,6 +93,7 @@ class ClassificationReport
$this->average[$metric] = 0.0;
continue;
}
+
$this->average[$metric] = array_sum($values) / count($values);
}
}
@@ -102,7 +103,8 @@ class ClassificationReport
*/
private function computePrecision(int $truePositive, int $falsePositive)
{
- if (0 == ($divider = $truePositive + $falsePositive)) {
+ $divider = $truePositive + $falsePositive;
+ if ($divider == 0) {
return 0.0;
}
@@ -114,23 +116,25 @@ class ClassificationReport
*/
private function computeRecall(int $truePositive, int $falseNegative)
{
- if (0 == ($divider = $truePositive + $falseNegative)) {
+ $divider = $truePositive + $falseNegative;
+ if ($divider == 0) {
return 0.0;
}
return $truePositive / $divider;
}
- private function computeF1Score(float $precision, float $recall) : float
+ private function computeF1Score(float $precision, float $recall): float
{
- if (0 == ($divider = $precision + $recall)) {
+ $divider = $precision + $recall;
+ if ($divider == 0) {
return 0.0;
}
return 2.0 * (($precision * $recall) / $divider);
}
- private static function getLabelIndexedArray(array $actualLabels, array $predictedLabels) : array
+ private static function getLabelIndexedArray(array $actualLabels, array $predictedLabels): array
{
$labels = array_values(array_unique(array_merge($actualLabels, $predictedLabels)));
sort($labels);
diff --git a/src/Phpml/Metric/ConfusionMatrix.php b/src/Phpml/Metric/ConfusionMatrix.php
index 0f0b738..e86a8ed 100644
--- a/src/Phpml/Metric/ConfusionMatrix.php
+++ b/src/Phpml/Metric/ConfusionMatrix.php
@@ -6,7 +6,7 @@ namespace Phpml\Metric;
class ConfusionMatrix
{
- public static function compute(array $actualLabels, array $predictedLabels, ?array $labels = null) : array
+ public static function compute(array $actualLabels, array $predictedLabels, ?array $labels = null): array
{
$labels = $labels ? array_flip($labels) : self::getUniqueLabels($actualLabels);
$matrix = self::generateMatrixWithZeros($labels);
@@ -31,7 +31,7 @@ class ConfusionMatrix
return $matrix;
}
- private static function generateMatrixWithZeros(array $labels) : array
+ private static function generateMatrixWithZeros(array $labels): array
{
$count = count($labels);
$matrix = [];
@@ -43,7 +43,7 @@ class ConfusionMatrix
return $matrix;
}
- private static function getUniqueLabels(array $labels) : array
+ private static function getUniqueLabels(array $labels): array
{
$labels = array_values(array_unique($labels));
sort($labels);
diff --git a/src/Phpml/ModelManager.php b/src/Phpml/ModelManager.php
index 2fa14f5..ebcdbe4 100644
--- a/src/Phpml/ModelManager.php
+++ b/src/Phpml/ModelManager.php
@@ -26,7 +26,7 @@ class ModelManager
}
}
- public function restoreFromFile(string $filepath) : Estimator
+ public function restoreFromFile(string $filepath): Estimator
{
if (!file_exists($filepath) || !is_readable($filepath)) {
throw FileException::cantOpenFile(basename($filepath));
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction.php b/src/Phpml/NeuralNetwork/ActivationFunction.php
index 65ba7b4..5b91425 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction.php
@@ -9,5 +9,5 @@ interface ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float;
+ public function compute($value): float;
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/BinaryStep.php b/src/Phpml/NeuralNetwork/ActivationFunction/BinaryStep.php
index 75b2ff1..764bc4e 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/BinaryStep.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/BinaryStep.php
@@ -11,7 +11,7 @@ class BinaryStep implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return $value >= 0 ? 1.0 : 0.0;
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/Gaussian.php b/src/Phpml/NeuralNetwork/ActivationFunction/Gaussian.php
index 081b8a5..da428a4 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/Gaussian.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/Gaussian.php
@@ -11,7 +11,7 @@ class Gaussian implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return exp(-pow($value, 2));
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/HyperbolicTangent.php b/src/Phpml/NeuralNetwork/ActivationFunction/HyperbolicTangent.php
index 5c66fd9..6378606 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/HyperbolicTangent.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/HyperbolicTangent.php
@@ -21,7 +21,7 @@ class HyperbolicTangent implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return tanh($this->beta * $value);
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/PReLU.php b/src/Phpml/NeuralNetwork/ActivationFunction/PReLU.php
index 60ade03..fc7ff62 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/PReLU.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/PReLU.php
@@ -21,7 +21,7 @@ class PReLU implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return $value >= 0 ? $value : $this->beta * $value;
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/Sigmoid.php b/src/Phpml/NeuralNetwork/ActivationFunction/Sigmoid.php
index dec45a2..4ae9603 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/Sigmoid.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/Sigmoid.php
@@ -21,7 +21,7 @@ class Sigmoid implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return 1 / (1 + exp(-$this->beta * $value));
}
diff --git a/src/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLU.php b/src/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLU.php
index dbe8ee6..2bb1cc7 100644
--- a/src/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLU.php
+++ b/src/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLU.php
@@ -21,7 +21,7 @@ class ThresholdedReLU implements ActivationFunction
/**
* @param float|int $value
*/
- public function compute($value) : float
+ public function compute($value): float
{
return $value > $this->theta ? $value : 0.0;
}
diff --git a/src/Phpml/NeuralNetwork/Layer.php b/src/Phpml/NeuralNetwork/Layer.php
index c70bdb3..7424348 100644
--- a/src/Phpml/NeuralNetwork/Layer.php
+++ b/src/Phpml/NeuralNetwork/Layer.php
@@ -28,20 +28,6 @@ class Layer
}
}
- /**
- * @param ActivationFunction|null $activationFunction
- *
- * @return Neuron
- */
- private function createNode(string $nodeClass, ?ActivationFunction $activationFunction = null)
- {
- if (Neuron::class == $nodeClass) {
- return new Neuron($activationFunction);
- }
-
- return new $nodeClass();
- }
-
public function addNode(Node $node): void
{
$this->nodes[] = $node;
@@ -50,8 +36,20 @@ class Layer
/**
* @return Node[]
*/
- public function getNodes() : array
+ public function getNodes(): array
{
return $this->nodes;
}
+
+ /**
+ * @return Neuron
+ */
+ private function createNode(string $nodeClass, ?ActivationFunction $activationFunction = null): Node
+ {
+ if ($nodeClass == Neuron::class) {
+ return new Neuron($activationFunction);
+ }
+
+ return new $nodeClass();
+ }
}
diff --git a/src/Phpml/NeuralNetwork/Network.php b/src/Phpml/NeuralNetwork/Network.php
index af04f4a..c2248a6 100644
--- a/src/Phpml/NeuralNetwork/Network.php
+++ b/src/Phpml/NeuralNetwork/Network.php
@@ -8,20 +8,15 @@ interface Network
{
/**
* @param mixed $input
- *
- * @return self
*/
- public function setInput($input);
+ public function setInput($input): self;
- /**
- * @return array
- */
- public function getOutput() : array;
+ public function getOutput(): array;
public function addLayer(Layer $layer);
/**
* @return Layer[]
*/
- public function getLayers() : array;
+ public function getLayers(): array;
}
diff --git a/src/Phpml/NeuralNetwork/Network/LayeredNetwork.php b/src/Phpml/NeuralNetwork/Network/LayeredNetwork.php
index 3baa5ac..4f05398 100644
--- a/src/Phpml/NeuralNetwork/Network/LayeredNetwork.php
+++ b/src/Phpml/NeuralNetwork/Network/LayeredNetwork.php
@@ -14,7 +14,7 @@ abstract class LayeredNetwork implements Network
/**
* @var Layer[]
*/
- protected $layers;
+ protected $layers = [];
public function addLayer(Layer $layer): void
{
@@ -24,7 +24,7 @@ abstract class LayeredNetwork implements Network
/**
* @return Layer[]
*/
- public function getLayers() : array
+ public function getLayers(): array
{
return $this->layers;
}
@@ -39,7 +39,7 @@ abstract class LayeredNetwork implements Network
return $this->layers[count($this->layers) - 1];
}
- public function getOutput() : array
+ public function getOutput(): array
{
$result = [];
foreach ($this->getOutputLayer()->getNodes() as $neuron) {
@@ -54,7 +54,7 @@ abstract class LayeredNetwork implements Network
*
* @return $this
*/
- public function setInput($input)
+ public function setInput($input): Network
{
$firstLayer = $this->layers[0];
diff --git a/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php b/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php
index 94a8423..a38e952 100644
--- a/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php
+++ b/src/Phpml/NeuralNetwork/Network/MultilayerPerceptron.php
@@ -20,41 +20,36 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
{
use Predictable;
- /**
- * @var int
- */
- private $inputLayerFeatures;
-
- /**
- * @var array
- */
- private $hiddenLayers;
-
/**
* @var array
*/
protected $classes = [];
- /**
- * @var int
- */
- private $iterations;
-
/**
* @var ActivationFunction
*/
protected $activationFunction;
- /**
- * @var float
- */
- private $learningRate;
-
/**
* @var Backpropagation
*/
protected $backpropagation = null;
+ /**
+ * @var int
+ */
+ private $inputLayerFeatures;
+
+ /**
+ * @var array
+ */
+ private $hiddenLayers = [];
+
+ /**
+ * @var float
+ */
+ private $learningRate;
+
/**
* @throws InvalidArgumentException
*/
@@ -78,18 +73,6 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
$this->initNetwork();
}
- private function initNetwork(): void
- {
- $this->addInputLayer($this->inputLayerFeatures);
- $this->addNeuronLayers($this->hiddenLayers, $this->activationFunction);
- $this->addNeuronLayers([count($this->classes)], $this->activationFunction);
-
- $this->addBiasNodes();
- $this->generateSynapses();
-
- $this->backpropagation = new Backpropagation($this->learningRate);
- }
-
public function train(array $samples, array $targets): void
{
$this->reset();
@@ -127,6 +110,18 @@ abstract class MultilayerPerceptron extends LayeredNetwork implements Estimator,
$this->removeLayers();
}
+ private function initNetwork(): void
+ {
+ $this->addInputLayer($this->inputLayerFeatures);
+ $this->addNeuronLayers($this->hiddenLayers, $this->activationFunction);
+ $this->addNeuronLayers([count($this->classes)], $this->activationFunction);
+
+ $this->addBiasNodes();
+ $this->generateSynapses();
+
+ $this->backpropagation = new Backpropagation($this->learningRate);
+ }
+
private function addInputLayer(int $nodes): void
{
$this->addLayer(new Layer($nodes, Input::class));
diff --git a/src/Phpml/NeuralNetwork/Node.php b/src/Phpml/NeuralNetwork/Node.php
index 6627c02..0b7726f 100644
--- a/src/Phpml/NeuralNetwork/Node.php
+++ b/src/Phpml/NeuralNetwork/Node.php
@@ -6,5 +6,5 @@ namespace Phpml\NeuralNetwork;
interface Node
{
- public function getOutput() : float;
+ public function getOutput(): float;
}
diff --git a/src/Phpml/NeuralNetwork/Node/Bias.php b/src/Phpml/NeuralNetwork/Node/Bias.php
index 4f32884..ac3fb8b 100644
--- a/src/Phpml/NeuralNetwork/Node/Bias.php
+++ b/src/Phpml/NeuralNetwork/Node/Bias.php
@@ -8,7 +8,7 @@ use Phpml\NeuralNetwork\Node;
class Bias implements Node
{
- public function getOutput() : float
+ public function getOutput(): float
{
return 1.0;
}
diff --git a/src/Phpml/NeuralNetwork/Node/Input.php b/src/Phpml/NeuralNetwork/Node/Input.php
index 8ff78ea..ce33439 100644
--- a/src/Phpml/NeuralNetwork/Node/Input.php
+++ b/src/Phpml/NeuralNetwork/Node/Input.php
@@ -18,7 +18,7 @@ class Input implements Node
$this->input = $input;
}
- public function getOutput() : float
+ public function getOutput(): float
{
return $this->input;
}
diff --git a/src/Phpml/NeuralNetwork/Node/Neuron.php b/src/Phpml/NeuralNetwork/Node/Neuron.php
index 096d54f..a6c10e6 100644
--- a/src/Phpml/NeuralNetwork/Node/Neuron.php
+++ b/src/Phpml/NeuralNetwork/Node/Neuron.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Phpml\NeuralNetwork\Node;
use Phpml\NeuralNetwork\ActivationFunction;
+use Phpml\NeuralNetwork\ActivationFunction\Sigmoid;
use Phpml\NeuralNetwork\Node;
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
@@ -13,7 +14,7 @@ class Neuron implements Node
/**
* @var Synapse[]
*/
- protected $synapses;
+ protected $synapses = [];
/**
* @var ActivationFunction
@@ -27,7 +28,7 @@ class Neuron implements Node
public function __construct(?ActivationFunction $activationFunction = null)
{
- $this->activationFunction = $activationFunction ?: new ActivationFunction\Sigmoid();
+ $this->activationFunction = $activationFunction ?: new Sigmoid();
$this->synapses = [];
$this->output = 0;
}
@@ -45,9 +46,9 @@ class Neuron implements Node
return $this->synapses;
}
- public function getOutput() : float
+ public function getOutput(): float
{
- if (0 === $this->output) {
+ if ($this->output === 0) {
$sum = 0;
foreach ($this->synapses as $synapse) {
$sum += $synapse->getOutput();
diff --git a/src/Phpml/NeuralNetwork/Node/Neuron/Synapse.php b/src/Phpml/NeuralNetwork/Node/Neuron/Synapse.php
index 0883f4e..08899bf 100644
--- a/src/Phpml/NeuralNetwork/Node/Neuron/Synapse.php
+++ b/src/Phpml/NeuralNetwork/Node/Neuron/Synapse.php
@@ -27,12 +27,7 @@ class Synapse
$this->weight = $weight ?: $this->generateRandomWeight();
}
- protected function generateRandomWeight() : float
- {
- return 1 / random_int(5, 25) * (random_int(0, 1) ? -1 : 1);
- }
-
- public function getOutput() : float
+ public function getOutput(): float
{
return $this->weight * $this->node->getOutput();
}
@@ -42,7 +37,7 @@ class Synapse
$this->weight += $delta;
}
- public function getWeight() : float
+ public function getWeight(): float
{
return $this->weight;
}
@@ -51,4 +46,9 @@ class Synapse
{
return $this->node;
}
+
+ protected function generateRandomWeight(): float
+ {
+ return 1 / random_int(5, 25) * (random_int(0, 1) ? -1 : 1);
+ }
}
diff --git a/src/Phpml/NeuralNetwork/Training/Backpropagation.php b/src/Phpml/NeuralNetwork/Training/Backpropagation.php
index 6722bd1..8382a8e 100644
--- a/src/Phpml/NeuralNetwork/Training/Backpropagation.php
+++ b/src/Phpml/NeuralNetwork/Training/Backpropagation.php
@@ -47,6 +47,7 @@ class Backpropagation
}
}
}
+
$this->prevSigmas = $this->sigmas;
}
@@ -55,7 +56,7 @@ class Backpropagation
$this->prevSigmas = null;
}
- private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer) : float
+ private function getSigma(Neuron $neuron, int $targetClass, int $key, bool $lastLayer): float
{
$neuronOutput = $neuron->getOutput();
$sigma = $neuronOutput * (1 - $neuronOutput);
@@ -65,6 +66,7 @@ class Backpropagation
if ($targetClass === $key) {
$value = 1;
}
+
$sigma *= ($value - $neuronOutput);
} else {
$sigma *= $this->getPrevSigma($neuron);
@@ -75,7 +77,7 @@ class Backpropagation
return $sigma;
}
- private function getPrevSigma(Neuron $neuron) : float
+ private function getPrevSigma(Neuron $neuron): float
{
$sigma = 0.0;
diff --git a/src/Phpml/NeuralNetwork/Training/Backpropagation/Sigma.php b/src/Phpml/NeuralNetwork/Training/Backpropagation/Sigma.php
index 23560fe..f21c7b1 100644
--- a/src/Phpml/NeuralNetwork/Training/Backpropagation/Sigma.php
+++ b/src/Phpml/NeuralNetwork/Training/Backpropagation/Sigma.php
@@ -29,12 +29,12 @@ class Sigma
return $this->neuron;
}
- public function getSigma() : float
+ public function getSigma(): float
{
return $this->sigma;
}
- public function getSigmaForNeuron(Neuron $neuron) : float
+ public function getSigmaForNeuron(Neuron $neuron): float
{
$sigma = 0.0;
diff --git a/src/Phpml/Pipeline.php b/src/Phpml/Pipeline.php
index a72e634..480a980 100644
--- a/src/Phpml/Pipeline.php
+++ b/src/Phpml/Pipeline.php
@@ -9,7 +9,7 @@ class Pipeline implements Estimator
/**
* @var array|Transformer[]
*/
- private $transformers;
+ private $transformers = [];
/**
* @var Estimator
@@ -41,7 +41,7 @@ class Pipeline implements Estimator
/**
* @return array|Transformer[]
*/
- public function getTransformers() : array
+ public function getTransformers(): array
{
return $this->transformers;
}
diff --git a/src/Phpml/Preprocessing/Imputer.php b/src/Phpml/Preprocessing/Imputer.php
index d2dbfcd..bd40948 100644
--- a/src/Phpml/Preprocessing/Imputer.php
+++ b/src/Phpml/Preprocessing/Imputer.php
@@ -9,6 +9,7 @@ use Phpml\Preprocessing\Imputer\Strategy;
class Imputer implements Preprocessor
{
public const AXIS_COLUMN = 0;
+
public const AXIS_ROW = 1;
/**
@@ -64,9 +65,9 @@ class Imputer implements Preprocessor
}
}
- private function getAxis(int $column, array $currentSample) : array
+ private function getAxis(int $column, array $currentSample): array
{
- if (self::AXIS_ROW === $this->axis) {
+ if ($this->axis === self::AXIS_ROW) {
return array_diff($currentSample, [$this->missingValue]);
}
diff --git a/src/Phpml/Preprocessing/Imputer/Strategy/MeanStrategy.php b/src/Phpml/Preprocessing/Imputer/Strategy/MeanStrategy.php
index 91badfb..3ad0321 100644
--- a/src/Phpml/Preprocessing/Imputer/Strategy/MeanStrategy.php
+++ b/src/Phpml/Preprocessing/Imputer/Strategy/MeanStrategy.php
@@ -9,7 +9,7 @@ use Phpml\Preprocessing\Imputer\Strategy;
class MeanStrategy implements Strategy
{
- public function replaceValue(array $currentAxis) : float
+ public function replaceValue(array $currentAxis): float
{
return Mean::arithmetic($currentAxis);
}
diff --git a/src/Phpml/Preprocessing/Imputer/Strategy/MedianStrategy.php b/src/Phpml/Preprocessing/Imputer/Strategy/MedianStrategy.php
index f010bea..ffd9983 100644
--- a/src/Phpml/Preprocessing/Imputer/Strategy/MedianStrategy.php
+++ b/src/Phpml/Preprocessing/Imputer/Strategy/MedianStrategy.php
@@ -9,7 +9,7 @@ use Phpml\Preprocessing\Imputer\Strategy;
class MedianStrategy implements Strategy
{
- public function replaceValue(array $currentAxis) : float
+ public function replaceValue(array $currentAxis): float
{
return Mean::median($currentAxis);
}
diff --git a/src/Phpml/Preprocessing/Normalizer.php b/src/Phpml/Preprocessing/Normalizer.php
index f038345..b2721de 100644
--- a/src/Phpml/Preprocessing/Normalizer.php
+++ b/src/Phpml/Preprocessing/Normalizer.php
@@ -11,7 +11,9 @@ use Phpml\Math\Statistic\StandardDeviation;
class Normalizer implements Preprocessor
{
public const NORM_L1 = 1;
+
public const NORM_L2 = 2;
+
public const NORM_STD = 3;
/**
@@ -27,12 +29,12 @@ class Normalizer implements Preprocessor
/**
* @var array
*/
- private $std;
+ private $std = [];
/**
* @var array
*/
- private $mean;
+ private $mean = [];
/**
* @throws NormalizerException
@@ -69,7 +71,7 @@ class Normalizer implements Preprocessor
$methods = [
self::NORM_L1 => 'normalizeL1',
self::NORM_L2 => 'normalizeL2',
- self::NORM_STD => 'normalizeSTD'
+ self::NORM_STD => 'normalizeSTD',
];
$method = $methods[$this->norm];
@@ -87,7 +89,7 @@ class Normalizer implements Preprocessor
$norm1 += abs($feature);
}
- if (0 == $norm1) {
+ if ($norm1 == 0) {
$count = count($sample);
$sample = array_fill(0, $count, 1.0 / $count);
} else {
@@ -103,9 +105,10 @@ class Normalizer implements Preprocessor
foreach ($sample as $feature) {
$norm2 += $feature * $feature;
}
+
$norm2 = sqrt((float) $norm2);
- if (0 == $norm2) {
+ if ($norm2 == 0) {
$sample = array_fill(0, count($sample), 1);
} else {
foreach ($sample as &$feature) {
diff --git a/src/Phpml/Regression/LeastSquares.php b/src/Phpml/Regression/LeastSquares.php
index f8adcb2..6ecfafc 100644
--- a/src/Phpml/Regression/LeastSquares.php
+++ b/src/Phpml/Regression/LeastSquares.php
@@ -28,7 +28,7 @@ class LeastSquares implements Regression
/**
* @var array
*/
- private $coefficients;
+ private $coefficients = [];
public function train(array $samples, array $targets): void
{
@@ -51,12 +51,12 @@ class LeastSquares implements Regression
return $result;
}
- public function getCoefficients() : array
+ public function getCoefficients(): array
{
return $this->coefficients;
}
- public function getIntercept() : float
+ public function getIntercept(): float
{
return $this->intercept;
}
@@ -79,7 +79,7 @@ class LeastSquares implements Regression
/**
* Add one dimension for intercept calculation.
*/
- private function getSamplesMatrix() : Matrix
+ private function getSamplesMatrix(): Matrix
{
$samples = [];
foreach ($this->samples as $sample) {
@@ -90,7 +90,7 @@ class LeastSquares implements Regression
return new Matrix($samples);
}
- private function getTargetsMatrix() : Matrix
+ private function getTargetsMatrix(): Matrix
{
if (is_array($this->targets[0])) {
return new Matrix($this->targets);
diff --git a/src/Phpml/SupportVectorMachine/DataTransformer.php b/src/Phpml/SupportVectorMachine/DataTransformer.php
index b057d01..2ce938e 100644
--- a/src/Phpml/SupportVectorMachine/DataTransformer.php
+++ b/src/Phpml/SupportVectorMachine/DataTransformer.php
@@ -34,7 +34,7 @@ class DataTransformer
return $set;
}
- public static function predictions(string $rawPredictions, array $labels) : array
+ public static function predictions(string $rawPredictions, array $labels): array
{
$numericLabels = self::numericLabels($labels);
$results = [];
@@ -47,7 +47,7 @@ class DataTransformer
return $results;
}
- public static function numericLabels(array $labels) : array
+ public static function numericLabels(array $labels): array
{
$numericLabels = [];
foreach ($labels as $label) {
diff --git a/src/Phpml/SupportVectorMachine/SupportVectorMachine.php b/src/Phpml/SupportVectorMachine/SupportVectorMachine.php
index cbee23d..2415eda 100644
--- a/src/Phpml/SupportVectorMachine/SupportVectorMachine.php
+++ b/src/Phpml/SupportVectorMachine/SupportVectorMachine.php
@@ -167,7 +167,7 @@ class SupportVectorMachine
}
/**
- * @return array
+ * @return array|string
*/
public function predict(array $samples)
{
diff --git a/src/Phpml/Tokenization/Tokenizer.php b/src/Phpml/Tokenization/Tokenizer.php
index e1f0f35..f2dffd9 100644
--- a/src/Phpml/Tokenization/Tokenizer.php
+++ b/src/Phpml/Tokenization/Tokenizer.php
@@ -6,5 +6,5 @@ namespace Phpml\Tokenization;
interface Tokenizer
{
- public function tokenize(string $text) : array;
+ public function tokenize(string $text): array;
}
diff --git a/src/Phpml/Tokenization/WhitespaceTokenizer.php b/src/Phpml/Tokenization/WhitespaceTokenizer.php
index 14e7d0a..5b071b8 100644
--- a/src/Phpml/Tokenization/WhitespaceTokenizer.php
+++ b/src/Phpml/Tokenization/WhitespaceTokenizer.php
@@ -6,7 +6,7 @@ namespace Phpml\Tokenization;
class WhitespaceTokenizer implements Tokenizer
{
- public function tokenize(string $text) : array
+ public function tokenize(string $text): array
{
return preg_split('/[\pZ\pC]+/u', $text, -1, PREG_SPLIT_NO_EMPTY);
}
diff --git a/src/Phpml/Tokenization/WordTokenizer.php b/src/Phpml/Tokenization/WordTokenizer.php
index 03d134b..68a75ea 100644
--- a/src/Phpml/Tokenization/WordTokenizer.php
+++ b/src/Phpml/Tokenization/WordTokenizer.php
@@ -6,7 +6,7 @@ namespace Phpml\Tokenization;
class WordTokenizer implements Tokenizer
{
- public function tokenize(string $text) : array
+ public function tokenize(string $text): array
{
$tokens = [];
preg_match_all('/\w\w+/u', $text, $tokens);
diff --git a/tests/Phpml/Association/AprioriTest.php b/tests/Phpml/Association/AprioriTest.php
index 3b47483..7b637c9 100644
--- a/tests/Phpml/Association/AprioriTest.php
+++ b/tests/Phpml/Association/AprioriTest.php
@@ -7,6 +7,7 @@ namespace tests\Phpml\Classification;
use Phpml\Association\Apriori;
use Phpml\ModelManager;
use PHPUnit\Framework\TestCase;
+use ReflectionClass;
class AprioriTest extends TestCase
{
@@ -172,7 +173,6 @@ class AprioriTest extends TestCase
/**
* Invokes objects method. Private/protected will be set accessible.
*
- * @param object &$object Instantiated object to be called on
* @param string $method Method name to be called
* @param array $params Array of params to be passed
*
@@ -180,7 +180,7 @@ class AprioriTest extends TestCase
*/
public function invoke(&$object, $method, array $params = [])
{
- $reflection = new \ReflectionClass(get_class($object));
+ $reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($method);
$method->setAccessible(true);
@@ -195,7 +195,7 @@ class AprioriTest extends TestCase
$testSamples = [['alpha', 'epsilon'], ['beta', 'theta']];
$predicted = $classifier->predict($testSamples);
- $filename = 'apriori-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'apriori-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/DecisionTreeTest.php b/tests/Phpml/Classification/DecisionTreeTest.php
index c7d2d2a..8533500 100644
--- a/tests/Phpml/Classification/DecisionTreeTest.php
+++ b/tests/Phpml/Classification/DecisionTreeTest.php
@@ -24,7 +24,7 @@ class DecisionTreeTest extends TestCase
['sunny', 75, 70, 'true', 'Play'],
['overcast', 72, 90, 'true', 'Play'],
['overcast', 81, 75, 'false', 'Play'],
- ['rain', 71, 80, 'true', 'Dont_play']
+ ['rain', 71, 80, 'true', 'Dont_play'],
];
private $extraData = [
@@ -32,16 +32,6 @@ class DecisionTreeTest extends TestCase
['scorching', 100, 93, 'true', 'Dont_play'],
];
- private function getData($input)
- {
- $targets = array_column($input, 4);
- array_walk($input, function (&$v): void {
- array_splice($v, 4, 1);
- });
-
- return [$input, $targets];
- }
-
public function testPredictSingleSample()
{
[$data, $targets] = $this->getData($this->data);
@@ -68,7 +58,7 @@ class DecisionTreeTest extends TestCase
$testSamples = [['sunny', 78, 72, 'false'], ['overcast', 60, 60, 'false']];
$predicted = $classifier->predict($testSamples);
- $filename = 'decision-tree-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'decision-tree-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
@@ -83,6 +73,16 @@ class DecisionTreeTest extends TestCase
[$data, $targets] = $this->getData($this->data);
$classifier = new DecisionTree(5);
$classifier->train($data, $targets);
- $this->assertTrue(5 >= $classifier->actualDepth);
+ $this->assertTrue($classifier->actualDepth <= 5);
+ }
+
+ private function getData($input)
+ {
+ $targets = array_column($input, 4);
+ array_walk($input, function (&$v): void {
+ array_splice($v, 4, 1);
+ });
+
+ return [$input, $targets];
}
}
diff --git a/tests/Phpml/Classification/Ensemble/AdaBoostTest.php b/tests/Phpml/Classification/Ensemble/AdaBoostTest.php
index 2cc8090..e01066c 100644
--- a/tests/Phpml/Classification/Ensemble/AdaBoostTest.php
+++ b/tests/Phpml/Classification/Ensemble/AdaBoostTest.php
@@ -52,7 +52,7 @@ class AdaBoostTest extends TestCase
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
$predicted = $classifier->predict($testSamples);
- $filename = 'adaboost-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'adaboost-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/Ensemble/BaggingTest.php b/tests/Phpml/Classification/Ensemble/BaggingTest.php
index 5bca8de..175b79a 100644
--- a/tests/Phpml/Classification/Ensemble/BaggingTest.php
+++ b/tests/Phpml/Classification/Ensemble/BaggingTest.php
@@ -26,7 +26,7 @@ class BaggingTest extends TestCase
['sunny', 75, 70, 'true', 'Play'],
['overcast', 72, 90, 'true', 'Play'],
['overcast', 81, 75, 'false', 'Play'],
- ['rain', 71, 80, 'true', 'Dont_play']
+ ['rain', 71, 80, 'true', 'Dont_play'],
];
private $extraData = [
@@ -61,7 +61,7 @@ class BaggingTest extends TestCase
$testSamples = [['sunny', 78, 72, 'false'], ['overcast', 60, 60, 'false']];
$predicted = $classifier->predict($testSamples);
- $filename = 'bagging-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'bagging-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
@@ -105,7 +105,7 @@ class BaggingTest extends TestCase
{
return [
DecisionTree::class => ['depth' => 5],
- NaiveBayes::class => []
+ NaiveBayes::class => [],
];
}
@@ -117,6 +117,7 @@ class BaggingTest extends TestCase
for ($i = 0; $i < 20; ++$i) {
$populated = array_merge($populated, $input);
}
+
shuffle($populated);
$targets = array_column($populated, 4);
array_walk($populated, function (&$v): void {
diff --git a/tests/Phpml/Classification/Ensemble/RandomForestTest.php b/tests/Phpml/Classification/Ensemble/RandomForestTest.php
index e4ca9e5..f2871e3 100644
--- a/tests/Phpml/Classification/Ensemble/RandomForestTest.php
+++ b/tests/Phpml/Classification/Ensemble/RandomForestTest.php
@@ -7,9 +7,20 @@ namespace tests\Phpml\Classification\Ensemble;
use Phpml\Classification\DecisionTree;
use Phpml\Classification\Ensemble\RandomForest;
use Phpml\Classification\NaiveBayes;
+use Throwable;
class RandomForestTest extends BaggingTest
{
+ public function testOtherBaseClassifier(): void
+ {
+ try {
+ $classifier = new RandomForest();
+ $classifier->setClassifer(NaiveBayes::class);
+ $this->assertEquals(0, 1);
+ } catch (Throwable $ex) {
+ $this->assertEquals(1, 1);
+ }
+ }
protected function getClassifier($numBaseClassifiers = 50)
{
$classifier = new RandomForest($numBaseClassifiers);
@@ -22,15 +33,4 @@ class RandomForestTest extends BaggingTest
{
return [DecisionTree::class => ['depth' => 5]];
}
-
- public function testOtherBaseClassifier(): void
- {
- try {
- $classifier = new RandomForest();
- $classifier->setClassifer(NaiveBayes::class);
- $this->assertEquals(0, 1);
- } catch (\Exception $ex) {
- $this->assertEquals(1, 1);
- }
- }
}
diff --git a/tests/Phpml/Classification/KNearestNeighborsTest.php b/tests/Phpml/Classification/KNearestNeighborsTest.php
index 7ef6182..d9114b5 100644
--- a/tests/Phpml/Classification/KNearestNeighborsTest.php
+++ b/tests/Phpml/Classification/KNearestNeighborsTest.php
@@ -73,7 +73,7 @@ class KNearestNeighborsTest extends TestCase
$classifier->train($trainSamples, $trainLabels);
$predicted = $classifier->predict($testSamples);
- $filename = 'knearest-neighbors-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'knearest-neighbors-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/Linear/AdalineTest.php b/tests/Phpml/Classification/Linear/AdalineTest.php
index 46f1a34..0a90a18 100644
--- a/tests/Phpml/Classification/Linear/AdalineTest.php
+++ b/tests/Phpml/Classification/Linear/AdalineTest.php
@@ -35,7 +35,7 @@ class AdalineTest extends TestCase
$samples = [
[0, 0], [0, 1], [1, 0], [1, 1], // First group : a cluster at bottom-left corner in 2D
[5, 5], [6, 5], [5, 6], [7, 5], // Second group: another cluster at the middle-right
- [3, 10],[3, 10],[3, 8], [3, 9] // Third group : cluster at the top-middle
+ [3, 10], [3, 10], [3, 8], [3, 9], // Third group : cluster at the top-middle
];
$targets = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2];
@@ -55,7 +55,7 @@ class AdalineTest extends TestCase
$samples = [
[0, 0], [0, 1], [1, 0], [1, 1], // First group : a cluster at bottom-left corner in 2D
[5, 5], [6, 5], [5, 6], [7, 5], // Second group: another cluster at the middle-right
- [3, 10],[3, 10],[3, 8], [3, 9] // Third group : cluster at the top-middle
+ [3, 10], [3, 10], [3, 8], [3, 9], // Third group : cluster at the top-middle
];
$targets = [2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1];
$classifier->train($samples, $targets);
@@ -74,7 +74,7 @@ class AdalineTest extends TestCase
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
$predicted = $classifier->predict($testSamples);
- $filename = 'adaline-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'adaline-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/Linear/DecisionStumpTest.php b/tests/Phpml/Classification/Linear/DecisionStumpTest.php
index fa522ad..7fbabec 100644
--- a/tests/Phpml/Classification/Linear/DecisionStumpTest.php
+++ b/tests/Phpml/Classification/Linear/DecisionStumpTest.php
@@ -40,7 +40,7 @@ class DecisionStumpTest extends TestCase
$samples = [
[0, 0], [0, 1], [1, 0], [1, 1], // First group : a cluster at bottom-left corner in 2D
[5, 5], [6, 5], [5, 6], [7, 5], // Second group: another cluster at the middle-right
- [3, 10],[3, 10],[3, 8], [3, 9] // Third group : cluster at the top-middle
+ [3, 10], [3, 10], [3, 8], [3, 9], // Third group : cluster at the top-middle
];
$targets = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2];
@@ -63,7 +63,7 @@ class DecisionStumpTest extends TestCase
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
$predicted = $classifier->predict($testSamples);
- $filename = 'dstump-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'dstump-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/Linear/PerceptronTest.php b/tests/Phpml/Classification/Linear/PerceptronTest.php
index 2721067..17b1db8 100644
--- a/tests/Phpml/Classification/Linear/PerceptronTest.php
+++ b/tests/Phpml/Classification/Linear/PerceptronTest.php
@@ -37,7 +37,7 @@ class PerceptronTest extends TestCase
$samples = [
[0, 0], [0, 1], [1, 0], [1, 1], // First group : a cluster at bottom-left corner in 2D
[5, 5], [6, 5], [5, 6], [7, 5], // Second group: another cluster at the middle-right
- [3, 10],[3, 10],[3, 8], [3, 9] // Third group : cluster at the top-middle
+ [3, 10], [3, 10], [3, 8], [3, 9], // Third group : cluster at the top-middle
];
$targets = [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2];
@@ -58,7 +58,7 @@ class PerceptronTest extends TestCase
$samples = [
[0, 0], [0, 1], [1, 0], [1, 1], // First group : a cluster at bottom-left corner in 2D
[5, 5], [6, 5], [5, 6], [7, 5], // Second group: another cluster at the middle-right
- [3, 10],[3, 10],[3, 8], [3, 9] // Third group : cluster at the top-middle
+ [3, 10], [3, 10], [3, 8], [3, 9], // Third group : cluster at the top-middle
];
$targets = [2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1];
$classifier->train($samples, $targets);
@@ -77,7 +77,7 @@ class PerceptronTest extends TestCase
$testSamples = [[0, 1], [1, 1], [0.2, 0.1]];
$predicted = $classifier->predict($testSamples);
- $filename = 'perceptron-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'perceptron-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/MLPClassifierTest.php b/tests/Phpml/Classification/MLPClassifierTest.php
index 519dc90..20bc5e1 100644
--- a/tests/Phpml/Classification/MLPClassifierTest.php
+++ b/tests/Phpml/Classification/MLPClassifierTest.php
@@ -150,7 +150,7 @@ class MLPClassifierTest extends TestCase
$testSamples = [[0, 0], [1, 0], [0, 1], [1, 1]];
$predicted = $classifier->predict($testSamples);
- $filename = 'perceptron-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'perceptron-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
@@ -189,7 +189,7 @@ class MLPClassifierTest extends TestCase
new MLPClassifier(2, [2], [0]);
}
- private function getSynapsesNodes(array $synapses) : array
+ private function getSynapsesNodes(array $synapses): array
{
$nodes = [];
foreach ($synapses as $synapse) {
diff --git a/tests/Phpml/Classification/NaiveBayesTest.php b/tests/Phpml/Classification/NaiveBayesTest.php
index 5b14f7e..c423c6d 100644
--- a/tests/Phpml/Classification/NaiveBayesTest.php
+++ b/tests/Phpml/Classification/NaiveBayesTest.php
@@ -59,7 +59,7 @@ class NaiveBayesTest extends TestCase
$classifier->train($trainSamples, $trainLabels);
$predicted = $classifier->predict($testSamples);
- $filename = 'naive-bayes-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'naive-bayes-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Classification/SVCTest.php b/tests/Phpml/Classification/SVCTest.php
index f734297..0941b34 100644
--- a/tests/Phpml/Classification/SVCTest.php
+++ b/tests/Phpml/Classification/SVCTest.php
@@ -57,7 +57,7 @@ class SVCTest extends TestCase
$classifier->train($trainSamples, $trainLabels);
$predicted = $classifier->predict($testSamples);
- $filename = 'svc-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'svc-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($classifier, $filepath);
diff --git a/tests/Phpml/Clustering/DBSCANTest.php b/tests/Phpml/Clustering/DBSCANTest.php
index d8fb0fe..f12fb03 100644
--- a/tests/Phpml/Clustering/DBSCANTest.php
+++ b/tests/Phpml/Clustering/DBSCANTest.php
@@ -34,10 +34,25 @@ class DBSCANTest extends TestCase
public function testDBSCANSamplesClusteringAssociative(): void
{
- $samples = ['a' => [1, 1], 'b' => [9, 9], 'c' => [1, 2], 'd' => [9, 8], 'e' => [7, 7], 'f' => [8, 7]];
+ $samples = [
+ 'a' => [1, 1],
+ 'b' => [9, 9],
+ 'c' => [1, 2],
+ 'd' => [9, 8],
+ 'e' => [7, 7],
+ 'f' => [8, 7],
+ ];
$clustered = [
- ['a' => [1, 1], 'c' => [1, 2]],
- ['b' => [9, 9], 'd' => [9, 8], 'e' => [7, 7], 'f' => [8, 7]],
+ [
+ 'a' => [1, 1],
+ 'c' => [1, 2],
+ ],
+ [
+ 'b' => [9, 9],
+ 'd' => [9, 8],
+ 'e' => [7, 7],
+ 'f' => [8, 7],
+ ],
];
$dbscan = new DBSCAN($epsilon = 3, $minSamples = 2);
diff --git a/tests/Phpml/Clustering/FuzzyCMeansTest.php b/tests/Phpml/Clustering/FuzzyCMeansTest.php
index 5aed678..7b19422 100644
--- a/tests/Phpml/Clustering/FuzzyCMeansTest.php
+++ b/tests/Phpml/Clustering/FuzzyCMeansTest.php
@@ -20,6 +20,7 @@ class FuzzyCMeansTest extends TestCase
unset($samples[$index]);
}
}
+
$this->assertCount(0, $samples);
return $fcm;
@@ -35,6 +36,7 @@ class FuzzyCMeansTest extends TestCase
foreach ($matrix as $row) {
$this->assertCount($sampleCount, $row);
}
+
// Transpose of the matrix
array_unshift($matrix, null);
$matrix = call_user_func_array('array_map', $matrix);
diff --git a/tests/Phpml/Clustering/KMeansTest.php b/tests/Phpml/Clustering/KMeansTest.php
index e665c9f..f453340 100644
--- a/tests/Phpml/Clustering/KMeansTest.php
+++ b/tests/Phpml/Clustering/KMeansTest.php
@@ -23,6 +23,7 @@ class KMeansTest extends TestCase
unset($samples[$index]);
}
}
+
$this->assertCount(0, $samples);
}
diff --git a/tests/Phpml/DimensionReduction/KernelPCATest.php b/tests/Phpml/DimensionReduction/KernelPCATest.php
index 66b4622..3f37e3c 100644
--- a/tests/Phpml/DimensionReduction/KernelPCATest.php
+++ b/tests/Phpml/DimensionReduction/KernelPCATest.php
@@ -16,12 +16,12 @@ class KernelPCATest extends TestCase
// A simple example whose result is known beforehand
$data = [
- [2,2], [1.5,1], [1.,1.5], [1.,1.],
- [2.,1.],[2,2.5], [2.,3.], [1.5,3],
- [1.,2.5], [1.,2.7], [1.,3.], [1,3],
- [1,2], [1.5,2], [1.5,2.2], [1.3,1.7],
- [1.7,1.3], [1.5,1.5], [1.5,1.6], [1.6,2],
- [1.7,2.1], [1.3,1.3], [1.3,2.2], [1.4,2.4]
+ [2, 2], [1.5, 1], [1., 1.5], [1., 1.],
+ [2., 1.], [2, 2.5], [2., 3.], [1.5, 3],
+ [1., 2.5], [1., 2.7], [1., 3.], [1, 3],
+ [1, 2], [1.5, 2], [1.5, 2.2], [1.3, 1.7],
+ [1.7, 1.3], [1.5, 1.5], [1.5, 1.6], [1.6, 2],
+ [1.7, 2.1], [1.3, 1.3], [1.3, 2.2], [1.4, 2.4],
];
$transformed = [
[0.016485613899708], [-0.089805657741674], [-0.088695974245924], [-0.069761503810802],
@@ -29,7 +29,7 @@ class KernelPCATest extends TestCase
[-0.10098315410297], [-0.15617881000654], [-0.21266832077299], [-0.21266832077299],
[-0.039234518840831], [0.40858295942991], [0.40110375047242], [-0.10555116296691],
[-0.13128352866095], [-0.20865959471756], [-0.17531601535848], [0.4240660966961],
- [0.36351946685163], [-0.14334173054136], [0.22454914091011], [0.15035027480881]];
+ [0.36351946685163], [-0.14334173054136], [0.22454914091011], [0.15035027480881], ];
$kpca = new KernelPCA(KernelPCA::KERNEL_RBF, null, 1, 15);
$reducedData = $kpca->fit($data);
diff --git a/tests/Phpml/DimensionReduction/LDATest.php b/tests/Phpml/DimensionReduction/LDATest.php
index 19124a0..42a0283 100644
--- a/tests/Phpml/DimensionReduction/LDATest.php
+++ b/tests/Phpml/DimensionReduction/LDATest.php
@@ -28,7 +28,7 @@ class LDATest extends TestCase
[4.7, 3.2, 1.3, 0.2],
[6.5, 3.0, 5.2, 2.0],
[6.2, 3.4, 5.4, 2.3],
- [5.9, 3.0, 5.1, 1.8]
+ [5.9, 3.0, 5.1, 1.8],
];
$transformed2 = [
[-1.4922092756753, 1.9047102045574],
@@ -36,7 +36,7 @@ class LDATest extends TestCase
[-1.3487505965419, 1.749846351699],
[1.7759343101456, 2.0371552314006],
[2.0059819019159, 2.4493123003226],
- [1.701474913008, 1.9037880473772]
+ [1.701474913008, 1.9037880473772],
];
$control = [];
diff --git a/tests/Phpml/DimensionReduction/PCATest.php b/tests/Phpml/DimensionReduction/PCATest.php
index 0a60004..38b4744 100644
--- a/tests/Phpml/DimensionReduction/PCATest.php
+++ b/tests/Phpml/DimensionReduction/PCATest.php
@@ -26,12 +26,12 @@ class PCATest extends TestCase
[2.0, 1.6],
[1.0, 1.1],
[1.5, 1.6],
- [1.1, 0.9]
+ [1.1, 0.9],
];
$transformed = [
[-0.827970186], [1.77758033], [-0.992197494],
[-0.274210416], [-1.67580142], [-0.912949103], [0.0991094375],
- [1.14457216], [0.438046137], [1.22382056]];
+ [1.14457216], [0.438046137], [1.22382056], ];
$pca = new PCA(0.90);
$reducedData = $pca->fit($data);
diff --git a/tests/Phpml/FeatureExtraction/TfIdfTransformerTest.php b/tests/Phpml/FeatureExtraction/TfIdfTransformerTest.php
index 0e1adbc..a8faacb 100644
--- a/tests/Phpml/FeatureExtraction/TfIdfTransformerTest.php
+++ b/tests/Phpml/FeatureExtraction/TfIdfTransformerTest.php
@@ -14,13 +14,41 @@ class TfIdfTransformerTest extends TestCase
// https://en.wikipedia.org/wiki/Tf-idf
$samples = [
- [0 => 1, 1 => 1, 2 => 2, 3 => 1, 4 => 0, 5 => 0],
- [0 => 1, 1 => 1, 2 => 0, 3 => 0, 4 => 2, 5 => 3],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 2,
+ 3 => 1,
+ 4 => 0,
+ 5 => 0,
+ ],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 0,
+ 3 => 0,
+ 4 => 2,
+ 5 => 3,
+ ],
];
$tfIdfSamples = [
- [0 => 0, 1 => 0, 2 => 0.602, 3 => 0.301, 4 => 0, 5 => 0],
- [0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0.602, 5 => 0.903],
+ [
+ 0 => 0,
+ 1 => 0,
+ 2 => 0.602,
+ 3 => 0.301,
+ 4 => 0,
+ 5 => 0,
+ ],
+ [
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0.602,
+ 5 => 0.903,
+ ],
];
$transformer = new TfIdfTransformer($samples);
diff --git a/tests/Phpml/FeatureExtraction/TokenCountVectorizerTest.php b/tests/Phpml/FeatureExtraction/TokenCountVectorizerTest.php
index 3419a29..463570c 100644
--- a/tests/Phpml/FeatureExtraction/TokenCountVectorizerTest.php
+++ b/tests/Phpml/FeatureExtraction/TokenCountVectorizerTest.php
@@ -33,9 +33,42 @@ class TokenCountVectorizerTest extends TestCase
];
$tokensCounts = [
- [0 => 1, 1 => 1, 2 => 2, 3 => 1, 4 => 1, 5 => 0, 6 => 0, 7 => 0, 8 => 0, 9 => 0],
- [0 => 0, 1 => 1, 2 => 1, 3 => 0, 4 => 0, 5 => 1, 6 => 1, 7 => 0, 8 => 0, 9 => 0],
- [0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 1, 6 => 0, 7 => 2, 8 => 1, 9 => 1],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 2,
+ 3 => 1,
+ 4 => 1,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 0,
+ 9 => 0,
+ ],
+ [
+ 0 => 0,
+ 1 => 1,
+ 2 => 1,
+ 3 => 0,
+ 4 => 0,
+ 5 => 1,
+ 6 => 1,
+ 7 => 0,
+ 8 => 0,
+ 9 => 0,
+ ],
+ [
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 1,
+ 6 => 0,
+ 7 => 2,
+ 8 => 1,
+ 9 => 1,
+ ],
];
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer());
@@ -66,10 +99,34 @@ class TokenCountVectorizerTest extends TestCase
];
$tokensCounts = [
- [0 => 1, 1 => 1, 2 => 0, 3 => 1, 4 => 1],
- [0 => 1, 1 => 1, 2 => 0, 3 => 1, 4 => 1],
- [0 => 0, 1 => 1, 2 => 0, 3 => 1, 4 => 1],
- [0 => 0, 1 => 1, 2 => 0, 3 => 1, 4 => 1],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 0,
+ 3 => 1,
+ 4 => 1,
+ ],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 0,
+ 3 => 1,
+ 4 => 1,
+ ],
+ [
+ 0 => 0,
+ 1 => 1,
+ 2 => 0,
+ 3 => 1,
+ 4 => 1,
+ ],
+ [
+ 0 => 0,
+ 1 => 1,
+ 2 => 0,
+ 3 => 1,
+ 4 => 1,
+ ],
];
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer(), null, 0.5);
@@ -88,9 +145,39 @@ class TokenCountVectorizerTest extends TestCase
];
$tokensCounts = [
- [0 => 1, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0],
- [0 => 1, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0],
- [0 => 1, 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0, 7 => 0, 8 => 0],
+ [
+ 0 => 1,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 0,
+ ],
+ [
+ 0 => 1,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 0,
+ ],
+ [
+ 0 => 1,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 0,
+ ],
];
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer(), null, 1);
@@ -124,9 +211,36 @@ class TokenCountVectorizerTest extends TestCase
];
$tokensCounts = [
- [0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 0, 5 => 0, 6 => 0, 7 => 0],
- [0 => 0, 1 => 1, 2 => 0, 3 => 0, 4 => 1, 5 => 1, 6 => 0, 7 => 0],
- [0 => 0, 1 => 0, 2 => 0, 3 => 0, 4 => 1, 5 => 0, 6 => 1, 7 => 1],
+ [
+ 0 => 1,
+ 1 => 1,
+ 2 => 1,
+ 3 => 1,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ ],
+ [
+ 0 => 0,
+ 1 => 1,
+ 2 => 0,
+ 3 => 0,
+ 4 => 1,
+ 5 => 1,
+ 6 => 0,
+ 7 => 0,
+ ],
+ [
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 1,
+ 5 => 0,
+ 6 => 1,
+ 7 => 1,
+ ],
];
$vectorizer = new TokenCountVectorizer(new WhitespaceTokenizer(), $stopWords);
diff --git a/tests/Phpml/Math/ComparisonTest.php b/tests/Phpml/Math/ComparisonTest.php
index d31b1ae..2c72f5f 100644
--- a/tests/Phpml/Math/ComparisonTest.php
+++ b/tests/Phpml/Math/ComparisonTest.php
@@ -23,18 +23,15 @@ class ComparisonTest extends TestCase
}
/**
- * @expectedException \Phpml\Exception\InvalidArgumentException
- * @expectedExceptionMessage Invalid operator "~=" provided
- */
+ * @expectedException \Phpml\Exception\InvalidArgumentException
+ * @expectedExceptionMessage Invalid operator "~=" provided
+ */
public function testThrowExceptionWhenOperatorIsInvalid(): void
{
Comparison::compare(1, 1, '~=');
}
- /**
- * @return array
- */
- public function provideData()
+ public function provideData(): array
{
return [
// Greater
diff --git a/tests/Phpml/Math/LinearAlgebra/EigenDecompositionTest.php b/tests/Phpml/Math/LinearAlgebra/EigenDecompositionTest.php
index 688874c..3956830 100644
--- a/tests/Phpml/Math/LinearAlgebra/EigenDecompositionTest.php
+++ b/tests/Phpml/Math/LinearAlgebra/EigenDecompositionTest.php
@@ -19,7 +19,7 @@ class EigenDecompositionTest extends TestCase
// http://www.cs.otago.ac.nz/cosc453/student_tutorials/principal_components.pdf
$matrix = [
[0.616555556, 0.615444444],
- [0.614444444, 0.716555556]
+ [0.614444444, 0.716555556],
];
$knownEigvalues = [0.0490833989, 1.28402771];
$knownEigvectors = [[-0.735178656, 0.677873399], [-0.677873399, -0.735178656]];
@@ -43,7 +43,7 @@ class EigenDecompositionTest extends TestCase
if ($i > $k) {
$A[$i][$k] = $A[$k][$i];
} else {
- $A[$i][$k] = rand(0, 10);
+ $A[$i][$k] = random_int(0, 10);
}
}
}
diff --git a/tests/Phpml/Math/MatrixTest.php b/tests/Phpml/Math/MatrixTest.php
index cd9fff2..8d0e1be 100644
--- a/tests/Phpml/Math/MatrixTest.php
+++ b/tests/Phpml/Math/MatrixTest.php
@@ -239,12 +239,12 @@ class MatrixTest extends TestCase
{
$array = [
[1, 1, 1],
- [2, 2, 2]
+ [2, 2, 2],
];
$transposed = [
[1, 2],
[1, 2],
- [1, 2]
+ [1, 2],
];
$this->assertEquals($transposed, Matrix::transposeArray($array));
diff --git a/tests/Phpml/Math/ProductTest.php b/tests/Phpml/Math/ProductTest.php
index 9c3a4b4..bd55d11 100644
--- a/tests/Phpml/Math/ProductTest.php
+++ b/tests/Phpml/Math/ProductTest.php
@@ -6,6 +6,7 @@ namespace tests\Phpml\Math;
use Phpml\Math\Product;
use PHPUnit\Framework\TestCase;
+use stdClass;
class ProductTest extends TestCase
{
@@ -16,6 +17,6 @@ class ProductTest extends TestCase
$this->assertEquals(8, Product::scalar([2], [4]));
//test for non numeric values
- $this->assertEquals(0, Product::scalar(['', null, [], new \stdClass()], [null]));
+ $this->assertEquals(0, Product::scalar(['', null, [], new stdClass()], [null]));
}
}
diff --git a/tests/Phpml/Math/SetTest.php b/tests/Phpml/Math/SetTest.php
index a572a42..645e607 100644
--- a/tests/Phpml/Math/SetTest.php
+++ b/tests/Phpml/Math/SetTest.php
@@ -13,7 +13,7 @@ class SetTest extends TestCase
{
$union = Set::union(new Set([3, 1]), new Set([3, 2, 2]));
- $this->assertInstanceOf('\Phpml\Math\Set', $union);
+ $this->assertInstanceOf(Set::class, $union);
$this->assertEquals(new Set([1, 2, 3]), $union);
$this->assertEquals(3, $union->cardinality());
}
@@ -22,7 +22,7 @@ class SetTest extends TestCase
{
$intersection = Set::intersection(new Set(['C', 'A']), new Set(['B', 'C']));
- $this->assertInstanceOf('\Phpml\Math\Set', $intersection);
+ $this->assertInstanceOf(Set::class, $intersection);
$this->assertEquals(new Set(['C']), $intersection);
$this->assertEquals(1, $intersection->cardinality());
}
@@ -31,7 +31,7 @@ class SetTest extends TestCase
{
$difference = Set::difference(new Set(['C', 'A', 'B']), new Set(['A']));
- $this->assertInstanceOf('\Phpml\Math\Set', $difference);
+ $this->assertInstanceOf(Set::class, $difference);
$this->assertEquals(new Set(['B', 'C']), $difference);
$this->assertEquals(2, $difference->cardinality());
}
diff --git a/tests/Phpml/Math/Statistic/CovarianceTest.php b/tests/Phpml/Math/Statistic/CovarianceTest.php
index 3a8c9d3..97ec194 100644
--- a/tests/Phpml/Math/Statistic/CovarianceTest.php
+++ b/tests/Phpml/Math/Statistic/CovarianceTest.php
@@ -31,7 +31,7 @@ class CovarianceTest extends TestCase
];
$knownCovariance = [
[0.616555556, 0.615444444],
- [0.615444444, 0.716555556]];
+ [0.615444444, 0.716555556], ];
$x = array_column($matrix, 0);
$y = array_column($matrix, 1);
diff --git a/tests/Phpml/Metric/ClassificationReportTest.php b/tests/Phpml/Metric/ClassificationReportTest.php
index b7ff02d..fb3471a 100644
--- a/tests/Phpml/Metric/ClassificationReportTest.php
+++ b/tests/Phpml/Metric/ClassificationReportTest.php
@@ -16,11 +16,31 @@ class ClassificationReportTest extends TestCase
$report = new ClassificationReport($labels, $predicted);
- $precision = ['cat' => 0.5, 'ant' => 0.0, 'bird' => 1.0];
- $recall = ['cat' => 1.0, 'ant' => 0.0, 'bird' => 0.67];
- $f1score = ['cat' => 0.67, 'ant' => 0.0, 'bird' => 0.80];
- $support = ['cat' => 1, 'ant' => 1, 'bird' => 3];
- $average = ['precision' => 0.75, 'recall' => 0.83, 'f1score' => 0.73];
+ $precision = [
+ 'cat' => 0.5,
+ 'ant' => 0.0,
+ 'bird' => 1.0,
+ ];
+ $recall = [
+ 'cat' => 1.0,
+ 'ant' => 0.0,
+ 'bird' => 0.67,
+ ];
+ $f1score = [
+ 'cat' => 0.67,
+ 'ant' => 0.0,
+ 'bird' => 0.80,
+ ];
+ $support = [
+ 'cat' => 1,
+ 'ant' => 1,
+ 'bird' => 3,
+ ];
+ $average = [
+ 'precision' => 0.75,
+ 'recall' => 0.83,
+ 'f1score' => 0.73,
+ ];
$this->assertEquals($precision, $report->getPrecision(), '', 0.01);
$this->assertEquals($recall, $report->getRecall(), '', 0.01);
@@ -36,11 +56,31 @@ class ClassificationReportTest extends TestCase
$report = new ClassificationReport($labels, $predicted);
- $precision = [0 => 0.5, 1 => 0.0, 2 => 1.0];
- $recall = [0 => 1.0, 1 => 0.0, 2 => 0.67];
- $f1score = [0 => 0.67, 1 => 0.0, 2 => 0.80];
- $support = [0 => 1, 1 => 1, 2 => 3];
- $average = ['precision' => 0.75, 'recall' => 0.83, 'f1score' => 0.73];
+ $precision = [
+ 0 => 0.5,
+ 1 => 0.0,
+ 2 => 1.0,
+ ];
+ $recall = [
+ 0 => 1.0,
+ 1 => 0.0,
+ 2 => 0.67,
+ ];
+ $f1score = [
+ 0 => 0.67,
+ 1 => 0.0,
+ 2 => 0.80,
+ ];
+ $support = [
+ 0 => 1,
+ 1 => 1,
+ 2 => 3,
+ ];
+ $average = [
+ 'precision' => 0.75,
+ 'recall' => 0.83,
+ 'f1score' => 0.73,
+ ];
$this->assertEquals($precision, $report->getPrecision(), '', 0.01);
$this->assertEquals($recall, $report->getRecall(), '', 0.01);
@@ -56,7 +96,10 @@ class ClassificationReportTest extends TestCase
$report = new ClassificationReport($labels, $predicted);
- $this->assertEquals([1 => 0.0, 2 => 0.5], $report->getPrecision(), '', 0.01);
+ $this->assertEquals([
+ 1 => 0.0,
+ 2 => 0.5,
+ ], $report->getPrecision(), '', 0.01);
}
public function testPreventDivideByZeroWhenTruePositiveAndFalseNegativeSumEqualsZero(): void
@@ -66,7 +109,11 @@ class ClassificationReportTest extends TestCase
$report = new ClassificationReport($labels, $predicted);
- $this->assertEquals([1 => 0.0, 2 => 1, 3 => 0], $report->getPrecision(), '', 0.01);
+ $this->assertEquals([
+ 1 => 0.0,
+ 2 => 1,
+ 3 => 0,
+ ], $report->getPrecision(), '', 0.01);
}
public function testPreventDividedByZeroWhenPredictedLabelsAllNotMatch(): void
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/BinaryStepTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/BinaryStepTest.php
index 95e95cb..91fc1c7 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/BinaryStepTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/BinaryStepTest.php
@@ -19,10 +19,7 @@ class BinaryStepTest extends TestCase
$this->assertEquals($expected, $binaryStep->compute($value));
}
- /**
- * @return array
- */
- public function binaryStepProvider()
+ public function binaryStepProvider(): array
{
return [
[1, 1],
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/GaussianTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/GaussianTest.php
index f7af7c0..58b4b87 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/GaussianTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/GaussianTest.php
@@ -19,10 +19,7 @@ class GaussianTest extends TestCase
$this->assertEquals($expected, $gaussian->compute($value), '', 0.001);
}
- /**
- * @return array
- */
- public function gaussianProvider()
+ public function gaussianProvider(): array
{
return [
[0.367, 1],
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/HyperboliTangentTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/HyperboliTangentTest.php
index 95f437f..00348d9 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/HyperboliTangentTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/HyperboliTangentTest.php
@@ -19,10 +19,7 @@ class HyperboliTangentTest extends TestCase
$this->assertEquals($expected, $tanh->compute($value), '', 0.001);
}
- /**
- * @return array
- */
- public function tanhProvider()
+ public function tanhProvider(): array
{
return [
[1.0, 0.761, 1],
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/PReLUTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/PReLUTest.php
index 873520e..7e8e718 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/PReLUTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/PReLUTest.php
@@ -19,10 +19,7 @@ class PReLUTest extends TestCase
$this->assertEquals($expected, $prelu->compute($value), '', 0.001);
}
- /**
- * @return array
- */
- public function preluProvider()
+ public function preluProvider(): array
{
return [
[0.01, 0.367, 0.367],
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/SigmoidTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/SigmoidTest.php
index 096a376..d5a0ea3 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/SigmoidTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/SigmoidTest.php
@@ -19,10 +19,7 @@ class SigmoidTest extends TestCase
$this->assertEquals($expected, $sigmoid->compute($value), '', 0.001);
}
- /**
- * @return array
- */
- public function sigmoidProvider()
+ public function sigmoidProvider(): array
{
return [
[1.0, 1, 7.25],
diff --git a/tests/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLUTest.php b/tests/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLUTest.php
index 1800d7b..19a0312 100644
--- a/tests/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLUTest.php
+++ b/tests/Phpml/NeuralNetwork/ActivationFunction/ThresholdedReLUTest.php
@@ -19,16 +19,13 @@ class ThresholdedReLUTest extends TestCase
$this->assertEquals($expected, $thresholdedReLU->compute($value));
}
- /**
- * @return array
- */
- public function thresholdProvider()
+ public function thresholdProvider(): array
{
return [
[1.0, 0, 1.0],
[0.5, 3.75, 3.75],
[0.0, 0.5, 0.5],
- [0.9, 0, 0.1]
+ [0.9, 0, 0.1],
];
}
}
diff --git a/tests/Phpml/NeuralNetwork/LayerTest.php b/tests/Phpml/NeuralNetwork/LayerTest.php
index 284b1eb..72d8758 100644
--- a/tests/Phpml/NeuralNetwork/LayerTest.php
+++ b/tests/Phpml/NeuralNetwork/LayerTest.php
@@ -8,6 +8,7 @@ use Phpml\NeuralNetwork\Layer;
use Phpml\NeuralNetwork\Node\Bias;
use Phpml\NeuralNetwork\Node\Neuron;
use PHPUnit\Framework\TestCase;
+use stdClass;
class LayerTest extends TestCase
{
@@ -43,7 +44,7 @@ class LayerTest extends TestCase
*/
public function testThrowExceptionOnInvalidNodeClass(): void
{
- new Layer(1, \stdClass::class);
+ new Layer(1, stdClass::class);
}
public function testAddNodesToLayer(): void
diff --git a/tests/Phpml/NeuralNetwork/Network/LayeredNetworkTest.php b/tests/Phpml/NeuralNetwork/Network/LayeredNetworkTest.php
index 48bee66..c1779b8 100644
--- a/tests/Phpml/NeuralNetwork/Network/LayeredNetworkTest.php
+++ b/tests/Phpml/NeuralNetwork/Network/LayeredNetworkTest.php
@@ -44,10 +44,7 @@ class LayeredNetworkTest extends TestCase
$this->assertEquals([0.5], $network->getOutput());
}
- /**
- * @return LayeredNetwork
- */
- private function getLayeredNetworkMock()
+ private function getLayeredNetworkMock(): LayeredNetwork
{
return $this->getMockForAbstractClass(LayeredNetwork::class);
}
diff --git a/tests/Phpml/NeuralNetwork/Node/Neuron/SynapseTest.php b/tests/Phpml/NeuralNetwork/Node/Neuron/SynapseTest.php
index 02d6dfa..1c09eae 100644
--- a/tests/Phpml/NeuralNetwork/Node/Neuron/SynapseTest.php
+++ b/tests/Phpml/NeuralNetwork/Node/Neuron/SynapseTest.php
@@ -7,6 +7,7 @@ namespace tests\Phpml\NeuralNetwork\Node\Neuron;
use Phpml\NeuralNetwork\Node\Neuron;
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
use PHPUnit\Framework\TestCase;
+use PHPUnit_Framework_MockObject_MockObject;
class SynapseTest extends TestCase
{
@@ -39,11 +40,9 @@ class SynapseTest extends TestCase
}
/**
- * @param int $output
- *
- * @return \PHPUnit_Framework_MockObject_MockObject
+ * @param int|float $output
*/
- private function getNodeMock($output = 1)
+ private function getNodeMock($output = 1): PHPUnit_Framework_MockObject_MockObject
{
$node = $this->getMockBuilder(Neuron::class)->getMock();
$node->method('getOutput')->willReturn($output);
diff --git a/tests/Phpml/NeuralNetwork/Node/NeuronTest.php b/tests/Phpml/NeuralNetwork/Node/NeuronTest.php
index 89f1ca1..a58f2ec 100644
--- a/tests/Phpml/NeuralNetwork/Node/NeuronTest.php
+++ b/tests/Phpml/NeuralNetwork/Node/NeuronTest.php
@@ -8,6 +8,7 @@ use Phpml\NeuralNetwork\ActivationFunction\BinaryStep;
use Phpml\NeuralNetwork\Node\Neuron;
use Phpml\NeuralNetwork\Node\Neuron\Synapse;
use PHPUnit\Framework\TestCase;
+use PHPUnit_Framework_MockObject_MockObject;
class NeuronTest extends TestCase
{
@@ -52,11 +53,9 @@ class NeuronTest extends TestCase
}
/**
- * @param int $output
- *
- * @return Synapse|\PHPUnit_Framework_MockObject_MockObject
+ * @return Synapse|PHPUnit_Framework_MockObject_MockObject
*/
- private function getSynapseMock($output = 2)
+ private function getSynapseMock(int $output = 2)
{
$synapse = $this->getMockBuilder(Synapse::class)->disableOriginalConstructor()->getMock();
$synapse->method('getOutput')->willReturn($output);
diff --git a/tests/Phpml/PipelineTest.php b/tests/Phpml/PipelineTest.php
index fc06e56..caf1961 100644
--- a/tests/Phpml/PipelineTest.php
+++ b/tests/Phpml/PipelineTest.php
@@ -72,7 +72,7 @@ class PipelineTest extends TestCase
{
$transformers = [
new TokenCountVectorizer(new WordTokenizer()),
- new TfIdfTransformer()
+ new TfIdfTransformer(),
];
$estimator = new SVC();
diff --git a/tests/Phpml/Preprocessing/NormalizerTest.php b/tests/Phpml/Preprocessing/NormalizerTest.php
index 22ed1bd..3d5940a 100644
--- a/tests/Phpml/Preprocessing/NormalizerTest.php
+++ b/tests/Phpml/Preprocessing/NormalizerTest.php
@@ -109,8 +109,9 @@ class NormalizerTest extends TestCase
for ($i = 0; $i < 10; ++$i) {
$sample = array_fill(0, 3, 0);
for ($k = 0; $k < 3; ++$k) {
- $sample[$k] = rand(1, 100);
+ $sample[$k] = random_int(1, 100);
}
+
// Last feature's value shared across samples.
$sample[] = 1;
diff --git a/tests/Phpml/Regression/LeastSquaresTest.php b/tests/Phpml/Regression/LeastSquaresTest.php
index 7d835a2..7517a9b 100644
--- a/tests/Phpml/Regression/LeastSquaresTest.php
+++ b/tests/Phpml/Regression/LeastSquaresTest.php
@@ -81,7 +81,7 @@ class LeastSquaresTest extends TestCase
$testSamples = [[9300], [10565], [15000]];
$predicted = $regression->predict($testSamples);
- $filename = 'least-squares-test-'.rand(100, 999).'-'.uniqid();
+ $filename = 'least-squares-test-'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($regression, $filepath);
diff --git a/tests/Phpml/Regression/SVRTest.php b/tests/Phpml/Regression/SVRTest.php
index 3cd0ee5..a220d21 100644
--- a/tests/Phpml/Regression/SVRTest.php
+++ b/tests/Phpml/Regression/SVRTest.php
@@ -48,7 +48,7 @@ class SVRTest extends TestCase
$testSamples = [64];
$predicted = $regression->predict($testSamples);
- $filename = 'svr-test'.rand(100, 999).'-'.uniqid();
+ $filename = 'svr-test'.random_int(100, 999).'-'.uniqid();
$filepath = tempnam(sys_get_temp_dir(), $filename);
$modelManager = new ModelManager();
$modelManager->saveToFile($regression, $filepath);