|
WorldInProgress.java
|
/* * Copyright (c) 2005, 2006, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * * Neither the name of the University of California, Berkeley nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package blog; import java.util.*; import common.Util; import common.ExtensibleLinkedList; import common.AddedTupleIterator; import common.DGraph;
|
PartialWorld implementation that maintains a list of uninstantiated
VarWithDistrib objects, and allows variables to be instantiated using a
special method of an iterator over this list. This is useful for
rejection sampling.
The list of uninstantiated basic variables only includes variables whose arguments necessarily exist in this partial world. Thus, as more number variables are instantiated and more objects necessarily exist, more variables will be added to the list. The list is not represented explicitly -- if integers or natural numbers serve as variable arguments, then the full list is infinite. Thus, the WorldInProgress class does not allow random access to the list. It only allows iteration, and additional variables are added lazily to the explicit list as needed. The hypothetical "full" list is ordered in such a way that every one of its elements has a finite index. This is achieved by interleaving variables that have integer arguments with variables that have non-guaranteed arguments. |
public class WorldInProgress extends DefaultPartialWorld {
Creates a new WorldInProgress with no instantiated random variables.
numbers) to allow as arguments of RVs that are
included in the uninstantiated RV list. To allow
unbounded integers, pass -1 for this parameter.
as arguments of RVs that are included in the
uninstantiated RVs list. Objects generated by the
empty tuple have depth 0; other non-guaranteed
objects have depth one greater than the maximum
depth of their generating objects. To allow
unbounded depths, pass -1 for this parameter.
|
public WorldInProgress(Model model, Evidence evidence,
int intBound, int depthBound) {
super(Collections.EMPTY_SET);
this.model = model;
this.evidence = evidence;
this.intBound = intBound;
this.depthBound = depthBound;
// Determine what types serve as arguments to basic RVs. Initialize
// their object lists to be empty. As we're doing this, add any
// random variables with empty arg lists to the list of uninstantiated
// RVs.
for (Iterator fIter = model.getFunctions().iterator();
fIter.hasNext(); ) {
Function f = (Function) fIter.next();
if (f instanceof RandomFunction) {
for (int i = 0; i < f.getArgTypes().length; ++i) {
objectsByType.put(f.getArgTypes()[i], new ArrayList());
}
if (f.getArgTypes().length == 0) {
uninstVars.add(new RandFuncAppVar((RandomFunction) f,
Collections.EMPTY_LIST));
}
}
}
for (Iterator typeIter = model.getTypes().iterator();
typeIter.hasNext(); ) {
Type generatedType = (Type) typeIter.next();
for (Iterator popIter = generatedType.getPOPs().iterator();
popIter.hasNext(); ) {
POP pop = (POP) popIter.next();
for (int i = 0; i < pop.getArgTypes().length; ++i) {
objectsByType.put(pop.getArgTypes()[i], new ArrayList());
}
if (pop.getArgTypes().length == 0) {
uninstVars.add(new NumberVar(pop, Collections.EMPTY_LIST));
}
}
}
for (Iterator skolemIter = evidence.getSkolemConstants().iterator();
skolemIter.hasNext(); ) {
SkolemConstant c = (SkolemConstant) skolemIter.next();
uninstVars.add(new RandFuncAppVar(c, Collections.EMPTY_LIST));
}
// Create initial object lists for those types. While doing so,
// add uninstantiated variables that have these objects as arguments.
for (Iterator typeIter = objectsByType.keySet().iterator();
typeIter.hasNext(); ) {
Type type = (Type) typeIter.next();
if (type.isSubtypeOf(BuiltInTypes.INTEGER)) {
addObjects(type, Collections.singleton(new Integer(0)));
intsAreArgs = true;
} else if (type == BuiltInTypes.BOOLEAN) {
addObjects(type, type.getGuaranteedObjects());
} else if (type.isBuiltIn()) {
Util.fatalError("Illegal argument type for random function: "
+ type, false);
} else {
// user-defined type
addObjects(type, type.getGuaranteedObjects());
}
}
}
public void setValue(VarWithDistrib var, Object value) {
super.setValue(var, value);
if (var instanceof NumberVar) {
int varDepth = getVarDepth(var);
if ((depthBound < 0) || (varDepth < depthBound)) {
if (getVarDepth(var) >= maxInt) {
// We're creating non-guaranteed objects of greater depth,
// so increase maxInt as well
increaseMaxInt();
}
// Add objects generated by this number variable
NumberVar nv = (NumberVar) var;
addObjects(nv.pop().type(), getSatisfiers(nv));
}
}
}
| Returns an iterator over the basic random variables whose arguments necessarily exist in this world, but which are not yet instantiated. |
public UninstVarIterator uninstVarIterator() {
return new UninstVarIterator();
}
| Returns true if every basic random variable whose arguments necessarily exist in this world is instantiated. |
public boolean isComplete() {
if (uninstVars.isEmpty()) {
increaseMaxInt();
}
return uninstVars.isEmpty(); // no uninstantiated vars -> complete
}
private int getVarDepth(VarWithDistrib var) {
int maxArgDepth = 0;
for (int i = 0; i < var.args().length; ++i) {
Object arg = var.args()[i];
if (arg instanceof NonGuaranteedObject) {
int d = ((NonGuaranteedObject) arg).getDepth();
maxArgDepth = Math.max(d, maxArgDepth);
}
}
return maxArgDepth;
}
|
Increases the maximum magnitude of integers (and natural numbers)
in the object lists by 1. Adds any basic RVs that use the newly
added integers to the uninstantiated variables list.
Note that no variables will be added if integers don't serve as arguments to basic RVs in this model, or if they only occur in argument lists along with types that happen to have an empty extension in this world. In either case, if increasing maxInt by 1 doesn't yield new variables, then further increases won't do anything either. So there's no point in calling this method in a loop. |
private void increaseMaxInt() {
if (intsAreArgs
&& ((intBound < 0) || (maxInt < intBound))) {
++maxInt;
if (objectsByType.containsKey(BuiltInTypes.NATURAL_NUM)) {
addObjects(BuiltInTypes.NATURAL_NUM,
Collections.singleton(new Integer(maxInt)));
}
if (objectsByType.containsKey(BuiltInTypes.INTEGER)) {
List newInts = new ArrayList();
newInts.add(new Integer(maxInt));
newInts.add(new Integer(-maxInt));
addObjects(BuiltInTypes.INTEGER, newInts);
}
}
}
private void addObjects(Type newObjType, Collection newObjs) {
if (newObjs.isEmpty()) {
return;
}
List objs = (List) objectsByType.get(newObjType);
if (objs != null) { // if type serves as an argument to some basic RV
// Add function app vars with these objects as argument
for (Iterator fIter = model.getFunctions().iterator();
fIter.hasNext(); ) {
Function f = (Function) fIter.next();
if (f instanceof RandomFunction) {
RandomFunction rf = (RandomFunction) f;
if (Arrays.asList(f.getArgTypes()).contains(newObjType)) {
addFuncAppVars(rf, newObjType, newObjs);
}
}
}
// Add number vars with these object as arguments
for (Iterator typeIter = model.getTypes().iterator();
typeIter.hasNext(); ) {
Type generatedType = (Type) typeIter.next();
for (Iterator popIter = generatedType.getPOPs().iterator();
popIter.hasNext(); ) {
POP pop = (POP) popIter.next();
if (Arrays.asList(pop.getArgTypes())
.contains(newObjType)) {
addNumberVars(pop, newObjType, newObjs);
}
}
}
// Don't need to worry about skolem constant vars because
// they don't have arguments
objs.addAll(newObjs);
}
}
private void addFuncAppVars(RandomFunction f, Type newObjType,
Collection newObjs) {
for (Iterator iter = getAddedTupleIterator
(Arrays.asList(f.getArgTypes()), newObjType, newObjs);
iter.hasNext(); ) {
List args = (List) iter.next();
VarWithDistrib v = new RandFuncAppVar(f, args);
if (Util.verbose()) {
System.out.println("Adding uninstantiated var: " + v);
}
uninstVars.add(v);
}
}
private void addNumberVars(POP pop, Type newObjType,
Collection newObjs) {
for (Iterator iter = getAddedTupleIterator
(Arrays.asList(pop.getArgTypes()), newObjType, newObjs);
iter.hasNext(); ) {
List genObjs = (List) iter.next();
VarWithDistrib v = new NumberVar(pop, genObjs);
if (Util.verbose()) {
System.out.println("Adding uninstantiated var: " + v);
}
uninstVars.add(v);
}
}
private Iterator getAddedTupleIterator(List argTypes, Type newObjType,
Collection newObjs) {
List orig = new ArrayList();
List added = new ArrayList();
for (Iterator iter = argTypes.iterator(); iter.hasNext(); ) {
Type type = (Type) iter.next();
orig.add(objectsByType.get(type));
if (type == newObjType) {
added.add(newObjs);
} else {
added.add(Collections.EMPTY_SET);
}
}
return new AddedTupleIterator(orig, added);
}
Inner class for iterating over the list of uninstantiated variables.
It is like an ordinary iterator, but has an extra method
setValue for instantiating the variable returned by
the last call to next.
|
public class UninstVarIterator implements Iterator {
public boolean hasNext() {
ensureListExtended();
return listIter.hasNext();
}
| Always returns an object of class VarWithDistrib. |
public Object next() {
ensureListExtended();
lastVar = (VarWithDistrib) listIter.next();
return lastVar;
}
The remove method is not supported, because the
only way to remove a variable from the list of uninstantiated
variables is to instantiate it.
|
public void remove() {
throw new UnsupportedOperationException
("Can't remove objects from UninstVarIterator.");
}
Instantiates the last variable returned by next to
the given value. The variable must be supported by this
partial world, or a fatal error will occur.
been called, or if
setValue has already
been called since the last call
to next
|
public void setValue(Object value) {
if (lastVar == null) {
throw new IllegalStateException
("No variable to instantiate.");
}
WorldInProgress.this.setValue(lastVar, value);
listIter.remove(); // no longer uninstantiated
lastVar = null;
}
private void ensureListExtended() {
if (!listIter.hasNext()) {
// Try extending the list of uninstantiated vars by
// increasing maxInt.
increaseMaxInt();
}
}
private Iterator listIter = uninstVars.iterator();
VarWithDistrib lastVar = null;
}
private Model model;
private Evidence evidence;
private Collection uninstVars = new ExtensibleLinkedList();
private Map objectsByType = new HashMap(); // from Type to List
private boolean intsAreArgs = false;
private int maxInt = 0; // max int added to object list so far
private int intBound;
private int depthBound;
}
This file was generated on Tue Jun 08 17:53:36 PDT 2010 from file WorldInProgress.java
by the ilog.language.tools.Hilite Java tool written by Hassan Aït-Kaci