semRewrite.CNF Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sigma-nlp Show documentation
Show all versions of sigma-nlp Show documentation
Natural language processing toolbox using Sigma knowledge engineering system.
package semRewrite;
/*
Copyright 2014-2015 IPsoft
Author: Adam Pease [email protected]
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program ; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
*/
import semRewrite.Clause;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Conjunctive Normal Form
*/
public class CNF {
public ArrayList clauses = new ArrayList();
/** ***************************************************************
*/
public String toString() {
StringBuffer sb = new StringBuffer();
//sb.append("[");
for (int i = 0; i < clauses.size(); i++) {
semRewrite.Clause d = clauses.get(i);
sb.append(d.toString());
if (clauses.size() > 1 && i < clauses.size() - 1)
sb.append(", ");
}
//sb.append("]");
return sb.toString();
}
/** ***************************************************************
*/
public List toListString() {
List retString = Lists.newArrayList();
for (semRewrite.Clause clause : clauses) {
retString.add(clause.toString());
}
return retString;
}
/** ***************************************************************
*/
@Override
public boolean equals(Object o) {
if (!(o instanceof semRewrite.CNF))
return false;
semRewrite.CNF cnf = (semRewrite.CNF) o;
//System.out.println("INFO in CNF.equals(): Checking " + cnf + " against " + this);
if (clauses.size() != cnf.clauses.size())
return false;
for (int i = 0; i < clauses.size(); i++) {
//System.out.println("INFO in CNF.equals(): checking disjunct " + clauses.get(i) +
// " " + cnf.clauses.get(i));
if (!clauses.get(i).equals(cnf.clauses.get(i)))
return false;
}
//System.out.println("INFO in CNF.equals(): true!");
return true;
}
/** ***************************************************************
*/
public semRewrite.CNF deepCopy() {
semRewrite.CNF cnfnew = new semRewrite.CNF();
for (int i = 0; i < clauses.size(); i++) {
cnfnew.clauses.add(clauses.get(i).deepCopy());
}
return cnfnew;
}
/** *************************************************************
*/
public boolean empty() {
return clauses.size() == 0;
}
/** *************************************************************
*/
public void preProcessQuestionWords(List qwords) {
for (semRewrite.Clause d: clauses)
d.preProcessQuestionWords(qwords);
}
/** ***************************************************************
*/
public void clearBound() {
//System.out.println("INFO in CNF.clearBound(): before " + this);
ArrayList newclauses = new ArrayList();
for (int i = 0; i < clauses.size(); i++) {
semRewrite.Clause d = clauses.get(i);
d.clearBound();
if (!d.empty())
newclauses.add(d);
}
//System.out.println("INFO in CNF.clearBound(): after " + this);
}
/** ***************************************************************
*/
public void clearPreserve() {
//System.out.println("INFO in CNF.clearBound(): before " + this);
ArrayList newclauses = new ArrayList();
for (int i = 0; i < clauses.size(); i++) {
semRewrite.Clause d = clauses.get(i);
d.clearPreserve();
if (!d.empty())
newclauses.add(d);
}
//System.out.println("INFO in CNF.clearBound(): after " + this);
}
/** ***************************************************************
*/
public void merge(semRewrite.CNF cnf) {
//System.out.println("INFO in CNF.merge(): before " + this + "\narg: " + cnf);
for (int i = 0; i < cnf.clauses.size(); i++)
if (!clauses.contains(cnf.clauses.get(i)))
clauses.add(cnf.clauses.get(i));
//System.out.println("INFO in CNF.merge(): after " + this);
}
/** ***************************************************************
*/
public semRewrite.CNF removeBound() {
//System.out.println("INFO in CNF.removeBound(): before " + this);
semRewrite.CNF newCNF = new semRewrite.CNF();
for (int i = 0; i < clauses.size(); i++) {
semRewrite.Clause d = clauses.get(i);
d.removeBound();
if (!d.empty())
newCNF.clauses.add(d);
}
//System.out.println("INFO in CNF.removeBound(): after " + newCNF);
return newCNF;
}
/** ***************************************************************
* Only positive clauses, no disjuncts, which is the output format
* of the Stanford Dependency Parser
*/
public static semRewrite.CNF parseSimple(Lexer lex) {
semRewrite.CNF cnf = new semRewrite.CNF();
String token = "";
try {
ArrayList tokens = new ArrayList();
tokens.add(Lexer.EOFToken);
tokens.add(Lexer.ClosePar);
tokens.add(Lexer.FullStop);
while (!lex.testTok(tokens)) {
semRewrite.Clause d = new semRewrite.Clause();
Literal c = Literal.parse(lex, 0);
d.disjuncts.add(c);
cnf.clauses.add(d);
if (lex.testTok(Lexer.Comma))
lex.next();
else if (lex.testTok(Lexer.ClosePar)) {
lex.next();
//System.out.println("INFO in CNF.parseSimple(): final token: " + lex.look());
if (!lex.testTok(Lexer.FullStop))
System.out.println("Error in CNF.parseSimple(): Bad token: " + lex.look());
}
else
if (!lex.testTok(Lexer.FullStop))
System.out.println("Error in CNF.parseSimple(): Bad token: " + lex.look());
}
}
catch (Exception ex) {
String message = ex.getMessage();
System.out.println("Error in CNF.parse(): " + message);
ex.printStackTrace();
}
//System.out.println("INFO in CNF.parseSimple(): returning: " + cnf);
return cnf;
}
/** ***************************************************************
* Apply variable substitutions to this set of clauses
*/
public semRewrite.CNF applyBindings(HashMap bindings) {
semRewrite.CNF cnf = new semRewrite.CNF();
for (int i = 0; i < clauses.size(); i++) {
semRewrite.Clause d = clauses.get(i);
semRewrite.Clause dnew = new semRewrite.Clause();
for (int j = 0; j < d.disjuncts.size(); j++) {
Literal c = d.disjuncts.get(j);
//System.out.println("INFO in CNF.applyBindings(): 1 " + c);
Literal c2 = c.applyBindings(bindings);
//System.out.println("INFO in CNF.applyBindings(): 1.5 " + c2);
dnew.disjuncts.add(c2);
//System.out.println("INFO in CNF.applyBindings(): 2 " + dnew);
}
//System.out.println("INFO in CNF.applyBindings(): 3 " + dnew);
cnf.clauses.add(dnew);
}
return cnf;
}
/** ***************************************************************
* Copy bound flags to this set of clauses
*/
public void copyBoundFlags(semRewrite.CNF cnf) {
for (int i = 0; i < clauses.size(); i++)
clauses.get(i).copyBoundFlags(cnf.clauses.get(i));
}
/** ***************************************************************
* Test a disjunct from a rule against a sentence. It must succeed
* for the rule to be bound. If a binding is found, it can exit
* without trying all the options.
*/
private HashMap unifyDisjunct(semRewrite.Clause d1, semRewrite.CNF cnf2, semRewrite.CNF cnf1, HashMap bindings) {
//System.out.println("INFO in CNF.unifyDisjunct(): checking " + d1 + " against " + cnf2);
HashMap result = new HashMap();
for (semRewrite.Clause d2 : cnf2.clauses) { // sentence
//System.out.println("INFO in CNF.unifyDisjunct(): checking " + d1 + " against " + d2);
HashMap bindings2 = d2.unify(d1);
//System.out.println("INFO in CNF.unifyDisjunct(): d1 " + d1 + " d2 " + d2);
//System.out.println("INFO in CNF.unifyDisjunct(): checked " + d1 + " against " + d2);
//System.out.println("INFO in CNF.unifyDisjunct(): bindings " + bindings2);
if (bindings2 != null) {
return bindings2;
}
}
return null;
}
/** ***************************************************************
* Unify this CNF with the argument. Note that the argument should
* be a superset of clauses of (or equal to) this instance. The argument
* is the "sentence" and this is the "rule"
*/
public HashMap unify(semRewrite.CNF cnf) {
semRewrite.CNF cnfnew2 = cnf.deepCopy(); // sentence
semRewrite.CNF cnfnew1 = this.deepCopy(); // rule
boolean negatedClause = false;
//System.out.println("INFO in CNF.unify(): cnf 1 " + cnf);
//System.out.println("INFO in CNF.unify(): this " + this);
HashMap result = new HashMap();
for (int i = 0; i < cnfnew1.clauses.size(); i++) { // rule
Clause d1 = cnfnew1.clauses.get(i);
if (d1.disjuncts.size() == 1 && d1.disjuncts.get(0).negated)
negatedClause = true;
HashMap result2 = unifyDisjunct(d1,cnfnew2,cnfnew1,result);
//System.out.println("INFO in CNF.unify(): results2 " + result2);
//System.out.println("INFO in CNF.unify(): cnfnew1 " + cnfnew1);
//System.out.println("INFO in CNF.unify(): cnfnew2 " + cnfnew2);
if (negatedClause) {
if (result2 != null) { // successful binding is a failure for a negated clause
//System.out.println("INFO in CNF.unify(): found a binding for a negated clause " + cnfnew1 + " with " + cnfnew2);
cnf.clearBound();
return null;
}
//System.out.println("INFO in CNF.unify(): no binding for a negated clause " + d1 + " with " + cnfnew2);
cnf.clearBound();
}
else {
if (result2 == null) { // every clause in the rule must match to succeed
cnf.clearBound(); // if no success, wipe all the intermediate bindings.
return null;
}
else {
cnf.copyBoundFlags(cnfnew2);
cnfnew1 = cnfnew1.applyBindings(result2);
//System.out.println("INFO in CNF.unify(): cnf 1 " + cnfnew1);
//System.out.println("INFO in CNF.unify(): cnf 2 " + cnfnew2);
cnfnew2 = cnfnew2.applyBindings(result2);
result.putAll(result2);
//System.out.println("INFO in CNF.unify(): bindings " + result);
}
}
}
if (result.keySet().size() == 0)
result = null;
//cnf.clearBound(); // if no success, wipe all the intermediate bindings.
return result;
}
/** *************************************************************
* A test method
*/
public static void testMerge() {
Lexer lex = new Lexer("sumo(BodyMotion,Bob-2), sumo(Human,John-1).");
semRewrite.CNF cnf1 = semRewrite.CNF.parseSimple(lex);
Lexer lex2 = new Lexer("foo(BodyMotion,Bob-2), bar(Human,John-1).");
semRewrite.CNF cnf2 = semRewrite.CNF.parseSimple(lex2);
cnf1.merge(cnf2);
System.out.println("INFO in CNF.testEquality(): should have four clauses: " + cnf1);
}
/** *************************************************************
* A test method
*/
public static void testParseSimple() {
Lexer lex = new Lexer("num(?O,?N), +sumo(?C,?O).");
semRewrite.CNF cnf1 = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testParseSimple(): " + cnf1);
}
/** *************************************************************
* A test method
*/
public static void testEquality() {
Lexer lex = new Lexer("sumo(BodyMotion,Bob-2), sumo(Human,John-1).");
semRewrite.CNF cnf1 = semRewrite.CNF.parseSimple(lex);
Lexer lex2 = new Lexer("sumo(BodyMotion,Bob-2), sumo(Human,John-1).");
semRewrite.CNF cnf2 = semRewrite.CNF.parseSimple(lex2);
System.out.println("INFO in CNF.testEquality(): should be true: " + cnf1.equals(cnf2));
}
/** *************************************************************
* A test method
*/
public static void testContains() {
Lexer lex = new Lexer("sumo(BodyMotion,Bob-2).");
semRewrite.CNF cnf1 = semRewrite.CNF.parseSimple(lex);
Lexer lex2 = new Lexer("sumo(BodyMotion,Bob-2).");
semRewrite.CNF cnf2 = semRewrite.CNF.parseSimple(lex2);
ArrayList al = new ArrayList();
al.add(cnf1);
if (!al.contains(cnf2))
al.add(cnf2);
System.out.println("INFO in CNF.testEquality(): should be 1: " + al.size());
}
/** *************************************************************
* A test method
*/
public static void testUnify() {
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
String rule = "sense(212345678,?E) ==> " +
"(sumo(Foo,?E)).";
Rule r = new Rule();
r = Rule.parseString(rule);
System.out.println(r.toString());
semRewrite.CNF cnf1 = Clausifier.clausify(r.lhs);
Lexer lex = new Lexer("sense(212345678,Foo).");
semRewrite.CNF cnf = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf1);
System.out.println("INFO in CNF.testUnify(): bindings: " + cnf1.unify(cnf));
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): expecting: Xsense(212345678,Foo).");
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
rule = "sense(212345678,?E) ==> " +
"(sumo(Foo,?E)).";
r = new Rule();
r = Rule.parseString(rule);
System.out.println(r.toString());
cnf1 = Clausifier.clausify(r.lhs);
lex = new Lexer("sense(2123,Foo).");
cnf = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf1);
System.out.println("INFO in CNF.testUnify(): bindings (should be null): " + cnf1.unify(cnf));
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
String rule2 = "det(?X,What*), sumo(?O,?X).";
lex = new Lexer(rule2);
cnf1 = semRewrite.CNF.parseSimple(lex);
String clauses = "nsubj(drives-2,John-1), root(ROOT-0,drives-2), sumo(Transportation,drives-2), sumo(Human,John-1).";
lex = new Lexer(clauses);
cnf = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf1);
System.out.println("INFO in CNF.testUnify(): bindings (should be null): " + cnf1.unify(cnf));
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
rule2 = "nsubj(?X,?Y), sumo(?O,?X).";
lex = new Lexer(rule2);
cnf1 = semRewrite.CNF.parseSimple(lex);
clauses = "nsubj(drives-2,John-1), root(ROOT-0,drives-2), sumo(Transportation,drives-2), sumo(Human,John-1).";
lex = new Lexer(clauses);
cnf = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf1);
System.out.println("INFO in CNF.testUnify(): bindings: " + cnf1.unify(cnf));
System.out.println("INFO in CNF.testUnify(): expecting: Xnsubj(drives-2,John-1), root(ROOT-0,drives-2), Xsumo(Transportation,drives-2), sumo(Human,John-1).");
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
rule = "nsubj(?V,?Who*).";
lex = new Lexer(rule);
cnf1 = semRewrite.CNF.parseSimple(lex);
String cnfstr = "nsubj(kicks-2,John-1), root(ROOT-0,kicks-2), det(cart-4,the-3), dobj(kicks-2,cart-4), sumo(Kicking,kicks-2), sumo(Human,John-1), sumo(Wagon,cart-4).";
lex = new Lexer(cnfstr);
cnf = semRewrite.CNF.parseSimple(lex);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf1);
System.out.println("INFO in CNF.testUnify(): bindings (should be null): " + cnf1.unify(cnf));
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
String rule3 = "nsubj(?V,Who*).";
Lexer lex2 = new Lexer(rule3);
semRewrite.CNF cnf12 = semRewrite.CNF.parseSimple(lex2);
String cnfstr2 = "nsubj(moves-2,Who-1), root(ROOT-0,kicks-2), det(cart-4,the-3), dobj(kicks-2,cart-4), sumo(Kicking,kicks-2), sumo(Human,John-1), sumo(Wagon,cart-4).";
lex2 = new Lexer(cnfstr2);
semRewrite.CNF cnf2 = semRewrite.CNF.parseSimple(lex2);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf2);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf12);
System.out.println("INFO in CNF.testUnify(): bindings (should be null): " + cnf12.unify(cnf2));
System.out.println("INFO in CNF.testUnify(): -------------------------------------");
String rule4 = "StartTime(?V,?T), day(?T,?D), month(?T,?M), year(?T,?Y).";
Lexer lex4 = new Lexer(rule4);
semRewrite.CNF cnf4 = semRewrite.CNF.parseSimple(lex4);
//String cnfstr5 = "root(ROOT-0,be-3), det(celebration-2,the-1), nsubj(be-3,celebration-2), prep_from(be-3,July-5), num(July-5,5-6), num(July-5,1980-8), prep_to(be-3,August-10), num(August-10,4-11), num(August-10,1980-13), sumo(SocialParty,celebration-2), number(SINGULAR,celebration-2), tense(PAST,be-3), number(SINGULAR,July-5), number(SINGULAR,August-10), day(time-2,4), StartTime(was-3,time-1), month(time-1,July), year(time-1,1980), month(time-2,August), EndTime(was-3,time-2), day(time-1,5), year(time-2,1980)";
String cnfstr5 = "day(time-2,4), StartTime(was-3,time-1), month(time-1,July), year(time-1,1980), month(time-2,August), EndTime(was-3,time-2), day(time-1,5), year(time-2,1980)";
//String cnfstr5 = "StartTime(was-3,time-1), month(time-1,July), year(time-1,1980), day(time-1,5)";
Lexer lex5 = new Lexer(cnfstr5);
semRewrite.CNF cnf5 = semRewrite.CNF.parseSimple(lex5);
System.out.println("INFO in CNF.testUnify(): cnf " + cnf4);
System.out.println("INFO in CNF.testUnify(): cnf1 " + cnf5);
System.out.println("INFO in CNF.testUnify(): bindings: " + cnf4.unify(cnf5));
}
/** *************************************************************
* A test method
*/
public static void main (String args[]) {
//testEquality();
//testContains();
//testMerge();
testUnify();
//testParseSimple();
}
}