[hltdi-l3] 2 new revisions pushed by onlysk...@gmail.com on 2014-05-09 22:45 GMT

1 view
Skip to first unread message

hltd...@googlecode.com

unread,
May 9, 2014, 6:45:22 PM5/9/14
to hltdi-...@googlegroups.com
2 new revisions:

Revision: a85b18db0ebb
Branch: default
Author: Michael Gasser <gas...@cs.indiana.edu>
Date: Wed May 7 22:10:05 2014 UTC
Log: Handling word count mismatch, source > target (< target already
handle...
http://code.google.com/p/hltdi-l3/source/detail?r=a85b18db0ebb

Revision: dc766d2c8fd8
Branch: default
Author: Michael Gasser <gas...@cs.indiana.edu>
Date: Fri May 9 22:41:32 2014 UTC
Log: Various fixes (additional constraints) on output order during
realizat...
http://code.google.com/p/hltdi-l3/source/detail?r=dc766d2c8fd8

==============================================================================
Revision: a85b18db0ebb
Branch: default
Author: Michael Gasser <gas...@cs.indiana.edu>
Date: Wed May 7 22:10:05 2014 UTC
Log: Handling word count mismatch, source > target (< target already
handled).
http://code.google.com/p/hltdi-l3/source/detail?r=a85b18db0ebb

Modified:
/hiiktuu.py
/hiiktuu/cs.py
/hiiktuu/entry.py
/hiiktuu/languages/eng.lg
/hiiktuu/languages/spa.lg
/hiiktuu/sentence.py

=======================================
--- /hiiktuu.py Tue May 6 07:23:09 2014 UTC
+++ /hiiktuu.py Wed May 7 22:10:05 2014 UTC
@@ -36,74 +36,18 @@
#import cProfile
#import pstats

-def agr_test1():
- # This should constraint seq vars seq0 and seq2 to be {2} and {3}
- sel = l3lite.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
- (2, 3, ('tam', 'tns'))})
- seq = [l3lite.Var('seq0', set(), {1, 2}, 1, 1), l3lite.DetVar('seq1',
{0}),
- l3lite.Var('seq2', set(), {3, 5}, 1, 1), l3lite.DetVar('seq3',
{4})]
- feat = [l3lite.DetLVar('f0', [l3lite.Features({'sn': 0, 'sp': 3})]),
- l3lite.DetLVar('f1', [l3lite.Features({'sn': 1})]),
- l3lite.DetLVar('f2', [l3lite.Features({'sn': 0, 'sp': 3, 'sg':
1})]),
- l3lite.DetLVar('f3', [l3lite.Features({'tam': 'ps'})]),
- l3lite.DetLVar('f4', [l3lite.Features({'tns': 'ps'})]),
- l3lite.DetLVar('f5', [l3lite.Features({'tam': 'pr'})])]
- agr = l3lite.AgrSelection(feat, sel, seq)
- return agr
-
-def agr_test2():
- # This should constrain feat var f0 to [{sn: 1, sp: 3}]
- sel = l3lite.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
- (2, 3, ('tam', 'tns'))})
- seq = [l3lite.DetVar('seq0', {2}), l3lite.DetVar('seq1', {0}),
- l3lite.Var('seq2', set(), {3, 5}, 1, 1), l3lite.DetVar('seq3',
{4})]
- feat = [l3lite.LVar('f0', [], [l3lite.Features({'sn': 0, 'sp': 3}),
- l3lite.Features({'sn': 0, 'sp': 2}),
- l3lite.Features({'sn': 1, 'sp': 3})],
- 1, 1),
- l3lite.DetLVar('f1', [l3lite.Features({'sn': 1})]),
- l3lite.DetLVar('f2', [l3lite.Features({'sn': 0, 'sp': 3, 'sg':
1})]),
- l3lite.DetLVar('f3', [l3lite.Features({'tam': 'ps'})]),
- l3lite.DetLVar('f4', [l3lite.Features({'tns': 'ps'})]),
- l3lite.DetLVar('f5', [l3lite.Features({'tam': 'pr'})])]
- agr = l3lite.AgrSelection(feat, sel, seq)
- return agr
-
-def agr_test3():
- # This should fail.
- sel = l3lite.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
- (2, 3, ('tam', 'tns'))})
- seq = [l3lite.DetVar('seq0', {2}), l3lite.DetVar('seq1', {0}),
- l3lite.Var('seq2', set(), {3, 5}, 1, 1), l3lite.DetVar('seq3',
{4})]
- feat = [l3lite.LVar('f0', [], [l3lite.Features({'sn': 0, 'sp': 3}),
- l3lite.Features({'sn': 0, 'sp': 2}),
- l3lite.Features({'sn': 1, 'sp': 3})],
- 1, 1),
- l3lite.DetLVar('f1', [l3lite.Features({'sn': 1})]),
- l3lite.DetLVar('f2', [l3lite.Features({'sn': 0, 'sp': 1, 'sg':
1})]),
- l3lite.DetLVar('f3', [l3lite.Features({'tam': 'ps'})]),
- l3lite.DetLVar('f4', [l3lite.Features({'tns': 'ps'})]),
- l3lite.DetLVar('f5', [l3lite.Features({'tam': 'pr'})])]
- agr = l3lite.AgrSelection(feat, sel, seq)
- return agr
-
-def agr_test4():
- # This should be entailed.
- sel = l3lite.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
- (2, 3, ('tam', 'tns'))})
- seq = [l3lite.DetVar('seq0', {2}), l3lite.DetVar('seq1', {0}),
- l3lite.Var('seq2', set(), {3, 5}, 1, 1), l3lite.DetVar('seq3',
{4})]
- feat = [l3lite.LVar('f0', [], [l3lite.Features({'sn': 0, 'sp': 1}),
- l3lite.Features({'sn': 0, 'sp':
1, 'sg': 1}),
- l3lite.Features({'sn': 0, 'sg': 3})],
- 1, 1),
- l3lite.DetLVar('f1', [l3lite.Features({'sn': 1})]),
- l3lite.DetLVar('f2', [l3lite.Features({'sn': 0, 'sp': 1, 'sg':
1})]),
- l3lite.DetLVar('f3', [l3lite.Features({'tam': 'ps'})]),
- l3lite.DetLVar('f4', [l3lite.Features({'tns': 'ps'})]),
- l3lite.DetLVar('f5', [l3lite.Features({'tam': 'ps', 'sn':
2})])]
- agr = l3lite.AgrSelection(feat, sel, seq)
- return agr
+def end_of_world(verbosity=0):
+ """
+ Eng->Spa
+ it's the end of the world -> es el fin del mundo
+ Illustrates
+ (1) source-target word count mismatch (source > target)
+ """
+ eng, spa = hiiktuu.Language.load('eng', 'spa')
+ s = hiiktuu.Sentence(raw="it's the end of the world", language=eng,
target=spa,
+ verbosity=verbosity)
+ s.do(verbosity=verbosity)
+ return s

def ate_fish(verbosity=0):
"""
@@ -112,8 +56,8 @@
Illustrates
(1) source-target feature agreement
"""
- amh, orm = l3lite.Language.load('amh', 'orm')
- s = l3lite.Sentence(raw="አሳ በላ", language=amh, target=orm,
verbosity=verbosity)
+ amh, orm = hiiktuu.Language.load('amh', 'orm')
+ s = hiiktuu.Sentence(raw="አሳ በላ", language=amh, target=orm,
verbosity=verbosity)
s.do(verbosity=verbosity)
return s

@@ -123,10 +67,10 @@
Either parse (trans=False) or translate -> Orm: qurxummii nyaate hin
beeku.
Illustrates
(1) source-target feature agreement
- (2) source-target group translation mismatch in word count
+ (2) source-target group translation mismatch in word count (source <
target)
"""
- amh, orm = l3lite.Language.load('amh', 'orm')
- s = l3lite.Sentence(raw="አሳ በልቶ አያውቅም", language=amh, target=orm,
+ amh, orm = hiiktuu.Language.load('amh', 'orm')
+ s = hiiktuu.Sentence(raw="አሳ በልቶ አያውቅም", language=amh, target=orm,
verbosity=verbosity)
if trans:
s.do(verbosity=verbosity)
@@ -141,8 +85,8 @@
Like the last case except since this is ungrammatical, no solution is
found that covers all of the words.
"""
- amh, orm = l3lite.Language.load('amh', 'orm')
- s = l3lite.Sentence(raw="አሳ በልተው አያውቅም", language=amh, target=orm,
+ amh, orm = hiiktuu.Language.load('amh', 'orm')
+ s = hiiktuu.Sentence(raw="አሳ በልተው አያውቅም", language=amh, target=orm,
verbosity=verbosity)
if trans:
s.do(verbosity=verbosity)
@@ -156,12 +100,12 @@
Paula les cantó las cuarenta -> Paula read them the riot act.
Illustrates
(1) source-target feature agreement
- (2) source-target group translation mismatch in word count
+ (2) source-target group translation mismatch in word count (source <
target)
(3) source-target group translation mismatch in word order
(4) source word not associated with any group
"""
- spa, eng = l3lite.Language.load('spa', 'eng')
- s = l3lite.Sentence(raw="Paula les cantó las cuarenta",
+ spa, eng = hiiktuu.Language.load('spa', 'eng')
+ s = hiiktuu.Sentence(raw="Paula les cantó las cuarenta",
language=spa, target=eng if trans else None,
verbosity=verbosity)
s.do(verbosity=verbosity)
@@ -169,319 +113,78 @@

def ui():
"""Create a UI and two languages."""
- u = l3lite.UI()
- e, s = l3lite.Language("English", 'eng'),
l3lite.Language("español", 'spa')
+ u = hiiktuu.UI()
+ e, s = hiiktuu.Language("English", 'eng'),
hiiktuu.Language("español", 'spa')
return u, e, s

-##def t1():
-## constraints = []
-## ## Groups
-## # 0: read(0) %sbd(1) the(2) riot(3) act(4)
-## # 1: read(5) %sth(6)
-## # 2: the(7) boy(8)
-## # 3: us(9)
-## # 4: the(10) act(11)
-## # 5: the(12) riot(13)
-## # 6: .(14)
-## groups = l3lite.Var('groups', set(), {0, 1, 2, 3, 4, 5, 6}, 2, 7)
-## ### Group node indices
-## ## All GNodes
-## gdetvars = [l3lite.DetVar('g0', {0, 1, 2, 3, 4}), # 1 is abstract
-## l3lite.DetVar('g1', {5, 6}), # 6 is abstract
-## l3lite.DetVar('g2', {7, 8}),
-## l3lite.DetVar('g3', {9}),
-## l3lite.DetVar('g4', {10, 11}),
-## l3lite.DetVar('g5', {12, 13}),
-## l3lite.DetVar('g6', {14})]
-## ## Concrete GNodes
-## gc_detvars = [l3lite.DetVar('g0', {0, 2, 3, 4}), # 1 is abstract
-## l3lite.DetVar('g1', {5}), # 6 is abstract
-## l3lite.DetVar('g2', {7, 8}),
-## l3lite.DetVar('g3', {9}),
-## l3lite.DetVar('g4', {10, 11}),
-## l3lite.DetVar('g5', {12, 13}),
-## l3lite.DetVar('g6', {14})]
-## ## Abstract GNodes
-## ga_detvars = [l3lite.DetVar('g0', {1}),
-## l3lite.DetVar('g1', {6}),
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY, l3lite.EMPTY]
-## ## Words (SNodes)
-## sentence = ['the', 'boy', 'read', 'us', 'the', 'riot', 'act']
-## ## Word positions associated with group nodes (what about unused
gnodes?)
-## gn0w = l3lite.DetIVar('gn0w', 2)
-## gn1w = l3lite.IVar('gn1w', {1, 3}) # abstract
-## gn2w = l3lite.IVar('gn2w', {0, 4})
-## gn3w = l3lite.DetIVar('gn3w', 5)
-## gn4w = l3lite.DetIVar('gn4w', 6)
-## gn5w = l3lite.DetIVar('gn5w', 2)
-## gn6w = l3lite.IVar('gn6w', {5, 6}) # abstract
-## gn7w = l3lite.IVar('gn7w', {0, 4})
-## gn8w = l3lite.DetIVar('gn8w', 1)
-## gn9w = l3lite.DetIVar('gn9w', 3)
-## gn10w = l3lite.IVar('gn10w', {0, 4})
-## gn11w = l3lite.DetIVar('gn11w', 6)
-## gn12w = l3lite.IVar('gn12w', {0, 4})
-## gn13w = l3lite.DetIVar('gn13w', 5)
-## gn14w = l3lite.DetIVar('gn14w', 7)
-## gn_w = [gn0w, gn1w, gn2w, gn3w, gn4w, gn5w, gn6w, gn7w, gn8w, gn9w,
gn10w, gn11w, gn12w, gn13w, gn14w]
-## ## Groups associated with group nodes
-## gn_g = [l3lite.DetIVar('gn0_g', 0),
-## l3lite.DetIVar('gn1_g', 0),
-## l3lite.DetIVar('gn2_g', 0),
-## l3lite.DetIVar('gn3_g', 0),
-## l3lite.DetIVar('gn4_g', 0),
-## l3lite.DetIVar('gn5_g', 1), l3lite.DetIVar('gn6_g', 1),
-## l3lite.DetIVar('gn7_g', 2), l3lite.DetIVar('gn8_g', 2),
-## l3lite.DetIVar('gn9_g', 3),
-## l3lite.DetIVar('gn10_g', 4), l3lite.DetIVar('gn11_g', 4),
-## l3lite.DetIVar('gn12_g', 5), l3lite.DetIVar('gn13_g', 5),
-## l3lite.DetIVar('gn14_g', 6)]
-## ## Group nodes associated with words
-## w0gn = l3lite.IVar('w0gn', {2, 7, 10, 12}) # the
-## w1gn = l3lite.Var('w1gn', set(), {1, 8}, 1, 2) # boy
-## w2gn = l3lite.IVar('w2gn', {0, 5}) # read
-## w3gn = l3lite.Var('w3gn', set(), {1, 9}, 1, 2) # us
-## w4gn = l3lite.IVar('w4gn', {2, 7, 10, 12}) # the
-## w5gn = l3lite.Var('w5gn', set(), {3, 6, 13}, 1, 2) # riot
-## w6gn = l3lite.Var('w6gn', set(), {4, 6, 11}, 1, 2) # act
-## w7gn = l3lite.DetIVar('w7gn', 14)
-## w2gnodes = [w0gn, w1gn, w2gn, w3gn, w4gn, w5gn, w6gn, w7gn]
-## # Union selection on gnodes for each snode
-## constraints.append(l3lite.UnionSelection(l3lite.DetVar('one', {1}),
w1gn, gn_w))
-## constraints.append(l3lite.UnionSelection(l3lite.DetVar('three',
{3}), w3gn, gn_w))
-## ### Word (SNode) ->
-## ## Concrete group nodes associated with words
-## w0cgn = w0gn
-## w1cgn = l3lite.DetIVar('w1cgn', 8)
-## w2cgn = w2gn
-## w3cgn = l3lite.DetIVar('w3cgn', 9)
-## w4cgn = w4gn
-## w5cgn = l3lite.IVar('w5cgn', {3, 13})
-## w6cgn = l3lite.IVar('w6cgn', {4, 11})
-## w7cgn = w7gn
-## w2cgnodes = [w0cgn, w1cgn, w2cgn, w3cgn, w4cgn, w5cgn, w6cgn, w7cgn]
-## ## w->m Merged concrete group nodes associated with words
-## w1gnm = l3lite.Var('w1gnm', set(), {8}, 0, 1) # boy (merged
with sbd)
-## w3gnm = l3lite.Var('w3gnm', set(), {9}, 0, 1) # us (merged
with sbd)
-## w5gnm = l3lite.Var('w5gnm', set(), {13}, 0, 1) # riot (merged
with sth)
-## w6gnm = l3lite.Var('w6gnm', set(), {11}, 0, 1) # act (merged
with sth)
-## w2gnm_nodes = [l3lite.EMPTY, w1gnm, l3lite.EMPTY, w3gnm,
l3lite.EMPTY, w5gnm, w6gnm, l3lite.EMPTY]
-## ## w->a Abstract group nodes associated with words
-## w1ga = l3lite.Var('w1ga', set(), {1}, 0, 1)
-## w3ga = l3lite.Var('w3ga', set(), {1}, 0, 1)
-## w5ga = l3lite.Var('w5ga', set(), {6}, 0, 1)
-## w6ga = l3lite.Var('w6ga', set(), {6}, 0, 1)
-## w2ga_nodes = [l3lite.EMPTY, w1ga, l3lite.EMPTY, w3ga, l3lite.EMPTY,
w5ga, w6ga, l3lite.EMPTY]
-## ## All word nodes
-## nodes = l3lite.DetVar('nodes', {0, 1, 2, 3, 4, 5, 6, 7})
-## ## Union selection on the gnodes of all words
-## # Words 1 (boy), 3 (us), 5 (riot), 6 (act) can have abstract nodes
-## constraints.extend(l3lite.Union([w1gn, w1cgn, w1ga]).constraints)
-## constraints.extend(l3lite.Union([w3gn, w3cgn, w3ga]).constraints)
-## constraints.extend(l3lite.Union([w5gn, w5cgn, w5ga]).constraints)
-## constraints.extend(l3lite.Union([w6gn, w6cgn, w6ga]).constraints)
-## # Union of all group nodes used
-## gnodeU = l3lite.Var('gnodeU', set(),
-## {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14}, 7, 9)
-## constraints.append(l3lite.UnionSelection(gnodeU, nodes, w2gnodes))
-## ## Union selection on the gnodes of all groups
-## constraints.append(l3lite.UnionSelection(gnodeU, groups, gdetvars))
-## ## Union selection on the words associated with each group node
-## constraints.append(l3lite.UnionSelection(nodes, gnodeU, gn_w))
-## # Positions of gnodes in each group
-## g0snode = l3lite.Var('g0snode', set(), {0, 1, 2, 3, 4, 5, 6}, 5, 5)
# read sbd the riot act
-## g1snode = l3lite.Var('g1snode', set(), {2, 5, 6}, 2, 2)
# read sth
-## g2snode = l3lite.Var('g2snode', set(), {0, 1, 4}, 2, 2)
# the boy
-## g3snode = l3lite.DetIVar('g3snode', 3)
# us
-## g4snode = l3lite.Var('g4snode', set(), {0, 4, 6}, 2, 2)
# the act
-## g5snode = l3lite.Var('g5snode', set(), {0, 4, 5}, 2, 2)
# the riot
-## g6snode = l3lite.DetIVar('g6snode', 7)
# .
-## gsnodes = [g0snode, g1snode, g2snode, g3snode, g4snode, g5snode,
g6snode]
-## # Positions of concrete gnodes in each group
-## g0cw = l3lite.Var('g0cw', set(), {0, 1, 2, 3, 4, 5, 6}, 4, 4)
-## g1cw = l3lite.DetVar('g1cw', {2})
-## g2cw = g2snode
-## g3cw = g3snode
-## g4cw = g4snode
-## g5cw = g5snode
-## g6cw = g6snode
-## g_cwords = [g0cw, g1cw, g2cw, g3cw, g4cw, g5cw, g6cw]
-## # Positions of abstract gnodes in each group
-## g0aw = l3lite.IVar('g0aw', {0, 1, 2, 3, 4, 5, 6})
-## g1aw = l3lite.IVar('g1aw', {0, 1, 2, 3, 4, 5, 6})
-## g_awords = [g0aw, g1aw,
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY]
-## # Union constraints for group abstract and concrete gnodes
-## constraints.extend(l3lite.Union([g0snode, g0cw, g0aw]).constraints)
-## constraints.extend(l3lite.Union([g1snode, g1cw, g1aw]).constraints)
-## ## Groups merged with groups
-## g0m = l3lite.Var('g0m', set(), {2, 3}, 0, 1)
-## g1m = l3lite.Var('g1m', set(), {4, 5}, 0, 1)
-## ## Groups merged with groups, including the group itself
-## g0gm = l3lite.Var('g0gm', {0}, {0, 2, 3}, 1, 2)
-## g1gm = l3lite.Var('g1gm', {1}, {1, 4, 5}, 1, 2)
-## g2gm = l3lite.DetVar('g2gm', {2})
-## g3gm = l3lite.DetVar('g3gm', {3})
-## g4gm = l3lite.DetVar('g4gm', {4})
-## g5gm = l3lite.DetVar('g5gm', {5})
-## g6gm = l3lite.DetVar('g6gm', {6})
-## # Relation between g->m only and g->m + self
-## constraints.extend(l3lite.Union([g0gm, g0m, l3lite.DetIVar('zero',
0)]).constraints)
-## constraints.extend(l3lite.Union([g1gm, g1m, l3lite.DetIVar('one',
1)]).constraints)
-## ## Abstract group node mergers (empty set possible if not selected)
-## # a->m
-## # Merge %sbd with boy or us
-## gan1m = l3lite.Var('gan1m', set(), {8, 9}, 0, 1)
-## # Merge %sth with riot or act
-## gan6m = l3lite.Var('gan6m', set(), {11, 13}, 0, 1)
-## gan_m = [l3lite.EMPTY, gan1m, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY,
-## l3lite.EMPTY, gan6m, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY,
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY]
-## # Merged gnodes must be among selected gnodes
-## constraints.extend(l3lite.Inclusion([gan1m, gnodeU]).constraints)
-## constraints.extend(l3lite.Inclusion([gan6m, gnodeU]).constraints)
-## # Relate merged gnodes to merged groups; selection variables should
-## # be the union of a->m variables for each group that has any
-## # Group 0, abstract gnode 1
-## constraints.append(l3lite.UnionSelection(g0m, gan1m, gn_g))
-## # Group 1, abstract gnode 6
-## constraints.append(l3lite.UnionSelection(g1m, gan6m, gn_g))
-## ## m-> a; Abstract nodes associated with concrete gnodes
-## gm8ga = l3lite.Var('gm8ga', set(), {1}, 0, 1)
-## gm9ga = l3lite.Var('gm9ga', set(), {1}, 0, 1)
-## gm11ga = l3lite.Var('gm11ga', set(), {6}, 0, 1)
-## gm13ga = l3lite.Var('gm13ga', set(), {6}, 0, 1)
-## gm_ga = [l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY,
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY, gm8ga, gm9ga,
l3lite.EMPTY,
-## gm11ga, l3lite.EMPTY, gm13ga,l3lite.EMPTY]
-## ## a->w Words associated with abstract group nodes
-## ga1w = l3lite.Var('ga1w', set(), {1, 3}, 0, 1)
-## ga6w = l3lite.Var('ga6w', set(), {5, 6}, 0, 1)
-## ga_w = [l3lite.EMPTY, ga1w, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY, l3lite.EMPTY,
-## ga6w, l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY, l3lite.EMPTY,
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY]
-## ## m->w Words associated with merged group nodes
-## gnm8w = l3lite.Var('gnm8w', set(), {1}, 0, 1)
-## gnm9w = l3lite.Var('gnm9w', set(), {3}, 0, 1)
-## gnm11w = l3lite.Var('gnm11w', set(), {6}, 0, 1)
-## gnm13w = l3lite.Var('gnm13w', set(), {5}, 0, 1)
-## gnm_w = [l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
l3lite.EMPTY,
-## l3lite.EMPTY, l3lite.EMPTY, l3lite.EMPTY,
-## gnm8w, gnm9w, l3lite.EMPTY, gnm11w, l3lite.EMPTY,
-## gnm13w, l3lite.EMPTY]
-## # Merging means the gnodes have the same sentence position
-## # gn1w = gn8w | gn9w ; gn6w = gn11w | gn13w
-## # Abstract nodes in used groups
-## anodes = l3lite.Var('anodes', set(), {1, 6})
-## constraints.append(l3lite.UnionSelection(anodes, groups,
[l3lite.DetVar('g0a', {1}),
-##
l3lite.DetVar('g1a', {6}),
-##
l3lite.EMPTY, l3lite.EMPTY,
-##
l3lite.EMPTY, l3lite.EMPTY,
-##
l3lite.EMPTY]))
-## # Word nodes that involve a merging of two gnodes
-## mwords = l3lite.Var('mwords', set(), {1, 3, 5, 6}, 0, 2)
-## # Set of all concrete gnodes that are merged with abstract nodes
-## merged_gnodes = l3lite.Var('merged_gnodes', set(), {0, 2, 3, 4, 5,
7, 8, 9, 10, 11, 12, 13, 14},
-## 0, 2)
-## ## UnionSelection constraints relating words, abstract nodes, and
merged gnodes
-## # Set of merged nodes is the union of the merged nodes for the set
of selected abstract nodes
-## constraints.append(l3lite.UnionSelection(merged_gnodes, anodes,
gan_m))
-## # Set of merged nodes is the union of the merged nodes of all merge
words
-## constraints.append(l3lite.UnionSelection(merged_gnodes, mwords,
w2gnm_nodes))
-## # Set of abstract nodes is the union of the abstract nodes of all
merge words
-## constraints.append(l3lite.UnionSelection(anodes, mwords, w2ga_nodes))
-## # Set of abstract nodes is the union of the abstract nodes of all
gnodes
-## constraints.append(l3lite.UnionSelection(anodes, merged_gnodes,
gm_ga))
-## # Set of merge words is the union of the words associated with all
selected abstract nodes
-## constraints.append(l3lite.UnionSelection(mwords, anodes, ga_w))
-## # Set of merge words is the union of the words associated with all
merge group nodes
-## constraints.append(l3lite.UnionSelection(mwords, merged_gnodes,
gnm_w))
-## ## Constraints on merged and abstract nodes
-## # Set of merged nodes must be a subset of all used gnodes
-## constraints.append(l3lite.Inclusion([merged_gnodes,
gnodeU]).constraints[0])
-## # All words must have different abstract nodes
-## constraints.extend(l3lite.Disjoint(w2ga_nodes).constraints)
-## # All concrete nodes must nodes have different abstract nodes
-## constraints.extend(l3lite.Disjoint(gm_ga).constraints)
-## ## Trees under gnode heads
-## g0tree = l3lite.Var('g0tree', set(), {0, 1, 2, 3, 4, 5, 6}, 5) #
at least 5 snodes
-## g1tree = l3lite.Var('g1tree', set(), {0, 1, 2, 3, 4, 5, 6}, 2) #
at least 2 snodes
-## g2tree = g2snode
-## g3tree = g3snode
-## g4tree = g4snode
-## g5tree = g5snode
-## g6tree = g6snode
-## gtrees = [g0tree, g1tree, g2snode, g3snode, g4snode, g5snode,
g6snode]
-## # g1 tree is the union of g0snode and the tree under whatever group
-## # merges with gnode 1 (sbd)
-## constraints.append(l3lite.UnionSelection(g0tree, g0gm, gsnodes))
-## constraints.append(l3lite.UnionSelection(g1tree, g1gm, gsnodes))
-## # Relate gnode merger with group merger
-## # If gnode 1 merges with gnode 8, then group 0 merges with group 2;
-## # if gnode 1 merges with gnode 9, then group 0 merges with group 3
-## # Select one or the other
-## # UnionSelection(choice, IVar('chooser', {0, 1}), [choice1, choice2])
-#### g0merge_sel = l3lite.IVar('g0m_sel', {0, 1, 2})
-#### constraints.append(l3lite.UnionSelection(g0gm, g0merge_sel,
[l3lite.DetVar('g0g2', {0, 2}),
-####
l3lite.DetVar('g0g3', {0, 3}),
-####
l3lite.DetVar('g0_', {0})]))
-#### constraints.append(l3lite.UnionSelection(gan1m, g0merge_sel,
-#### [l3lite.DetVar('gan1g8',
{8}),
-#### l3lite.DetVar('gan1g9',
{9}),
-#### l3lite.EMPTY]))
-#### g1merge_sel = l3lite.IVar('g1m_sel', {0, 1, 2})
-#### constraints.append(l3lite.UnionSelection(g1gm, g1merge_sel,
[l3lite.DetVar('g1g4', {1, 4}),
-####
l3lite.DetVar('g1g5', {1, 5}),
-####
l3lite.DetVar('g1_', {1})]))
-#### constraints.append(l3lite.UnionSelection(gan6m, g1merge_sel,
-#### [l3lite.DetVar('gan6g11',
{11}),
-#### l3lite.DetVar('gan6g13',
{13}),
-#### l3lite.EMPTY]))
-## ### Order
-## # Position pair constraints
-## gposcons = l3lite.Var('gposcons', set(),
-## {(0, 1), (1, 2), (2, 3), (3, 4), (0, 2), (1,
3), (2, 4), (0, 3), (1, 4),
-## (5, 6), (7, 8), (10, 11), (12, 13)})
-## # Union selection on position pair constraints
-## gp0 = l3lite.DetVar('gp0', {(0, 1), (1, 2), (2, 3), (3, 4), (0, 2),
(1, 3), (2, 4), (0, 3), (1, 4)})
-## gp1 = l3lite.DetVar('gp1', {(5, 6)})
-## gp2 = l3lite.DetVar('gp2', {(7, 8)})
-## gp3 = l3lite.DetVar('gp3', set())
-## gp4 = l3lite.DetVar('gp4', {(10, 11)})
-## gp5 = l3lite.DetVar('gp5', {(12, 13)})
-## gp6 = l3lite.DetVar('gp6', set())
-## gpos = [gp0, gp1, gp2, gp3, gp4, gp5, gp6]
-## constraints.append(l3lite.PrecedenceSelection(gposcons,
-## [gn0w, gn1w, gn2w,
gn3w, gn4w, gn5w,
-## gn6w, gn7w, gn8w,
gn9w, gn10w, gn11w, gn12w, gn13w, gn14w]))
-## # Union selection on position pair constraints
-## constraints.append(l3lite.UnionSelection(gposcons, groups, gpos))
-## # Complex union selection on positions of all concrete nodes in each
selected group
-## constraints.append(l3lite.ComplexUnionSelection(selvar=groups,
-## selvars=g_cwords,
-## seqvars=w2cgnodes,
-## mainvars=gc_detvars))
-## # Complex union selection on positions of all abstract gnodes in
each selected group
-## constraints.append(l3lite.ComplexUnionSelection(selvar=groups,
-## selvars=g_awords,
-## seqvars=w2ga_nodes,
-## mainvars=ga_detvars))
-## ### Projectivity
-## # Complex set convexity
-## constraints.append(l3lite.ComplexSetConvexity(groups, gtrees))
-## return constraints
+##def agr_test1():
+## # This should constraint seq vars seq0 and seq2 to be {2} and {3}
+## sel = hiiktuu.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
+## (2, 3, ('tam', 'tns'))})
+## seq = [hiiktuu.Var('seq0', set(), {1, 2}, 1, 1),
hiiktuu.DetVar('seq1', {0}),
+## hiiktuu.Var('seq2', set(), {3, 5}, 1, 1),
hiiktuu.DetVar('seq3', {4})]
+## feat = [hiiktuu.DetLVar('f0', [hiiktuu.Features({'sn': 0, 'sp':
3})]),
+## hiiktuu.DetLVar('f1', [hiiktuu.Features({'sn': 1})]),
+## hiiktuu.DetLVar('f2', [hiiktuu.Features({'sn': 0, 'sp':
3, 'sg': 1})]),
+## hiiktuu.DetLVar('f3', [hiiktuu.Features({'tam': 'ps'})]),
+## hiiktuu.DetLVar('f4', [hiiktuu.Features({'tns': 'ps'})]),
+## hiiktuu.DetLVar('f5', [hiiktuu.Features({'tam': 'pr'})])]
+## agr = hiiktuu.AgrSelection(feat, sel, seq)
+## return agr
##
-##def run_constraints(constraints, times=10):
-## for t in range(times):
-## print("\nITERATION {}".format(t))
-## for c in constraints:
-## state, changed = c.run()
-## if state == 0:
-## print('FAILED: constraint {}'.format(c))
-## return
-## if changed:
-## print("Running {}".format(c))
-## print(" Changed:
{}".format(list(changed)[0].pretty_string()))
+##def agr_test2():
+## # This should constrain feat var f0 to [{sn: 1, sp: 3}]
+## sel = hiiktuu.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
+## (2, 3, ('tam', 'tns'))})
+## seq = [hiiktuu.DetVar('seq0', {2}), hiiktuu.DetVar('seq1', {0}),
+## hiiktuu.Var('seq2', set(), {3, 5}, 1, 1),
hiiktuu.DetVar('seq3', {4})]
+## feat = [hiiktuu.LVar('f0', [], [hiiktuu.Features({'sn': 0, 'sp': 3}),
+## hiiktuu.Features({'sn': 0, 'sp': 2}),
+## hiiktuu.Features({'sn': 1, 'sp': 3})],
+## 1, 1),
+## hiiktuu.DetLVar('f1', [hiiktuu.Features({'sn': 1})]),
+## hiiktuu.DetLVar('f2', [hiiktuu.Features({'sn': 0, 'sp':
3, 'sg': 1})]),
+## hiiktuu.DetLVar('f3', [hiiktuu.Features({'tam': 'ps'})]),
+## hiiktuu.DetLVar('f4', [hiiktuu.Features({'tns': 'ps'})]),
+## hiiktuu.DetLVar('f5', [hiiktuu.Features({'tam': 'pr'})])]
+## agr = hiiktuu.AgrSelection(feat, sel, seq)
+## return agr
+##
+##def agr_test3():
+## # This should fail.
+## sel = hiiktuu.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
+## (2, 3, ('tam', 'tns'))})
+## seq = [hiiktuu.DetVar('seq0', {2}), hiiktuu.DetVar('seq1', {0}),
+## hiiktuu.Var('seq2', set(), {3, 5}, 1, 1),
hiiktuu.DetVar('seq3', {4})]
+## feat = [hiiktuu.LVar('f0', [], [hiiktuu.Features({'sn': 0, 'sp': 3}),
+## hiiktuu.Features({'sn': 0, 'sp': 2}),
+## hiiktuu.Features({'sn': 1, 'sp': 3})],
+## 1, 1),
+## hiiktuu.DetLVar('f1', [hiiktuu.Features({'sn': 1})]),
+## hiiktuu.DetLVar('f2', [hiiktuu.Features({'sn': 0, 'sp':
1, 'sg': 1})]),
+## hiiktuu.DetLVar('f3', [hiiktuu.Features({'tam': 'ps'})]),
+## hiiktuu.DetLVar('f4', [hiiktuu.Features({'tns': 'ps'})]),
+## hiiktuu.DetLVar('f5', [hiiktuu.Features({'tam': 'pr'})])]
+## agr = hiiktuu.AgrSelection(feat, sel, seq)
+## return agr
+##
+##def agr_test4():
+## # This should be entailed.
+## sel = hiiktuu.DetVar('sel', {(0, 1, ('sn', 'sn'), ('sp', 'sp')),
+## (2, 3, ('tam', 'tns'))})
+## seq = [hiiktuu.DetVar('seq0', {2}), hiiktuu.DetVar('seq1', {0}),
+## hiiktuu.Var('seq2', set(), {3, 5}, 1, 1),
hiiktuu.DetVar('seq3', {4})]
+## feat = [hiiktuu.LVar('f0', [], [hiiktuu.Features({'sn': 0, 'sp': 1}),
+## hiiktuu.Features({'sn': 0, 'sp':
1, 'sg': 1}),
+## hiiktuu.Features({'sn': 0, 'sg': 3})],
+## 1, 1),
+## hiiktuu.DetLVar('f1', [hiiktuu.Features({'sn': 1})]),
+## hiiktuu.DetLVar('f2', [hiiktuu.Features({'sn': 0, 'sp':
1, 'sg': 1})]),
+## hiiktuu.DetLVar('f3', [hiiktuu.Features({'tam': 'ps'})]),
+## hiiktuu.DetLVar('f4', [hiiktuu.Features({'tns': 'ps'})]),
+## hiiktuu.DetLVar('f5', [hiiktuu.Features({'tam': 'ps', 'sn':
2})])]
+## agr = hiiktuu.AgrSelection(feat, sel, seq)
+## return agr

if __name__ == "__main__":
print('HIIKTUU, version {}\n'.format(__version__))
=======================================
--- /hiiktuu/cs.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/cs.py Wed May 7 22:10:05 2014 UTC
@@ -31,7 +31,7 @@
from .constraint import *

class Solver:
- """A solver for a constraint satisfaction problem."""
+ """A solver for a constraint satisfaction problem, actually a state in
the search space."""

id = 0

@@ -162,3 +162,97 @@
print('# changed vars {}'.format(len(all_changed)))
return awaken

+ def select_variable(self, vars, verbosity=0):
+ """One possibility for selecting variables to branch on:
+ prefer larger upper domains."""
+ vars = self.dstore
+ return sorted(vars, key=lambda v:
len(v.get_upper(dstore=self.dstore)))[0]
+
+ def split_var_values(self, variable, verbosity=0):
+ """For a selected variable, select a value by calling the value
selection function,
+ and return two sets of values: the selected value and the other
values. Assumes
+ variable is a set or int variable."""
+ undecided = variable.get_undecided(dstore=dstore)
+ # Split undecided into two non-empty subsets
+ if not undecided:
+ print("SOMETHING WRONG; {} HAS NO UNDECIDED
VALUES".format(variable))
+ elem = Solver.ran_select(undecided)
+ return {elem}, undecided - {elem}
+
+ ## Two variable value selection functions.
+
+ @staticmethod
+ def ran_select(values):
+ return random.choice(values)
+
+ @staticmethod
+ def smallest_select(values):
+ """Select smallest value."""
+ value_list = list(values)
+ value_list.sort()
+ return value_list[0]
+
+ def select_constraints(self, variable, verbosity=0):
+ """Return a pair of constraints for the selected variable."""
+ subset1, subset2 = self.split_var_values(variable,
verbosity=verbosity)
+ if isinstance(variable, IVar):
+ if verbosity:
+ print(' values: {}, {}'.format(subset1, subset2))
+ return Member(variable, subset1, problem=self.problem), \
+ Member(variable, subset2, problem=self.problem)
+ else:
+ # For an set Var, add subset1 to the lower bound, subtract
subset1
+ # from the upper bound
+ v1 = variable.get_lower(dstore=dstore) | subset1
+ v2 = variable.get_upper(dstore=dstore) - subset1
+ if verbosity:
+ print(' values: {}, {}'.format(subset1, subset2))
+ return Superset(variable, v1, problem=self.problem), \
+ Subset(variable, v2, problem=self.problem)
+
+ def distribute(self, distributor, project=False, verbosity=0):
+ """Creates and returns two new solver objects by cloning the
dstore with the distributor."""
+ if self.status != Solver.distributable:
+ return []
+ undet = self.dstore.ess_undet
+ if verbosity:
+ ndet = len(undet)
+ print('DISTRIBUTION')
+ print('Distributing, undetermined vars {}'.format(ndet))
+ for v in list(undet)[:5]:
+ v.pprint(dstore=self.dstore)
+ if ndet > 5:
+ print('...')
+ # Select a variable and two disjoint basic constraints on it
+ var = select_variable(undet, verbosity=verbosity)
+ constraint1, constraint2 = self.select_constraints(var,
verbosity=verbosity)
+ if verbosity:
+ print('Distribution constraints: a -- {}, b --
{}'.format(constraint1, constraint2))
+ # The constraints of the selected variable (make copies)
+ constraints = var.constraints[:]
+ # Create the new solvers (states), applying one of the constraints
to each
+ new_dstore1 = self.dstore.clone(constraint1, name=self.name+'a',
project=project)
+ new_dstore2 = self.dstore.clone(constraint2, name=self.name+'b',
project=project)
+ # Create a new CSpace for each dstore, preserving the accumulated
penalty
+ cspace1 = CSpace(name=self.name+'a', depth=self.depth+1,
+ variables=self.variables,
+ propagators=propagators,
+ penalty=self.penalty,
+ parent=self,
+ dstore=new_dstore1,
+ failed_props=self.failed_props[:],
+ entailed=self.entailed[:],
+ verbosity=verbosity)
+ cspace2 = CSpace(name=self.name+'b', depth=self.depth+1,
+ variables=self.variables,
+ propagators=propagators,
+## projectors=newproj2,
+## dead_projectors=self.dead_projectors.copy(),
+ penalty=self.penalty,
+ parent=self,
+ dstore=new_dstore2,
+ failed_props=self.failed_props[:],
+ entailed=self.entailed[:],
+ verbosity=verbosity)
+ self.children.extend([cspace1, cspace2])
+ return [((var, constraint2), cspace2), ((var, constraint1),
cspace1)]
=======================================
--- /hiiktuu/entry.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/entry.py Wed May 7 22:10:05 2014 UTC
@@ -49,6 +49,10 @@
# -- Eliminated everything but Groups.
# 2014.05.01
# -- Group/node matching fixed.
+# 2014.05.06
+# -- Group entry indices need to distinguish ambiguous words/lexemes.
+# Indices can be things like "end_n", with POS or other identifiers
after "_".
+# "end_n" and "end_v" would be different roots of "end" in the forms
dict.

import copy, itertools
import yaml
@@ -655,8 +659,9 @@
Entry.__init__(self, name, language, trans=trans)
self.tokens = tokens
if head:
+ head_token = head.partition('_')[0]
self.head = head
- self.head_index = tokens.index(head)
+ self.head_index = tokens.index(head_token)
else:
self.head = tokens[head_index]
self.head_index = head_index
=======================================
--- /hiiktuu/languages/eng.lg Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/languages/eng.lg Wed May 7 22:10:05 2014 UTC
@@ -1,14 +1,16 @@
name: English
abbrev: eng
forms:
- "it's":
- seg:
- - [it, {root: it, features: {num: 0, per: 3, gen: 2}, cats: [$pron]}]
- - [is, {root: be, features: {tns: prs, per: 3, num: 0}, cats: [$aux,
$cop]}]
+# "it's":
+# seg:
+# - [it, {root: it, features: {num: 0, per: 3, gen: 2}, cats:
[$pron]}]
+# - [is, {root: be, features: {tns: prs, per: 3, num: 0}, cats:
[$aux, $cop]}]
end:
- root: end
+ - root: end_n
features: {num: 0, prs: 3}
cats: [$abs]
+ - root: end_v
+ features: {tns: prs, per: 3, num: 1}
boy:
root: boy
features: {num: 0, prs: 3}
@@ -36,8 +38,17 @@
features: {tns: prt}

groups:
- end:
+ "it's":
+ - words: ["it's"]
+ trans:
+ spa:
+ - [es, align: [0]]
+ end_n:
- words: [the, end, of, the, world]
+ trans:
+ spa:
+ - [el_fin_del_mundo,
+ align: [0, 1, 2, -1, 3]]
read:
- words: [read, $sbd, the, riot, act]
- words: [read, $sth]
=======================================
--- /hiiktuu/languages/spa.lg Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/languages/spa.lg Wed May 7 22:10:05 2014 UTC
@@ -2,6 +2,10 @@
abbrev: spa

groups:
+ es:
+ - words: [es]
+ fin:
+ - words: [el, fin, del, mundo]
cantar:
# cantar las cuarenta (with pronoun indirect object)
- words: [$algnp, cantar, las, cuarenta]
=======================================
--- /hiiktuu/sentence.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/sentence.py Wed May 7 22:10:05 2014 UTC
@@ -742,6 +742,7 @@
# print("Translations for {}: {}".format(self, translations))
ntokens = len(self.group.tokens)
for tgroup, alignment in translations:
+# print("TGroup {}', alignment {}".format(tgroup, alignment))
if isinstance(tgroup, str):
# First find the target Group object
tgroup = self.target.groupnames[tgroup]
@@ -764,6 +765,7 @@
tokens = tgroup.tokens
features = tgroup.features
targ_index = alignment['align'][gn_index]
+# print("Alignment: {}".format(alignment['align']))
if targ_index < 0:
# This means there's no target language token
continue
@@ -993,6 +995,7 @@
print('Building {}'.format(self))
tginsts, tgnodes, trans_index = self.groups_tnodes,
self.gnode_dict, self.index
# Figure out the target forms for each snode
+ print('tgnodes {}'.format(tgnodes))
for snode, (gnodes, features) in zip(self.sentence.nodes,
self.solution.snodes):
if not gnodes:
# snode is not covered by any group
@@ -1022,9 +1025,13 @@
# print('tgroups {}, token {}, t_indices
{}'.format(tgroups, token, t_indices))
else:
gnode = gnodes[0]
- tgroup, token, targ_feats, agrs, t_index =
tgnodes[gnode]
- if len(tgroup.tokens) > 1:
- t_indices.append((tgroup, t_index))
+ if gnode not in tgnodes:
+ continue
+ else:
+ gnode = gnodes[0]
+ tgroup, token, targ_feats, agrs, t_index =
tgnodes[gnode]
+ if len(tgroup.tokens) > 1:
+ t_indices.append((tgroup, t_index))
# print('tgroup {}, token {}, t_index
{}'.format(tgroup, token, t_indices))

# Make target and source features agree as required

==============================================================================
Revision: dc766d2c8fd8
Branch: default
Author: Michael Gasser <gas...@cs.indiana.edu>
Date: Fri May 9 22:41:32 2014 UTC
Log: Various fixes (additional constraints) on output order during
realization.
http://code.google.com/p/hltdi-l3/source/detail?r=dc766d2c8fd8

Modified:
/hiiktuu.py
/hiiktuu/constraint.py
/hiiktuu/cs.py
/hiiktuu/entry.py
/hiiktuu/languages/eng.lg
/hiiktuu/languages/spa.lg
/hiiktuu/sentence.py
/l3xdg/solver.py

=======================================
--- /hiiktuu.py Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu.py Fri May 9 22:41:32 2014 UTC
@@ -36,6 +36,20 @@
#import cProfile
#import pstats

+def kick_the_bucket(verbosity=0):
+ """
+ Eng->Spa
+ """
+ eng, spa = hiiktuu.Language.load('eng', 'spa')
+ s = hiiktuu.Sentence(raw='John kicked the bucket', language=eng,
target=spa,
+ verbosity=verbosity)
+# s.do(verbosity=verbosity)
+ s.initialize()
+ s.solve()
+ sol = s.solutions[0]
+ sol.translate()
+ return sol
+
def end_of_world(verbosity=0):
"""
Eng->Spa
=======================================
--- /hiiktuu/constraint.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/constraint.py Fri May 9 22:41:32 2014 UTC
@@ -47,6 +47,10 @@
# 2014.05.05
# -- ComplexAgrSelection constraint.
# Generalization of three complex constraints to ComplexConstraint
class.
+# 2014.05.08
+# -- Added Order constraint for ordering indices of sequences, replacing
multiple
+# SetPrecedence constraints, and including one additional condition not
in
+# SetPrecedence.

from .variable import *
# This is imported in another branch too...
@@ -513,6 +517,7 @@
if not set(range(min_lower, max_lower+1)) - lower:
if min_lower - min(upper) <= 1 and max(upper) - max_lower <= 1:
return True
+
return False

def infer(self, dstore=None, verbosity=0, tracevar=[]):
@@ -926,6 +931,67 @@
## print(' Variables {} changed'.format(changed))
## return Constraint.sleeping, changed

+class Order(Constraint):
+ """N int variables, whose values are positions from 0 to n-1."""
+
+ def __init__(self, variables, problem=None, weight=1, record=True):
+ Constraint.__init__(self, variables, problem=problem,
+ weight=weight, record=record)
+ self.max_value = len(variables) - 1
+ self.name = '{0} <...<'.format(self.variables)
+
+ def fails(self, dstore=None):
+ """Fail if any determined variable has a value greater than
maximum (n-1)
+ or if two determined variables have the same value or in any value
+ in the range is not in the domain of any variable."""
+ det_values = []
+ for v in self.variables:
+ if v.determined(dstore=dstore, constraint=self) is not False:
+ val = v.get_value(dstore=dstore)
+ val = list(val)[0]
+ if val > self.max_value or val in det_values:
+ return True
+ det_values.append(val)
+ for i in range(len(self.variables)):
+ found = False
+ for v in self.variables:
+ if i in v.get_upper(dstore=dstore):
+ found = True
+ break
+ if not found:
+ return True
+ return False
+
+ def is_entailed(self, dstore=None):
+ """Entailed if all variables are determined."""
+ for v in self.variables:
+ # Some variable is not determined
+ if v.determined(dstore=dstore, constraint=self) is False:
+ return False
+ return True
+
+ def infer(self, dstore=None, verbosity=0, tracevar=[]):
+ """If some value is only in the domain of one variable, determine
that variable
+ at that value."""
+ changed = set()
+ state = Constraint.sleeping
+ for i in range(len(self.variables)):
+ v = None
+ for vb in self.variables:
+ if i in vb.get_upper(dstore=dstore):
+ if v:
+ # Already a variable that has this value
+ v = None
+ break
+ else:
+ v = vb
+ if v:
+ if v.determine(i, dstore=dstore,
+ constraint=(verbosity>1 or vb in tracevar)
and self):
+ changed.add(v)
+ return state, changed
+ return state, changed
+
# Selection constraint propagators

class Selection(Constraint):
=======================================
--- /hiiktuu/cs.py Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu/cs.py Fri May 9 22:41:32 2014 UTC
@@ -41,30 +41,36 @@
distributable = 3
skipped = 4

- def __init__(self, constraints, dstore,
+ def __init__(self, constraints, dstore, depth=0, name='', parent=None,
description='', verbosity=0):
self.constraints = constraints
self.dstore = dstore
+ # Depth of search
+ self.depth = depth
# Used in solver's printname
self.description = description
+ # Solver (state) that generated this one
+ self.parent = parent
self.verbosity=verbosity
self.entailed = []
self.failed = []
self.status = Solver.running
self.id = Solver.id
+ self.name = name or "({})={}=v{}".format(description, self.id,
self.depth)
+ self.children = []
Solver.id += 1

def __repr__(self):
- return "Solver{} ({})".format(' ' + self.description if
self.description else '', self.id)
+ return "Solver{}".format(self.name)

- def exit(self, result):
+ def exit(self, result, verbosity=0):
if result == Constraint.failed:
return True
else:
- return self.fixed_point(result)
+ return self.fixed_point(result, verbosity=verbosity)

def fixed_point(self, awaken, verbosity=0):
- if verbosity > 1:
+ if verbosity:
s = "# constraints to awaken: {}, # variables to determine: {}|
{}"
print(s.format(len(awaken), len(self.dstore.ess_undet),
len(self.dstore.undetermined)))
if self.dstore.is_determined():
@@ -91,8 +97,8 @@
print(s.format(self, len(self.dstore.ess_undet),
len(self.dstore.undetermined), len(self.constraints)))
awaken = set(self.constraints)
it = 0
- while not self.exit(awaken):
- if verbosity > 1:
+ while not self.exit(awaken, verbosity=verbosity):
+ if verbosity:
print("Running iteration {}".format(it))
awaken = self.run_constraints(awaken, verbosity=verbosity,
tracevar=tracevar)
it += 1
@@ -224,35 +230,23 @@
if ndet > 5:
print('...')
# Select a variable and two disjoint basic constraints on it
- var = select_variable(undet, verbosity=verbosity)
+ var = self.select_variable(undet, verbosity=verbosity)
constraint1, constraint2 = self.select_constraints(var,
verbosity=verbosity)
if verbosity:
print('Distribution constraints: a -- {}, b --
{}'.format(constraint1, constraint2))
# The constraints of the selected variable (make copies)
constraints = var.constraints[:]
# Create the new solvers (states), applying one of the constraints
to each
- new_dstore1 = self.dstore.clone(constraint1, name=self.name+'a',
project=project)
- new_dstore2 = self.dstore.clone(constraint2, name=self.name+'b',
project=project)
- # Create a new CSpace for each dstore, preserving the accumulated
penalty
- cspace1 = CSpace(name=self.name+'a', depth=self.depth+1,
- variables=self.variables,
- propagators=propagators,
- penalty=self.penalty,
+ new_dstore1 = self.dstore.clone(constraint1, name=self.name+'a')
+ new_dstore2 = self.dstore.clone(constraint2, name=self.name+'b')
+ # Create a new Solver for each dstore, preserving the accumulateod
penalty
+ solver1 = Solver(self.constraints, new_dstore1,
+ name=self.name+'a', depth=self.depth+1,
parent=self,
- dstore=new_dstore1,
- failed_props=self.failed_props[:],
- entailed=self.entailed[:],
verbosity=verbosity)
- cspace2 = CSpace(name=self.name+'b', depth=self.depth+1,
- variables=self.variables,
- propagators=propagators,
-## projectors=newproj2,
-## dead_projectors=self.dead_projectors.copy(),
- penalty=self.penalty,
+ solver2 = Solver(self.constraints, new_dstore2,
+ name=self.name+'b', depth=self.depth+1,
parent=self,
- dstore=new_dstore2,
- failed_props=self.failed_props[:],
- entailed=self.entailed[:],
verbosity=verbosity)
- self.children.extend([cspace1, cspace2])
- return [((var, constraint2), cspace2), ((var, constraint1),
cspace1)]
+ self.children.extend([solver1, solver2])
+ return [((var, constraint2), solver2), ((var, constraint1),
solver1)]
=======================================
--- /hiiktuu/entry.py Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu/entry.py Fri May 9 22:41:32 2014 UTC
@@ -659,9 +659,12 @@
Entry.__init__(self, name, language, trans=trans)
self.tokens = tokens
if head:
- head_token = head.partition('_')[0]
self.head = head
- self.head_index = tokens.index(head_token)
+ if head in tokens:
+ self.head_index = tokens.index(head)
+ else:
+ self.head_index = tokens.index(head.partition('_')[0])
+# self.head_index = tokens.index(head_tokens[0]) or
tokens.index(head_tokens[1])
else:
self.head = tokens[head_index]
self.head_index = head_index
=======================================
--- /hiiktuu/languages/eng.lg Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu/languages/eng.lg Fri May 9 22:41:32 2014 UTC
@@ -36,8 +36,29 @@
read:
root: read
features: {tns: prt}
+ kicked:
+ root: kick_v
+ features: {tns: prt}
+ bucket:
+ root: bucket
+ features: {num: 0, prs: 3}
+ cats: [$sth, $concrete]

groups:
+ kick_v:
+# - words: [kick_v, the, bucket]
+# trans:
+# spa:
+# - [estirar_la_pata, {align: [0, 1, 2], agr: [{tns: tmp}, false,
false]}]
+ - words: [kick_v, $concrete]
+ trans:
+ spa:
+ - [patear_$concreto, {align: [0, 1], agr: [{tns: tmp}, false]}]
+ bucket:
+ - words: [the, bucket]
+ trans:
+ spa:
+ - [el_balde, {align: [0, 1]}]
"it's":
- words: ["it's"]
trans:
=======================================
--- /hiiktuu/languages/spa.lg Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu/languages/spa.lg Fri May 9 22:41:32 2014 UTC
@@ -2,6 +2,10 @@
abbrev: spa

groups:
+ patear:
+ - words: [patear, $concreto]
+ estirar:
+ - words: [estirar, la, pata]
es:
- words: [es]
fin:
@@ -37,9 +41,21 @@
- words: [el, muchacho]
trans:
eng:
- - [the boy, {align: [0, 1]}]
+ - [the_boy, {align: [0, 1]}]
+ balde:
+ - words: [el, balde]

forms:
+ balde:
+ root: balde
+ features: {num: 0, prs: 3, gen: 0}
+ cats: [$algo, $concreto]
+ pateó:
+ root: patear
+ features: {num: 0, prs: 3, tmp: prt}
+ estiró:
+ root: estirar
+ features: {num: 0, prs: 3, tmp: prt}
canción:
root: canción
features: {num: 0, prs: 3}
=======================================
--- /hiiktuu/sentence.py Wed May 7 22:10:05 2014 UTC
+++ /hiiktuu/sentence.py Fri May 9 22:41:32 2014 UTC
@@ -44,8 +44,13 @@
# Introduced "chunks": target output units that are not connected.
# 2014.05.04-5
# -- New agreement variables and constraints.
+# 2014.05.09
+# -- Fixed output ordering so that order between nodes in merged groups
+# is right: all nodes in outer group before merged node must
+# precede all nodes in inner group, and all nodes in outer group
+# after merged node must follow all nodes in inner group.

-import itertools
+import itertools, copy
# ui.py loads language, etc.
from .ui import *
from .cs import *
@@ -76,6 +81,8 @@
self.verbosity = verbosity
# GNodes in GInsts
self.gnodes = []
+ # Indices of covered SNodes
+ self.covered_indices = []
# A list of constraints to run
self.constraints = []
# Root domain store for variables
@@ -84,7 +91,7 @@
self.variables = {}
# Solver to find solutions
self.solver = Solver(self.constraints, self.dstore,
- description='for group selection',
verbosity=verbosity)
+ description='group selection',
verbosity=verbosity)
# Solutions found during parsing
self.solutions = []
if verbosity:
@@ -253,7 +260,10 @@
covered[i] = []
covered[i].append(gnode.sent_index)
for snode in self.nodes:
- snode.gnodes = covered.get(snode.index, [])
+ gnodes = covered.get(snode.index, [])
+ snode.gnodes = gnodes
+ if gnodes:
+ self.covered_indices.append(snode.index)

## Create IVars and (set) Vars with sentence DS as root DS

@@ -458,13 +468,14 @@
# Get the indices of the selected groups
groups = self.variables['groups'].get_value(dstore=dstore)
ginsts = [self.groups[g] for g in groups]
+ trees = [list(g.variables['tree'].get_value(dstore=dstore)) for g
in ginsts]
# Get the indices of the GNodes for each SNode
s2gnodes = []
for node in self.nodes:
gnodes = node.variables['gnodes'].get_value(dstore=dstore)
s2gnodes.append(gnodes)
self.solutions.append(Solution(self, ginsts, s2gnodes,
- len(self.solutions)))
+ len(self.solutions), trees=trees))

class SNode:
"""Sentence token and its associated analyses and variables."""
@@ -678,6 +689,7 @@
def create_variables(self, verbosity=0):
ngroups = len(self.sentence.groups)
nsnodes = len(self.sentence.nodes)
+ cand_snodes = self.sentence.covered_indices
# GNode indices for this GInst (determined)
self.variables['gnodes'] =
DetVar('g{}->gnodes'.format(self.index), {gn.sent_index for gn in
self.nodes})
# Abstract GNode indices for GInst (determined)
@@ -690,7 +702,8 @@
self.variables['cgnodes'] = self.variables['gnodes']
# SNode positions of GNodes for this GInst
self.svar('gnodes_pos', 'g{}->gnodes_pos'.format(self.index),
- set(), set(range(nsnodes)), self.ngnodes, self.ngnodes)
+ set(), set(cand_snodes), self.ngnodes, self.ngnodes,
ess=True)
+# set(), set(range(nsnodes)), self.ngnodes, self.ngnodes)
# SNode positions of abstract GNodes for this GInst
if self.nanodes == 0:
# No abstract nodes
@@ -700,10 +713,12 @@
else:
# Position for each abstract node in the group
self.svar('agnodes_pos', 'g{}->agnodes_pos'.format(self.index),
- set(), set(range(nsnodes)), self.nanodes,
self.nanodes)
+ set(), set(cand_snodes), self.nanodes, self.nanodes)
+# set(), set(range(nsnodes)), self.nanodes,
self.nanodes)
# Position for each concrete node in the group
self.svar('cgnodes_pos', 'g{}->cgnodes_pos'.format(self.index),
- set(), set(range(nsnodes)), self.ncgnodes,
self.ncgnodes)
+ set(), set(cand_snodes), self.ncgnodes,
self.ncgnodes)
+# set(), set(range(nsnodes)), self.ncgnodes,
self.ncgnodes)
# Other GInsts merged with this one, excluding and including itself
if self.nanodes == 0:
# No abstract nodes, so this is a determined variable with one
value (its own index)
@@ -726,7 +741,8 @@
else:
self.svar('tree', 'g{}->tree'.format(self.index),
# at least as long as the number of self's nodes
- set(), set(range(nsnodes)), self.ngnodes, nsnodes)
+ set(), set(cand_snodes), self.ngnodes,
len(cand_snodes), ess=True)
+# set(), set(range(nsnodes)), self.ngnodes, nsnodes,
ess=True)
# Determined variable for within-source agreement constraints,
gen: 0}
agr = self.get_agr()
if agr:
@@ -773,7 +789,7 @@
token = tokens[targ_index]
feats = features[targ_index] if features else None
gnodes.append((gnode, token, feats, agrs, targ_index))
- self.translations.append((tgroup, gnodes, tnodes))
+ self.translations.append((tgroup, gnodes, tnodes, self))

class GNode:

@@ -872,11 +888,12 @@
GNode in a selected group. Created when a complete variable
assignment.get('features'))
is found for a sentence."""

- def __init__(self, sentence, ginsts, s2gnodes, index):
+ def __init__(self, sentence, ginsts, s2gnodes, index, trees=None):
self.sentence = sentence
# List of sets of gnode indices
self.s2gnodes = s2gnodes
self.ginsts = ginsts
+ self.trees = trees
self.index = index
# A list of pairs for each snode: (gnodes, features)
self.snodes = []
@@ -901,7 +918,7 @@
print("Making translations for {}".format(self))
translations = itertools.product(*[g.translations for g in
self.ginsts])
for index, translation in enumerate(translations):
- t = Translation(self, translation, index, verbosity=verbosity)
+ t = Translation(self, translation, index,
trees=copy.deepcopy(self.trees), verbosity=verbosity)
t.initialize(verbosity=verbosity)
t.realize(verbosity=verbosity)
self.translations.append(t)
@@ -930,7 +947,7 @@
"""Representation of a single translation for an input sentence.
Multiple translations are possible with a single Solution."""

- def __init__(self, solution, attribs, index, verbosity=0):
+ def __init__(self, solution, attribs, index, trees=None, verbosity=0):
self.solution = solution
self.index = index
self.sentence = solution.sentence
@@ -939,25 +956,30 @@
# from attributes
self.gnode_dict = {}
self.groups_tnodes = []
- for tgroup, tgnodes, tnodes in attribs:
+ for tgroup, tgnodes, tnodes, ginst in attribs:
+# print('tgroup {}, tgnodes {}, tnodes {}, ginsts
{}'.format(tgroup, tgnodes, tnodes, ginst))
for tgnode, tokens, feats, agrs, t_index in tgnodes:
self.gnode_dict[tgnode] = (tgroup, tokens, feats, agrs,
t_index)
- self.groups_tnodes.append((tgroup, tnodes))
+ self.groups_tnodes.append((tgroup, tnodes, ginst))
# form list / order constraint pairs for each sentence position
self.nodes = []
# Ordered units: merged groups or uncovered words
self.chunks = []
+ # Merged group indices
+ self.mergers = []
# pairs of node indices representing order constraints
self.order_pairs = []
+ # Source-sentence indices for tgroup trees
+ self.trees = trees
# Root domain store for variables
self.dstore = DStore(name="T{}".format(self.index))
- # Order variables for each node
- self.variables = []
+ # Order variables for each node, tree variables for groups
+ self.variables = {}
# Order and disjunction constraints
self.constraints = []
# Translation needs a solver to figure out positions of words
self.solver = Solver(self.constraints, self.dstore,
- description='for target realization',
+ description='target realization',
verbosity=verbosity)
# Final output
self.output = None
@@ -995,7 +1017,7 @@
print('Building {}'.format(self))
tginsts, tgnodes, trans_index = self.groups_tnodes,
self.gnode_dict, self.index
# Figure out the target forms for each snode
- print('tgnodes {}'.format(tgnodes))
+# print('tgnodes {}'.format(tgnodes))
for snode, (gnodes, features) in zip(self.sentence.nodes,
self.solution.snodes):
if not gnodes:
# snode is not covered by any group
@@ -1005,7 +1027,13 @@
if len(gnodes) > 1:
# There are two gnodes for this snode; only the
concrete node
# can have translations
+# s = "Snode {} merges abstract node {} in group {}
with concrete node {} in group {}"
+# if gnodes[0].cat:
+# print(s.format(snode.index, gnodes[0],
gnodes[0].ginst.group, gnodes[1], gnodes[1].ginst.group))
+# else:
+# print(s.format(snode.index, gnodes[1],
gnodes[1].ginst.group, gnodes[0], gnodes[0].ginst.group))
gn0, gn1 = tgnodes[gnodes[0]], tgnodes[gnodes[1]]
+# print("gn0 {}, gn1 {}".format(gn0, gn1))
tgroups, tokens, targ_feats, agrs, t_index = zip(gn0,
gn1)
token = False
i = 0
@@ -1022,7 +1050,12 @@
t_indices.append((tgroups[0], gn0[-1]))
if len(tgroups[1].tokens) > 1:
t_indices.append((tgroups[1], gn1[-1]))
-# print('tgroups {}, token {}, t_indices
{}'.format(tgroups, token, t_indices))
+ ## Record this node and its groups in mergers
+ tg = list(zip(tgroups, gnodes))
+ # Sort the groups by which is the "outer" group in the
merger
+ tg.sort(key=lambda x: x[1].cat)
+ tg = [x[0] for x in tg]
+ self.mergers.append([snode.index, tg])
else:
gnode = gnodes[0]
if gnode not in tgnodes:
@@ -1047,13 +1080,16 @@
self.nodes.append((gen, t_indices))
# Add TNode elements
tgnode_elements = []
- for ginst, tnodes in tginsts:
+ for ginst_i, (tginst, tnodes, ginst) in enumerate(tginsts):
if tnodes:
for tnode in tnodes:
+ src_index = len(self.nodes)
+# print('TG {}, tnode {}, sindex {}, ginst
{}'.format(tginst, tnode, src_index, ginst))
+ self.trees[ginst_i].append(src_index)
forms = tnode.generate()
if verbosity:
print(' Generating tnode form {}/{}:
{}'.format(tnode.token, tnode.features, forms))
- index = [(ginst, tnode.index)]
+ index = [(tginst, tnode.index)]
self.nodes.append((forms, index))

def set_chunks(self, verbosity=0):
@@ -1103,17 +1139,21 @@

def make_order_pairs(self, verbosity=0):
"""Convert group/index pairs to integer (index) order pairs.
- Constrain chunks to appear in source-language order."""
+ Constrain chunks to appear in source-language order.
+ Constrain order in merged groups."""
tgroup_dict = {}
for index, (forms, constraints) in enumerate(self.nodes):
-# print('index {}, forms {}, constraints {}'.format(index,
forms, constraints))
+# print(' index {}, forms {}, constraints {}'.format(index,
forms, constraints))
for tgroup, tg_index in constraints:
if tgroup not in tgroup_dict:
tgroup_dict[tgroup] = []
tgroup_dict[tgroup].append((index, tg_index))
+# print('tgroup dict {}'.format(tgroup_dict))
for pairs in tgroup_dict.values():
+# print(' pairs {}'.format(pairs))
for pairpair in itertools.combinations(pairs, 2):
pairpair = list(pairpair)
+# print(' pairpair {}'.format(pairpair))
# Sort by the target index
pairpair.sort(key=lambda x: x[1])
self.order_pairs.append([x[0] for x in pairpair])
@@ -1123,19 +1163,69 @@
for index in indices:
for next_index in next_indices:
self.order_pairs.append([index, next_index])
+ # Order nodes within merged groups
+ for node, (inner, outer) in self.mergers:
+ # Indices (input, tgroup) in inner and outer groups
+ inner_nodes = tgroup_dict[inner]
+ outer_nodes = tgroup_dict[outer]
+ # Get the tgroup index for the merge node
+# print("node {}, inner nodes {}, outer nodes {}".format(node,
inner_nodes, outer_nodes))
+ merge_tg_i = dict(outer_nodes)[node]
+# print("pos of merge node in outer group:
{}".format(merge_tg_i))
+ # Get input indices for outer groups units before and after
the merged node
+ prec_outer = [n for n, i in outer_nodes if i < merge_tg_i]
+ foll_outer = [n for n, i in outer_nodes if i > merge_tg_i]
+# print("outer nodes before {} / after {} merger
node".format(prec_outer, foll_outer))
+ if prec_outer or foll_outer:
+ # Get input indices for inner group nodes other than the
merge node
+ other_inner = [n for n, i in inner_nodes if n != node]
+# print('inner nodes other than merge node:
{}'.format(other_inner))
+ # Each outer group node before the merge node must precede
all inner group nodes,
+ # and each outer group node after the merge node must
follow all inner group nodes.
+ # Add order pair constraints (using input indices) for
these constraints.
+ for o in prec_outer:
+ for i in other_inner:
+ self.order_pairs.append([o, i])
+ for o in foll_outer:
+ for i in other_inner:
+ self.order_pairs.append([i, o])
+
+ def svar(self, name, lower, upper, lower_card=0, upper_card=MAX,
+ ess=True):
+ return Var(name, lower, upper, lower_card, upper_card,
+ essential=ess, rootDS=self.dstore)

def create_variables(self, verbosity=0):
- """Create an IVar for each translation node."""
+ """Create an IVar for each translation node and variables for each
group tree."""
nnodes = len(self.nodes)
- self.variables = [IVar("o{}".format(i), set(range(nnodes)),
rootDS=self.dstore, essential=True) for i in range(nnodes)]
+ self.variables['order_pairs'] = DetVar("order_pairs",
set([tuple(positions) for positions in self.order_pairs]))
+ self.variables['order'] = [IVar("o{}".format(i),
set(range(nnodes)), rootDS=self.dstore, essential=True) for i in
range(nnodes)]
+ # target-language trees
+ self.variables['tree_sindices'] = []
+ self.variables['trees'] = []
+ for i, t in enumerate(self.trees):
+ if len(t) > 1:
+ # Only make a variable if the tree has more than one node.
+
self.variables['tree_sindices'].append(DetVar("tree{}_sindices".format(i),
set(t)))
+
self.variables['trees'].append(self.svar("tree{}".format(i), set(),
set(range(nnodes)), len(t), len(t), ess=False))

def create_constraints(self, verbosity=0):
"""Make order and disjunction constraints."""
if verbosity:
print("Creating constraints for {}".format(self))
- for first, second in self.order_pairs:
- self.constraints.append(SetPrecedence([self.variables[first],
self.variables[second]]))
- self.constraints.extend(Disjoint(self.variables).constraints)
+ ## Order constraints
+ order_vars = self.variables['order']
+# for first, second in self.order_pairs:
+# self.constraints.append(SetPrecedence([order_vars[first],
order_vars[second]]))
+
self.constraints.append(PrecedenceSelection(self.variables['order_pairs'],
+ order_vars))
+ self.constraints.append(Order(order_vars))
+# self.constraints.extend(Disjoint(order_vars).constraints)
+ ## Tree constraints
+ for i_var, tree in zip(self.variables['tree_sindices'],
self.variables['trees']):
+ self.constraints.append(UnionSelection(tree, i_var,
order_vars))
+ # Convexity (projectivity)
+ self.constraints.append(SetConvexity(tree))

def realize(self, verbosity=0):
"""Run constraint satisfaction on the order and disjunction
constraints,
@@ -1150,7 +1240,8 @@
if self.solver.status == Solver.succeeded:
# No more awake constraints and no undetermined variables; get
positions from
# variable values
- positions = [list(v.get_value(dstore=self.dstore))[0] for v in
self.variables]
+ order_vars = self.variables['order']
+ positions = [list(v.get_value(dstore=self.dstore))[0] for v in
order_vars]
node_pos = list(zip([n[0] for n in self.nodes], positions))
node_pos.sort(key=lambda x: x[1])
self.output = [n[0] for n in node_pos]
=======================================
--- /l3xdg/solver.py Sun Apr 27 18:07:59 2014 UTC
+++ /l3xdg/solver.py Fri May 9 22:41:32 2014 UTC
@@ -250,8 +250,8 @@
self.variables = set()
for prop in propagators:
self.variables.update(prop.variables)
- # Needed for project()
- self.executed_events = set()
+# # Needed for project()
+# self.executed_events = set()
if verbosity > 1:
self.dstore.print_undet()
# elif verbosity:
Reply all
Reply to author
Forward
0 new messages