grammar_cop 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.DS_Store +0 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +8 -0
- data/data/.DS_Store +0 -0
- data/data/Makefile +511 -0
- data/data/Makefile.am +4 -0
- data/data/Makefile.in +511 -0
- data/data/de/.DS_Store +0 -0
- data/data/de/4.0.affix +7 -0
- data/data/de/4.0.dict +474 -0
- data/data/de/Makefile +387 -0
- data/data/de/Makefile.am +9 -0
- data/data/de/Makefile.in +387 -0
- data/data/en/.DS_Store +0 -0
- data/data/en/4.0.affix +26 -0
- data/data/en/4.0.batch +1002 -0
- data/data/en/4.0.biolg.batch +411 -0
- data/data/en/4.0.constituent-knowledge +127 -0
- data/data/en/4.0.dict +8759 -0
- data/data/en/4.0.dict.m4 +6928 -0
- data/data/en/4.0.enwiki.batch +14 -0
- data/data/en/4.0.fixes.batch +2776 -0
- data/data/en/4.0.knowledge +306 -0
- data/data/en/4.0.regex +225 -0
- data/data/en/4.0.voa.batch +114 -0
- data/data/en/Makefile +554 -0
- data/data/en/Makefile.am +19 -0
- data/data/en/Makefile.in +554 -0
- data/data/en/README +173 -0
- data/data/en/tiny.dict +157 -0
- data/data/en/words/.DS_Store +0 -0
- data/data/en/words/Makefile +456 -0
- data/data/en/words/Makefile.am +78 -0
- data/data/en/words/Makefile.in +456 -0
- data/data/en/words/currency +205 -0
- data/data/en/words/currency.p +28 -0
- data/data/en/words/entities.given-bisex.sing +39 -0
- data/data/en/words/entities.given-female.sing +4141 -0
- data/data/en/words/entities.given-male.sing +1633 -0
- data/data/en/words/entities.locations.sing +68 -0
- data/data/en/words/entities.national.sing +253 -0
- data/data/en/words/entities.organizations.sing +7 -0
- data/data/en/words/entities.us-states.sing +11 -0
- data/data/en/words/units.1 +45 -0
- data/data/en/words/units.1.dot +4 -0
- data/data/en/words/units.3 +2 -0
- data/data/en/words/units.4 +5 -0
- data/data/en/words/units.4.dot +1 -0
- data/data/en/words/words-medical.adv.1 +1191 -0
- data/data/en/words/words-medical.prep.1 +67 -0
- data/data/en/words/words-medical.v.4.1 +2835 -0
- data/data/en/words/words-medical.v.4.2 +2848 -0
- data/data/en/words/words-medical.v.4.3 +3011 -0
- data/data/en/words/words-medical.v.4.4 +3036 -0
- data/data/en/words/words-medical.v.4.5 +3050 -0
- data/data/en/words/words.adj.1 +6794 -0
- data/data/en/words/words.adj.2 +638 -0
- data/data/en/words/words.adj.3 +667 -0
- data/data/en/words/words.adv.1 +1573 -0
- data/data/en/words/words.adv.2 +67 -0
- data/data/en/words/words.adv.3 +157 -0
- data/data/en/words/words.adv.4 +80 -0
- data/data/en/words/words.n.1 +11464 -0
- data/data/en/words/words.n.1.wiki +264 -0
- data/data/en/words/words.n.2.s +2017 -0
- data/data/en/words/words.n.2.s.biolg +1 -0
- data/data/en/words/words.n.2.s.wiki +298 -0
- data/data/en/words/words.n.2.x +65 -0
- data/data/en/words/words.n.2.x.wiki +10 -0
- data/data/en/words/words.n.3 +5717 -0
- data/data/en/words/words.n.t +23 -0
- data/data/en/words/words.v.1.1 +1038 -0
- data/data/en/words/words.v.1.2 +1043 -0
- data/data/en/words/words.v.1.3 +1052 -0
- data/data/en/words/words.v.1.4 +1023 -0
- data/data/en/words/words.v.1.p +17 -0
- data/data/en/words/words.v.10.1 +14 -0
- data/data/en/words/words.v.10.2 +15 -0
- data/data/en/words/words.v.10.3 +88 -0
- data/data/en/words/words.v.10.4 +17 -0
- data/data/en/words/words.v.2.1 +1253 -0
- data/data/en/words/words.v.2.2 +1304 -0
- data/data/en/words/words.v.2.3 +1280 -0
- data/data/en/words/words.v.2.4 +1285 -0
- data/data/en/words/words.v.2.5 +1287 -0
- data/data/en/words/words.v.4.1 +2472 -0
- data/data/en/words/words.v.4.2 +2487 -0
- data/data/en/words/words.v.4.3 +2441 -0
- data/data/en/words/words.v.4.4 +2478 -0
- data/data/en/words/words.v.4.5 +2483 -0
- data/data/en/words/words.v.5.1 +98 -0
- data/data/en/words/words.v.5.2 +98 -0
- data/data/en/words/words.v.5.3 +103 -0
- data/data/en/words/words.v.5.4 +102 -0
- data/data/en/words/words.v.6.1 +388 -0
- data/data/en/words/words.v.6.2 +401 -0
- data/data/en/words/words.v.6.3 +397 -0
- data/data/en/words/words.v.6.4 +405 -0
- data/data/en/words/words.v.6.5 +401 -0
- data/data/en/words/words.v.8.1 +117 -0
- data/data/en/words/words.v.8.2 +118 -0
- data/data/en/words/words.v.8.3 +118 -0
- data/data/en/words/words.v.8.4 +119 -0
- data/data/en/words/words.v.8.5 +119 -0
- data/data/en/words/words.y +104 -0
- data/data/lt/.DS_Store +0 -0
- data/data/lt/4.0.affix +6 -0
- data/data/lt/4.0.constituent-knowledge +24 -0
- data/data/lt/4.0.dict +135 -0
- data/data/lt/4.0.knowledge +38 -0
- data/data/lt/Makefile +389 -0
- data/data/lt/Makefile.am +11 -0
- data/data/lt/Makefile.in +389 -0
- data/ext/.DS_Store +0 -0
- data/ext/link_grammar/.DS_Store +0 -0
- data/ext/link_grammar/extconf.rb +2 -0
- data/ext/link_grammar/link-grammar/.DS_Store +0 -0
- data/ext/link_grammar/link-grammar/.deps/analyze-linkage.Plo +198 -0
- data/ext/link_grammar/link-grammar/.deps/and.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/api.Plo +244 -0
- data/ext/link_grammar/link-grammar/.deps/build-disjuncts.Plo +212 -0
- data/ext/link_grammar/link-grammar/.deps/command-line.Plo +201 -0
- data/ext/link_grammar/link-grammar/.deps/constituents.Plo +201 -0
- data/ext/link_grammar/link-grammar/.deps/count.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/disjunct-utils.Plo +126 -0
- data/ext/link_grammar/link-grammar/.deps/disjuncts.Plo +123 -0
- data/ext/link_grammar/link-grammar/.deps/error.Plo +121 -0
- data/ext/link_grammar/link-grammar/.deps/expand.Plo +133 -0
- data/ext/link_grammar/link-grammar/.deps/extract-links.Plo +198 -0
- data/ext/link_grammar/link-grammar/.deps/fast-match.Plo +200 -0
- data/ext/link_grammar/link-grammar/.deps/idiom.Plo +200 -0
- data/ext/link_grammar/link-grammar/.deps/jni-client.Plo +217 -0
- data/ext/link_grammar/link-grammar/.deps/link-parser.Po +1 -0
- data/ext/link_grammar/link-grammar/.deps/massage.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/post-process.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/pp_knowledge.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/pp_lexer.Plo +201 -0
- data/ext/link_grammar/link-grammar/.deps/pp_linkset.Plo +200 -0
- data/ext/link_grammar/link-grammar/.deps/prefix.Plo +102 -0
- data/ext/link_grammar/link-grammar/.deps/preparation.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/print-util.Plo +200 -0
- data/ext/link_grammar/link-grammar/.deps/print.Plo +201 -0
- data/ext/link_grammar/link-grammar/.deps/prune.Plo +202 -0
- data/ext/link_grammar/link-grammar/.deps/read-dict.Plo +223 -0
- data/ext/link_grammar/link-grammar/.deps/read-regex.Plo +123 -0
- data/ext/link_grammar/link-grammar/.deps/regex-morph.Plo +131 -0
- data/ext/link_grammar/link-grammar/.deps/resources.Plo +203 -0
- data/ext/link_grammar/link-grammar/.deps/spellcheck-aspell.Plo +1 -0
- data/ext/link_grammar/link-grammar/.deps/spellcheck-hun.Plo +115 -0
- data/ext/link_grammar/link-grammar/.deps/string-set.Plo +198 -0
- data/ext/link_grammar/link-grammar/.deps/tokenize.Plo +160 -0
- data/ext/link_grammar/link-grammar/.deps/utilities.Plo +222 -0
- data/ext/link_grammar/link-grammar/.deps/word-file.Plo +201 -0
- data/ext/link_grammar/link-grammar/.deps/word-utils.Plo +212 -0
- data/ext/link_grammar/link-grammar/.libs/analyze-linkage.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/and.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/api.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/build-disjuncts.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/command-line.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/constituents.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/count.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/disjunct-utils.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/disjuncts.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/error.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/expand.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/extract-links.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/fast-match.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/idiom.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/jni-client.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java-symbols.expsym +31 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java.4.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java.4.dylib.dSYM/Contents/Info.plist +20 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java.4.dylib.dSYM/Contents/Resources/DWARF/liblink-grammar-java.4.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java.a +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-java.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar-symbols.expsym +194 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.4.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.4.dylib.dSYM/Contents/Info.plist +20 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.4.dylib.dSYM/Contents/Resources/DWARF/liblink-grammar.4.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.a +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.dylib +0 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.la +41 -0
- data/ext/link_grammar/link-grammar/.libs/liblink-grammar.lai +41 -0
- data/ext/link_grammar/link-grammar/.libs/massage.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/post-process.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/pp_knowledge.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/pp_lexer.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/pp_linkset.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/prefix.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/preparation.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/print-util.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/print.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/prune.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/read-dict.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/read-regex.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/regex-morph.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/resources.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/spellcheck-aspell.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/spellcheck-hun.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/string-set.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/tokenize.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/utilities.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/word-file.o +0 -0
- data/ext/link_grammar/link-grammar/.libs/word-utils.o +0 -0
- data/ext/link_grammar/link-grammar/Makefile +900 -0
- data/ext/link_grammar/link-grammar/Makefile.am +202 -0
- data/ext/link_grammar/link-grammar/Makefile.in +900 -0
- data/ext/link_grammar/link-grammar/analyze-linkage.c +1317 -0
- data/ext/link_grammar/link-grammar/analyze-linkage.h +24 -0
- data/ext/link_grammar/link-grammar/and.c +1603 -0
- data/ext/link_grammar/link-grammar/and.h +27 -0
- data/ext/link_grammar/link-grammar/api-structures.h +362 -0
- data/ext/link_grammar/link-grammar/api-types.h +72 -0
- data/ext/link_grammar/link-grammar/api.c +1887 -0
- data/ext/link_grammar/link-grammar/api.h +96 -0
- data/ext/link_grammar/link-grammar/autoit/.DS_Store +0 -0
- data/ext/link_grammar/link-grammar/autoit/README +10 -0
- data/ext/link_grammar/link-grammar/autoit/_LGTest.au3 +22 -0
- data/ext/link_grammar/link-grammar/autoit/_LinkGrammar.au3 +545 -0
- data/ext/link_grammar/link-grammar/build-disjuncts.c +487 -0
- data/ext/link_grammar/link-grammar/build-disjuncts.h +21 -0
- data/ext/link_grammar/link-grammar/command-line.c +458 -0
- data/ext/link_grammar/link-grammar/command-line.h +15 -0
- data/ext/link_grammar/link-grammar/constituents.c +1836 -0
- data/ext/link_grammar/link-grammar/constituents.h +26 -0
- data/ext/link_grammar/link-grammar/corpus/.DS_Store +0 -0
- data/ext/link_grammar/link-grammar/corpus/.deps/cluster.Plo +1 -0
- data/ext/link_grammar/link-grammar/corpus/.deps/corpus.Plo +1 -0
- data/ext/link_grammar/link-grammar/corpus/Makefile +527 -0
- data/ext/link_grammar/link-grammar/corpus/Makefile.am +46 -0
- data/ext/link_grammar/link-grammar/corpus/Makefile.in +527 -0
- data/ext/link_grammar/link-grammar/corpus/README +17 -0
- data/ext/link_grammar/link-grammar/corpus/cluster.c +286 -0
- data/ext/link_grammar/link-grammar/corpus/cluster.h +32 -0
- data/ext/link_grammar/link-grammar/corpus/corpus.c +483 -0
- data/ext/link_grammar/link-grammar/corpus/corpus.h +46 -0
- data/ext/link_grammar/link-grammar/count.c +828 -0
- data/ext/link_grammar/link-grammar/count.h +25 -0
- data/ext/link_grammar/link-grammar/disjunct-utils.c +261 -0
- data/ext/link_grammar/link-grammar/disjunct-utils.h +27 -0
- data/ext/link_grammar/link-grammar/disjuncts.c +138 -0
- data/ext/link_grammar/link-grammar/disjuncts.h +13 -0
- data/ext/link_grammar/link-grammar/error.c +92 -0
- data/ext/link_grammar/link-grammar/error.h +35 -0
- data/ext/link_grammar/link-grammar/expand.c +67 -0
- data/ext/link_grammar/link-grammar/expand.h +13 -0
- data/ext/link_grammar/link-grammar/externs.h +22 -0
- data/ext/link_grammar/link-grammar/extract-links.c +625 -0
- data/ext/link_grammar/link-grammar/extract-links.h +16 -0
- data/ext/link_grammar/link-grammar/fast-match.c +309 -0
- data/ext/link_grammar/link-grammar/fast-match.h +17 -0
- data/ext/link_grammar/link-grammar/idiom.c +373 -0
- data/ext/link_grammar/link-grammar/idiom.h +15 -0
- data/ext/link_grammar/link-grammar/jni-client.c +779 -0
- data/ext/link_grammar/link-grammar/jni-client.h +236 -0
- data/ext/link_grammar/link-grammar/liblink-grammar-java.la +42 -0
- data/ext/link_grammar/link-grammar/liblink-grammar.la +41 -0
- data/ext/link_grammar/link-grammar/link-features.h +37 -0
- data/ext/link_grammar/link-grammar/link-features.h.in +37 -0
- data/ext/link_grammar/link-grammar/link-grammar-java.def +31 -0
- data/ext/link_grammar/link-grammar/link-grammar.def +194 -0
- data/ext/link_grammar/link-grammar/link-includes.h +465 -0
- data/ext/link_grammar/link-grammar/link-parser.c +849 -0
- data/ext/link_grammar/link-grammar/massage.c +329 -0
- data/ext/link_grammar/link-grammar/massage.h +13 -0
- data/ext/link_grammar/link-grammar/post-process.c +1113 -0
- data/ext/link_grammar/link-grammar/post-process.h +45 -0
- data/ext/link_grammar/link-grammar/pp_knowledge.c +376 -0
- data/ext/link_grammar/link-grammar/pp_knowledge.h +14 -0
- data/ext/link_grammar/link-grammar/pp_lexer.c +1920 -0
- data/ext/link_grammar/link-grammar/pp_lexer.h +19 -0
- data/ext/link_grammar/link-grammar/pp_linkset.c +158 -0
- data/ext/link_grammar/link-grammar/pp_linkset.h +20 -0
- data/ext/link_grammar/link-grammar/prefix.c +482 -0
- data/ext/link_grammar/link-grammar/prefix.h +139 -0
- data/ext/link_grammar/link-grammar/preparation.c +412 -0
- data/ext/link_grammar/link-grammar/preparation.h +20 -0
- data/ext/link_grammar/link-grammar/print-util.c +87 -0
- data/ext/link_grammar/link-grammar/print-util.h +32 -0
- data/ext/link_grammar/link-grammar/print.c +1085 -0
- data/ext/link_grammar/link-grammar/print.h +16 -0
- data/ext/link_grammar/link-grammar/prune.c +1864 -0
- data/ext/link_grammar/link-grammar/prune.h +17 -0
- data/ext/link_grammar/link-grammar/read-dict.c +1785 -0
- data/ext/link_grammar/link-grammar/read-dict.h +29 -0
- data/ext/link_grammar/link-grammar/read-regex.c +161 -0
- data/ext/link_grammar/link-grammar/read-regex.h +12 -0
- data/ext/link_grammar/link-grammar/regex-morph.c +126 -0
- data/ext/link_grammar/link-grammar/regex-morph.h +17 -0
- data/ext/link_grammar/link-grammar/resources.c +180 -0
- data/ext/link_grammar/link-grammar/resources.h +23 -0
- data/ext/link_grammar/link-grammar/sat-solver/.DS_Store +0 -0
- data/ext/link_grammar/link-grammar/sat-solver/.deps/fast-sprintf.Plo +1 -0
- data/ext/link_grammar/link-grammar/sat-solver/.deps/sat-encoder.Plo +1 -0
- data/ext/link_grammar/link-grammar/sat-solver/.deps/util.Plo +1 -0
- data/ext/link_grammar/link-grammar/sat-solver/.deps/variables.Plo +1 -0
- data/ext/link_grammar/link-grammar/sat-solver/.deps/word-tag.Plo +1 -0
- data/ext/link_grammar/link-grammar/sat-solver/Makefile +527 -0
- data/ext/link_grammar/link-grammar/sat-solver/Makefile.am +29 -0
- data/ext/link_grammar/link-grammar/sat-solver/Makefile.in +527 -0
- data/ext/link_grammar/link-grammar/sat-solver/clock.hpp +33 -0
- data/ext/link_grammar/link-grammar/sat-solver/fast-sprintf.cpp +26 -0
- data/ext/link_grammar/link-grammar/sat-solver/fast-sprintf.hpp +7 -0
- data/ext/link_grammar/link-grammar/sat-solver/guiding.hpp +244 -0
- data/ext/link_grammar/link-grammar/sat-solver/matrix-ut.hpp +79 -0
- data/ext/link_grammar/link-grammar/sat-solver/sat-encoder.cpp +2811 -0
- data/ext/link_grammar/link-grammar/sat-solver/sat-encoder.h +11 -0
- data/ext/link_grammar/link-grammar/sat-solver/sat-encoder.hpp +381 -0
- data/ext/link_grammar/link-grammar/sat-solver/trie.hpp +118 -0
- data/ext/link_grammar/link-grammar/sat-solver/util.cpp +23 -0
- data/ext/link_grammar/link-grammar/sat-solver/util.hpp +14 -0
- data/ext/link_grammar/link-grammar/sat-solver/variables.cpp +5 -0
- data/ext/link_grammar/link-grammar/sat-solver/variables.hpp +829 -0
- data/ext/link_grammar/link-grammar/sat-solver/word-tag.cpp +159 -0
- data/ext/link_grammar/link-grammar/sat-solver/word-tag.hpp +162 -0
- data/ext/link_grammar/link-grammar/spellcheck-aspell.c +148 -0
- data/ext/link_grammar/link-grammar/spellcheck-hun.c +136 -0
- data/ext/link_grammar/link-grammar/spellcheck.h +34 -0
- data/ext/link_grammar/link-grammar/string-set.c +169 -0
- data/ext/link_grammar/link-grammar/string-set.h +16 -0
- data/ext/link_grammar/link-grammar/structures.h +498 -0
- data/ext/link_grammar/link-grammar/tokenize.c +1049 -0
- data/ext/link_grammar/link-grammar/tokenize.h +15 -0
- data/ext/link_grammar/link-grammar/utilities.c +847 -0
- data/ext/link_grammar/link-grammar/utilities.h +281 -0
- data/ext/link_grammar/link-grammar/word-file.c +124 -0
- data/ext/link_grammar/link-grammar/word-file.h +15 -0
- data/ext/link_grammar/link-grammar/word-utils.c +526 -0
- data/ext/link_grammar/link-grammar/word-utils.h +152 -0
- data/ext/link_grammar/link_grammar.c +202 -0
- data/ext/link_grammar/link_grammar.h +99 -0
- data/grammar_cop.gemspec +24 -0
- data/lib/.DS_Store +0 -0
- data/lib/grammar_cop.rb +9 -0
- data/lib/grammar_cop/.DS_Store +0 -0
- data/lib/grammar_cop/dictionary.rb +19 -0
- data/lib/grammar_cop/linkage.rb +30 -0
- data/lib/grammar_cop/parse_options.rb +32 -0
- data/lib/grammar_cop/sentence.rb +36 -0
- data/lib/grammar_cop/version.rb +3 -0
- data/test/.DS_Store +0 -0
- data/test/grammar_cop_test.rb +27 -0
- metadata +407 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
#ifndef __CLOCK_H__
|
2
|
+
#define __CLOCK_H__
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Time measurment functions
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include <iostream>
|
9
|
+
#include <ctime>
|
10
|
+
|
11
|
+
class Clock {
|
12
|
+
private:
|
13
|
+
clock_t start;
|
14
|
+
public:
|
15
|
+
Clock() {
|
16
|
+
reset();
|
17
|
+
}
|
18
|
+
|
19
|
+
void reset()
|
20
|
+
{
|
21
|
+
start = clock();
|
22
|
+
}
|
23
|
+
|
24
|
+
public:
|
25
|
+
double elapsed()
|
26
|
+
{
|
27
|
+
clock_t stop = clock();
|
28
|
+
return ((double)stop-(double)start)/CLOCKS_PER_SEC;
|
29
|
+
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
#endif
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#include "fast-sprintf.hpp"
|
2
|
+
|
3
|
+
char* fast_sprintf(char* buffer, int num) {
|
4
|
+
char* begin = buffer;
|
5
|
+
do {
|
6
|
+
*buffer++ = '0' + num % 10;
|
7
|
+
num /= 10;
|
8
|
+
} while (num > 0);
|
9
|
+
char* end = buffer - 1;
|
10
|
+
|
11
|
+
for (; begin < end; begin++, end--) {
|
12
|
+
char tmp = *begin;
|
13
|
+
*begin = *end;
|
14
|
+
*end = tmp;
|
15
|
+
}
|
16
|
+
|
17
|
+
*buffer = '\0';
|
18
|
+
|
19
|
+
return buffer;
|
20
|
+
}
|
21
|
+
|
22
|
+
char* fast_sprintf(char* buffer, const char* str) {
|
23
|
+
while(*buffer++ = *str++)
|
24
|
+
;
|
25
|
+
return buffer - 1;
|
26
|
+
}
|
@@ -0,0 +1,244 @@
|
|
1
|
+
#ifndef __GUIDING_HPP__
|
2
|
+
#define __GUIDING_HPP__
|
3
|
+
|
4
|
+
#include "Solver.h"
|
5
|
+
#include "util.hpp"
|
6
|
+
|
7
|
+
// This class represents different guding strategies of LinkParser SAT search
|
8
|
+
class Guiding {
|
9
|
+
public:
|
10
|
+
struct SATParameters {
|
11
|
+
/* Should the variable with the given number be used as a decision
|
12
|
+
variable during the SAT search? */
|
13
|
+
bool isDecision;
|
14
|
+
/* What is the decision priority of the variable with the given number
|
15
|
+
during the SAT search? */
|
16
|
+
double priority;
|
17
|
+
/* What is the preffered polarity of the variable with the given number
|
18
|
+
during the SAT search? */
|
19
|
+
double polarity;
|
20
|
+
};
|
21
|
+
|
22
|
+
Guiding(Sentence sent)
|
23
|
+
: _sent(sent) {
|
24
|
+
}
|
25
|
+
|
26
|
+
/* Abstract functions that calculate params for each type of variable */
|
27
|
+
|
28
|
+
/* string variables */
|
29
|
+
virtual void setStringParameters (int var, const char* str) {
|
30
|
+
bool isDecision = false;
|
31
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
32
|
+
}
|
33
|
+
virtual void setStringParameters (int var, const char* str, int cost) = 0;
|
34
|
+
|
35
|
+
/* epsilon variables */
|
36
|
+
virtual void setEpsilonParameters (int var) {
|
37
|
+
bool isDecision = false;
|
38
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
39
|
+
}
|
40
|
+
|
41
|
+
/* link_cc variables */
|
42
|
+
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label) = 0;
|
43
|
+
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label,
|
44
|
+
int cost) = 0;
|
45
|
+
|
46
|
+
/* linked_variables */
|
47
|
+
virtual void setLinkedParameters (int var, int wi, int wj) {
|
48
|
+
bool isDecision = false;
|
49
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
50
|
+
}
|
51
|
+
|
52
|
+
virtual void setLinkedMinMaxParameters (int var, int wi, int wj) {
|
53
|
+
bool isDecision = false;
|
54
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
55
|
+
}
|
56
|
+
|
57
|
+
/* link_cw_variables */
|
58
|
+
virtual void setLinkCWParameters (int var, int wi, int wj, const char* cj) {
|
59
|
+
bool isDecision = false;
|
60
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
61
|
+
}
|
62
|
+
|
63
|
+
/* link_top_cw variables */
|
64
|
+
virtual void setLinkTopCWParameters (int var, int wi, int wj, const char* cj) {
|
65
|
+
bool isDecision = false;
|
66
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
67
|
+
}
|
68
|
+
|
69
|
+
/* link_top_ww variables */
|
70
|
+
virtual void setLinkTopWWParameters (int var, int wi, int wj) {
|
71
|
+
bool isDecision = false;
|
72
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
73
|
+
}
|
74
|
+
|
75
|
+
/* fat_link variables */
|
76
|
+
virtual void setFatLinkParameters (int var, int wi, int wj) = 0;
|
77
|
+
/* thin_link variables */
|
78
|
+
virtual void setThinLinkParameters (int var, int wi, int wj) = 0;
|
79
|
+
/* neighbor fat link variables */
|
80
|
+
virtual void setNeighborFatLinkParameters (int var, int w) = 0;
|
81
|
+
|
82
|
+
/* Pass SAT search parameters to the MiniSAT solver */
|
83
|
+
void passParametersToSolver(Solver* solver) {
|
84
|
+
for (int v = 0; v < _parameters.size(); v++) {
|
85
|
+
solver->setDecisionVar(v, _parameters[v].isDecision);
|
86
|
+
if (_parameters[v].isDecision) {
|
87
|
+
solver->setActivity(v, _parameters[v].priority);
|
88
|
+
/* TODO: make polarity double instead of boolean*/
|
89
|
+
solver->setPolarity(v, _parameters[v].polarity > 0.0);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
protected:
|
95
|
+
/* Set the parameters for the given variable to given values */
|
96
|
+
void setParameters(int var, bool isDecision, double priority, double polarity) {
|
97
|
+
if (var >= _parameters.size())
|
98
|
+
_parameters.resize(var + 1);
|
99
|
+
_parameters[var].isDecision = isDecision;
|
100
|
+
_parameters[var].priority = priority;
|
101
|
+
_parameters[var].polarity = polarity;
|
102
|
+
|
103
|
+
// printf("Set: %d %s .%g. .%g.\n", var, isDecision ? "true" : "false", priority, polarity);
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
/* Sentence that is being parsed */
|
108
|
+
Sentence _sent;
|
109
|
+
|
110
|
+
/* Parameters for each variable */
|
111
|
+
std::vector<SATParameters> _parameters;
|
112
|
+
};
|
113
|
+
|
114
|
+
////////////////////////////////////////////////////////////////////////////
|
115
|
+
class CostDistanceGuiding : public Guiding {
|
116
|
+
public:
|
117
|
+
double cost2priority(int cost) {
|
118
|
+
return cost == 0 ? 0.0 : (double)(_sent->length + cost);
|
119
|
+
}
|
120
|
+
|
121
|
+
CostDistanceGuiding(Sentence sent)
|
122
|
+
: Guiding(sent) {
|
123
|
+
}
|
124
|
+
|
125
|
+
virtual void setStringParameters (int var, const char* str, int cost) {
|
126
|
+
bool isDecision = cost > 0.0;
|
127
|
+
double priority = cost2priority(cost);
|
128
|
+
double polarity = 0.0;
|
129
|
+
setParameters(var, isDecision, priority, polarity);
|
130
|
+
}
|
131
|
+
|
132
|
+
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label) {
|
133
|
+
bool isDecision = true;
|
134
|
+
double priority = 0.0;
|
135
|
+
double polarity = 0.0;
|
136
|
+
setParameters(var, isDecision, priority, polarity);
|
137
|
+
}
|
138
|
+
|
139
|
+
virtual void setLinkParameters(int var, int i, const char* ci, int j, const char* cj, const char* label,
|
140
|
+
int cost) {
|
141
|
+
bool isDecision = true;
|
142
|
+
double priority = cost2priority(cost);
|
143
|
+
double polarity = 0.0;
|
144
|
+
setParameters(var, isDecision, priority, polarity);
|
145
|
+
}
|
146
|
+
|
147
|
+
void setFatLinkParameters(int var, int i, int j) {
|
148
|
+
bool isDecision = true;
|
149
|
+
double priority = (double)abs(j - i);
|
150
|
+
|
151
|
+
if (_sent->is_conjunction[i])
|
152
|
+
priority = 0.0;
|
153
|
+
|
154
|
+
double polarity = abs(j - i) == 1 ? 1.0 : 0.0;
|
155
|
+
setParameters(var, isDecision, priority, polarity);
|
156
|
+
}
|
157
|
+
|
158
|
+
void setThinLinkParameters(int var, int i, int j) {
|
159
|
+
bool isDecision = true;
|
160
|
+
|
161
|
+
double priority = (double)(j - i);
|
162
|
+
if (_sent->is_conjunction[i] || _sent->is_conjunction[j])
|
163
|
+
priority = priority / 2;
|
164
|
+
|
165
|
+
double polarity = j - i == 1 ? 1.0 : 0.0;
|
166
|
+
if (i == 0 && j == _sent->length - 2 && isEndingInterpunction(_sent->word[j].string)) {
|
167
|
+
polarity = 1.0;
|
168
|
+
}
|
169
|
+
if (i == 0 && j == _sent->length - 1 && !isEndingInterpunction(_sent->word[j - 1].string)) {
|
170
|
+
polarity = 1.0;
|
171
|
+
}
|
172
|
+
|
173
|
+
setParameters(var, isDecision, priority, polarity);
|
174
|
+
}
|
175
|
+
|
176
|
+
void setNeighborFatLinkParameters(int var, int w) {
|
177
|
+
bool isDecision = true;
|
178
|
+
double priority = _sent->length;
|
179
|
+
double polarity = 1.0;
|
180
|
+
setParameters(var, isDecision, priority, polarity);
|
181
|
+
}
|
182
|
+
|
183
|
+
};
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
////////////////////////////////////////////////////////////////////////////
|
188
|
+
class CostDistanceGuidingOnlyLink : public Guiding {
|
189
|
+
public:
|
190
|
+
double cost2priority(int cost) {
|
191
|
+
return cost == 0 ? 0.0 : (double)(_sent->length + cost);
|
192
|
+
}
|
193
|
+
|
194
|
+
CostDistanceGuidingOnlyLink(Sentence sent)
|
195
|
+
: Guiding(sent) {
|
196
|
+
}
|
197
|
+
|
198
|
+
virtual void setStringParameters (int var, const char* str, int cost) {
|
199
|
+
bool isDecision = cost > 0.0;
|
200
|
+
double priority = cost2priority(cost);
|
201
|
+
double polarity = 0.0;
|
202
|
+
setParameters(var, isDecision, priority, polarity);
|
203
|
+
}
|
204
|
+
|
205
|
+
virtual void setLinkParameters (int var, int wi, const char* ci, int wj, const char* cj, const char* label) {
|
206
|
+
bool isDecision = true;
|
207
|
+
double priority = _sent->length - (wj - wi);
|
208
|
+
double polarity = wj - wi <= 3 ? 1.0 : 0.0;;
|
209
|
+
setParameters(var, isDecision, priority, polarity);
|
210
|
+
}
|
211
|
+
|
212
|
+
virtual void setLinkParameters(int var, int wi, const char* ci, int wj, const char* cj, const char* label,
|
213
|
+
int cost) {
|
214
|
+
bool isDecision = true;
|
215
|
+
double priority = cost > 0 ? cost2priority(cost) : wj - wi;
|
216
|
+
double polarity = wj - wi <= 3 ? 1.0 : 0.0;
|
217
|
+
setParameters(var, isDecision, priority, polarity);
|
218
|
+
}
|
219
|
+
|
220
|
+
void setFatLinkParameters(int var, int i, int j) {
|
221
|
+
bool isDecision = true;
|
222
|
+
double priority = (double)abs(j - i);
|
223
|
+
|
224
|
+
if (_sent->is_conjunction[i])
|
225
|
+
priority = 0.0;
|
226
|
+
|
227
|
+
double polarity = abs(j - i) == 1 ? 1.0 : 0.0;
|
228
|
+
setParameters(var, isDecision, priority, polarity);
|
229
|
+
}
|
230
|
+
|
231
|
+
void setThinLinkParameters(int var, int i, int j) {
|
232
|
+
bool isDecision = false;
|
233
|
+
setParameters(var, isDecision, 0.0, 0.0);
|
234
|
+
}
|
235
|
+
|
236
|
+
void setNeighborFatLinkParameters(int var, int w) {
|
237
|
+
bool isDecision = true;
|
238
|
+
double priority = _sent->length;
|
239
|
+
double polarity = 1.0;
|
240
|
+
setParameters(var, isDecision, priority, polarity);
|
241
|
+
}
|
242
|
+
|
243
|
+
};
|
244
|
+
#endif
|
@@ -0,0 +1,79 @@
|
|
1
|
+
#ifndef __MATRIX_UPPER_TRIANGLE_HPP__
|
2
|
+
#define __MATRIX_UPPER_TRIANGLE_HPP__
|
3
|
+
|
4
|
+
#include <vector>
|
5
|
+
|
6
|
+
#ifndef assert
|
7
|
+
#define assert(ex,string) { \
|
8
|
+
if (!(ex)) { \
|
9
|
+
printf("Assertion failed: %s\n", string); \
|
10
|
+
exit(1); \
|
11
|
+
} \
|
12
|
+
}
|
13
|
+
#endif
|
14
|
+
|
15
|
+
template<class T>
|
16
|
+
class Matrix {
|
17
|
+
public:
|
18
|
+
Matrix(int n = 1, T init = T()) {
|
19
|
+
resize(n, init);
|
20
|
+
}
|
21
|
+
|
22
|
+
virtual void resize(int n, T init = T()) {
|
23
|
+
_n = n;
|
24
|
+
_data.resize(size(_n), init);
|
25
|
+
}
|
26
|
+
|
27
|
+
virtual const T& operator() (int i, int j) const {
|
28
|
+
return _data[pos(i, j, _n)];
|
29
|
+
}
|
30
|
+
|
31
|
+
virtual T& operator() (int i, int j) {
|
32
|
+
return _data[pos(i, j, _n)];
|
33
|
+
}
|
34
|
+
|
35
|
+
void set(int i, int j, T t) {
|
36
|
+
(*this)(i, j) = t;
|
37
|
+
}
|
38
|
+
|
39
|
+
protected:
|
40
|
+
virtual int pos (int i, int j, int n) const {
|
41
|
+
return n*i + j;
|
42
|
+
}
|
43
|
+
|
44
|
+
virtual int size(int n) const {
|
45
|
+
return n*n;
|
46
|
+
}
|
47
|
+
|
48
|
+
std::vector<T> _data;
|
49
|
+
int _n;
|
50
|
+
};
|
51
|
+
|
52
|
+
template <class T>
|
53
|
+
class MatrixUpperTriangle : public Matrix<T> {
|
54
|
+
public:
|
55
|
+
MatrixUpperTriangle(int n = 1, T init = T())
|
56
|
+
: Matrix<T>(n, init) {
|
57
|
+
}
|
58
|
+
|
59
|
+
const T& operator() (int i, int j) const {
|
60
|
+
assert(i < j, "MatrixUpperTriangle: i >= j");
|
61
|
+
return Matrix<T>::_data[pos(i, j, Matrix<T>::_n)];
|
62
|
+
}
|
63
|
+
|
64
|
+
T& operator() (int i, int j) {
|
65
|
+
assert(i < j, "MatrixUpperTriangle: i >= j");
|
66
|
+
return Matrix<T>::_data[pos(i, j, Matrix<T>::_n)];
|
67
|
+
}
|
68
|
+
|
69
|
+
protected:
|
70
|
+
virtual int size(int n) const {
|
71
|
+
return n*(n-1)/2;
|
72
|
+
}
|
73
|
+
|
74
|
+
virtual int pos (int i, int j, int n) const {
|
75
|
+
return i*(n-2) - i*(i-1)/2 + j - 1;
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
#endif
|
@@ -0,0 +1,2811 @@
|
|
1
|
+
#include <cstdlib>
|
2
|
+
#include <cstdio>
|
3
|
+
#include <cstring>
|
4
|
+
#include <iostream>
|
5
|
+
#include <vector>
|
6
|
+
#include <map>
|
7
|
+
#include <algorithm>
|
8
|
+
#include <iterator>
|
9
|
+
using std::cout;
|
10
|
+
using std::cerr;
|
11
|
+
using std::endl;
|
12
|
+
|
13
|
+
#include "sat-encoder.hpp"
|
14
|
+
#include "variables.hpp"
|
15
|
+
#include "word-tag.hpp"
|
16
|
+
#include "matrix-ut.hpp"
|
17
|
+
#include "clock.hpp"
|
18
|
+
#include "fast-sprintf.hpp"
|
19
|
+
#include "minisat/Solver.h"
|
20
|
+
|
21
|
+
|
22
|
+
extern "C" {
|
23
|
+
#include <link-grammar/api.h>
|
24
|
+
#include "preparation.h"
|
25
|
+
}
|
26
|
+
|
27
|
+
// Macro DEBUG_print is used to dump to stdout information while debugging
|
28
|
+
#ifdef _DEBUG
|
29
|
+
#define DEBUG_print(x) (cout << x << endl)
|
30
|
+
#else
|
31
|
+
#define DEBUG_print(x) (0)
|
32
|
+
#endif
|
33
|
+
|
34
|
+
/*-------------------------------------------------------------------------*
|
35
|
+
* C N F C O N V E R S I O N *
|
36
|
+
*-------------------------------------------------------------------------*/
|
37
|
+
void SATEncoder::generate_literal(Lit l) {
|
38
|
+
vec<Lit> clause(1);
|
39
|
+
clause[0] = l;
|
40
|
+
add_clause(clause);
|
41
|
+
}
|
42
|
+
|
43
|
+
void SATEncoder::generate_and_definition(Lit lhs, vec<Lit>& rhs) {
|
44
|
+
vec<Lit> clause;
|
45
|
+
for (int i = 0; i < rhs.size(); i++) {
|
46
|
+
clause.growTo(2);
|
47
|
+
clause[0] = ~lhs;
|
48
|
+
clause[1] = rhs[i];
|
49
|
+
add_clause(clause);
|
50
|
+
}
|
51
|
+
|
52
|
+
for (int i = 0; i < rhs.size(); i++) {
|
53
|
+
clause.growTo(2);
|
54
|
+
clause[0] = ~rhs[i];
|
55
|
+
clause[1] = lhs;
|
56
|
+
add_clause(clause);
|
57
|
+
}
|
58
|
+
}
|
59
|
+
void SATEncoder::generate_classical_and_definition(Lit lhs, vec<Lit>& rhs) {
|
60
|
+
{
|
61
|
+
vec<Lit> clause;
|
62
|
+
for (int i = 0; i < rhs.size(); i++) {
|
63
|
+
clause.growTo(2);
|
64
|
+
|
65
|
+
clause[0] = ~lhs;
|
66
|
+
clause[1] = rhs[i];
|
67
|
+
add_clause(clause);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
{
|
72
|
+
vec<Lit> clause(rhs.size() + 1);
|
73
|
+
for (int i = 0; i < rhs.size(); i++) {
|
74
|
+
clause[i] = ~rhs[i];
|
75
|
+
}
|
76
|
+
clause[rhs.size()] = lhs;
|
77
|
+
add_clause(clause);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
void SATEncoder::generate_or_definition(Lit lhs, vec<Lit>& rhs) {
|
82
|
+
{
|
83
|
+
vec<Lit> clause;
|
84
|
+
for (int i = 0; i < rhs.size(); i++) {
|
85
|
+
clause.growTo(2);
|
86
|
+
clause[0] = lhs;
|
87
|
+
clause[1] = ~rhs[i];
|
88
|
+
add_clause(clause);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
{
|
93
|
+
vec<Lit> clause(rhs.size() + 1);
|
94
|
+
for (int i = 0; i < rhs.size(); i++) {
|
95
|
+
clause[i] = rhs[i];
|
96
|
+
}
|
97
|
+
clause[rhs.size()] = ~lhs;
|
98
|
+
add_clause(clause);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
void SATEncoder::generate_conditional_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs) {
|
103
|
+
{
|
104
|
+
vec<Lit> clause;
|
105
|
+
for (int i = 0; i < rhs.size(); i++) {
|
106
|
+
clause.growTo(3);
|
107
|
+
clause[0] = ~condition;
|
108
|
+
clause[1] = lhs;
|
109
|
+
clause[2] = ~rhs[i];
|
110
|
+
add_clause(clause);
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
{
|
115
|
+
vec<Lit> clause(rhs.size() + 2);
|
116
|
+
for (int i = 0; i < rhs.size(); i++) {
|
117
|
+
clause[i] = rhs[i];
|
118
|
+
}
|
119
|
+
clause[rhs.size()] = ~lhs;
|
120
|
+
clause[rhs.size()+1] = ~condition;
|
121
|
+
add_clause(clause);
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
void SATEncoder::generate_conditional_lr_implication_or_definition(Lit condition, Lit lhs, vec<Lit>& rhs) {
|
126
|
+
{
|
127
|
+
vec<Lit> clause;
|
128
|
+
for (int i = 0; i < rhs.size(); i++) {
|
129
|
+
clause.growTo(2);
|
130
|
+
clause[0] = lhs;
|
131
|
+
clause[1] = ~rhs[i];
|
132
|
+
add_clause(clause);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
{
|
137
|
+
vec<Lit> clause(rhs.size() + 2);
|
138
|
+
for (int i = 0; i < rhs.size(); i++) {
|
139
|
+
clause[i] = rhs[i];
|
140
|
+
}
|
141
|
+
clause[rhs.size()] = ~lhs;
|
142
|
+
clause[rhs.size()+1] = ~condition;
|
143
|
+
add_clause(clause);
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
void SATEncoder::generate_conditional_lr_implication_or_definition(Lit condition1, Lit condition2, Lit lhs, vec<Lit>& rhs) {
|
148
|
+
{
|
149
|
+
vec<Lit> clause;
|
150
|
+
for (int i = 0; i < rhs.size(); i++) {
|
151
|
+
clause.growTo(2);
|
152
|
+
clause[0] = lhs;
|
153
|
+
clause[1] = ~rhs[i];
|
154
|
+
add_clause(clause);
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
{
|
159
|
+
vec<Lit> clause(rhs.size() + 3);
|
160
|
+
for (int i = 0; i < rhs.size(); i++) {
|
161
|
+
clause[i] = rhs[i];
|
162
|
+
}
|
163
|
+
clause[rhs.size()] = ~lhs;
|
164
|
+
clause[rhs.size()+1] = ~condition1;
|
165
|
+
clause[rhs.size()+2] = ~condition2;
|
166
|
+
add_clause(clause);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
void SATEncoder::generate_xor_conditions(vec<Lit>& vect) {
|
171
|
+
vec<Lit> clause;
|
172
|
+
for (int i = 0; i < vect.size(); i++) {
|
173
|
+
for (int j = i + 1; j < vect.size(); j++) {
|
174
|
+
if (vect[i] == vect[j])
|
175
|
+
continue;
|
176
|
+
clause.growTo(2);
|
177
|
+
clause[0] = ~vect[i];
|
178
|
+
clause[1] = ~vect[j];
|
179
|
+
add_clause(clause);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
void SATEncoder::generate_and(vec<Lit>& vect) {
|
185
|
+
for (int i = 0; i < vect.size(); i++) {
|
186
|
+
generate_literal(vect[i]);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
void SATEncoder::generate_or(vec<Lit>& vect) {
|
192
|
+
add_clause(vect);
|
193
|
+
}
|
194
|
+
|
195
|
+
void SATEncoder::generate_equivalence_definition(Lit l1, Lit l2) {
|
196
|
+
{
|
197
|
+
vec<Lit> clause(2);
|
198
|
+
clause[0] = ~l1;
|
199
|
+
clause[1] = l2;
|
200
|
+
add_clause(clause);
|
201
|
+
}
|
202
|
+
{
|
203
|
+
vec<Lit> clause(2);
|
204
|
+
clause[0] = l1;
|
205
|
+
clause[1] = ~l2;
|
206
|
+
add_clause(clause);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
|
211
|
+
/*-------------------------------------------------------------------------*
|
212
|
+
* E N C O D I N G *
|
213
|
+
*-------------------------------------------------------------------------*/
|
214
|
+
void SATEncoder::encode() {
|
215
|
+
Clock clock;
|
216
|
+
generate_satisfaction_conditions();
|
217
|
+
DEBUG_print(clock.elapsed());
|
218
|
+
generate_linked_definitions();
|
219
|
+
DEBUG_print(clock.elapsed());
|
220
|
+
generate_planarity_conditions();
|
221
|
+
DEBUG_print(clock.elapsed());
|
222
|
+
|
223
|
+
#ifdef _CONNECTIVITY_
|
224
|
+
generate_connectivity();
|
225
|
+
DEBUG_print(clock.elapsed());
|
226
|
+
#endif
|
227
|
+
|
228
|
+
generate_encoding_specific_clauses();
|
229
|
+
DEBUG_print(clock.elapsed());
|
230
|
+
|
231
|
+
pp_prune();
|
232
|
+
power_prune();
|
233
|
+
DEBUG_print(clock.elapsed());
|
234
|
+
|
235
|
+
_variables->setVariableParameters(_solver);
|
236
|
+
}
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
/*-------------------------------------------------------------------------*
|
241
|
+
* W O R D - T A G S *
|
242
|
+
*-------------------------------------------------------------------------*/
|
243
|
+
void SATEncoder::build_word_tags() {
|
244
|
+
for (int w = 0; w < _sent->length; w++) {
|
245
|
+
_word_tags.push_back(WordTag(w, _variables, _sent, _opts));
|
246
|
+
int dfs_position = 0;
|
247
|
+
|
248
|
+
if (_sent->word[w].x == NULL) {
|
249
|
+
DEBUG_print("Word ." << w << ".: " << _sent->word[w].string << " (null)" << endl);
|
250
|
+
continue;
|
251
|
+
}
|
252
|
+
|
253
|
+
bool join = _sent->word[w].x->next != NULL;
|
254
|
+
Exp* exp = join ? join_alternatives(w) : _sent->word[w].x->exp;
|
255
|
+
|
256
|
+
#ifdef _DEBUG
|
257
|
+
cout << "Word ." << w << ".: " << _sent->word[w].string << endl;
|
258
|
+
print_expression(exp);
|
259
|
+
cout << endl;
|
260
|
+
#endif
|
261
|
+
|
262
|
+
char name[MAX_VARIABLE_NAME];
|
263
|
+
sprintf(name, "w%d", w);
|
264
|
+
bool leading_right = true;
|
265
|
+
bool leading_left = true;
|
266
|
+
std::vector<int> eps_right, eps_left;
|
267
|
+
|
268
|
+
_word_tags[w].insert_connectors(exp, dfs_position, leading_right, leading_left, eps_right, eps_left, name, true, 0);
|
269
|
+
|
270
|
+
if (join)
|
271
|
+
free_alternatives(exp);
|
272
|
+
}
|
273
|
+
|
274
|
+
for (int wl = 0; wl < _sent->length - 1; wl++) {
|
275
|
+
for (int wr = wl + 1; wr < _sent->length; wr++) {
|
276
|
+
_word_tags[wl].add_matches_with_word(_word_tags[wr]);
|
277
|
+
}
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
void SATEncoder::find_all_matches_between_words(int w1, int w2,
|
282
|
+
std::vector<std::pair<const PositionConnector*, const PositionConnector*> >& matches) {
|
283
|
+
const std::vector<PositionConnector>& w1_right = _word_tags[w1].get_right_connectors();
|
284
|
+
std::vector<PositionConnector>::const_iterator i;
|
285
|
+
for (i = w1_right.begin(); i != w1_right.end(); i++) {
|
286
|
+
const std::vector<PositionConnector*>& w2_left_c = (*i).matches;
|
287
|
+
std::vector<PositionConnector*>::const_iterator j;
|
288
|
+
for (j = w2_left_c.begin(); j != w2_left_c.end(); j++) {
|
289
|
+
if ((*j)->word == w2) {
|
290
|
+
matches.push_back(std::pair<const PositionConnector*, const PositionConnector*>(&(*i), *j));
|
291
|
+
}
|
292
|
+
}
|
293
|
+
}
|
294
|
+
}
|
295
|
+
|
296
|
+
bool SATEncoder::matches_in_interval(int wi, int pi, int l, int r) {
|
297
|
+
for (int w = l; w < r; w++) {
|
298
|
+
if (_word_tags[w].match_possible(wi, pi))
|
299
|
+
return true;
|
300
|
+
}
|
301
|
+
return false;
|
302
|
+
}
|
303
|
+
|
304
|
+
/*-------------------------------------------------------------------------*
|
305
|
+
* S A T I S F A C T I O N *
|
306
|
+
*-------------------------------------------------------------------------*/
|
307
|
+
|
308
|
+
void SATEncoder::generate_satisfaction_conditions() {
|
309
|
+
for (int w = 0; w < _sent->length; w++) {
|
310
|
+
if (_sent->word[w].x == NULL) {
|
311
|
+
DEBUG_print("Word: " << _sent->word[w].string << " : " << "(null)" << endl);
|
312
|
+
handle_null_expression(w);
|
313
|
+
continue;
|
314
|
+
}
|
315
|
+
|
316
|
+
bool join = _sent->word[w].x->next != NULL;
|
317
|
+
Exp* exp = join ? join_alternatives(w) : _sent->word[w].x->exp;
|
318
|
+
|
319
|
+
#ifdef _DEBUG
|
320
|
+
cout << "Word: " << _sent->word[w].string << endl;
|
321
|
+
print_expression(exp);
|
322
|
+
cout << endl;
|
323
|
+
#endif
|
324
|
+
|
325
|
+
char name[MAX_VARIABLE_NAME];
|
326
|
+
sprintf(name, "w%d", w);
|
327
|
+
|
328
|
+
determine_satisfaction(w, name);
|
329
|
+
int dfs_position = 0;
|
330
|
+
generate_satisfaction_for_expression(w, dfs_position, exp, name, 0);
|
331
|
+
|
332
|
+
if (join)
|
333
|
+
free_alternatives(exp);
|
334
|
+
}
|
335
|
+
}
|
336
|
+
|
337
|
+
|
338
|
+
void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, Exp* e, char* var, int parrent_cost) {
|
339
|
+
E_list *l;
|
340
|
+
int total_cost = parrent_cost + e->cost;
|
341
|
+
|
342
|
+
if (e->type == CONNECTOR_type) {
|
343
|
+
dfs_position++;
|
344
|
+
|
345
|
+
generate_satisfaction_for_connector(w, dfs_position, e->u.string, e->dir, e->multi, e->cost, var);
|
346
|
+
|
347
|
+
if (total_cost > _cost_cutoff) {
|
348
|
+
Lit lhs = Lit(_variables->string_cost(var, e->cost));
|
349
|
+
generate_literal(~lhs);
|
350
|
+
}
|
351
|
+
} else {
|
352
|
+
if (e->type == AND_type) {
|
353
|
+
if (e->u.l == NULL) {
|
354
|
+
/* zeroary and */
|
355
|
+
_variables->string_cost(var, e->cost);
|
356
|
+
if (total_cost > _cost_cutoff) {
|
357
|
+
generate_literal(~Lit(_variables->string_cost(var, e->cost)));
|
358
|
+
}
|
359
|
+
} else if (e->u.l != NULL && e->u.l->next == NULL) {
|
360
|
+
/* unary and - skip */
|
361
|
+
generate_satisfaction_for_expression(w, dfs_position, e->u.l->e, var, total_cost);
|
362
|
+
} else {
|
363
|
+
/* n-ary and */
|
364
|
+
int i;
|
365
|
+
|
366
|
+
char new_var[MAX_VARIABLE_NAME];
|
367
|
+
char* last_new_var = new_var;
|
368
|
+
char* last_var = var;
|
369
|
+
while(*last_new_var = *last_var) {
|
370
|
+
last_new_var++;
|
371
|
+
last_var++;
|
372
|
+
}
|
373
|
+
|
374
|
+
vec<Lit> rhs;
|
375
|
+
for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) {
|
376
|
+
// sprintf(new_var, "%sc%d", var, i)
|
377
|
+
char* s = last_new_var;
|
378
|
+
*s++ = 'c';
|
379
|
+
fast_sprintf(s, i);
|
380
|
+
rhs.push(Lit(_variables->string(new_var)));
|
381
|
+
}
|
382
|
+
|
383
|
+
Lit lhs = Lit(_variables->string_cost(var, e->cost));
|
384
|
+
generate_and_definition(lhs, rhs);
|
385
|
+
|
386
|
+
/* Preceeds */
|
387
|
+
int dfs_position_tmp = dfs_position;
|
388
|
+
for (l = e->u.l; l->next != NULL; l = l->next) {
|
389
|
+
generate_conjunct_order_constraints(w, l->e, l->next->e, dfs_position_tmp);
|
390
|
+
}
|
391
|
+
|
392
|
+
/* Recurse */
|
393
|
+
for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) {
|
394
|
+
// sprintf(new_var, "%sc%d", var, i)
|
395
|
+
char* s = last_new_var;
|
396
|
+
*s++ = 'c';
|
397
|
+
fast_sprintf(s, i);
|
398
|
+
|
399
|
+
generate_satisfaction_for_expression(w, dfs_position, l->e, new_var, total_cost);
|
400
|
+
}
|
401
|
+
}
|
402
|
+
} else if (e->type == OR_type) {
|
403
|
+
if (e->u.l == NULL) {
|
404
|
+
/* zeroary or */
|
405
|
+
cerr << "Zeroary OR" << endl;
|
406
|
+
exit(EXIT_FAILURE);
|
407
|
+
} else if (e->u.l != NULL && e->u.l->next == NULL) {
|
408
|
+
/* unary or */
|
409
|
+
generate_satisfaction_for_expression(w, dfs_position, e->u.l->e, var, total_cost);
|
410
|
+
} else {
|
411
|
+
/* n-ary or */
|
412
|
+
int i;
|
413
|
+
|
414
|
+
char new_var[MAX_VARIABLE_NAME];
|
415
|
+
char* last_new_var = new_var;
|
416
|
+
char* last_var = var;
|
417
|
+
while(*last_new_var = *last_var) {
|
418
|
+
last_new_var++;
|
419
|
+
last_var++;
|
420
|
+
}
|
421
|
+
|
422
|
+
vec<Lit> rhs;
|
423
|
+
for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) {
|
424
|
+
// sprintf(new_var, "%sc%d", var, i)
|
425
|
+
char* s = last_new_var;
|
426
|
+
*s++ = 'd';
|
427
|
+
fast_sprintf(s, i);
|
428
|
+
rhs.push(Lit(_variables->string(new_var)));
|
429
|
+
}
|
430
|
+
|
431
|
+
Lit lhs = Lit(_variables->string_cost(var, e->cost));
|
432
|
+
generate_or_definition(lhs, rhs);
|
433
|
+
generate_xor_conditions(rhs);
|
434
|
+
|
435
|
+
/* Recurse */
|
436
|
+
for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) {
|
437
|
+
char* s = last_new_var;
|
438
|
+
*s++ = 'd';
|
439
|
+
fast_sprintf(s, i);
|
440
|
+
|
441
|
+
generate_satisfaction_for_expression(w, dfs_position, l->e, new_var, total_cost);
|
442
|
+
}
|
443
|
+
}
|
444
|
+
}
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
Exp* SATEncoder::join_alternatives(int w) {
|
449
|
+
// join all alternatives using and OR_type node
|
450
|
+
Exp* exp;
|
451
|
+
E_list* or_list = NULL;;
|
452
|
+
for (X_node* x = _sent->word[w].x; x != NULL; x = x->next) {
|
453
|
+
E_list* new_node = (E_list*)xalloc(sizeof(E_list));
|
454
|
+
new_node->e = x->exp;
|
455
|
+
new_node->next = NULL;
|
456
|
+
if (or_list == NULL) {
|
457
|
+
or_list = new_node;
|
458
|
+
} else {
|
459
|
+
E_list *y;
|
460
|
+
for (y = or_list; y->next != NULL; y = y->next)
|
461
|
+
;
|
462
|
+
y->next = new_node;
|
463
|
+
}
|
464
|
+
}
|
465
|
+
exp = (Exp*)xalloc(sizeof(Exp));
|
466
|
+
exp->type = OR_type;
|
467
|
+
exp->u.l = or_list;
|
468
|
+
exp->cost = 0;
|
469
|
+
|
470
|
+
return exp;
|
471
|
+
}
|
472
|
+
|
473
|
+
void SATEncoder::free_alternatives(Exp* exp) {
|
474
|
+
E_list *l = exp->u.l;
|
475
|
+
while (l != NULL) {
|
476
|
+
E_list* next = l->next;
|
477
|
+
xfree(l, sizeof(E_list));
|
478
|
+
l = next;
|
479
|
+
}
|
480
|
+
xfree(exp, sizeof(exp));
|
481
|
+
}
|
482
|
+
|
483
|
+
|
484
|
+
void SATEncoder::generate_link_cw_ordinary_definition(int wi, int pi, const char* Ci, char dir, int cost, int wj) {
|
485
|
+
Lit lhs = Lit(_variables->link_cw(wj, wi, pi, Ci));
|
486
|
+
|
487
|
+
char str[MAX_VARIABLE_NAME];
|
488
|
+
sprintf(str, "w%d", wj);
|
489
|
+
Lit condition = Lit(_variables->string(str));
|
490
|
+
|
491
|
+
vec<Lit> rhs;
|
492
|
+
|
493
|
+
// Collect matches (wi, pi) with word wj
|
494
|
+
std::vector<PositionConnector*>& matches = _word_tags[wi].get(pi)->matches;
|
495
|
+
std::vector<PositionConnector*>::const_iterator i;
|
496
|
+
for (i = matches.begin(); i != matches.end(); i++) {
|
497
|
+
/* TODO: PositionConnector->matches[wj] */
|
498
|
+
if ((*i)->word != wj)
|
499
|
+
continue;
|
500
|
+
|
501
|
+
if (dir == '+') {
|
502
|
+
rhs.push(Lit(_variables->link_cost(wi, pi, Ci,
|
503
|
+
(*i)->word, (*i)->position, (*i)->connector->string,
|
504
|
+
cost + (*i)->cost)));
|
505
|
+
} else if (dir == '-'){
|
506
|
+
rhs.push(Lit(_variables->link((*i)->word, (*i)->position, (*i)->connector->string,
|
507
|
+
wi, pi, Ci)));
|
508
|
+
}
|
509
|
+
}
|
510
|
+
|
511
|
+
// Generate clauses
|
512
|
+
DEBUG_print("--------- link_cw as ordinary down");
|
513
|
+
generate_conditional_lr_implication_or_definition(condition, lhs, rhs);
|
514
|
+
generate_xor_conditions(rhs);
|
515
|
+
DEBUG_print("--------- end link_cw as ordinary down");
|
516
|
+
}
|
517
|
+
|
518
|
+
/*--------------------------------------------------------------------------*
|
519
|
+
* C O N J U N C T O R D E R I N G *
|
520
|
+
*--------------------------------------------------------------------------*/
|
521
|
+
int SATEncoder::num_connectors(Exp* e) {
|
522
|
+
if (e->type == CONNECTOR_type)
|
523
|
+
return 1;
|
524
|
+
else {
|
525
|
+
int num = 0;
|
526
|
+
for (E_list* l = e->u.l; l != NULL; l = l->next) {
|
527
|
+
num += num_connectors(l->e);
|
528
|
+
}
|
529
|
+
return num;
|
530
|
+
}
|
531
|
+
}
|
532
|
+
|
533
|
+
int SATEncoder::empty_connectors(Exp* e, char dir) {
|
534
|
+
if (e->type == CONNECTOR_type) {
|
535
|
+
return e->dir != dir;
|
536
|
+
} else if (e->type == OR_type) {
|
537
|
+
for (E_list* l = e->u.l; l != NULL; l = l->next) {
|
538
|
+
if (empty_connectors(l->e, dir))
|
539
|
+
return true;
|
540
|
+
}
|
541
|
+
return false;
|
542
|
+
} else if (e->type == AND_type) {
|
543
|
+
for (E_list* l = e->u.l; l != NULL; l = l->next) {
|
544
|
+
if (!empty_connectors(l->e, dir))
|
545
|
+
return false;
|
546
|
+
}
|
547
|
+
return true;
|
548
|
+
} else
|
549
|
+
throw std::string("Unkown connector type");
|
550
|
+
}
|
551
|
+
|
552
|
+
int SATEncoder::non_empty_connectors(Exp* e, char dir) {
|
553
|
+
if (e->type == CONNECTOR_type) {
|
554
|
+
return e->dir == dir;
|
555
|
+
} else if (e->type == OR_type) {
|
556
|
+
for (E_list* l = e->u.l; l != NULL; l = l->next) {
|
557
|
+
if (non_empty_connectors(l->e, dir))
|
558
|
+
return true;
|
559
|
+
}
|
560
|
+
return false;
|
561
|
+
} else if (e->type == AND_type) {
|
562
|
+
for (E_list* l = e->u.l; l != NULL; l = l->next) {
|
563
|
+
if (non_empty_connectors(l->e, dir))
|
564
|
+
return true;
|
565
|
+
}
|
566
|
+
return false;
|
567
|
+
} else
|
568
|
+
throw std::string("Unkown connector type");
|
569
|
+
}
|
570
|
+
|
571
|
+
bool SATEncoder::trailing_connectors_and_aux(int w, E_list* l, char dir, int& dfs_position,
|
572
|
+
std::vector<PositionConnector*>& connectors) {
|
573
|
+
if (l == NULL) {
|
574
|
+
return true;
|
575
|
+
} else {
|
576
|
+
int dfs_position_in = dfs_position;
|
577
|
+
dfs_position += num_connectors(l->e);
|
578
|
+
if (trailing_connectors_and_aux(w, l->next, dir, dfs_position, connectors)) {
|
579
|
+
trailing_connectors(w, l->e, dir, dfs_position_in, connectors);
|
580
|
+
}
|
581
|
+
return empty_connectors(l->e, dir);
|
582
|
+
}
|
583
|
+
}
|
584
|
+
|
585
|
+
void SATEncoder::trailing_connectors(int w, Exp* exp, char dir, int& dfs_position,
|
586
|
+
std::vector<PositionConnector*>& connectors) {
|
587
|
+
if (exp->type == CONNECTOR_type) {
|
588
|
+
dfs_position++;
|
589
|
+
if (exp->dir == dir) {
|
590
|
+
connectors.push_back(_word_tags[w].get(dfs_position));
|
591
|
+
}
|
592
|
+
} else if (exp->type == OR_type) {
|
593
|
+
for (E_list* l = exp->u.l; l != NULL; l = l->next) {
|
594
|
+
trailing_connectors(w, l->e, dir, dfs_position, connectors);
|
595
|
+
}
|
596
|
+
} else if (exp->type == AND_type) {
|
597
|
+
trailing_connectors_and_aux(w, exp->u.l, dir, dfs_position, connectors);
|
598
|
+
}
|
599
|
+
}
|
600
|
+
|
601
|
+
void SATEncoder::certainly_non_trailing(int w, Exp* exp, char dir, int& dfs_position,
|
602
|
+
std::vector<PositionConnector*>& connectors, bool has_right) {
|
603
|
+
if (exp->type == CONNECTOR_type) {
|
604
|
+
dfs_position++;
|
605
|
+
if (exp->dir == dir && has_right) {
|
606
|
+
connectors.push_back(_word_tags[w].get(dfs_position));
|
607
|
+
}
|
608
|
+
} else if (exp->type == OR_type) {
|
609
|
+
for (E_list* l = exp->u.l; l != NULL; l = l->next) {
|
610
|
+
certainly_non_trailing(w, l->e, dir, dfs_position, connectors, has_right);
|
611
|
+
}
|
612
|
+
} else if (exp->type == AND_type) {
|
613
|
+
if (has_right) {
|
614
|
+
for (E_list* l = exp->u.l; l != NULL; l = l->next) {
|
615
|
+
certainly_non_trailing(w, l->e, dir, dfs_position, connectors, true);
|
616
|
+
}
|
617
|
+
} else {
|
618
|
+
for (E_list* l = exp->u.l; l != NULL; l = l->next) {
|
619
|
+
has_right = false;
|
620
|
+
for (E_list* m = l->next; m != NULL; m = m->next) {
|
621
|
+
if (non_empty_connectors(m->e, dir) && !empty_connectors(m->e, dir)) {
|
622
|
+
has_right = true;
|
623
|
+
break;
|
624
|
+
}
|
625
|
+
}
|
626
|
+
certainly_non_trailing(w, l->e, dir, dfs_position, connectors, has_right);
|
627
|
+
}
|
628
|
+
}
|
629
|
+
}
|
630
|
+
}
|
631
|
+
|
632
|
+
void SATEncoder::leading_connectors(int w, Exp* exp, char dir, int& dfs_position, vector<PositionConnector*>& connectors) {
|
633
|
+
if (exp->type == CONNECTOR_type) {
|
634
|
+
dfs_position++;
|
635
|
+
if (exp->dir == dir) {
|
636
|
+
connectors.push_back(_word_tags[w].get(dfs_position));
|
637
|
+
}
|
638
|
+
} else if (exp->type == OR_type) {
|
639
|
+
for (E_list* l = exp->u.l; l != NULL; l = l->next) {
|
640
|
+
leading_connectors(w, l->e, dir, dfs_position, connectors);
|
641
|
+
}
|
642
|
+
} else if (exp->type == AND_type) {
|
643
|
+
E_list* l;
|
644
|
+
for (l = exp->u.l; l != NULL; l = l->next) {
|
645
|
+
leading_connectors(w, l->e, dir, dfs_position, connectors);
|
646
|
+
if (!empty_connectors(l->e, dir))
|
647
|
+
break;
|
648
|
+
}
|
649
|
+
|
650
|
+
if (l != NULL) {
|
651
|
+
for (l = l->next; l != NULL; l = l->next)
|
652
|
+
dfs_position += num_connectors(l->e);
|
653
|
+
}
|
654
|
+
}
|
655
|
+
}
|
656
|
+
|
657
|
+
void SATEncoder::generate_conjunct_order_constraints(int w, Exp *e1, Exp* e2, int& dfs_position) {
|
658
|
+
DEBUG_print("----- conjunct order constraints");
|
659
|
+
int dfs_position_e1 = dfs_position;
|
660
|
+
std::vector<PositionConnector*> last_right_in_e1, first_right_in_e2;
|
661
|
+
trailing_connectors(w, e1, '+', dfs_position_e1, last_right_in_e1);
|
662
|
+
|
663
|
+
int dfs_position_e2 = dfs_position_e1;
|
664
|
+
leading_connectors(w, e2, '+', dfs_position_e2, first_right_in_e2);
|
665
|
+
|
666
|
+
vec<Lit> clause;
|
667
|
+
|
668
|
+
if (!last_right_in_e1.empty() && !first_right_in_e2.empty()) {
|
669
|
+
std::vector<PositionConnector*>::iterator i, j;
|
670
|
+
for (i = last_right_in_e1.begin(); i != last_right_in_e1.end(); i++) {
|
671
|
+
std::vector<PositionConnector*>& matches_e1 = (*i)->matches;
|
672
|
+
|
673
|
+
for (j = first_right_in_e2.begin(); j != first_right_in_e2.end(); j++) {
|
674
|
+
std::vector<PositionConnector*>& matches_e2 = (*j)->matches;
|
675
|
+
std::vector<PositionConnector*>::const_iterator m1, m2;
|
676
|
+
|
677
|
+
std::vector<int> mw1;
|
678
|
+
for (m1 = matches_e1.begin(); m1 != matches_e1.end(); m1++) {
|
679
|
+
if ((m1+1) == matches_e1.end() || (*m1)->word != (*(m1 + 1))->word)
|
680
|
+
mw1.push_back((*m1)->word);
|
681
|
+
}
|
682
|
+
|
683
|
+
std::vector<int> mw2;
|
684
|
+
for (m2 = matches_e2.begin(); m2 != matches_e2.end(); m2++) {
|
685
|
+
if ((m2+1) == matches_e2.end() || (*m2)->word != (*(m2 + 1))->word)
|
686
|
+
mw2.push_back((*m2)->word);
|
687
|
+
}
|
688
|
+
|
689
|
+
std::vector<int>::const_iterator mw1i, mw2i;
|
690
|
+
for (mw1i = mw1.begin(); mw1i != mw1.end(); mw1i++) {
|
691
|
+
for (mw2i = mw2.begin(); mw2i != mw2.end(); mw2i++) {
|
692
|
+
if (*mw1i >= *mw2i) {
|
693
|
+
clause.growTo(2);
|
694
|
+
clause[0] = ~Lit(_variables->link_cw(*mw1i, w, (*i)->position, (*i)->connector->string));
|
695
|
+
clause[1] = ~Lit(_variables->link_cw(*mw2i, w, (*j)->position, (*j)->connector->string));
|
696
|
+
add_clause(clause);
|
697
|
+
}
|
698
|
+
}
|
699
|
+
}
|
700
|
+
}
|
701
|
+
}
|
702
|
+
}
|
703
|
+
|
704
|
+
DEBUG_print("----");
|
705
|
+
dfs_position_e1 = dfs_position;
|
706
|
+
std::vector<PositionConnector*> last_left_in_e1, first_left_in_e2;
|
707
|
+
trailing_connectors(w, e1, '-', dfs_position_e1, last_left_in_e1);
|
708
|
+
|
709
|
+
dfs_position_e2 = dfs_position_e1;
|
710
|
+
leading_connectors(w, e2, '-', dfs_position_e2, first_left_in_e2);
|
711
|
+
|
712
|
+
if (!last_left_in_e1.empty() && !first_left_in_e2.empty()) {
|
713
|
+
std::vector<PositionConnector*>::iterator i, j;
|
714
|
+
for (i = last_left_in_e1.begin(); i != last_left_in_e1.end(); i++) {
|
715
|
+
std::vector<PositionConnector*>& matches_e1 = (*i)->matches;
|
716
|
+
|
717
|
+
for (j = first_left_in_e2.begin(); j != first_left_in_e2.end(); j++) {
|
718
|
+
std::vector<PositionConnector*>& matches_e2 = (*j)->matches;
|
719
|
+
|
720
|
+
std::vector<PositionConnector*>::const_iterator m1, m2;
|
721
|
+
|
722
|
+
|
723
|
+
std::vector<int> mw1;
|
724
|
+
for (m1 = matches_e1.begin(); m1 != matches_e1.end(); m1++) {
|
725
|
+
if ((m1+1) == matches_e1.end() || (*m1)->word != (*(m1 + 1))->word)
|
726
|
+
mw1.push_back((*m1)->word);
|
727
|
+
}
|
728
|
+
|
729
|
+
std::vector<int> mw2;
|
730
|
+
for (m2 = matches_e2.begin(); m2 != matches_e2.end(); m2++) {
|
731
|
+
if ((m2+1) == matches_e2.end() || (*m2)->word != (*(m2 + 1))->word)
|
732
|
+
mw2.push_back((*m2)->word);
|
733
|
+
}
|
734
|
+
|
735
|
+
std::vector<int>::const_iterator mw1i, mw2i;
|
736
|
+
for (mw1i = mw1.begin(); mw1i != mw1.end(); mw1i++) {
|
737
|
+
for (mw2i = mw2.begin(); mw2i != mw2.end(); mw2i++) {
|
738
|
+
if (*mw1i <= *mw2i) {
|
739
|
+
clause.growTo(2);
|
740
|
+
clause[0] = ~Lit(_variables->link_cw(*mw1i, w, (*i)->position, (*i)->connector->string));
|
741
|
+
clause[1] = ~Lit(_variables->link_cw(*mw2i, w, (*j)->position, (*j)->connector->string));
|
742
|
+
add_clause(clause);
|
743
|
+
}
|
744
|
+
}
|
745
|
+
}
|
746
|
+
}
|
747
|
+
}
|
748
|
+
}
|
749
|
+
|
750
|
+
dfs_position = dfs_position_e1;
|
751
|
+
|
752
|
+
DEBUG_print("---end conjunct order constraints");
|
753
|
+
}
|
754
|
+
|
755
|
+
|
756
|
+
|
757
|
+
/*--------------------------------------------------------------------------*
|
758
|
+
* C O N N E C T I V I T Y *
|
759
|
+
*--------------------------------------------------------------------------*/
|
760
|
+
|
761
|
+
#ifdef _CONNECTIVITY_
|
762
|
+
void SATEncoder::generate_connectivity() {
|
763
|
+
for (int w = 1; w < _sent->length; w++) {
|
764
|
+
if (!_linkage_possible(0, w)) {
|
765
|
+
vec<Lit> clause;
|
766
|
+
clause.push(~Lit(_variables->con(w, 1)));
|
767
|
+
generate_and(clause);
|
768
|
+
}
|
769
|
+
else {
|
770
|
+
generate_equivalence_definition(Lit(_variables->con(w, 1)),
|
771
|
+
Lit(_variables->linked(0, w)));
|
772
|
+
}
|
773
|
+
}
|
774
|
+
|
775
|
+
for (int d = 2; d < _sent->length; d++) {
|
776
|
+
for (int w = 1; w < _sent->length; w++) {
|
777
|
+
Lit lhs = Lit(_variables->con(w, d));
|
778
|
+
|
779
|
+
vec<Lit> rhs;
|
780
|
+
rhs.push(Lit(_variables->con(w, d-1)));
|
781
|
+
for (int w1 = 1; w1 < _sent->length; w1++) {
|
782
|
+
if (w == w1)
|
783
|
+
continue;
|
784
|
+
|
785
|
+
if (!_linkage_possible(std::min(w, w1), std::max(w, w1))) {
|
786
|
+
continue;
|
787
|
+
}
|
788
|
+
rhs.push(Lit(_variables->l_con(w, w1, d-1)));
|
789
|
+
}
|
790
|
+
generate_or_definition(lhs, rhs);
|
791
|
+
|
792
|
+
|
793
|
+
/* lc definitions*/
|
794
|
+
for (int w1 = 1; w1 < _sent->length; w1++) {
|
795
|
+
if (w == w1)
|
796
|
+
continue;
|
797
|
+
|
798
|
+
int mi = std::min(w, w1), ma = std::max(w, w1);
|
799
|
+
if (!_linked_possible(mi, ma))
|
800
|
+
continue;
|
801
|
+
|
802
|
+
Lit lhs = Lit(_variables->l_con(w, w1, d-1));
|
803
|
+
vec<Lit> rhs(2);
|
804
|
+
rhs[0] = Lit(_variables->linked(mi, ma));
|
805
|
+
rhs[1] = Lit(_variables->con(w1, d-1));
|
806
|
+
generate_classical_and_definition(lhs, rhs);
|
807
|
+
}
|
808
|
+
}
|
809
|
+
}
|
810
|
+
|
811
|
+
|
812
|
+
for (int w = 1; w < _sent->length; w++) {
|
813
|
+
generate_literal(Lit(_variables->con(w, _sent->length-1)));
|
814
|
+
}
|
815
|
+
}
|
816
|
+
#endif
|
817
|
+
|
818
|
+
void SATEncoder::dfs(int node, const MatrixUpperTriangle<int>& graph, int component, std::vector<int>& components) {
|
819
|
+
if (components[node] != -1)
|
820
|
+
return;
|
821
|
+
|
822
|
+
components[node] = component;
|
823
|
+
for (int other_node = node + 1; other_node < components.size(); other_node++) {
|
824
|
+
if (graph(node, other_node))
|
825
|
+
dfs(other_node, graph, component, components);
|
826
|
+
}
|
827
|
+
for (int other_node = 0; other_node < node; other_node++) {
|
828
|
+
if (graph(other_node, node))
|
829
|
+
dfs(other_node, graph, component, components);
|
830
|
+
}
|
831
|
+
}
|
832
|
+
|
833
|
+
|
834
|
+
bool SATEncoder::connectivity_components(std::vector<int>& components) {
|
835
|
+
// get satisfied linked(wi, wj) variables
|
836
|
+
const std::vector<int>& linked_variables = _variables->linked_variables();
|
837
|
+
std::vector<int> satisfied_linked_variables;
|
838
|
+
for (std::vector<int>::const_iterator i = linked_variables.begin(); i != linked_variables.end(); i++) {
|
839
|
+
int var = *i;
|
840
|
+
if (_solver->model[var] == l_True) {
|
841
|
+
satisfied_linked_variables.push_back(var);
|
842
|
+
}
|
843
|
+
}
|
844
|
+
|
845
|
+
// build the connectivity graph
|
846
|
+
MatrixUpperTriangle<int> graph(_sent->length, 0);
|
847
|
+
std::vector<int>::const_iterator i;
|
848
|
+
for (i = satisfied_linked_variables.begin(); i != satisfied_linked_variables.end(); i++) {
|
849
|
+
graph.set(_variables->linked_variable(*i)->left_word,
|
850
|
+
_variables->linked_variable(*i)->right_word, 1);
|
851
|
+
}
|
852
|
+
|
853
|
+
// determine the connectivity components
|
854
|
+
components.resize(_sent->length);
|
855
|
+
std::fill(components.begin(), components.end(), -1);
|
856
|
+
for (int node = 0; node < _sent->length; node++)
|
857
|
+
dfs(node, graph, node, components);
|
858
|
+
bool connected = true;
|
859
|
+
for (int node = 0; node < _sent->length; node++) {
|
860
|
+
if (components[node] != 0) {
|
861
|
+
connected = false;
|
862
|
+
}
|
863
|
+
}
|
864
|
+
|
865
|
+
return connected;
|
866
|
+
}
|
867
|
+
|
868
|
+
void SATEncoder::generate_disconnectivity_prohibiting(std::vector<int> components) {
|
869
|
+
// vector of unique components
|
870
|
+
std::vector<int> different_components = components;
|
871
|
+
std::sort(different_components.begin(), different_components.end());
|
872
|
+
different_components.erase(std::unique(different_components.begin(), different_components.end()),
|
873
|
+
different_components.end());
|
874
|
+
|
875
|
+
// Each connected component must contain a branch going out of it
|
876
|
+
std::vector<int>::const_iterator c;
|
877
|
+
for (c = different_components.begin(); c != different_components.end(); c++) {
|
878
|
+
vec<Lit> clause;
|
879
|
+
const std::vector<int>& linked_variables = _variables->linked_variables();
|
880
|
+
for (std::vector<int>::const_iterator i = linked_variables.begin(); i != linked_variables.end(); i++) {
|
881
|
+
int var = *i;
|
882
|
+
const Variables::LinkedVar* lv = _variables->linked_variable(var);
|
883
|
+
if ((components[lv->left_word] == *c && components[lv->right_word] != *c) ||
|
884
|
+
(components[lv->left_word] != *c && components[lv->right_word] == *c)) {
|
885
|
+
clause.push(Lit(var));
|
886
|
+
}
|
887
|
+
}
|
888
|
+
_solver->addConflictingClause(clause);
|
889
|
+
if (different_components.size() == 2)
|
890
|
+
break;
|
891
|
+
}
|
892
|
+
}
|
893
|
+
|
894
|
+
/*--------------------------------------------------------------------------*
|
895
|
+
* P L A N A R I T Y *
|
896
|
+
*--------------------------------------------------------------------------*/
|
897
|
+
void SATEncoder::generate_planarity_conditions() {
|
898
|
+
vec<Lit> clause;
|
899
|
+
for (int wi1 = 0; wi1 < _sent->length; wi1++) {
|
900
|
+
for (int wj1 = wi1+1; wj1 < _sent->length; wj1++) {
|
901
|
+
for (int wi2 = wj1+1; wi2 < _sent->length; wi2++) {
|
902
|
+
if (!_linked_possible(wi1, wi2))
|
903
|
+
continue;
|
904
|
+
for (int wj2 = wi2+1; wj2 < _sent->length; wj2++) {
|
905
|
+
if (!_linked_possible(wj1, wj2))
|
906
|
+
continue;
|
907
|
+
clause.growTo(2);
|
908
|
+
clause[0] = ~Lit(_variables->linked(wi1, wi2));
|
909
|
+
clause[1] = ~Lit(_variables->linked(wj1, wj2));
|
910
|
+
add_clause(clause);
|
911
|
+
}
|
912
|
+
}
|
913
|
+
}
|
914
|
+
}
|
915
|
+
|
916
|
+
// generate_linked_min_max_planarity();
|
917
|
+
}
|
918
|
+
|
919
|
+
/*--------------------------------------------------------------------------*
|
920
|
+
* P O W E R P R U N I N G *
|
921
|
+
*--------------------------------------------------------------------------*/
|
922
|
+
|
923
|
+
void SATEncoder::generate_epsilon_definitions() {
|
924
|
+
for (int w = 0; w < _sent->length; w++) {
|
925
|
+
if (_sent->word[w].x == NULL) {
|
926
|
+
continue;
|
927
|
+
}
|
928
|
+
|
929
|
+
bool join = _sent->word[w].x->next != NULL;
|
930
|
+
Exp* exp = join ? join_alternatives(w) : _sent->word[w].x->exp;
|
931
|
+
|
932
|
+
char name[MAX_VARIABLE_NAME];
|
933
|
+
sprintf(name, "w%d", w);
|
934
|
+
|
935
|
+
int dfs_position;
|
936
|
+
|
937
|
+
dfs_position = 0;
|
938
|
+
generate_epsilon_for_expression(w, dfs_position, exp, name, true, '+');
|
939
|
+
|
940
|
+
dfs_position = 0;
|
941
|
+
generate_epsilon_for_expression(w, dfs_position, exp, name, true, '-');
|
942
|
+
|
943
|
+
if (join)
|
944
|
+
free_alternatives(exp);
|
945
|
+
}
|
946
|
+
}
|
947
|
+
|
948
|
+
bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* e,
|
949
|
+
char* var, bool root, char dir) {
|
950
|
+
E_list *l;
|
951
|
+
if (e->type == CONNECTOR_type) {
|
952
|
+
dfs_position++;
|
953
|
+
if (var != NULL) {
|
954
|
+
if (e->dir == dir) {
|
955
|
+
// generate_literal(-_variables->epsilon(name, var, e->dir));
|
956
|
+
return false;
|
957
|
+
} else {
|
958
|
+
generate_equivalence_definition(Lit(_variables->epsilon(var, dir)),
|
959
|
+
Lit(_variables->string(var)));
|
960
|
+
return true;
|
961
|
+
}
|
962
|
+
}
|
963
|
+
} else if (e->type == AND_type) {
|
964
|
+
if (e->u.l == NULL) {
|
965
|
+
/* zeroary and */
|
966
|
+
generate_equivalence_definition(Lit(_variables->string(var)),
|
967
|
+
Lit(_variables->epsilon(var, dir)));
|
968
|
+
return true;
|
969
|
+
} else
|
970
|
+
if (e->u.l != NULL && e->u.l->next == NULL) {
|
971
|
+
/* unary and - skip */
|
972
|
+
return generate_epsilon_for_expression(w, dfs_position, e->u.l->e, var, root, dir);
|
973
|
+
} else {
|
974
|
+
/* Recurse */
|
975
|
+
E_list* l;
|
976
|
+
int i;
|
977
|
+
bool eps = true;
|
978
|
+
|
979
|
+
char new_var[MAX_VARIABLE_NAME];
|
980
|
+
char* last_new_var = new_var;
|
981
|
+
char* last_var = var;
|
982
|
+
while(*last_new_var = *last_var) {
|
983
|
+
last_new_var++;
|
984
|
+
last_var++;
|
985
|
+
}
|
986
|
+
|
987
|
+
|
988
|
+
for (i = 0, l = e->u.l; l != NULL; l = l->next, i++) {
|
989
|
+
// sprintf(new_var, "%sc%d", var, i)
|
990
|
+
char* s = last_new_var;
|
991
|
+
*s++ = 'c';
|
992
|
+
fast_sprintf(s, i);
|
993
|
+
|
994
|
+
if (!generate_epsilon_for_expression(w, dfs_position, l->e, new_var, false, dir)) {
|
995
|
+
eps = false;
|
996
|
+
break;
|
997
|
+
}
|
998
|
+
}
|
999
|
+
|
1000
|
+
if (l != NULL) {
|
1001
|
+
for (l = l->next; l != NULL; l = l->next)
|
1002
|
+
dfs_position += num_connectors(l->e);
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
if (!root && eps) {
|
1006
|
+
Lit lhs = Lit(_variables->epsilon(var, dir));
|
1007
|
+
vec<Lit> rhs;
|
1008
|
+
for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) {
|
1009
|
+
// sprintf(new_var, "%sc%d", var, i)
|
1010
|
+
char* s = last_new_var;
|
1011
|
+
*s++ = 'c';
|
1012
|
+
fast_sprintf(s, i);
|
1013
|
+
rhs.push(Lit(_variables->epsilon(new_var, dir)));
|
1014
|
+
}
|
1015
|
+
generate_classical_and_definition(lhs, rhs);
|
1016
|
+
}
|
1017
|
+
return eps;
|
1018
|
+
}
|
1019
|
+
} else if (e->type == OR_type) {
|
1020
|
+
if (e->u.l != NULL && e->u.l->next == NULL) {
|
1021
|
+
/* unary or - skip */
|
1022
|
+
return generate_epsilon_for_expression(w, dfs_position, e->u.l->e, var, root, dir);
|
1023
|
+
} else {
|
1024
|
+
/* Recurse */
|
1025
|
+
E_list* l;
|
1026
|
+
int i;
|
1027
|
+
bool eps = false;
|
1028
|
+
|
1029
|
+
char new_var[MAX_VARIABLE_NAME];
|
1030
|
+
char* last_new_var = new_var;
|
1031
|
+
char* last_var = var;
|
1032
|
+
while(*last_new_var = *last_var) {
|
1033
|
+
last_new_var++;
|
1034
|
+
last_var++;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
vec<Lit> rhs;
|
1038
|
+
for (i = 0, l = e->u.l; l != NULL; l = l->next, i++) {
|
1039
|
+
// sprintf(new_var, "%sc%d", var, i)
|
1040
|
+
char* s = last_new_var;
|
1041
|
+
*s++ = 'd';
|
1042
|
+
fast_sprintf(s, i);
|
1043
|
+
|
1044
|
+
if (generate_epsilon_for_expression(w, dfs_position, l->e, new_var, false, dir) && !root) {
|
1045
|
+
rhs.push(Lit(_variables->epsilon(new_var, dir)));
|
1046
|
+
eps = true;
|
1047
|
+
}
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
if (!root && eps) {
|
1051
|
+
Lit lhs = Lit(_variables->epsilon(var, dir));
|
1052
|
+
generate_or_definition(lhs, rhs);
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
return eps;
|
1056
|
+
}
|
1057
|
+
}
|
1058
|
+
return false;
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
void SATEncoder::power_prune() {
|
1062
|
+
generate_epsilon_definitions();
|
1063
|
+
|
1064
|
+
// on two non-adjacent words, a pair of connectors can be used only
|
1065
|
+
// if not [both of them are the deepest].
|
1066
|
+
|
1067
|
+
for (int wl = 0; wl < _sent->length - 2; wl++) {
|
1068
|
+
const std::vector<PositionConnector>& rc = _word_tags[wl].get_right_connectors();
|
1069
|
+
std::vector<PositionConnector>::const_iterator rci;
|
1070
|
+
for (rci = rc.begin(); rci != rc.end(); rci++) {
|
1071
|
+
if (!(*rci).leading_right || (*rci).connector->multi)
|
1072
|
+
continue;
|
1073
|
+
|
1074
|
+
const std::vector<PositionConnector*>& matches = rci->matches;
|
1075
|
+
for (std::vector<PositionConnector*>::const_iterator lci = matches.begin(); lci != matches.end(); lci++) {
|
1076
|
+
if (!(*lci)->leading_left || (*lci)->connector->multi || (*lci)->word <= wl + 2)
|
1077
|
+
continue;
|
1078
|
+
|
1079
|
+
// printf("LR: .%d. .%d. %s\n", wl, rci->position, rci->connector->string);
|
1080
|
+
// printf("LL: .%d. .%d. %s\n", (*lci)->word, (*lci)->position, (*lci)->connector->string);
|
1081
|
+
|
1082
|
+
vec<Lit> clause;
|
1083
|
+
for (std::vector<int>::const_iterator i = rci->eps_right.begin(); i != rci->eps_right.end(); i++) {
|
1084
|
+
clause.push(~Lit(*i));
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
for (std::vector<int>::const_iterator i = (*lci)->eps_left.begin(); i != (*lci)->eps_left.end(); i++) {
|
1088
|
+
clause.push(~Lit(*i));
|
1089
|
+
}
|
1090
|
+
|
1091
|
+
add_additional_power_pruning_conditions(clause, wl, (*lci)->word);
|
1092
|
+
|
1093
|
+
clause.push(~Lit(_variables->link(wl, rci->position, rci->connector->string,
|
1094
|
+
(*lci)->word, (*lci)->position, (*lci)->connector->string)));
|
1095
|
+
add_clause(clause);
|
1096
|
+
}
|
1097
|
+
}
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
/*
|
1101
|
+
// on two adjacent words, a pair of connectors can be used only if
|
1102
|
+
// they're the deepest ones on their disjuncts
|
1103
|
+
for (int wl = 0; wl < _sent->length - 2; wl++) {
|
1104
|
+
const std::vector<PositionConnector>& rc = _word_tags[wl].get_right_connectors();
|
1105
|
+
std::vector<PositionConnector>::const_iterator rci;
|
1106
|
+
for (rci = rc.begin(); rci != rc.end(); rci++) {
|
1107
|
+
if (!(*rci).leading_right)
|
1108
|
+
continue;
|
1109
|
+
|
1110
|
+
const std::vector<PositionConnector*>& matches = rci->matches;
|
1111
|
+
for (std::vector<PositionConnector*>::const_iterator lci = matches.begin(); lci != matches.end(); lci++) {
|
1112
|
+
if (!(*lci)->leading_left || (*lci)->word != wl + 1)
|
1113
|
+
continue;
|
1114
|
+
int link = _variables->link(wl, rci->position, rci->connector->string,
|
1115
|
+
(*lci)->word, (*lci)->position, (*lci)->connector->string);
|
1116
|
+
std::vector<int> clause(2);
|
1117
|
+
clause[0] = -link;
|
1118
|
+
|
1119
|
+
for (std::vector<int>::const_iterator i = rci->eps_right.begin(); i != rci->eps_right.end(); i++) {
|
1120
|
+
clause[1] = *i;
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
for (std::vector<int>::const_iterator i = (*lci)->eps_left.begin(); i != (*lci)->eps_left.end(); i++) {
|
1124
|
+
clause[1] = *i;
|
1125
|
+
}
|
1126
|
+
|
1127
|
+
add_clause(clause);
|
1128
|
+
}
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
|
1133
|
+
// Two deep connectors cannot match (deep means notlast)
|
1134
|
+
std::vector<std::vector<PositionConnector*> > certainly_deep_left(_sent->length), certainly_deep_right(_sent->length);
|
1135
|
+
for (int w = 0; w < _sent->length; w++) {
|
1136
|
+
if (_sent->word[w].x == NULL)
|
1137
|
+
continue;
|
1138
|
+
|
1139
|
+
bool join = _sent->word[w].x->next != NULL;
|
1140
|
+
Exp* exp = join ? join_alternatives(w) : _sent->word[w].x->exp;
|
1141
|
+
|
1142
|
+
int dfs_position = 0;
|
1143
|
+
certainly_non_trailing(w, exp, '+', dfs_position, certainly_deep_right[w], false);
|
1144
|
+
dfs_position = 0;
|
1145
|
+
certainly_non_trailing(w, exp, '-', dfs_position, certainly_deep_left[w], false);
|
1146
|
+
|
1147
|
+
if (join)
|
1148
|
+
free_alternatives(exp);
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
for (int w = 0; w < _sent->length; w++) {
|
1152
|
+
std::vector<PositionConnector*>::const_iterator i;
|
1153
|
+
for (i = certainly_deep_right[w].begin(); i != certainly_deep_right[w].end(); i++) {
|
1154
|
+
const std::vector<PositionConnector*>& matches = (*i)->matches;
|
1155
|
+
std::vector<PositionConnector*>::const_iterator j;
|
1156
|
+
for (j = matches.begin(); j != matches.end(); j++) {
|
1157
|
+
if (std::find(certainly_deep_left[(*j)->word].begin(), certainly_deep_left[(*j)->word].end(),
|
1158
|
+
*j) != certainly_deep_left[(*j)->word].end()) {
|
1159
|
+
generate_literal(-_variables->link((*i)->word, (*i)->position, (*i)->connector->string,
|
1160
|
+
(*j)->word, (*j)->position, (*j)->connector->string));
|
1161
|
+
}
|
1162
|
+
}
|
1163
|
+
}
|
1164
|
+
}
|
1165
|
+
*/
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
/*--------------------------------------------------------------------------*
|
1169
|
+
* P O S T P R O C E S S I N G & P P P R U N I N G *
|
1170
|
+
*--------------------------------------------------------------------------*/
|
1171
|
+
void SATEncoder::pp_prune() {
|
1172
|
+
const std::vector<int>& link_variables = _variables->link_variables();
|
1173
|
+
|
1174
|
+
|
1175
|
+
if (_sent->dict->postprocessor == NULL)
|
1176
|
+
return;
|
1177
|
+
|
1178
|
+
pp_knowledge * knowledge;
|
1179
|
+
knowledge = _sent->dict->postprocessor->knowledge;
|
1180
|
+
|
1181
|
+
for (int i=0; i<knowledge->n_contains_one_rules; i++) {
|
1182
|
+
pp_rule rule;
|
1183
|
+
const char * selector;
|
1184
|
+
pp_linkset * link_set;
|
1185
|
+
|
1186
|
+
rule = knowledge->contains_one_rules[i];
|
1187
|
+
selector = rule.selector; /* selector string for this rule */
|
1188
|
+
link_set = rule.link_set; /* the set of criterion links */
|
1189
|
+
|
1190
|
+
|
1191
|
+
vec<Lit> triggers;
|
1192
|
+
for (int i = 0; i < link_variables.size(); i++) {
|
1193
|
+
const Variables::LinkVar* var = _variables->link_variable(link_variables[i]);
|
1194
|
+
if (post_process_match(rule.selector, var->label)) {
|
1195
|
+
triggers.push(Lit(link_variables[i]));
|
1196
|
+
}
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
if (triggers.size() == 0)
|
1200
|
+
continue;
|
1201
|
+
|
1202
|
+
vec<Lit> criterions;
|
1203
|
+
for (int j = 0; j < link_variables.size(); j++) {
|
1204
|
+
pp_linkset_node *p;
|
1205
|
+
for (int hashval = 0; hashval < link_set->hash_table_size; hashval++) {
|
1206
|
+
for (p = link_set->hash_table[hashval]; p!=NULL; p=p->next) {
|
1207
|
+
const Variables::LinkVar* var = _variables->link_variable(link_variables[j]);
|
1208
|
+
if (post_process_match(p->str, var->label)) {
|
1209
|
+
criterions.push(Lit(link_variables[j]));
|
1210
|
+
}
|
1211
|
+
}
|
1212
|
+
}
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
DEBUG_print("---pp_pruning--");
|
1216
|
+
for (int k = 0; k < triggers.size(); k++) {
|
1217
|
+
vec<Lit> clause(criterions.size() + 1);
|
1218
|
+
for (int i = 0; i < criterions.size(); i++)
|
1219
|
+
clause[i] = criterions[i];
|
1220
|
+
clause[criterions.size()] = (~triggers[k]);
|
1221
|
+
add_clause(clause);
|
1222
|
+
}
|
1223
|
+
DEBUG_print("---end pp_pruning--");
|
1224
|
+
}
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
/* TODO: replace with analyze_xxx_linkage */
|
1228
|
+
bool SATEncoder::post_process_linkage(Linkage linkage)
|
1229
|
+
{
|
1230
|
+
if (parse_options_get_use_fat_links(_opts) &&
|
1231
|
+
set_has_fat_down(_sent)) {
|
1232
|
+
Linkage_info li = analyze_fat_linkage(_sent, _opts, PP_SECOND_PASS);
|
1233
|
+
return li.N_violations == 0;
|
1234
|
+
} else {
|
1235
|
+
Linkage_info li = analyze_thin_linkage(_sent, _opts, PP_SECOND_PASS);
|
1236
|
+
return li.N_violations == 0;
|
1237
|
+
}
|
1238
|
+
return 1;
|
1239
|
+
}
|
1240
|
+
|
1241
|
+
/*--------------------------------------------------------------------------*
|
1242
|
+
* D E C O D I N G *
|
1243
|
+
*--------------------------------------------------------------------------*/
|
1244
|
+
Linkage SATEncoder::create_linkage()
|
1245
|
+
{
|
1246
|
+
/* Using exalloc since this is external to the parser itself. */
|
1247
|
+
Linkage linkage = (Linkage) exalloc(sizeof(struct Linkage_s));
|
1248
|
+
memset(linkage, 0, sizeof(struct Linkage_s));
|
1249
|
+
|
1250
|
+
linkage->num_words = _sent->length;
|
1251
|
+
linkage->word = (const char **) exalloc(linkage->num_words*sizeof(char *));
|
1252
|
+
linkage->sent = _sent;
|
1253
|
+
linkage->opts = _opts;
|
1254
|
+
// linkage->info = sent->link_info[k];
|
1255
|
+
|
1256
|
+
if (_sent->parse_info) {
|
1257
|
+
Parse_info pi = _sent->parse_info;
|
1258
|
+
for (int i=0; i< MAX_LINKS; i++) {
|
1259
|
+
free_connectors(pi->link_array[i].lc);
|
1260
|
+
free_connectors(pi->link_array[i].rc);
|
1261
|
+
}
|
1262
|
+
free_parse_info(_sent->parse_info);
|
1263
|
+
_sent->parse_info = NULL;
|
1264
|
+
}
|
1265
|
+
Parse_info pi = _sent->parse_info = parse_info_new(_sent->length);
|
1266
|
+
bool fat = extract_links(pi);
|
1267
|
+
|
1268
|
+
// compute_chosen_words(sent, linkage);
|
1269
|
+
/* TODO: this is just a simplified version of the
|
1270
|
+
compute_chosen_words. */
|
1271
|
+
for (int i = 0; i < _sent->length; i++) {
|
1272
|
+
char *s = (char *) exalloc(strlen(_sent->word[i].string)+1);
|
1273
|
+
strcpy(s, _sent->word[i].string);
|
1274
|
+
linkage->word[i] = s;
|
1275
|
+
}
|
1276
|
+
linkage->num_words = _sent->length;
|
1277
|
+
pi->N_words = _sent->length;
|
1278
|
+
|
1279
|
+
if (!fat || !parse_options_get_use_fat_links(_opts))
|
1280
|
+
extract_thin_linkage(_sent, _opts, linkage);
|
1281
|
+
else
|
1282
|
+
extract_fat_linkage(_sent, _opts, linkage);
|
1283
|
+
|
1284
|
+
linkage_set_current_sublinkage(linkage, 0);
|
1285
|
+
return linkage;
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
void SATEncoder::generate_linkage_prohibiting()
|
1289
|
+
{
|
1290
|
+
vec<Lit> clause;
|
1291
|
+
const std::vector<int>& link_variables = _variables->link_variables();
|
1292
|
+
for (std::vector<int>::const_iterator i = link_variables.begin(); i != link_variables.end(); i++) {
|
1293
|
+
int var = *i;
|
1294
|
+
if (_solver->model[var] == l_True) {
|
1295
|
+
clause.push(~Lit(var));
|
1296
|
+
} else if (_solver->model[var] == l_False) {
|
1297
|
+
clause.push(Lit(var));
|
1298
|
+
}
|
1299
|
+
}
|
1300
|
+
_solver->addConflictingClause(clause);
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
Linkage SATEncoder::get_next_linkage()
|
1304
|
+
{
|
1305
|
+
if (l_False == _solver->solve()) return NULL;
|
1306
|
+
Linkage linkage = create_linkage();
|
1307
|
+
|
1308
|
+
std::vector<int> components;
|
1309
|
+
bool connected = connectivity_components(components);
|
1310
|
+
if (connected) {
|
1311
|
+
// num_connected_linkages++;
|
1312
|
+
|
1313
|
+
if (post_process_linkage(linkage)) {
|
1314
|
+
cout << "Linkage PP OK" << endl;
|
1315
|
+
_sent->num_valid_linkages++;
|
1316
|
+
} else {
|
1317
|
+
cout << "Linkage PP NOT OK" << endl;
|
1318
|
+
}
|
1319
|
+
|
1320
|
+
generate_linkage_prohibiting();
|
1321
|
+
} else {
|
1322
|
+
cout << "Linkage DISCONNECTED" << endl;
|
1323
|
+
generate_disconnectivity_prohibiting(components);
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
_solver->printStats();
|
1327
|
+
return linkage;
|
1328
|
+
}
|
1329
|
+
|
1330
|
+
/*******************************************************************************
|
1331
|
+
* SAT encoding for sentences that do not contain conjunction. *
|
1332
|
+
*******************************************************************************/
|
1333
|
+
|
1334
|
+
void SATEncoderConjunctionFreeSentences::generate_encoding_specific_clauses() {
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
void SATEncoderConjunctionFreeSentences::handle_null_expression(int w) {
|
1338
|
+
// Formula is unsatisfiable
|
1339
|
+
vec<Lit> clause;
|
1340
|
+
add_clause(clause);
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
void SATEncoderConjunctionFreeSentences::determine_satisfaction(int w, char* name) {
|
1344
|
+
// All tags must be satisfied
|
1345
|
+
generate_literal(Lit(_variables->string(name)));
|
1346
|
+
}
|
1347
|
+
|
1348
|
+
void SATEncoderConjunctionFreeSentences::generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
|
1349
|
+
char dir, bool multi, int cost, char* var) {
|
1350
|
+
Lit lhs = Lit(_variables->string_cost(var, cost));
|
1351
|
+
|
1352
|
+
#ifdef _DEBUG
|
1353
|
+
cout << "*** Connector: ." << wi << ". ." << pi << ". " << Ci << dir << endl;
|
1354
|
+
#endif
|
1355
|
+
|
1356
|
+
// words that can potentially match (wi, pi)
|
1357
|
+
int low = (dir == '-') ? 0 : wi + 1;
|
1358
|
+
int hi = (dir == '-') ? wi : _sent->length;
|
1359
|
+
|
1360
|
+
std::vector<int> _w_;
|
1361
|
+
for (int wj = low; wj < hi; wj++) {
|
1362
|
+
// Eliminate words that cannot be connected to (wi, pi)
|
1363
|
+
if (!_word_tags[wj].match_possible(wi, pi))
|
1364
|
+
continue;
|
1365
|
+
|
1366
|
+
// Now we know that there is a potential link between the
|
1367
|
+
// connector (wi, pi) and the word wj
|
1368
|
+
_w_.push_back(wj);
|
1369
|
+
|
1370
|
+
generate_link_cw_ordinary_definition(wi, pi, Ci, dir, cost, wj);
|
1371
|
+
}
|
1372
|
+
|
1373
|
+
vec<Lit> _link_cw_;
|
1374
|
+
for (int i = 0; i < _w_.size(); i++)
|
1375
|
+
_link_cw_.push(Lit(_variables->link_cw(_w_[i], wi, pi, Ci)));
|
1376
|
+
generate_or_definition(lhs, _link_cw_);
|
1377
|
+
|
1378
|
+
DEBUG_print("--------- multi");
|
1379
|
+
if (!multi) {
|
1380
|
+
generate_xor_conditions(_link_cw_);
|
1381
|
+
}
|
1382
|
+
DEBUG_print("--------- end multi");
|
1383
|
+
|
1384
|
+
#ifdef _DEBUG
|
1385
|
+
cout << "*** End Connector: ." << wi << ". ." << pi << ". " << Ci << endl;
|
1386
|
+
#endif
|
1387
|
+
}
|
1388
|
+
|
1389
|
+
void SATEncoderConjunctionFreeSentences::generate_linked_definitions() {
|
1390
|
+
_linked_possible.resize(_sent->length, 1);
|
1391
|
+
|
1392
|
+
DEBUG_print("------- linked definitions");
|
1393
|
+
for (int w1 = 0; w1 < _sent->length; w1++) {
|
1394
|
+
for (int w2 = w1 + 1; w2 < _sent->length; w2++) {
|
1395
|
+
DEBUG_print("---------- ." << w1 << ". ." << w2 << ".");
|
1396
|
+
Lit lhs = Lit(_variables->linked(w1, w2));
|
1397
|
+
|
1398
|
+
vec<Lit> rhs;
|
1399
|
+
const std::vector<PositionConnector>& w1_connectors = _word_tags[w1].get_right_connectors();
|
1400
|
+
std::vector<PositionConnector>::const_iterator c;
|
1401
|
+
for (c = w1_connectors.begin(); c != w1_connectors.end(); c++) {
|
1402
|
+
assert(c->word == w1, "Connector word must match");
|
1403
|
+
if (_word_tags[w2].match_possible(c->word, c->position)) {
|
1404
|
+
rhs.push(Lit(_variables->link_cw(w2, c->word, c->position, c->connector->string)));
|
1405
|
+
}
|
1406
|
+
}
|
1407
|
+
|
1408
|
+
_linked_possible.set(w1, w2, rhs.size() > 0);
|
1409
|
+
generate_or_definition(lhs, rhs);
|
1410
|
+
}
|
1411
|
+
}
|
1412
|
+
DEBUG_print("------- end linked definitions");
|
1413
|
+
}
|
1414
|
+
|
1415
|
+
void SATEncoder::generate_linked_min_max_planarity() {
|
1416
|
+
DEBUG_print("---- linked_max");
|
1417
|
+
for (int w1 = 0; w1 < _sent->length; w1++) {
|
1418
|
+
for (int w2 = 0; w2 < _sent->length; w2++) {
|
1419
|
+
Lit lhs = Lit(_variables->linked_max(w1, w2));
|
1420
|
+
vec<Lit> rhs;
|
1421
|
+
if (w2 < _sent->length - 1) {
|
1422
|
+
rhs.push(Lit(_variables->linked_max(w1, w2 + 1)));
|
1423
|
+
if (w1 != w2 + 1 && _linked_possible(std::min(w1, w2+1), std::max(w1, w2+1)))
|
1424
|
+
rhs.push(~Lit(_variables->linked(std::min(w1, w2+1), std::max(w1, w2+1))));
|
1425
|
+
}
|
1426
|
+
generate_classical_and_definition(lhs, rhs);
|
1427
|
+
}
|
1428
|
+
}
|
1429
|
+
DEBUG_print("---- end linked_max");
|
1430
|
+
|
1431
|
+
|
1432
|
+
DEBUG_print("---- linked_min");
|
1433
|
+
for (int w1 = 0; w1 < _sent->length; w1++) {
|
1434
|
+
for (int w2 = 0; w2 < _sent->length; w2++) {
|
1435
|
+
Lit lhs = Lit(_variables->linked_min(w1, w2));
|
1436
|
+
vec<Lit> rhs;
|
1437
|
+
if (w2 > 0) {
|
1438
|
+
rhs.push(Lit(_variables->linked_min(w1, w2 - 1)));
|
1439
|
+
if (w1 != w2-1 && _linked_possible(std::min(w1, w2 - 1), std::max(w1, w2 - 1)))
|
1440
|
+
rhs.push(~Lit(_variables->linked(std::min(w1, w2 - 1), std::max(w1, w2 - 1))));
|
1441
|
+
}
|
1442
|
+
generate_classical_and_definition(lhs, rhs);
|
1443
|
+
}
|
1444
|
+
}
|
1445
|
+
DEBUG_print("---- end linked_min");
|
1446
|
+
|
1447
|
+
|
1448
|
+
vec<Lit> clause;
|
1449
|
+
for (int wi = 3; wi < _sent->length; wi++) {
|
1450
|
+
for (int wj = 1; wj < wi - 1; wj++) {
|
1451
|
+
for (int wl = wj + 1; wl < wi; wl++) {
|
1452
|
+
clause.growTo(3);
|
1453
|
+
clause[0] = ~Lit(_variables->linked_min(wi, wj));
|
1454
|
+
clause[1] = ~Lit(_variables->linked_max(wi, wl - 1));
|
1455
|
+
clause[2] = Lit(_variables->linked_min(wl, wj));
|
1456
|
+
add_clause(clause);
|
1457
|
+
}
|
1458
|
+
}
|
1459
|
+
}
|
1460
|
+
|
1461
|
+
DEBUG_print("------------");
|
1462
|
+
|
1463
|
+
for (int wi = 0; wi < _sent->length - 1; wi++) {
|
1464
|
+
for (int wj = wi + 1; wj < _sent->length - 1; wj++) {
|
1465
|
+
for (int wl = wi+1; wl < wj; wl++) {
|
1466
|
+
clause.growTo(3);
|
1467
|
+
clause[0] = ~Lit(_variables->linked_max(wi, wj));
|
1468
|
+
clause[1] = ~Lit(_variables->linked_min(wi, wl + 1));
|
1469
|
+
clause[2] = Lit(_variables->linked_max(wl, wj));
|
1470
|
+
add_clause(clause);
|
1471
|
+
}
|
1472
|
+
}
|
1473
|
+
}
|
1474
|
+
|
1475
|
+
DEBUG_print("------------");
|
1476
|
+
clause.clear();
|
1477
|
+
for (int wi = 1; wi < _sent->length; wi++) {
|
1478
|
+
for (int wj = wi + 2; wj < _sent->length - 1; wj++) {
|
1479
|
+
for (int wl = wi + 1; wl < wj; wl++) {
|
1480
|
+
clause.growTo(2);
|
1481
|
+
clause[0] = ~Lit(_variables->linked_min(wi, wj));
|
1482
|
+
clause[1] = Lit(_variables->linked_min(wl, wi));
|
1483
|
+
add_clause(clause);
|
1484
|
+
|
1485
|
+
clause.growTo(2);
|
1486
|
+
clause[0] = ~Lit(_variables->linked_max(wj, wi));
|
1487
|
+
clause[1] = Lit(_variables->linked_max(wl, wj));
|
1488
|
+
add_clause(clause);
|
1489
|
+
}
|
1490
|
+
}
|
1491
|
+
}
|
1492
|
+
}
|
1493
|
+
|
1494
|
+
bool SATEncoderConjunctionFreeSentences::extract_links(Parse_info pi)
|
1495
|
+
{
|
1496
|
+
int current_link = 0;
|
1497
|
+
const std::vector<int>& link_variables = _variables->link_variables();
|
1498
|
+
std::vector<int>::const_iterator i;
|
1499
|
+
for (i = link_variables.begin(); i != link_variables.end(); i++) {
|
1500
|
+
if (_solver->model[*i] != l_True)
|
1501
|
+
continue;
|
1502
|
+
|
1503
|
+
const Variables::LinkVar* var = _variables->link_variable(*i);
|
1504
|
+
if (_solver->model[_variables->linked(var->left_word, var->right_word)] != l_True)
|
1505
|
+
continue;
|
1506
|
+
|
1507
|
+
pi->link_array[current_link].l = var->left_word;
|
1508
|
+
pi->link_array[current_link].r = var->right_word;
|
1509
|
+
// pi->link_array[j].name = var->label;
|
1510
|
+
|
1511
|
+
Connector* connector;
|
1512
|
+
|
1513
|
+
connector = connector_new();
|
1514
|
+
connector->string = var->left_connector;
|
1515
|
+
pi->link_array[current_link].lc = connector;
|
1516
|
+
|
1517
|
+
connector = connector_new();
|
1518
|
+
connector->string = var->right_connector;
|
1519
|
+
pi->link_array[current_link].rc = connector;
|
1520
|
+
|
1521
|
+
current_link++;
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
pi->N_links = current_link;
|
1525
|
+
DEBUG_print("Total: ." << pi->N_links << "." << endl);
|
1526
|
+
return false;
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
|
1530
|
+
/*******************************************************************************
|
1531
|
+
* SAT encoding for sentences that contain conjunction. *
|
1532
|
+
*******************************************************************************/
|
1533
|
+
|
1534
|
+
// Check if a connector is andable
|
1535
|
+
static int is_andable(Sentence sent, Connector* c, char dir) {
|
1536
|
+
/* if no set, then everything is considered andable */
|
1537
|
+
if (sent->dict->andable_connector_set == NULL)
|
1538
|
+
return TRUE;
|
1539
|
+
return match_in_connector_set(sent, sent->dict->andable_connector_set, c, dir);
|
1540
|
+
}
|
1541
|
+
|
1542
|
+
void SATEncoderConjunctiveSentences::handle_null_expression(int w)
|
1543
|
+
{
|
1544
|
+
// Formula is unsatisfiable, but only if w is not a conjunctive
|
1545
|
+
// word. Conjunctive words can have empty tags, but then they must
|
1546
|
+
// have fat-links attached.
|
1547
|
+
if (!isConnectiveOrComma(w)) {
|
1548
|
+
vec<Lit> clause;
|
1549
|
+
add_clause(clause);
|
1550
|
+
} else {
|
1551
|
+
char str[MAX_VARIABLE_NAME];
|
1552
|
+
sprintf(str, "fl_d_%d", w);
|
1553
|
+
generate_literal(Lit(_variables->string(str)));
|
1554
|
+
sprintf(str, "w%d", w);
|
1555
|
+
generate_literal(~Lit(_variables->string(str)));
|
1556
|
+
}
|
1557
|
+
}
|
1558
|
+
|
1559
|
+
void SATEncoderConjunctiveSentences::determine_satisfaction(int w, char* name) {
|
1560
|
+
if (!parse_options_get_use_fat_links(_opts) ||
|
1561
|
+
!isConnectiveOrComma(w)) {
|
1562
|
+
// Non-conjunctive words must have their tags satisfied
|
1563
|
+
generate_literal(Lit(_variables->string(name)));
|
1564
|
+
} else {
|
1565
|
+
// Tags of conjunctive words are satisfied iff they are not fat-linked
|
1566
|
+
either_tag_or_fat_link(w, Lit(_variables->string(name)));
|
1567
|
+
}
|
1568
|
+
}
|
1569
|
+
|
1570
|
+
|
1571
|
+
void SATEncoderConjunctiveSentences::generate_satisfaction_for_connector(int wi, int pi, const char* Ci,
|
1572
|
+
char dir, bool multi, int cost, char* var) {
|
1573
|
+
Lit lhs = Lit(_variables->string_cost(var, cost));
|
1574
|
+
|
1575
|
+
#ifdef _DEBUG
|
1576
|
+
cout << "*** Connector: ." << wi << ". ." << pi << ". " << Ci << dir << endl;
|
1577
|
+
#endif
|
1578
|
+
// words that can potentially match (wi, pi)
|
1579
|
+
int low = (dir == '-') ? 0 : wi + 1;
|
1580
|
+
int hi = (dir == '-') ? wi : _sent->length;
|
1581
|
+
|
1582
|
+
// determine if opposite of (wi, pi) is andable
|
1583
|
+
Connector conn;
|
1584
|
+
init_connector(&conn);
|
1585
|
+
conn.label = NORMAL_LABEL;
|
1586
|
+
conn.priority = THIN_priority;
|
1587
|
+
conn.string = Ci;
|
1588
|
+
bool andable_opposite = is_andable(_sent, &conn, dir == '+' ? '-' : '+');
|
1589
|
+
|
1590
|
+
std::vector<int> _w_;
|
1591
|
+
for (int wj = low; wj < hi; wj++) {
|
1592
|
+
// Eliminate words that cannot be connected to (wi, pi)
|
1593
|
+
if (!link_cw_possible(wi, pi, Ci, dir, wj, 1, _sent->length-1))
|
1594
|
+
continue;
|
1595
|
+
|
1596
|
+
// Now we know that there is a potential link between the
|
1597
|
+
// connector (wi, pi) and the word w
|
1598
|
+
_w_.push_back(wj);
|
1599
|
+
|
1600
|
+
// link_cw down definitions as ordinary words
|
1601
|
+
if (_word_tags[wj].match_possible(wi, pi) || isConnectiveOrComma(wj)) {
|
1602
|
+
generate_link_cw_ordinary_definition(wi, pi, Ci, dir, cost, wj);
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
// link_cw down definitions as special words
|
1606
|
+
if (isConnectiveOrComma(wj)) {
|
1607
|
+
if (!link_cw_possible_with_fld(wi, pi, Ci, dir, wj, 1, _sent->length-1)) {
|
1608
|
+
generate_link_cw_connective_impossible(wi, pi, Ci, wj);
|
1609
|
+
} else {
|
1610
|
+
generate_link_cw_connective_definition(wi, pi, Ci, wj);
|
1611
|
+
}
|
1612
|
+
}
|
1613
|
+
|
1614
|
+
// ------------------------------------------------------------------------
|
1615
|
+
|
1616
|
+
// link_top_cw up defintions
|
1617
|
+
if (andable_opposite) {
|
1618
|
+
// connections can be either directly established or inherited from above
|
1619
|
+
generate_link_top_cw_up_definition(wj, wi, pi, Ci, multi);
|
1620
|
+
} else {
|
1621
|
+
// connection is established iff it is directly established
|
1622
|
+
// i.e., it cannot be inherited from above
|
1623
|
+
generate_link_top_cw_iff_link_cw(wj, wi, pi, Ci);
|
1624
|
+
}
|
1625
|
+
|
1626
|
+
// Commas cannot be directly connected if they have fat links down
|
1627
|
+
if (parse_options_get_use_fat_links(_opts) &&
|
1628
|
+
isComma(_sent, wj)) {
|
1629
|
+
vec<Lit> clause;
|
1630
|
+
char str[MAX_VARIABLE_NAME];
|
1631
|
+
sprintf(str,"fl_d_%d", wj);
|
1632
|
+
clause.push(~Lit(_variables->string(str)));
|
1633
|
+
clause.push(~Lit(_variables->link_top_cw(wj, wi, pi, Ci)));
|
1634
|
+
add_clause(clause);
|
1635
|
+
}
|
1636
|
+
}
|
1637
|
+
|
1638
|
+
vec<Lit> _link_cw_;
|
1639
|
+
for (int i = 0; i < _w_.size(); i++)
|
1640
|
+
_link_cw_.push(Lit(_variables->link_cw(_w_[i], wi, pi, Ci)));
|
1641
|
+
generate_or_definition(lhs, _link_cw_);
|
1642
|
+
|
1643
|
+
vec<Lit> _link_top_cw_;
|
1644
|
+
for (int i = 0; i < _w_.size(); i++)
|
1645
|
+
_link_top_cw_.push(Lit(_variables->link_top_cw(_w_[i], wi, pi, Ci)));
|
1646
|
+
// Faster
|
1647
|
+
generate_or_definition(lhs, _link_top_cw_);
|
1648
|
+
|
1649
|
+
DEBUG_print("--------- multi");
|
1650
|
+
if (!multi) {
|
1651
|
+
generate_xor_conditions(_link_top_cw_);
|
1652
|
+
}
|
1653
|
+
DEBUG_print("--------- end multi");
|
1654
|
+
|
1655
|
+
#ifdef _DEBUG
|
1656
|
+
cout << "*** End Connector: ." << wi << ". ." << pi << ". " << Ci << endl;
|
1657
|
+
#endif
|
1658
|
+
}
|
1659
|
+
|
1660
|
+
void SATEncoderConjunctiveSentences::add_additional_power_pruning_conditions(vec<Lit>& clause, int wl, int wr) {
|
1661
|
+
char str[MAX_VARIABLE_NAME];
|
1662
|
+
sprintf(str, "fl_ur_%d", wl);
|
1663
|
+
clause.push(Lit(_variables->string(str)));
|
1664
|
+
sprintf(str, "fl_ul_%d", wl);
|
1665
|
+
clause.push(Lit(_variables->string(str)));
|
1666
|
+
sprintf(str, "fl_ul_%d", wr);
|
1667
|
+
clause.push(Lit(_variables->string(str)));
|
1668
|
+
sprintf(str, "fl_ur_%d", wr);
|
1669
|
+
clause.push(Lit(_variables->string(str)));
|
1670
|
+
}
|
1671
|
+
|
1672
|
+
void SATEncoderConjunctiveSentences::generate_encoding_specific_clauses() {
|
1673
|
+
generate_label_compatibility();
|
1674
|
+
generate_fat_link_existence();
|
1675
|
+
generate_fat_link_up_definitions();
|
1676
|
+
generate_fat_link_down_definitions();
|
1677
|
+
generate_fat_link_up_between_down_conditions();
|
1678
|
+
generate_fat_link_comma_conditions();
|
1679
|
+
generate_fat_link_crossover_conditions();
|
1680
|
+
generate_fat_link_Left_Wall_not_inside();
|
1681
|
+
generate_fat_link_linked_upperside();
|
1682
|
+
generate_fat_link_neighbor();
|
1683
|
+
}
|
1684
|
+
|
1685
|
+
void SATEncoderConjunctiveSentences::init_connective_words() {
|
1686
|
+
for (int i = 0; i < _sent->length; i++) {
|
1687
|
+
if (::isConnectiveOrComma(_sent, i)) {
|
1688
|
+
_connectives.push_back(i);
|
1689
|
+
_is_connective_or_comma.push_back(true);
|
1690
|
+
} else {
|
1691
|
+
_is_connective_or_comma.push_back(false);
|
1692
|
+
}
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
|
1696
|
+
}
|
1697
|
+
|
1698
|
+
/* If there is a direct link between a connective word wi and a
|
1699
|
+
connector (w,p), then there is an indirect link between wi and (w, p).
|
1700
|
+
*/
|
1701
|
+
void SATEncoderConjunctiveSentences::generate_link_top_cw_iff_link_cw(int wi, int wj, int pj, const char* Cj) {
|
1702
|
+
DEBUG_print("--------- link_top_cw iff link_cw");
|
1703
|
+
vec<Lit> clause;
|
1704
|
+
|
1705
|
+
clause.growTo(2);
|
1706
|
+
clause[0] = ~Lit(_variables->link_cw(wi, wj, pj, Cj));
|
1707
|
+
clause[1] = Lit(_variables->link_top_cw(wi, wj, pj, Cj));
|
1708
|
+
add_clause(clause);
|
1709
|
+
|
1710
|
+
clause.growTo(2);
|
1711
|
+
clause[0] = ~Lit(_variables->link_top_cw(wi, wj, pj, Cj));
|
1712
|
+
clause[1] = Lit(_variables->link_cw(wi, wj, pj, Cj));
|
1713
|
+
add_clause(clause);
|
1714
|
+
|
1715
|
+
DEBUG_print("--------- end link_top_cw iff link_cw");
|
1716
|
+
}
|
1717
|
+
|
1718
|
+
|
1719
|
+
|
1720
|
+
void SATEncoderConjunctiveSentences::generate_link_top_cw_up_definition(int wj, int wi, int pi, const char* Ci, bool multi) {
|
1721
|
+
DEBUG_print("--------- link_top_cw definition");
|
1722
|
+
Lit link_cw_wj = Lit(_variables->link_cw(wj, wi, pi, Ci));
|
1723
|
+
Lit link_top_cw_wj = Lit(_variables->link_top_cw(wj, wi, pi, Ci));
|
1724
|
+
char dir = wi < wj ? '+' : '-';
|
1725
|
+
|
1726
|
+
vec<Lit> clause;
|
1727
|
+
|
1728
|
+
clause.growTo(2);
|
1729
|
+
clause[0] = ~link_top_cw_wj;
|
1730
|
+
clause[1] = link_cw_wj;
|
1731
|
+
add_clause(clause);
|
1732
|
+
|
1733
|
+
|
1734
|
+
// Collect connectors up
|
1735
|
+
std::vector<int> Wk;
|
1736
|
+
for (int k = 0; k < _connectives.size(); k++) {
|
1737
|
+
int wk = _connectives[k];
|
1738
|
+
if (wk != wj && (wj - wi)*(wk - wi) > 0 &&
|
1739
|
+
link_cw_possible_with_fld(wi, pi, Ci, dir, wk, 1, _sent->length - 1))
|
1740
|
+
Wk.push_back(wk);
|
1741
|
+
}
|
1742
|
+
|
1743
|
+
|
1744
|
+
for (int k = 0; k < Wk.size(); k++) {
|
1745
|
+
int wk = Wk[k];
|
1746
|
+
clause.growTo(4);
|
1747
|
+
clause[0] = link_top_cw_wj;
|
1748
|
+
clause[1] = ~link_cw_wj;
|
1749
|
+
clause[2] = ~Lit(_variables->fat_link(wj, wk));
|
1750
|
+
clause[3] = Lit(_variables->link_cw(wk, wi, pi, Ci));
|
1751
|
+
add_clause(clause);
|
1752
|
+
}
|
1753
|
+
|
1754
|
+
clause.clear();
|
1755
|
+
for (int k = 0; k < Wk.size(); k++) {
|
1756
|
+
int wk = Wk[k];
|
1757
|
+
clause.growTo(3);
|
1758
|
+
clause[0] = ~link_top_cw_wj;
|
1759
|
+
clause[1] = ~Lit(_variables->fat_link(wj, wk));
|
1760
|
+
clause[2] = ~Lit(_variables->link_cw(wk, wi, pi, Ci));
|
1761
|
+
add_clause(clause);
|
1762
|
+
}
|
1763
|
+
|
1764
|
+
|
1765
|
+
clause.clear();
|
1766
|
+
clause.push(~link_cw_wj);
|
1767
|
+
clause.push(link_top_cw_wj);
|
1768
|
+
for (int k = 0; k < Wk.size(); k++) {
|
1769
|
+
int wk = Wk[k];
|
1770
|
+
clause.push(Lit(_variables->fat_link(wj, wk)));
|
1771
|
+
}
|
1772
|
+
add_clause(clause);
|
1773
|
+
|
1774
|
+
|
1775
|
+
if (clause.size() == 2)
|
1776
|
+
return;
|
1777
|
+
|
1778
|
+
// Faster
|
1779
|
+
clause.clear();
|
1780
|
+
clause.push(~link_cw_wj);
|
1781
|
+
clause.push(link_top_cw_wj);
|
1782
|
+
for (int k = 0; k < Wk.size(); k++) {
|
1783
|
+
int wk = Wk[k];
|
1784
|
+
clause.push(Lit(_variables->link_cw(wk, wi, pi, Ci)));
|
1785
|
+
}
|
1786
|
+
add_clause(clause);
|
1787
|
+
|
1788
|
+
|
1789
|
+
if (multi) {
|
1790
|
+
// cannot directly link to both ends of the fat link
|
1791
|
+
clause.clear();
|
1792
|
+
for (int k = 0; k < Wk.size(); k++) {
|
1793
|
+
int wk = Wk[k];
|
1794
|
+
clause.growTo(3);
|
1795
|
+
clause[0] = ~Lit(_variables->fat_link(wj, wk));
|
1796
|
+
clause[1] = ~Lit(_variables->link_top_cw(wj, wi, pi, Ci));
|
1797
|
+
clause[2] = ~Lit(_variables->link_top_cw(wk, wi, pi, Ci));
|
1798
|
+
add_clause(clause);
|
1799
|
+
}
|
1800
|
+
}
|
1801
|
+
|
1802
|
+
DEBUG_print("--------- end link_top_cw definition");
|
1803
|
+
}
|
1804
|
+
|
1805
|
+
/* If there is an indirect link from a connective word or a comma wi to a
|
1806
|
+
connector (wj, pj), then, there exist two words wk1 and wk2, such that:
|
1807
|
+
(1)
|
1808
|
+
(a) wk1 is between wi and wj
|
1809
|
+
(b) there is a fat-link between wk1 and wi
|
1810
|
+
(c) there is an indirect link between wk1 and (wj, pj)
|
1811
|
+
(2)
|
1812
|
+
(a) wi is between wk2 and wj
|
1813
|
+
(b) there is a fat-link between wk2 and wi
|
1814
|
+
(c) there is an indirect link between wk2 and (wj, pj)
|
1815
|
+
*/
|
1816
|
+
void SATEncoderConjunctiveSentences::generate_link_cw_connective_definition(int wj, int pj, const char* Cj, int wi) {
|
1817
|
+
DEBUG_print("--------- link_cw as special");
|
1818
|
+
|
1819
|
+
char str[MAX_VARIABLE_NAME];
|
1820
|
+
sprintf(str, "fl_d_%d", wi);
|
1821
|
+
Lit not_wi_fld = ~Lit(_variables->string(str));
|
1822
|
+
|
1823
|
+
char link_cw_k1_str[MAX_VARIABLE_NAME];
|
1824
|
+
sprintf(link_cw_k1_str, "%d_%d_%d__1", wj, pj, wi);
|
1825
|
+
Lit link_cw_k1(_variables->string(link_cw_k1_str));
|
1826
|
+
|
1827
|
+
char link_cw_k2_str[MAX_VARIABLE_NAME];
|
1828
|
+
sprintf(link_cw_k2_str, "%d_%d_%d__2", wj, pj, wi);
|
1829
|
+
Lit link_cw_k2(_variables->string(link_cw_k2_str));
|
1830
|
+
|
1831
|
+
Lit not_link_wi_wjpj = ~Lit(_variables->link_cw(wi, wj, pj, Cj));
|
1832
|
+
|
1833
|
+
char dir = wj < wi ? '+' : '-';
|
1834
|
+
|
1835
|
+
vec<Lit> clause;
|
1836
|
+
clause.growTo(3);
|
1837
|
+
clause[0] = not_wi_fld;
|
1838
|
+
clause[1] = not_link_wi_wjpj;
|
1839
|
+
clause[2] = link_cw_k1;
|
1840
|
+
add_clause(clause);
|
1841
|
+
|
1842
|
+
clause.growTo(3);
|
1843
|
+
clause[0] = not_wi_fld;
|
1844
|
+
clause[1] = not_link_wi_wjpj;
|
1845
|
+
clause[2] = link_cw_k2;
|
1846
|
+
add_clause(clause);
|
1847
|
+
|
1848
|
+
clause.growTo(3);
|
1849
|
+
clause[0] = ~link_cw_k1;
|
1850
|
+
clause[1] = ~link_cw_k2;
|
1851
|
+
clause[2] = ~not_link_wi_wjpj;
|
1852
|
+
add_clause(clause);
|
1853
|
+
|
1854
|
+
clause.clear();
|
1855
|
+
|
1856
|
+
// B(wi, w, wj)
|
1857
|
+
int wl, wr;
|
1858
|
+
if (wi < wj) {
|
1859
|
+
wl = wi + 1;
|
1860
|
+
wr = wj;
|
1861
|
+
} else {
|
1862
|
+
wl = wj + 1;
|
1863
|
+
wr = wi;
|
1864
|
+
}
|
1865
|
+
|
1866
|
+
std::vector<bool> link_cw_possible_cache(wr - wl);
|
1867
|
+
|
1868
|
+
for (int wk1 = wl; wk1 < wr; wk1++) {
|
1869
|
+
if (!(link_cw_possible_cache[wk1 - wl] = link_cw_possible(wj, pj, Cj, dir, wk1, wl, wr)))
|
1870
|
+
continue;
|
1871
|
+
|
1872
|
+
clause.growTo(3);
|
1873
|
+
clause[0] = ~link_cw_k1;
|
1874
|
+
clause[1] = ~Lit(_variables->fat_link(wk1, wi));
|
1875
|
+
clause[2] = Lit(_variables->link_cw(wk1, wj, pj, Cj));
|
1876
|
+
add_clause(clause);
|
1877
|
+
}
|
1878
|
+
|
1879
|
+
clause.clear();
|
1880
|
+
clause.push(~link_cw_k1);
|
1881
|
+
for (int wk1 = wl; wk1 < wr; wk1++) {
|
1882
|
+
if (!link_cw_possible_cache[wk1 - wl])
|
1883
|
+
continue;
|
1884
|
+
|
1885
|
+
clause.push(Lit(_variables->fat_link(wk1, wi)));
|
1886
|
+
}
|
1887
|
+
add_clause(clause);
|
1888
|
+
|
1889
|
+
// Faster
|
1890
|
+
clause.clear();
|
1891
|
+
clause.push(~link_cw_k1);
|
1892
|
+
for (int wk1 = wl; wk1 < wr; wk1++) {
|
1893
|
+
if (!link_cw_possible_cache[wk1 - wl])
|
1894
|
+
continue;
|
1895
|
+
|
1896
|
+
clause.push(Lit(_variables->link_cw(wk1, wj, pj, Cj)));
|
1897
|
+
}
|
1898
|
+
add_clause(clause);
|
1899
|
+
|
1900
|
+
|
1901
|
+
clause.clear();
|
1902
|
+
for (int wk1 = wl; wk1 < wr; wk1++) {
|
1903
|
+
if (!link_cw_possible_cache[wk1 - wl])
|
1904
|
+
continue;
|
1905
|
+
clause.growTo(3);
|
1906
|
+
clause[0] = ~Lit(_variables->fat_link(wk1, wi));
|
1907
|
+
clause[1] = ~Lit(_variables->link_cw(wk1, wj, pj, Cj));
|
1908
|
+
clause[2] = link_cw_k1;
|
1909
|
+
add_clause(clause);
|
1910
|
+
}
|
1911
|
+
|
1912
|
+
DEBUG_print("---");
|
1913
|
+
|
1914
|
+
// B(wk2, wi, wj)
|
1915
|
+
if (wi < wj) {
|
1916
|
+
wl = 1;
|
1917
|
+
wr = wi;
|
1918
|
+
} else {
|
1919
|
+
wl = wi + 1;
|
1920
|
+
wr = _sent->length - 1;
|
1921
|
+
}
|
1922
|
+
link_cw_possible_cache.resize(wr - wl);
|
1923
|
+
|
1924
|
+
clause.clear();
|
1925
|
+
for (int wk2 = wl; wk2 < wr; wk2++) {
|
1926
|
+
if (!(link_cw_possible_cache[wk2 - wl] = link_cw_possible(wj, pj, Cj, dir, wk2, wl, wr)))
|
1927
|
+
continue;
|
1928
|
+
|
1929
|
+
clause.growTo(3);
|
1930
|
+
clause[0] = ~link_cw_k2;
|
1931
|
+
clause[1] = ~Lit(_variables->fat_link(wk2, wi));
|
1932
|
+
clause[2] = Lit(_variables->link_cw(wk2, wj, pj, Cj));
|
1933
|
+
add_clause(clause);
|
1934
|
+
}
|
1935
|
+
|
1936
|
+
clause.clear();
|
1937
|
+
clause.push(~link_cw_k2);
|
1938
|
+
for (int wk2 = wl; wk2 < wr; wk2++) {
|
1939
|
+
if (!link_cw_possible_cache[wk2 - wl])
|
1940
|
+
continue;
|
1941
|
+
|
1942
|
+
clause.push(Lit(_variables->fat_link(wk2, wi)));
|
1943
|
+
}
|
1944
|
+
add_clause(clause);
|
1945
|
+
|
1946
|
+
// Faster
|
1947
|
+
clause.clear();
|
1948
|
+
clause.push(~link_cw_k2);
|
1949
|
+
for (int wk2 = wl; wk2 < wr; wk2++) {
|
1950
|
+
if (!link_cw_possible_cache[wk2 - wl])
|
1951
|
+
continue;
|
1952
|
+
|
1953
|
+
clause.push(Lit(_variables->link_cw(wk2, wj, pj, Cj)));
|
1954
|
+
}
|
1955
|
+
add_clause(clause);
|
1956
|
+
|
1957
|
+
clause.clear();
|
1958
|
+
for (int wk2 = wl; wk2 < wr; wk2++) {
|
1959
|
+
if (!link_cw_possible_cache[wk2 - wl])
|
1960
|
+
continue;
|
1961
|
+
clause.growTo(3);
|
1962
|
+
clause[0] = ~Lit(_variables->fat_link(wk2, wi));
|
1963
|
+
clause[1] = ~Lit(_variables->link_cw(wk2, wj, pj, Cj));
|
1964
|
+
clause[2] = link_cw_k2;
|
1965
|
+
add_clause(clause);
|
1966
|
+
}
|
1967
|
+
|
1968
|
+
DEBUG_print("--------- end link_cw as special");
|
1969
|
+
}
|
1970
|
+
|
1971
|
+
void SATEncoderConjunctiveSentences::generate_link_cw_connective_impossible(int wi, int pi, const char* Ci, int wj) {
|
1972
|
+
DEBUG_print("--------- link_cw as special down - impossible");
|
1973
|
+
// If the connective word w has fat-links down it cannot be
|
1974
|
+
// connected to (wi, pi)
|
1975
|
+
vec<Lit> clause;
|
1976
|
+
char str[MAX_VARIABLE_NAME];
|
1977
|
+
sprintf(str,"fl_d_%d", wj);
|
1978
|
+
clause.push(~Lit(_variables->string(str)));
|
1979
|
+
clause.push(~Lit(_variables->link_cw(wj, wi, pi, Ci)));
|
1980
|
+
add_clause(clause);
|
1981
|
+
DEBUG_print("--------- end link_cw as special down - impossible");
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
|
1985
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_up_definitions() {
|
1986
|
+
Lit lhs;
|
1987
|
+
vec<Lit> rhs;
|
1988
|
+
char fl_str[MAX_VARIABLE_NAME];
|
1989
|
+
vec<Lit> clause;
|
1990
|
+
|
1991
|
+
for (int w = 1; w < _sent->length - 1; w++) {
|
1992
|
+
DEBUG_print("----fat_link up definition");
|
1993
|
+
// Fatlink up left definition
|
1994
|
+
rhs.clear();
|
1995
|
+
for (std::vector<int>::const_iterator cl = _connectives.begin(); cl != _connectives.end(); cl++) {
|
1996
|
+
if (*cl < w)
|
1997
|
+
rhs.push(Lit(_variables->fat_link(w, *cl)));
|
1998
|
+
}
|
1999
|
+
sprintf(fl_str, "fl_ul_%d", w);
|
2000
|
+
lhs = Lit(_variables->string(fl_str));
|
2001
|
+
generate_or_definition(lhs, rhs);
|
2002
|
+
generate_xor_conditions(rhs);
|
2003
|
+
|
2004
|
+
// Fatlink up right definition
|
2005
|
+
rhs.clear();
|
2006
|
+
for (std::vector<int>::const_iterator cr = _connectives.begin(); cr != _connectives.end(); cr++) {
|
2007
|
+
if (*cr > w)
|
2008
|
+
rhs.push(Lit(_variables->fat_link(w, *cr)));
|
2009
|
+
}
|
2010
|
+
sprintf(fl_str, "fl_ur_%d", w);
|
2011
|
+
lhs = Lit(_variables->string(fl_str));
|
2012
|
+
generate_or_definition(lhs, rhs);
|
2013
|
+
generate_xor_conditions(rhs);
|
2014
|
+
|
2015
|
+
// There can not be two links up
|
2016
|
+
clause.growTo(2);
|
2017
|
+
sprintf(fl_str, "fl_ul_%d", w);
|
2018
|
+
clause[0] = ~Lit(_variables->string(fl_str));
|
2019
|
+
sprintf(fl_str, "fl_ur_%d", w);
|
2020
|
+
clause[1] = ~Lit(_variables->string(fl_str));
|
2021
|
+
add_clause(clause);
|
2022
|
+
|
2023
|
+
|
2024
|
+
DEBUG_print("----end fat_link up definition");
|
2025
|
+
}
|
2026
|
+
}
|
2027
|
+
|
2028
|
+
|
2029
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_down_definitions() {
|
2030
|
+
// Fat links down
|
2031
|
+
char fl_str[MAX_VARIABLE_NAME];
|
2032
|
+
std::vector<int>::const_iterator w;
|
2033
|
+
for (w = _connectives.begin(); w != _connectives.end(); w++) {
|
2034
|
+
DEBUG_print("----fat_link down definition");
|
2035
|
+
// Fatlink down left definition
|
2036
|
+
vec<Lit> rhs;
|
2037
|
+
for (int wl = 1; wl < *w; wl++) {
|
2038
|
+
rhs.push(Lit(_variables->fat_link(wl, *w)));
|
2039
|
+
}
|
2040
|
+
sprintf(fl_str, "fl_d_%d", *w);
|
2041
|
+
Lit lhs = Lit(_variables->string(fl_str));
|
2042
|
+
generate_or_definition(lhs, rhs);
|
2043
|
+
generate_xor_conditions(rhs);
|
2044
|
+
|
2045
|
+
// Fatlink down right definition
|
2046
|
+
rhs.clear();
|
2047
|
+
for (int wr = *w + 1; wr < _sent->length - 1; wr++) {
|
2048
|
+
rhs.push(Lit(_variables->fat_link(wr, *w)));
|
2049
|
+
}
|
2050
|
+
sprintf(fl_str, "fl_d_%d", *w);
|
2051
|
+
lhs = Lit(_variables->string(fl_str));
|
2052
|
+
generate_or_definition(lhs, rhs);
|
2053
|
+
generate_xor_conditions(rhs);
|
2054
|
+
DEBUG_print("----end fat_link down definition");
|
2055
|
+
}
|
2056
|
+
}
|
2057
|
+
|
2058
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_comma_conditions() {
|
2059
|
+
char fl_str[MAX_VARIABLE_NAME];
|
2060
|
+
std::vector<int>::const_iterator w;
|
2061
|
+
vec<Lit> clause;
|
2062
|
+
for (w = _connectives.begin(); w != _connectives.end(); w++) {
|
2063
|
+
if (isComma(_sent, *w)) {
|
2064
|
+
DEBUG_print("---comma---");
|
2065
|
+
|
2066
|
+
// If comma has a link down it has to have a link up to the right
|
2067
|
+
sprintf(fl_str, "fl_d_%d", *w);
|
2068
|
+
clause.growTo(2);
|
2069
|
+
clause[0] = ~Lit(_variables->string(fl_str));
|
2070
|
+
sprintf(fl_str, "fl_ur_%d", *w);
|
2071
|
+
clause[1] = Lit(_variables->string(fl_str));
|
2072
|
+
add_clause(clause);
|
2073
|
+
|
2074
|
+
|
2075
|
+
// If comma has a link down it cannot have a link up to the left
|
2076
|
+
sprintf(fl_str, "fl_d_%d", *w);
|
2077
|
+
clause.growTo(2);
|
2078
|
+
clause[0] = ~Lit(_variables->string(fl_str));
|
2079
|
+
sprintf(fl_str, "fl_ul_%d", *w);
|
2080
|
+
clause[1] = ~Lit(_variables->string(fl_str));
|
2081
|
+
add_clause(clause);
|
2082
|
+
|
2083
|
+
DEBUG_print("---end comma---");
|
2084
|
+
}
|
2085
|
+
}
|
2086
|
+
}
|
2087
|
+
|
2088
|
+
|
2089
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_crossover_conditions() {
|
2090
|
+
vec<Lit> clause;
|
2091
|
+
// If a word has a fat link up, than it cannot establish links with words behind that connective
|
2092
|
+
for (int w = 1; w < _sent->length - 1; w++) {
|
2093
|
+
DEBUG_print("----links cannot crossover the fat-links");
|
2094
|
+
std::vector<int>::const_iterator c1, c2;
|
2095
|
+
for (c1 = _connectives.begin(); c1 != _connectives.end(); c1++) {
|
2096
|
+
if (*c1 > w) {
|
2097
|
+
for (int w1 = *c1 + 1; w1 < _sent->length; w1++) {
|
2098
|
+
if (!_linked_possible(w, w1))
|
2099
|
+
continue;
|
2100
|
+
|
2101
|
+
clause.growTo(3);
|
2102
|
+
clause[0] = ~Lit(_variables->fat_link(w, *c1));
|
2103
|
+
clause[1] = Lit(_variables->link_top_ww(*c1, w1));
|
2104
|
+
clause[2] = ~Lit(_variables->link_top_ww(w, w1));
|
2105
|
+
add_clause(clause);
|
2106
|
+
}
|
2107
|
+
}
|
2108
|
+
|
2109
|
+
if (*c1 < w) {
|
2110
|
+
for (int w1 = 0; w1 < *c1; w1++) {
|
2111
|
+
if (!_linked_possible(w1, w))
|
2112
|
+
continue;
|
2113
|
+
|
2114
|
+
clause.growTo(3);
|
2115
|
+
clause[0] = ~Lit(_variables->fat_link(w, *c1));
|
2116
|
+
clause[1] = Lit(_variables->link_top_ww(*c1, w1));
|
2117
|
+
clause[2] = ~Lit(_variables->link_top_ww(w, w1));
|
2118
|
+
add_clause(clause);
|
2119
|
+
}
|
2120
|
+
}
|
2121
|
+
}
|
2122
|
+
DEBUG_print("----end links cannot cross over the fat-links");
|
2123
|
+
}
|
2124
|
+
|
2125
|
+
|
2126
|
+
// One step structure violation pruning heuristic If a word is
|
2127
|
+
// directly linked to a fat linked word, than it cannot establish
|
2128
|
+
// links with words behind that connective
|
2129
|
+
std::vector<int>::const_iterator c;
|
2130
|
+
for (c = _connectives.begin(); c != _connectives.end(); c++) {
|
2131
|
+
DEBUG_print("----links cannot crossover the fat-links heuristic");
|
2132
|
+
for (int w = 1; w < *c; w++) {
|
2133
|
+
for (int w1 = 0; w1 < w; w1++) {
|
2134
|
+
if (!_linked_possible(w1, w))
|
2135
|
+
continue;
|
2136
|
+
for (int w2 = *c; w2 < _sent->length; w2++) {
|
2137
|
+
if (!_linked_possible(w1, w2))
|
2138
|
+
continue;
|
2139
|
+
|
2140
|
+
|
2141
|
+
vec<Lit> clause;
|
2142
|
+
clause.push(~Lit(_variables->fat_link(w, *c)));
|
2143
|
+
clause.push(~Lit(_variables->linked(w1, w)));
|
2144
|
+
clause.push(~Lit(_variables->linked(w1, w2)));
|
2145
|
+
add_clause(clause);
|
2146
|
+
}
|
2147
|
+
}
|
2148
|
+
}
|
2149
|
+
for (int w = *c + 1; w < _sent->length - 1; w++) {
|
2150
|
+
for (int w1 = w+1; w1 < _sent->length; w1++) {
|
2151
|
+
if (!_linked_possible(w, w1))
|
2152
|
+
continue;
|
2153
|
+
for (int w2 = 0; w2 <= *c; w2++) {
|
2154
|
+
if (!_linked_possible(w2, w1))
|
2155
|
+
continue;
|
2156
|
+
|
2157
|
+
vec<Lit> clause;
|
2158
|
+
clause.push(~Lit(_variables->fat_link(w, *c)));
|
2159
|
+
clause.push(~Lit(_variables->linked(w, w1)));
|
2160
|
+
clause.push(~Lit(_variables->linked(w2, w1)));
|
2161
|
+
add_clause(clause);
|
2162
|
+
}
|
2163
|
+
}
|
2164
|
+
}
|
2165
|
+
DEBUG_print("----end links cannot cross over the fat-links heuristic");
|
2166
|
+
}
|
2167
|
+
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_up_between_down_conditions() {
|
2171
|
+
// If a connective wi has a fat-link down to wj, it cannot have
|
2172
|
+
// links up between wi and wj.
|
2173
|
+
vec<Lit> clause;
|
2174
|
+
for (std::vector<int>::const_iterator wi = _connectives.begin(); wi != _connectives.end(); wi++) {
|
2175
|
+
DEBUG_print("---up between down---");
|
2176
|
+
for (int wj = 1; wj < _sent->length - 1; wj++) {
|
2177
|
+
if (*wi == wj)
|
2178
|
+
continue;
|
2179
|
+
int l = std::min(*wi, wj) + 1;
|
2180
|
+
int r = std::max(*wi, wj);
|
2181
|
+
|
2182
|
+
for (int wk = l; wk < r; wk++) {
|
2183
|
+
int mi = std::min(*wi, wk);
|
2184
|
+
int ma = std::max(*wi, wk);
|
2185
|
+
if (!_linked_possible(mi, ma))
|
2186
|
+
continue;
|
2187
|
+
|
2188
|
+
clause.growTo(2);
|
2189
|
+
clause[0] = ~Lit(_variables->fat_link(wj, *wi));
|
2190
|
+
clause[1] = ~Lit(_variables->linked(mi, ma));
|
2191
|
+
add_clause(clause);
|
2192
|
+
}
|
2193
|
+
|
2194
|
+
if (isConnectiveOrComma(wj)) {
|
2195
|
+
clause.growTo(2);
|
2196
|
+
clause[0] = ~Lit(_variables->fat_link(wj, *wi));
|
2197
|
+
clause[1] = ~Lit(_variables->fat_link(*wi, wj));
|
2198
|
+
add_clause(clause);
|
2199
|
+
}
|
2200
|
+
|
2201
|
+
|
2202
|
+
}
|
2203
|
+
DEBUG_print("---end up between down---");
|
2204
|
+
}
|
2205
|
+
}
|
2206
|
+
|
2207
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_neighbor() {
|
2208
|
+
// Search guiding heuristic: one fat-link is usually just next to the word
|
2209
|
+
Lit lhs;
|
2210
|
+
vec<Lit> rhs;
|
2211
|
+
char fl_str[MAX_VARIABLE_NAME];
|
2212
|
+
std::vector<int>::const_iterator w;
|
2213
|
+
for (w = _connectives.begin(); w != _connectives.end(); w++) {
|
2214
|
+
DEBUG_print("----fat-link-neighbor");
|
2215
|
+
if (*w > 1 && *w < _sent->length - 1) {
|
2216
|
+
rhs.clear();
|
2217
|
+
rhs.push(Lit(_variables->fat_link(*w - 1, *w)));
|
2218
|
+
rhs.push(Lit(_variables->fat_link(*w + 1, *w)));
|
2219
|
+
lhs = Lit(_variables->neighbor_fat_link(*w));
|
2220
|
+
sprintf(fl_str, "fl_d_%d", *w);
|
2221
|
+
Lit fld = Lit(_variables->string(fl_str));
|
2222
|
+
generate_conditional_or_definition(fld, lhs, rhs);
|
2223
|
+
}
|
2224
|
+
DEBUG_print("----end fat-link-neighbor");
|
2225
|
+
}
|
2226
|
+
}
|
2227
|
+
|
2228
|
+
void SATEncoderConjunctiveSentences::generate_label_compatibility() {
|
2229
|
+
// Eliminate non-matching indirect links
|
2230
|
+
DEBUG_print("----label compatibility");
|
2231
|
+
vec<Lit> clause;
|
2232
|
+
const std::vector<int>& vars = _variables->link_variables();
|
2233
|
+
std::vector<int>::const_iterator i, j;
|
2234
|
+
for (i = vars.begin(); i != vars.end(); i++) {
|
2235
|
+
const Variables::LinkVar* vari = _variables->link_variable(*i);
|
2236
|
+
|
2237
|
+
const std::vector<int>& varsjr = _variables->link_variables(vari->right_word, vari->right_position);
|
2238
|
+
for (j = varsjr.begin(); j != varsjr.end(); j++) {
|
2239
|
+
const Variables::LinkVar* varj = _variables->link_variable(*j);
|
2240
|
+
if (!labels_match(vari->label, varj->label)) {
|
2241
|
+
clause.growTo(2);
|
2242
|
+
clause[0] = ~Lit(*i);
|
2243
|
+
clause[1] = ~Lit(*j);
|
2244
|
+
add_clause(clause);
|
2245
|
+
}
|
2246
|
+
}
|
2247
|
+
|
2248
|
+
const std::vector<int>& varsjl = _variables->link_variables(vari->left_word, vari->left_position);
|
2249
|
+
for (j = varsjl.begin(); j != varsjl.end(); j++) {
|
2250
|
+
const Variables::LinkVar* varj = _variables->link_variable(*j);
|
2251
|
+
if (!labels_match(vari->label, varj->label)) {
|
2252
|
+
clause.growTo(2);
|
2253
|
+
clause[0] = ~Lit(*i);
|
2254
|
+
clause[1] = ~Lit(*j);
|
2255
|
+
add_clause(clause);
|
2256
|
+
}
|
2257
|
+
}
|
2258
|
+
}
|
2259
|
+
DEBUG_print("----label compatibility");
|
2260
|
+
}
|
2261
|
+
|
2262
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_existence() {
|
2263
|
+
// If there is a fat link from wa to wb then there should be
|
2264
|
+
// at least one connector in the wa word tag that is indirectly
|
2265
|
+
// connected to words between:
|
2266
|
+
// if wa < wb: [0, wa) and [wb+2, n)
|
2267
|
+
// if wa > wb: [0, wb-1) and [wa+1, n)
|
2268
|
+
DEBUG_print("----fat-link-existence");
|
2269
|
+
vec<Lit> clause_a, clause_b;
|
2270
|
+
for (std::vector<int>::const_iterator wb = _connectives.begin(); wb != _connectives.end(); wb++) {
|
2271
|
+
for (int wa = 1; wa < _sent->length-1; wa++) {
|
2272
|
+
if (isConnectiveOrComma(wa))
|
2273
|
+
continue;
|
2274
|
+
if (wa == *wb)
|
2275
|
+
continue;
|
2276
|
+
|
2277
|
+
int up = (wa < *wb) ? wa : *wb - 1;
|
2278
|
+
int low = (wa < *wb) ? *wb + 2 : wa + 1;
|
2279
|
+
|
2280
|
+
clause_a.clear();
|
2281
|
+
clause_b.clear();
|
2282
|
+
clause_a.push(~Lit(_variables->fat_link(wa, *wb)));
|
2283
|
+
clause_b.push(~Lit(_variables->fat_link(wa, *wb)));
|
2284
|
+
|
2285
|
+
std::vector<PositionConnector>::const_iterator ci;
|
2286
|
+
char dir;
|
2287
|
+
|
2288
|
+
const std::vector<PositionConnector>& lconnectors = _word_tags[wa].get_left_connectors();
|
2289
|
+
for (ci = lconnectors.begin(); ci != lconnectors.end(); ci++) {
|
2290
|
+
const std::vector<PositionConnector*>& matches = ci->matches;
|
2291
|
+
std::vector<PositionConnector*>::const_iterator m;
|
2292
|
+
for (m = matches.begin(); m != matches.end(); m++) {
|
2293
|
+
if ((0 <= (*m)->word && (*m)->word < up) &&
|
2294
|
+
link_cw_possible_with_fld((*m)->word, (*m)->position, (*m)->connector->string,
|
2295
|
+
'+', *wb, 1, _sent->length - 1)) {
|
2296
|
+
clause_a.push(Lit(_variables->link_cw(wa, (*m)->word, (*m)->position, (*m)->connector->string)));
|
2297
|
+
clause_b.push(Lit(_variables->link_cw(*wb, (*m)->word, (*m)->position, (*m)->connector->string)));
|
2298
|
+
}
|
2299
|
+
}
|
2300
|
+
}
|
2301
|
+
|
2302
|
+
const std::vector<PositionConnector>& rconnectors = _word_tags[wa].get_right_connectors();
|
2303
|
+
for (ci = rconnectors.begin(); ci != rconnectors.end(); ci++) {
|
2304
|
+
const std::vector<PositionConnector*>& matches = ci->matches;
|
2305
|
+
std::vector<PositionConnector*>::const_iterator m;
|
2306
|
+
for (m = matches.begin(); m != matches.end(); m++) {
|
2307
|
+
if ((low <= (*m)->word && (*m)->word < _sent->length) &&
|
2308
|
+
link_cw_possible_with_fld((*m)->word, (*m)->position, (*m)->connector->string,
|
2309
|
+
'-', *wb, 1, _sent->length - 1)) {
|
2310
|
+
clause_a.push(Lit(_variables->link_cw(wa, (*m)->word, (*m)->position, (*m)->connector->string)));
|
2311
|
+
clause_b.push(Lit(_variables->link_cw(*wb, (*m)->word, (*m)->position, (*m)->connector->string)));
|
2312
|
+
}
|
2313
|
+
}
|
2314
|
+
}
|
2315
|
+
|
2316
|
+
add_clause(clause_a);
|
2317
|
+
add_clause(clause_b);
|
2318
|
+
}
|
2319
|
+
}
|
2320
|
+
DEBUG_print("----end fat-link-existence");
|
2321
|
+
}
|
2322
|
+
|
2323
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_Left_Wall_not_inside() {
|
2324
|
+
// Wall cannot be connected just inside the fat-link tree
|
2325
|
+
for (int w = 1; w < _sent->length-1; w++) {
|
2326
|
+
DEBUG_print("---Left Wall cannot be connected inside");
|
2327
|
+
vec<Lit> clause;
|
2328
|
+
std::vector<int>::const_iterator c;
|
2329
|
+
|
2330
|
+
if (!_linked_possible(0, w))
|
2331
|
+
continue;
|
2332
|
+
|
2333
|
+
for (c = _connectives.begin(); c != _connectives.end(); c++) {
|
2334
|
+
if (w == *c)
|
2335
|
+
continue;
|
2336
|
+
if (!_linked_possible(0, *c))
|
2337
|
+
continue;
|
2338
|
+
|
2339
|
+
clause.growTo(3);
|
2340
|
+
clause[0] = ~Lit(_variables->linked(0, w));
|
2341
|
+
clause[1] = ~Lit(_variables->fat_link(w, *c));
|
2342
|
+
clause[2] = Lit(_variables->linked(0, *c));
|
2343
|
+
add_clause(clause);
|
2344
|
+
}
|
2345
|
+
DEBUG_print("---end Left Wall cannot be connected inside");
|
2346
|
+
}
|
2347
|
+
}
|
2348
|
+
|
2349
|
+
void SATEncoderConjunctiveSentences::generate_fat_link_linked_upperside() {
|
2350
|
+
// Fat link must be linked on the upper side
|
2351
|
+
DEBUG_print("--- Fat link must be linked on the upper side");
|
2352
|
+
vec<Lit> clause;
|
2353
|
+
std::vector<int>::const_iterator c;
|
2354
|
+
for (c = _connectives.begin(); c != _connectives.end(); c++) {
|
2355
|
+
if (isComma(_sent, *c))
|
2356
|
+
continue;
|
2357
|
+
|
2358
|
+
clause.clear();
|
2359
|
+
char fl_str[MAX_VARIABLE_NAME];
|
2360
|
+
sprintf(fl_str, "fl_d_%d", *c);
|
2361
|
+
clause.push(~Lit(_variables->string(fl_str)));
|
2362
|
+
|
2363
|
+
for (int wl = 0; wl < *c - 1; wl++) {
|
2364
|
+
if (_linked_possible(wl, *c)) {
|
2365
|
+
const std::vector<PositionConnector>& vc = _word_tags[wl].get_right_connectors();
|
2366
|
+
std::vector<PositionConnector>::const_iterator i;
|
2367
|
+
for (i = vc.begin(); i != vc.end(); i++) {
|
2368
|
+
if (link_cw_possible(wl, i->position, i->connector->string, '+', *c, 1, _sent->length - 1))
|
2369
|
+
clause.push(Lit(_variables->link_cw(*c, wl, (*i).position, (*i).connector->string)));
|
2370
|
+
}
|
2371
|
+
}
|
2372
|
+
}
|
2373
|
+
for (int wr = *c+2; wr < _sent->length; wr++) {
|
2374
|
+
if (_linked_possible(*c, wr)) {
|
2375
|
+
const std::vector<PositionConnector>& vc = _word_tags[wr].get_left_connectors();
|
2376
|
+
std::vector<PositionConnector>::const_iterator i;
|
2377
|
+
for (i = vc.begin(); i != vc.end(); i++) {
|
2378
|
+
if (link_cw_possible(wr, i->position, i->connector->string, '-', *c, 1, _sent->length - 1))
|
2379
|
+
clause.push(Lit(_variables->link_cw(*c, wr, (*i).position, (*i).connector->string)));
|
2380
|
+
}
|
2381
|
+
}
|
2382
|
+
}
|
2383
|
+
|
2384
|
+
std::vector<int>::const_iterator c1;
|
2385
|
+
for (c1 = _connectives.begin(); c1 != _connectives.end(); c1++) {
|
2386
|
+
if (c1 != c)
|
2387
|
+
clause.push(Lit(_variables->fat_link(*c, *c1)));
|
2388
|
+
}
|
2389
|
+
add_clause(clause);
|
2390
|
+
}
|
2391
|
+
DEBUG_print("---end Fat link must be connected on the upper side");
|
2392
|
+
}
|
2393
|
+
|
2394
|
+
void SATEncoderConjunctiveSentences::either_tag_or_fat_link(int w, Lit tag) {
|
2395
|
+
DEBUG_print("----either tag or fat_link");
|
2396
|
+
vec<Lit> clause;
|
2397
|
+
char fl_str[MAX_VARIABLE_NAME];
|
2398
|
+
sprintf(fl_str, "fl_d_%d", w);
|
2399
|
+
|
2400
|
+
// Either tag of the word is satisfied or there must be fat-link on
|
2401
|
+
// this word
|
2402
|
+
clause.growTo(2);
|
2403
|
+
clause[0] = tag;
|
2404
|
+
clause[1] = Lit(_variables->string(fl_str));
|
2405
|
+
add_clause(clause);
|
2406
|
+
|
2407
|
+
// There cannot be both fat-links and a satisfied tag
|
2408
|
+
clause.growTo(2);
|
2409
|
+
clause[0] = ~tag;
|
2410
|
+
clause[1] = ~Lit(_variables->string(fl_str));
|
2411
|
+
add_clause(clause);
|
2412
|
+
|
2413
|
+
DEBUG_print("----end either tag or fat_link");
|
2414
|
+
}
|
2415
|
+
|
2416
|
+
// Check if there can be a connection between the connector (wi, pi)
|
2417
|
+
// with the word w when the word w has fat links down
|
2418
|
+
bool SATEncoderConjunctiveSentences::link_cw_possible_with_fld(int wi, int pi, const char* Ci,
|
2419
|
+
char dir, int w, int llim, int rlim) {
|
2420
|
+
// Connective word can match iff the connector is andable and there
|
2421
|
+
// are words wk1 and wk2 such that B(wi, wk1, w) and B(wi, w, wk1)
|
2422
|
+
// and there are connectors on wk1 and wk2 that can match (wi, pi)
|
2423
|
+
Connector conn;
|
2424
|
+
init_connector(&conn);
|
2425
|
+
conn.label = NORMAL_LABEL;
|
2426
|
+
conn.priority = THIN_priority;
|
2427
|
+
conn.string = Ci;
|
2428
|
+
bool andable_opposite = is_andable(_sent, &conn, dir == '+' ? '-' : '+');
|
2429
|
+
|
2430
|
+
if (!andable_opposite) {
|
2431
|
+
return false;
|
2432
|
+
}
|
2433
|
+
|
2434
|
+
int low = wi < w ? std::max(llim, wi + 1) : llim;
|
2435
|
+
int hi = wi < w ? rlim : std::min(wi, rlim);
|
2436
|
+
|
2437
|
+
return matches_in_interval(wi, pi, low, w) && matches_in_interval(wi, pi, w + 1, hi);
|
2438
|
+
}
|
2439
|
+
|
2440
|
+
// Check if there can be a connection between the connector (wi, pi) with the word w
|
2441
|
+
bool SATEncoderConjunctiveSentences::link_cw_possible(int wi, int pi, const char* Ci, char dir, int w, int llim, int rlim) {
|
2442
|
+
if (!isConnectiveOrComma(w)) {
|
2443
|
+
// Ordinary word can match iff it has a connector that can match
|
2444
|
+
return _word_tags[w].match_possible(wi, pi);
|
2445
|
+
} else {
|
2446
|
+
// Connective word can match iff it can match as an ordinary word
|
2447
|
+
// or the connector is andable and there are words wk1 and wk2
|
2448
|
+
// such that B(wi, wk1, w) and B(wi, w, wk1) and there are
|
2449
|
+
// connectors on wk1 and wk2 that can match (wi, pi)
|
2450
|
+
return _word_tags[w].match_possible(wi, pi) ||
|
2451
|
+
link_cw_possible_with_fld(wi, pi, Ci, dir, w, llim, rlim);
|
2452
|
+
}
|
2453
|
+
}
|
2454
|
+
|
2455
|
+
|
2456
|
+
|
2457
|
+
|
2458
|
+
void SATEncoderConjunctiveSentences::generate_link_top_ww_connective_comma_definition(Lit lhs, int w1, int w2) {
|
2459
|
+
DEBUG_print("---- link_top_connective_comma");
|
2460
|
+
|
2461
|
+
vec<Lit> clause;
|
2462
|
+
|
2463
|
+
vec<Lit> fatlinks_left, fatlinks_right, link_top_left, link_top_right;
|
2464
|
+
int low = w1 < w2 ? 1 : w2+1;
|
2465
|
+
int hi = w1 < w2 ? w2 : _sent->length - 1;
|
2466
|
+
for (int w = low; w < w1; w++) {
|
2467
|
+
Lit fl(_variables->fat_link(w, w1));
|
2468
|
+
Lit tl(_variables->link_top_ww(w, w2));
|
2469
|
+
|
2470
|
+
clause.growTo(3);
|
2471
|
+
clause[0] = ~fl;
|
2472
|
+
clause[1] = ~lhs;
|
2473
|
+
clause[2] = tl;
|
2474
|
+
add_clause(clause);
|
2475
|
+
|
2476
|
+
fatlinks_left.push(fl);
|
2477
|
+
link_top_left.push(tl);
|
2478
|
+
}
|
2479
|
+
|
2480
|
+
DEBUG_print("---------");
|
2481
|
+
|
2482
|
+
for (int w = w1 + 1; w < hi; w++) {
|
2483
|
+
Lit fr(_variables->fat_link(w, w1));
|
2484
|
+
Lit tr(_variables->link_top_ww(w, w2));
|
2485
|
+
|
2486
|
+
clause.growTo(3);
|
2487
|
+
clause[0] = ~fr;
|
2488
|
+
clause[1] = ~lhs;
|
2489
|
+
clause[2] = tr;
|
2490
|
+
add_clause(clause);
|
2491
|
+
|
2492
|
+
fatlinks_right.push(fr);
|
2493
|
+
link_top_right.push(tr);
|
2494
|
+
}
|
2495
|
+
|
2496
|
+
clause.clear();
|
2497
|
+
for (int i = 0; i < fatlinks_left.size(); i++) {
|
2498
|
+
for (int j = 0; j < fatlinks_right.size(); j++) {
|
2499
|
+
clause.growTo(5);
|
2500
|
+
clause[0] = ~fatlinks_left[i];
|
2501
|
+
clause[1] = ~link_top_left[i];
|
2502
|
+
clause[2] = ~fatlinks_right[j];
|
2503
|
+
clause[3] = ~link_top_right[j];
|
2504
|
+
clause[4] = lhs;
|
2505
|
+
add_clause(clause);
|
2506
|
+
}
|
2507
|
+
}
|
2508
|
+
|
2509
|
+
DEBUG_print("---- end link_top_connective_comma");
|
2510
|
+
}
|
2511
|
+
|
2512
|
+
|
2513
|
+
void SATEncoderConjunctiveSentences::generate_linked_definitions() {
|
2514
|
+
Matrix<int> _thin_link_possible;
|
2515
|
+
_thin_link_possible.resize(_sent->length, 1);
|
2516
|
+
|
2517
|
+
DEBUG_print("------- link_top_ww definitions");
|
2518
|
+
for (int w1 = 0; w1 < _sent->length; w1++) {
|
2519
|
+
for (int w2 = 0; w2 < _sent->length; w2++) {
|
2520
|
+
if (w1 == w2)
|
2521
|
+
continue;
|
2522
|
+
DEBUG_print("---------- ." << w1 << ". ." << w2 << ".");
|
2523
|
+
Lit lhs;
|
2524
|
+
vec<Lit> rhs;
|
2525
|
+
const std::vector<PositionConnector>& w1_connectors =
|
2526
|
+
(w1 < w2) ? _word_tags[w1].get_right_connectors() : _word_tags[w1].get_left_connectors();
|
2527
|
+
std::vector<PositionConnector>::const_iterator c;
|
2528
|
+
for (c = w1_connectors.begin(); c != w1_connectors.end(); c++) {
|
2529
|
+
if (link_cw_possible(w1, c->position, c->connector->string, c->dir, w2, 1, _sent->length - 1)) {
|
2530
|
+
rhs.push(Lit(_variables->link_top_cw(w2, w1, c->position, c->connector->string)));
|
2531
|
+
}
|
2532
|
+
}
|
2533
|
+
lhs = Lit(_variables->link_top_ww(w1, w2));
|
2534
|
+
|
2535
|
+
if (!isConnectiveOrComma(w1) || abs(w1 - w2) == 1) {
|
2536
|
+
if (rhs.size() == 0)
|
2537
|
+
_thin_link_possible.set(w1, w2, 0);
|
2538
|
+
|
2539
|
+
generate_or_definition(lhs, rhs);
|
2540
|
+
} else {
|
2541
|
+
char w1_str[MAX_VARIABLE_NAME];
|
2542
|
+
sprintf(w1_str, "w%d", w1);
|
2543
|
+
generate_conditional_or_definition(Lit(_variables->string(w1_str)), lhs, rhs);
|
2544
|
+
generate_link_top_ww_connective_comma_definition(lhs, w1, w2);
|
2545
|
+
}
|
2546
|
+
|
2547
|
+
DEBUG_print("----------");
|
2548
|
+
}
|
2549
|
+
}
|
2550
|
+
DEBUG_print("------- end link_top_ww definitions");
|
2551
|
+
|
2552
|
+
|
2553
|
+
DEBUG_print("------- thin_link definitions");
|
2554
|
+
Lit lhs;
|
2555
|
+
vec<Lit> rhs;
|
2556
|
+
for (int w1 = 0; w1 < _sent->length - 1; w1++) {
|
2557
|
+
for (int w2 = w1 + 1; w2 < _sent->length; w2++) {
|
2558
|
+
rhs.clear();
|
2559
|
+
if (_thin_link_possible(w1, w2)) {
|
2560
|
+
lhs = Lit(_variables->thin_link(w1, w2));
|
2561
|
+
rhs.growTo(2);
|
2562
|
+
rhs[0] = Lit(_variables->link_top_ww(w1, w2));
|
2563
|
+
rhs[1] = Lit(_variables->link_top_ww(w2, w1));
|
2564
|
+
generate_classical_and_definition(lhs, rhs);
|
2565
|
+
}
|
2566
|
+
}
|
2567
|
+
}
|
2568
|
+
DEBUG_print("------- thin_linked definitions");
|
2569
|
+
|
2570
|
+
|
2571
|
+
DEBUG_print("------- linked definitions");
|
2572
|
+
_linked_possible.resize(_sent->length, 1);
|
2573
|
+
for (int w1 = 0; w1 < _sent->length - 1; w1++) {
|
2574
|
+
for (int w2 = w1 + 1; w2 < _sent->length; w2++) {
|
2575
|
+
rhs.clear();
|
2576
|
+
if (_thin_link_possible(w1, w2))
|
2577
|
+
rhs.push(Lit(_variables->thin_link(w1, w2)));
|
2578
|
+
if (isConnectiveOrComma(w1) && w2 < _sent->length - 1)
|
2579
|
+
rhs.push(Lit(_variables->fat_link(w2, w1)));
|
2580
|
+
if (isConnectiveOrComma(w2) && w1 > 0)
|
2581
|
+
rhs.push(Lit(_variables->fat_link(w1, w2)));
|
2582
|
+
|
2583
|
+
if (rhs.size() > 0) {
|
2584
|
+
lhs = Lit(_variables->linked(w1, w2));
|
2585
|
+
generate_or_definition(lhs, rhs);
|
2586
|
+
_linked_possible.set(w1, w2, 1);
|
2587
|
+
}
|
2588
|
+
else {
|
2589
|
+
_linked_possible.set(w1, w2, 0);
|
2590
|
+
}
|
2591
|
+
}
|
2592
|
+
}
|
2593
|
+
DEBUG_print("------- linked definitions");
|
2594
|
+
|
2595
|
+
|
2596
|
+
DEBUG_print("---Weak connectivity");
|
2597
|
+
for (int w1 = 0; w1 < _sent->length; w1++) {
|
2598
|
+
// At least one link should exist (weak connectivity)
|
2599
|
+
vec<Lit> clause;
|
2600
|
+
for (int w2 = 0; w2 < w1; w2++) {
|
2601
|
+
if (_linked_possible(w2, w1))
|
2602
|
+
clause.push(Lit(_variables->linked(w2, w1)));
|
2603
|
+
}
|
2604
|
+
for (int w2 = w1+1; w2 < _sent->length; w2++) {
|
2605
|
+
if (_linked_possible(w1, w2))
|
2606
|
+
clause.push(Lit(_variables->linked(w1, w2)));
|
2607
|
+
}
|
2608
|
+
add_clause(clause);
|
2609
|
+
}
|
2610
|
+
DEBUG_print("---end Weak connectivity");
|
2611
|
+
|
2612
|
+
}
|
2613
|
+
|
2614
|
+
|
2615
|
+
void SATEncoderConjunctiveSentences::get_satisfied_link_top_cw_connectors(int word, int top_word,
|
2616
|
+
std::vector<int>& link_top_cw_vars) {
|
2617
|
+
static int tab = 0;
|
2618
|
+
|
2619
|
+
// Check if top_word acts as an ordinary or as a special connective words
|
2620
|
+
char str[MAX_VARIABLE_NAME];
|
2621
|
+
sprintf(str, "w%d", top_word);
|
2622
|
+
bool ordinary = _solver->model[_variables->string(str)] == l_True;
|
2623
|
+
|
2624
|
+
if (ordinary) {
|
2625
|
+
const std::vector<int>& link_top_cw_variables = _variables->link_top_cw_variables();
|
2626
|
+
std::vector<int>::const_iterator i;
|
2627
|
+
for (i = link_top_cw_variables.begin(); i != link_top_cw_variables.end(); i++) {
|
2628
|
+
if (_solver->model[*i] != l_True)
|
2629
|
+
continue;
|
2630
|
+
|
2631
|
+
const Variables::LinkTopCWVar* var = _variables->link_top_cw_variable(*i);
|
2632
|
+
if (var->top_word != word || var->connector_word != top_word)
|
2633
|
+
continue;
|
2634
|
+
|
2635
|
+
link_top_cw_vars.push_back(*i);
|
2636
|
+
}
|
2637
|
+
|
2638
|
+
} else {
|
2639
|
+
// Find two words that are fat_linked up to the top word
|
2640
|
+
for (int w = 1; w < _sent->length - 1; w++) {
|
2641
|
+
if (w == top_word)
|
2642
|
+
continue;
|
2643
|
+
if (_solver->model[_variables->fat_link(w, top_word)] == l_True) {
|
2644
|
+
get_satisfied_link_top_cw_connectors(word, w, link_top_cw_vars);
|
2645
|
+
}
|
2646
|
+
}
|
2647
|
+
}
|
2648
|
+
}
|
2649
|
+
|
2650
|
+
bool SATEncoderConjunctiveSentences::extract_links(Parse_info pi)
|
2651
|
+
{
|
2652
|
+
int current_link = 0;
|
2653
|
+
bool fat = false;
|
2654
|
+
|
2655
|
+
const std::vector<int>& linked_variables = _variables->linked_variables();
|
2656
|
+
std::vector<int>::const_iterator i;
|
2657
|
+
for (i = linked_variables.begin(); i != linked_variables.end(); i++) {
|
2658
|
+
if (_solver->model[*i] != l_True)
|
2659
|
+
continue;
|
2660
|
+
|
2661
|
+
const Variables::LinkedVar* var = _variables->linked_variable(*i);
|
2662
|
+
|
2663
|
+
// Check if words are connected with a fat-link
|
2664
|
+
bool fl_lr = 0 < var->left_word && var->right_word < _sent->length - 1 &&
|
2665
|
+
parse_options_get_use_fat_links(_opts) &&
|
2666
|
+
isConnectiveOrComma(var->right_word) &&
|
2667
|
+
_solver->model[_variables->fat_link(var->left_word, var->right_word)] == l_True;
|
2668
|
+
bool fl_rl = 0 < var->left_word && var->right_word < _sent->length - 1 &&
|
2669
|
+
parse_options_get_use_fat_links(_opts) &&
|
2670
|
+
isConnectiveOrComma(var->left_word) &&
|
2671
|
+
_solver->model[_variables->fat_link(var->right_word, var->left_word)] == l_True;
|
2672
|
+
if (fl_lr || fl_rl) {
|
2673
|
+
// a fat link
|
2674
|
+
pi->link_array[current_link].l = var->left_word;
|
2675
|
+
pi->link_array[current_link].r = var->right_word;
|
2676
|
+
|
2677
|
+
Connector* connector;
|
2678
|
+
|
2679
|
+
connector = connector_new();
|
2680
|
+
connector->priority = fl_lr ? UP_priority : DOWN_priority;
|
2681
|
+
connector->string = "fat";
|
2682
|
+
pi->link_array[current_link].lc = connector;
|
2683
|
+
|
2684
|
+
connector = connector_new();
|
2685
|
+
connector->priority = fl_lr ? DOWN_priority : UP_priority;
|
2686
|
+
connector->string = "fat";
|
2687
|
+
pi->link_array[current_link].rc = connector;
|
2688
|
+
|
2689
|
+
current_link++;
|
2690
|
+
fat = true;
|
2691
|
+
} else {
|
2692
|
+
// a thin link
|
2693
|
+
std::vector<int> link_top_cw_vars_right;
|
2694
|
+
std::vector<int> link_top_cw_vars_left;
|
2695
|
+
get_satisfied_link_top_cw_connectors(var->left_word, var->right_word, link_top_cw_vars_left);
|
2696
|
+
get_satisfied_link_top_cw_connectors(var->right_word, var->left_word, link_top_cw_vars_right);
|
2697
|
+
|
2698
|
+
std::vector<const char*> strings_right;
|
2699
|
+
std::vector<int>::const_iterator rc, lc;
|
2700
|
+
for (rc = link_top_cw_vars_right.begin(); rc != link_top_cw_vars_right.end(); rc++) {
|
2701
|
+
const Variables::LinkTopCWVar* var = _variables->link_top_cw_variable(*rc);
|
2702
|
+
strings_right.push_back(var->connector);
|
2703
|
+
}
|
2704
|
+
|
2705
|
+
std::vector<const char*> strings_left;
|
2706
|
+
for (lc = link_top_cw_vars_left.begin(); lc != link_top_cw_vars_left.end(); lc++) {
|
2707
|
+
const Variables::LinkTopCWVar* var = _variables->link_top_cw_variable(*lc);
|
2708
|
+
strings_left.push_back(var->connector);
|
2709
|
+
}
|
2710
|
+
|
2711
|
+
// String unification
|
2712
|
+
std::vector<const char*>::const_iterator li, ri;
|
2713
|
+
const char* left_string = strings_left[0];
|
2714
|
+
for (li = strings_left.begin() + 1; li != strings_left.end(); li++) {
|
2715
|
+
left_string = intersect_strings(_sent, left_string, *li);
|
2716
|
+
}
|
2717
|
+
|
2718
|
+
const char* right_string = strings_right[0];
|
2719
|
+
for (ri = strings_right.begin() + 1; ri != strings_right.end(); ri++) {
|
2720
|
+
right_string = intersect_strings(_sent, right_string, *ri);
|
2721
|
+
}
|
2722
|
+
|
2723
|
+
pi->link_array[current_link].l = var->left_word;
|
2724
|
+
pi->link_array[current_link].r = var->right_word;
|
2725
|
+
|
2726
|
+
Connector* connector;
|
2727
|
+
|
2728
|
+
connector = connector_new();
|
2729
|
+
connector->string = right_string;
|
2730
|
+
pi->link_array[current_link].lc = connector;
|
2731
|
+
|
2732
|
+
connector = connector_new();
|
2733
|
+
connector->string = left_string;
|
2734
|
+
pi->link_array[current_link].rc = connector;
|
2735
|
+
|
2736
|
+
current_link++;
|
2737
|
+
}
|
2738
|
+
}
|
2739
|
+
|
2740
|
+
pi->N_links = current_link;
|
2741
|
+
return fat;
|
2742
|
+
}
|
2743
|
+
|
2744
|
+
|
2745
|
+
/****************************************************************************
|
2746
|
+
* Main entry point into the SAT parser *
|
2747
|
+
****************************************************************************/
|
2748
|
+
extern "C" int sat_parse(Sentence sent, Parse_Options opts)
|
2749
|
+
{
|
2750
|
+
SATEncoder* encoder = (SATEncoder*) sent->hook;
|
2751
|
+
if (encoder) delete encoder;
|
2752
|
+
|
2753
|
+
// Prepare for parsing - extracted for "preparation.c"
|
2754
|
+
build_deletable(sent, 0);
|
2755
|
+
build_effective_dist(sent, 0);
|
2756
|
+
init_count(sent);
|
2757
|
+
count_set_effective_distance(sent);
|
2758
|
+
|
2759
|
+
bool conjunction = FALSE;
|
2760
|
+
if (parse_options_get_use_fat_links(opts)) {
|
2761
|
+
conjunction = sentence_contains_conjunction(sent);
|
2762
|
+
}
|
2763
|
+
|
2764
|
+
// Create the encoder, encode the formula and solve it
|
2765
|
+
if (conjunction) {
|
2766
|
+
DEBUG_print("Conjunctive sentence\n");
|
2767
|
+
encoder = new SATEncoderConjunctiveSentences(sent, opts);
|
2768
|
+
} else {
|
2769
|
+
DEBUG_print("Conjunction free sentence\n");
|
2770
|
+
encoder = new SATEncoderConjunctionFreeSentences(sent, opts);
|
2771
|
+
}
|
2772
|
+
sent->hook = encoder;
|
2773
|
+
encoder->encode();
|
2774
|
+
|
2775
|
+
// XXX this is wrong, we actually don't know yet ...
|
2776
|
+
// If we don't return some large number here, then the
|
2777
|
+
// Command-line client will fail to print all of the possible
|
2778
|
+
// linkages. Work around this by lying ...
|
2779
|
+
sent->num_valid_linkages = 222;
|
2780
|
+
sent->num_linkages_post_processed = 222;
|
2781
|
+
|
2782
|
+
return 0;
|
2783
|
+
}
|
2784
|
+
|
2785
|
+
extern "C" Linkage sat_create_linkage(int k, Sentence sent, Parse_Options opts)
|
2786
|
+
{
|
2787
|
+
SATEncoder* encoder = (SATEncoder*) sent->hook;
|
2788
|
+
if (!encoder) return NULL;
|
2789
|
+
|
2790
|
+
return encoder->get_next_linkage();
|
2791
|
+
}
|
2792
|
+
|
2793
|
+
extern "C" void sat_sentence_delete(Sentence sent)
|
2794
|
+
{
|
2795
|
+
SATEncoder* encoder = (SATEncoder*) sent->hook;
|
2796
|
+
if (!encoder) return;
|
2797
|
+
delete encoder;
|
2798
|
+
|
2799
|
+
// Don't do this parse-info-free stuff, if there's no encoder.
|
2800
|
+
// That's because it will screw up the regular parser.
|
2801
|
+
if (sent->parse_info) {
|
2802
|
+
Parse_info pi = sent->parse_info;
|
2803
|
+
for (int i=0; i< MAX_LINKS; i++) {
|
2804
|
+
free_connectors(pi->link_array[i].lc);
|
2805
|
+
free_connectors(pi->link_array[i].rc);
|
2806
|
+
}
|
2807
|
+
free_parse_info(sent->parse_info);
|
2808
|
+
sent->parse_info = NULL;
|
2809
|
+
}
|
2810
|
+
|
2811
|
+
}
|