001 package aima.logic.propositional.algorithms; 002 003 import java.util.ArrayList; 004 import java.util.Hashtable; 005 import java.util.Iterator; 006 import java.util.List; 007 import java.util.Set; 008 import java.util.Stack; 009 010 import aima.logic.propositional.parsing.ast.BinarySentence; 011 import aima.logic.propositional.parsing.ast.Sentence; 012 import aima.logic.propositional.parsing.ast.Symbol; 013 import aima.logic.propositional.visitors.SymbolCollector; 014 import aima.util.Converter; 015 016 /** 017 * @author Ravi Mohan 018 * 019 */ 020 021 public class PLFCEntails { 022 023 private Hashtable<HornClause, Integer> count; 024 025 private Hashtable<Symbol, Boolean> inferred; 026 027 private Stack<Symbol> agenda; 028 029 public PLFCEntails() { 030 count = new Hashtable<HornClause, Integer>(); 031 inferred = new Hashtable<Symbol, Boolean>(); 032 agenda = new Stack<Symbol>(); 033 } 034 035 public boolean plfcEntails(KnowledgeBase kb, String s) { 036 return plfcEntails(kb, new Symbol(s)); 037 } 038 039 public boolean plfcEntails(KnowledgeBase kb, Symbol q) { 040 List<HornClause> hornClauses = asHornClauses(kb.getSentences()); 041 while (agenda.size() != 0) { 042 Symbol p = agenda.pop(); 043 while (!inferred(p)) { 044 inferred.put(p, Boolean.TRUE); 045 046 for (int i = 0; i < hornClauses.size(); i++) { 047 HornClause hornClause = hornClauses.get(i); 048 if (hornClause.premisesContainsSymbol(p)) { 049 decrementCount(hornClause); 050 if (countisZero(hornClause)) { 051 if (hornClause.head().equals(q)) { 052 return true; 053 } else { 054 agenda.push(hornClause.head()); 055 } 056 } 057 } 058 } 059 } 060 } 061 return false; 062 } 063 064 private List<HornClause> asHornClauses(List sentences) { 065 List<HornClause> hornClauses = new ArrayList<HornClause>(); 066 for (int i = 0; i < sentences.size(); i++) { 067 Sentence sentence = (Sentence) sentences.get(i); 068 HornClause clause = new HornClause(sentence); 069 hornClauses.add(clause); 070 } 071 return hornClauses; 072 } 073 074 private boolean countisZero(HornClause hornClause) { 075 076 return (count.get(hornClause)).intValue() == 0; 077 } 078 079 private void decrementCount(HornClause hornClause) { 080 int value = (count.get(hornClause)).intValue(); 081 count.put(hornClause, new Integer(value - 1)); 082 083 } 084 085 private boolean inferred(Symbol p) { 086 Object value = inferred.get(p); 087 return ((value == null) || value.equals(Boolean.TRUE)); 088 } 089 090 public class HornClause { 091 List<Symbol> premiseSymbols; 092 093 Symbol head; 094 095 public HornClause(Sentence sentence) { 096 if (sentence instanceof Symbol) { 097 head = (Symbol) sentence; 098 agenda.push(head); 099 premiseSymbols = new ArrayList<Symbol>(); 100 count.put(this, new Integer(0)); 101 inferred.put(head, Boolean.FALSE); 102 } else if (!isImpliedSentence(sentence)) { 103 throw new RuntimeException("Sentence " + sentence 104 + " is not a horn clause"); 105 106 } else { 107 BinarySentence bs = (BinarySentence) sentence; 108 head = (Symbol) bs.getSecond(); 109 inferred.put(head, Boolean.FALSE); 110 Set<Symbol> symbolsInPremise = new SymbolCollector() 111 .getSymbolsIn(bs.getFirst()); 112 Iterator<Symbol> iter = symbolsInPremise.iterator(); 113 while (iter.hasNext()) { 114 inferred.put(iter.next(), Boolean.FALSE); 115 } 116 premiseSymbols = new Converter<Symbol>() 117 .setToList(symbolsInPremise); 118 count.put(this, new Integer(premiseSymbols.size())); 119 } 120 121 } 122 123 private boolean isImpliedSentence(Sentence sentence) { 124 return ((sentence instanceof BinarySentence) && ((BinarySentence) sentence) 125 .getOperator().equals("=>")); 126 } 127 128 public Symbol head() { 129 130 return head; 131 } 132 133 public boolean premisesContainsSymbol(Symbol q) { 134 return premiseSymbols.contains(q); 135 } 136 137 public List getPremiseSymbols() { 138 return premiseSymbols; 139 } 140 141 @Override 142 public boolean equals(Object o) { 143 144 if (this == o) { 145 return true; 146 } 147 if ((o == null) || (this.getClass() != o.getClass())) { 148 return false; 149 } 150 HornClause ohc = (HornClause) o; 151 if (premiseSymbols.size() != ohc.premiseSymbols.size()) { 152 return false; 153 } 154 boolean result = true; 155 for (Symbol s : premiseSymbols) { 156 if (!ohc.premiseSymbols.contains(s)) { 157 return false; 158 } 159 } 160 161 return true; 162 163 } 164 165 @Override 166 public int hashCode() { 167 int result = 17; 168 for (Symbol s : premiseSymbols) { 169 result = 37 * result + s.hashCode(); 170 } 171 return result; 172 } 173 174 @Override 175 public String toString() { 176 return premiseSymbols.toString() + " => " + head; 177 } 178 } 179 }