### Improve distance performance and reduce duplication in distance classes. (#348)

```* Issue #347: Reduce duplicated code.

* Issue #347: Replace array_* with regular loops for better perfomance.```
parent 6844cf40
 ... ... @@ -4,27 +4,16 @@ declare(strict_types=1); namespace Phpml\Math\Distance; use Phpml\Exception\InvalidArgumentException; use Phpml\Math\Distance; class Chebyshev implements Distance /** * Class Chebyshev */ class Chebyshev extends Distance { /** * @throws InvalidArgumentException * {@inheritdoc} */ public function distance(array \$a, array \$b): float { if (count(\$a) !== count(\$b)) { throw new InvalidArgumentException('Size of given arrays does not match'); } \$differences = []; \$count = count(\$a); for (\$i = 0; \$i < \$count; ++\$i) { \$differences[] = abs(\$a[\$i] - \$b[\$i]); } return max(\$differences); return max(\$this->deltas(\$a, \$b)); } }
 norm = \$norm; } /** * @throws InvalidArgumentException */ public function distance(array \$a, array \$b): float { \$distance = 0; foreach (\$this->deltas(\$a, \$b) as \$delta) { \$distance += \$delta ** \$this->norm; } return \$distance ** (1 / \$this->norm); } /** * @throws InvalidArgumentException */ protected function deltas(array \$a, array \$b): array { \$count = count(\$a); if (\$count !== count(\$b)) { throw new InvalidArgumentException('Size of given arrays does not match'); } \$deltas = []; for (\$i = 0; \$i < \$count; \$i++) { \$deltas[] = abs(\$a[\$i] - \$b[\$i]); } return \$deltas; } }
 ... ... @@ -4,31 +4,25 @@ declare(strict_types=1); namespace Phpml\Math\Distance; use Phpml\Exception\InvalidArgumentException; use Phpml\Math\Distance; class Euclidean implements Distance /** * Class Euclidean * * L^2 Metric. */ class Euclidean extends Distance { /** * @throws InvalidArgumentException * Euclidean constructor. */ public function distance(array \$a, array \$b): float public function __construct() { if (count(\$a) !== count(\$b)) { throw new InvalidArgumentException('Size of given arrays does not match'); } \$distance = 0; foreach (\$a as \$i => \$val) { \$distance += (\$val - \$b[\$i]) ** 2; } return sqrt((float) \$distance); parent::__construct(2.0); } /** * Square of Euclidean distance * * @throws \Phpml\Exception\InvalidArgumentException */ public function sqDistance(array \$a, array \$b): float { ... ...
 ... ... @@ -4,22 +4,18 @@ declare(strict_types=1); namespace Phpml\Math\Distance; use Phpml\Exception\InvalidArgumentException; use Phpml\Math\Distance; class Manhattan implements Distance /** * Class Manhattan * * L^1 Metric. */ class Manhattan extends Distance { /** * @throws InvalidArgumentException * Manhattan constructor. */ public function distance(array \$a, array \$b): float public function __construct() { if (count(\$a) !== count(\$b)) { throw new InvalidArgumentException('Size of given arrays does not match'); } return array_sum(array_map(function (\$m, \$n) { return abs(\$m - \$n); }, \$a, \$b)); parent::__construct(1.0); } }
 ... ... @@ -4,37 +4,11 @@ declare(strict_types=1); namespace Phpml\Math\Distance; use Phpml\Exception\InvalidArgumentException; use Phpml\Math\Distance; class Minkowski implements Distance /** * Class Minkowski * * L^n Metric. */ class Minkowski extends Distance { /** * @var float */ private \$lambda; public function __construct(float \$lambda = 3.0) { \$this->lambda = \$lambda; } /** * @throws InvalidArgumentException */ public function distance(array \$a, array \$b): float { if (count(\$a) !== count(\$b)) { throw new InvalidArgumentException('Size of given arrays does not match'); } \$distance = 0; \$count = count(\$a); for (\$i = 0; \$i < \$count; ++\$i) { \$distance += pow(abs(\$a[\$i] - \$b[\$i]), \$this->lambda); } return (float) pow(\$distance, 1 / \$this->lambda); } }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment