Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 280309d

Browse files
author
Eric Naeseth
committed
Initial copy of the fp_growth module; we can create trees and add transactions to them.
1 parent 8befb07 commit 280309d

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

fp_growth.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# encoding: utf-8
2+
3+
"""
4+
A Python implementation of the FP-growth algorithm.
5+
"""
6+
7+
__author__ = 'Eric Naeseth <[email protected]>'
8+
__copyright__ = 'Copyright © 2009 Eric Naeseth'
9+
__license__ = 'MIT License'
10+
11+
class FPTree(object):
12+
"""
13+
An FP tree.
14+
15+
This object may only store transaction items that are hashable (i.e., all
16+
items must be valid as dictionary keys or set members).
17+
"""
18+
def __init__(self):
19+
# The root node of the tree.
20+
self._root = FPNode(self, None, None)
21+
22+
# A dictionary mapping items to the head and tail of a path of
23+
# "neighbors" that will hit every node containing that item.
24+
self._paths = {}
25+
26+
def add(self, transaction):
27+
"""
28+
Adds a transaction to the tree.
29+
"""
30+
31+
point = self._root
32+
33+
for item in transaction:
34+
next_point = point.search(item)
35+
if next_point:
36+
# There is already a node in this tree for the current
37+
# transaction item; reuse it.
38+
next_point.increment()
39+
else:
40+
# Create a new point and add it as a child of the point we're
41+
# currently looking at.
42+
next_point = FPNode(self, item)
43+
point.add(next_point)
44+
45+
# Update the path of nodes that contain this item to include
46+
# our new node.
47+
try:
48+
path = self._paths[item]
49+
path[1].neighbor = next_point # path[1] is the tail
50+
path[1] = next_point
51+
except KeyError:
52+
# First node for this item; start a new path.
53+
self._paths[item] = [next_point, next_point]
54+
55+
point = next_point
56+
57+
58+
class FPNode(object):
59+
"""A node in an FP tree."""
60+
61+
def __init__(self, tree, item, count=1):
62+
self._tree = tree
63+
self._item = item
64+
self._count = count
65+
self._parent = None
66+
self._children = {}
67+
self._neighbor = None
68+
69+
def add(self, child):
70+
"""Adds the given FPNode `child` as a child of this node."""
71+
72+
if not isinstance(child, FPNode):
73+
raise TypeError("Can only add other FPNodes as children")
74+
75+
if not child.item in self._children:
76+
self._children[child.item] = child
77+
child.parent = self
78+
79+
def search(self, item):
80+
"""
81+
Checks to see if this node contains a child node for the given item.
82+
If so, that node is returned; otherwise, `None` is returned.
83+
"""
84+
85+
try:
86+
return self._children[item]
87+
except KeyError:
88+
return None
89+
90+
def __contains__(self, item):
91+
return item in self._children
92+
93+
@property
94+
def tree(self):
95+
"""The tree in which this node appears."""
96+
return self._tree
97+
98+
@property
99+
def item(self):
100+
"""The item contained in this node."""
101+
return self._item
102+
103+
@property
104+
def count(self):
105+
"""The count associated with this node's item."""
106+
return self._count
107+
108+
def increment(self):
109+
"""Increments the count associated with this node's item."""
110+
if self._count is None:
111+
raise ValueError("Root nodes have no associated count.")
112+
self._count += 1
113+
114+
@property
115+
def root(self):
116+
"""True if this node is the root of a tree; false if otherwise."""
117+
return self._item is None and self._count is None
118+
119+
def parent():
120+
doc = "The node's parent."
121+
def fget(self):
122+
return self._parent
123+
def fset(self, value):
124+
if not isinstance(value, FPNode):
125+
raise TypeError("A node must have an FPNode as a parent.")
126+
if value.tree is not self.tree:
127+
raise ValueError("Cannot have a parent from another tree.")
128+
self._parent = value
129+
return locals()
130+
parent = property(**parent())
131+
132+
def neighbor():
133+
doc = """
134+
The node's neighbor; the one with the same value that is "to the right"
135+
of it in the tree.
136+
"""
137+
def fget(self):
138+
return self._neighbor
139+
def fset(self, value):
140+
if not isinstance(value, FPNode):
141+
raise TypeError("A node must have an FPNode as a neighbor.")
142+
if value.tree is not self.tree:
143+
raise ValueError("Cannot have a neighbor from another tree.")
144+
self._neighbor = value
145+
return locals()
146+
neighbor = property(**neighbor())
147+
148+
@property
149+
def children(self):
150+
"""The nodes that are children of this node."""
151+
return tuple(self._children)
152+
153+
154+
def __repr__(self):
155+
if self.root:
156+
return "<%s (root)>" % type(self).__name__
157+
return "<%s %r (%r)>" % (type(self).__name__, self.item, self.count)
158+

0 commit comments

Comments
 (0)