diff --git a/src/main/java/blog/bn/DynamicCBN.java b/src/main/java/blog/bn/DynamicCBN.java
new file mode 100644
index 00000000..37791bf6
--- /dev/null
+++ b/src/main/java/blog/bn/DynamicCBN.java
@@ -0,0 +1,37 @@
+/**
+ *
+ */
+package blog.bn;
+
+import java.util.Iterator;
+
+import blog.common.HashDynamicGraph;
+import blog.sample.TraceParentRecEvalContext;
+import blog.world.PartialWorld;
+
+/**
+ * @author David T
+ * @since Oct 28, 2014
+ *
+ */
+public class DynamicCBN extends HashDynamicGraph implements CBN {
+ public DynamicCBN(CBN underlying, PartialWorld world) {
+ for (Iterator iter = underlying.nodes().iterator(); iter.hasNext();) {
+ BayesNetVar var = (BayesNetVar) iter.next();
+ Node curNode = new Node(var);
+ addNode(curNode);
+ for (Iterator iter2 = underlying.getParents(var).iterator(); iter2
+ .hasNext();) {
+ BayesNetVar par = (BayesNetVar) iter2.next();
+ Node parNode = new Node(par);
+ addEdge(new Edge(parNode, curNode));
+ }
+ TraceParentRecEvalContext context = new TraceParentRecEvalContext(world);
+ if (var instanceof VarWithDistrib) {
+ ((VarWithDistrib) var).getDistrib(context);
+ } else if (var instanceof DerivedVar) {
+ ((DerivedVar) var).getValue(context);
+ }
+ }
+ }
+}
diff --git a/src/main/java/blog/bn/DynamicCBNDiff.java b/src/main/java/blog/bn/DynamicCBNDiff.java
new file mode 100644
index 00000000..a44e9241
--- /dev/null
+++ b/src/main/java/blog/bn/DynamicCBNDiff.java
@@ -0,0 +1,21 @@
+/**
+ *
+ */
+package blog.bn;
+
+import blog.common.HashDynamicGraphDiff;
+
+/**
+ * @author David T
+ * @since Oct 28, 2014
+ *
+ */
+public class DynamicCBNDiff extends HashDynamicGraphDiff implements CBN {
+ public DynamicCBNDiff(DynamicCBN underlying) {
+ super(underlying);
+ }
+
+ public DynamicCBN getUnderlying() {
+ return (DynamicCBN) underlying;
+ }
+}
diff --git a/src/main/java/blog/common/DynamicGraph.java b/src/main/java/blog/common/DynamicGraph.java
new file mode 100644
index 00000000..8656cee6
--- /dev/null
+++ b/src/main/java/blog/common/DynamicGraph.java
@@ -0,0 +1,80 @@
+/**
+ *
+ */
+package blog.common;
+
+import java.util.Set;
+
+import blog.bn.BayesNetVar;
+
+/**
+ * @author David T
+ * @since Oct 16, 2014
+ *
+ */
+public interface DynamicGraph extends DGraph {
+
+ MultiMap getParentsMap();
+
+ MultiMap getChildrenMap();
+
+ MultiMap getEdgesAppearOnMap();
+
+ MultiMap getNodesRelatedToMap();
+
+ Set getBarrenNodeSet();
+
+ public class Edge {
+ public Edge(Node src, Node dst) {
+ this.src = src;
+ this.dst = dst;
+ }
+
+ public void setSrc(Node src) {
+ this.src = src;
+ }
+
+ public void setDst(Node dst) {
+ this.dst = dst;
+ }
+
+ public Node getSrc() {
+ return src;
+ }
+
+ public Node getDst() {
+ return dst;
+ }
+
+ private Node src, dst;
+ }
+
+ public class Node {
+ public Node(Object var) {
+ this.var = (BayesNetVar) var;
+ }
+
+ public void setNode(Object var) {
+ this.var = (BayesNetVar) var;
+ }
+
+ public BayesNetVar getNode() {
+ return var;
+ }
+
+ public void incOutDegree() {
+ outDegree++;
+ }
+
+ public void decOutDegree() {
+ outDegree--;
+ }
+
+ public boolean isBarren() {
+ return (outDegree == 0);
+ }
+
+ private BayesNetVar var;
+ private int outDegree = 0;
+ }
+}
diff --git a/src/main/java/blog/common/DynamicGraphDiff.java b/src/main/java/blog/common/DynamicGraphDiff.java
new file mode 100644
index 00000000..9f60b7c9
--- /dev/null
+++ b/src/main/java/blog/common/DynamicGraphDiff.java
@@ -0,0 +1,13 @@
+/**
+ *
+ */
+package blog.common;
+
+/**
+ * @author David T
+ * @since Sep 28, 2014
+ *
+ */
+public interface DynamicGraphDiff extends DynamicGraph {
+ DynamicGraph getUnderlying();
+}
diff --git a/src/main/java/blog/common/HashDynamicGraph.java b/src/main/java/blog/common/HashDynamicGraph.java
new file mode 100644
index 00000000..9a868b2a
--- /dev/null
+++ b/src/main/java/blog/common/HashDynamicGraph.java
@@ -0,0 +1,157 @@
+/**
+ *
+ */
+package blog.common;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author David T
+ * @since Oct 16, 2014
+ *
+ */
+public class HashDynamicGraph extends AbstractDGraph implements DynamicGraph,
+ Cloneable {
+
+ public HashDynamicGraph() {
+ nodeSet = new HashSet();
+ parents = new HashMultiMap();
+ children = new HashMultiMap();
+ edgesAppearOn = new HashMultiMap();
+ nodesRelatedTo = new HashMultiMap();
+ barrenNodeSet = new HashSet();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see blog.common.DGraph#nodes()
+ */
+ @Override
+ public Set nodes() {
+ return Collections.unmodifiableSet(nodeSet);
+ }
+
+ public MultiMap getParentsMap() {
+ return parents;
+ }
+
+ public MultiMap getChildrenMap() {
+ return children;
+ }
+
+ public MultiMap getEdgesAppearOnMap() {
+ return edgesAppearOn;
+ }
+
+ public MultiMap getNodesRelatedToMap() {
+ return nodesRelatedTo;
+ }
+
+ public boolean addNode(Node v) {
+ return nodeSet.add(v);
+ }
+
+ public boolean removeNode(Node v) {
+ if (nodeSet.contains(v)) {
+ for (Iterator iter = ((Set) parents.get(v)).iterator(); iter.hasNext();) {
+ Node curNode = (Node) iter.next();
+ ((Set) children.get(curNode)).remove(v);
+ }
+ for (Iterator iter = ((Set) children.get(v)).iterator(); iter.hasNext();) {
+ Node curNode = (Node) iter.next();
+ ((Set) parents.get(curNode)).remove(v);
+ }
+ parents.remove(v);
+ children.remove(v);
+ if (edgesAppearOn.containsKey(v)) {
+ for (Iterator iter = ((Set) edgesAppearOn.get(v)).iterator(); iter
+ .hasNext();) {
+ Edge curEdge = (Edge) iter.next();
+ ((Set) nodesRelatedTo.get(curEdge)).remove(v);
+ }
+ edgesAppearOn.remove(v);
+ }
+ }
+ return nodeSet.remove(v);
+ }
+
+ public boolean addEdge(Edge e) {
+ if (nodeSet.contains(e.getSrc()) && nodeSet.contains(e.getDst())
+ && !((Set) parents.get(e.getDst())).contains(e.getSrc())) {
+ ((Set) parents.get(e.getDst())).add(e.getSrc());
+ ((Set) children.get(e.getSrc())).add(e.getDst());
+ e.getSrc().incOutDegree();
+ if (!e.getSrc().isBarren()) {
+ barrenNodeSet.remove(e.getSrc());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public boolean removeEdge(Edge e) {
+ if (nodeSet.contains(e.getSrc()) && nodeSet.contains(e.getDst())
+ && ((Set) children.get(e.getSrc())).contains(e.getDst())) {
+ ((Set) parents.get(e.getDst())).remove(e.getSrc());
+ ((Set) children.get(e.getSrc())).remove(e.getDst());
+ e.getSrc().decOutDegree();
+ if (e.getSrc().isBarren()) {
+ barrenNodeSet.add(e.getSrc());
+ }
+ if (nodesRelatedTo.containsKey(e)) {
+ for (Iterator iter = ((Set) nodesRelatedTo.get(e)).iterator(); iter
+ .hasNext();) {
+ Node curNode = (Node) iter.next();
+ ((Set) edgesAppearOn.get(curNode)).remove(e);
+ }
+ nodesRelatedTo.remove(e);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public boolean addLabel(Edge e, Node labelNode) {
+ if (!((Set) edgesAppearOn.get(labelNode)).contains(e)) {
+ ((Set) edgesAppearOn.get(labelNode)).add(e);
+ ((Set) nodesRelatedTo.get(e)).add(labelNode);
+ return true;
+ }
+ return false;
+ }
+
+ public Set getBarrenNodeSet() {
+ return barrenNodeSet;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see blog.common.DGraph#getParents(java.lang.Object)
+ */
+ @Override
+ public Set getParents(Object v) {
+ return Collections.unmodifiableSet((Set) parents.get(v));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see blog.common.DGraph#getChildren(java.lang.Object)
+ */
+ @Override
+ public Set getChildren(Object v) {
+ return Collections.unmodifiableSet((Set) children.get(v));
+ }
+
+ protected Set nodeSet;
+ protected MultiMap parents;
+ protected MultiMap children;
+ protected MultiMap edgesAppearOn;
+ protected MultiMap nodesRelatedTo;
+ protected Set barrenNodeSet;
+}
diff --git a/src/main/java/blog/common/HashDynamicGraphDiff.java b/src/main/java/blog/common/HashDynamicGraphDiff.java
new file mode 100644
index 00000000..690c65de
--- /dev/null
+++ b/src/main/java/blog/common/HashDynamicGraphDiff.java
@@ -0,0 +1,34 @@
+/**
+ *
+ */
+package blog.common;
+
+/**
+ * @author David T
+ * @since Sep 28, 2014
+ *
+ */
+public class HashDynamicGraphDiff extends HashDynamicGraph implements
+ DynamicGraphDiff, Cloneable {
+
+ public HashDynamicGraphDiff(DynamicGraph underlying) {
+ this.underlying = underlying;
+ this.nodeSet = new HashSetDiff(underlying.nodes());
+ this.parents = new HashMultiMapDiff(underlying.getParentsMap());
+ this.children = new HashMultiMapDiff(underlying.getChildrenMap());
+ this.edgesAppearOn = new HashMultiMapDiff(underlying.getEdgesAppearOnMap());
+ this.nodesRelatedTo = new HashMultiMapDiff(
+ underlying.getNodesRelatedToMap());
+ }
+
+ public DynamicGraph getUnderlying() {
+ return underlying;
+ }
+
+ protected DynamicGraph underlying;
+ protected SetDiff nodeSet;
+ protected MultiMapDiff parents;
+ protected MultiMapDiff children;
+ protected MultiMapDiff edgesAppearOn;
+ protected MultiMapDiff nodesRelatedTo;
+}
diff --git a/src/main/java/blog/model/FuncAppTerm.java b/src/main/java/blog/model/FuncAppTerm.java
index a0bddd31..f4d1ea3e 100644
--- a/src/main/java/blog/model/FuncAppTerm.java
+++ b/src/main/java/blog/model/FuncAppTerm.java
@@ -49,6 +49,7 @@
import blog.bn.DerivedVar;
import blog.bn.RandFuncAppVar;
import blog.sample.EvalContext;
+import blog.sample.TraceLabelEvalContext;
/**
* Represents a function invocation.
@@ -165,6 +166,7 @@ public Object evaluate(EvalContext context) {
// if (argValues == null) { // Not reusing anymore since this array was
// being used for being argument arrays for RandFuncAppVars and had to be
// cloned anyway.
+
Object[] oldArgValues = argValues;
argValues = new Object[args.length];
// }
@@ -182,8 +184,17 @@ public Object evaluate(EvalContext context) {
}
}
+ if (context instanceof TraceLabelEvalContext) {
+ ((TraceLabelEvalContext) context).addRelatedClause(this);
+ }
+ if (context instanceof TraceLabelEvalContext) {
+ ((TraceLabelEvalContext) context).setCurrentClause(this);
+ }
Object result = f.getValueInContext(argValues, context, false);
argValues = oldArgValues;
+ if (context instanceof TraceLabelEvalContext) {
+ ((TraceLabelEvalContext) context).removeRelatedClause(this);
+ }
return result;
}
diff --git a/src/main/java/blog/sample/ParentRecEvalContext.java b/src/main/java/blog/sample/ParentRecEvalContext.java
index fc2fdd21..f4285a1e 100644
--- a/src/main/java/blog/sample/ParentRecEvalContext.java
+++ b/src/main/java/blog/sample/ParentRecEvalContext.java
@@ -35,7 +35,9 @@
package blog.sample;
-import java.util.*;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
import blog.ObjectIdentifier;
import blog.bn.BasicVar;
@@ -53,80 +55,80 @@
* {@link #getOrComputeValue(BasicVar)} instead.
*/
public class ParentRecEvalContext extends DefaultEvalContext {
- /**
- * Creates a new ParentRecEvalContext using the given world.
- */
- public ParentRecEvalContext(PartialWorld world) {
- super(world);
- }
+ /**
+ * Creates a new ParentRecEvalContext using the given world.
+ */
+ public ParentRecEvalContext(PartialWorld world) {
+ super(world);
+ }
- /**
- * Creates a new ParentRecEvalContext using the given world. If the
- * errorIfUndet flag is true, the access methods on this instance
- * will print error messages and exit the program if the world is not complete
- * enough to determine the correct return value. Otherwise they will just
- * return null in such cases.
- */
- public ParentRecEvalContext(PartialWorld world, boolean errorIfUndet) {
- super(world, errorIfUndet);
- }
+ /**
+ * Creates a new ParentRecEvalContext using the given world. If the
+ * errorIfUndet flag is true, the access methods on this instance
+ * will print error messages and exit the program if the world is not complete
+ * enough to determine the correct return value. Otherwise they will just
+ * return null in such cases.
+ */
+ public ParentRecEvalContext(PartialWorld world, boolean errorIfUndet) {
+ super(world, errorIfUndet);
+ }
- final public Object getValue(BasicVar var) {
- Object value = getOrComputeValue(var);
- if (value == null) {
- latestUninstParent = var;
- var.ensureStable();
- handleMissingVar(var);
- } else {
- if (parents.add(var)) {
- var.ensureStable();
- }
- }
- return value;
- }
+ public Object getValue(BasicVar var) {
+ Object value = getOrComputeValue(var);
+ if (value == null) {
+ latestUninstParent = var;
+ var.ensureStable();
+ handleMissingVar(var);
+ } else {
+ if (parents.add(var)) {
+ var.ensureStable();
+ }
+ }
+ return value;
+ }
- protected Object getOrComputeValue(BasicVar var) {
- return world.getValue(var);
- }
+ protected Object getOrComputeValue(BasicVar var) {
+ return world.getValue(var);
+ }
- // Note that we don't have to override getSatisfiers, because the
- // DefaultEvalContext implementation of getSatisfiers calls getValue
- // on the number variable
+ // Note that we don't have to override getSatisfiers, because the
+ // DefaultEvalContext implementation of getSatisfiers calls getValue
+ // on the number variable
- public NumberVar getPOPAppSatisfied(Object obj) {
- if (obj instanceof NonGuaranteedObject) {
- return ((NonGuaranteedObject) obj).getNumberVar();
- }
+ public NumberVar getPOPAppSatisfied(Object obj) {
+ if (obj instanceof NonGuaranteedObject) {
+ return ((NonGuaranteedObject) obj).getNumberVar();
+ }
- if (obj instanceof ObjectIdentifier) {
- parents.add(new OriginVar((ObjectIdentifier) obj));
- return world.getPOPAppSatisfied(obj);
- }
+ if (obj instanceof ObjectIdentifier) {
+ parents.add(new OriginVar((ObjectIdentifier) obj));
+ return world.getPOPAppSatisfied(obj);
+ }
- // Must be guaranteed object, so not generated by any number var
- return null;
- }
+ // Must be guaranteed object, so not generated by any number var
+ return null;
+ }
- /**
- * Returns the set of basic random variables that are instantiated and whose
- * values have been used in calls to the access methods. This set is backed by
- * the ParentRecEvalContext and will change as more random variables are used.
- *
- * @return unmodifiable Set of BasicVar
- */
- public Set getParents() {
- return Collections.unmodifiableSet(parents);
- }
+ /**
+ * Returns the set of basic random variables that are instantiated and whose
+ * values have been used in calls to the access methods. This set is backed by
+ * the ParentRecEvalContext and will change as more random variables are used.
+ *
+ * @return unmodifiable Set of BasicVar
+ */
+ public Set getParents() {
+ return Collections.unmodifiableSet(parents);
+ }
- /**
- * Returns the variable whose value was most recently needed by an access
- * method, but which is not instantiated. This method returns null if no such
- * variable exists.
- */
- public BasicVar getLatestUninstParent() {
- return latestUninstParent;
- }
+ /**
+ * Returns the variable whose value was most recently needed by an access
+ * method, but which is not instantiated. This method returns null if no such
+ * variable exists.
+ */
+ public BasicVar getLatestUninstParent() {
+ return latestUninstParent;
+ }
- protected Set parents = new LinkedHashSet(); // of BasicVar
- protected BasicVar latestUninstParent = null;
+ protected Set parents = new LinkedHashSet(); // of BasicVar
+ protected BasicVar latestUninstParent = null;
}
diff --git a/src/main/java/blog/sample/TraceLabelEvalContext.java b/src/main/java/blog/sample/TraceLabelEvalContext.java
new file mode 100644
index 00000000..9deade20
--- /dev/null
+++ b/src/main/java/blog/sample/TraceLabelEvalContext.java
@@ -0,0 +1,212 @@
+/**
+ *
+ */
+package blog.sample;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import blog.ObjectIdentifier;
+import blog.bn.BasicVar;
+import blog.bn.BayesNetVar;
+import blog.bn.NumberVar;
+import blog.bn.OriginVar;
+import blog.bn.VarWithDistrib;
+import blog.common.HashMultiMap;
+import blog.common.MultiMap;
+import blog.distrib.CondProbDistrib;
+import blog.model.ArgSpec;
+import blog.model.DependencyModel;
+import blog.model.NonGuaranteedObject;
+import blog.world.PartialWorld;
+
+/**
+ * A Evaluation Context class that could store the trace of visited BasicVars
+ * (when you try to get the distributions or values for some Basic or Derived
+ * variables).
+ * This class could also store the case levels in order to get the CBN decision
+ * tree structure (useful for the Open Universe Gibbs Sampling).
+ *
+ * @author Da Tang
+ * @since Oct 27, 2014
+ */
+public class TraceLabelEvalContext extends TraceParentRecEvalContext {
+
+ public TraceLabelEvalContext(PartialWorld world) {
+ super(world);
+ }
+
+ protected TraceLabelEvalContext(
+ PartialWorld world,
+ LinkedHashMap respVarsAndContexts) {
+ super(world, respVarsAndContexts);
+ }
+
+ protected Object getOrComputeValue(BasicVar var) {
+ Object value = world.getValue(var);
+ if (value == null) {
+ numCalculateNewVars++;
+ if (var instanceof VarWithDistrib) {
+ value = instantiate((VarWithDistrib) var);
+ } else {
+ throw new IllegalArgumentException("Don't know how to instantiate: "
+ + var);
+ }
+ }
+ return value;
+ }
+
+ public Object getValue(BasicVar var) {
+ Object value = getOrComputeValue(var);
+ if (value == null) {
+ latestUninstParent = var;
+ var.ensureStable();
+ handleMissingVar(var);
+ } else {
+ if (parents.add(var)) {
+ var.ensureStable();
+ parentTrace.addLast(var);
+ caseLevelTrace.addLast(caseLevel);
+ addCurLabelToClauseMap(var);
+ if (currentClause != null) {
+ clauseToVarMap.put(currentClause, var);
+ }
+ }
+ }
+ dependentVar.add(var);
+ return value;
+ }
+
+ public NumberVar getPOPAppSatisfied(Object obj) {
+ if (obj instanceof NonGuaranteedObject) {
+ return ((NonGuaranteedObject) obj).getNumberVar();
+ }
+
+ if (obj instanceof ObjectIdentifier) {
+ parents.add(new OriginVar((ObjectIdentifier) obj));
+ parentTrace.addLast(new OriginVar((ObjectIdentifier) obj));
+ caseLevelTrace.addLast(caseLevelTrace);
+ addCurLabelToClauseMap(new OriginVar((ObjectIdentifier) obj));
+ if (currentClause != null) {
+ clauseToVarMap
+ .put(currentClause, new OriginVar((ObjectIdentifier) obj));
+ }
+ return world.getPOPAppSatisfied(obj);
+ }
+
+ // Must be guaranteed object, so not generated by any number var
+ return null;
+ }
+
+ protected Object instantiate(VarWithDistrib var) {
+ var.ensureStable();
+
+ /*
+ * if (Util.verbose()) { System.out.println("Need to instantiate: " + var);
+ * }
+ */
+
+ if (respVarsAndContexts.containsKey(var)) {
+ cycleError(var);
+ }
+
+ // Create a new "child" context and get the distribution for
+ // var in that context.
+ respVarsAndContexts.put(var, this);
+ TraceLabelEvalContext spawn = new TraceLabelEvalContext(world,
+ respVarsAndContexts);
+ spawn.afterSamplingListener = afterSamplingListener;
+ DependencyModel.Distrib distrib = var.getDistrib(spawn);
+ logProb += spawn.getLogProbability();
+ respVarsAndContexts.remove(var);
+ List parentTrace = spawn.getParentTrace(), caseLevelTrace = spawn
+ .getCaseLevelTrace();
+ for (int i = 0; i < parentTrace.size(); i++) {
+ this.parentTrace.addLast(parentTrace.get(i));
+ this.caseLevelTrace.addLast((Integer) caseLevelTrace.get(i)
+ + this.caseLevel);
+ }
+ this.caseLevel += spawn.getCaseLevel();
+ this.curRelatedClause = spawn.getCurRelatedClause();
+ this.labelToRelatedClauseMap = spawn.getLabelToRelatedClauseMap();
+ this.clauseToVarMap = spawn.getClauseToVarMap();
+
+ // Sample new value for var
+ CondProbDistrib cpd = distrib.getCPD();
+ cpd.setParams(distrib.getArgValues());
+ Object newValue = cpd.sampleVal();
+ double logProbForThisValue = cpd.getLogProb(newValue);
+ logProb += logProbForThisValue;
+
+ // Assert any identifiers that are used by var
+ Object[] args = var.args();
+ for (int i = 0; i < args.length; ++i) {
+ if (args[i] instanceof ObjectIdentifier) {
+ world.assertIdentifier((ObjectIdentifier) args[i]);
+ }
+ }
+ if (newValue instanceof ObjectIdentifier) {
+ world.assertIdentifier((ObjectIdentifier) newValue);
+ }
+
+ // Actually set value
+ world.setValue(var, newValue);
+
+ if (afterSamplingListener != null) {
+ afterSamplingListener.evaluate(var, newValue, logProbForThisValue);
+ }
+
+ if (staticAfterSamplingListener != null) {
+ staticAfterSamplingListener.evaluate(var, newValue, logProbForThisValue);
+ }
+
+ /*
+ * if (Util.verbose()) { System.out.println("Instantiated: " + var); }
+ */
+
+ return newValue;
+ }
+
+ public Object addRelatedClause(ArgSpec clause) {
+ return curRelatedClause.add(clause);
+ }
+
+ public Object removeRelatedClause(ArgSpec clause) {
+ return curRelatedClause.remove(clause);
+ }
+
+ public Object addClauseToVarRelation(ArgSpec clause, BayesNetVar var) {
+ return clauseToVarMap.put(clause, var);
+ }
+
+ public Object addCurLabelToClauseMap(BayesNetVar var) {
+ Set curClauseSet = new HashSet();
+ curClauseSet.addAll(curRelatedClause);
+ return labelToRelatedClauseMap.put(var, curClauseSet);
+ }
+
+ public Set getCurRelatedClause() {
+ return curRelatedClause;
+ }
+
+ public MultiMap getLabelToRelatedClauseMap() {
+ return labelToRelatedClauseMap;
+ }
+
+ public Map getClauseToVarMap() {
+ return clauseToVarMap;
+ }
+
+ public void setCurrentClause(ArgSpec clause) {
+ currentClause = clause;
+ }
+
+ protected Set curRelatedClause = new HashSet();
+ protected MultiMap labelToRelatedClauseMap = new HashMultiMap();
+ protected Map clauseToVarMap = new HashMap();
+ protected ArgSpec currentClause;
+}
diff --git a/src/main/java/blog/sample/TraceParentRecEvalContext.java b/src/main/java/blog/sample/TraceParentRecEvalContext.java
new file mode 100644
index 00000000..048b233b
--- /dev/null
+++ b/src/main/java/blog/sample/TraceParentRecEvalContext.java
@@ -0,0 +1,189 @@
+/**
+ *
+ */
+package blog.sample;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import blog.ObjectIdentifier;
+import blog.bn.BasicVar;
+import blog.bn.NumberVar;
+import blog.bn.OriginVar;
+import blog.bn.VarWithDistrib;
+import blog.common.HashMapWithPreimages;
+import blog.distrib.CondProbDistrib;
+import blog.model.DependencyModel;
+import blog.model.NonGuaranteedObject;
+import blog.world.PartialWorld;
+
+/**
+ * A Evaluation Context class that could store the trace of visited BasicVars
+ * (when you try to get the distributions or values for some Basic or Derived
+ * variables).
+ * This class could also store the case levels in order to get the CBN decision
+ * tree structure (useful for the Open Universe Gibbs Sampling).
+ *
+ * @author Da Tang
+ * @since August 21, 2014
+ */
+public class TraceParentRecEvalContext extends ClassicInstantiatingEvalContext {
+
+ public TraceParentRecEvalContext(PartialWorld world) {
+ super(world);
+ }
+
+ protected TraceParentRecEvalContext(
+ PartialWorld world,
+ LinkedHashMap respVarsAndContexts) {
+ super(world, respVarsAndContexts);
+ }
+
+ protected Object getOrComputeValue(BasicVar var) {
+ Object value = world.getValue(var);
+ if (value == null) {
+ numCalculateNewVars++;
+ if (var instanceof VarWithDistrib) {
+ value = instantiate((VarWithDistrib) var);
+ } else {
+ throw new IllegalArgumentException("Don't know how to instantiate: "
+ + var);
+ }
+ }
+ return value;
+ }
+
+ public Object getValue(BasicVar var) {
+ Object value = getOrComputeValue(var);
+ if (value == null) {
+ latestUninstParent = var;
+ var.ensureStable();
+ handleMissingVar(var);
+ } else {
+ if (parents.add(var)) {
+ var.ensureStable();
+ parentTrace.addLast(var);
+ caseLevelTrace.addLast(caseLevel);
+ }
+ }
+ dependentVar.add(var);
+ return value;
+ }
+
+ public NumberVar getPOPAppSatisfied(Object obj) {
+ if (obj instanceof NonGuaranteedObject) {
+ return ((NonGuaranteedObject) obj).getNumberVar();
+ }
+
+ if (obj instanceof ObjectIdentifier) {
+ parents.add(new OriginVar((ObjectIdentifier) obj));
+ parentTrace.addLast(new OriginVar((ObjectIdentifier) obj));
+ caseLevelTrace.addLast(caseLevelTrace);
+ return world.getPOPAppSatisfied(obj);
+ }
+
+ // Must be guaranteed object, so not generated by any number var
+ return null;
+ }
+
+ protected Object instantiate(VarWithDistrib var) {
+ var.ensureStable();
+
+ /*
+ * if (Util.verbose()) { System.out.println("Need to instantiate: " + var);
+ * }
+ */
+
+ if (respVarsAndContexts.containsKey(var)) {
+ cycleError(var);
+ }
+
+ // Create a new "child" context and get the distribution for
+ // var in that context.
+ respVarsAndContexts.put(var, this);
+ TraceParentRecEvalContext spawn = new TraceParentRecEvalContext(world,
+ respVarsAndContexts);
+ spawn.afterSamplingListener = afterSamplingListener;
+ DependencyModel.Distrib distrib = var.getDistrib(spawn);
+ logProb += spawn.getLogProbability();
+ respVarsAndContexts.remove(var);
+ List parentTrace = spawn.getParentTrace(), caseLevelTrace = spawn
+ .getCaseLevelTrace();
+ for (int i = 0; i < parentTrace.size(); i++) {
+ this.parentTrace.addLast(parentTrace.get(i));
+ this.caseLevelTrace.addLast((Integer) caseLevelTrace.get(i)
+ + this.caseLevel);
+ }
+ this.caseLevel += spawn.getCaseLevel();
+
+ // Sample new value for var
+ CondProbDistrib cpd = distrib.getCPD();
+ cpd.setParams(distrib.getArgValues());
+ Object newValue = cpd.sampleVal();
+ double logProbForThisValue = cpd.getLogProb(newValue);
+ logProb += logProbForThisValue;
+
+ // Assert any identifiers that are used by var
+ Object[] args = var.args();
+ for (int i = 0; i < args.length; ++i) {
+ if (args[i] instanceof ObjectIdentifier) {
+ world.assertIdentifier((ObjectIdentifier) args[i]);
+ }
+ }
+ if (newValue instanceof ObjectIdentifier) {
+ world.assertIdentifier((ObjectIdentifier) newValue);
+ }
+
+ // Actually set value
+ world.setValue(var, newValue);
+
+ if (afterSamplingListener != null) {
+ afterSamplingListener.evaluate(var, newValue, logProbForThisValue);
+ }
+
+ if (staticAfterSamplingListener != null) {
+ staticAfterSamplingListener.evaluate(var, newValue, logProbForThisValue);
+ }
+
+ /*
+ * if (Util.verbose()) { System.out.println("Instantiated: " + var); }
+ */
+
+ return newValue;
+ }
+
+ public List getParentTrace() {
+ return Collections.unmodifiableList(parentTrace);
+ }
+
+ public void increaseCaseLevel() {
+ caseLevel++;
+ }
+
+ public List getCaseLevelTrace() {
+ return Collections.unmodifiableList(caseLevelTrace);
+ }
+
+ public int getCaseLevel() {
+ return caseLevel;
+ }
+
+ public int getNumCalculateNewVars() {
+ return numCalculateNewVars;
+ }
+
+ public Set getDependentVar() {
+ return Collections.unmodifiableSet(dependentVar);
+ }
+
+ protected LinkedList parentTrace = new LinkedList();
+ protected LinkedList caseLevelTrace = new LinkedList();
+ protected int caseLevel = 0;
+ protected HashMapWithPreimages assignment;
+ protected int numCalculateNewVars = 0;
+ protected Set dependentVar = new HashSet();
+}
diff --git a/src/main/java/blog/world/DynamicPartialWorldDiff.java b/src/main/java/blog/world/DynamicPartialWorldDiff.java
new file mode 100644
index 00000000..2583ea46
--- /dev/null
+++ b/src/main/java/blog/world/DynamicPartialWorldDiff.java
@@ -0,0 +1,39 @@
+/**
+ *
+ */
+package blog.world;
+
+import blog.bn.DynamicCBN;
+import blog.bn.DynamicCBNDiff;
+
+/**
+ * @author David T
+ * @since Oct 28, 2014
+ *
+ */
+public class DynamicPartialWorldDiff extends PartialWorldDiff {
+ /**
+ * Construct a new DynamicPartialWordDiff instance taking the underlying
+ * PartialWorld as input. Construct a DynamicCBNDiff instance if the
+ * parameter underlying is an instance of PartialWorldDiff.
+ *
+ * @param underlying
+ */
+ public DynamicPartialWorldDiff(PartialWorld underlying) {
+ super(underlying);
+ cbn = new DynamicCBNDiff(new DynamicCBN(underlying.getCBN(), underlying));
+ }
+
+ /**
+ * This method is no longer used since we don't need to compute the core and
+ * hence only the first constructor is needed.
+ *
+ * @param underlying
+ * @param toCopy
+ */
+ public DynamicPartialWorldDiff(PartialWorld underlying, PartialWorld toCopy) {
+ super(underlying, toCopy);
+ }
+
+ private DynamicCBNDiff cbn;
+}