0

I often work with multidimensional arrays whose array indices are generated from a complicated user-specified set.

I'm looking for a library with classes for representing complicated sets with an arbitrary number of indices, and arbitrarily complicated predicates. Given a set description, the desired output would be a generator. This generator would in turn produce either dicts or tuples which correspond to the multidimensional array indices.

Does such a library exist?


Example

Suppose we had the following user-specified set (in set-builder notation), which represents the indices of some array variable x[i][j]:

{i in 1..100, j in 1..50: i >= 20, j >= 21, 2*(i + j) <= 100}

I'd like to put this into some sort of a lazy class (a generator expression perhaps) that will allow me to lazily evaluate the elements of the set to generate the indices for my array. Suppose this class were called lazyset; this would be the desired behavior:

>>> S = lazyset("{i in 1..100, j in 1..50: i >= 20, j >= 21, 2*(i+j) <= 100}")
>>> S
<generator object <genexpr> at 0x1f3e7d0>
>>> next(S)
{'i': 20, 'j': 21}
>>> next(S)
{'i': 20, 'j': 22}

I'm thinking I could roll my own using generator expressions, but this almost seems like a solved problem. So I thought I'd asked if anyone's come across an established library that handles this (to some extent, at least). Does such a library exist?

Gilead
  • 1,263
  • 10
  • 21

2 Answers2

2

This looks more like a constraint-solver problem to me:

import constraint as c

p = c.Problem()
p.addVariable(0, range(1,101))
p.addVariable(1, range(1,51))
p.addConstraint(lambda i: i >= 20, [0])
p.addConstraint(lambda j: j >= 21, [1])
p.addConstraint(c.MaxSumConstraint(50))

indices = ((s[0], s[1]) for s in p.getSolutionIter())  # convert to tuple generator

then if you do

for ij in indices:
    print ij

you get

(29, 21)
(28, 22)
(28, 21)
(27, 23)
(27, 22)
(27, 21)

...

(20, 25)
(20, 24)
(20, 23)
(20, 22)
(20, 21)
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • That is a certainly a creative idea! I hadn't thought of using a constraint solver to build the set. I can already see applications of python-constraint in other parts of my code. I'm just wondering however, if there was a more lightweight way of doing this, because I'm just looking to iterate through the indices, and then checking each index against all the predicates; if the particular index satisfies all the predicates, accept it, and if not reject it. I'm just wondering if the constraint-solver algorithm reduces to this case of affairs. Either way, it's a very creative idea! – Gilead Jun 20 '12 at 14:08
  • @Gilead: `constraint` will evaluate each constraint as soon as the required variables are defined; in the worst case (all constraints depend on all variables), that is precisely what it reduces to. – Hugh Bothwell Jun 20 '12 at 14:49
0

Although I am not certain if this specifically (the set-builder notation) is supported by scipy. I think scipy is your best bet regardless.

There is support for sparse arrays/sets in scipy so you can easily let it handle the allocation of those without actually allocating the space :)

Wolph
  • 78,177
  • 11
  • 137
  • 148
  • Thanks for your input, that certainly is an option that I hadn't thought of! However, I'm thinking of using generators because I don't intend to store these indices. I just want an iterable object that I can run `for` loops over. – Gilead Jun 20 '12 at 14:02