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}},
            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.



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.