Skip to content

Commit

Permalink
Merge pull request #972 from ampli/sat-long-chain
Browse files Browse the repository at this point in the history
sat-solver: Fix to handle long expression chains
  • Loading branch information
linas authored Jul 17, 2019
2 parents 7609bd2 + 110d1a1 commit c98b712
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
7 changes: 7 additions & 0 deletions bindings/python-examples/parses-sat-en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ C(S (NP this.p)
C (VP is.v
C (NP a test.n)))
C

% This sentence should not have a complete linkage (fixed in issue #972).
% (If the SAT parser is fixed to produce incomplete linkages, include
% the incomplete linkage here.)
II saw make some changes in the program
O
O
12 changes: 8 additions & 4 deletions bindings/python-examples/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1149,7 +1149,6 @@ def validate_opcode(opcode):
wordpos = ""
linkages = Sentence(sent, lgdict, popt).parse()
linkage = next(linkages, None)
self.assertTrue(linkage, "at {}:{}: Sentence has no linkages".format(testfile, lineno))

# Generate the next linkage of the last input sentence
elif line[0] == 'N':
Expand All @@ -1163,9 +1162,14 @@ def validate_opcode(opcode):
# It ends with an empty line
elif line[0] == 'O':
diagram += line[1:]
if line[1] == '\n' and len(diagram) > 1:
self.assertEqual(linkage.diagram(), diagram, "at {}:{}".format(testfile, lineno))
diagram = None
if line[1] == '\n':
if diagram == 'C\nC\n':
self.assertFalse(linkage)
diagram = None
elif len(diagram) > 2:
self.assertTrue(linkage, "at {}:{}: Sentence has no linkages".format(testfile, lineno))
self.assertEqual(linkage.diagram(), diagram, "at {}:{}".format(testfile, lineno))
diagram = None

# Lines starting with C are the constituent output (type 1)
# It ends with an empty line
Expand Down
34 changes: 33 additions & 1 deletion link-grammar/sat-solver/sat-encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,39 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position,
/* Precedes */
int dfs_position_tmp = dfs_position;
for (l = e->u.l; l->next != NULL; l = l->next) {
generate_conjunct_order_constraints(w, l->e, l->next->e, dfs_position_tmp);
Exp e_tmp, *e_rhs = &e_tmp;

if (l->next->next == NULL) {
e_rhs = l->next->e;
}
else {
// A workaround for issue #932:
// Since the generated ordering conditions are not transitive
// (see the example below), chains w/length > 2 miss needed
// constrains. So if the chain length > 2, refer to it as if
// it is a 2-component chain (1st: l->e; 2nd: AND of the rest).
//
// Problem example:
// Sentence: *I saw make some changes in the program
// In word 2 we get here this subexpression (among many others):
// e = (K+ & {[[@MV+]]} & (O*n+ or ())) // (& chain length = 3)
// The generated constrains are only: (Decoding:
// (word-number_connector-position_connector-string)_to-word-number)
// Clause: -link_cw_(2_4_K)_6 -link_cw_(2_5_MV)_6
// Clause: -link_cw_(2_5_MV)_6 -link_cw_(2_6_O*n)_4
// (Reading: If MV connects from word 2 to word 6, then O*n
// cannot connect from word 2 to word 4).
// Clause: -link_cw_(2_5_MV)_6 -link_cw_(2_6_O*n)_5
// However, the following, which are generated when the
// chain length is limited to 2, are missing:
// Clause: -link_cw_(2_4_K)_6 -link_cw_(2_6_O*n)_4
// Clause: -link_cw_(2_4_K)_6 -link_cw_(2_6_O*n)_5
// Clearly, they cannot be concluded transitively.
e_rhs->type = AND_type;
e_rhs->u.l = l->next;
e_rhs->cost = 0.0;
};
generate_conjunct_order_constraints(w, l->e, e_rhs, dfs_position_tmp);
}

/* Recurse */
Expand Down

0 comments on commit c98b712

Please sign in to comment.