Skip to content

Commit fa2a681

Browse files
committed
init
1 parent de0cff2 commit fa2a681

File tree

7 files changed

+676
-2
lines changed

7 files changed

+676
-2
lines changed

‎.gitignore

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# typical for all available operation systems
2+
__MACOSX/
3+
.DS_Store
4+
Thumbs.db
5+
6+
# some files
7+
*.gz
8+
*.tar
9+
*.bat
10+
*.dat
11+
*.pdf
12+
*.psd
13+
*.log
14+
*.txt
15+
*.flv
16+
*.wmv
17+
*.xlsx
18+
*.xls
19+
*.docx
20+
*.doc
21+
*.phar
22+
*.mmdb
23+
*.csv
24+
25+
# ide settings
26+
.idea/

‎README.md

+136-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,136 @@
1-
# php-fpgrowth
2-
PHP implementation of the Frequent Pattern Growth algorithm
1+
# FP-Growth
2+
A PHP implementation of the Frequent Pattern Growth algorithm
3+
4+
## Getting Started
5+
You can install the package with composer:
6+
7+
composer require enzomc/php-fpgrowth
8+
9+
## Usage
10+
11+
#### Run algorithm
12+
13+
use EnzoMC\PhpFPGrowth\FPGrowth;
14+
15+
$support = 3;
16+
$confidence = 0.7;
17+
18+
$fpgrowth = new FPGrowth($support, $confidence);
19+
20+
$transactions = [
21+
['M', 'O', 'N', 'K', 'E', 'Y'],
22+
['D', 'O', 'N', 'K', 'E', 'Y'],
23+
['M', 'A', 'K', 'E'],
24+
['M', 'U', 'C', 'K', 'Y'],
25+
['C', 'O', 'O', 'K', 'I', 'E']
26+
];
27+
28+
$fpgrowth->run($transactions);
29+
30+
$patterns = $fpgrowth->getPatterns();
31+
$rules = $fpgrowth->getRules();
32+
33+
34+
#### Returned results
35+
36+
Patterns returns as array of arrays like:
37+
38+
[
39+
['ITEM_1,ITEM_2' => 3],
40+
['ITEM_3' => 5],
41+
...
42+
]
43+
44+
Where key is itemset, value is support of that itemset
45+
46+
47+
Rules returns as array of arrays like:
48+
49+
[
50+
['ITEM_1,ITEM_2' => ['ITEM_3',0.7]],
51+
['ITEM_4' => ['ITEM_5',0.7]],
52+
...
53+
]
54+
55+
Where keys is left path of rule, value is array, where first item is right path of the rule and second item is confidence of that rule
56+
57+
#### Result with example transactions
58+
59+
`var_dump($patterns);`
60+
61+
array(10) {
62+
["M"]=>
63+
int(3)
64+
["K,M"]=>
65+
int(3)
66+
["Y"]=>
67+
int(3)
68+
["K,Y"]=>
69+
int(3)
70+
["E,O"]=>
71+
int(4)
72+
["E,K"]=>
73+
int(4)
74+
["E,K,O"]=>
75+
int(4)
76+
["O"]=>
77+
int(4)
78+
["K,O"]=>
79+
int(4)
80+
["K"]=>
81+
int(5)
82+
}
83+
84+
`var_dump($rules);`
85+
86+
array(7) {
87+
["M"]=>
88+
array(2) {
89+
[0]=>
90+
string(1) "K"
91+
[1]=>
92+
float(1)
93+
}
94+
["Y"]=>
95+
array(2) {
96+
[0]=>
97+
string(1) "K"
98+
[1]=>
99+
float(1)
100+
}
101+
["O"]=>
102+
array(2) {
103+
[0]=>
104+
string(1) "K"
105+
[1]=>
106+
float(1)
107+
}
108+
["K"]=>
109+
array(2) {
110+
[0]=>
111+
string(1) "O"
112+
[1]=>
113+
float(0.8)
114+
}
115+
["E,K"]=>
116+
array(2) {
117+
[0]=>
118+
string(1) "O"
119+
[1]=>
120+
float(1)
121+
}
122+
["E,O"]=>
123+
array(2) {
124+
[0]=>
125+
string(1) "K"
126+
[1]=>
127+
float(1)
128+
}
129+
["K,O"]=>
130+
array(2) {
131+
[0]=>
132+
string(1) "E"
133+
[1]=>
134+
float(1)
135+
}
136+
}

‎composer.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "enzomc/php-fpgrowth",
3+
"description": "PHP implementation of the Frequent Pattern Growth algorithm",
4+
"type": "isc",
5+
"authors": [
6+
{
7+
"name": "Ivan Rebrov",
8+
"email": "rebrvivan95@gmail.com"
9+
}
10+
],
11+
"require": {
12+
"php": ">=7.0"
13+
},
14+
"autoload": {
15+
"psr-0": {
16+
"EnzoMC\\PhpFPGrowth\\": "src/"
17+
}
18+
}
19+
}

‎example/example.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
use EnzoMC\PhpFPGrowth\FPGrowth;
4+
5+
$transactions = [
6+
['M', 'O', 'N', 'K', 'E', 'Y'],
7+
['D', 'O', 'N', 'K', 'E', 'Y'],
8+
['M', 'A', 'K', 'E'],
9+
['M', 'U', 'C', 'K', 'Y'],
10+
['C', 'O', 'O', 'K', 'I', 'E'],
11+
];
12+
13+
$support = 3;
14+
$confidence = 0.7;
15+
16+
$fpgrowth = new FPGrowth($support, $confidence);
17+
18+
$fpgrowth->run($transactions);
19+
20+
$patterns = $fpgrowth->getPatterns();
21+
$rules = $fpgrowth->getRules();

‎src/FPGrowth.php

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<?php
2+
3+
4+
namespace EnzoMC\PhpFPGrowth;
5+
6+
7+
class FPGrowth
8+
{
9+
protected $support = 3;
10+
protected $confidence = 0.7;
11+
12+
private $patterns;
13+
private $rules;
14+
15+
/**
16+
* @return mixed
17+
*/
18+
public function getSupport()
19+
{
20+
return $this->support;
21+
}
22+
23+
/**
24+
* @param mixed $support
25+
*/
26+
public function setSupport($support)
27+
{
28+
$this->support = $support;
29+
return $this;
30+
}
31+
32+
/**
33+
* @return mixed
34+
*/
35+
public function getConfidence()
36+
{
37+
return $this->confidence;
38+
}
39+
40+
/**
41+
* @param mixed $confidence
42+
*/
43+
public function setConfidence($confidence)
44+
{
45+
$this->confidence = $confidence;
46+
return $this;
47+
}
48+
49+
/**
50+
* @return mixed
51+
*/
52+
public function getPatterns()
53+
{
54+
return $this->patterns;
55+
}
56+
57+
/**
58+
* @return mixed
59+
*/
60+
public function getRules()
61+
{
62+
return $this->rules;
63+
}
64+
65+
/**
66+
* FPGrowth constructor.
67+
* @param $support 1, 2, 3 ...
68+
* @param $confidence 0 ... 1
69+
*/
70+
public function __construct($support, $confidence)
71+
{
72+
$this->support = $support;
73+
$this->confidence = $confidence;
74+
}
75+
76+
/**
77+
* Do algorithm
78+
* @param $transactions
79+
*/
80+
public function run($transactions)
81+
{
82+
$this->patterns = $this->findFrequentPatterns($transactions, $this->support);
83+
$this->rules = $this->generateAssociationRules($this->patterns, $this->confidence);
84+
}
85+
86+
protected function findFrequentPatterns($transactions, $support_threshold)
87+
{
88+
$tree = new FPTree($transactions, $support_threshold, null, null);
89+
return $tree->minePatterns($support_threshold);
90+
}
91+
92+
protected function generateAssociationRules($patterns, $confidence_threshold)
93+
{
94+
$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) {
100+
sort($antecedent);
101+
$antecedentStr = implode(',', $antecedent);
102+
$consequent = array_diff($itemset, $antecedent);
103+
sort($consequent);
104+
$consequentStr = implode(',', $consequent);
105+
if (isset($patterns[$antecedentStr])) {
106+
$lower_support = $patterns[$antecedentStr];
107+
$confidence = (floatval($upper_support) / $lower_support);
108+
if ($confidence >= $confidence_threshold) {
109+
$rules[$antecedentStr] = [$consequentStr, $confidence];
110+
}
111+
}
112+
}
113+
}
114+
}
115+
return $rules;
116+
}
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+
}
179+
}

0 commit comments

Comments
 (0)