Example #1
0
 def bind_mandatory_breaks(self):
     i = 0
     while i < len(self.__units):
         u = self.__units[i]
         if u.is_not_bound() and u.is_head():
             self.bind_left(i, gnoetics.token_lookup_break())
             i += 1
         elif u.is_not_bound() and u.is_tail():
             self.bind_right(i, gnoetics.token_lookup_break())
         else:
             i += 1
Example #2
0
 def bind_mandatory_breaks(self):
     i = 0
     while i < len(self.__units):
         u = self.__units[i]
         if u.is_not_bound() and u.is_head():
             self.bind_left(i, gnoetics.token_lookup_break())
             i += 1
         elif u.is_not_bound() and u.is_tail():
             self.bind_right(i, gnoetics.token_lookup_break())
         else:
             i += 1
Example #3
0
    def __from_xml(self, node):

        assert node.localName == "unit"

        P = {}

        P["syllables"] = int(node.getAttribute("syllables"))
        P["meter"] = node.getAttribute("meter")

        x = node.getAttribute("rhyme")
        if x:
            P["rhyme"] = x

        P["is_beginning_of_line"] = bool(
            node.getAttribute("is_beginning_of_line"))
        P["is_beginning_of_stanza"] = bool(
            node.getAttribute("is_beginning_of_stanza"))
        P["is_end_of_line"] = bool(node.getAttribute("is_end_of_line"))
        P["is_end_of_stanza"] = bool(node.getAttribute("is_end_of_stanza"))

        P["is_head"] = bool(node.getAttribute("is_head"))
        P["is_tail"] = bool(node.getAttribute("is_tail"))

        P["id"] = int(node.getAttribute("id"))

        self.__populate(**P)

        if node.getAttribute("is_bound"):
            tok = None
            if node.getAttribute("binding_is_break"):
                tok = gnoetics.token_lookup_break()
            else:
                x = node.getAttribute("binding")
                if node.getAttribute("binding_is_punctuation"):
                    x = "*punct* %s" % x
                tok = gnoetics.token_lookup(x)

            assert tok.has_left_glue() == bool(
                node.getAttribute("has_left_glue"))
            assert tok.has_right_glue() == bool(
                node.getAttribute("has_right_glue"))

            if tok:
                self.bind(tok)
Example #4
0
    def __from_xml(self, node):

        assert node.localName == "unit"

        P = {}

        P["syllables"] = int(node.getAttribute("syllables"))
        P["meter"]     = node.getAttribute("meter")
        
        x = node.getAttribute("rhyme")
        if x:
            P["rhyme"] = x

        P["is_beginning_of_line"]   = bool(node.getAttribute("is_beginning_of_line"))
        P["is_beginning_of_stanza"] = bool(node.getAttribute("is_beginning_of_stanza"))
        P["is_end_of_line"]         = bool(node.getAttribute("is_end_of_line"))
        P["is_end_of_stanza"]       = bool(node.getAttribute("is_end_of_stanza"))

        P["is_head"] = bool(node.getAttribute("is_head"))
        P["is_tail"] = bool(node.getAttribute("is_tail"))

        P["id"] = int(node.getAttribute("id"))

        self.__populate(**P)

        if node.getAttribute("is_bound"):
            tok = None
            if node.getAttribute("binding_is_break"):
                tok = gnoetics.token_lookup_break()
            else:
                x = node.getAttribute("binding")
                if node.getAttribute("binding_is_punctuation"):
                    x = "*punct* %s" % x
                tok = gnoetics.token_lookup(x)

            assert tok.has_left_glue() == bool(node.getAttribute("has_left_glue"))
            assert tok.has_right_glue() == bool(node.getAttribute("has_right_glue"))

            if tok:
                self.bind(tok)
Example #5
0
#!/usr/bin/python

import random, sys, string, time
import gnoetics

p = gnoetics.Sonnet()

p.bind_left(0, gnoetics.token_lookup_break())
p.bind_left(1, gnoetics.token_lookup("the"))
p.bind_left(2, gnoetics.token_lookup("insane"))
p.bind_left(3, gnoetics.token_lookup("butchershop"))
p.bind_left(4, gnoetics.token_lookup("was"))
p.bind_left(5, gnoetics.token_lookup("undertow"))
p.bind_left(6, gnoetics.token_lookup("before"))
p.bind_left(7, gnoetics.token_lookup("*punct* ."))
p.bind_left(8, gnoetics.token_lookup_break())
p.bind_left(9, gnoetics.token_lookup("who"))
p.bind_left(10, gnoetics.token_lookup("soever"))
p.bind_right(13, gnoetics.token_lookup("monkey"))

print p.to_string()
Example #6
0
def solve_unit(poem,
               model,
               leading_tokens,
               unit,
               trailing_tokens,
               weights=None,
               allow_left_queries=True,
               allow_right_queries=False,
               verbose=None,
               extra_filters=True):

    # Copy list of leading and trailing tokens, so we can
    # manipulate them freely
    leading_tokens = list(leading_tokens)
    trailing_tokens = list(trailing_tokens)

    if verbose is None:
        verbose = os.getenv("GNOETRY_DEBUG") is not None

    def token_list_is_valid(token_list, allow_break_at):
        if allow_break_at < 0:
            allow_break_at += len(token_list)
        for i, tok in enumerate(token_list):
            if tok.is_wildcard():
                return False  # No wildcards!
            if tok.is_break() and i != allow_break_at:
                return False  # Breaks only where we say it is OK!
        return True

    lead_ok = token_list_is_valid(leading_tokens, allow_break_at=0)
    trail_ok = token_list_is_valid(trailing_tokens, allow_break_at=-1)

    if (not lead_ok) and verbose:
        print "Bad leading tokens!"
        print leading_tokens
        print

    if (not trail_ok) and verbose:
        print "Bad trailing tokens!"
        print trailing_tokens
        print

    assert lead_ok
    assert trail_ok

    # Double leading/trailing breaks

    if leading_tokens and leading_tokens[0].is_break():
        leading_tokens.insert(0, gnoetics.token_lookup_break())

    if trailing_tokens and trailing_tokens[-1].is_break():
        trailing_tokens.append(gnoetics.token_lookup_break())

    assert len(leading_tokens) + len(trailing_tokens) >= 2

    assert unit.is_not_bound()

    syl = unit.get_syllables()
    if syl == 0:
        print "*** Ouch!"
        print leading_tokens
        print unit
        print trailing_tokens
        print "*** Ouch!"
    assert syl > 0

    meter = unit.get_meter()
    rhyme = unit.get_rhyme()
    rhymes_with = poem.get_bound_rhyme(rhyme)

    word_count = 0
    punct_count = 0
    for tok in leading_tokens:
        if tok.is_punctuation():
            punct_count += 1
        elif not tok.is_break():
            word_count += 1
    for tok in trailing_tokens:
        if tok.is_punctuation():
            punct_count += 1
        elif not tok.is_break():
            word_count += 1

    discourage_punct = False
    if word_count > 2 and word_count < 3 * punct_count:
        discourage_punct = True

    def punctution_between(token_list, i0, i1):
        for i in range(i0, i1 + 1):
            if -len(token_list) <= i < len(token_list) \
                   and token_list[i].is_punctuation():
                return True
        return False

    forbid_punct = False
    if extra_filters and \
       (punctution_between(leading_tokens, -2, -1) \
        or punctution_between(trailing_tokens, 0, 1)):
        forbid_punct = True

    have_both = False

    def single_both(s, b):
        if have_both:
            return b
        else:
            return s

    left_queries = []
    right_queries = []

    if leading_tokens and trailing_tokens:
        have_both = True

        if trailing_tokens[0].is_break():
            allow_left_queries = False
            allow_right_queries = True
            discourage_punct = False
            forbid_punct = False

        else:

            Q_filter = {
                "min_syllables": syl,
                "max_syllables": syl,
                "meter_left": meter,
            }

            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20

            Q = (leading_tokens[-1], gnoetics.token_lookup_wildcard(),
                 trailing_tokens[0], Q_filter)

            left_queries.append(Q)  # or right

    if leading_tokens and allow_left_queries:

        Q_filter = {
            "min_syllables": 0,
            "max_syllables": syl - 1,
            "meter_left": meter,
        }

        Q = (leading_tokens[-2], leading_tokens[-1],
             gnoetics.token_lookup_wildcard(), Q_filter)
        left_queries.append(Q)

        if not have_both:
            Q_filter = {
                "min_syllables": syl,
                "max_syllables": syl,
                "meter_left": meter,
            }
            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20

            Q = (leading_tokens[-2], leading_tokens[-1],
                 gnoetics.token_lookup_wildcard(), Q_filter)
            left_queries.append(Q)

    if trailing_tokens and allow_right_queries:

        Q_filter = {
            "min_syllables": 0,
            "max_syllables": syl - 1,
            "meter_right": meter,
        }

        Q = (gnoetics.token_lookup_wildcard(), trailing_tokens[0],
             trailing_tokens[1], Q_filter)
        right_queries.append(Q)

        if not have_both:
            Q_filter = {
                "min_syllables": syl,
                "max_syllables": syl,
                "meter_left": meter,
            }
            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20

            Q = (gnoetics.token_lookup_wildcard(), trailing_tokens[0],
                 trailing_tokens[1], Q_filter)
            right_queries.append(Q)

    if discourage_punct or forbid_punct:
        if discourage_punct:
            pref = 0
        else:
            pref = -1
        for Q in left_queries:
            Q[-1]["punctuation_preference"] = pref
        for Q in right_queries:
            Q[-1]["punctuation_preference"] = pref

    if left_queries:
        if verbose:
            print "Left queries:", left_queries
        ranker = gnoetics.Ranker()
        if weights is not None:
            for txt, wt in weights.items():
                ranker.set_weight(txt, wt)
        for t1, t2, t3, filter in left_queries:
            model.query(t1, t2, t3, filter, ranker)
        left_solns = ranker.get_solutions()
        if verbose:
            print "Left solns:", map(lambda x: x.get_word(), left_solns)
    else:
        left_solns = []

    if right_queries:
        if verbose:
            print "Right queries:", right_queries
        ranker = gnoetics.Ranker()
        if weights is not None:
            for txt, wt in weights.items():
                ranker.set_weight(txt, wt)
        for t1, t2, t3, filter in right_queries:
            model.query(t1, t2, t3, filter, ranker)
        right_solns = ranker.get_solutions()
        if verbose:
            print "Right solns:", map(lambda x: x.get_word(), right_solns)
    else:
        right_solns = []

    return left_solns, right_solns
Example #7
0
def solve_unit(poem, model, leading_tokens, unit, trailing_tokens,
               weights=None,
               allow_left_queries=True,
               allow_right_queries=False,
               verbose=None,
               extra_filters=True):

    # Copy list of leading and trailing tokens, so we can
    # manipulate them freely
    leading_tokens = list(leading_tokens)
    trailing_tokens = list(trailing_tokens)

    if verbose is None:
        verbose = os.getenv("GNOETRY_DEBUG") is not None

    def token_list_is_valid(token_list, allow_break_at):
        if allow_break_at < 0:
            allow_break_at += len(token_list)
        for i, tok in enumerate(token_list):
            if tok.is_wildcard():
                return False # No wildcards!
            if tok.is_break() and i != allow_break_at:
                return False # Breaks only where we say it is OK!
        return True

    lead_ok = token_list_is_valid(leading_tokens, allow_break_at=0)
    trail_ok = token_list_is_valid(trailing_tokens, allow_break_at=-1)

    if (not lead_ok) and verbose:
        print "Bad leading tokens!"
        print leading_tokens
        print

    if (not trail_ok) and verbose:
        print "Bad trailing tokens!"
        print trailing_tokens
        print

    assert lead_ok
    assert trail_ok

    # Double leading/trailing breaks
    
    if leading_tokens and leading_tokens[0].is_break():
        leading_tokens.insert(0, gnoetics.token_lookup_break())

    if trailing_tokens and trailing_tokens[-1].is_break():
        trailing_tokens.append(gnoetics.token_lookup_break())

    assert len(leading_tokens) + len(trailing_tokens) >= 2

    assert unit.is_not_bound()

    syl = unit.get_syllables()
    if syl == 0:
        print "*** Ouch!"
        print leading_tokens
        print unit
        print trailing_tokens
        print "*** Ouch!"
    assert syl > 0
    
    meter = unit.get_meter()
    rhyme = unit.get_rhyme()
    rhymes_with = poem.get_bound_rhyme(rhyme)

    word_count = 0
    punct_count = 0
    for tok in leading_tokens:
        if tok.is_punctuation():
            punct_count += 1
        elif not tok.is_break():
            word_count += 1
    for tok in trailing_tokens:
        if tok.is_punctuation():
            punct_count += 1
        elif not tok.is_break():
            word_count += 1

    discourage_punct = False
    if word_count > 2 and word_count < 3 * punct_count:
        discourage_punct = True

    def punctution_between(token_list, i0, i1):
        for i in range(i0, i1+1):
            if -len(token_list) <= i < len(token_list) \
                   and token_list[i].is_punctuation():
                return True
        return False

    forbid_punct = False
    if extra_filters and \
       (punctution_between(leading_tokens, -2, -1) \
        or punctution_between(trailing_tokens, 0, 1)):
        forbid_punct = True


    have_both = False
    def single_both(s, b):
        if have_both:
            return b
        else:
            return s
        
    left_queries = []
    right_queries = []

    if leading_tokens and trailing_tokens:
        have_both = True

        if trailing_tokens[0].is_break():
            allow_left_queries = False
            allow_right_queries = True
            discourage_punct = False
            forbid_punct = False

        else:

            Q_filter = { "min_syllables": syl,
                         "max_syllables": syl,
                         "meter_left":    meter,
                         }

            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20
                
            Q = (leading_tokens[-1],
                 gnoetics.token_lookup_wildcard(),
                 trailing_tokens[0],
                 Q_filter)

            left_queries.append(Q)  # or right


    if leading_tokens and allow_left_queries:
        
        Q_filter = { "min_syllables": 0,
                     "max_syllables": syl-1,
                     "meter_left":    meter,
                     }

        Q = (leading_tokens[-2],
             leading_tokens[-1],
             gnoetics.token_lookup_wildcard(),
             Q_filter)
        left_queries.append(Q)


        if not have_both:
            Q_filter = { "min_syllables": syl,
                         "max_syllables": syl,
                         "meter_left":    meter,
                         }
            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20
                
            Q = (leading_tokens[-2],
                 leading_tokens[-1],
                 gnoetics.token_lookup_wildcard(),
                 Q_filter)
            left_queries.append(Q)


    if trailing_tokens and allow_right_queries:

        Q_filter = { "min_syllables": 0,
                     "max_syllables": syl-1,
                     "meter_right":   meter,
                     }
        
        Q = (gnoetics.token_lookup_wildcard(),
             trailing_tokens[0],
             trailing_tokens[1],
             Q_filter)
        right_queries.append(Q)


        if not have_both:
            Q_filter = { "min_syllables": syl,
                         "max_syllables": syl,
                         "meter_left":    meter,
                         }
            if rhymes_with:
                Q_filter["rhymes_with"] = rhymes_with
            elif rhyme:
                Q_filter["has_rhyme_threshold"] = gnoetics.RHYME_FALSE
                Q_filter["rhyme_p_threshold"] = 0.20

            Q = (gnoetics.token_lookup_wildcard(),
                 trailing_tokens[0],
                 trailing_tokens[1],
                 Q_filter)
            right_queries.append(Q)




    if discourage_punct or forbid_punct:
        if discourage_punct:
            pref = 0
        else:
            pref = -1
        for Q in left_queries:
            Q[-1]["punctuation_preference"] = pref
        for Q in right_queries:
            Q[-1]["punctuation_preference"] = pref


    if left_queries:
        if verbose:
            print "Left queries:", left_queries
        ranker = gnoetics.Ranker()
        if weights is not None:
            for txt, wt in weights.items():
                ranker.set_weight(txt, wt)
        for t1, t2, t3, filter in left_queries:
            model.query(t1, t2, t3, filter, ranker)
        left_solns = ranker.get_solutions()
        if verbose:
            print "Left solns:", map(lambda x: x.get_word(), left_solns)
    else:
        left_solns = []

    if right_queries:
        if verbose:
            print "Right queries:", right_queries
        ranker = gnoetics.Ranker()
        if weights is not None:
            for txt, wt in weights.items():
                ranker.set_weight(txt, wt)
        for t1, t2, t3, filter in right_queries:
            model.query(t1, t2, t3, filter, ranker)
        right_solns = ranker.get_solutions()
        if verbose:
            print "Right solns:", map(lambda x: x.get_word(), right_solns)
    else:
        right_solns = []

    return left_solns, right_solns