1 # import numpy # numpy provides Fast Arrays, for future optimization
4 # the following will only print when in this module:
5 if __name__ == "__main__":
6 print "DMV-module tests:"
7 a = io.CNF_Rule(3,1,3,0.1)
9 print "import io works"
11 class DMV_Grammar(io.Grammar):
14 We need to be able to access rules per mother node, sum every H, every
15 H_, ..., every H', every H'_, etc. for the IO-algorithm.
17 What other representations do we need? (P_STOP formula uses
18 deps_D(h,l/r) at least)'''
22 return [r for r in self.p_rules if r.head == head and r.bars == bars]
24 def headed_rule_probs(self):
25 '''Give all rules sorted by head, for use in DMV-specific
26 probabilities (need deps_D(h, l/r) and so on also)'''
29 def __init__(self, p_rules, p_terminals):
30 io.Grammar.__init__(self, p_rules, p_terminals)
33 class DMV_Rule(io.CNF_Rule):
34 '''A single CNF rule in the PCFG, of the form
36 with the added information of bars
42 if(self.bars == 2): # todo: print prettier?
44 return b + io.CNF_Rule.__str__(self)
46 def __init__(self, head, L, R, prob, bars):
47 io.CNF_Rule.__init__(self, head, L, R, prob)
51 raise ValueError("bars must be either 0, 1 or 2; was given: %s" % bars)
54 # the following will only print when in this module:
55 if __name__ == "__main__":
56 # these are not Real rules, just testing the classes. todo: make
57 # a rule-set to test inner() on.
59 s = DMV_Rule(0,1,2, 1.0, 0) # s->np vp
60 np = DMV_Rule(1,3,4, 0.3, 0) # np->n p
61 b[1, 'n'] = 0.7 # np->'n'
62 b[3, 'n'] = 1.0 # n->'n'
63 b[4, 'p'] = 1.0 # p->'p'
64 vp = DMV_Rule(2,5,1, 0.1, 0) # vp->v np (two parses use this rule)
65 vp2 = DMV_Rule(2,2,4, 0.9, 0) # vp->vp p
66 b[5, 'v'] = 1.0 # v->'v'
68 g = DMV_Grammar([s,np,vp,vp2], b)
70 test1 = io.inner(0,0, 1, g, ['n'])
72 print "should be 0.70 : %.2f" % test1
75 test2 = io.inner(0,2, (2,0), g, ['v','n','p'])
76 print "should be 0.?? : %.2f" % test2
79 def all_inner_dmv(sent, g):
81 for bars in [0, 1, 2]:
82 for s in range(s, len(sent)): # summing over r = s to r = t-1
83 for t in range(s+1, len(sent)):
84 io.inner(s, t, (bars, h), g, sent)
91 # '''Here it seems like they store bracketing information on a per-head
92 # (per direction) basis, in deps_D(h, dir) which gives us a list. '''
93 # P_D = array indexed on h`s from sentence
95 # for a from deps_D(h, dir):
97 # P_STOP (notSTOP | h, dir, adj) * \
98 # P_CHOOSE (a | h,dir) * \
100 # P_STOP (STOP | h, dir, adj)
103 # def P_STOP(STOP | h, dir, adj):
106 # for i<loc(h): # where h is in the sentence
108 # P_STOP_num += c(h-r : i, k)
113 # P_STOP_den += c(l-h-r : i, k)
114 # return P_STOP_num / P_STOP_den
118 ##################################################################
119 # just junk from here on down: #
120 ##################################################################
122 def initialize(taglist):
123 '''If H and A are non-equal tags, we want every rule
130 to have some initial probability. It's supposed to be harmonic,
131 which we get from an M-step of the IO-algorithm; do we need a full
132 rule count? -- Where we check the distance from H to A in each case,
133 and the probability is C/distance + C' ... but then what constants
134 do we need in order to sum to 1?
136 p.4 in Carroll & Charniak gives the number of DG rules for
137 sentences of length n as n*(2^{n-1}+1).
139 "harmonic" completion where all non-ROOT words took the same
140 number of arguments, and each took other words as arguments in
141 inverse proportion to (a constant plus) the distance between
142 them. The ROOT always had a single argument and took each word
143 with equal probability. (p.5 in DMV-article)
147 Given their model, we have these types of probabilities:
149 - P_STOP(-STOP | h, dir, adj)
150 - P_STOP(STOP | h, dir, adj)
151 - P_CHOOSE(a | h, dir)
153 and then each has to sum to 1 given certain values for h, dir, adj.
154 (so P_STOP(-STOP | VBD, L, non-adj)+P_STOP( STOP | VBD, L, non-adj)=1;
155 and summing P_CHOOSE(a | VBD, L), over all a, equals 1).
158 rules = [ ] # should be a simple array where indexes correspond to
159 # heads h, so if h->_a_ h_, then h == heads[i] iff
160 # rules[i] == (_a_, h_)
164 rules['ROOT'] = ('ROOT', h)
165 rules['_' + h + '_'] = ('STOP', h + '_') # _H_ -> STOP H_
166 rules[ h + '_'] = ('h' , 'STOP' ) # H_ -> H STOP
169 rules[h] = (h , '_' + a + '_') # H -> H _A_
170 rules[h + '_'] = ('_' + a + '_', h + '_') # H_ -> _A_ H_
172 # not sure what kind of rule-access we'll need
173 # (dictionary?).. also, rules should be stored somewhere "globally
176 # put the probabilities in a single array, indexed on rule-number,
177 # (anticipating the need for quick and simple access)
178 p_rules = numpy.zeros( (len(rules)) )
180 return (p_rules, rules)
184 p = tuple([(tag, 1) for tag in tags])
185 test = numpy.zeros((len(tags)+1, len(tags)+1))
188 #if __name__ == "__main__":
189 # pprint.pprint(initialize(['vbd', 'nn', 'jj', 'dt']))
190 # print bracket(("foo", "bar", "fie","foe"))