/******************************************************************************* * Copyright (C) 2008-2012 Dominik Jain. * * This file is part of ProbCog. * * ProbCog 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 3 of the License, or * (at your option) any later version. * * ProbCog 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 ProbCog. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package probcog.logic; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Vector; import probcog.srl.GenericDatabase; import edu.tum.cs.util.StringTool; /** * Represents a logical conjunction. * @author Dominik Jain */ public class Conjunction extends ComplexFormula { public Conjunction(Collection<Formula> children) { super(children); } public Conjunction(Formula... children) { super(children); } public String toString() { return "(" + StringTool.join(" ^ ", children) + ")"; } @Override public boolean isTrue(IPossibleWorld w) { for (Formula child : children) if (!child.isTrue(w)) return false; return true; } @Override public Formula toCNF() { /* try{ Negation.cnfDepth++; System.out.printf(String.format("%%%dc", Negation.cnfDepth), ' '); System.out.println(this); */ if(this.children.length == 1) return this.children[0].toCNF(); Vector<Formula> clauses = new Vector<Formula>(); // first convert all children to CNF and eliminate nested conjunctions by collecting all conjuncts centrally for (Formula child : this.children) { child = child.toCNF(); if (child instanceof Conjunction) { Conjunction conj = (Conjunction) child; clauses.addAll(Arrays.asList(conj.children)); } else if (child instanceof TrueFalse) { TrueFalse tf = (TrueFalse) child; if (!tf.isTrue()) return tf; } else clauses.add(child); } // normalize the obtained clauses by eliminating clauses that are supersets of other clauses Vector<HashSet<String>> sclauses = new Vector<HashSet<String>>(); for (Formula clause : clauses) { HashSet<String> s = new HashSet<String>(); if (clause instanceof Disjunction) { for (Formula l : ((Disjunction) clause).children) s.add(l.toString()); } else { s.add(clause.toString()); } sclauses.add(s); } for (int i = 0; i < sclauses.size(); i++) { for (int j = i + 1; j < sclauses.size(); j++) { HashSet<String> s1 = sclauses.get(i); HashSet<String> s2 = sclauses.get(j); int iLarger = j; if (s1.size() > s2.size()) { HashSet<String> t = s1; s1 = s2; s2 = t; iLarger = i; } // s1 is the smaller set; check if the larger set s2 contains all its elements boolean isSubset = true; for (String s : s1) if (!s2.contains(s)) { isSubset = false; break; } if (!isSubset) continue; // remove the larger set sclauses.remove(iLarger); clauses.remove(iLarger); if (iLarger == j) j--; else j = i; } } // return the conjunction of clauses if(clauses.size() == 1) return clauses.get(0); return new Conjunction(clauses); /* } finally { Negation.cnfDepth--; } */ } @Override public Formula toNNF() { Vector<Formula> conjuncts = new Vector<Formula>(); for(Formula child : this.children) { Formula newChild = child.toNNF(); if(newChild instanceof Conjunction) { // flatten nested conjunction for(Formula nestedChild : ((Conjunction)newChild).children) conjuncts.add(nestedChild); } else conjuncts.add(newChild); } return new Conjunction(conjuncts); } /** * This method simplifies the formula (atoms that are given by the evidence are evaluated to TrueFalse) * @param evidence (evidence of the current szenario) * @return returns a Formula simplified by the evidence or an instance of TrueFalse */ @Override public Formula simplify(GenericDatabase<?, ?> evidence) { Vector<Formula> simplifiedChildren = new Vector<Formula>(); // check for each child, whether an entry in evidenceDB exists for (Formula child : this.children) { child = child.simplify(evidence); // if the child is false, then the complete conjunction is false if (child instanceof TrueFalse) { if (!((TrueFalse) child).isTrue()) return TrueFalse.FALSE; else continue; } else // adds the child to simplified children if it isn't instance of TrueFalse simplifiedChildren.add(child); } // returns the simplified formula if vector isn't empty if (!simplifiedChildren.isEmpty()) return new Conjunction(simplifiedChildren); else // otherwise return true return TrueFalse.TRUE; } }