Tuesday, October 02, 2007

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 < nItems; 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

Comments:
Hi Mark,
Nice blog! Your AI book is a great collaboration to ruby development community. I also believe that ruby is ideal for ai development. In fact, I have started a small open source project about ai in ruby, it is called ai4r (http://ai4r.rubyforge.org/). There you will find some basic things already implemented (decision trees, neural networks, and a genetic algorithms example), trying to be as "short and simple" as possible.
Again, thank you very much for your great content in the blog and the free books.

Regards,
Sergio.
 
Hello Sergio,

I just downloaded ai4r - looks nice!

I have had little time to work on the Ruby AI book lately, but when I can get back to it, I will likely use some of ai4r in the examples.

Thanks,
Mark
 
Post a Comment





<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [ATOM]