/******************************************************************************* * 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.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Vector; import probcog.srl.GenericDatabase; import edu.tum.cs.util.StringTool; /** * Represents a logical disjunction. * @author Dominik Jain */ public class Disjunction extends ComplexFormula { public Disjunction(Collection<Formula> children) { super(children); } public Disjunction(Formula... children) { super(children); } public String toString() { return "(" + StringTool.join(" v ", children) + ")"; } @Override public boolean isTrue(IPossibleWorld w) { for (Formula child : children) if (child.isTrue(w)) return true; return false; } @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(); HashSet<Formula> clause = new HashSet<Formula>(); HashSet<String> strClause = new HashSet<String>(); Vector<Conjunction> conjunctions = new Vector<Conjunction>(); // convert children to CNF and group by disjunction (flattened) and conjunction // make sure that the flattened disjunction contains no duplicates for (Formula child : children) { child = child.toCNF(); if (child instanceof Conjunction) { conjunctions.add((Conjunction) child); } else if (child instanceof Disjunction) { for (Formula c : ((Disjunction) child).children) if (!strClause.contains(child.toString())) { clause.add(c); strClause.add(c.toString()); } //clause.addAll(Arrays.asList(((Disjunction)child).children)); } else if (child instanceof TrueFalse) { if (((TrueFalse) child).isTrue()) return child; } else { // must be literal/atom if (!strClause.contains(child.toString())) { clause.add(child); strClause.add(child.toString()); } } } if (conjunctions.isEmpty()) return clause.size() == 1 ? clause.iterator().next() : new Disjunction(clause); else { if(conjunctions.size() == 1 && clause.size() == 0) return conjunctions.get(0); // apply distributivity // use the first conjunction to distribute: (C_1 ^ ... ^ C_n) v RD = (C_1 v RD) ^ ... ^ (C_n v RD) Iterator<Conjunction> i = conjunctions.iterator(); Formula[] conjuncts = i.next().children; while (i.hasNext()) clause.add(i.next()); //Formula RD = new Disjunction(clause); Vector<Formula> elems = new Vector<Formula>(); for (Formula Ci : conjuncts) { @SuppressWarnings("unchecked") HashSet<Formula> newClause = (HashSet<Formula>)clause.clone(); newClause.add(Ci); elems.add(new Disjunction(newClause)); } return new Conjunction(elems).toCNF(); } /* } finally { Negation.cnfDepth--; } */ } @Override public Formula toNNF() { Vector<Formula> disjuncts = new Vector<Formula>(); for(Formula child : this.children) { Formula newChild = child.toNNF(); if(newChild instanceof Disjunction) { // flatten nested disjunction for(Formula nestedChild : ((Disjunction)newChild).children) disjuncts.add(nestedChild); } else disjuncts.add(newChild); } return new Disjunction(disjuncts); } /** * 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 true, then complete disjunction is true if (child instanceof TrueFalse) { if (((TrueFalse) child).isTrue()) return TrueFalse.TRUE; else continue; } else // adds the child to simplified children if it isn't instance of TrueFalse simplifiedChildren.add(child); } // return the simplified formula if the vector isn't empty if (!simplifiedChildren.isEmpty()) return new Disjunction(simplifiedChildren); else // otherwise return false return TrueFalse.FALSE; } }