From f6091b071603a03b1a795f01a9e6ba299907d950 Mon Sep 17 00:00:00 2001 From: td11 Date: Sat, 18 Oct 2014 11:19:08 +0800 Subject: [PATCH 1/5] GraphDiff basics. --- src/main/java/blog/common/DynamicGraph.java | 80 ++++++++++ .../java/blog/common/DynamicGraphDiff.java | 13 ++ .../java/blog/common/HashDynamicGraph.java | 148 ++++++++++++++++++ .../blog/common/HashDynamicGraphDiff.java | 36 +++++ 4 files changed, 277 insertions(+) create mode 100644 src/main/java/blog/common/DynamicGraph.java create mode 100644 src/main/java/blog/common/DynamicGraphDiff.java create mode 100644 src/main/java/blog/common/HashDynamicGraph.java create mode 100644 src/main/java/blog/common/HashDynamicGraphDiff.java 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..55f1e5a6 --- /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 { + +} diff --git a/src/main/java/blog/common/HashDynamicGraph.java b/src/main/java/blog/common/HashDynamicGraph.java new file mode 100644 index 00000000..29789c0c --- /dev/null +++ b/src/main/java/blog/common/HashDynamicGraph.java @@ -0,0 +1,148 @@ +/** + * + */ +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 { + + /* + * (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 = new HashSet(); + protected MultiMap parents = new HashMultiMap(); + protected MultiMap children = new HashMultiMap(); + protected MultiMap edgesAppearOn = new HashMultiMap(); + protected MultiMap nodesRelatedTo = new HashMultiMap(); + protected Set barrenNodeSet = new HashSet(); +} diff --git a/src/main/java/blog/common/HashDynamicGraphDiff.java b/src/main/java/blog/common/HashDynamicGraphDiff.java new file mode 100644 index 00000000..7262940d --- /dev/null +++ b/src/main/java/blog/common/HashDynamicGraphDiff.java @@ -0,0 +1,36 @@ +/** + * + */ +package blog.common; + +import blog.world.PartialWorld; + +/** + * @author David T + * @since Sep 28, 2014 + * + */ +public class HashDynamicGraphDiff extends HashDynamicGraph implements + DynamicGraphDiff, Cloneable { + + public HashDynamicGraphDiff(PartialWorld world) { + + } + + 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()); + } + + protected DynamicGraph underlying; + protected SetDiff nodeSet; + protected MultiMapDiff parents; + protected MultiMapDiff children; + protected MultiMapDiff edgesAppearOn; + protected MultiMapDiff nodesRelatedTo; +} From 637d2162028d4dd3e113ce4302ac1959b7263ac0 Mon Sep 17 00:00:00 2001 From: td11 Date: Tue, 28 Oct 2014 14:36:40 +0800 Subject: [PATCH 2/5] Use trace to solve the label problem. --- src/main/java/blog/bn/DynamicCBN.java | 17 ++ src/main/java/blog/bn/DynamicCBNDiff.java | 17 ++ .../java/blog/common/HashDynamicGraph.java | 21 +- .../blog/common/HashDynamicGraphDiff.java | 5 - src/main/java/blog/model/FuncAppTerm.java | 10 + .../blog/sample/ParentRecEvalContext.java | 136 +++++------ .../blog/sample/TraceLabelEvalContext.java | 212 ++++++++++++++++++ .../sample/TraceParentRecEvalContext.java | 189 ++++++++++++++++ .../blog/world/DynamicPartialWorldDiff.java | 19 ++ 9 files changed, 548 insertions(+), 78 deletions(-) create mode 100644 src/main/java/blog/bn/DynamicCBN.java create mode 100644 src/main/java/blog/bn/DynamicCBNDiff.java create mode 100644 src/main/java/blog/sample/TraceLabelEvalContext.java create mode 100644 src/main/java/blog/sample/TraceParentRecEvalContext.java create mode 100644 src/main/java/blog/world/DynamicPartialWorldDiff.java diff --git a/src/main/java/blog/bn/DynamicCBN.java b/src/main/java/blog/bn/DynamicCBN.java new file mode 100644 index 00000000..a629668e --- /dev/null +++ b/src/main/java/blog/bn/DynamicCBN.java @@ -0,0 +1,17 @@ +/** + * + */ +package blog.bn; + +import blog.common.HashDynamicGraph; + +/** + * @author David T + * @since Oct 28, 2014 + * + */ +public class DynamicCBN extends HashDynamicGraph implements CBN { + public DynamicCBN() { + super(); + } +} diff --git a/src/main/java/blog/bn/DynamicCBNDiff.java b/src/main/java/blog/bn/DynamicCBNDiff.java new file mode 100644 index 00000000..aff4f995 --- /dev/null +++ b/src/main/java/blog/bn/DynamicCBNDiff.java @@ -0,0 +1,17 @@ +/** + * + */ +package blog.bn; + +import blog.common.HashDynamicGraphDiff; + +/** + * @author David T + * @since 2014年10月28日 + * + */ +public class DynamicCBNDiff extends HashDynamicGraphDiff implements CBN { + public DynamicCBNDiff(DynamicCBN underlying) { + super(underlying); + } +} diff --git a/src/main/java/blog/common/HashDynamicGraph.java b/src/main/java/blog/common/HashDynamicGraph.java index 29789c0c..9a868b2a 100644 --- a/src/main/java/blog/common/HashDynamicGraph.java +++ b/src/main/java/blog/common/HashDynamicGraph.java @@ -16,6 +16,15 @@ 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) * @@ -139,10 +148,10 @@ public Set getChildren(Object v) { return Collections.unmodifiableSet((Set) children.get(v)); } - protected Set nodeSet = new HashSet(); - protected MultiMap parents = new HashMultiMap(); - protected MultiMap children = new HashMultiMap(); - protected MultiMap edgesAppearOn = new HashMultiMap(); - protected MultiMap nodesRelatedTo = new HashMultiMap(); - protected Set barrenNodeSet = new HashSet(); + 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 index 7262940d..6969b362 100644 --- a/src/main/java/blog/common/HashDynamicGraphDiff.java +++ b/src/main/java/blog/common/HashDynamicGraphDiff.java @@ -3,7 +3,6 @@ */ package blog.common; -import blog.world.PartialWorld; /** * @author David T @@ -13,10 +12,6 @@ public class HashDynamicGraphDiff extends HashDynamicGraph implements DynamicGraphDiff, Cloneable { - public HashDynamicGraphDiff(PartialWorld world) { - - } - public HashDynamicGraphDiff(DynamicGraph underlying) { this.underlying = underlying; this.nodeSet = new HashSetDiff(underlying.nodes()); diff --git a/src/main/java/blog/model/FuncAppTerm.java b/src/main/java/blog/model/FuncAppTerm.java index a0bddd31..4489f546 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,9 @@ 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. + if (context instanceof TraceLabelEvalContext) { + ((TraceLabelEvalContext) context).addRelatedClause(this); + } Object[] oldArgValues = argValues; argValues = new Object[args.length]; // } @@ -182,8 +186,14 @@ public Object evaluate(EvalContext context) { } } + 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..1f749554 --- /dev/null +++ b/src/main/java/blog/world/DynamicPartialWorldDiff.java @@ -0,0 +1,19 @@ +/** + * + */ +package blog.world; + +/** + * @author David T + * @since Oct 28, 2014 + * + */ +public class DynamicPartialWorldDiff extends PartialWorldDiff { + public DynamicPartialWorldDiff(PartialWorld underlying) { + super(underlying); + } + + public DynamicPartialWorldDiff(PartialWorld underlying, PartialWorld toCopy) { + super(underlying, toCopy); + } +} From a2a284f2b333033ee0b351ae3d935f2cf6809399 Mon Sep 17 00:00:00 2001 From: td11 Date: Wed, 29 Oct 2014 16:21:59 +0800 Subject: [PATCH 3/5] basic parse for translating the origin CBN into new CBN. --- src/main/java/blog/bn/DynamicCBN.java | 16 ++++++++++++++-- src/main/java/blog/bn/DynamicCBNDiff.java | 2 +- .../java/blog/world/DynamicPartialWorldDiff.java | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/blog/bn/DynamicCBN.java b/src/main/java/blog/bn/DynamicCBN.java index a629668e..cfe7efeb 100644 --- a/src/main/java/blog/bn/DynamicCBN.java +++ b/src/main/java/blog/bn/DynamicCBN.java @@ -3,6 +3,8 @@ */ package blog.bn; +import java.util.Iterator; + import blog.common.HashDynamicGraph; /** @@ -11,7 +13,17 @@ * */ public class DynamicCBN extends HashDynamicGraph implements CBN { - public DynamicCBN() { - super(); + public DynamicCBN(CBN underlying) { + 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)); + } + } } } diff --git a/src/main/java/blog/bn/DynamicCBNDiff.java b/src/main/java/blog/bn/DynamicCBNDiff.java index aff4f995..9ad8f713 100644 --- a/src/main/java/blog/bn/DynamicCBNDiff.java +++ b/src/main/java/blog/bn/DynamicCBNDiff.java @@ -7,7 +7,7 @@ /** * @author David T - * @since 2014年10月28日 + * @since Oct 28, 2014 * */ public class DynamicCBNDiff extends HashDynamicGraphDiff implements CBN { diff --git a/src/main/java/blog/world/DynamicPartialWorldDiff.java b/src/main/java/blog/world/DynamicPartialWorldDiff.java index 1f749554..ff5d4b69 100644 --- a/src/main/java/blog/world/DynamicPartialWorldDiff.java +++ b/src/main/java/blog/world/DynamicPartialWorldDiff.java @@ -3,6 +3,7 @@ */ package blog.world; + /** * @author David T * @since Oct 28, 2014 From 54890e7fc2d3876a6c76db5085d15bcff60f8b2b Mon Sep 17 00:00:00 2001 From: Da Tang Date: Sat, 29 Nov 2014 12:42:28 +0800 Subject: [PATCH 4/5] small changes for CBN diff --- src/main/java/blog/bn/DynamicCBNDiff.java | 4 ++++ .../java/blog/common/DynamicGraphDiff.java | 2 +- .../blog/common/HashDynamicGraphDiff.java | 5 ++++- .../blog/world/DynamicPartialWorldDiff.java | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/blog/bn/DynamicCBNDiff.java b/src/main/java/blog/bn/DynamicCBNDiff.java index 9ad8f713..a44e9241 100644 --- a/src/main/java/blog/bn/DynamicCBNDiff.java +++ b/src/main/java/blog/bn/DynamicCBNDiff.java @@ -14,4 +14,8 @@ 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/DynamicGraphDiff.java b/src/main/java/blog/common/DynamicGraphDiff.java index 55f1e5a6..9f60b7c9 100644 --- a/src/main/java/blog/common/DynamicGraphDiff.java +++ b/src/main/java/blog/common/DynamicGraphDiff.java @@ -9,5 +9,5 @@ * */ public interface DynamicGraphDiff extends DynamicGraph { - + DynamicGraph getUnderlying(); } diff --git a/src/main/java/blog/common/HashDynamicGraphDiff.java b/src/main/java/blog/common/HashDynamicGraphDiff.java index 6969b362..690c65de 100644 --- a/src/main/java/blog/common/HashDynamicGraphDiff.java +++ b/src/main/java/blog/common/HashDynamicGraphDiff.java @@ -3,7 +3,6 @@ */ package blog.common; - /** * @author David T * @since Sep 28, 2014 @@ -22,6 +21,10 @@ public HashDynamicGraphDiff(DynamicGraph underlying) { underlying.getNodesRelatedToMap()); } + public DynamicGraph getUnderlying() { + return underlying; + } + protected DynamicGraph underlying; protected SetDiff nodeSet; protected MultiMapDiff parents; diff --git a/src/main/java/blog/world/DynamicPartialWorldDiff.java b/src/main/java/blog/world/DynamicPartialWorldDiff.java index ff5d4b69..89640ffc 100644 --- a/src/main/java/blog/world/DynamicPartialWorldDiff.java +++ b/src/main/java/blog/world/DynamicPartialWorldDiff.java @@ -3,6 +3,8 @@ */ package blog.world; +import blog.bn.DynamicCBN; +import blog.bn.DynamicCBNDiff; /** * @author David T @@ -10,11 +12,28 @@ * */ 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())); } + /** + * 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; } From f7448c66447f909905bfcb8720aaf3bd945ff130 Mon Sep 17 00:00:00 2001 From: datang1992 Date: Wed, 21 Jan 2015 15:10:15 +0800 Subject: [PATCH 5/5] First step for the ensure support. --- src/main/java/blog/bn/DynamicCBN.java | 10 +++++++++- src/main/java/blog/model/FuncAppTerm.java | 7 ++++--- src/main/java/blog/world/DynamicPartialWorldDiff.java | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/blog/bn/DynamicCBN.java b/src/main/java/blog/bn/DynamicCBN.java index cfe7efeb..37791bf6 100644 --- a/src/main/java/blog/bn/DynamicCBN.java +++ b/src/main/java/blog/bn/DynamicCBN.java @@ -6,6 +6,8 @@ import java.util.Iterator; import blog.common.HashDynamicGraph; +import blog.sample.TraceParentRecEvalContext; +import blog.world.PartialWorld; /** * @author David T @@ -13,7 +15,7 @@ * */ public class DynamicCBN extends HashDynamicGraph implements CBN { - public DynamicCBN(CBN underlying) { + public DynamicCBN(CBN underlying, PartialWorld world) { for (Iterator iter = underlying.nodes().iterator(); iter.hasNext();) { BayesNetVar var = (BayesNetVar) iter.next(); Node curNode = new Node(var); @@ -24,6 +26,12 @@ public DynamicCBN(CBN underlying) { 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/model/FuncAppTerm.java b/src/main/java/blog/model/FuncAppTerm.java index 4489f546..f4d1ea3e 100644 --- a/src/main/java/blog/model/FuncAppTerm.java +++ b/src/main/java/blog/model/FuncAppTerm.java @@ -166,9 +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. - if (context instanceof TraceLabelEvalContext) { - ((TraceLabelEvalContext) context).addRelatedClause(this); - } + Object[] oldArgValues = argValues; argValues = new Object[args.length]; // } @@ -186,6 +184,9 @@ public Object evaluate(EvalContext context) { } } + if (context instanceof TraceLabelEvalContext) { + ((TraceLabelEvalContext) context).addRelatedClause(this); + } if (context instanceof TraceLabelEvalContext) { ((TraceLabelEvalContext) context).setCurrentClause(this); } diff --git a/src/main/java/blog/world/DynamicPartialWorldDiff.java b/src/main/java/blog/world/DynamicPartialWorldDiff.java index 89640ffc..2583ea46 100644 --- a/src/main/java/blog/world/DynamicPartialWorldDiff.java +++ b/src/main/java/blog/world/DynamicPartialWorldDiff.java @@ -21,7 +21,7 @@ public class DynamicPartialWorldDiff extends PartialWorldDiff { */ public DynamicPartialWorldDiff(PartialWorld underlying) { super(underlying); - cbn = new DynamicCBNDiff(new DynamicCBN(underlying.getCBN())); + cbn = new DynamicCBNDiff(new DynamicCBN(underlying.getCBN(), underlying)); } /**