Revision: f42994054b58
Branch: default
Author: Michael Gasser <
gas...@cs.indiana.edu>
Date: Mon May 19 06:57:46 2014 UTC
Log: Agreement between TL nodes.
http://code.google.com/p/hltdi-l3/source/detail?r=f42994054b58
Modified:
/hiiktuu.py
/hiiktuu/constraint.py
/hiiktuu/entry.py
/hiiktuu/features.py
/hiiktuu/language.py
/hiiktuu/languages/amh.lg
/hiiktuu/languages/eng.lg
/hiiktuu/languages/orm.lg
/hiiktuu/languages/spa.lg
/hiiktuu/sentence.py
/paperdrafts/lglp/lglp14.pdf
/paperdrafts/lglp/lglp14.tex
=======================================
--- /hiiktuu.py Fri May 16 04:02:37 2014 UTC
+++ /hiiktuu.py Mon May 19 06:57:46 2014 UTC
@@ -28,7 +28,7 @@
# 2014.02.09
# -- Created
-__version__ = 0.9
+__version__ = 1.0
import hiiktuu
@@ -36,18 +36,48 @@
#import cProfile
#import pstats
+def piece_of_mind_parse_ung(verbosity=0):
+ """
+ Eng parse.
+ Illustrates
+ (1) within SL agreement (fails because 'my' doesn't agree with 'gives')
+ """
+ eng = hiiktuu.Language.load('eng')[0]
+ s = hiiktuu.Sentence(raw='Mary gives them a piece of my mind',
+ language=eng,
+ verbosity=verbosity)
+ s.initialize(verbosity=verbosity)
+ s.solve(translate=False, verbosity=verbosity)
+ return s
+
+def piece_of_mind_trans(verbosity=0):
+ """
+ Eng->Spa
+ Illustrates
+ (1) within SL agreement (succeeds because 'her' agrees with 'gives')
+ (2) SL-TL feature agreement
+ (3) SL-TL word count mismatch (SL > TL)
+ """
+ eng, spa = hiiktuu.Language.load('eng', 'spa')
+ s = hiiktuu.Sentence(raw='Mary gives them a piece of her mind',
+ language=eng, target=spa,
+ verbosity=verbosity)
+ s.initialize(verbosity=verbosity)
+ s.solve(translate=True, verbosity=verbosity)
+ return s
+
def kick_the_bucket(verbosity=0):
"""
Eng->Spa
+ Illustrates
+ (1) SL group ambiguity (search for solutions)
+ (2) SL-TL feature agreement
"""
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(verbosity=verbosity)
s.solve(verbosity=verbosity)
-# sol = s.solutions[0]
-# sol.translate()
return s
def end_of_world(verbosity=0):
@@ -55,14 +85,13 @@
Eng->Spa
it's the end of the world -> es el fin del mundo
Illustrates
- (1) source-target word count mismatch (source > target)
+ (1) SL-TL word count mismatch (SL > TL)
"""
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.initialize(verbosity=verbosity)
s.solve(verbosity=verbosity)
-# s.do(verbosity=verbosity)
return s
def ate_fish(verbosity=0):
@@ -70,7 +99,7 @@
Amh->Orm
አሳ በላ (he ate fish) -> qurxummii nyaate.
Illustrates
- (1) source-target feature agreement
+ (1) SL-TL feature agreement
"""
amh, orm = hiiktuu.Language.load('amh', 'orm')
s = hiiktuu.Sentence(raw="አሳ በላ", language=amh, target=orm,
verbosity=verbosity)
@@ -83,8 +112,8 @@
Amh አሳ በልቶ አያውቅም 'he's never eaten fish'
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 (source <
target)
+ (1) SL-TL feature agreement
+ (2) SL-TL word count mismatch (SL < TL)
"""
amh, orm = hiiktuu.Language.load('amh', 'orm')
s = hiiktuu.Sentence(raw="አሳ በልቶ አያውቅም", language=amh, target=orm,
@@ -110,22 +139,44 @@
s.solve(verbosity=verbosity)
return s
-def cantar_las_cuarenta(trans=True, verbosity=0):
+def cantar_las_cuarenta_she(trans=True, verbosity=0):
"""
Spa->Eng
Paula les cantó las cuarenta -> Paula read them the riot act.
+ -> Paula gave them a piece of her mind.
Illustrates
- (1) source-target feature agreement
- (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
+ (1) SL-TL feature agreement
+ (2) SL-TL mismatch in word count (SL < TL)
+ (3) SL-TL mismatch in word order
+ (4) SL word not associated with any group
+ (5) within-TL-group agreement
"""
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.initialize(verbosity=verbosity)
+ s.solve(translate=trans, verbosity=verbosity)
+ return s
+
+def cantar_las_cuarenta_I(trans=True, verbosity=0):
+ """
+ Spa->Eng
+ les canté las cuarenta -> read them the riot act.
+ -> gave them a piece of my mind.
+ Illustrates
+ (1) SL-TL feature agreement
+ (2) SL-TL mismatch in word count (SL < TL)
+ (3) SL-TL mismatch in word order
+ (4) SL word not associated with any group
+ (5) within-TL-group agreement
+ """
+ spa, eng = hiiktuu.Language.load('spa', 'eng')
+ s = hiiktuu.Sentence(raw="les canté las cuarenta",
+ language=spa, target=eng if trans else None,
+ verbosity=verbosity)
s.initialize(verbosity=verbosity)
- s.solve(verbosity=verbosity)
+ s.solve(translate=trans, verbosity=verbosity)
return s
def ui():
=======================================
--- /hiiktuu/constraint.py Fri May 16 04:02:37 2014 UTC
+++ /hiiktuu/constraint.py Mon May 19 06:57:46 2014 UTC
@@ -264,187 +264,6 @@
return Constraint.entailed, {var}
return Constraint.entailed, set()
-### Set cardinality
-##
-##class CardinalityGEQ(Constraint):
-## """Set variable's cardinality is constrained to be >= lower bound."""
-##
-## def __init__(self, var, lower, problem=None):
-## Constraint.__init__(self, (var,), problem=problem)
-## self.lower = lower
-##
self.name = '|{0}|>={1}'.format(self.get_var(), self.lower)
-##
-## def fails(self, dstore=None):
-## """Is the var's upper cardinality bound < lower?"""
-## if self.get_var().get_upper_card(dstore=dstore) < self.lower:
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Is the variable's lower cardinality bound already >= lower?"""
-## if self.get_var().get_lower_card(dstore=dstore) >= self.lower:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## """The variable's cardinality is restricted be >= lower: lower
bound
-## is raised if necessary."""
-## var = self.get_var()
-## if var.strengthen_lower_card(self.lower, dstore=dstore,
-## constraint=(verbosity>1 or var in
tracevar) and self):
-## return Constraint.entailed, {var}
-## return Constraint.entailed, set()
-##
-##class CardinalityLEQ(Constraint):
-## """Set variable's cardinality is constrained to be <= upper bound."""
-##
-## def __init__(self, var, upper, problem=None):
-## Constraint.__init__(self, (var,), problem=problem)
-## self.upper = upper
-##
self.name = '|{0}| c= {1}'.format(self.get_var(), self.upper)
-##
-## def fails(self, dstore=None):
-## """Is the var's lower cardinality bound > upper?"""
-## if self.get_var().get_lower_card(dstore=dstore) > self.upper:
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Is the variable's upper cardinality bound already <= upper?"""
-## if self.get_var().get_upper_card(dstore=dstore) <= self.upper:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## """The variable's cardinality is restricted to be <= upper:
-## upper bound is lowered if necessary."""
-## var = self.get_var()
-## if var.strengthen_upper_card(self.upper, dstore=dstore,
-## constraint=(verbosity>1 or var in
tracevar) and self):
-## return Constraint.entailed, {var}
-## return Constraint.entailed, set()
-##
-##### Constraints that propagate
-##
-#### Primitive propagators
-##
-### Integer domain variables only
-##
-##class LessThan(Constraint):
-## """IVar1 is less than or equal to IVar2."""
-##
-## def __init__(self, variables, problem=None, weight=1):
-## Constraint.__init__(self, variables, problem=problem,
-## weight=weight)
-##
self.name = '{0} <= {1}'.format(self.get_iv1(), self.get_iv2())
-##
-## def get_iv1(self):
-## return self.variables[0]
-##
-## def get_iv2(self):
-## return self.variables[1]
-##
-## def fails(self, dstore=None):
-## """
-## Fail if min of domain1 > max of domain2.
-## """
-## iv1 = self.get_iv1()
-## iv2 = self.get_iv2()
-## min1 = min(iv1.get_domain(dstore=dstore))
-## max2 = max(iv2.get_domain(dstore=dstore))
-## if min1 > max2:
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if max of domain1 <= min of domain2."""
-## iv1 = self.get_iv1()
-## iv2 = self.get_iv2()
-## max1 = max(iv1.get_domain(dstore=dstore))
-## min2 = min(iv2.get_domain(dstore=dstore))
-## if max1 <= min2:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## iv1 = self.get_iv1()
-## iv2 = self.get_iv2()
-## d1 = iv1.get_domain(dstore=dstore)
-## d2 = iv2.get_domain(dstore=dstore)
-## # iv2 must be between the min of iv1's domain and the maximum
value
-## iv2_values = set(range(min(d1), max(d2) + 1))
-## if iv2.strengthen(iv2_values, dstore=dstore,
-## constraint=(verbosity>1 or iv2 in tracevar)
and self):
-## changed.add(iv2)
-## # iv1 must be between the min of its domain and the max of iv2's
domain
-## # (iv2's domain may have changed)
-## iv1_values = set(range(min(d1),
max(iv2.get_domain(dstore=dstore)) + 1))
-## # Maximum value of sv2's upper bound constrains sv1's upper card
-## if iv1.strengthen(iv1_values, dstore=dstore,
-## constraint=(verbosity>1 or iv1 in tracevar)
and self):
-## changed.add(iv1)
-##
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-## return Constraint.sleeping, changed
-##
-##class CardinalityEq(Constraint):
-## """Set variable's cardinality is constrained to be equal to value of
IVar."""
-##
-## def __init__(self, variables, problem=None, weight=1):
-## Constraint.__init__(self, variables, problem=problem,
-## weight=weight)
-##
self.sv = variables[0]
-## self.iv = variables[1]
-##
self.name = '|{0}| = {1}'.format(
self.sv, self.iv)
-##
-## def fails(self, dstore=None):
-## """Is the sv's lower cardinality bound > max of iv's domain?"""
-## if self.iv.determined(dstore=dstore) is not False and
self.sv.determined(dstore=dstore) is not False:
-### print('Both vars determined: {}, {}'.format(self.iv,
self.sv))
-## if self.iv.get_value(dstore=dstore) !=
self.sv.get_upper_card(dstore=dstore):
-## return True
-## if self.sv.get_lower_card(dstore=dstore) >
max(self.iv.get_domain(dstore=dstore)):
-## return True
-## if min(self.iv.get_domain(dstore=dstore)) >
self.sv.get_upper_card(dstore=dstore):
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Is the variable's upper cardinality bound already = iv?"""
-## if self.iv.determined(dstore=dstore) is not False and
self.sv.determined(dstore=dstore) is not False:
-## if self.sv.get_upper_card(dstore=dstore) ==
self.iv.get_value(dstore=dstore):
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## """sv's upper cardinality is restricted to be <= min of iv's
domain.
-## iv's domain is restricted to values >= lower cardinality of
sv."""
-## state = Constraint.sleeping
-## changed = set()
-## sv =
self.sv
-## iv = self.iv
-## sv_low_card = sv.get_lower_card(dstore=dstore)
-## sv_up_card = sv.get_upper_card(dstore=dstore)
-## if iv.strengthen(set(range(sv_low_card, sv.max)), dstore=dstore,
-## constraint=(verbosity>1 or iv in tracevar) and
self):
-## changed.add(iv)
-## return state, changed
-## if iv.strengthen(set(range(0, sv_up_card + 1)), dstore=dstore,
-## constraint=(verbosity>1 or iv in tracevar) and
self):
-## changed.add(iv)
-## return state, changed
-## iv_dom = iv.get_domain(dstore=dstore)
-## if sv.strengthen_lower_card(min(iv_dom), dstore=dstore,
-## constraint=(verbosity>1 or sv in
tracevar) and self):
-## changed.add(sv)
-## return state, changed
-## if sv.strengthen_upper_card(max(iv_dom), dstore=dstore,
-## constraint=(verbosity>1 or sv in
tracevar) and self):
-## changed.add(sv)
-## return state, changed
-
# Set domain variables only
class SetConvexity(Constraint):
@@ -702,98 +521,6 @@
print(' Variables {} changed'.format(changed))
return Constraint.sleeping, changed
-##class CardinalitySubset(Constraint):
-## """Cardinality of set variable 1 is within set variable 2. This
constraint is not included
-## in Müller, but it is needed for XDG valency.
-## It could be handled with IVMemberSV."""
-##
-## def __init__(self, variables, problem=None, weight=1):
-## Constraint.__init__(self, variables, problem=problem,
-## weight=weight)
-##
self.name = '|{0}| c= {1}'.format(self.get_sv1(), self.get_sv2())
-##
-## def get_sv1(self):
-## return self.variables[0]
-##
-## def get_sv2(self):
-## return self.variables[1]
-##
-## def fails(self, dstore=None):
-## """Fail if minimum cardinality of SV1 is greater than maximum
possible value of SV2
-## or if maximum cardinality of SV1 is less than the minimum
possible value of SV2.
-## Fixed 2011.12.09: minimum possible value of SV2 is minimum of
*upper* bound, not
-## lower bound."""
-## sv1 = self.get_sv1()
-## sv2 = self.get_sv2()
-## upper2 = sv2.get_upper(dstore=dstore)
-## max2card = max(upper2) if upper2 else 0
-## if sv1.get_lower_card(dstore=dstore) > max2card:
-## return True
-### lower2 = sv2.get_lower(dstore=dstore)
-## min2card = min(upper2) if upper2 else 0
-## # min(lower2) if lower2 else 0
-## if sv1.get_upper_card(dstore=dstore) < min2card:
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if cardinality of SV1 determined, SV2 determined,
and the former is in the latter."""
-## sv1 = self.get_sv1()
-## sv2 = self.get_sv2()
-## if sv2.determined(dstore=dstore, constraint=self) is not False
and \
-## sv1.get_lower_card(dstore=dstore) ==
sv1.get_upper_card(dstore=dstore) in sv2.get_value(dstore=dstore):
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## state = Constraint.sleeping
-## sv1 = self.get_sv1()
-## sv2 = self.get_sv2()
-## sv1_low_card = sv1.get_lower_card(dstore=dstore)
-## sv1_up_card = sv1.get_upper_card(dstore=dstore)
-### if tracevar in self.variables:
-### print(self, 'INFERRING')
-## # If sv1's cardinality is determined, then it must be in sv2
-## if sv1_low_card == sv1_up_card:
-### print('SV1 {} has same upper and lower card {}'.format(sv1,
sv1_low_card))
-## if sv2.strengthen_lower({sv1_low_card}, dstore=dstore,
-## constraint=(verbosity>1 or sv2 in
tracevar) and self):
-### constraint=self):
-### if sv2.determine({sv1_low_card}, dstore=dstore,
-### constraint=(verbosity>1 or sv2 in
tracevar) and self):
-## changed.add(sv2)
-## return state, changed
-##
-### if tracevar in self.variables:
-### print(self, 'GOT TO 0')
-##
-## sv2_upper = sv2.get_upper(dstore=dstore)
-### sv2_lower = sv2.get_lower(dstore=dstore)
-##
-## # Minimum value of sv2 constrains sv1's lower card
-## # Fixed 2011.12.09: minimum value of sv2 is min of *upper*
bound, not lower
-## if sv2_upper:
-## # Could be empty set, in which case no strengthening is
possible
-## if sv1.strengthen_lower_card(min(sv2_upper), dstore=dstore,
-## constraint=(verbosity>1 or sv1
in tracevar) and self):
-## changed.add(sv1)
-## return state, changed
-##
-### if tracevar in self.variables:
-### print(self, 'GOT TO 1')
-## # Maximum value of sv2's upper bound constrains sv1's upper card
-## upcard = max(sv2_upper) if sv2_upper else 0
-## if sv1.strengthen_upper_card(upcard, dstore=dstore,
constraint=(verbosity>1 or sv1 in tracevar) and self):
-## changed.add(sv1)
-## return state, changed
-### if tracevar in self.variables:
-### print(self, 'GOT TO 2')
-##
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-## return state, changed
-
class SetPrecedence(Constraint):
"""All elements of set variable 1 must precede all elements of set
variable 2."""
@@ -814,7 +541,8 @@
@staticmethod
def cant_precede(var1, var2, dstore=None):
"""Is the highest value that must occur in var1 >= the lowest
value that must occur in var2?"""
-# print("Can't precede {}, {}".format(var1, var2))
+ if not var1.get_upper(dstore=dstore):
+ print("Can't precede {}, {}".format(var1, var2))
# Lower
if isinstance(var1, IVar):
v1 = min(var1.get_upper(dstore=dstore))
@@ -875,67 +603,6 @@
return state, changed
return state, changed
-### Integer domain and set domain variables
-##
-##class IVMemberSV(Constraint):
-## """Integer variable value must be member of set variable value."""
-##
-## def __init__(self, variables, problem=None, propagate=True,
-## weight=1):
-## Constraint.__init__(self, variables, problem=problem,
propagate=propagate,
-## weight=weight)
-##
self.name = '{0} c {1}'.format(self.get_iv(), self.get_sv())
-##
-## def get_iv(self):
-## """The domain variable."""
-## return self.variables[0]
-##
-## def get_sv(self):
-## """The set variable."""
-## return self.variables[1]
-##
-## def fails(self, dstore=None):
-## """Fail if none of the IV values are in SV upper bound."""
-## iv = self.get_iv()
-## sv = self.get_sv()
-## iv_dom = iv.get_domain(dstore=dstore)
-## sv_up = sv.get_upper(dstore=dstore)
-## if len(iv_dom & sv_up) == 0:
-## return True
-## return False
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if IV values are subset of SV lower bound."""
-## iv = self.get_iv()
-## sv = self.get_sv()
-## iv_dom = iv.get_domain(dstore=dstore)
-## sv_low = sv.get_lower(dstore=dstore)
-### if self.pattern:
-### # For patterns, the propagator is entailed if every element
in the domain of iv
-### # unifies with the lower bound of sv
-### if all([unify_fssets({tup}, sv_low) for tup in iv_dom]):
-### return True
-## if iv_dom <= sv_low:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## iv = self.get_iv()
-## sv = self.get_sv()
-## # Constrain the values of IV to be within upper bound of SV
-## if iv.strengthen(sv.get_upper(dstore=dstore), dstore=dstore,
-## constraint=(verbosity>1 or iv in tracevar) and
self):
-## changed.add(iv)
-## # If IV is determined, constrain SV to include it
-## if iv.determined(dstore=dstore, verbosity=verbosity) is not
False:
-## if sv.strengthen_lower(iv.get_domain(dstore=dstore),
dstore=dstore,
-## constraint=(verbosity>1 or sv in
tracevar) and self):
-## changed.add(sv)
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-## return Constraint.sleeping, changed
-
class Order(Constraint):
"""N int variables, whose values are positions from 0 to n-1."""
@@ -1111,246 +778,6 @@
string += elem.__repr__()
return string + ']'
-##class IntSelection(Selection):
-## """Selection constraint with integer variable as selection variable.
-## Müller treats this as derived from UnionSelection, but it is more
efficient
-## to treat it as a primitive, at least in this program.
-## """
-##
-## def __init__(self, mainvar=None, selvar=None, seqvars=None,
problem=None, weight=1,
-## maxset=None):
-## Selection.__init__(self, mainvar=mainvar, selvar=selvar,
seqvars=seqvars,
-## problem=problem, weight=weight)
-## self.maxset = maxset or ALL
-##
self.name = '{0} = {1} [{2}]'.format(self.mainvar,
self.format_seq(self.seqvars), self.selvar)
-##
-## def fails(self, dstore=None):
-## """Fail if the domain of sel var includes only indices that are
beyond the
-## length of seq vars, of if the domain of sel var is empty."""
-## selvar = self.selvar
-## sel_domain = selvar.get_domain(dstore=dstore)
-## if not sel_domain or min(sel_domain) >= len(self.seqvars):
-## return True
-## elif selvar.determined(dstore=dstore, constraint=self) is not
False:
-## # If the selvar is determined, check the selected seq var
-## seqvar = self.seqvars[selvar.get_value(dstore=dstore)]
-## if seqvar.determined(dstore=dstore, constraint=self) is not
False:
-## # The seqvar is determined too; see if it cannot be
equal to the mainvar
-## # This is true if the upper bound of mainvar fails to
contain values in seqvar's value
-## seqval = seqvar.get_value(dstore=dstore)
-## # In case seqvar is an IVar, make its value a set
-## if not isinstance(seqval, set):
-## seqval = {seqval}
-## mainvar = self.mainvar
-## mainvar_upper = mainvar.get_upper(dstore=dstore)
-## if seqval - mainvar_upper:
-## return True
-## # It's also true if the lower bound of mainvar contains
values not in seqvar's value
-## mainvar_lower = mainvar.get_lower(dstore=dstore)
-## if mainvar_lower - seqval:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## seqvars = self.seqvars
-## selvar = self.selvar
-## mainvar = self.mainvar
-## changed = set()
-## state = Constraint.sleeping
-##
-## sel_infer = Selection.infer(self, dstore=dstore,
verbosity=verbosity, tracevar=tracevar)
-## if sel_infer:
-## return sel_infer
-##
-## if selvar.determined(dstore=dstore, verbosity=verbosity,
constraint=self) is not False:
-## # The selection var is determined
-##
-## # index of selected seq var
-## selval = selvar.get_value(dstore=dstore)
-## # selected seq var
-## sel_seqvar = seqvars[selval]
-##
-## # If the selection var is determined, check whether the
indexed sequence var
-## # is also
-##
-## if sel_seqvar.determined(dstore=dstore, verbosity=verbosity,
constraint=self) is not False:
-## selseq_value = sel_seqvar.get_value(dstore=dstore)
-## # If it's determined, determine the main var
-## if mainvar.determine(selseq_value, dstore=dstore,
-## constraint=(verbosity>1 or mainvar
in tracevar) and self):
-## changed.add(mainvar)
-## state = Constraint.entailed
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-### if self.det_seqs:
-### state = self.determine_seqs(dstore=dstore,
verbosity=verbosity, tracevar=tracevar, changed=changed)
-## return state, changed
-##
-## # Otherwise check whether the main var is determined, in
which case the selected
-## # seq var can be constrained to its value
-## if mainvar.determined(dstore=dstore, verbosity=verbosity,
constraint=self) is not False:
-## mainvalue = mainvar.get_value(dstore=dstore)
-## if sel_seqvar.determine(mainvalue, dstore=dstore,
-## constraint=(verbosity>1 or
sel_seqvar in tracevar) and self):
-## changed.add(sel_seqvar)
-## return state, changed
-##
-## sel_domain = selvar.get_domain(dstore=dstore)
-##
-## # The main variable must be a subset of the union of the upper
bounds of all
-## # sequence variables indexed by the elements in the domain of
the selection variable,
-## # that is, eliminate any elements from the upper bound that are
not in this union
-## seq_uppers = [seqvars[j].get_upper(dstore=dstore) for j in
sel_domain]
-## if mainvar.strengthen_upper(set().union(*seq_uppers),
dstore=dstore,
-## constraint=(verbosity>1 or mainvar
in tracevar) and self):
-## changed.add(mainvar)
-## return state, changed
-##
-## # The main variable must be a superset of the intersection of
the lower bounds of all
-## # sequence variables indexed by the lower bound of the selection
variable, that is,
-## # add any elements to the lower bound that are in this
intersection
-## seq_lowers = [seqvars[j].get_lower(dstore=dstore) for j in
sel_domain]
-## if
mainvar.strengthen_lower(seq_lowers[0].intersection(*seq_lowers[1:]),
dstore=dstore,
-## constraint=(verbosity>1 or mainvar
in tracevar) and self):
-## changed.add(mainvar)
-## return state, changed
-##
-## # If the lower bound of some seqvar is not a subset of mainvar's
upper bound,
-## # or the upper bound of the seqvar is not a superset of
mainvar's lower bound,
-## # then exclude its index from selection var's domain
-## for j in sel_domain.copy():
-## seqvar = seqvars[j]
-## if not seqvar.get_lower(dstore=dstore) <=
mainvar.get_upper(dstore=dstore) or \
-## not seqvar.get_upper(dstore=dstore) >=
mainvar.get_lower(dstore=dstore):
-## # mainvar cannot equal seqvar, so remove j from selvar's
domain
-## if selvar.discard_value(j, dstore=dstore,
-## constraint=(verbosity>1 or
selvar in tracevar) and self):
-## changed.add(selvar)
-## return state, changed
-##
-## # If excluding any index from selection var's domain in figuring
the
-## # union of upper bounds of indexed sequence variables causes the
lower bound
-## # of the main variable to contain elements not in the union,
-## # then that index must be the value of the selection var.
-## for j in selvar.get_domain(dstore=dstore): # Might have changed
-## # Consider only indices that in the upper bound of selection
variable
-## # Exclude j
-## indices = sel_domain - {j}
-## # Get the union of the upper bounds of the indexed sequence
variables
-## seqvar_union =
set().union(*[seqvars[i].get_upper(dstore=dstore) for i in indices])
-## # Does the lower bound of the main variables have any
elements not in the union?
-## main_union_diff = mainvar.get_lower(dstore=dstore) -
seqvar_union
-## if len(main_union_diff) > 0:
-## # Yes; add the difference to the excluded seq var's
lower bound
-## if seqvars[j].strengthen_lower(main_union_diff,
dstore=dstore,
-## constraint=(verbosity>1
or seqvars[j] in tracevar) and self):
-## changed.add(seqvars[j])
-## return state, changed
-## # and make j the value of the selection var
-## if selvar.determine(j, dstore=dstore,
-## constraint=(verbosity>1 or selvar in
tracevar) and self):
-## changed.add(selvar)
-## return state, changed
-##
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-##
-## return state, changed
-##
-##class OneSelection(IntSelection):
-## """Select one of seq vars for main var."""
-##
-## def __init__(self, mainvar, seqvars, problem=None, weight=1):
-## selvar = IVar(
mainvar.name + ':choice',
set(range(len(seqvars))), problem=problem,
-## rootDS=problem.dstore if problem else None)
-## IntSelection.__init__(self, mainvar, selvar, seqvars,
problem=problem, weight=weight)
-##
-##class IntIntSelection(Selection):
-## """Selection constraint with integer variables as selection variable
and main
-## variable and determined int variables as seq variables."""
-##
-## def __init__(self, mainvar=None, selvar=None, seqvars=None,
problem=None, weight=1,
-## maxset=None):
-## Selection.__init__(self, mainvar=mainvar, selvar=selvar,
seqvars=seqvars,
-## problem=problem, weight=weight)
-## self.maxset = maxset or ALL
-##
self.name = '{0} = {1} [{2}]'.format(self.mainvar,
self.format_seq(self.seqvars), self.selvar)
-##
-## def fails(self, dstore=None):
-## """Fail if the domain of sel var includes only indices that are
beyond the
-## length of seq vars, of if the domain of sel var is empty."""
-## selvar = self.selvar
-## sel_domain = selvar.get_domain(dstore=dstore)
-## if not sel_domain or min(sel_domain) >= len(self.seqvars):
-## return True
-## elif selvar.determined(dstore=dstore, constraint=self) is not
False:
-## # If the selvar is determined, check the selected seq var
-## seqvar = self.seqvars[selvar.get_value(dstore=dstore)]
-## # The seqvar is determined too; see if it cannot be equal to
the mainvar
-## # This is true if the upper bound of mainvar fails to
contain values in seqvar's value
-## seqval = {seqvar.get_value(dstore=dstore)}
-## mainvar = self.mainvar
-## mainvar_domain = mainvar.get_domain(dstore=dstore)
-## if seqval - mainvar_domain:
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## seqvars = self.seqvars
-## selvar = self.selvar
-## mainvar = self.mainvar
-## changed = set()
-## state = Constraint.sleeping
-##
-## sel_infer = Selection.infer(self, dstore=dstore,
verbosity=verbosity, tracevar=tracevar)
-## if sel_infer:
-## return sel_infer
-##
-## if selvar.determined(dstore=dstore, verbosity=verbosity,
constraint=self) is not False:
-## # The selection var is determined
-##
-## # index of selected seq var
-## selval = selvar.get_value(dstore=dstore)
-## # selected seq var
-## sel_seqvar = seqvars[selval]
-##
-## selseq_value = sel_seqvar.get_value(dstore=dstore)
-## if mainvar.determine(selseq_value, dstore=dstore,
-## constraint=(verbosity>1 or mainvar in
tracevar) and self):
-## changed.add(mainvar)
-## state = Constraint.entailed
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-## return state, changed
-##
-## sel_domain = selvar.get_domain(dstore=dstore)
-##
-## # The main variable must be a subset of the union of the values
of all
-## # sequence variables indexed by the elements in the domain of
the selection variable;
-## # that is, eliminate any elements from the domain that are not
in this union
-## seq_vals = {seqvars[j].get_value(dstore=dstore) for j in
sel_domain}
-## if mainvar.strengthen(seq_vals, dstore=dstore,
-## constraint=(verbosity>1 or mainvar in
tracevar) and self):
-## changed.add(mainvar)
-## return state, changed
-##
-## # If the lower bound of some seqvar is not a subset of mainvar's
upper bound,
-## # or the upper bound of the seqvar is not a superset of
mainvar's lower bound,
-## # then exclude its index from selection var's domain
-## for j in sel_domain.copy():
-## seqvar = seqvars[j]
-## if seqvar.get_value(dstore=dstore) not in
mainvar.get_domain(dstore=dstore):
-## # mainvar cannot equal seqvar, so remove j from selvar's
domain
-## if selvar.discard_value(j, dstore=dstore,
-## constraint=(verbosity>1 or
selvar in tracevar) and self):
-## changed.add(selvar)
-## return state, changed
-##
-## if verbosity > 1 and changed:
-## print(' Variables {} changed'.format(changed))
-##
-## return state, changed
-
class UnionSelection(Selection):
'''All variables can be set vars; seq vars can also be int vars.
Select the union of the selected sets.'''
@@ -2011,130 +1438,6 @@
# Create an AgrSelection constraint for this agr selection
variable
self.constraints.append(AgrSelection(featvars, sel,
seqvars, record=False, weight=1))
-##class SimplePrecedenceSelection(Constraint):
-## """
-## Simpler than PrecedenceSelection.
-## posvars: set vars consisting of int positions
-## selvar: a set var consisting of indices within posvars, whose values
must appear
-## in the order they appear in in posvars
-## """
-##
-## def __init__(self, selvar=None, posvars=None, problem=None,
-## weight=1, maxset=None):
-## Constraint.__init__(self, [selvar] + posvars, problem=problem,
-## weight=weight)
-## self.selvar = selvar
-## self.posvars = posvars
-## self.maxset = maxset or ALL
-##
self.name = '<...< {}
[{}]'.format(Selection.format_seq(self.posvars), self.selvar)
-##
-## def get_upper_posvars(self, dstore=None):
-## """All posvars included in the upper bound of the selvar."""
-## selupper = self.selvar.get_upper(dstore=dstore)
-## return [posvar for index, posvar in enumerate(self.posvars) if
index in selupper]
-##
-## def get_lower_posvars(self, dstore=None):
-## """All posvars included in the lower bound of the selvar."""
-## sellower = self.selvar.get_lower(dstore=dstore)
-## return [posvar for index, posvar in enumerate(self.posvars) if
index in sellower]
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if all variables are determined or
-## if all indices that *could* be included are already in the right
order.
-## """
-## if self.selvar.determined(dstore=dstore, constraint=self) is not
False \
-## and all([v.determined(dstore=dstore, constraint=self) is not
False for v in self.posvars]):
-## return True
-## upperposvars = self.get_upper_posvars(dstore=dstore)
-## for posvar1, posvar2 in itertools.combinations(upperposvars, 2):
-## if not SetPrecedence.must_precede(posvar1, posvar2,
dstore=dstore):
-## return False
-## return True
-##
-## def fails(self, dstore=None):
-## """Fail if the lower bound of selvar includes position variables
-## that necessarily violate the precedence constraint."""
-## lowerposvars = self.get_lower_posvars(dstore=dstore)
-## for posvar1, posvar2 in itertools.combinations(lowerposvars, 2):
-## if SetPrecedence.cant_precede(posvar1, posvar2,
dstore=dstore):
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## state = Constraint.sleeping
-##
-## ## Constrain the selection variable based on the position
variables.
-## # For each index in the sel var's upper bound, check to see
whether
-## # the possible precedence constraints can't succeed
-## discard_selup = set()
-## strengthen_sellow = set()
-## selupper = self.selvar.get_upper(dstore=dstore)
-## sellower = self.selvar.get_lower(dstore=dstore)
-## upper_i_var = [(index, self.posvars[index]) for index in
selupper]
-## lower_i_var = [(index, self.posvars[index]) for index in
sellower]
-## for index1, posvar1 in upper_i_var:
-## for index2, posvar2 in lower_i_var:
-## if index1 < index2:
-## if SetPrecedence.cant_precede(posvar1, posvar2,
dstore=dstore):
-## discard_selup.add(index1)
-## elif index1 > index2:
-## if SetPrecedence.cant_precede(posvar2, posvar1,
dstore=dstore):
-## discard_selup.add(index1)
-## if discard_selup:
-## if self.selvar.discard_upper(discard_selup, dstore=dstore,
-## constraint=(verbosity>1 or
self.selvar in tracevar) and self):
-## changed.add(self.selvar)
-## return state, changed
-##
-## ## Constrain the position variables based on the selection
variable.
-## # For each pair of indices in the sel var's lower bound, check
to see
-## # whether indices can be excluded from the upper bounds of the
corresponding
-## # position variables.
-## lowerposvars = self.get_lower_posvars(dstore=dstore)
-## for index, v1 in enumerate(lowerposvars[:-1]):
-## for v2 in lowerposvars[index+1:]:
-## v1_low = v1.get_lower(dstore=dstore)
-## v2_low = v2.get_lower(dstore=dstore)
-## v1_up = v1.get_upper(dstore=dstore)
-## v2_up = v2.get_upper(dstore=dstore)
-##
-## # If the lower bound on v1 is not empty, v2 must be a
subset of
-## # {min(MAX, max(v1 + 1)), ..., MAX}
-## if v1_low and v1_up and v2_up:
-## v2_up_new = range(min([max(v1_up), max(v1_low) +
1]), max(v2_up)+1)
-## if v2.strengthen_upper(v2_up_new, dstore=dstore,
-## constraint=(verbosity>1 or v2
in tracevar) and self):
-## changed.add(v2)
-## return state, changed
-## # If the lower bound on v2 is not empty, v1 must be a
subset of
-## # {0, ..., max(0, min(v2_low) - 1)}
-## if v2_low:
-## v1_up_new = range(0, max([0, min(v2_low) - 1]) + 1)
-## if v1.strengthen_upper(v1_up_new, dstore=dstore,
-## constraint=(verbosity>1 or v1
in tracevar) and self):
-## changed.add(v1)
-## return state, changed
-## v1_up = v1.get_upper(dstore=dstore)
-## v2_up = v2.get_upper(dstore=dstore)
-## if v1_up and v2_up and v1.get_lower_card(dstore=dstore)
and v2.get_lower_card(dstore=dstore):
-## # Eliminate elements of v1 upper that are >= max of
v2 upper
-## lowenough1 = {x for x in v1_up if x < max(v2_up)}
-## if v1.strengthen_upper(lowenough1, dstore=dstore,
-## constraint=(verbosity>1 or v1
in tracevar) and self):
-## changed.add(v1)
-## return state, changed
-## # Eliminate elements of v2 upper that are <= min of
v1 upper
-## # (v1_up might have changed and might now be empty)
-## v1_up = v1.get_upper(dstore=dstore)
-## if v1_up:
-## highenough2 = {x for x in v2_up if x >
min(v1_up)}
-## if v2.strengthen_upper(highenough2,
dstore=dstore,
-## constraint=(verbosity>1
or v2 in tracevar) and self):
-## changed.add(v2)
-## return state, changed
-## return state, changed
-
class PrecedenceSelection(Constraint):
"""
PrecedenceSelection is different enough from UnionSelection and
IntersectionSelection
@@ -2261,207 +1564,6 @@
return state, changed
return state, changed
-##class EqualitySelection(Constraint):
-## """Elements of main var list are constrained to be equal to elements
of seq vars.
-## Selection var is a set of pairs: (main_var_index, seq_var_index)
-##
-## mainvars: list of IVars
-## seqvars: SVars or IVars
-## selvar: SVar of (int, int) tuples
-## """
-##
-## def __init__(self, mainvars=None, selvar=None, seqvars=None,
-## problem=None, weight=1,
-## maxset=None, agr_maps=None, rev_agr_maps=None):
-## Constraint.__init__(self, mainvars + [selvar] + seqvars,
problem=problem,
-## weight=weight)
-## self.mainvars = mainvars
-## self.selvar = selvar
-## self.seqvars = seqvars
-## # Maximum set of tuples for the particular problem
-## self.maxset = maxset or ALL
-## # Dictionary for use in CrossAgreement, mapping feature values
between languages
-## self.agr_maps = agr_maps
-## self.rev_agr_maps = rev_agr_maps
-##
self.name = '{} = {}
[{}]'.format(Selection.format_list(self.mainvars),
-##
Selection.format_seq(self.seqvars),
-## self.selvar)
-### print('Created ES constraint {}'.format(
self.name))
-### if self.agr_maps:
-### print('Agr maps: {}'.format(self.agr_maps))
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if all variables are determined or
-## if all pairs of indices that *could* be included correspond to
-## constraints that are already satisfied.
-## """
-## if self.selvar.determined(dstore=dstore, constraint=self) is not
False \
-## and all([v.determined(dstore=dstore, constraint=self) is not
False for v in self.mainvars]) \
-## and all([v.determined(dstore=dstore, constraint=self) is not
False for v in self.seqvars]):
-## return True
-## selupper = self.selvar.get_upper(dstore=dstore)
-## for mainindex, seqindex in selupper:
-## mainvar = self.mainvars[mainindex]
-## seqvar = self.seqvars[seqindex]
-## # Are mainvar and seqvar not already equal?
-## if not mainvar.equals(seqvar, dstore=dstore):
-## return False
-## return True
-##
-## def get_mapped_feats(self, src_feats, indices, rev=False):
-## map = None
-## agr_maps = self.rev_agr_maps if rev else self.agr_maps
-## for feats, m in agr_maps:
-## if indices == feats:
-## map = m
-## break
-## res = set()
-## if not map:
-### print('No mapping found for {} | {}'.format(src_feats,
indices))
-## return res
-## for sfeat in src_feats:
-## m = set()
-## for msfeat, mtfeats in map:
-## if sfeat == msfeat:
-## m.update(mtfeats)
-## if m:
-## res.update(m)
-## else:
-## # no explicit mapping; just copy the source feature
-## res.add(sfeat)
-### print('Mapped feats for {}: {}'.format(src_feats, res))
-## return res
-##
-## def fails(self, dstore=None):
-## """Fail if the lower bound of selvar includes at least one
representing an equivalence
-## that can't hold."""
-## sellower = self.selvar.get_lower(dstore=dstore)
-## for mainindex, seqindex in sellower:
-## mainvar = self.mainvars[mainindex]
-## seqvar = self.seqvars[seqindex]
-## mapped = None
-## agr_map = self.agr_maps
-## if agr_map:
-## mapped =
self.get_mapped_feats(seqvar.get_upper(dstore=dstore), (seqindex,
mainindex))
-## if mainvar.cant_equal(seqvar, dstore=dstore, mapped=mapped):
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## state = Constraint.sleeping
-##
-## selvar = self.selvar
-## mainvars = self.mainvars
-## seqvars = self.seqvars
-##
-## ## Constrain the selection variable
-## sel_discard = set()
-## for mainindex, seqindex in selvar.get_upper(dstore=dstore):
-## # For each mainvar and seqvar indexed in sel var's upper
bound,
-## # check to see if they can't be equal
-## mapped = None
-## agr_map = self.agr_maps
-## seqvar = seqvars[seqindex]
-## if agr_map:
-## mapped =
self.get_mapped_feats(seqvar.get_upper(dstore=dstore), (seqindex,
mainindex))
-## if mainvars[mainindex].cant_equal(seqvar, dstore=dstore,
mapped=mapped):
-## sel_discard.add((mainindex, seqindex))
-## if selvar.discard_upper(sel_discard, dstore=dstore,
-## constraint=(verbosity>1 or selvar in
tracevar) and self):
-## changed.add(selvar)
-##
-## ## Constrain the main and/or seq variables
-## for mainindex, seqindex in selvar.get_lower(dstore=dstore):
-## # For each mainvar and seqvar indexed in sel var's lower
bound,
-## # attempt to equate them
-## mainvar = mainvars[mainindex]
-## seqvar = seqvars[seqindex]
-## mapped = None
-## rev_mapped = None
-## agr_map = self.agr_maps
-## seqvar = seqvars[seqindex]
-## if agr_map:
-## mapped =
self.get_mapped_feats(seqvar.get_upper(dstore=dstore), (seqindex,
mainindex))
-## rev_mapped =
self.get_mapped_feats(seqvar.get_upper(dstore=dstore), (mainindex,
seqindex), True)
-## if mainvar.equate(seqvar, dstore=dstore, mapped=mapped,
-## constraint=(verbosity>1 or mainvar in
tracevar) and self):
-## changed.add(mainvar)
-## if seqvar.equate(mainvar, dstore=dstore, mapped=rev_mapped,
-## constraint=(verbosity>1 or seqvar in
tracevar) and self):
-### print('Changed seqvar', seqvar)
-### if mapped:
-### print(' mapped', mapped, 'mainvar',
mainvar, 'seqvar', seqvar)
-### print(' revmapped', rev_mapped, 'mainvar',
mainvar, 'seqvar', seqvar)
-## changed.add(seqvar)
-##
-## return state, changed
-##
-##class SimpleEqualitySelection(Constraint):
-## """Selection var is a set of pairs: (seq_var_index, value), where
value is a
-## tuple of ints. For each indexed seq var in the selection var, the
value
-## is a set, either the empty set or a single tuple of ints. This value
must
-## match the value specified in the selection var or be empty."""
-##
-## def __init__(self, selvar=None, seqvars=None,
-## problem=None, weight=1,
-## maxset=None):
-## Constraint.__init__(self, [selvar] + seqvars, problem=problem,
-## weight=weight)
-## self.selvar = selvar
-## self.seqvars = seqvars
-## self.maxset = maxset or ALL
-##
self.name = '= {}
[{}]'.format(Selection.format_seq(self.seqvars), self.selvar)
-##
-## def is_entailed(self, dstore=None):
-## """Entailed if all variables are determined."""
-## if self.selvar.determined(dstore=dstore, constraint=self) is not
False \
-## and all([v.determined(dstore=dstore, constraint=self) is not
False for v in self.seqvars]):
-## return True
-## return False
-##
-## def fails(self, dstore=None):
-## """Fail if the lower bound of selvar includes at least one
representing an equivalence
-## that can't hold."""
-## sellower = self.selvar.get_lower(dstore=dstore)
-## for seqindex, value in sellower:
-## seqvar = self.seqvars[seqindex]
-### print('Cant equal value?', seqvar, value)
-## if seqvar.cant_equal_value(value, dstore=dstore):
-## return True
-## return False
-##
-## def infer(self, dstore=None, verbosity=0, tracevar=None):
-## changed = set()
-## state = Constraint.sleeping
-##
-## selvar = self.selvar
-## seqvars = self.seqvars
-##
-## ## Constrain the selection variable
-## sel_discard = set()
-## for seqindex, value in selvar.get_upper(dstore=dstore):
-## # For each seqvar indexed in sel var's upper bound,
-## # check to see if the value is possible
-## if seqvars[seqindex].cant_equal_value(value, dstore=dstore):
-## sel_discard.add((seqindex, value))
-## if selvar.discard_upper(sel_discard, dstore=dstore,
-## constraint=(verbosity>1 or selvar in
tracevar) and self):
-## changed.add(selvar)
-##
-## ## Constrain seq variables
-## for seqindex, value in selvar.get_lower(dstore=dstore):
-## # For each seqvar indexed in sel var's lower bound,
-## # attempt to equate it with value
-## seqvar = seqvars[seqindex]
-## # value may be an integer or tuple
-## if not isinstance(value, set):
-## value = {value}
-## seqvar.strengthen_upper(value, dstore=dstore,
-## constraint=(verbosity>1 or seqvar in
tracevar) and self)
-##
-## return state, changed
-
### Constraints derived from other Constraints
class DerivedConstraint:
@@ -2483,16 +1585,6 @@
for c in self.constraints:
c.weight = weight
-#class IntEquality(DerivedConstraint):
-# """IVar equality:
-# I1 <= I2 and I2 <= I1.
-# """
-# def init_constraints(self):
-# self.constraints = [LessThan(self.variables, problem=self.problem,
-# weight=self.weight),
-# LessThan(list(reversed(self.variables)),
problem=self.problem,
-# weight=self.weight)]
-
class Inclusion(DerivedConstraint):
"""Set inclusion:
S1 c= S2: S1 c= S2 U S3 and S3 c= 0
@@ -2503,19 +1595,6 @@
self.constraints = [SubsetUnion(self.variables + [sv3],
problem=self.problem,
weight=self.weight,
record=self.record)]
-##class Equality(DerivedConstraint):
-## """Set equality:
-## S1 c= S2 and S2 c= S1.
-## """
-##
-## def init_constraints(self):
-## sv3 = EMPTY
-## rev_vars = list(reversed(self.variables))
-## self.constraints = [SubsetUnion(self.variables + [sv3],
problem=self.problem, propagate=self.propagate,
-## weight=self.weight),
-## SubsetUnion(rev_vars + [sv3],
problem=self.problem, propagate=self.propagate,
-## weight=self.weight)]
-
class Disjoint(DerivedConstraint):
"""S1 || S2 || S3...: 0 >= S1 ^ S2 and 0 >= S1 ^ S3 and 0 >= S2 ^ S3...
The variables must not share any elements.
=======================================
--- /hiiktuu/entry.py Fri May 9 22:41:32 2014 UTC
+++ /hiiktuu/entry.py Mon May 19 06:57:46 2014 UTC
@@ -59,8 +59,8 @@
from .features import *
-LEXEME_PRE = '%'
-CLASS_PRE = '$'
+LEXEME_CHAR = '_'
+CAT_CHAR = '$'
class Entry:
"""Superclass for Group and possibly other lexical classes."""
@@ -87,7 +87,12 @@
@staticmethod
def is_cat(name):
"""Is this the name of a category?"""
- return name[0] == CLASS_PRE
+ return CAT_CHAR in name
+
+ @staticmethod
+ def is_lexeme(name):
+ """Is this the name of a lexeme?"""
+ return LEXEME_CHAR in name
## Serialization
@@ -693,7 +698,7 @@
# fv = ['{}={}'.format(f, v) for f, v in feat_dict.items()]
# fv = ','.join(fv)
# strings.append("{}:{}".format(form, fv))
- return '_'.join(tokens)
+ return '.'.join(tokens)
# Serialization
=======================================
--- /hiiktuu/features.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/features.py Mon May 19 06:57:46 2014 UTC
@@ -32,6 +32,9 @@
# Copying of agreement features: agree:().
# 2014.05.05
# -- More methods for agreement, needed in AgrSelection constraint.
+# 2014.05.18
+# -- mutual_agree() makes two Features agree with one another on
+# feature pairs.
class Features(dict):
@@ -121,6 +124,22 @@
else:
target[targ_feat] = src_value
+ def mutual_agree(self, target, agrs):
+ """Make target agree with self and self agree with target
+ on features specified in agrs dict or list of pairs."""
+ agr_pairs = agrs.items() if isinstance(agrs, dict) else agrs
+ for src_feat, targ_feat in agr_pairs:
+ if src_feat in self:
+ src_value = self[src_feat]
+ if targ_feat in target and target[targ_feat] != src_value:
+ # Clash; fail!
+ return 'fail'
+ else:
+ target[targ_feat] = src_value
+ elif targ_feat in target:
+ targ_value = target[targ_feat]
+ self[src_feat] = targ_value
+
def agrees(self, target, agrs):
"""Does target agree with self on features specified in agrs dict
or list of pairs?"""
agr_pairs = agrs.items() if isinstance(agrs, dict) else agrs
=======================================
--- /hiiktuu/language.py Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/language.py Mon May 19 06:57:46 2014 UTC
@@ -384,12 +384,16 @@
def generate(self, root, features, verbosity=0):
if verbosity:
print("Generating {}:{}".format(root, features))
+ if root not in self.genforms:
+ return [root]
if not features:
- # Just return the "root"
- return [root]
- if root not in self.genforms:
- print("Impossible to generate root {}".format(root))
- return
+ features = Features({})
+# if not features:
+# # Just return the "root"
+# return [root]
+# if root not in self.genforms:
+# print("Impossible to generate root {}".format(root))
+# return
gendict = self.genforms[root]
# List of matching forms
result = []
=======================================
--- /hiiktuu/languages/amh.lg Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/languages/amh.lg Mon May 19 06:57:46 2014 UTC
@@ -1,64 +1,64 @@
name: አማርኛ
abbrev: amh
groups:
- በላ:
- - words: [$food, በላ]
+ በላ_:
+ - words: [$food, በላ_]
features: [{case: acc}, False]
trans:
orm:
- - [$food_nyaate,
+ - [$food.nyaate_,
{align: [0, 1],
agr: [false, {sp: prs, sn: num, sg: gen}]}]
- አወቀ:
- - words: [$vb, አወቀ]
+ አወቀ_:
+ - words: [$vb, አወቀ_]
features: [{tam: ger}, {tam: imf, pol: neg}]
agr: [[0, 1, [sp, sp], [sn, sn], [sg, sg]]]
- name: ^አድርጎ^አያውቅም
+ name: ^አድርጎ.^አያውቅም
trans:
orm:
- - [^godhe_hin^beeku,
+ - [^godhe.hin^beeku,
{align: [0, 2],
agr: [{sp: prs, sn: num, sg: gen},
{sp: prs, sn: num, sg: gen}]}]
- - words: [$fact, አወቀ]
+ - words: [$fact, አወቀ_]
trans:
orm:
- - [$fact_beeke,
+ - [$fact.beeke_,
{align: [0, 1],
agr: [False, {sp: prs, sn: num, sg: gen}]}]
- አሳ:
- - words: [አሳ]
+ አሳ_:
+ - words: [አሳ_]
trans:
orm:
- - [qurxummii]
- - [kalluuna]
+ - [qurxummii_]
+ - [kalluuna_]
forms:
ያውቃል:
- root: አወቀ
+ root: አወቀ_
features: {tam: imf, pol: aff, sp: 3, sn: 0, sg: 0}
cats: [$vb]
አያውቅም:
- root: አወቀ
+ root: አወቀ_
features: {tam: imf, pol: neg, sp: 3, sn: 0, sg: 0}
cats: [$vb]
በልቶ:
- root: በላ
+ root: በላ_
features: {tam: ger, sp: 3, sn: 0, sg: 0}
cats: [$vb]
በልተው:
- root: በላ
+ root: በላ_
features: {tam: ger, sp: 3, sn: 1}
cats: [$vb]
በላ:
- root: በላ
+ root: በላ_
features: {tam: prf, sp: 3, sn: 0, sg: 0}
cats: [$vb]
ድንች:
- root: ድንች
+ root: ድንች_
features: {num: 0, poss: 0, def: 0}
cats: [$food, $thing]
አሳ:
- root: አሳ
+ root: አሳ_
features: {num: 0, poss: 0, def: 0}
cats: [$food, $animal, $thing]
=======================================
--- /hiiktuu/languages/eng.lg Wed May 14 07:28:54 2014 UTC
+++ /hiiktuu/languages/eng.lg Mon May 19 06:57:46 2014 UTC
@@ -12,53 +12,67 @@
- root: end_v
features: {tns: prs, per: 3, num: 1}
boy:
- root: boy
+ root: boy_
features: {num: 0, prs: 3}
cats: [$sbd]
act:
- root: act
+ root: act_
features: {num: 0, prs: 3}
cats: [$sth]
us:
- root: we
+ root: we_
features: {num: 1, prs: 1, case: 1}
cats: [$sbd]
them:
- root: they
+ root: they_
features: {num: 1, prs: 3, case: 1}
+ cats: [$sbd]
song:
- root: song
+ root: song_
features: {num: 0, prs: 3}
cats: [$singable]
sang:
- root: sing
+ root: sing_
features: {tns: prt}
+ gave:
+ root: give_
+ features: {tns: prt}
+ gives:
+ root: give_
+ features: {tns: prs, num: 0, prs: 3}
read:
- root: read
+ root: read_
features: {tns: prt}
kicked:
root: kick_v
features: {tns: prt}
bucket:
- root: bucket
+ root: bucket_
features: {num: 0, prs: 3}
cats: [$sth, $concrete]
+ my:
+ root: possadj_
+ features: {num: 0, prs: 1}
+ cats: [$sbds]
+ her:
+ root: possadj_
+ features: {num: 0, prs: 3, gen: 1}
+ cats: [$sbds]
+ his:
+ root: possadj_
+ features: {num: 0, prs: 3, gen: 0}
+ cats: [$sbds]
groups:
kick_v:
- words: [kick_v, the, bucket]
trans:
spa:
- - [estirar_la_pata, {align: [0, 1, 2], agr: [{tns: tmp}, false,
false]}]
+ - [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]}]
+ - [patear_.$concreto, {align: [0, 1], agr: [{tns: tmp}, false]}]
"it's":
- words: ["it's"]
trans:
@@ -68,20 +82,43 @@
- words: [the, end, of, the, world]
trans:
spa:
- - [el_fin_del_mundo,
+ - [el.fin.del.mundo,
align: [0, 1, 2, -1, 3]]
- read:
- - words: [read, $sbd, the, riot, act]
- - words: [read, $sth]
- give:
- - words: [give, $sbd, a, piece, of, $ones, mind]
- sing:
- - words: [sing, $singable]
+ read_:
+ - words: [read_, $sbd, the, riot, act]
+ - words: [read_, $sth]
+ give_:
+ - words: [give_, $sbd, a, piece, of, possadj_, mind]
+ agr: [[0, 5, [num, num], [prs, prs]]]
+ trans:
+ spa:
+ - [$algnp.cantar_.las.cuarenta,
+ {align: [1, 0, 2, 3, -1, -1, -1],
+ agr: [{tns: tmp, num: num, prs: prs}, false, false, false,
false, false, false]}]
+ sing_:
+ - words: [sing_, $singable]
boy:
- words: [the, boy]
us:
- words: [us]
them:
- words: [them]
+ trans:
+ spa:
+ - [les, {align: [0]}]
+ her:
+ - words: [her]
+ trans:
+ spa:
+ - [su, {align: [0]}]
+ my:
+ - words: [my]
+ his:
+ - words: [his]
song:
- words: [a, song]
+ bucket:
+ - words: [the, bucket]
+ trans:
+ spa:
+ - [el.balde, {align: [0, 1]}]
=======================================
--- /hiiktuu/languages/orm.lg Tue May 6 07:09:41 2014 UTC
+++ /hiiktuu/languages/orm.lg Mon May 19 06:57:46 2014 UTC
@@ -1,44 +1,44 @@
name: afaan oromoo
abbrev: orm
groups:
- nyaate:
- - words: [$food, nyaate]
+ nyaate_:
+ - words: [$food, nyaate_]
features: [{case: acc}, False]
- beeke:
- - words: [$vb, hin, beeke]
+ beeke_:
+ - words: [$vb, hin, beeke_]
features: [{tam: cnt}, false, {tam: prs, pol: neg}]
- name: ^godhe_hin^beeku
+ name: ^godhe.hin^beeku
- words: [$fact, beeke]
- qurxummii:
- - words: [qurxummii]
- kalluuna:
- - words: [kalluuna]
+ qurxummii_:
+ - words: [qurxummii_]
+ kalluuna_:
+ - words: [kalluuna_]
forms:
beeka:
- root: beeke
+ root: beeke_
features: {tam: prs, pol: aff, prs: 3, num: 0, gen: 0}
cats: [$vb]
beeku:
- root: beeke
+ root: beeke_
features: {tam: prs, pol: neg, prs: 3, num: 0, gen: 0}
cats: [$vb]
nyaate:
- root: nyaate
+ root: nyaate_
features: {tam: cnt, prs: 3, num: 0, gen: 0}
cats: [$vb]
nyaatani:
- root: nyaate
+ root: nyaate_
features: {tam: cnt, prs: 3, num: 1}
cats: [$vb]
dinnicha:
- root: dinnicha
+ root: dinnicha_
features: {num: 0, case: acc}
cats: [$food, $thing]
qurxummii:
- root: qurxummii
+ root: qurxummii_
features: {num: 0, case: acc}
cats: [$food, $animal, $thing]
kalluuna:
- root: kalluuna
+ root: kalluuna_
features: {num: 0, case: acc}
cats: [$food, $animal, $thing]
=======================================
--- /hiiktuu/languages/spa.lg Fri May 9 22:41:32 2014 UTC
+++ /hiiktuu/languages/spa.lg Mon May 19 06:57:46 2014 UTC
@@ -2,34 +2,37 @@
abbrev: spa
groups:
- patear:
- - words: [patear, $concreto]
- estirar:
- - words: [estirar, la, pata]
+ patear_:
+ - words: [patear_, $concreto]
+ estirar_:
+ - words: [estirar_, la, pata]
es:
- words: [es]
fin:
- words: [el, fin, del, mundo]
- cantar:
+ cantar_:
# cantar las cuarenta (with pronoun indirect object)
- - words: [$algnp, cantar, las, cuarenta]
+ - words: [$algnp, cantar_, las, cuarenta]
trans:
eng:
- - [read_$sbd_the_riot_act,
+ - [read_.$sbd.the.riot.act,
+ {align: [1, 0, 2, 3],
+ agr: [false, {tmp: tns, num: num, prs: prs}, false, false]}]
+ - [give_.$sbd.a.piece.of.possadj_.mind,
{align: [1, 0, 2, 3],
agr: [false, {tmp: tns, num: num, prs: prs}, false, false]}]
# cantar (una canción)
- - words: [cantar, $cantable]
+ - words: [cantar_, $cantable]
trans:
eng:
- - [sing_$singable,
+ - [sing_.$singable,
{align: [0, 1],
agr: [{tmp: tns, num: num, prs: prs}, false]}]
canción:
- words: [una, canción]
trans:
eng:
- - [a_song, {align: [0, 1]}]
+ - [a.song, {align: [0, 1]}]
canciones:
- words: [canciones]
les:
@@ -37,11 +40,15 @@
trans:
eng:
- [them]
+ su:
+ - words: [su]
+ adjpos_:
+ - words: [adjpos_]
muchacho:
- words: [el, muchacho]
trans:
eng:
- - [the_boy, {align: [0, 1]}]
+ - [the.boy, {align: [0, 1]}]
balde:
- words: [el, balde]
@@ -51,17 +58,17 @@
features: {num: 0, prs: 3, gen: 0}
cats: [$algo, $concreto]
pateó:
- root: patear
+ root: patear_
features: {num: 0, prs: 3, tmp: prt}
estiró:
- root: estirar
+ root: estirar_
features: {num: 0, prs: 3, tmp: prt}
canción:
- root: canción
+ root: canción_
features: {num: 0, prs: 3}
cats: [$cantable, $algo]
canciones:
- root: canción
+ root: canción_
features: {num: 1, prs: 3}
cats: [$cantable, $algo]
les:
@@ -71,14 +78,29 @@
nos:
root: nosotros
features: {num: 1, prs: 1, case: i}
+ su:
+ root: adjpos_
+ features: {prs: 3, modnum: 0}
+ sus:
+ root: adjpos_
+ features: {prs: 3, modnum: 1}
+ mi:
+ root: adjpos_
+ features: {prs: 1, num: 1, modnum: 0}
+ mis:
+ root: adjpos_
+ features: {prs: 1, num: 1, modnum: 1}
cantó:
- root: cantar
+ root: cantar_
features: {num: 0, prs: 3, tmp: prt}
canta:
- root: cantar
+ root: cantar_
features: {num: 0, prs: 3, tmp: prs}
+ canté:
+ root: cantar_
+ features: {num: 0, prs: 1, tmp: prt}
muchacho:
- root: muchacho
+ root: muchacho_
features: {num: 0, prs: 3, gen: 0}
cats: [$algn]
=======================================
--- /hiiktuu/sentence.py Fri May 16 07:05:16 2014 UTC
+++ /hiiktuu/sentence.py Mon May 19 06:57:46 2014 UTC
@@ -55,11 +55,15 @@
# end up empty when it should be.
# 2014.05.15
# -- Fixed how group trees are worked out: using the snode->gnodes
variables
-# rather than merger-related variables and tree variables
+# rather than merger-related variables and tree variables.
# -- Search in group selection and output ordering.
+# 2014.05.16
+# -- Fixed a bug in how SL snodes with no corresponding TL snodes are
+# handled during node merging.
+# 2014.05.18
+# -- Target-language within-group agreement ("GIVES them a piece of
HER/HIS mind")
import itertools, copy
-# ui.py loads language, etc.
from .ui import *
from .cs import *
@@ -69,6 +73,7 @@
parsing or translation."""
id = 0
+ word_width = 10
def __init__(self, raw='', language=None,
tokens=None, analyses=None,
@@ -116,22 +121,17 @@
else:
return '|| {} sentence {} ||'.format(self.language,
self.id)
-# def do(self, verbosity=0):
-# """If target language, translate. If not, parse."""
-# if self.target:
-# print("Attempting to translate sentence {}".format(self))
-# else:
-# print("Attempting to parse sentence {}".format(self))
-# if self.initialize(verbosity=verbosity):
-# if self.solve(verbosity=verbosity):
-# if self.target:
-# for solution in self.solutions:
-# solution.translate(verbosity=verbosity)
-# print("Translations found:")
-# for translation in solution.translations:
-# translation.display()
-# else:
-# print("No solution found")
+ def display(self, show_all_sols=True, show_trans=True,
+ word_width=0):
+ """Show the sentence and one or more solutions in terminal."""
+ s = " "
+ word_width = word_width or Sentence.word_width
+ for node in self.nodes:
+ s += "{}".format(node.token).center(word_width)
+ print(s)
+ solutions = self.solutions if show_all_sols else self.solutions[:1]
+ for solution in solutions:
+ solution.display(word_width=word_width)
def parse(self, verbosity=0):
print("Attempting to parse {}".format(self))
@@ -152,7 +152,7 @@
self.create_constraints(verbosity=verbosity)
return True
- def solve(self, verbosity=0):
+ def solve(self, translate=True, verbosity=0):
"""Generate solutions and translations."""
generator = self.solver.generator(test_verbosity=verbosity,
expand_verbosity=verbosity)
@@ -163,7 +163,8 @@
solution =
self.create_solution(dstore=succeeding_state.dstore, verbosity=verbosity)
if verbosity:
print('FOUND ANALYSIS', solution)
- solution.translate(verbosity=verbosity)
+ if translate:
+ solution.translate(verbosity=verbosity)
if not input('SEARCH FOR ANOTHER ANALYSIS? [yes/NO] '):
proceed = False
except StopIteration:
@@ -466,6 +467,9 @@
self.constraints.append(ComplexSetConvexity(self.variables['groups'],
[g.variables['tree']
for g in self.groups]))
# Agreement
+# print("snode variables")
+# for sn in self.nodes:
+# print(' {} variables: {}'.format(sn, sn.variables))
if any([g.variables.get('agr') for g in self.groups]):
self.constraints.append(ComplexAgrSelection(selvar=self.variables['groups'],
seqvars=[gn.variables['snodes'] for gn in self.gnodes],
@@ -586,7 +590,8 @@
self.variables['gnodes'] = EMPTY
self.variables['cgnodes'] = EMPTY
self.variables['agnodes'] = EMPTY
- self.variables['mgnodes'] = EMPTY
+# self.variables['mgnodes'] = EMPTY
+ self.variables['features'] = EMPTY
else:
# GNodes associated with this SNode: 0, 1, or 2
self.svar('gnodes', "w{}->gn".format(self.index), set(),
@@ -712,6 +717,25 @@
def __repr__(self):
return '<<{}:{}>>'.format(
self.group.name,
self.group.id)
+ def display(self, word_width=10, s2gnodes=None):
+ """Show group in terminal."""
+ s = '<{}>'.format(self.index)
+ n_index = 0
+ n = self.nodes[n_index]
+ ngnodes = len(self.nodes)
+ for gn_indices in s2gnodes:
+ if n.sent_index in gn_indices:
+ i = '*{}*' if n.head else "{}"
+ s += i.format(n.index).center(word_width)
+ n_index += 1
+ if n_index >= ngnodes:
+ break
+ else:
+ n = self.nodes[n_index]
+ else:
+ s += ' '*word_width
+ print(s)
+
def pos_pairs(self):
"""Return position constraint pairs for gnodes in the group."""
gnode_pos = [gn.sent_index for gn in self.nodes]
@@ -940,7 +964,9 @@
def generate(self, verbosity=0):
"""Generate forms for the TNode."""
- if self.features:
+ print("Generating form for target token {} and features
{}".format(self.token, self.features))
+ if Entry.is_lexeme(self.token):
+# if self.features:
return self.sentence.target.generate(self.token, self.features)
else:
return [self.token]
@@ -971,6 +997,11 @@
def __repr__(self):
return "|< {} >|({})".format(self.sentence.raw, self.index)
+ def display(self, word_width=10):
+ """Show solution groups (GInsts) in terminal."""
+ for g in self.ginsts:
+ g.display(word_width=word_width, s2gnodes=self.s2gnodes)
+
def translate(self, verbosity=0):
"""Do everything you need to create the translation."""
self.merge_nodes(verbosity=verbosity)
@@ -1028,12 +1059,12 @@
# Create GNode dict and list of target group, gnodes and tnodes
# from attributes
self.gnode_dict = {}
- self.groups_tnodes = []
+ self.group_attribs = []
for tgroup, tgnodes, tnodes, ginst in attribs:
# print('tgroup {}, tgnodes {}, tnodes {}, ginst
{}'.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, ginst))
+ self.group_attribs.append((tgroup, tnodes, ginst, tgroup.agr))
# form list / order constraint pairs for each sentence position
self.nodes = []
# Ordered units: merged groups or uncovered words
@@ -1054,7 +1085,11 @@
self.solver = Solver(self.constraints, self.dstore,
description='target realization',
verbosity=verbosity)
- # Final output; different ones have alternate word orders
+ # These are produced in self.build()
+ self.node_features = None
+ self.group_nodes = None
+ self.agreements = None
+ # Final outputs; different ones have alternate word orders
self.outputs = []
def __repr__(self):
@@ -1082,6 +1117,7 @@
if verbosity:
print("Initializing translation {}".format(self))
self.build(verbosity=verbosity)
+ self.generate_words(verbosity=verbosity)
self.set_chunks(verbosity=verbosity)
self.make_order_pairs(verbosity=verbosity)
self.create_variables(verbosity=verbosity)
@@ -1092,30 +1128,32 @@
generate surface target forms from resulting roots and features."""
if verbosity:
print('Building {}'.format(self))
- tginsts, tgnodes, trans_index = self.groups_tnodes,
self.gnode_dict, self.index
+ tginsts, tgnodes, trans_index = self.group_attribs,
self.gnode_dict, self.index
# print("Tginsts {}, tgnodes {}, trans_index {}".format(tginsts,
tgnodes, trans_index))
# Figure out the target forms for each snode
# print('tgnodes {}'.format(tgnodes))
# Dictionary mapping source node indices to initial target node
indices
tnode_index = 0
node_index_map = {}
+ node_features = []
+ agreements = {}
+ group_nodes = {}
for snode, (gnodes, features) in zip(self.sentence.nodes,
self.solution.snodes):
# print(" Snode {}, gnodes {}, features {}, tnode_index
{}".format(snode, gnodes, features, tnode_index))
if not gnodes:
# snode is not covered by any group
- self.nodes.append(([snode.token], []))
node_index_map[snode.index] = tnode_index
+ node_features.append((snode.token, None, []))
tnode_index += 1
else:
t_indices = []
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))
+ # Check with there is no translation for one or the
other; if so, skip this snode
+ if gnodes[0] not in tgnodes or gnodes[1] not in
tgnodes:
+# print("No translation for {}".format(snode))
+ continue
gn0, gn1 = tgnodes[gnodes[0]], tgnodes[gnodes[1]]
# print(" gn0 {}, gn1 {}".format(gn0, gn1))
tgroups, tokens, targ_feats, agrs, t_index = zip(gn0,
gn1)
@@ -1130,9 +1168,7 @@
targ_feats = Features.unify_all(targ_feats)
# Merge the agreements
agrs = Translation.combine_agrs(agrs)
-# if len(tgroups[0].tokens) > 1:
t_indices.append((tgroups[0], gn0[-1]))
-# if len(tgroups[1].tokens) > 1:
t_indices.append((tgroups[1], gn1[-1]))
## Record this node and its groups in mergers
tg = list(zip(tgroups, gnodes))
@@ -1151,7 +1187,7 @@
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))
+# print(' tgroup {}, token {}, t_index
{}'.format(tgroup, token, t_index))
# Make target and source features agree as required
if not targ_feats:
@@ -1159,14 +1195,13 @@
if agrs:
# print("Feature agree, targ feats {}, agrs
{}".format(targ_feats, agrs))
features.agree(targ_feats, agrs)
- # Generate target forms for this SNode
- gen = self.sentence.target.generate(token, targ_feats)
- if verbosity > 1:
- print(" Generating node form {}/{}: {}".format(token,
targ_feats, gen))
node_index_map[snode.index] = tnode_index
tnode_index += 1
- self.nodes.append((gen, t_indices))
+ node_features.append((token, targ_feats, t_indices))
+ for t_index in t_indices:
+ group_nodes[t_index] = (token, targ_feats)
# print("S->T index mapping {}".format(node_index_map))
+# print('Trees {}'.format(self.trees))
# Fix indices in tgroup trees
trees = []
for t in self.trees:
@@ -1179,17 +1214,44 @@
# print('Mapped tree indices {}'.format(self.trees))
# Add TNode elements
tgnode_elements = []
- for ginst_i, (tginst, tnodes, ginst) in enumerate(tginsts):
+ for ginst_i, (tginst, tnodes, ginst, agr) in enumerate(tginsts):
+ if agr:
+ agreements[tginst] = agr
if tnodes:
for tnode in tnodes:
- src_index = len(self.nodes)
+ features = tnode.features or Features({})
+ src_index = len(node_features)
# 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 = [(tginst, tnode.index)]
- self.nodes.append((forms, index))
+ node_features.append((tnode.token, features, index))
+ group_nodes[index[0]] = (tnode.token, features)
+# if agreements:
+# print("Agreements {}".format(agreements))
+# print("Node features: {}".format(node_features))
+ self.node_features = node_features
+ self.group_nodes = group_nodes
+ self.agreements = agreements
+
+ def generate_words(self, verbosity=0):
+ """Do inter-group agreement constraints, and generate wordforms
for each target node."""
+ for group, agr_constraints in self.agreements.items():
+ for agr_constraint in agr_constraints:
+ i1, i2 = agr_constraint[0], agr_constraint[1]
+ feature_pairs = agr_constraint[2:]
+ # Find the sentence nodes for the agreeing group nodes in
the group_nodes dict
+ agr_node1 = self.group_nodes[(group, i1)]
+ agr_node2 = self.group_nodes[(group, i2)]
+# print("Found node1 {} and node2 {} for constraint
{}".format(agr_node1, agr_node2, feature_pairs))
+ agr_feats1, agr_feats2 = agr_node1[1], agr_node2[1]
+ agr_feats1.mutual_agree(agr_feats2, feature_pairs)
+ generator = self.sentence.target.generate
+ for token, features, index in self.node_features:
+# print("Token {}, features {}".format(token, features))
+ output = generator(token, features)
+ self.nodes.append((output, index))
+ if verbosity:
+ print("Generating target node {}: {}".format(index,
output))
def set_chunks(self, verbosity=0):
"""Find output chunks: a list of sets of snode indices."""
@@ -1288,6 +1350,7 @@
for o in foll_outer:
for i in other_inner:
self.order_pairs.append([i, o])
+# print('Order pairs: {}'.format(self.order_pairs))
def svar(self, name, lower, upper, lower_card=0, upper_card=MAX,
ess=True):
@@ -1303,6 +1366,7 @@
self.variables['tree_sindices'] = []
self.variables['trees'] = []
for i, t in enumerate(self.trees):
+# print('Tree {}: {}'.format(i, t))
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)))
@@ -1349,7 +1413,7 @@
if display:
self.display(len(self.outputs)-1)
if verbosity:
- print('FOUND REALIZATION {}'.format(self.output[-1]))
+ print('FOUND REALIZATION {}'.format(self.outputs[-1]))
if not input('SEARCH FOR ANOTHER REALIZATION FOR
TRANSLATION? [yes/NO] '):
proceed = False
except StopIteration:
=======================================
--- /paperdrafts/lglp/lglp14.pdf Fri May 16 19:51:18 2014 UTC
+++ /paperdrafts/lglp/lglp14.pdf Mon May 19 06:57:46 2014 UTC
Binary file, no diff available.
=======================================
--- /paperdrafts/lglp/lglp14.tex Fri May 16 19:51:18 2014 UTC
+++ /paperdrafts/lglp/lglp14.tex Mon May 19 06:57:46 2014 UTC
@@ -310,7 +310,7 @@
groups:
giveV:
- words: [giveV, $sbd, a, piece, of, $sbds, mind]
- agr: [[2, 6, {prs: prs, num: num}]]
+ agr: [[1, 6, {prs: prs, num: num}]]
my:
- words: [my]
mayor:
@@ -346,7 +346,7 @@
Since the group contains no subject, we constrain it to agree with the
person and number
of the verb.
Thus the entry for this group also contains an agreement attribute
specifying that
-the the sixth element must agree with the second on person and number
features.
+the the sixth element must agree with the first on person and number
features.
\section{Constraint satisfaction and translation}
\label{sect:cs}