/*******************************************************************************
* Copyright (C) 2009-2012 Ralf Wernicke, 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.sat.weighted;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
import java.util.Map.Entry;
import probcog.logic.Conjunction;
import probcog.logic.Formula;
import probcog.logic.TrueFalse;
import probcog.logic.sat.Clause.TautologyException;
/**
* A knowledge base of weighted clauses that is built up from general weighted formulas (retaining a mapping from formulas to clauses and vice versa)
* @author Ralf Wernicke
* @author Dominik Jain
*/
public class WeightedClausalKB implements Iterable<WeightedClause> {
protected Vector<WeightedClause> clauses;
protected HashMap<WeightedClause, Formula> cl2Formula;
protected edu.tum.cs.util.datastruct.Map2List<WeightedFormula, WeightedClause> formula2clauses;
/**
* constructs a weighted clausal KB from a collection of weighted formulas
* @param kb some collection of weighted formulas
* @param requirePositiveWeights whether to negate formulas with negative weights to yield positive weights only
* @throws java.lang.Exception
*/
public WeightedClausalKB(Iterable<WeightedFormula> kb, boolean requirePositiveWeights) throws Exception {
this();
for(WeightedFormula wf : kb) {
addFormula(wf, requirePositiveWeights);
}
}
/**
* constructs an empty weighted clausal KB
*/
public WeightedClausalKB() {
clauses = new Vector<WeightedClause>();
cl2Formula = new HashMap<WeightedClause, Formula>();
formula2clauses = new edu.tum.cs.util.datastruct.Map2List<WeightedFormula, WeightedClause>();
}
/**
* adds an arbitrary formula to the knowledge base (converting it to CNF and splitting it into clauses)
* @param wf formula whose clauses to add (it is automatically converted to CNF and split into clauses; the association between the formula and its clauses is retained)
* @param makeWeightPositive whether to negate the formula if its weight is negative
* @throws java.lang.Exception
*/
public void addFormula(WeightedFormula wf, boolean makeWeightPositive) throws Exception {
if(makeWeightPositive && wf.weight < 0) {
wf.weight *= -1;
wf.formula = new probcog.logic.Negation(wf.formula);
}
// convert formula to CNF
Formula cnf = wf.formula.toCNF();
// add its clauses
if(cnf instanceof Conjunction) { // conjunction of clauses
Conjunction c = (Conjunction) cnf;
int numChildren = c.children.length;
for(Formula child : c.children) {
try {
addClause(wf, new WeightedClause(child, wf.weight / numChildren, wf.isHard));
}
catch(TautologyException e) {}
}
}
else if(!(cnf instanceof TrueFalse)) { // clause
try {
addClause(wf, new WeightedClause(cnf, wf.weight, wf.isHard));
}
catch(TautologyException e) {}
}
}
/**
* adds a weighted clause to this KB
* @param wf the weighted formula whose CNF the clause appears in
* @param wc the clause to add
*/
public void addClause(WeightedFormula wf, WeightedClause wc) {
cl2Formula.put(wc, wf.formula);
clauses.add(wc);
formula2clauses.add(wf, wc);
}
/**
* adds a weighted clause to the KB (where the weighted formula the clause originated from is the clause itself)
* @param wc the weighted clause to add
*/
public void addClause(WeightedClause wc) {
addClause(new WeightedFormula(wc, wc.weight, wc.isHard), wc);
}
/**
* Method returns the iterator of the weighted clauses in knowledge base.
* @return Iterator of weighted clauses
*/
public Iterator<WeightedClause> iterator() {
return clauses.iterator();
}
/**
* returns the number of weighted clauses in the knowledge base.
* @return size of the knowledge base (number of weighted clauses)
*/
public int size() {
return clauses.size();
}
/**
* prints all weighted clauses in the knowledge base to stdout
*/
public void print() {
int i = 0;
for (WeightedClause c : this)
System.out.printf("%4d %s\n", ++i, c.toString());
}
/**
* @return a mapping from weighted clauses to the original formulas they were part of.
*/
public HashMap<WeightedClause, Formula> getClause2Formula() {
return cl2Formula;
}
/**
* gets a set of entries with formulas and the clauses that the formulas are made up of when converted to CNF
* @return
*/
public Set<Entry<WeightedFormula,Vector<WeightedClause>>> getFormulasAndClauses() {
return formula2clauses.entrySet();
}
}