package powerloom;
/* Import statements for working with PowerLoom. */
import edu.isi.powerloom.*;
import edu.isi.powerloom.logic.*;
import edu.isi.stella.Module;
import edu.isi.stella.javalib.*;
import edu.isi.stella.Stella_Object;
import edu.isi.stella.Cons;
import java.io.File;
/** PowerLoomExample class provides an example of using the Java
* interface to PowerLoom. It will initialize the PowerLoom system,
* load the KB files specified as command line arguments, and then
* execute some PowerLoom code.
*
* The command line arguments must load the business.plm knowledge
* base file or else the examples in this file will fail. It is
* passed as a command line parameter so that the example does not
* depend on there being a particular location for the ontologgy
* files. If no argument is given, then business.plm and
* kbs/business.plm will be tried, in that order.
*
* In the calls to PLI methods, the last (environment) variable can
* always be specified as null, getting the default behavior.
*
* @version $Id: PowerLoomExample.java,v 1.4 2004/06/08 00:00:34 tar Exp $
*/
public class PowerLoomExample {
private static String kbfileDefault = "business.plm";
private static String kbdirDefault = "kbs";
private static String workingModule = "BUSINESS";
private static void loadVerbosely (String filename) {
System.out.print(" Loading " + filename + " ...");
try {
PLI.load(filename, null);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(" done.");
}
public static void main (String[] args) {
// Initialize the basic PowerLoom code.
// This may need to be augmented if you want to use additional
// PowerLoom or Stella code. One common extension is to use
// the PowerLoom system, which will require the additional
// initialization, commented out below.
System.out.print("Initializing...");
PLI.initialize();
// StartupPowerLoomSystem.startupPowerLoomSystem();
System.out.println(" done.");
// Load the knowledge bases. This will either take the names from
// the command line or else it will try a plain file default and a
// plain file default in the default kb directory.
System.out.println("Loading KBs:");
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
loadVerbosely(args[i]);
}
} else if (new File(kbfileDefault).exists()) {
loadVerbosely(kbfileDefault);
} else if (new File(kbdirDefault, kbfileDefault).exists()) {
loadVerbosely(new File(kbdirDefault, kbfileDefault).getAbsolutePath());
} else {
System.err.println("Oops. This needs an ontology file argument!");
System.exit(0);
}
// *** Initialization is now complete.
// We begin working with the knowledge base.
doPowerLoomExamples();
}
/** Example interactions with a PowerLoom knowledge base. We use
* the "s..." method calls since they are generally simpler to
* use from Java than constructing the Stella/PowerLoom data
* structures.
*
* In all of these, it is important to check parentheses balance
* for correct operation. PowerLoom will complain otherwise,
* which can help you debug things.
*/
static void doPowerLoomExamples() {
// The following code parallels the user interaction in example.text
// First we change into the BUSINESS module, which is not strictly necessary
// since all the function calls will supply the module argument.
PLI.sChangeModule(workingModule, null);
// Then we assert a few additional facts:
PLI.sAssertProposition("(and (company c3) (company-name c3 \"Mom's Grocery\") (number-of-employees c3 2))", workingModule, null);
PLI.sAssertProposition("(and (corporation c4) "
+ "(company-name c4 \"Yoyodyne, Inc.\")"
+ "(> (number-of-employees c4) 20000))",
workingModule, null);
// Now we do the first query, getting back a PowerLoom iterator, which we
// then step over and print the answers. We use a static method defined below
// for convenience in asking the query and then printing out the answers.
//
printPowerLoomAnswers("all ?x (small-company ?x)",
workingModule,
null);
// We could make the print-out prettier by using the company name
// rather than the instance name. In the next query we use an
// existentially quantified variable that is not returned to hold
// the company instance.
printPowerLoomAnswers2("all ?x (exists ?c (and (small-company ?c) (company-name ?c ?x)))",
workingModule,
null);
// We here examine the differences between the NOT and FAIL
// oerators. NOT requires a hard proof, whereas FAIL does not.
// Note that we need to provide a positive clause as well,
// otherwise PowerLoom will just give up on the query, because
// there are just too many things that are not small companies.
printPowerLoomAnswers("all ?x (not (small-company ?x))",
workingModule,
null);
printPowerLoomAnswers("all ?x (and (company ?x) (not (small-company ?x)))",
workingModule,
null);
printPowerLoomAnswers("all ?x (and (company ?x) (fail (small-company ?x)))",
workingModule,
null);
// Here is a slightly more complicated query. It returns more
// than one item in each answer tuple.
printPowerLoomAnswers("all (?name ?emp) (exists ?c (and (company ?c) (company-name ?c ?name) (number-of-employees ?c ?emp)))",
workingModule,
null);
// This is how one would be able to assign values from the
// returned tuples to Java native data types. For simplicity we
// ask for only a single returned values from the query.
//
// Note: Best practice would be to include a test for the data
// type using one of the PLI.isInteger(), PLI.isString(),
// etc. functions because there are some cases where
// PowerLoom will return a skolem instance in place of an
// actual value. The query returning the number of
// employees is one such example.
String query = "1 (?instance ?name ?emp) (and (small-company ?instance) (company-name ?instance ?name) (number-of-employees ?instance ?emp))";
PlIterator answer = PLI.sRetrieve(query, workingModule, null);
// Check for answer. Necessary to get to the value anyway:
System.out.println();
printSeparator();
System.out.println("Retrieving '" + query + "'");
if (answer.nextP()) {
// Here we take apart the first tuple, held in the "value" field
// of the PLIterator instance. Also, these interface functions
// require the actual module object and not just its name. So
// we look that up and use it.
Module mod = PLI.getModule(workingModule, null);
Stella_Object instance = PLI.getNthValue(answer.value, 0, mod, null);
String cname = PLI.getNthString(answer.value, 1, mod, null);
int employees = PLI.getNthInteger(answer.value, 2, mod, null);
System.out.println("Returns object " + instance
+ " with name \"" + cname
+ "\" and " + employees + " employees.");
} else {
System.out.println("No answers found");
}
printSeparator();
// We create a new relation here, taking care to pay attention to
// the capitalization of names. Remember that in a module that is
// not defined to be case sensitive, internal names are mapped to
// uppercase. This is handled internally by the interface functions.
PLI.sCreateRelation("competitor", 2, workingModule, null);
// Now we assert the symmetric property about this relation:
PLI.sAssertProposition("(symmetric competitor)", workingModule, null);
// Remember that assertions require that instance names are used.
PLI.sAssertProposition("(competitor c3 c4)", workingModule, null);
// A quick test to make sure that the symmetric property holds:
printPowerLoomAnswers("all ?c (competitor c4 ?c)", workingModule, null);
// One could use a simpler ask query as well:
printPowerLoomTruth("(competitor c4 c3)", workingModule, null);
// Arbitrary PowerLoom commands can be run using the evaluate and
// sEvaluate commands. This can be useful for adding additional
// definitions that are more complex than what the general concept
// creation interface supports. Anything that can be typed at the
// PowerLoom prompt can be passed to this interface function.
PLI.sEvaluate("(defrelation mismatched-competitor ((?c1 company) (?c2 company)) :<=> (and (competitor ?c1 c2) (> (absolute-value (- (number-of-employees ?c1) (number-of-employees ?c2))) 1000)))",
workingModule,
null);
// And testing it:
printPowerLoomTruth("(mismatched-competitor c4 c3)", workingModule, null);
// Error Handling:
// If there is an error in the PowerLoom form, then an exception will
// be thrown. Errors in the logic itself are subtypes of
// edu.isi.powerloom.logic.LogicException whereas underlying internal
// code problems will be subtypes of edu.isi.stella.StellaException
// Note that LogicException is also a subtype of StellaException.
// and StellaException is a subtype of java.lang.Exception.
try {
//System.out.println();
//System.out.println("Error example:");
//PLI.sRetrieve("all ?x (use-a-name-that-does-not-exist ?x)", workingModule, null);
} catch (edu.isi.powerloom.logic.LogicException le) {
System.out.println("Caught a logic exception: " + le);
} catch (edu.isi.stella.StellaException se) {
System.out.println("Really Bad News, an internal Stella exception: " + se);
}
// Not enough parentheses:
try {
//System.out.println();
//System.out.println("Error example 2:");
//PLI.sRetrieve("all (?x ?y) (and (competitor ?x ?y) (small-company ?x)", workingModule, null);
} catch (edu.isi.powerloom.logic.LogicException le) {
System.out.println("Caught a logic exception: " + le);
} catch (edu.isi.stella.StellaException se) {
System.out.println("Really Bad News, an internal Stella exception: " + se);
}
System.out.println();
System.out.println("==== End of Example Code ====");
}
/** Takes a query, gets the PowerLoom answers and iterates over them to print
* them out.
* @param query The PowerLoom language query to be executed
* @param module The name of the module in which to execute the query
* @param env The PowerLoom environment for the query.
*/
static void printPowerLoomAnswers (String query, String module, Environment env) {
// variable to hold the query answers, which is a special
// PowerLoom iterator.
try {
PlIterator answer = PLI.sRetrieve(query, module, env);
System.out.println();
printSeparator();
System.out.println("Answers to query `" + query + "'");
while (answer.nextP()) {
System.out.println(answer.value);
}
} catch (Exception e) {
e.printStackTrace();
}
printSeparator();
}
/** Takes a query, gets the PowerLoom answers and iterates over them to print
* them out. This version uses a wrapper around the native PowerLoom iterator
* so that the Java Iterator interface can be used.
*
* @param query The PowerLoom language query to be executed
* @param module The name of the module in which to execute the query
* @param env The PowerLoom environment for the query.
*/
static void printPowerLoomAnswers2 (String query, String module, Environment env) {
// variable to hold the query answers, which uses a convenience class to wrap
// the native PowerLoom iterator and provide the standard Java interface.
java.util.Iterator answer = new StellaIterator(PLI.sRetrieve(query, module, env));
System.out.println();
printSeparator();
System.out.println("Answers to query `" + query + "'");
while (answer.hasNext()) {
System.out.println(answer.next());
}
printSeparator();
}
/** Takes a propositional query, gets the PowerLoom truth value and
* prints it out.
* @param query The PowerLoom language query to be executed
* @param module The name of the module in which to execute the query
* @param env The PowerLoom environment for the query.
*/
static void printPowerLoomTruth (String query, String module, Environment env) {
// variable to hold the query answer, which is a TruthValue object in
// the edu.isi.powerloom.logic package.
TruthValue answer = PLI.sAsk(query, module, env);
System.out.println();
printSeparator();
System.out.print("The proposition `" + query + "' is ");
if (PLI.isTrue(answer)) {
System.out.println("true");
} else if (PLI.isFalse(answer)) {
System.out.println("false");
} else if (PLI.isUnknown(answer)) {
System.out.println("unknown");
}
printSeparator();
}
/** Utility function to print a separator line.
*/
static void printSeparator () {
System.out.println("-----------------------------------------");
}
}