Skip to content

Commit

Permalink
feat: add entropy operation
Browse files Browse the repository at this point in the history
  • Loading branch information
drupol committed Nov 16, 2023
1 parent 904df55 commit ab3e143
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 1 deletion.
7 changes: 6 additions & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ parameters:

-
message: "#^Parameter \\#1 \\$callable of class loophp\\\\collection\\\\Collection constructor expects callable\\(mixed \\.\\.\\.\\)\\: iterable\\<int, float\\>, Closure\\(iterable\\)\\: Generator\\<int, float, mixed, mixed\\> given\\.$#"
count: 1
count: 2
path: src/Collection.php

-
Expand Down Expand Up @@ -210,6 +210,11 @@ parameters:
count: 1
path: src/Operation/Duplicate.php

-
message: "#^Parameter \\#1 \\$ of closure expects callable\\(mixed, mixed, iterable\\)\\: mixed, Closure\\(mixed, int, loophp\\\\collection\\\\Collection\\)\\: float given\\.$#"
count: 1
path: src/Operation/Entropy.php

-
message: "#^Template type V of method loophp\\\\collection\\\\Operation\\\\Find\\:\\:__invoke\\(\\) is not referenced in a parameter\\.$#"
count: 1
Expand Down
15 changes: 15 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@
<code><![CDATA[Closure(bool): Closure(iterable<TKey, T>): (Generator<int, T>|Generator<TKey, T>)]]></code>
</InvalidReturnType>
</file>
<file src="src/Operation/Entropy.php">
<InvalidArgument>
<code><![CDATA[static fn (mixed $_, int $key, Collection $collection): float => $collection
->limit($key + 1)
->frequency()
->keys()
->map(
static fn (int $freq): float => $freq / ($key + 1)
)
->reduce(
static fn (float $acc, float $freq): float => 0 === $key ? $acc : $acc - (($freq) * log($freq, 2)) / log($key + 1, 2),
0
)]]></code>
</InvalidArgument>
</file>
<file src="src/Operation/Product.php">
<InvalidArgument>
<code>[[]]</code>
Expand Down
5 changes: 5 additions & 0 deletions src/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ public static function empty(): CollectionInterface
return self::fromIterable([]);
}

public function entropy(): CollectionInterface
{
return new self((new Operation\Entropy())(), [$this]);
}

public function equals(iterable $other): bool
{
return (new Operation\Equals())()($other)($this)->current();
Expand Down
5 changes: 5 additions & 0 deletions src/CollectionDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,11 @@ public static function empty(): static
return new static(Collection::empty());
}

public function entropy(): static
{
return new static($this->innerCollection->entropy());
}

public function equals(iterable $other): bool
{
return $this->innerCollection->equals($other);
Expand Down
2 changes: 2 additions & 0 deletions src/Contract/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
* @template-extends Operation\DropWhileable<TKey, T>
* @template-extends Operation\Dumpable<TKey, T>
* @template-extends Operation\Duplicateable<TKey, T>
* @template-extends Operation\Entropyable<TKey, T>
* @template-extends Operation\Everyable<TKey, T>
* @template-extends Operation\Explodeable<TKey, T>
* @template-extends Operation\Falsyable<TKey, T>
Expand Down Expand Up @@ -162,6 +163,7 @@ interface Collection extends
Operation\Dumpable,
Operation\Duplicateable,
Operation\Equalsable,
Operation\Entropyable,
Operation\Everyable,
Operation\Explodeable,
Operation\Falsyable,
Expand Down
27 changes: 27 additions & 0 deletions src/Contract/Operation/Entropyable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Contract\Operation;

use loophp\collection\Contract\Collection;

/**
* @template TKey
* @template T
*/
interface Entropyable
{
/**
* Calculate the normalized Shannon entropy for each collection items.
*
* If you're looking for one single result, you must get the last item using
* `last` operation.
*
* @see https://en.wikipedia.org/wiki/Entropy_(information_theory)
* @see https://loophp-collection.readthedocs.io/en/stable/pages/api.html#entropy
*
* @return Collection<int, float>
*/
public function entropy(): Collection;
}
45 changes: 45 additions & 0 deletions src/Operation/Entropy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace loophp\collection\Operation;

use Closure;
use Generator;
use loophp\collection\Collection;
use loophp\collection\Contract\Collection as CollectionInterface;

/**
* @immutable
*
* @template TKey
* @template T
*/
final class Entropy extends AbstractOperation
{
/**
* @return Closure(iterable<TKey, T>): Generator<int, float>
*/
public function __invoke(): Closure
{
/** @var Closure(iterable<TKey, T>): Generator<int, float> $pipe */
$pipe = (new Pipe())()(
(static fn (iterable $iterable): CollectionInterface => Collection::fromIterable($iterable)->normalize()->squash()),
(new Map())()(
static fn (mixed $_, int $key, Collection $collection): float => $collection
->limit($key + 1)
->frequency()
->keys()
->map(
static fn (int $freq): float => $freq / ($key + 1)
)
->reduce(
static fn (float $acc, float $freq): float => 0 === $key ? $acc : $acc - (($freq) * log($freq, 2)) / log($key + 1, 2),
0
)
),
);

return $pipe;
}
}
1 change: 1 addition & 0 deletions tests/unit/CollectionGenericOperationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ final class CollectionGenericOperationTest extends TestCase
* @dataProvider dropWhileOperationProvider
* @dataProvider dumpOperationProvider
* @dataProvider duplicateOperationProvider
* @dataProvider entropyOperationProvider
* @dataProvider explodeOperationProvider
* @dataProvider filterOperationProvider
* @dataProvider flatMapOperationProvider
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/Traits/GenericCollectionProviders.php
Original file line number Diff line number Diff line change
Expand Up @@ -1028,6 +1028,31 @@ public function name(): string
];
}

public static function entropyOperationProvider()
{
$operation = 'entropy';

yield [
$operation,
[],
[],
[],
];

yield [
$operation,
[],
[
'a',
'b',
],
[
(float) 0,
(float) 1,
],
];
}

public static function equalsOperationProvider()
{
$operation = 'equals';
Expand Down

0 comments on commit ab3e143

Please sign in to comment.