7
$\begingroup$

What List-like structures in Python can Wolfram Client handle and how can support for new structures be added?

In this answer I describe how to execute from Python, code in a Mathematica package that that has been compiled to C.

One such compiled function for test purposes is this:

compiledTestFunction2 = 
    Compile[{{n, _Real, 1}, {m, _Real, 1}},
        Module[{},
            Cross[n, m]
        ],
        CompilationTarget->"C", "RuntimeOptions"->"Speed"];

(Cross[] is compilable). This function is called from Python by defining

compiledTestFunctionPython2 = session.function('compiledTestFunction2')

And the function is invoked as

compiledTestFunctionPython2(thing1, thing2)

Using Wolfram Language functions via Wolfram Client to Wolfram Engine we obtain a reference result:

thing1 = array.array('f', [1,2,3])
thing2 = array.array('f',[2,3.3,7])
session.evaluate(wl.Cross(thing1, thing2))
PackedArray([ 4.1, -1. , -0.7])

We obtain the correct answer if we define thing1 and thing2 as Python:

  • Lists e.g. [1, 2, 3]
  • Arrays e.g. array.array('f', [1, 2, 3])
  • Tuples e.g. (1, 2, 3), and even
  • Sets e.g. set([1, 2, 3]) despite the lack of ostensible order to sets

but Numpy arrays are not supported. Attempting to use a Numpy array such as

thing1 = np.array([1.0, 2.0, 3.0])

causes the compiled function to be returned unevaluated with the error:

Argument … at position 1 should be a rank 1 tensor of machine-size real numbers.

Questions What array types does Wolfram Client handle and could support for other structures such as Numpy arrays be added; if so, how? (The documentation says Numpy is supported, but does it work for compiled functions?)

And although PackedArray([...]) is returned by default, is there any choice in the matter?

Update on passing in 26/11/2019

By trying to force Numpy arrays to be of a particular data type, using

thing1 = np.array([1.0, 2.0., 3.0], dtype = np.float16)

we discover, from the Not Supported Error for dtype('float16'), that Wolfram Client serialisation (in \wolframclient\serializers\encoders\numpy.py) supports the following: int8, int16, int32, int64, uint8, uint16, uint32, uint64, float32, float64, complex64, complex128

However, no explicit float choices are acceptable to the compiled function.

It looks as though any existing numpy array must be coerced back to some other form, and after a few experiments it seems that the most efficient way is e.g.

thing1 = np.array([1.0, 2.0, 3.0], dtype = np.float64)
thing1 = array.array('d', thing1)

but the differences between array, list and tuple are small.

Update on receiving back 26/11/2019

According to the documentation here

By default, packed arrays are deserialized as list. Specify a consumer instance that supports NumPy arrays WXFConsumerNumpy

If one then prepares a session with

session = WolframLanguageSession(kernelLoc, consumer=WXFConsumerNumpy())

then my compiled function that returns a 1D (table) of reals appears back in Python as class 'wolframclient.utils.packedarray.PackedArray' - not numpy array. Why?

I have yet to find the list of deserializers.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.