/*******************************************************************************
* 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.srl.directed.inference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import probcog.bayesnets.core.BeliefNetworkEx;
import probcog.bayesnets.inference.SATIS_BSampler;
import probcog.bayesnets.inference.Sampler;
import probcog.logic.GroundLiteral;
import probcog.logic.PossibleWorld;
import probcog.logic.WorldVariables;
import probcog.logic.sat.ClausalKB;
import probcog.logic.sat.Clause;
import probcog.logic.sat.SampleSAT;
import probcog.srl.AbstractVariable;
import probcog.srl.directed.bln.GroundBLN;
import probcog.srl.directed.bln.coupling.VariableLogicCoupling;
import edu.ksu.cis.bnj.ver3.core.BeliefNode;
/**
* SAT-IS: satisfiability-based importance sampling for inference in mixed networks with
* probabilistic and deterministic constraints.
*
* @author Dominik Jain
*/
public class SATIS extends BNSampler {
GroundBLN gbln;
/**
* the SAT sampler that is used to sample the sub-state that is determined by the hard logical constraints
*/
SampleSAT ss;
/**
* the set of nodes whose values are determined by the SAT sampler (because they are part of a hard logical constraint)
*/
HashSet<BeliefNode> determinedVars;
boolean unitPropagation = false;
public SATIS(GroundBLN bln) throws Exception {
super(bln, SATIS_BSampler.class);
gbln = bln;
this.paramHandler.add("unitPropagation", "setUnitPropagation");
// create SAT sampler
PossibleWorld state = new PossibleWorld(gbln.getWorldVars());
ss = new SampleSAT(state, gbln.getWorldVars(), gbln.getDatabase().getEntries());
//ss = new SampleSATPriors(state, gbln.getWorldVars(), gbln.getDatabase().getEntries(), gbln.getGroundNetwork());
paramHandler.addSubhandler(ss.getParameterHandler());
}
public void setUnitPropagation(boolean enabled) {
unitPropagation = enabled;
}
protected void initSATSampler() throws Exception {
System.out.println("initializing SAT sampler...");
if(unitPropagation) ss.enableUnitPropagation();
this.ss.setDebugMode(debug);
ClausalKB ckb = getClausalKB();
ss.initConstraints(ckb);
// get the set of variables that is determined by the sat sampler
determinedVars = new HashSet<BeliefNode>();
for(Clause c : ckb) {
for(GroundLiteral lit : c.lits) {
BeliefNode var = gbln.getVariable(lit.gndAtom);
if(var == null)
throw new Exception("Could not find node corresponding to ground atom '" + lit.gndAtom.toString() + "' with index " + lit.gndAtom.index + "; set of mapped ground atoms is " + gbln.getCoupling().getCoupledGroundAtoms());
determinedVars.add(var);
}
}
}
protected ClausalKB getClausalKB() throws Exception {
return new ClausalKB(gbln.getKB());
}
@Override
protected Sampler getSampler() throws Exception {
initSATSampler();
return new SATIS_BSampler(gbln.getGroundNetwork(), ss, gbln.getCoupling(), determinedVars);
}
/**
* SampleSAT samples uniformly from the set of solutions.
* If there is a large number of solutions and many of them are improbable, then
* the sampled distribution may be dominated by a few high-probability worlds that
* were sampled. To prevent this, we use the prior to initialize random variables,
* thus introducing a slight bias towards worlds with higher probability.
* @author Dominik Jain
*/
protected class SampleSATPriors extends SampleSAT {
BeliefNetworkEx bn;
HashMap<BeliefNode, double[]> priors = null;
Random generator;
public SampleSATPriors(PossibleWorld state, WorldVariables vars, Iterable<? extends AbstractVariable<?>> db, BeliefNetworkEx bn) throws Exception {
super(state, vars, db);
this.bn = bn;
generator = new Random();
}
protected void setRandomState() {
if(priors == null)
priors = bn.computePriors(evidenceDomainIndices);
VariableLogicCoupling coupling = gbln.getCoupling();
for(BeliefNode node : bn.bn.getNodes()) {
if(!coupling.hasCoupling(node))
continue;
int domIdx = Sampler.sample(priors.get(node), generator);
coupling.setVariableValue(node, domIdx, this.state);
}
}
}
}