Message Boards Message Boards

GROUPS:

Use .NETLink to call the MathNet library

Posted 9 years ago
4766 Views
|
0 Replies
|
4 Total Likes
|

Wolfram Language(WL) provides several useful interfaces to link itself to libraries written in other language. NETLink and JLink are such very powerful tools that bridge WL to the strong objective-oriented languages. I am going to show briefly an example about how to call a NuGet library for C sharp from WL.

http://www.mathdotnet.com/ is a project on NuGet that promotes the numerical computing power of C sharp. It does lots of things like what BLAS and LAPACK does for linear algebra and numeric solvers. Of course Mathematica and MATLAB(R) are much more mature products than this library. I use this library simply to show how you can call an external library.

I am writing this example with Mathematica 10 + Windows 7 + Visual Studio 2012.

  1. Follow this link http://numerics.mathdotnet.com/ to install the MathNet assembly into any open project or clone the git drive
  2. You can locate the assembly on your machine by right-clicking the entry in Solution Explorer (VS 2012): reference->MathNet.Numeric->Properties

enter image description here

Now you can open Mathematica and load the .NETLink package.

Needs["NETLink`"]

You can launch the runtime link connection with

InstallNET[]

Assume things are going well, here is what you see:

enter image description here

If you have targeted the location of MathNet.Numerics.dll in your project, you can load the assembly with LoadNETAssembly

LoadNETAssembly["MathNet.Numerics","C:\\Users\\shenghui\\...myCSharpProj1\\packages\\MathNet.Numerics.3.2.3\\lib\\net40\\"]

Of course your absolute path may be different, here it is just my location to store the dll file. As in the VS2012, you have a xml tree about the build-in classes and objects in this MathNet package:

enter image description here

The same view can be generated within Mathematica by NETTypeInfo function:

enter image description here

http://numerics.mathdotnet.com/docs/ provides the following example code ( Using's are omitted ):

Matrix<double> A = DenseMatrix.OfArray(new double[,] {
        {1,1,1,1},
        {1,2,3,4},
        {4,3,2,1}});
Vector<double>[] nullspace = A.Kernel();

This is where Mathematica has to call a different method. The Vector generic type is valid and can be loaded into Mathematica without problem:

In:= netType=LoadNETType["MathNet.Numerics.LinearAlgebra.Vector<int>"]
Out:= NETType[MathNet.Numerics.LinearAlgebra.Vector`1[System.Int32],16]

However NETNew cannot create a vector object:

enter image description here

because there is no constructor with this type. The workaround is from taking a look at class list of the NETTypeInfo of the MathNet assembly:

enter image description here

NETInfo[assem, "Classes", "*Dense*"] is a call of such funciton with pattern match. I use this function when I notice that the C Sharp code in the online example calls the Dense.Build method to create a dynamic (a fancy way of using new) vector or matrix object. The dense method stores every item of the array. Contrary, the sparse method only store the non-zero entries.

The ....DenseVector type contains public constructors:

enter image description here

(Notice that NETTypeInfo can take the string name of the class/type/assembly as well)

To create a vector in the runtime, you just put a regular Mathematica vector of real numbers into the place of arguments:

In:= a = NETNew[ "MathNet.Numerics.LinearAlgebra.Double.DenseVector", {1, 2, 3, 4}] 
Out:= <<NETObject[MathNet.Numerics.LinearAlgebra.Double.DenseVector]>>

In:= b = NETNew[ "MathNet.Numerics.LinearAlgebra.Double.DenseVector", 10] 
Out:= <<NETObject[MathNet.Numerics.LinearAlgebra.Double.DenseVector]>>
(* b is {0,0,...,0} *)

In:= c = NETNew["MathNet.Numerics.LinearAlgebra.Double.DenseMatrix", 2, 2, {1,2,3,4}]
Out:= <<NETObject[MathNet.Numerics.LinearAlgebra.Double.DenseMatrix]>>
(* c is a col-major matrix: {{1,3},{2,4}}*)

To get the result back to Mathematica, use the method associated with these types:

 In:= a@ToArray[]
 Out= {1.,2.,3.,4.}

 In:= c@ToArray[]
 Out= {{1.,3.},{2.,4.}}

I can do this because the return type of the ToArray is double[] or double[,], which are basic System type in C sharp and Mathematica can convert these type to Real automatically. One more thing to say here is that Mathematica kernel is smart enough to avoid namespace/context clashing:

In:= res=(c@Transpose[])@Inverse[] (*MathNet's Transpose and Inverse*)
Out= « NETObject[MathNet.Numerics.LinearAlgebra.Double.DenseMatrix]»

Check the result:

In:= res@ToArray[]
Out= {{-2.,1.},{1.5,-0.5}}

which is the same as the familiar Mathematica implementation:

In:= Inverse[Transpose[c@ToArray[]]] (*the Mathematica Inverse and Transpose*)
Out= {{-2.,1.},{1.5,-0.5}}
POSTED BY: Shenghui Yang
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract