git @ Cat's Eye Technologies NaNoGenLab / d1d36a1
Add recursive-template experiment. Chris Pressey 10 years ago
4 changed file(s) with 173 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
22 *.jp2
33 *.png
44 *.pyc
5 tmp.html
44 *.jp2
55 *.png
66 *.pyc
7 tmp.html
0 recursive-templates
1 ===================
2
3 Hypothesis
4 ----------
5
6 We hypothesize that if we try this, it might be interesting.
7
8 Apparatus
9 ---------
10
11 * Python 2.7.6 (probably works with older versions too)
12 * Some input text
13
14 Method
15 ------
16
17 * Pick one of a number of templates.
18 * Replace each of the variables in that template with another template.
19 * Repeat the last step for a specified number of times.
20 * At your option, replace all the remaining variables with words. Or not.
21
22 Observations
23 ------------
24
25 Here is `./recursive-templates.py --generations=3`:
26
27 > wonder and irritation can't understand irritation is the biscuit of sheep is the elegy can't understand territory can't understand dragon is the protector of meerkat of sausage is no tree is the fox and sausage of sheep is the horse of sausage is the horse is no irritation can't understand dog and dog can't understand cat is no territory is the bell is the elegy of meerkat of cat and fox of dog is no dragon can't understand territory is the book of wonder is no fox and irritation and wonder is no tree!
28
29 The structure is made clearer if we parenthesize each template; here is
30 `./recursive-templates.py --generations=3 --parenthesize`:
31
32 > ((((fox and elegy) can't understand (sheep and protector)) is no ((sheep and elegy) can't understand (cat and candle))) can't understand (((wonder can't understand protector) can't understand (tree and horse)) is no ((dragon can't understand dog) can't understand (microphone can't understand cat))))!
33
34 So this looks like an acceptable (sort of) alternative to a recursive descent
35 generator as used in [reluctance-generator](../reluctance-generator/). We
36 could have different "types" of variables for the different parts of speech
37 slash grammar productions, i.e. `$V1 blah $N1 blah $N2`.
38
39 When I started writing it I didn't immediately realize that special handling
40 would be needed to treat the variables as local to the template. But once I
41 realized that, I saw it was not dissimilar to how variables work in pattern
42 matching and unification and such. In this, we just textually replace each
43 variable with a "fresh" variable with a unique number.
44
45 There is a command-line option which explicitly *does not* do this, so you
46 can see what it's like treating the variables as "global" to the
47 text-in-progress at each step. Here is some output from
48 `./recursive-templates.py --generations=3 --no-variable-renaming`. As
49 you can see, it's much longer and more repetitive:
50
51 > sheep can't understand sheep can't understand meerkat and sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat can't understand sheep can't understand sheep can't understand meerkat and sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat is no sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat is the sheep can't understand sheep can't understand meerkat and sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat is no sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat of sheep can't understand sheep can't understand meerkat and sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat is the sheep can't understand sheep can't understand meerkat can't understand sheep can't understand meerkat of sheep can't understand sheep can't understand meerkat and sheep can't understand meerkat!
0 #!/usr/bin/env python
1
2 from optparse import OptionParser
3 import random
4 import re
5 import sys
6
7
8 DEBUG = False
9
10
11 TEMPLATES = [
12 "$1 is the $2 of $3",
13 "$1 and $2",
14 "$1 can't understand $2",
15 "$1 is no $2",
16 ]
17
18
19 NOUNS = [
20 'dog', 'cat', 'horse', 'biscuit', 'sausage', 'tree', 'book', 'bell',
21 'candle', 'dragon', 'meerkat', 'wonder', 'irritation', 'elegy',
22 'protector', 'microphone', 'sheep', 'wolf', 'fox', 'territory'
23 ]
24
25
26 counter = 30
27 def get_fresh_var():
28 global counter
29 v = '${0}'.format(counter)
30 counter += 1
31 return v
32
33
34 def rename_variables(text):
35 variables = []
36 n = ''
37 while text:
38 if text[0] != '$':
39 n += text[0]
40 text = text[1:]
41 else:
42 text = text[1:]
43 while text and text[0].isdigit():
44 text = text[1:]
45 v = get_fresh_var()
46 n += v
47 variables.append(v)
48 return n, variables
49
50
51 def get_variables(text):
52 v = 1
53 variables = []
54 while True:
55 variable = '${0}'.format(v)
56 if variable in text:
57 variables.append(variable)
58 v += 1
59 else:
60 break
61 return text, variables
62
63
64 def main(argv):
65 global DEBUG
66 optparser = OptionParser(__doc__)
67 optparser.add_option("--generations", default=4,
68 help="number of iterations to apply")
69 optparser.add_option("--parenthesize", action='store_true', default=False,
70 help="parenthesize templates")
71 optparser.add_option("--no-variable-renaming", action='store_true', default=False,
72 help="don't rename variables on each step")
73 optparser.add_option("--debug", action='store_true', default=False,
74 help="output debuging info")
75 (options, args) = optparser.parse_args(argv[1:])
76
77 DEBUG = options.debug
78 if options.parenthesize:
79 for i in xrange(0, len(TEMPLATES)):
80 TEMPLATES[i] = '(' + TEMPLATES[i] + ')'
81
82 text = random.choice(TEMPLATES)
83
84 acquire_variables = rename_variables
85 if options.no_variable_renaming:
86 acquire_variables = get_variables
87
88 if DEBUG:
89 print text
90 print
91
92 for i in xrange(0, int(options.generations)):
93 (text, variables) = acquire_variables(text)
94
95 if DEBUG:
96 print text, variables
97 print
98
99 for variable in variables:
100 replacement = random.choice(TEMPLATES)
101 text = text.replace(variable, replacement)
102
103 if DEBUG:
104 print text
105 print
106 print
107
108 #print text + '!'
109
110 (text, variables) = acquire_variables(text)
111 for variable in variables:
112 replacement = random.choice(NOUNS)
113 text = text.replace(variable, replacement)
114
115 print text + '!'
116
117 if __name__ == '__main__':
118 main(sys.argv)