commit 5400e99e1a18bba2cd5d7a97442339e0a60cc843
parent cc5ea7bfcdfb88adbf85a24676b0e5992d605195
Author: Antoine Amarilli <a3nm@a3nm.net>
Date: Tue, 13 Mar 2012 15:35:01 +0100
refactor rhyme
Diffstat:
rhyme.py | | | 126 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- |
1 file changed, 70 insertions(+), 56 deletions(-)
diff --git a/rhyme.py b/rhyme.py
@@ -11,6 +11,68 @@ NBEST = 5
# phonetic vowels
vowel = list("Eeaio592O#@y%u")
+class Constraint:
+ def __init__(self, phon, eye, aphon):
+ self.phon = phon # minimal number of common suffix phones
+ self.eye = eye # minimal number of common suffix letters
+ self.aphon = aphon # minimal number of common suffix vowel phones
+
+ def mmax(self, a, b):
+ """max, with -1 representing infty"""
+ if a == -1 or b == -1:
+ return -1
+ else:
+ return max(a, b)
+
+ def restrict(self, c):
+ """take the max between us and constraint object c"""
+ if not c:
+ return
+ self.phon = self.mmax(self.phon, c.phon)
+ self.eye = self.mmax(self.eye, c.eye)
+ self.aphon = self.mmax(self.aphon, c.aphon)
+
+class Rhyme:
+ def __init__(self, line, constraint):
+ self.constraint = constraint
+ self.phon = lookup(line)
+ self.eye = line
+
+ def match(self, phon, eye):
+ """limit our phon and eye to those which match phon and eye and which
+ respect constraints"""
+ new_phon = set()
+ for x in self.phon:
+ for y in phon:
+ val = phon_rhyme(x, y)
+ if val >= self.constraint.phon and self.constraint.phon >= 0:
+ new_phon.add(x[-val:])
+ val = assonance_rhyme(x, y)
+ if val >= self.constraint.aphon and self.constraint.aphon >= 0:
+ new_phon.add(x[-val:])
+ self.phon = new_phon
+ if self.eye:
+ val = eye_rhyme(self.eye, eye)
+ if val >= self.constraint.eye and self.constraint.eye >= 0:
+ self.eye = self.eye[-val:]
+ else:
+ self.eye = None
+
+ def restrict(self, r):
+ """take the intersection between us and rhyme object r"""
+ self.constraint.restrict(r.constraint)
+ self.match(r.phon, r.eye)
+
+ def feed(self, line, constraint=None):
+ """extend us with a line and a constraint"""
+ return self.restrict(Rhyme(line, constraint))
+
+ def satisfied(self):
+ return self.eye or len(self.phon) > 0
+
+ def print(self):
+ pprint(self.phon)
+
def suffix(x, y):
"""length of the longest common suffix of x and y"""
bound = min(len(x), len(y))
@@ -19,7 +81,7 @@ def suffix(x, y):
return i
return bound
-def rhyme(x, y):
+def phon_rhyme(x, y):
"""are x and y acceptable phonetic rhymes?"""
assert(isinstance(x, str))
assert(isinstance(y, str))
@@ -33,7 +95,7 @@ def strip_consonants(x):
return str([a for a in x if a in vowel or a == 'j'])
def assonance_rhyme(x, y):
- return rhyme(strip_consonants(x), strip_consonants(y))
+ return phon_rhyme(strip_consonants(x), strip_consonants(y))
def eye_rhyme(x, y):
"""value of x and y as an eye rhyme"""
@@ -55,51 +117,6 @@ def lookup(s):
frhyme.lookup(escape(a), NBEST)])), s))
return functools.reduce(concat_couples, sets, set(['']))
-def init_rhyme(line, constraint):
- """initialize a rhyme"""
- return (lookup(line), line, constraint)
-
-def mmax(a, b):
- """max, with -1 representing infty"""
- if a == -1 or b == -1:
- return -1
- else:
- return max(a, b)
-
-def max_constraints(a, b):
- # TODO get rid of that
- return (mmax(a[0], b[0]), mmax(a[1], b[1]), mmax(a[2], b[2]))
-
-def check_rhyme(current, new):
- oldp, old, old_constraints = current
- new, new_constraints = new
- constraints = max_constraints(new_constraints, old_constraints)
- newp = lookup(new)
- newp_r, new_r = match(oldp, old, newp, new, constraints)
- return (newp_r, new_r, constraints)
-
-def match(ap, a, bp, b, constraints):
- # ap is the possible pronunciations, a the only possible writing
- normalc, eyec, assonancec = constraints
- rp = set()
- for x in ap:
- for y in bp:
- val = rhyme(x, y)
- if val >= normalc and normalc >= 0:
- rp.add(x[-val:])
- val = assonance_rhyme(x, y)
- if val >= assonancec and assonancec >= 0:
- rp.add(x[-val:])
- if a != None:
- val = eye_rhyme(a, b)
- if val >= eyec and eyec >= 0:
- r = a[0][-val:]
- else:
- r = None
- else:
- r = None
- return rp, r
-
#workaround for lexique
def escape(t):
return re.sub('œ', 'oe', re.sub('æ', 'ae', t))
@@ -112,17 +129,14 @@ if __name__ == '__main__':
line = line.lower().strip().split(' ')
if len(line) < 1:
continue
- constraint = (1, -1, -1)
- np, p, c = init_rhyme(line[0], constraint)
- pprint(np)
- ok = True
+ constraint = Constraint(1, -1, -1)
+ rhyme = Rhyme(line[0], constraint)
for x in line[1:]:
- np, n, c = check_rhyme((np, p, c), (x, constraint))
- pprint(np)
- if n == None and len(np) == 0:
+ rhyme.feed(x)
+ rhyme.print()
+ if not rhyme.satisfied():
print("No.")
- ok = False
break
- if ok:
+ if rhyme.satisfied():
print ("Yes.")