[Python-ideas] Support multiplication for sets

Terry Reedy tjreedy at udel.edu
Sat Oct 8 02:57:33 CEST 2011


On 10/7/2011 7:20 AM, Paul Moore wrote:
> On 7 October 2011 11:37, Jakob Bowyer<jkbbwr-Re5JQEeQqe8AvxtiuMwx3w at public.gmane.org>  wrote:
>> There is that but from a math point of view the syntax a * b does make
>> sence.
>> Its slightly clearer and makes more sense to people from outside of a
>> programming background.

Math used a different symbol, an 'X' without serifs, for cross-products. 
The result is a set of 'ordered pairs', which is different from a duple.

> I'm not sure I'd agree, even though I come from a maths background.
> Explicit is better than implicit and all that...
>
> Even if it is slightly clearer to some people, I bet there are others
> (not from a mathematical background) who would be confused by it. And
> in that case, itertools.product is easier to google for than "*"...)
> And that's ignoring the cost of implementing, testing, documenting the
> change.
>
> Actually, just to give a flavour of the sorts of design decisions that
> would need to be considered, consider this:
>
>>>> a = set((1,2))
>>>> b = set((3,4))
>>>> c = set((5,6))
>>>> from itertools import product
>>>> def times(s1,s2):
> ...    return set(product(s1,s2))
> ...
>>>> times(a,times(b,c))
> {(1, (3, 6)), (2, (3, 5)), (2, (4, 5)), (1, (4, 6)), (1, (4, 5)), (2,
> (3, 6)), (2, (4, 6)), (1, (3, 5))}
>>>> times(times(a,b),c)
> {((2, 4), 6), ((1, 4), 5), ((1, 4), 6), ((2, 3), 6), ((1, 3), 6), ((2,
> 3), 5), ((2, 4), 5), ((1, 3), 5)}
>>>>
>
> So your multiplication isn't commutative

It is not *associative* -- unless one special-cases tuples to add 
non-tuple elements to tuple elements.

> (the types of the elements in
> the 2 expressions above are different).

If the elements of A*B are sequences, then A*B is also not commutative. 
But it would be if the elements were sets instead of pairs.

> That doesn't seem intuitive -
> so maybe a*b*c should be a set of 3-tuples. But how would that work?

In math, *...* is a ternary operator with 3 args, like if...else in 
Python or ;...: in C, but it generalizes to an n-ary operator. From
https://secure.wikimedia.org/wikipedia/en/wiki/Cartesian_product
'''
The Cartesian product can be generalized to the n-ary Cartesian product 
over n sets X1, ..., Xn:

     X_1\times\cdots\times X_n = \{(x_1, \ldots, x_n) : x_i \in X_i \}.

It is a set of n-tuples. If tuples are defined as nested ordered pairs, 
it can be identified to (X1 × ... × Xn-1) × Xn.'''

In other words, think of aXbXc as XX(a,b,c) and similarly for more Xs. 
In Python, better to define XX explicitly. One can even write the n-fold 
generalization by simulating n nested for loops.

> The problem very quickly becomes a lot larger than you first assume.
>
> Operator overloading is used much more sparingly in Python than in,
> say, C++. It's as much a language style issue as anything else.
>
> Sorry, but I still don't see enough benefit to justify this.

In most situations, one really needs an iterator that produces the pairs 
one at a time rather than a complete collection. And when one does want 
a complete collection, one might often want it ordered as a list rather 
than unordered as a set. Itertools.product covers all these use cases. 
And even that does not cover the n-ary case.

For many combinatorial algorithms, one need a 'cross-concatenation' 
operator defined on collections of sequences which adds the pair of 
sequences in each cross-product pair. The same 'x' symbol, possibly 
circled, has been used for that. Both are in unicode, but Python is 
currently restricted to a sparse set of ascii symbols.

-- 
Terry Jan Reedy





More information about the Python-ideas mailing list