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; +}