Using the PowerLoom reasoning system with JRuby

I am writing a free web book on AI programming with Ruby (a work in progress).

I wanted to use the PowerLoom reasoning system for the book chapter on reasoning. I had two choices: using the C++ PowerLoom libraries with Ruby bindings or writing a Java wrapper class and then using JRuby. I decided to use JRuby. After some more work on converting to native Ruby types for query results, the material in this blog will eventually make its way into my Ruby AI book (along with a larger example). Here is a simple PowerLoom source file "test.plm" that I will use (part of an example by Robert M. NacGregor in the PowerLoom distribution):

(defmodule "BUSINESS"
:documentation "Module for the Business demo example used in the PowerLoom Manual."
:includes ("PL-USER"))

(in-module "BUSINESS")

;; clear any info from previous runs:
(clear-module "BUSINESS")
(reset-features)

;;; Concepts

(defconcept company)
(defconcept corporation (?c company))

;;; Relation

(defrelation company-name ((?c company) (?name STRING)))

and here is a JRuby example program that uses the wrapper (seen later):

require "java"
require "powerloom.jar"
require "pl.jar"
require 'pp'

include_class "PowerLoomWrapper"

pl = PowerLoomWrapper.new

pl.load("test.plm")
pl.changeModule("BUSINESS")
pl.assertProposition("(and (company c3) (company-name c3 \"Mom's Grocery\"))")

answers = pl.doQuery("all ?x (company ?x)")
answers.each {|answer| puts answer}

answers = pl.doQuery("all (?x ?name) (and (company ?x) (company-name ?x ?name))")
answers.each {|answer| puts answer}

Assuming that you get the powerloom.jar and stella.jar files from the PowerLoom web site (grab the latest download), this Java wrapper should work for you:

import edu.isi.powerloom.*;
import edu.isi.powerloom.logic.*;
import edu.isi.stella.Cons;
import java.io.File;

public class PowerLoomWrapper {

public PowerLoomWrapper() {
System.out.print("Initializing...");
PLI.initialize();
System.out.println(" done.");
}
public int load(String fpath) {
try {
PLI.load(fpath, null);
return 1;
} catch (Exception ex) {
System.out.println("Error loading " + fpath + " is: " + ex);
return 0;
}
}
public int changeModule(String workingModule) {
try {
PLI.sChangeModule(workingModule, null);
this.workingModule = workingModule;
return 1;
} catch (Exception ex) {
System.out.println("Error changing module " + workingModule + " is: " + ex);
return 0;
}
}
public int assertProposition(String proposition) {
try {
PLI.sAssertProposition(proposition, workingModule, null);
return 1;
} catch (Exception ex) {
System.out.println("Error asserting proposition '" + proposition + "' is: " + ex);
return 0;
}
}
public int createRelation(String relation, int arity) {
try {
PLI.sCreateRelation(relation, arity, workingModule, null);
return 1;
} catch (Exception ex) {
System.out.println("Error creating relation '" + relation + "' with arity=" + arity + " is: " + ex);
return 0;
}
}

// following method donated by Thomas Russ:
public java.util.ArrayList doQuery(String query) {
java.util.ArrayList ret = null;
try {
PlIterator rawAnswer = PLI.sRetrieve(query, workingModule, null);
ret = new java.util.ArrayList(rawAnswer.length());
java.util.Iterator answer =
new edu.isi.stella.javalib.StellaIterator(rawAnswer);
while (answer.hasNext()) {
Object obj = answer.next();
int nItems = PLI.getColumnCount((edu.isi.stella.Stella_Object)obj);
java.util.ArrayList r2 = new java.util.ArrayList(nItems);
for (int i = 0; i r2.add(fix(PLI.getNthValue((edu.isi.stella.Stella_Object)obj, i, null, null)));
}
ret.add(r2);
}
} catch (Exception ex) {
System.out.println("Error with query '" + query + "': " + ex);
ret = new java.util.ArrayList(0);
}
return ret;
}


private String workingModule = "PL-USER";
}

Here is the Makefile that I use for building a second jar file pl.jar" and running the sample program:

all:
javac -classpath .:powerloom.jar:stella.jar PowerLoomWrapper.java
jar cvf pl.jar PowerLoomWrapper.class PowerLoomWrapper.java
/Users/markw/bin/jruby-1.0/bin/jruby jruby_powerloom.rb
Related Posts

Comments are closed.