11<?php
22
3+ declare (strict_types=1 );
34
45namespace EnzoMC \PhpFPGrowth ;
56
7+ use drupol \phpermutations \Generators \Combinations ;
68
79class 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}
0 commit comments