@@ -88,7 +88,53 @@ def collect_path(node):
88
88
return path
89
89
90
90
return (collect_path (node ) for node in self .nodes (item ) if node .leaf )
91
+
92
+ def conditional_tree_from_paths (paths , minimum_support ):
93
+ """Builds a conditional FP-tree from the given prefix paths."""
94
+ tree = FPTree ()
95
+ condition_item = None
96
+ items = set ()
97
+
98
+ # Import the nodes in the paths into the new tree. Only the counts of the
99
+ # leaf notes matter; the remaining counts will be reconstructed from the
100
+ # leaf counts.
101
+ for path in paths :
102
+ if condition_item is None :
103
+ condition_item = path [- 1 ]
104
+
105
+ point = tree .root
106
+ for node in path :
107
+ next_point = point .search (node .item )
108
+ if not next_point :
109
+ items .add (node .item )
110
+ count = node .count if node .leaf else 0
111
+ next_point = FPNode (tree , node .item , count )
112
+ point .add (next_point )
113
+ tree ._update_route (next_point )
114
+ point = next_point
115
+
116
+ # Calculate the counts of the non-leaf nodes.
117
+ for path in tree .prefix_paths (condition_item ):
118
+ count = None
119
+ for node in reversed (path ):
120
+ if count is not None :
121
+ node ._count += count
122
+ count = node .count
123
+
124
+ # Eliminate the nodes for any items that are no longer frequent.
125
+ for item in items :
126
+ support = sum (n .count for n in tree .nodes (item ))
127
+ if support < minimum_support :
128
+ # Doesn't make the cut anymore
129
+ for node in tree .nodes (item ):
130
+ node .parent .remove (node )
131
+
132
+ # Finally, remove the nodes corresponding to the item for which this
133
+ # conditional tree was generated.
134
+ for node in tree .nodes (condition_item ):
135
+ node .parent .remove (item )
91
136
137
+ return tree
92
138
93
139
class FPNode (object ):
94
140
"""A node in an FP tree."""
0 commit comments