Skip to content

Commit 783d6a2

Browse files
authored
Merge pull request #3 from EnzoMC/v1.1
V1.1
2 parents 0c3f6ed + 3395b42 commit 783d6a2

File tree

6 files changed

+295
-191
lines changed

6 files changed

+295
-191
lines changed

‎.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ Thumbs.db
2323
*.csv
2424

2525
# ide settings
26-
.idea/
26+
.idea/
27+
28+
# composer packages
29+
vendor/

‎composer.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
}
1010
],
1111
"require": {
12-
"php": ">=7.0"
12+
"php": ">=7.4",
13+
"drupol/phpermutations": "^1.4"
1314
},
1415
"autoload": {
1516
"psr-4": {

‎composer.lock

+84
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/FPGrowth.php

+45-94
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,50 @@
11
<?php
22

3+
declare(strict_types=1);
34

45
namespace EnzoMC\PhpFPGrowth;
56

7+
use drupol\phpermutations\Generators\Combinations;
68

79
class FPGrowth
810
{
9-
protected $support = 3;
10-
protected $confidence = 0.7;
11+
protected int $support = 3;
12+
protected float $confidence = 0.7;
1113

1214
private $patterns;
1315
private $rules;
1416

1517
/**
16-
* @return mixed
18+
* @return int
1719
*/
18-
public function getSupport()
20+
public function getSupport(): int
1921
{
2022
return $this->support;
2123
}
2224

2325
/**
24-
* @param mixed $support
26+
* @param int $support
27+
* @return self
2528
*/
26-
public function setSupport($support)
29+
public function setSupport(int $support): self
2730
{
2831
$this->support = $support;
2932
return $this;
3033
}
3134

3235
/**
33-
* @return mixed
36+
* @return float
3437
*/
35-
public function getConfidence()
38+
public function getConfidence(): float
3639
{
3740
return $this->confidence;
3841
}
3942

4043
/**
41-
* @param mixed $confidence
44+
* @param float $confidence
45+
* @return self
4246
*/
43-
public function setConfidence($confidence)
47+
public function setConfidence(float $confidence): self
4448
{
4549
$this->confidence = $confidence;
4650
return $this;
@@ -64,48 +68,57 @@ public function getRules()
6468

6569
/**
6670
* FPGrowth constructor.
67-
* @param $support 1, 2, 3 ...
68-
* @param $confidence 0 ... 1
71+
* @param int $support 1, 2, 3 ...
72+
* @param float $confidence 0 ... 1
6973
*/
70-
public function __construct($support, $confidence)
74+
public function __construct(int $support, float $confidence)
7175
{
72-
$this->support = $support;
73-
$this->confidence = $confidence;
76+
$this->setSupport($support);
77+
$this->setConfidence($confidence);
7478
}
7579

7680
/**
7781
* Do algorithm
78-
* @param $transactions
82+
* @param array $transactions
7983
*/
80-
public function run($transactions)
84+
public function run(array $transactions)
8185
{
82-
$this->patterns = $this->findFrequentPatterns($transactions, $this->support);
83-
$this->rules = $this->generateAssociationRules($this->patterns, $this->confidence);
86+
$this->patterns = $this->findFrequentPatterns($transactions);
87+
$this->rules = $this->generateAssociationRules($this->patterns);
8488
}
8589

86-
protected function findFrequentPatterns($transactions, $support_threshold)
90+
/**
91+
* @param array $transactions
92+
* @return array<string,int>
93+
*/
94+
protected function findFrequentPatterns(array $transactions): array
8795
{
88-
$tree = new FPTree($transactions, $support_threshold, null, null);
89-
return $tree->minePatterns($support_threshold);
96+
$tree = new FPTree($transactions, $this->support, null, 0);
97+
return $tree->minePatterns($this->support);
9098
}
9199

92-
protected function generateAssociationRules($patterns, $confidence_threshold)
100+
/**
101+
* @param array $patterns
102+
* @return array
103+
*/
104+
protected function generateAssociationRules(array $patterns): array
93105
{
94106
$rules = [];
95-
foreach (array_keys($patterns) as $itemsetStr) {
96-
$itemset = explode(',', $itemsetStr);
97-
$upper_support = $patterns[$itemsetStr];
98-
for ($i = 1; $i < count($itemset); $i++) {
99-
foreach (self::combinations($itemset, $i) as $antecedent) {
107+
foreach (array_keys($patterns) as $pattern) {
108+
$itemSet = explode(',', $pattern);
109+
$upperSupport = $patterns[$pattern];
110+
for ($i = 1; $i < count($itemSet); $i++) {
111+
$combinations = new Combinations($itemSet, $i);
112+
foreach ($combinations->generator() as $antecedent) {
100113
sort($antecedent);
101114
$antecedentStr = implode(',', $antecedent);
102-
$consequent = array_diff($itemset, $antecedent);
115+
$consequent = array_diff($itemSet, $antecedent);
103116
sort($consequent);
104117
$consequentStr = implode(',', $consequent);
105118
if (isset($patterns[$antecedentStr])) {
106-
$lower_support = $patterns[$antecedentStr];
107-
$confidence = (floatval($upper_support) / $lower_support);
108-
if ($confidence >= $confidence_threshold) {
119+
$lowerSupport = $patterns[$antecedentStr];
120+
$confidence = floatval($upperSupport) / $lowerSupport;
121+
if ($confidence >= $this->confidence) {
109122
$rules[] = [$antecedentStr, $consequentStr, $confidence];
110123
}
111124
}
@@ -114,66 +127,4 @@ protected function generateAssociationRules($patterns, $confidence_threshold)
114127
}
115128
return $rules;
116129
}
117-
118-
public static function iter($var)
119-
{
120-
121-
switch (true) {
122-
case $var instanceof \Iterator:
123-
return $var;
124-
125-
case $var instanceof \Traversable:
126-
return new \IteratorIterator($var);
127-
128-
case is_string($var):
129-
$var = str_split($var);
130-
131-
case is_array($var):
132-
return new \ArrayIterator($var);
133-
134-
default:
135-
$type = gettype($var);
136-
throw new \InvalidArgumentException("'$type' type is not iterable");
137-
}
138-
139-
return;
140-
}
141-
142-
public static function combinations($iterable, $r)
143-
{
144-
$pool = is_array($iterable) ? $iterable : iterator_to_array(self::iter($iterable));
145-
$n = sizeof($pool);
146-
147-
if ($r > $n) {
148-
return;
149-
}
150-
151-
$indices = range(0, $r - 1);
152-
yield array_slice($pool, 0, $r);
153-
154-
for (; ;) {
155-
for (; ;) {
156-
for ($i = $r - 1; $i >= 0; $i--) {
157-
if ($indices[$i] != $i + $n - $r) {
158-
break 2;
159-
}
160-
}
161-
162-
return;
163-
}
164-
165-
$indices[$i]++;
166-
167-
for ($j = $i + 1; $j < $r; $j++) {
168-
$indices[$j] = $indices[$j - 1] + 1;
169-
}
170-
171-
$row = [];
172-
foreach ($indices as $i) {
173-
$row[] = $pool[$i];
174-
}
175-
176-
yield $row;
177-
}
178-
}
179130
}

‎src/FPNode.php

+25-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
<?php
22

3+
declare(strict_types=1);
34

45
namespace EnzoMC\PhpFPGrowth;
56

6-
use stdClass;
7-
8-
class FPNode extends stdClass
7+
class FPNode
98
{
9+
public $value;
10+
public int $count;
11+
public ?FPNode $parent = null;
12+
public ?FPNode $link = null;
13+
/** @var FPNode[] */
14+
public array $children;
15+
1016
/**
1117
* Create the node.
18+
* @param mixed $value
19+
* @param int $count
20+
* @param FPNode|null $parent
1221
*/
13-
function __construct($value, $count, $parent)
22+
public function __construct($value, int $count, ?FPNode $parent)
1423
{
1524
$this->value = $value;
1625
$this->count = $count;
@@ -21,11 +30,13 @@ function __construct($value, $count, $parent)
2130

2231
/**
2332
* Check if node has a particular child node.
33+
* @param mixed $value
34+
* @return bool
2435
*/
25-
function has_child($value)
36+
public function hasChild($value): bool
2637
{
2738
foreach ($this->children as $node) {
28-
if (($node->value == $value)) {
39+
if ($node->value == $value) {
2940
return true;
3041
}
3142
}
@@ -34,21 +45,25 @@ function has_child($value)
3445

3546
/**
3647
* Return a child node with a particular value.
48+
* @param $value
49+
* @return FPNode|null
3750
*/
38-
function get_child($value)
51+
public function getChild($value): ?FPNode
3952
{
4053
foreach ($this->children as $node) {
41-
if (($node->value == $value)) {
54+
if ($node->value == $value) {
4255
return $node;
4356
}
4457
}
45-
return;
58+
return null;
4659
}
4760

4861
/**
4962
* Add a node as a child node.
63+
* @param $value
64+
* @return FPNode
5065
*/
51-
function add_child($value)
66+
public function addChild($value): FPNode
5267
{
5368
$child = new FPNode($value, 1, $this);
5469
$this->children[] = $child;

0 commit comments

Comments
 (0)