Issue in R arules package using java - java

For a university project I have to implement arules(package of R) in java. I have successfully integrated R and java using JRI. I did not understand how to get output of "inspect(Groceries[1:1])". I have tried with asString(),asString[]() but this gives me following error:
Exception in thread "main" java.lang.NullPointerException
at TestR.main(TestR.java:11)
Also, how can implement summary(Groceries) in java? How to get output of summary in String array or string?
R code:
>data(Groceries)
>inspect(Groceries[1:1])
>summary(Groceries)
Java code:
import org.rosuda.JRI.Rengine;
import org.rosuda.JRI.REXP;
public class TestR {
public static void main(String[] args){
Rengine re = new Rengine(new String[]{"--no-save"}, false, null);
re.eval("library(arules)");
re.eval("data(Groceries)");
REXP result = re.eval("inspect(Groceries[1:1])");
System.out.println(result.asString());
}
}

Appears that the inspect function in pkg:arules returns NULL. The output you see is a "side-effect". You can attempt to "capture output" but this is untested since I don't have experience with this integration across languages. Try instead.:
REXP result = re.eval("capture.output( inspect(Groceries[1:1]) )");
In an R console session you will get:
library(arules)
data("Adult")
rules <- apriori(Adult)
val <- inspect(rules[1000])
> str(val)
NULL
> val.co <- capture.output(inspect(rules[1000]))
> val.co
[1] " lhs rhs support confidence lift"
[2] "1 {education=Some-college, "
[3] " sex=Male, "
[4] " capital-loss=None} => {native-country=United-States} 0.1208181 0.9256471 1.031449"
But I haven't tested this in a non-interactive session. May need to muck with the file argument to capture.output, ... or it may not work at all.

Related

JDK 17 Foreign memory API throws exception - Method threw 'java.lang.UnsatisfiedLinkError' exception

I'm trying to execute the following code using JDK 17.0.1. I have ensured the JDK 17 is on the class path.
Here is the code i'm executing:
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryHandles;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.ResourceScope;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
public class PanamaMain {
public static void main (String[] args) {
MemoryAddress address = MemorySegment.allocateNative(4, ResourceScope.newImplicitScope()).address();
VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
int value = (int) handle.get(address); //This line throws the exception mentioned above.
System.out.println("Memory Value: " + value);
}
}
The cause of the exception is: java.lang.UnsatisfiedLinkError: 'java.lang.Object java.lang.invoke.VarHandle.get(java.lang.Object[])'
Exception Details
I saw some replies on a similar exception suggesting using the java.library.path system property but I got an error that the java.library.path is an invalid flag.
I would appreciate your help/tips on this issue! Thank you in advance for your time!
The VarHandle.get method is expecting a MemorySegment (not MemoryAddress) and offset in bytes within the segment. The layouts of standard C types are found in CLinker.C_XXX so you don't need to hardcode byte size of int as 4.
Assuming that your PATH is correct for launching JDK17 then this should work:
MemorySegment segment = MemorySegment.allocateNative(CLinker.C_INT, ResourceScope.newImplicitScope());
VarHandle handle = MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
handle.set(segment, 0, 4567);
int value = (int)handle.get(segment, 0);
System.out.println("Memory Value: " + value + " = 0x"+Integer.toHexString(value));
Prints:
Memory Value: 4567 = 0x11d7
In JDK17 you can also use MemoryAccess to set or get values from allocated MemorySegment. , and could change to:
MemorySegment segment = MemorySegment.allocateNative(CLinker.C_INT, ResourceScope.newImplicitScope());
MemoryAccess.setInt(segment, -1234);
int value = MemoryAccess.getInt(segment);
System.out.println("Memory Value: " + value + " = 0x"+Integer.toHexString(value));
Prints
Memory Value: -1234 = 0xfffffb2e
Note that the API has changed, so the equivalent code in JDK18+ will be different.

R Integrate with Java using Rserve

I have build an application connecting R and java using the RServe package. In this project I use neuralnet to predict output. Where is the source code that I use are as follows:
myneuralnetscript=function(){
trainingData = read.csv("D:\\Kuliah\\Semester V\\TA\\Implementasi\\training.csv")
testingData = read.csv("D:\\Kuliah\\Semester V\\TA\\Implementasi\\testing.csv")
X1training <- trainingData$open
X2training <- trainingData$high
X3training <- trainingData$low
X4training <- trainingData$close
X5training <- trainingData$volume
targetTraining <- trainingData$target
X1testing <- testingData$open
X2testing <- testingData$high
X3testing <- testingData$low
X4testing <- testingData$close
X5testing <- testingData$volume
targetTesting <- testingData$target
xTraining <- cbind(X1training,X2training,X3training,X4training,X5training)
sum.trainingData <- data.frame(xTraining,targetTraining)
net.sum <- neuralnet(targetTraining~X1training+X2training+X3training+X4training+X5training, sum.trainingData, hidden=5,act.fct="logistic")
xTesting <- cbind(X1testing,X2testing,X3testing,X4testing,X5testing)
sum.testingData <- data.frame(xTesting,targetTesting)
result <- compute(net.sum,sum.testingData[,1:5])
return(result)
}
The output generated as follows:
Here the program from Java to access the results of the R.
public static void main(String[] args) {
RConnection connection = null;
try {
/* Create a connection to Rserve instance running on default port
* 6311
*/
connection = new RConnection();
//Directory of R script
connection.eval("source('D:\\\\Kuliah\\\\Semester V\\\\TA\\\\Implementasi\\\\R\\\\neuralNet.R')");
//Call method
double output = connection.eval("myneuralnetscript()").asDouble();
System.out.println(output);
} catch (RserveException | REXPMismatchException e) {
System.out.println("There is some problem indeed...");
}
}
However, the output that appears is "There is some problem indeed ...".
Please do not catch exceptions just to print a useless message. Remove your try catch and declare main to throw Exception. That way you'll see the actual error.
Either Rserve is not running locally on 6311 or it's failing to evaluate or the result of second evaluation cannot be coerced into a single double.
When you run eval do
tryCatch({CODE},e=function ()e)
instead and check if return inherits from try-error and get the message

R, Java, RCaller

So i'm trying to use RCaller to do the following (in psuedo-code):
x=simarray(..) // in java
'send x to R'
run y = rlogcon(40000, sort(x)) //in R, rlogcon is part of rlogcondens and the function
produces a numeric vector of length 40000
//send y to java and hold it in a double matrix.
this is what i've got in my main function (i've adapted one of the examples I found, but I must have made a mistake/misunderstood something. I tested the example on my machine, and it worked as expected):
RCaller caller = new RCaller();
RCode code = new RCode();
double[] x = a.simarraysimbeta(5, 1, 100, 30, 40); //some method
savesample("simarraysimbeta.txt",x); //testing, it works.
caller.setRscriptExecutable("C:\\Program Files\\R\\R-3.1.0\\bin\\Rscript.exe");
code.addDoubleArray("X", x);
code.addRCode("library(logcondens)"); //rlogcon is part of logcondens library
code.addRCode("ols <- rlogcon(40,000, sort(X))");
caller.setRCode(code);
caller.runAndReturnResult("ols");
double[] residuals = caller.getParser().getAsDoubleArray("X_star");
and the following relevent imports:
import rcaller.RCaller;
import rcaller.RCode;
import rcaller;
I get the following error:
Exception in thread "main" rcaller.exception.ParseException: Can not
handle R results due to : rcaller.exception.ParseException: Can not
parse output: The generated file
C:\Users\jo\AppData\Local\Temp\Routput8804446513483695061 is empty
here is the output:
concat<-function(to,...){
to<-paste(to,toString(...),sep="");
return(to);
}
cleanNames<-function(names){
cleanNames<-paste(unlist(strsplit(names,"\\.")),collapse="_");
Exception in thread "main" rcaller.exception.ParseException: Can not
handle R results due to : rcaller.exception.ParseException: Can not
parse output: The generated file
C:\Users\jo\AppData\Local\Temp\Routput8804446513483695061 is empty
cleanNames<-paste(unlist(strsplit(cleanNames,"<")),collapse="");
at rcaller.RCaller.runAndReturnResult(RCaller.java:409)
cleanNames<-paste(unlist(strsplit(cleanNames,">")),collapse="");
at dissertation.Dissertation.main(Dissertation.java:709)
cleanNames<-paste(unlist(strsplit(cleanNames," ")),collapse="");
cleanNames<-paste(unlist(strsplit(cleanNames,"\\(")),collapse="");
cleanNames<-paste(unlist(strsplit(cleanNames,"\\)")),collapse="");
cleanNames<-paste(unlist(strsplit(cleanNames,"\\[")),collapse="");
cleanNames<-paste(unlist(strsplit(cleanNames,"\\]")),collapse="");
cleanNames<-paste(unlist(strsplit(cleanNames,"\\*")),collapse="");
return(cleanNames);
}
makevectorxml<-function(code,objt,name=""){
xmlcode<-code;
if(name==""){
varname<-cleanNames(deparse(substitute(obj)));
}else{
varname<-name;
}
obj<-objt;
n <- 0; m <- 0
mydim <- dim(obj)
if(!is.null(mydim)){
n <- mydim[1]; m <- mydim[2];
}else{
n <- length(obj); m <- 1;
}
if(is.matrix(obj)) obj<-as.vector(obj);
if(typeof(obj)=="language") obj<-toString(obj);
if(typeof(obj)=="logical") obj<-as.character(obj);
if(is.vector(obj) && is.numeric(obj)){
xmlcode<-paste(xmlcode,"<variable name=\"",varname,"\" type=\"numeric\" n=\"", n, "\" m=\"", m, "\">",sep="");
for (i in obj){
xmlcode<-paste(xmlcode,"<v>",sep="");
xmlcode<-paste(xmlcode,toString(i),sep="");
xmlcode<-paste(xmlcode,"</v>",sep="");
}
xmlcode<-paste(xmlcode,"</variable>\n",sep="");
}
if(is.vector(obj) && is.character(obj)){
xmlcode<-paste(xmlcode,"<variable name=\"",varname,"\" type=\"character\">\n",sep="");
for (i in obj){
xmlcode<-paste(xmlcode,"<v>",sep="");
xmlcode<-paste(xmlcode,toString(i),sep="");
xmlcode<-paste(xmlcode,"</v>",sep="");
}
xmlcode<-paste(xmlcode,"</variable>\n");
}
return(xmlcode);
}
makexml<-function(obj,name=""){
xmlcode<-"<?xml version=\"1.0\"?>\n";
xmlcode<-concat(xmlcode,"<root>\n");
if(!is.list(obj)){
xmlcode<-makevectorxml(xmlcode,obj,name);
}
else{
objnames<-names(obj);
for (i in 1:length(obj)){
xmlcode<-makevectorxml(xmlcode,obj[[i]],cleanNames(objnames[[i]]));
}
}
xmlcode<-concat(xmlcode,"</root>\n");
return(xmlcode);
}
X<-c(##100 doubles);
library(logcondens)
ols <- rlogcon(40,000, sort(X))
cat(makexml(obj=ols, name="ols"), file="C:/Users/##/AppData/Local/Temp/Routput8804446513483695061")
40,000 shold be 40000 in your code.
There are two ways in which a file remains empty:
there is an error in R code
the result is NULL or NA
I recommend you to use tryCach in R
ols <- tryCatch({
rlogcon(40,000, sort(X))
}, error = function(e) {
-1
})
And at the end if ols equlas -1, you'll know that there was an error in R

Calling R from Java using RServe weird error

I have this code :
import org.rosuda.REngine.Rserve.RConnection;
public class TestProgram {
public static void main(String[] args) {
try {
RConnection rConnection = new RConnection();
// make a new local connection on default port (6311)
rConnection.eval("for(i in 1:.Machine$integer.max){}");
System.out.println("Done!");
}
catch(Exception e) {
System.out.println(e.toString());
}
}
}
I get this exception :
org.rosuda.REngine.Rserve.RserveException: eval failed, request status: error code: 127
If I change :
rConnection.eval("for(i in 1:.Machine$integer.max){}");
to
rConnection.eval("for(i in 1:777){}");
it does work :-)
Does anyone know what's going on ?
P.S I started Rserve from R ( same machine ) using :
>library(Rserve)
>Rserve()
> sessionInfo()
R version 3.0.1 (2013-05-16)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_United States.1252
[2] LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] Rserve_1.7-3
loaded via a namespace (and not attached):
[1] tools_3.0.1
OS is Windows 8. I did not try this on Linux.
You should check the return from the eval function to see if it extends try-error. If it does then print it to debug string to get the error message. The section below was taken from the Rserve documentation. This will give you the error message that caused the 127. You should also probably use parseAndEval rather than just eval.
http://www.rforge.net/Rserve/faq.html
c.assign(".tmp.", myCode);
REXP r = c.parseAndEval("try(eval(parse(text=.tmp.)),silent=TRUE)");
if (r.inherits("try-error")) System.err.println("Error: "+r.toString())
else { // success .. }
You might also want to check this link in case it is a restriction of your R environment.
R - Big Data - vector exceeds vector length limit
EDIT: Fixing Chris Hinshaw's answer
c.assign(".tmp.", myCode);
REXP r = c.parseAndEval("try(eval(parse(text=.tmp.)),silent=TRUE)");
if (r.inherits("try-error")) System.err.println("Error: " + r.asString())
else { // success .. }
Note that the println should be using asString(), not toString()

Tuprolog and defining infix operators

So I have some prolog...
cobrakai$more operator.pl
be(a,c).
:-op(35,xfx,be).
+=(a,c).
:-op(35,xfx,+=).
cobrakai$
Which defines some infix operators. I run it using SWI prolog and get the following (perfectly expected) results
?- halt.
cobrakai$swipl -s operator.pl
% library(swi_hooks) compiled into pce_swi_hooks 0.00 sec, 3,992 bytes
% /Users/josephreddington/Documents/workspace/com.plancomps.prolog.helloworld/operator.pl compiled 0.00 sec, 992 bytes
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.5)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
?- be(a,c).
true.
?- a be c.
true.
?- +=(a,c).
ERROR: toplevel: Undefined procedure: (+=)/2 (DWIM could not correct goal)
?- halt.
cobrakai$swipl -s operator.pl
% library(swi_hooks) compiled into pce_swi_hooks 0.00 sec, 3,992 bytes
% /Users/josephreddington/Documents/workspace/com.plancomps.prolog.helloworld/operator.pl compiled 0.00 sec, 1,280 bytes
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.10.5)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
?- be(a,c).
true.
?- a be c.
true.
?- +=(a,c).
true.
?- a += c.
true.
?- halt.
However, when I use Tuprolog to process the same file from Java (using the following code)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import alice.tuprolog.Prolog;
import alice.tuprolog.SolveInfo;
import alice.tuprolog.Theory;
public class Testinfixoperatorconstruction {
public static void main(String[] args) throws Exception {
Prolog engine = new Prolog();
engine.loadLibrary("alice.tuprolog.lib.DCGLibrary");
engine.addTheory(new Theory(readFile("/Users/josephreddington/Documents/workspace/com.plancomps.prolog.helloworld/operator.pl")));
SolveInfo info = engine.solve("be(a,c).");
System.out.println(info.getSolution());
info = engine.solve("a be c.");
System.out.println(info.getSolution());
}
private static String readFile(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
StringBuilder stringBuilder = new StringBuilder();
String ls = System.getProperty("line.separator");
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
stringBuilder.append(ls);
}
return stringBuilder.toString();
}
}
The prolog file does not parse - failing on the '+=' token.
Exception in thread "main" alice.tuprolog.InvalidTheoryException: Unexpected token '+='
at alice.tuprolog.TheoryManager.consult(TheoryManager.java:193)
at alice.tuprolog.Prolog.addTheory(Prolog.java:242)
at Testinfixoperatorconstruction.main(Testinfixoperatorconstruction.java:14)
We can try a slightly different approach, adding the operator directly in the java code with...
public static void main(String[] args) throws Exception {
Prolog engine = new Prolog();
engine.loadLibrary("alice.tuprolog.lib.DCGLibrary");
engine.getOperatorManager().opNew("be", "xfx", 35);
engine.getOperatorManager().opNew("+=", "xfx", 35);
engine.addTheory(new Theory(
readFile("/Users/josephreddington/Documents/workspace/com.plancomps.prolog.helloworld/operator2.pl")));
SolveInfo info = engine.solve("be(a,c).");
System.out.println(info.getSolution());
info = engine.solve("a be c.");
System.out.println(info.getSolution());
}
but we get the same error... :(
Can anyone tell me why this is happening? (and solutions would also be welcome).
SWI-Prolog could be too much permissive while parsing directives. Try enclosing operators between parenthesis:
:-op(35,xfx,(+=)).
edit I tried using 2p.jar, that allowed me to spot the problem. Need to quote operator' atom:
:-op(35,xfx, '+=').
X += Y.
p :- a += b.
interactive 2p console accepts this syntax. Note that 2p.jar by default load tuprolog libraries

Categories

Resources