tags:

views:

200

answers:

5

Python does not provide built-in support for multi-dimensional arrays. I need to develop an 11-dimensional array and a set of functions to operate on it (mostly linear algebra, vector arithmetics). However, no external library import is allowed. I have a code in C and trying to port it to Python:

typedef vec3_t float[3];
vec3_t Array[dim0][dim1][dim2][dim3][dim4][dim5][dim6][dim7][dim8][dim9][dim10];
Array[0][0][0][0][0][0][0][0][0][0][1] = {1.0, 0.0, 0.0};

How can it be implemented in Python effectively (with good readability)?

PS: For Python 2.5 version at most.

+2  A: 

I've written a Matrix class here:

Multidimensional array in Python

It can be used like this:

m = Matrix(4,5,2,6)
m[2,3,1,3] = 'x'
m[2,3,1,3] // -> 'x'
Georg
+5  A: 

With so many dimensions, and no library imports allowed, I'd go (as the basic choice) for a dictionary indexed by tuples. This way, you get very nice syntax for simple indexing:

Array = dict()
Array[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] = [1.0, 0.0, 0.0]

You'll probably want to wrap it in a class to add functionality beyond simple indexing, but, not knowing what it is that you want beyond that (initialization/defaults? slicing? iteration? etc, etc...), it's just too hard to guess. If you can specify precisely all that you want to do with that "multi-dimensional array", it shouldn't be hard to show you the code that best provides it!

Alex Martelli
I need later different matrix-multiplications, vector arithmetics
psihodelia
@psihodelia: In that case your options are limited to using numpy (external library), finding a library on the internet or code it yourself.
Georg
I'm not sure how a "later different" matrix multiplication differs from a normal one (nor even exactly how matrix multiplication is defined on 11-dimensional arrays, to be honest!-), nor exactly what "vector arithmetics" you need to perform on 11-dimensional arrays. If you can code it in C (or pseudo-code, for that matter), you can code it in Python, of course, and probably more concisely too... -- but, it **is** still going to be a lot of coding, just to avoid importing any existing module. Why, exactly, can't you import some pure-python library like `pyarray` and save yourself some work?-)
Alex Martelli
Alex Martelli
A: 

"Multi-dimension" is just a fancy term to mean "many memory locations". If you look at it in a broader sense, they are just really "1 dimensional". Anyway, to suggest an alternative, you can use dictionaries.

>>> d={}
>>> d[0]={}
>>> d[0][0]="1"
>>> d[0]
{0: '1'}

Create your dicts this way to your "11"th dimension.

+1  A: 

Another possibility would be to create a 1-dimensional array and then read/write it using functions that take 11 index arguments. You multiply out the indices (based on the max for each dimension) to calculate a position in the array. The get/set functions themselves won't be all that pretty (with 11 indices) but once you have them written, getting and setting array indices will look almost as clean as it does in C. I'm not sure how performance would compare to that of nested lists but my guess is that it would be favorable.

The basic concept can be shown with 2 dimensions:

def readArray2(arr,i1,i2,dim2):
    index = i1 * dim2 + i2
    return arr[index]

It gets more complicated with more dimensions, though:

def readArray3(arr,i1,i2,i3,dim2,dim3):
    index = i1 * dim2 * dim3 + i2 * dim3 + i3
    return arr[index]

And so on for larger arrays. You could generalize this to a variable number of dimensions. I'd probably put the indices and dimensions into lists and then iterate over them.

Nate C-K
+1  A: 

A potentially very legible solution, though probably performance-poor, would use a dict with eleven-element tuples as keys:

>>> d[0,1,2,3,4,5,6,7,8,9,0] = [1.0, 0.0, 0.0]

This also allows you to store the coordinate vectors and pass them around as single objects:

>>> coord = (0,1,2,3,4,5,6,7,8,9,0)
>>> d[coord]
[1.0, 0.0, 0.0]

You could enforce key integrity by either using your own class or a subclass of dict:

>>> class Space(dict):
>>>     def __setitem__(self, key, value):
>>>         if len(key) == 11:
>>>             dict.__setitem__(self, key, value)
>>>         else:
>>>             raise IndexError("Keys must be eleven-dimensional vectors.")

You could improve performance by using your own class with the same __getitem__/__setitem__ interface, but that need not even be done at first.

eswald