001 /* 002 * Created on Dec 4, 2004 003 * 004 */ 005 package aima.logic.propositional.visitors; 006 007 import aima.logic.propositional.parsing.AbstractPLVisitor; 008 import aima.logic.propositional.parsing.ast.BinarySentence; 009 import aima.logic.propositional.parsing.ast.Sentence; 010 import aima.logic.propositional.parsing.ast.UnarySentence; 011 012 /** 013 * @author Ravi Mohan 014 * 015 */ 016 public class CNFTransformer extends AbstractPLVisitor { 017 @Override 018 public Object visitBinarySentence(BinarySentence bs, Object arg) { 019 if (bs.isBiconditional()) { 020 return transformBiConditionalSentence(bs); 021 } else if (bs.isImplication()) { 022 return transformImpliedSentence(bs); 023 } else if (bs.isOrSentence() 024 && (bs.firstTermIsAndSentence() || bs.secondTermIsAndSentence())) { 025 return distributeOrOverAnd(bs); 026 } else { 027 return super.visitBinarySentence(bs, arg); 028 } 029 } 030 031 @Override 032 public Object visitNotSentence(UnarySentence us, Object arg) { 033 return transformNotSentence(us); 034 } 035 036 public Sentence transform(Sentence s) { 037 Sentence toTransform = s; 038 while (!(toTransform.equals(step(toTransform)))) { 039 toTransform = step(toTransform); 040 } 041 042 return toTransform; 043 } 044 045 private Sentence step(Sentence s) { 046 return (Sentence) s.accept(this, null); 047 } 048 049 private Sentence transformBiConditionalSentence(BinarySentence bs) { 050 Sentence first = new BinarySentence("=>", (Sentence) bs.getFirst() 051 .accept(this, null), (Sentence) bs.getSecond().accept(this, 052 null)); 053 Sentence second = new BinarySentence("=>", (Sentence) bs.getSecond() 054 .accept(this, null), (Sentence) bs.getFirst() 055 .accept(this, null)); 056 return new BinarySentence("AND", first, second); 057 } 058 059 private Sentence transformImpliedSentence(BinarySentence bs) { 060 Sentence first = new UnarySentence((Sentence) bs.getFirst().accept( 061 this, null)); 062 return new BinarySentence("OR", first, (Sentence) bs.getSecond() 063 .accept(this, null)); 064 } 065 066 private Sentence transformNotSentence(UnarySentence us) { 067 if (us.getNegated() instanceof UnarySentence) { 068 return (Sentence) ((UnarySentence) us.getNegated()).getNegated() 069 .accept(this, null); 070 } else if (us.getNegated() instanceof BinarySentence) { 071 BinarySentence bs = (BinarySentence) us.getNegated(); 072 if (bs.isAndSentence()) { 073 Sentence first = new UnarySentence((Sentence) bs.getFirst() 074 .accept(this, null)); 075 Sentence second = new UnarySentence((Sentence) bs.getSecond() 076 .accept(this, null)); 077 return new BinarySentence("OR", first, second); 078 } else if (bs.isOrSentence()) { 079 Sentence first = new UnarySentence((Sentence) bs.getFirst() 080 .accept(this, null)); 081 Sentence second = new UnarySentence((Sentence) bs.getSecond() 082 .accept(this, null)); 083 return new BinarySentence("AND", first, second); 084 } else { 085 return (Sentence) super.visitNotSentence(us, null); 086 } 087 } else { 088 return (Sentence) super.visitNotSentence(us, null); 089 } 090 } 091 092 private Sentence distributeOrOverAnd(BinarySentence bs) { 093 BinarySentence andTerm = bs.firstTermIsAndSentence() ? (BinarySentence) bs 094 .getFirst() 095 : (BinarySentence) bs.getSecond(); 096 Sentence otherterm = bs.firstTermIsAndSentence() ? bs.getSecond() : bs 097 .getFirst(); 098 // (alpha or (beta and gamma) = ((alpha or beta) and (alpha or gamma)) 099 Sentence alpha = (Sentence) otherterm.accept(this, null); 100 Sentence beta = (Sentence) andTerm.getFirst().accept(this, null); 101 Sentence gamma = (Sentence) andTerm.getSecond().accept(this, null); 102 Sentence distributed = new BinarySentence("AND", new BinarySentence( 103 "OR", alpha, beta), new BinarySentence("OR", alpha, gamma)); 104 return distributed; 105 } 106 107 }