Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is it possible to create a C++ program using MathLink that will invoke the Maple kernel and execute a very basic Maple command using OpenMaple?

I'm envisioning the following:

Install["MapleLink"]

starts the external program MapleLink and installs the Mathematica definition RunMaple.

?RunMaple

RunMaple[expr] returns a string which is the output when Maple executes expression expr

A sample output:

RunMaple["seq(i, i=0..3);"]

"0, 1, 2, 3"

I'm also open to using J/Link.

share|improve this question
1  
Should be quite possible, but I would rather use Java bindings. Cross-platform, higher-level, also JLink is much easier to use than MathLink - what's not to like? –  Leonid Shifrin Oct 9 '12 at 13:45
    
I'm totally open to any solution. I'll edit the problem to reflect this. –  James Rohal Oct 9 '12 at 13:50
1  
out of curiosity what is your usage/application. (Why are you unable to just run the Maple code in Maple?) –  Mike Honeychurch Oct 9 '12 at 21:33
    
I would find it convenient to access the output from some commands in the RegularChains package. –  James Rohal Oct 10 '12 at 0:20
    
Did you find a solution to this James? I am interested in using a few Maple functions inside Mathematica too. –  Szabolcs Jan 23 '13 at 2:10

1 Answer 1

Begin Note: I have successfully got this working in the following environments.

  1. On a Mac PC running version 9.0.0.0 using a locally installed JRE (version 1.6.0_37).
  2. On a Windows PC running version 9.0.0.0 using a locally installed JRE (version 1.7.0_13).

I found that on my Windows PC, the JRE included with Mathematica is version 1.6.0_10 and the method described below fails when initializing the Maple engine at this step:

MapleEngine = JavaNew[engineload, {"java"}, defaultexception, Null, Null]
Java::excptn: "A Java exception occurred: "java.lang.UnsatisfiedLinkError: "

So if you are getting the error seen above, try loading a newer version of Java when doing ReinstallJava. I show how to do this below.

You can find out the version of Java that Mathematica is running by executing the following.

Needs["JLink`"]
ReinstallJava[];
LoadJavaClass["java.lang.System"];
java`lang`System`getProperty["java.version"]

End Note

Java OpenMaple provides an interface between the Maple evaluation engine and a Java program. J/Link provides Mathematica users with the ability to interact with arbitrary Java classes directly from the front end. The goal here is to use J/Link to access the methods from OpenMaple. It is assumed that Maple is installed on the computer you are doing this on.

First, load J/Link.

Needs["JLink`"]

We will refer to the location of the Maple installation as MAPLEDIR and the location of the Java OpenMaple native library as BINDIR as per this example. You can find these locations by executing, kernelopts(mapledir); and kernelopts(bindir); in Maple, respectively. The images below show the outputs in Windows and OS X, respectively.

kernelopts(mapledir) and kernelopts(bindir) in Maple in Windows

kernelopts(mapledir) and kernelopts(bindir) in Maple in OS X

Here are the directories from my Windows and Mac machine, respectively.

(* Windows *)
MAPLEDIR = "C:\\Program Files (x86)\\Maple 16";
BINDIR = "C:\\Program Files (x86)\\Maple 16\\bin.win";
(* OS X *)
MAPLEDIR = "/Library/Frameworks/Maple.framework/Versions/16";
BINDIR = "/Library/Frameworks/Maple.framework/Versions/16/bin.APPLE_UNIVERSAL_OSX";

Add the Java OpenMaple components to the class path.

(* Windows *)
AddToClassPath[MAPLEDIR <> "\\java\\externalcall.jar"];
AddToClassPath[MAPLEDIR <> "\\java\\jopenmaple.jar"];
(* OS X *)
AddToClassPath[MAPLEDIR <> "/java/externalcall.jar"];
AddToClassPath[MAPLEDIR <> "/java/jopenmaple.jar"];

Update the environment variables.

(* Windows *)
oldPATH = "PATH" /. GetEnvironment["PATH"];
SetEnvironment["PATH" -> oldPATH <> ";" <> BINDIR];
(* OS X *)
SetEnvironment["DYLD_LIBRARY_PATH" -> BINDIR];
SetEnvironment["MAPLE" -> MAPLEDIR];

Since SetEnvironment is new in 9, lower versions should see this answer.

Now that we are done with the set up, we will launch the Java runtime. As per the Note above, I launch the local version of Java in Windows and use the built-in version of Java in OS X.

(* Windows *)
ReinstallJava[CommandLine -> "C:\\Program Files (x86)\\Java\\jre7\\bin\\java.exe"]
(* OS X *)
ReinstallJava[];

Next, create a default instance of a class implementing the EngineCallBacks interface.

exceptionload = LoadJavaClass["com.maplesoft.openmaple.EngineCallBacksDefault"]
defaultexception = JavaNew[exceptionload]
JavaClass[com.maplesoft.openmaple.EngineCallBacksDefault, <>]
« JavaObject[com.maplesoft.openmaple.EngineCallBacksDefault] »

Next, create an instance of Engine to start the Maple session. Only one Engine can be created during a single run of the JVM, even after the Engine has been stopped.

engineload = LoadJavaClass["com.maplesoft.openmaple.Engine"]
MapleEngine = JavaNew[engineload, {"java"}, defaultexception, Null, Null]
JavaClass[com.maplesoft.openmaple.Engine, <>]
« JavaObject[com.maplesoft.openmaple.Engine] »

In Windows, if the Maple kernel gets initialized, then the following splash screen briefly appears. (This did not show up in OS X.)

Maple splash screen in Windows

Using MapleEngine, you can now perform computations using evaluate. Depending on what the input is, the object returned by evaluate differs.

out = MapleEngine@evaluate["seq(i, i=0..3);"];
« JavaObject[com.maplesoft.openmaple.Expseq] »

In this example, the method returns an Expseq object. However, Algebraic is the base class for every Java OpenMaple class that represents a Maple object. Since Expseq publicly inherits from Algebraic, we can use methods from Algebraic to study it. First, we load the Algebraic class.

algebraicload = LoadJavaClass["com.maplesoft.openmaple.Algebraic"]
JavaClass[com.maplesoft.openmaple.Algebraic, <>]

Now we can manipulate our output out.

out@algebraicload`toString[]
[0, 1, 2, 3]

Here, out has head String.

You can create persisting variables using the newName method. We assign the value 100 to the variable abcde and then add 5 to it.

name = MapleEngine@newName["abcde", True];
name@assign[MapleEngine@newNumeric[100]];
out = MapleEngine@evaluate["abcde + 5;"];
out@algebraicload`intValue[]
105

There is a lot more you can do if you take a look at the Java OpenMaple API. The code above is only a starting point. I can imagine someone building a nice package off of this.

share|improve this answer
    
Excellent! If you make a small package out of this, could you please put it on GitHub for easier collaboration? –  Szabolcs Jan 26 '13 at 2:05
    
I definitely will. –  James Rohal Jan 26 '13 at 19:31
    
I think Mathematica doesn't include Java on OS X so we're free to install whichever version we'd like to use. (It does indeed include 1.6u10 on Windows). Thanks for the hints on getting it working on Win! –  Szabolcs Feb 8 '13 at 4:53
    
What I'm actually interested in is transferring large integers (larger than machine integers). Actually transferring a list of them. Is the best way just using a string? –  Szabolcs Feb 8 '13 at 4:56
    
Oh, I did not know it did not include it. I will make that change. In regards to the large integers, I think a string may be your best bet. A quick search on "max length of Java strings" brings up a result saying strings can be no longer than Integer.MAX_VALUE (in excess of two billion) characters. OpenMaple supports strings via MString: maplesoft.com/support/help/Maple/view.aspx?path=OpenMaple/Java/… –  James Rohal Feb 8 '13 at 5:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.