I want to make a query to use Prolog in java through JPL, I read the documentation (http://www.swi-prolog.org/packages/jpl/java_api/getting_started.html)
The prolog predicates are these:
child_of(joe, ralf).
child_of(mary, joe).
child_of(steve, joe).
child_of(steve, ralf).
descendent_of(X, Y) :-
child_of(X, Y).
descendent_of(X, Y) :-
child_of(Z, Y),
descendent_of(X, Z).
My code looks like this
Variable X = new Variable();
Query q4 =
new Query(
"descendent_of",
new Term[] {X,new Atom("joe")}
);
java.util.Hashtable solution;
while ( q4.hasMoreSolutions() ){
solution = q4.nextSolution();
System.out.println( "X = " + solution.get(X));
}
According to my prolog predicates, my java code should retrieve 'mary' and 'steve', but I get this:
X = null
X = null
What I'm doing wrong? thanks in advance
EDIT: this is my entire testing
Query q1 =
new Query(
"consult",
new Term[] {new Atom("C:\\Users\\cardozo\\Documents\\fer\\info2\\lore\\test.pl")}
);
return q1;
System.out.println( "consult " + (q.query() ? "succeeded" : "failed"));
Query q2 =
new Query(
"child_of",
new Term[] {new Atom("joe"),new Atom("X")}
);
Boolean resp= q2.query();
System.out.println("child_of(joe,X) is " + resp.toString()
);
Query q3 =
new Query(
"descendent_of",
new Term[] {new Atom("steve"),new Atom("ralf")}
);
System.out.println(
"descendent_of(joe,ralf) is " +
( q3.query() ? "provable" : "not provable" )
);
Variable X = new Variable();
Query q4 =
new Query(
"descendent_of",
new Term[] {X,new Atom("joe")}
);
java.util.Hashtable solution;
q4.query();
while ( q4.hasMoreSolutions() ){
solution = q4.nextSolution();
System.out.println( "X = " + solution.get("X"));
}
And this is what I get in my java console as result
run:
% C:\Users\cardozo\Documents\fer\info2\lore\test.pl compiled 0.00 sec, 8 clauses
consult succeeded
child_of(joe,X) is false
descendent_of(joe,ralf) is provable
X = null
X = null
BUILD SUCCESSFUL (total time: 0 seconds)
I found the solution, I have to use the class Compound (included in jpl) like this
Query q4 = new Query(new Compound("descendent_of", new Term[] { new Variable("X"), new Atom("joe")}));
while ( q4.hasMoreSolutions() ){
solution = q4.nextSolution();
System.out.println( "X = " + solution.get("X"));
}
And I get the solution
X = mary
X = steve
I would try to get variable by name:
solution.get("X")
edit
with a literal query like
Query q4 = new Query("descendent_of(X,joe)")
Related
I have tried numerous ways and followed some of the examples that are scattered around the web on how to write a jagged array (an array of arrays that may be of differing lengths) in HDF5.
Most of the examples are in C and rather low-level. Anyhow I can't seem to get it working and I just looked at the C-source code and it pretty much says that any variable-length datatypes that are not strings are not supported (if I understood correctly).
My miserable dysfunctional code (as is):
public void WIP_createVLenFloatDataSet( List<? extends Number> floats ) throws Exception
{
String group = "/test";
long groupId = createGroupIfNotExist( group );
MDataQualifier qualifier = new MDataQualifierImpl( group, "float", "0.0.0" );
long datasetId = openDataSet( qualifier );
long heapType = H5.H5Tcopy( MDataType.FLOAT_ARRAY.getHDFType() );
heapType = H5.H5Tvlen_create( heapType );
// heapType = H5.H5Tarray_create( heapType, 1, new long[]{1} );
if( !exists( datasetId ) )
{
long[] maxDims = new long[]{ HDF5Constants.H5S_UNLIMITED };
long dataspaceId = H5.H5Screate_simple( 1, new long[]{ 1 }, null );
// Create the dataset.
long datasetId1 = -1;
try
{
if( exists( m_fileId ) && exists( dataspaceId ) && exists( heapType ) )
{
long creationProperties = H5.H5Pcreate( HDF5Constants.H5P_DATASET_CREATE );
H5.H5Pset_chunk( creationProperties, /*ndims*/1, new long[]{ 1 } );
datasetId1 = H5.H5Dcreate( groupId, qualifier.getVersionedName(), heapType, dataspaceId, H5P_DEFAULT, creationProperties, H5P_DEFAULT );
// H5.H5Pclose( creationProperties );
}
}
catch( Exception e )
{
LOG.error( "Problems creating the dataset: " + e.getMessage(), e );
}
datasetId = datasetId1;
if( exists( datasetId ) )
{
// flushIfNecessary();
LOG.trace( "Wrote empty dataset {}", qualifier.getVersionedName() );
}
}
List<? extends Number> data = ( List<? extends Number> )floats;
// H5.H5Dwrite( datasetId, heapType, dataspaceId, memSpaceId, HDF5Constants.H5P_DEFAULT, Floats.toArray( data) );
ByteBuffer bb = ByteBuffer.allocate( data.size() * 4 );
floats.forEach( f -> bb.putFloat( f.floatValue() ) );
// H5.H5Dwrite( datasetId, heapType, H5S_ALL, H5S_ALL, H5P_DEFAULT, Floats.toArray( data ) );
H5.H5Dwrite( datasetId, heapType, H5S_ALL, H5S_ALL, H5P_DEFAULT, bb.array() );
}
Has anyone done this before and can at least confirm that it's not possible?
The most I can get out of HDF5 is the message "buf does not support variable length type".
Apparently the "glue code" of the JNI wrapper doesn't support this. If you want to use this feature you either have to implement your own JNI or wait for a newer version. The official JNI code is open source and can be found here.
Error is occurred while executing the code.
Variable X = new Variable();
Term goal= new Compound("parent", new Term []{new Atom("ali"),X});
Query q = new Query(goal);
while (q.hasMoreElements()) {
Hashtable binding = (Hashtable) q.nextElement();
Term t = (Term) binding.get(X);
System.out.println(t);
}
and Error is
Exception in thread "main" java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.Hashtable
at newProj.MyMain.main(MyMain.java:18)
Prolog Predicates are
parent(ali, rabia).
parent(shomaila, mubashir).
parent(shomaila, rabia).
parent(nadia, ali).
parent(sumiya, shomaila).
parent(raheel, ali).
parent(anwar, shomaila).
parent(sara, anwar).
parent(anwar, sana).
parent(sana,naveed).
Try this
Query q =new Query("parent("ali",X)")
java.util.Hashtable solution;
while ( q.hasMoreSolutions() ){
solution = q.nextSolution();
System.out.println( "X = " + solution.get(X));
}
I have two Prolog files. Clauses and Rules as follows:
clauses.pl
get(mary,milk).
go(sandra,kitchen,1).
get(john,football).
go(john,hallway,1).
go(mary,garden,1).
go(john,kitchen,2).
rules.pl
/* X = person Y=location T,T2= time
This rule finds last location of a person */
isAt(X,Y) :- go(X, Y, T), \+ (go(X,_,T2), T2 > T).
/* This rule finds the last location of an object */
whereIs(Q,R) :- findall(R,(get(P,Q,I),go(P,R,_)),L), last(L,R),!.
When I create a Query to find out where John is in Java via the following:
//include the prolog file with clauses to test
File clauseFile = new File ("clauses_qa2.pl");
File ruleFile = new File ("rules.pl");
String clausePath = clauseFile.getAbsolutePath();
String rulePath = ruleFile.getAbsolutePath();
System.out.println("Clause file path: " + clausePath);
System.out.println("Rule file path: " + rulePath);
String t1 = "consult('" + clausePath + "').";
String t2 = "consult('" + rulePath + "').";
jpl.JPL.init();
Query q1 = new Query(t1);
Query q2 = new Query(t2);
Variable X = new Variable("_");
Variable Y = new Variable();
Query q = new Query("isAt",new Term[]{new Atom("john"),X,Y});
while (q.hasMoreElements()) {
Hashtable binding = (Hashtable) q.nextElement();
Term t = (Term) binding.get(X);
System.out.println(t);
}
System.out.println(q.toString());
I get the following error:
Exception in thread "main" jpl.PrologException: PrologException: error(existence_error(procedure, /(isAt, 3)), context(:(system, /('$c_call_prolog', 0)), _1))
at jpl.Query.get1(Query.java:336)
at jpl.Query.hasMoreSolutions(Query.java:258)
at jpl.Query.hasMoreElements(Query.java:472)
However, if I remove that while loops and simply print out the query, I get the following response from Prolog:
Clause file path: G:\Natural Language Final Project\PrologTest\clauses_qa2.pl
Rule file path: G:\Natural Language Final Project\PrologTest\rules.pl
isAt( john, _, _0 )
So I know that at least the query is getting to Prolog from Java. Any ideas about what could be causing the error?
Note:
Turns out that my file paths were not correct.
Changing the code to create the Query as follows:
static void
test_1()
{
Variable X = new Variable();
Term args[] = {
new Atom( "john" ),
X
};
Query query =
new Query(
"isAt",
args );
System.out.println( "iSAt(john, X) = " + query.query() );
}
public static void main(String[] args) throws IOException {
//include the prolog file with clauses to test
File clauseFile = new File ("G:\\Natural Language Final Project\\PrologTest\\src\\clauses_qa2.pl");
File ruleFile = new File ("G:\\Natural Language Final Project\\PrologTest\\src\\rules.pl");
String clausePath = clauseFile.getAbsolutePath();
String rulePath = ruleFile.getAbsolutePath();
System.out.println("Clause file path: " + clausePath);
System.out.println("Rule file path: " + rulePath);
String t1 = "consult('" + "G:\\Natural Language Final Project\\PrologTest\\src\\clauses_qa2.pl"+"').";
String t2 = "consult('" + "G:\\Natural Language Final Project\\PrologTest\\src\\rules.pl"+"').";
/*Scanner scan = new Scanner(ruleFile);
while (scan.hasNextLine()){
System.out.println(scan.nextLine());
}*/
jpl.JPL.init();
Term consult_arg[] = {
new Atom( "G:\\Natural Language Final Project\\PrologTest\\src\\clauses_qa2.pl")
};
Query consult_query =
new Query(
"consult",
consult_arg );
Term consult_arg2[] = {
new Atom( "G:\\Natural Language Final Project\\PrologTest\\src\\rules.pl")
};
Query consult_query2 =
new Query(
"consult",
consult_arg2);
boolean consulted = consult_query.query()&& consult_query2.query();
if ( !consulted ){
System.err.println( "Consult failed" );
System.exit( 1 );
}
test_1();
Variable X = new Variable("_");
Variable Y = new Variable();
Query q = new Query("isAt",new Term[]{new Atom("john"),X});
while (q.hasMoreElements()) {
Hashtable binding = (Hashtable) q.nextElement();
Term t = (Term) binding.get(X);
System.out.println(t);
}
System.out.println(q.toString());
}
results in the following output:
iSAt(john, X) = true
null
isAt( john, _ )
Which is better than the compiler errors, but the answer should be:
isAt(john,X)
X= kitchen
I don't have enough reputation, or I'd leave this as a comment...
I suspect the problem is that the arity of isAt() is 2, but the query is using isAt() with arity 3: isAt(john, X, Y).
I have a drools rule created via the Guvnor console and the rule validates and inserts a fact into the working memory if conditions were met. The rule is:
1. | rule "EligibilityCheck001"
2. | dialect "mvel"
3. | when
4. | Eligibility( XXX== "XXX" , YYY== "YYY" , ZZZ== "ZZZ" , BBB == "BBB" )
5. | then
6. | EligibilityInquiry fact0 = new EligibilityInquiry();
7. | fact0.setServiceName( "ABCD" );
8. | fact0.setMemberStatus( true );
9. | insert(fact0 );
10. | System.out.println( "Hello from Drools");
11. | end
Java code that executes the rule is as follows
RuleAgent ruleAgent = RuleAgent.newRuleAgent("/Guvnor.properties");
RuleBase ruleBase = ruleAgent.getRuleBase();
FactType factType = ruleBase.getFactType("mortgages.Eligibility");
Object obj = factType.newInstance();
factType.set(obj, "XXX", "XXX");
factType.set(obj, "YYY", "YYY");
factType.set(obj, "ZZZ", "XXX");
factType.set(obj, "BBB", "BBB");
WorkingMemory workingMemory = ruleBase.newStatefulSession();
workingMemory.insert(obj);
workingMemory.fireAllRules();
System.out.println("After drools execution");
long count = workingMemory.getFactCount();
System.out.println("count " + count);
Everything looks great with the output as below:
Hello from Drools
After drools execution
count 2
I cannot seem to find a way to get the EligibilityInquiry fact object back in my Java code and get the attributes set in the rule above (serviceName and status). I have used the StatefulSession approach.
The properties file has the link to the snapshot with basic authentication via username and password. There are 2 total facts: EligibilityInquiry and Eligibility.
I am fairly new to drools and any help with the above is appreciated.
(Note: I fixed the order of statement, a typo ("XX") and removed the comments from the output. Less surprise.)
This snippet assumes that EligibilityInquiry is also declared in DRL.
FactType eligInqFactType = ruleBase.getFactType("mortgages", "EligibilityInquiry");
Class<?> eligInqClass = eligInqFactType.getFactClass();
ObjectFilter filter = new FilterByClass( eligInqClass );
Collection<Object> eligInqs = workingMemory.getObjects( filter );
And the filter is
public class FilterByClass implements ObjectFilter {
private Class<?> theClass;
public FilterByClass( Class<?> clazz ){
theClass = clazz;
}
public boolean accept(Object object){
return theClass.isInstance( object );
}
}
You might also use a query, which takes about the same amount of code.
// DRL code
query "eligInqs"
eligInq : EligibilityInquiry()
end
// after return from fireAllRules
QueryResults results = workingMemory.getQueryResults( "eligInqs" );
for ( QueryResultsRow row : results ) {
Object eligInqObj = row.get( "eligInq" );
System.out.println( eligInqClass.cast( eligInqObj ) );
}
Or you can call workingMemory.getObjects() and iterate the collection and check for the class of each object.
for( Object obj: workingMemory.getObjects() ){
if( obj.isInstance( eligInqClass ) ){
System.out.println( eligInqClass.cast( eligInqObj ) );
}
}
Or you can (with or without inserting the created EligibilityInquiry object as a fact) add the fact to a global java.util.List eligInqList and iterate that in your Java code. Note that the API of StatefulKnowledgeSession is required (instead of WorkingMemory).
// Java - prior to fireAllRules
StatefulKnowledgeSession kSession() = ruleBase.newStatefulSession();
List<?> list = new ArrayList();
kSession.setGlobal( "eligInqList", list );
// DRL
global java.util.List eligInqList;
// in a rule
then
EligibilityInquiry fact0 = new EligibilityInquiry();
fact0.setServiceName( "ABCD" );
fact0.setMemberStatus( true );
insert(fact0 );
eligInqList.add( fact0 );
end
// after return from fireAllRules
for( Object elem: list ){
System.out.println( eligInqClass.cast( elem ) );
}
Probably an embarras de richesses.
I am a newbie to java bytecode and javassist. I created a new class file with using javassist. Although I added fields and methods, I couldn't achieve to add line number to method. Result of my research, I understand that I need to add linenumberattribute to codeattribute of method info. Moreover, linenumberattribute consists of linenumbertable. I don't know how can I create a new linenumberattribute with javassist.
I am writing a compiler that produces JVM code. I need line numbers in the output. I do it this way.
I build up a list of objects similar to this:
public class MyLineNum {
public final short pc;
public final short lineNum;
}
Then I add the line number table:
final ClassFile classFile = ...;
final ConstPool constPool = classFile.getConstPool();
final MethodInfo minfo = new MethodInfo( ... );
final Bytecode code = new Bytecode( constPool );
... code that writes to 'code'
final List<MyLineNum> lineNums = new ArrayList<>();
... code that adds to 'lineNums'
final CodeAttribute codeAttr = code.toCodeAttribute();
if ( !lineNums.isEmpty() ) {
// JVM spec describes method line number table thus:
// u2 line_number_table_length;
// { u2 start_pc;
// u2 line_number;
// } line_number_table[ line_number_table_length ];
final int numLineNums = lineNums.size();
final byte[] lineNumTbl = new byte[ ( numLineNums * 4 ) + 2 ];
// Write line_number_table_length.
int byteIx = 0;
ByteArray.write16bit( numLineNums, lineNumTbl, byteIx );
byteIx += 2;
// Write the individual line number entries.
for ( final MyLineNum ln : lineNums) {
// start_pc
ByteArray.write16bit( ln.pc, lineNumTbl, byteIx );
byteIx += 2;
// line_number
ByteArray.write16bit( ln.lineNum, lineNumTbl, byteIx );
byteIx += 2;
}
// Add the line number table to the CodeAttribute.
#SuppressWarnings("unchecked")
final List<AttributeInfo> codeAttrAttrs = codeAttr.getAttributes();
codeAttrAttrs.removeIf( ( ai ) -> ai.getName().equals( "LineNumberTable" ) ); // remove if already present
codeAttrAttrs.add( new AttributeInfo( constPool, "LineNumberTable", lineNumTbl ) );
}
// Attach the CodeAttribute to the MethodInfo.
minfo.setCodeAttribute( codeAttr );
// Attach the MethodInfo to the ClassFile.
try {
classFile.addMethod( minfo );
}
catch ( final DuplicateMemberException ex ) {
throw new AssertionError( "Caught " + ex, ex );
}