Chapter 17. Interfacing Mathematica

I want somebody to share Share the rest of my life Share my innermost thoughts Know my intimate details Someone who’ll stand by my side And give me support And in return She’ll get my support She will listen to me When I want to speak

As wonderful as Mathematica is, there are many practical reasons for needing to interact with other languages and data sources. Luckily, Mathematica is designed to interoperate well with third-party tools. The foundation of much of this interoperability is MathLink. The MathLink protocol is central to Mathematica because it is how the frontend communicates with the kernel. A link (LinkObject) is a communications channel that allows Mathematica expressions and data values to be transmitted between the kernel and programs written in C, Java, .NET, and even scripting languages like Python. 17.5 Using Mathematica with Java, 17.6 Using Mathematica to Interact with Microsoft’s .NET Framework, 17.7 Using the Mathematica Kernel from a .NET Application, and 17.8 Querying a Database solve some of the most common language interoperability problems.

Equally important to programming language interoperability is database interoperability. A powerful language like Mathematica would be far less useful if it did not allow full access to enterprise data. In the past, the ability to read in data from flat files would suffice, but today most enterprises keep data in some form of relational database. Mathematica supports a variety of database linkages, such as generic Open Database Connectivity (ODBC), Java Database Connectivity (JDBC), as well as specific database products like MySQL (http://www.mysql.com/) and HSQL (http://hsqldb.org/). 17.8 Querying a Database and 17.9 Updating a Database show typical database connectivity use cases. 17.10 Introspection of Databases shows how to extract metadata from a database.

More mundane, but nonetheless useful, interfacing problems involve launching external programs and using remote kernels. See 17.1 Calling External Command Line Programs from Mathematica, 17.2 Launching Windows Programs from Mathematica, and 17.3 Connecting the Frontend to a Remote Kernel.

Use the menu Evaluation, Kernel Configuration to create a configuration for a remote kernel. Select Add from the dialog. You will then be presented with the Kernel Properties dialog shown in Figure 17-1. It makes sense to give the kernel a meaningful name that will remind you what server it is connected to, but you can name it after your spouse or your dog if you like. Select the radio button Remote Machine and then enter the machine’s name, a login name, and the kernel program (which is often "math," but see the Discussion section). I like to check the option "Append name to In/Out prompts" to remind me I am working with a remote kernel, but this is a matter of taste. If you will mostly be working with this specific remote kernel, you can also check the automatic launch option.

When you have the kernel configured, you can use Evaluation, Start Kernel to start it and Evaluation, Notebook Kernel to associate it with the current notebook.

If you have network access to a more powerful computer than the one you use daily and that computer has Mathematica installed, then you can reap a lot of benefit from using a remote kernel. For example, I like to work on my laptop because it gives me the flexibility to work anywhere in my house. However, my basement has my powerful Mac Pro, so I usually run my kernel there. This not only gives me access to a faster machine, but frees resources on the laptop that would otherwise be used by the local kernel.

There is a caveat to the solution. If the machine you are connected to is a Mac, there is no program called "math." You must instead give the full path to the program called MathKernel in the edit box for Kernel Program. The location will depend on where Mathematica was installed. For example, I installed Mathematica under /Applications/Wolfram, so I entered /Applications/Wolfram/Mathematica.app/Contents/MacOS/MathKernel.

If you have trouble connecting to the remote kernel you should take the following steps.

Here I demonstrate the process of creating a C program with functions that can be invoked from Mathematica. This example uses Microsoft Visual C++ 2005. Refer to the See Also section for information on using other programming environments. The simplest way to interface Mathematica to C is to utilize the preprocessor mprep, which takes a template file describing one or more C functions, and generate the glue code needed to interface those functions to Mathematica. Here is an example of an mprep file describing three different functions.

:Begin:

:Function:      fExample1
:Pattern:       fExample1[x_Integer, y_Integer]
:Arguments:     {x, y}
:ArgumentTypes: {Integer, Integer}
:ReturnType:    Integer

:Function:      fExample2
:Pattern:       fExample2[x_List, y_List]
:Arguments:     {x, y}
:ArgumentTypes: {IntegerList, RealList}
:ReturnType:    Integer

:Function:      fExample3
:Pattern:       fExample3[aStr_String]
:Arguments:     {aStr}
:ArgumentTypes: {String}
:ReturnType:    String

:End:

The C source code corresponding to these definitions follows. Note that lists are passed as pointers to arrays and that an extra integer parameter is needed for each such list to receive the length of the array. In this listing, you will also find the definition of WinMain that is required for Windows executables built with Microsoft Visual Studio. The body of WinMain is standard boilerplate that you can copy into your own project. The implementation of the functions themselves is really not important in this code as its main purpose is to demonstrate the C interface mechanics.

//functions.h

extern "C"
{
int fExample1(int x, int y);
double fExample2(int * x, long xLen, double* y, long yLen);
char * fExample3(char * aStr);
}
//functions.cpp

#include "functions.h"
#include <mathlink.h>
#include <stdio.h>
#include <ctype.h>


int fExample1(int x, int y)
{
    return (x >> y) + 1;
}

double fExample2(int * x, int xLen, double* y, int yLen)
{
    double result = 0.0;
    int i = 0;
    for (; i<xLen && i<yLen; ++i)
    {
        result += x[i] * y[i] ;
    }
    for (;i < yLen; ++i)
    {
        result += y[i];
    }
    return result ;
}

char * fExample3(char * aStr)
{
     for(char *p=aStr;*p;++p)
     {
         *p = toupper(*p) ;
     }
     return aStr ;
}


int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious,
LPSTR lpszCmdLine, int nCmdShow)
{
    char   buff[512];
    char FAR * buff_start = buff;
    char FAR * argv[32];
    char FAR * FAR * argv_end = argv + 32;
    hinstPrevious = hinstPrevious; /*suppress warning*/

    if( !MLInitializeIcon( hinstCurrent, nCmdShow)) return 1;
    MLScanString( argv, &argv_end, &lpszCmdLine, &buff_start);
    return MLMain( (int)(argv_end - argv), argv);
}

Once you have a MathLink program compiled to an executable, you can install it using Install. By default, Install will look in the current directory for the executable; either change the current directory or give Install the full path. Install returns a LinkObject, which can be used to get information about available functions and also to terminate the connection using Uninstall.

saveCurDir = Directory[] ;
SetDirectory[
  "oreilly\\Mathematica Cookbook\\code\mathLinkExample\\Debug"];
link =Install["mathLinkExample"];
SetDirectory[saveCurDir];

You can interrogate a link for the available functions.

LinkPatterns[link]
{fExample1[x_Integer, y_Integer],
 fExample2 [x_List, y_List], fExample3 [aStr_String]=

You call installed MathLink functions just like normal Mathematica functions.

fExample1[2000, 4]
126

fExample2 [{1, 2, 3}, {2.0, 4.0, 6.0, 8.0}]
36.

fExample3["Testing"]
TESTING

Uninstall[link]
mathLinkExample

Although the solution is fairly straightforward, there are numerous details that are specific to the OS and compilation environment (compiler and IDE or make system). The Mathematica documentation for MathLink contains detailed instructions for many common environments, and you should follow those directions carefully. It is highly recommended that you use either the example in the solution given or some of the simple examples that are installed with Mathematica to become familiar with the process before trying to interface your own C functions.

Often you will need to return objects more complex than integers and doubles from your C functions. If this is the case, you should specify a return type of Manual in the template file. Manual means that you will manually code the function to call the appropriate low-level MathLink C API functions needed to return the correct data to Mathematica.

//randomList.tm

#include <stdlib.h>
#include <mathlink.h>

:Begin:
:Function:      randomIntList
:Pattern:       randomIntList[n_Integer]
:Arguments:     {n}
:ArgumentTypes: {Integer}
:ReturnType:    Manual
:End:

extern "C" void randomIntList(int n)
{
    int* randData = new int [n] ;
    if (randData)
    {
        for(int i=0; i<n; ++i)
        {
            randData[i] = rand() ;
        }
        MLPutInteger32List(stdlink, randData , n);
        delete [] randData;
    }
    else
    {
       MLPutInteger32List(stdlink,0,0) ;
    }
}
saveCurDir = Directory[];
SetDirectory[
  "oreilly\\Mathematica Cookbook\\code\mathLinkExample2\\Debug"];
link2 = Install["mathLinkExample2"];
SetDirectory[saveCurDir];

LinkPatterns[link2]
{randomIntList[n_Integer]}

randomIntList[12]
{2287, 5306, 19 753, 3868, 19 313,
 1043, 29 879, 26846, 14625, 1380, 24555, 28439}

Uninstall[link2];

The example given illustrates the use of MLPutInteger32List to return an array of data as a list. The MathLink API contains many related functions for returning a variety of types, including integers, strings, lists, multidimensional arrays, and the like. This example also demonstrates that template files processed by mprep can mix source code with template directives.

Another common requirement is the need to execute initialization code once when you install the MathLink program. C-based initialization code can easily be added to the applications main() or WinMain(), but what about Mathematica code? A typical example is code that installs documentation for the installed functions. For this you use mprep’s :Evaluate: specifications. For an example of this see http://bit.ly/duSEnb.

Discussion

InstallJava takes options that control how the Java is loaded. CommandLine javapath allows you to specify the particular version of Java you want to load if you have several versions available. For example, CommandLine "c:\\Program Files\\Java \\jre1.6.0_07\\bin\\java". ClassPath classpath is used to provide a classpath that is different from the default obtained from the CLASSPATH environment variable. If you require special Java Virtual Machine (JVM) options, use JVMArguments arguments .

When InstallJava is invoked several times during a Mathematica session, the subsequent invocations are ignored. However, sometimes you want to clear out the old JVM and start fresh. In that case, use ReinstallJava to exit and reload Java. This is especially useful if you are making changes to a Java Archive (JAR) that you are developing alongside the Mathematica notebook that uses it. ReinstallJava takes the same options as InstallJava.

Discussion

The following example uses a genetic algorithm (GA) Java library called JGAP (see http://jgap.sourceforge.net/ ). GAs are in the class of evolutionary inspired algorithms typically used to tackle complex optimization problems. This example demonstrates an ideal blend of Mathematica and Java because it shows how easy it is to script a Java application and exploit the visualization features of Mathematica to investigate its behavior.

The example also illustrates the use of JavaBlock as a means of automatically cleaning up Java objects when they are no longer needed. It also shows how Java arrays of objects are replaced by Mathematica lists and how the translation is automated by JLink.

Discussion

I implement the problem using a function called knapsack, which takes an optional fitness function. The reason for this will become apparent later. Most of the code within knapsack is straightforward use of JLink facilities interspersed with standard Mathematica code. The comments in the code point out what’s going on, and much of the detail is specific to the JGAP library and the knapsack problem. One thing that might trip you up in your own Java-interfacing projects is dealing with Java arrays of objects. There is no JLink function specifically designed to construct arrays. Instead, wherever you need to call a Java function that expects an array, simply pass it a Mathematica list of objects created with JavaNew and Jlink will translate. Mathematica’s Table is convenient for that purpose and it is how the following code creates an array of Gene objects. Likewise, when calling a Java function that returns an array, expect Mathematica to convert it to a list.

knapsack[fitnessFunc_ : None] :=
  (*Use a JavaBlock to release all Java objects when block completes.*)
  JavaBlock[
   Module[{conf, fitnessFunc2, sampleGenes, sampleChromosome, population,
     individuals, bestSolutionSoFar, packing, volumeFound, dummy},
    (*JGAP uses a configuration object to organize the
     genetic algorithm's parameters and objects.*)
    LoadJavaClass["org.jgap.Configuration"];
    Configuration'reset[];
    conf = JavaNew["org.jgap.impl.DefaultConfiguration"];
  (*We want to preserve the fittest individual.*)
  conf @ setPreservFittestlndividual[True];
      (*The fitness function is
       implemented as a class in the example code.*)
      fitnessFunc2 = If[fitnessFunc === None,
        JavaNew["examples.knapsack.KnapsackFitnessFunction", targetVolume],
        JavaNew["jgapMathematica.FitnessFunction", fitnessFunc]] ;
      conf@setFitnessFunction[fitnessFunc2];
      (*In the original Java code sampleGenes is a Java array of class
       Gene. However, in Mathematica you create lists of objects, and the
       JLink code will take care of translating to arrays when necessary.*)
      sampleGenes = Table[JavaNew["org.jgap.impl.IntegerGene",
         conf, 0, Ceiling [0.75 targetVolume/itemVolumes [[i]]]],
        {i, 1, Length[itemVolumes]}];

      sampleChromosome = JavaNew["org.jgap.Chromosome", conf, sampleGenes];
      conf @ setSampleChromosome[sampleChromosome];
         conf @ setPopulationSize[popSize];
         LoadJavaClass["org.jgap.Genotype"];
         population = org'jgap'Genotype'randomInitialGenotype[conf];
         (*Let's run the evolution for 200 generations and
          capture the fittest at each generation. *)
         {dummy, {saveFitnessValues }} = Reap [Do [population @ evolve[];
            Sow [population@getFittestChromosome[] @getFitnessValue []],
            {generations}]];
         bestSolutionSoFar = population@getFittestChromosome[];
      Print ["Fitness of Best:", bestSolutionSoFar@getFitnessValue []];
      (*Here we decode the best solution to get the qty of each item.*)
      packing =
          Table [{bestSolutionSoFar@getGene [i] @ getAllele[],
            itemNames[[i + 1]]}, {i, 0, bestSolutionSoFar@size[] - 1}];
      Print["Packing found: ", packing];
        volumeFound = Total[packing[[All, 1]] * itemVolumes];
      Print["Volume used ", volumeFound];
        Print["Difference from desired volume: ", targetVolume - volumeFound];
        ]
       ]

Using a fairly healthy population size and a large number of generations, we unfortunately get a fairly poor solution! This indicates a problem with the design of our GA. Let’s see how we can draw on Mathematica to help resolve this.

Discussion

By plotting the logarithm of the fitness at each generation, we can see that the fitness landscape of this problem is extremely steep since we make a rapid transition from very low fitness to very high fitness. This suggests the fitness function provided with this JGAP sample might not be ideal. The poor quality of the solution is further indication of a poorly designed fitness function. The real lesson is that Mathematica is an ideal experimental playground for Java libraries because the full wealth of analytic and visual tools is at your disposal. In fact, I use Mathematica to help find a better fitness function, so read on.

Discussion

If you want to experiment with Java libraries, it is ideal to be able to implement interfaces defined by those libraries directly in Mathematica. In fact, this can be done rather easily using ImplementJavaInterface. The following example uses Implement-JavaInterface to try an alternate fitness function for the knapsack problem. There is a caveat, however. ImplementJavaInterface will only work with true interfaces, not abstract classes. In JGAP, FitnessFunction is an abstract class, hence we can’t implement it using ImplementJavaInterface. The solution in cases like this is to create an adapter like the one in the following listing.

package jgapMathematica;

import org.jgap.IChromosome;

public class FitnessFunction extends org.jgap.FitnessFunction {

    private IMathematicFitness m_fitness;

    public FitnessFunction(IMathematicFitness fitness) {
        m_fitness = fitness ;

    }

    @Override
    protected double evaluate(final IChromosome chromosome) {
        return m_fitness.evaluate(chromosome);
        }

}

The above fitness function allows us to use the following interface within Mathematica code.

package jgapMathematica;

import org.jgap.IChromosome;

public interface IMathematicFitness {
    public double evaluate(final IChromosome chromosome) ;
}

Once this is done, we can write any fitness function we like in pure Mathematica code. This solution is general in that any abstract class you find in any Java library can be adapted in a similar manner. Below, we exploit the adapter to write a new fitness function for the knapsack problem. The function penalizes solutions that use more volume than specified, while giving increasing reward to solutions that use close to the available volume.

Discussion
Discussion

Keep in mind that implementing interface in Mathematica code is convenient but comes at a very high cost. In our case, it makes the GA run much slower and forces the use of a much smaller population size. This is especially true because the fitness function is called many times, and it must call back into Java, making it extremely costly. This is not a real issue because the goal here is experimentation. When a reasonable fitness function is found, it can be ported back to Java. You can use the same methodology when working with other Java libraries. Of course, if the interface you implement in Mathematica is called infrequently, the hassle of porting back to Java may seem unnecessary.

Receiving numerical data back in string form is fine when you just want to display the result of a computation, but if you want to feed the results Mathematica returns into further computations, it is less than ideal. There are other ways to read the data returned by evaluation expressions, but these involve being cognizant of the types you expect back.

using System;
using Wolfram.NETLink;

namespace TestNetLink2
{

     public class TestNetLink2
     {

         public static void Main(String[] args)
         {

             //Launch the Mathematica Kernel
             IKernelLink ml = MathLinkFactory.CreateKernelLink();
             //Discard the initial response kernel will send when launched.
             ml.WaitAndDiscardAnswer();
             //Solve a differential equation and evaluate at the value 2.
             string expr = "s = NDSolve[{y''[x]+Sin[y[x]] y[x] == 0, y[0] ==
                1," +
                 "y'[0] == 0},y,{x, 0,30}]; y[2] /. s";
             //Evaluate expression. Notice this does not return anything.
             ml.Evaluate(expr);
             //Wait for results to be ready.
             ml.WaitForAnswer();
             //Read the result being sure to use the method that retrieves a

n

                appropriate
             //type. In this case, we expect a list of doubles but MathLink
                converts
             //these into arrays. Here you get the first element of the arra

y

                and can then
             //perform additional computations such as adding 10.
             double result = ml.GetDoubleArray()[0] + 10.0;
             Console.WriteLine("Result = " + result);
        }
    }
}

The IKernelLink interface has a variety of methods for retrieving typed results. These include GetBoolean, GetDouble, Getlnteger, GetString, GetDecimal, GetDouble-Array, and quite a few others. Refer to the NETLink documentation for the full set of methods.

In addition to IKernelLink, there is a very high-level interface to Mathematica implemented as a class called MathKernel that is ideal for creating a custom frontend to Mathematica. MathKernel derives from System.ComponentModel.Component and follows the conventions of .NET components. A nice example of using MathKernel can be found in the Mathematica installation directory ($InstallationDirectory) under SystemFiles/Links/NETLink/Examples/Part2/MathKernelApp.

You want to compute with data retrieved from an external database.

Note

Problem

The examples in 17.8 Querying a Database and 17.10 Introspection of Databases assume the existence of certain databases. If you don’t have access to a database system where you can set up these databases, the examples will obviously not work. If you have a database system or know how to install one, you can get files to initialize the database for these examples from the book’s website. Naturally, these examples are only for illustrating techniques that you can employ on real databases you wish to interface to Mathematica.

Mathematica supports several flavors of database connectivity, including ODBC, JDBC, MySQL, and HSQLDB (Hyper Structured Query Language Database).