# Cartesian Products¶

sage.combinat.cartesian_product.CartesianProduct(*iters)

This is deprecated. Use cartesian_product instead.

EXAMPLES:

sage: cp = CartesianProduct([1,2], [3,4]); cp
doctest:...: DeprecationWarning: CartesianProduct is deprecated. Use
See http://trac.sagemath.org/18411 for details.
The Cartesian product of ({1, 2}, {3, 4})
sage: cp.list()
[(1, 3), (1, 4), (2, 3), (2, 4)]


Note that you must not use a generator-type object that is returned by a function (using “yield”). They cannot be copied or rewound (you cannot jump back to the beginning), but this is necessary to construct the Cartesian product:

sage: def a(n): yield 1*n; yield 2*n
sage: def b(): yield 'a'; yield 'b'
sage: CartesianProduct(a(3), b()).list()
Traceback (most recent call last):
...
ValueError: generators are not allowed, see the
documentation (type "CartesianProduct?") for a workaround


The usage of iterable is also deprecated, so the following will no longer be supported:

sage: from sage.combinat.misc import IterableFunctionCall
sage: C = CartesianProduct(IterableFunctionCall(a, 3), IterableFunctionCall(b))
doctest:...: DeprecationWarning: Usage of IterableFunctionCall in
CartesianProduct is deprecated. You can use EnumeratedSetFromIterator
See http://trac.sagemath.org/18411 for details.
sage: list(C)
doctest:...: UserWarning: Sage is not able to determine whether the
factors of this Cartesian product are finite. The lexicographic ordering
might not go through all elements.
[(3, 'a'), (3, 'b'), (6, 'a'), (6, 'b')]


You might use EnumeratedSetFromIterator for that purpose.:

sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator
sage: A = EnumeratedSetFromIterator(a, (3,), category=FiniteEnumeratedSets())
sage: B = EnumeratedSetFromIterator(b, category=FiniteEnumeratedSets())
sage: C = cartesian_product([A, B])
sage: C.list()
[(3, 'a'), (3, 'b'), (6, 'a'), (6, 'b')]

class sage.combinat.cartesian_product.CartesianProduct_iters(*iters)

Cartesian product of finite sets.

This class will soon be deprecated (see trac ticket #18411 and trac ticket #19195). One should instead use the functorial construction cartesian_product. The main differences in behavior are:

• construction: CartesianProduct takes as many argument as there are factors whereas cartesian_product takes a single list (or iterable) of factors;
• representation of elements: elements are represented by plain Python list for CartesianProduct versus a custom element class for cartesian_product;
• membership testing: because of the above, plain Python lists are not considered as elements of a cartesian_product.

All of these is illustrated in the examples below.

EXAMPLES:

sage: F1 = ['a', 'b']
sage: F2 = [1, 2, 3, 4]
sage: F3 = Permutations(3)
sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: C = CartesianProduct_iters(F1, F2, F3)
sage: c = cartesian_product([F1, F2, F3])

sage: type(C.an_element())
<... 'list'>
sage: type(c.an_element())
<class 'sage.sets.cartesian_product.CartesianProduct_with_category.element_class'>

sage: l = ['a', 1, Permutation([3,2,1])]
sage: l in C
True
sage: l in c
False
sage: elt = c(l)
sage: elt
('a', 1, [3, 2, 1])
sage: elt in c
True
sage: elt.parent() is c
True

cardinality()

Returns the number of elements in the Cartesian product of everything in *iters.

EXAMPLES:

sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: CartesianProduct_iters(range(2), range(3)).cardinality()
6
sage: CartesianProduct_iters(range(2), range(3)).cardinality()
6
sage: CartesianProduct_iters(range(2), range(3), range(4)).cardinality()
24


This works correctly for infinite objects:

sage: CartesianProduct_iters(ZZ, QQ).cardinality()
+Infinity
sage: CartesianProduct_iters(ZZ, []).cardinality()
0

is_finite()

The Cartesian product is finite if all of its inputs are finite, or if any input is empty.

EXAMPLES:

sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: CartesianProduct_iters(ZZ, []).is_finite()
True
sage: CartesianProduct_iters(4,4).is_finite()
Traceback (most recent call last):
...
ValueError: Unable to determine whether this product is finite

list()

Returns

EXAMPLES:

sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: CartesianProduct_iters(range(3), range(3)).list()
[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
sage: CartesianProduct_iters('dog', 'cat').list()
[['d', 'c'],
['d', 'a'],
['d', 't'],
['o', 'c'],
['o', 'a'],
['o', 't'],
['g', 'c'],
['g', 'a'],
['g', 't']]

random_element()

Returns a random element from the Cartesian product of *iters.

EXAMPLES:

sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: CartesianProduct_iters('dog', 'cat').random_element()
['d', 'a']

unrank(x)

For finite Cartesian products, we can reduce unrank to the constituent iterators.

EXAMPLES:

sage: from sage.combinat.cartesian_product import CartesianProduct_iters
sage: C = CartesianProduct_iters(range(1000), range(1000), range(1000))
sage: C[238792368]
[238, 792, 368]


Check for trac ticket #15919:

sage: FF = IntegerModRing(29)
sage: C = CartesianProduct_iters(FF, FF, FF)
sage: C.unrank(0)
[0, 0, 0]

sage.combinat.cartesian_product.isgenerator(obj)