Bladeren bron

Greatly simplify MarkovChain implementation

tags/v0.3
Ben Kurtovic 5 jaren geleden
bovenliggende
commit
8a945b0782
1 gewijzigde bestanden met toevoegingen van 27 en 23 verwijderingen
  1. +27
    -23
      earwigbot/wiki/copyvios/markov.py

+ 27
- 23
earwigbot/wiki/copyvios/markov.py Bestand weergeven

@@ -20,7 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from collections import defaultdict
from re import sub, UNICODE

__all__ = ["EMPTY", "EMPTY_INTERSECTION", "MarkovChain",
@@ -34,23 +33,27 @@ class MarkovChain(object):

def __init__(self, text):
self.text = text
self.chain = defaultdict(lambda: defaultdict(lambda: 0))
words = sub(r"[^\w\s-]", "", text.lower(), flags=UNICODE).split()
self.chain = self._build()
self.size = self._get_size()

def _build(self):
"""Build and return the Markov chain from the input text."""
padding = self.degree - 1
words = sub(r"[^\w\s-]", "", self.text.lower(), flags=UNICODE).split()
words = ([self.START] * padding) + words + ([self.END] * padding)
for i in range(len(words) - self.degree + 1):
last = i + self.degree - 1
self.chain[tuple(words[i:last])][words[last]] += 1
self.size = self._get_size()
chain = {}

for i in xrange(len(words) - self.degree + 1):
phrase = tuple(words[i:i+self.degree])
if phrase in chain:
chain[phrase] += 1
else:
chain[phrase] = 1
return chain

def _get_size(self):
"""Return the size of the Markov chain: the total number of nodes."""
size = 0
for node in self.chain.itervalues():
for hits in node.itervalues():
size += hits
return size
return sum(self.chain.itervalues())

def __repr__(self):
"""Return the canonical string representation of the MarkovChain."""
@@ -65,20 +68,21 @@ class MarkovChainIntersection(MarkovChain):
"""Implements the intersection of two chains (i.e., their shared nodes)."""

def __init__(self, mc1, mc2):
self.chain = defaultdict(lambda: defaultdict(lambda: 0))
self.mc1, self.mc2 = mc1, mc2
c1 = mc1.chain
c2 = mc2.chain

for word, nodes1 in c1.iteritems():
if word in c2:
nodes2 = c2[word]
for node, count1 in nodes1.iteritems():
if node in nodes2:
count2 = nodes2[node]
self.chain[word][node] = min(count1, count2)
self.chain = self._build()
self.size = self._get_size()

def _build(self):
"""Build and return the Markov chain from the input chains."""
c1 = self.mc1.chain
c2 = self.mc2.chain
chain = {}

for phrase in c1:
if phrase in c2:
chain[phrase] = min(c1[phrase], c2[phrase])
return chain

def __repr__(self):
"""Return the canonical string representation of the intersection."""
res = "MarkovChainIntersection(mc1={0!r}, mc2={1!r})"


Laden…
Annuleren
Opslaan