Main.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.io.*;
import java.util.*;
import java.lang.reflect.*;
import java_cup.runtime.Symbol;
import common.Util;
import common.Timer;
import common.cmdline.*;



Main program for the BLOG (Bayesian Logic) inference engine. Usage:
java blog.Main file1 ... fileN
Each file contains a sequence of BLOG statements. These may be declarations (specifying the model itself), evidence statements, or queries. The convention is to use one file for the model (with the "mblog" suffix), one file for the evidence (with the "eblog" suffix), and one file for the queries (with the "qblog" suffix). The files are loaded in the order specified, so the first file must be a model file. Optional flags:
-r, --randomize
Initialize the random seed based on the clock time. If this flag is not given, the program uses a fixed random seed so its behavior is reproducible. Default: false
-e classname, --engine=classname
Use classname as the inference engine. Default: blog.SamplingEngine
-n num, --num_samples=num
Run the sampling engine for num samples. Default: 10000 samples.
-b num, --burn_in=num
Treat first num samples as burn-in period (don't use them to compute query results). Default: 0.
-s classname --sampler=classname
Use classname to generate each sample. Default: blog.LWSampler (a likelihood weighting sampler)
-p classname, --proposer=classname
Use classname as the proposal distribution for the Metropolis-Hastings sampler. Default: blog.GenericProposer (samples each var given its parents)
-t, num, --num_trials=num
Do num independent runs (trials) of the inference algorithm. Default: 1
--generate
Rather than answering queries, just sample possible worlds from the prior distribution defined by the model, and print them out. Default: false
-k package, --package package
Look in package (e.g., "blog.distrib") when resolving the names of CondProbDistrib and NonRandomFunction classes in the model file. This option can be included several times with different packages; the packages are searched in the order given. The last places searched are the top-level package ("") and finally the default package blog.distrib. Note that you still need to set the Java classpath so that it includes all these packages.
-v, --verbose
Print information about the world generated at each iteration. Off by default (for perfomance reasons, consider leaving this option off).
-g, --debug
Print model, evidence, and queries for debugging. Default: false
-w file-prefix, --write=file-prefix
Write sampling results to file specified by this argument. Use with the -i flag.
-i, --interval
To be used with the -w option, specify the interval at which output is written. Note that if -i and -n are the same, output is written only once, at the last iteration.
-h file-prefix, --histogram_output=file-prefix
Output the histogram of an ArgSpecQuery to a file. The results are taken after the final sample completes.
-P key=value
Include the entry key=value in the properties table that is passed to the inference engine. This feature can be used to set configuration parameters for various inference engines (and the components they use, such as samplers). See the individual inference classes for documentation. Note: The -P option cannot be used to specify values for properties for which there exist special-purpose options, such as --engine or --num_samples.
-x, --extend setup-extender[,key=value,...]
Extend the problem setup (model, evidence and queries) using an object of class setup-extender. This class must implement the SetupExtender interface. The class name can optionally be followed by a series of key=value pairs (each preceded by a comma) that will be passed to the setup extender's constructor in a properties table.


public class Main {
	
    public static void main(String[] args) {
	parseOptions (args);
	Util.setVerbose(verbose);
	Util.initRandom (randomize);
	BLOGParser.setPackagesToSearch(packages);
	
	List readersAndOrigins = makeReaders(filenames);
		
	setup(model, evidence, queries, readersAndOrigins, setupExtenders, 
	      Util.verbose(), true);

	System.out.println("............................................");
	if (generate) {
	    generateWorlds();
	} else {
	    // Run inference for the specified number of trials
	    InferenceEngine engine 
		= InferenceEngine.constructEngine(model, inferenceProps);
	    for(int i = 0; i < numStatSamples; i++){
		printTimes(System.out, "-", 80);
		System.out.println("Trial " + i + ": ");
		
		engine.setEvidence(evidence);
		engine.setQueries(queries);
		engine.answerQueries();
		
		// Print query results
		System.out.println("======== Query Results =========");
		for (Iterator iter = queries.iterator(); iter.hasNext(); ) {
		    Query q = (Query) iter.next();
		    q.printResults(System.out);
		    q.zeroOut();
		}
		
		System.out.println();
	    }
	    
	    if (numStatSamples > 1) {
		printTimes(System.out, "=", 80);
		System.out.println("Summary of statistics for all trials:");
		for (Iterator iter = queries.iterator(); iter.hasNext(); ) {
		    Query q = (Query) iter.next();
		    q.printVarianceResults(System.out);
		}
	    }
	}

	Timer.printAllTimers();
    }

    public static List makeReaders(Collection filenames) {
	List readersAndOrigins = new LinkedList();
	for(Iterator iter = filenames.iterator(); iter.hasNext(); ) {
		String filename = (String) iter.next();
		try {
			readersAndOrigins.add
			    (new Object[]{new FileReader(filename), filename});
		} catch(FileNotFoundException e) {
			System.err.println("File not found: " + filename);
			Util.fatalError(e);
		}
	}
	return readersAndOrigins;
    }

    private static boolean semanticsCorrect(Model model, Evidence evidence, 
					    List queries) {
	boolean correct = true;

	if (!model.checkTypesAndScope()) {
	    correct = false;
	}

	if (!evidence.checkTypesAndScope(model)) {
	    correct = false;
	}

	for (Iterator iter = queries.iterator(); iter.hasNext(); ) {
	    Query q = (Query) iter.next();
	    if (!q.checkTypesAndScope(model)) {
		correct = false;
	    }
	}

	if (!model.checkCompleteness()) {
	    correct = false;
	}

	return correct;
    }

    private static void generateWorlds() {
	RejectionSampler sampler = new RejectionSampler(model, inferenceProps);
	sampler.initializeCompleteSampling();

	System.out.println("Sampling " + numSamples + " worlds from prior...");
	System.out.println();
	for (int i = 0; i < numSamples; ++i) {
	    sampler.nextSample();
	    sampler.getLatestWorld().print(System.out);
	    System.out.println();
	}
    }

    private static void parseOptions (String[] args) {
	Map specialOptions = new HashMap(); // from String to Option

	common.cmdline.Parser.setProgramDesc
	    ("Bayesian Logic (BLOG) inference engine");
	common.cmdline.Parser.setUsageLine
	    ("Usage: runblog <file1> ... <fileN>");

	BooleanOption optRandomize 
	    = new BooleanOption("r", "randomize", false, 
				"Use clock time as random seed");

	StringOption optEngine
	    = new StringOption("e", "engine", "blog.SamplingEngine", 
			       "Use inference engine class <s>");
	specialOptions.put("engineClass", optEngine);

	IntOption optNumSamples
	    = new IntOption("n", "num_samples", 10000, 
			    "Run inference engine for <n> samples");
	specialOptions.put("numSamples", optNumSamples);

	IntOption optBurnIn
	    = new IntOption("b", "burn_in", 0, 
			    "Treat first <n> samples as burn-in");
	specialOptions.put("burnIn", optBurnIn);

	StringOption optSampler
	    = new StringOption("s", "sampler", "blog.LWSampler", 
			       "Use sampler class <s>");
	specialOptions.put("samplerClass", optSampler);
	
	StringOption optProposer
	    = new StringOption("p", "proposer", "blog.GenericProposer", 
			       "Use Metropolis-Hastings proposer class <s>");
	specialOptions.put("proposerClass", optProposer);

	IntOption optNumTrials
	    = new IntOption("t", "num_trials", 1, 
			    "Do <n> independent runs of inference");
	BooleanOption optGenerate
	    = new BooleanOption(null, "generate", false, 
				"Sample worlds from prior and print them");
	StringListOption optPackages
	    = new StringListOption("k", "package", 
				   "Parser looks for classes in package <s>");
	BooleanOption optVerbose
	    = new BooleanOption("v", "verbose", false, 
				"Print info about every world sampled");
	BooleanOption optDebug
	    = new BooleanOption("g", "debug", false, 
				"Print model, evidence, and queries");
	StringOption optWrite
	    = new StringOption("w", "write", null, 
			       "Write sampling results to file <s>");
	IntOption optInterval
	    = new IntOption("i", "interval", 0, 
			    "Write results after every <n> samples");
	StringOption optHist
	    = new StringOption("h", "histogram_output", null, 
			       "Write histogram output to file <s>");
	PropertiesOption optInferenceProps
	    = new PropertiesOption("P", null, null, 
				   "Set inference configuration properties");

	StringListOption optSetupExtenders
	    = new StringListOption("x", "extend", 
				   "Extend setup with object of class <s>");
	
	IntOption optNumMoves
	    = new IntOption("m", "num_moves", 1,
			    "Use <m> moves per rejuvenation step (PF only)");
	
	filenames = common.cmdline.Parser.parse(args);
	if (filenames.isEmpty()) {
	    System.err.println("Error: no BLOG input files specified.");
	    Parser.printUsage(System.err);
	    System.exit(1);
	}

	randomize = optRandomize.getValue();
	numStatSamples = optNumTrials.getValue();
	generate = optGenerate.getValue();
	packages = optPackages.getValue();
	verbose = optVerbose.getValue();
	debug = optDebug.getValue();

	outputPath = optWrite.getValue();	
	if (outputPath != null) {
	    // Need to determine output interval
	    outputInterval = optInterval.getValue();
	    if (outputInterval == 0) {
		// default value is num samples / 100
		outputInterval = Math.max(optNumSamples.getValue() / 100, 1);
	    }
	} else if (optInterval.wasPresent()) {
	    System.err.println("Warning: ignoring --interval option "
			       + "because no output file specified.");
	}

	histOut = optHist.getValue();

	// Make sure properties that have special-purpose options weren't 
	// specified with -P.
	inferenceProps = optInferenceProps.getValue();
	for (Iterator iter = inferenceProps.keySet().iterator(); 
	     iter.hasNext(); ) {
	    String property = (String) iter.next();
	    Option specialOpt = (Option) specialOptions.get(property);
	    if (specialOpt != null) {
		Util.fatalError("Can't use -P to set value for \""
				+ property + "\".  Use special-purpose "
				+ "option " + specialOpt + " instead.", 
				false);
	    }
	}

	// Enter properties from special-purpose options
	inferenceProps.setProperty("engineClass", optEngine.getValue());
	inferenceProps.setProperty("numSamples", 
				   String.valueOf(optNumSamples.getValue()));
	numSamples = optNumSamples.getValue();
	inferenceProps.setProperty("burnIn", 
				   String.valueOf(optBurnIn.getValue()));
	inferenceProps.setProperty("samplerClass", optSampler.getValue());
	inferenceProps.setProperty("proposerClass", optProposer.getValue());

	for (Iterator iter = optSetupExtenders.getValue().iterator(); 
	     iter.hasNext(); ) {
	    addSetupExtender((String) iter.next());
	}
    }

    private static void addSetupExtender(String extenderSpec) {
	int curCommaIndex = extenderSpec.indexOf(',');
	String classname = (curCommaIndex == -1) ? 
	    extenderSpec : extenderSpec.substring(0, curCommaIndex);

	Properties params = new Properties();
	while (curCommaIndex != -1) {
	    int nextCommaIndex = extenderSpec.indexOf(',', curCommaIndex + 1);
	    String paramSpec = (nextCommaIndex == -1) ? 
		extenderSpec.substring(curCommaIndex + 1)
		: extenderSpec.substring(curCommaIndex + 1, nextCommaIndex);

	    int equalsIndex = paramSpec.indexOf('=');
	    if (equalsIndex == -1) {
		Util.fatalError("Setup extender parameter \"" + paramSpec
				+ "\" is not of the form key=value.",
				false);
	    }
	    params.setProperty(paramSpec.substring(0, equalsIndex), 
			       paramSpec.substring(equalsIndex + 1));

	    curCommaIndex = nextCommaIndex;
	}

	SetupExtender extender = null;
	try {
	    Class extenderClass = Class.forName(classname);
	    Class[] constrArgTypes = {Properties.class};
	    Constructor ct = extenderClass.getConstructor(constrArgTypes);
	    Object[] constrArgs = {params};
	    extender = (SetupExtender) ct.newInstance(constrArgs);
	} catch (ClassNotFoundException e) {
	    Util.fatalError("Setup extender class not found: " + classname, 
			    false);
	} catch (NoSuchMethodException e) {
	    Util.fatalError("Setup extender class " + classname 
			    + " does not have a constructor with a single "
			    + "argument of type java.util.Properties.", 
			    false);
	} catch (ClassCastException e) {
	    Util.fatalError("Setup extender class " + classname + " does not "
			    + "implement the SetupExtender interface.", 
			    false);
	} catch (Exception e) {
	    Util.fatalError(e, true);
	} 

	setupExtenders.add(extender);
    }

    

Print to the PrintStream ps the String s exactly n times, followed by a newline.


    public static void printTimes(PrintStream ps, String s, int n) {
	for (int i = 0 ; i < n ; i++) {
	    ps.print(s);
	}
	ps.println();
    }

    

Returns a PrintStream representing the newly created file, with given pathname s. Guaranteed not to be null.


    public static PrintStream filePrintStream(String s) {
	try {
	    File f = new File(s);
	    if (! f.createNewFile()) {
		System.err.println("Cannot create file (already exists): "
				   + f.getPath());
		System.exit(1);
	    }
	    if (! f.canWrite()) {
		System.err.println("Cannot write to file: " + f.getPath());
		System.exit(1);
	    }
	    return new PrintStream(new FileOutputStream(f));
	} catch (Exception e) {
	    System.err.println("Cannot create/open a file for output: " + s);
	    System.err.println(e);
	    System.exit(1);
	    return null;  // for some reason, the compiler needs this.
	}
    }

    

Reads and prepares model, evidence and queries for inference. a { parsed and origin name (such as file name). be run. "Parsing from..."

Parameters: 
readersAndOrigins - A list of Object[] of size two, containing
setupExtenders - A collection of {@link SetupExtender}(s) to
verbose - Whether the procedure is verbose.
parseFromMessage - Whether to print a message indicating
Link:  java.io.Reader} with text to be


    public static void setup(Model model, Evidence evidence, List queries,
			     Collection readersAndOrigins, 
			     Collection setupExtenders, 
			     boolean verbose, boolean parseFromMessage)
    {
    	// Parse input readers
    	for(Iterator iter = readersAndOrigins.iterator(); iter.hasNext(); ) {
	    Object[] readerAndOrigin = (Object[]) iter.next();
	    Reader reader = (Reader) readerAndOrigin[0];
	    String origin = (String) readerAndOrigin[1];
	    try {
		BLOGParser.parseReader(model, evidence, queries, debug, 
				       reader, origin, parseFromMessage);
	    } catch (Exception e) {
		System.err.println("Error parsing file: " + origin);
		Util.fatalError(e);
	    }
    	}

    	// Run setup extenders
    	for (Iterator iter = setupExtenders.iterator(); iter.hasNext(); ) {
	    SetupExtender extender = (SetupExtender) iter.next();
	    try {
		extender.extendSetup(model, evidence, queries);
	    } catch (Exception e) {
		System.err.println("Error running setup extender: " 
				   + extender.getClass().getName());
		Util.fatalError(e);
	    }
    	}

    	if (debug || verbose) {
	    // Print model for debugging
	    System.out.println("............................................");
	    model.print(System.out);
	    System.out.println("............................................");
	    
	    // Print evidence for debugging
	    System.out.println("\nEvidence:"); 
	    evidence.print(System.out);
	    System.out.println("............................................");
	    
	    // Print queries for debugging
	    System.out.println("\nQueries:");
	    for (Iterator iter = queries.iterator(); iter.hasNext(); ) {
		System.out.println(iter.next());
	    }
    	}
	
    	// Run semantic checks on model, evidence and queries
    	if (!semanticsCorrect(model, evidence, queries)) {
	    System.err.println("The model failed one or more checks.");
	    System.err.println("Quitting...");
	    System.exit(1);
    	}

    	// Do compilation pass
    	int errors = model.compile();
    	errors += evidence.compile();
    	for (Iterator iter = queries.iterator(); iter.hasNext(); ) {
	    errors += ((Query) iter.next()).compile();
    	}
    	if (errors > 0) {
	    System.err.println("Encountered " + errors 
			       + " errors in compilation phase.");
	    System.exit(1);
    	}
    }
    
    

A version of { Collection, boolean, boolean)} receiving a single string, no setup extenders, and not verbose.

Link:  #setup(Model, Evidence, List, Collection,


    public static void stringSetup(Model model, Evidence evidence, 
				   List queries, String modelString)
    {
    	Reader reader = new StringReader(modelString);
    	String origin = Util.abbreviation(modelString);
    	List readersAndOrigins = new LinkedList();
    	readersAndOrigins.add(new Object[]{reader, origin});
    	setup(model, evidence, queries, readersAndOrigins, new LinkedList(), 
	      false /* verbose */, false);
    }

    public static String outputPath() {
	return outputPath;
    }

    public static int outputInterval() {
	return outputInterval;
    }

    public static int numSamples() {
	return numSamples;
    }

    public static int numTrials() {
	return numStatSamples;
    }

    public static String histOut() {
	return histOut;
    }

    private static List filenames; // of String
    private static Properties inferenceProps;
    private static boolean randomize = false;
    private static int numSamples;
    private static int numStatSamples;
    private static Model model = new Model();
    private static Evidence evidence = new Evidence();
    private static List queries = new ArrayList();
    private static boolean generate;
    private static List packages; // of String
    private static boolean verbose;
    private static boolean debug;
    private static String outputPath;
    private static int outputInterval;
    private static String histOut;
    private static List setupExtenders = new ArrayList(); // of SetupExtender
}


This file was generated on Tue Jun 08 17:53:36 PDT 2010 from file Main.java
by the ilog.language.tools.Hilite Java tool written by Hassan Aït-Kaci