∀ Discrete mathematics

Power set and Cartesian product, clearly explained

What the power set and Cartesian product are, why they have 2^n and n·m elements, and how they apply to permissions, configurations and testing.

Union and intersection combine sets while staying "at the same level". There are, however, two constructions that produce new and much larger sets: the power set, which collects all subsets, and the Cartesian product, which forms all possible pairs. They underlie concepts such as relations, functions and configuration spaces, and they explain why certain problems grow so quickly.

The power set

The power set of A, written 𝒫(A) or 2ᴬ, is the set of all subsets of A, including the empty set and A itself.

If A = {r, w, x}:

𝒫(A) = {∅, {r}, {w}, {x}, {r, w}, {r, x}, {w, x}, {r, w, x}}

There are 8 elements. In general, if |A| = n, then |𝒫(A)| = 2ⁿ.

Why 2ⁿ

Building a subset means making, for each element of A, a binary decision: in or out. There are n independent decisions, so the combinations number 2 · 2 · … · 2 = 2ⁿ.

This reasoning also suggests a very practical representation: a subset of an n-element set can be encoded as a string of n bits. With the order r, w, x, the string 101 represents {r, x} and 000 the empty set. That is exactly how Unix permissions are stored: read, write and execute are three bits, and permission 5 in octal, 101 in binary, means "read and execute".

Enumerating all subsets

The correspondence with binary numbers gives an algorithm straight away:

def power_set(elements):
    n = len(elements)
    for mask in range(2 ** n):
        yield {elements[i] for i in range(n) if mask >> i & 1}

list(power_set(["r", "w", "x"]))

The loop counts from 0 to 2ⁿ − 1 and, for each number, includes the elements whose bits are set. It works well while n is small: with 30 elements there are more than a billion subsets. That is why algorithms that try "every combination" quickly become impractical.

The Cartesian product

The Cartesian product of A and B is the set of all ordered pairs (a, b) with a ∈ A and b ∈ B:

A × B = {(a, b) | a ∈ A, b ∈ B}

In an ordered pair the order matters: (1, 2) ≠ (2, 1). And, unlike sets, repetition is allowed: (3, 3) is a valid pair.

If A = {S, M, L} (sizes) and B = {black, white} (colours):

A × B = {(S, black), (S, white), (M, black), (M, white), (L, black), (L, white)}

There are 3 · 2 = 6 pairs. In general |A × B| = |A| · |B|.

More than two factors

The product extends to n sets, producing n-tuples: A₁ × A₂ × … × Aₙ. A row in a three-column database table is an element of D₁ × D₂ × D₃, where Dᵢ is the domain of values of each column. The Cartesian plane is ℝ × ℝ, and an IPv4 address is an element of {0, …, 255}⁴, a set with 256⁴ = 2³² elements.

The Cartesian product in SQL

A CROSS JOIN between two tables produces exactly the Cartesian product of their rows. With tables of 1,000 and 2,000 rows you get 2 million rows. A JOIN written without its linking condition has the same effect, and it is a classic mistake that makes query execution times explode.

Cartesian products and testing

When software has several configuration parameters, the space of all configurations is their Cartesian product. With a choice of 3 operating systems, 4 browsers and 5 languages, there are 3 · 4 · 5 = 60 combinations.

Testing them all is feasible; with ten parameters of five values each it no longer is (5¹⁰ is almost ten million). That is why techniques such as pairwise testing are used: you choose a subset of the Cartesian product in which every pair of values of different parameters appears at least once. Many defects depend on the interaction of just two parameters, and this approach catches them with far fewer tests.

Power set and product compared

Power set Cartesian product
Elements subsets of A pairs (a, b)
Cardinality 2ⁿ n · m
Growth exponential polynomial
Example permission combinations product variants

There is also a deep link: a relation between A and B is defined as a subset of A × B, that is, an element of 𝒫(A × B). The possible relations between two 3-element sets therefore number 2⁹ = 512.

In short

  • The power set contains every subset and, if |A| = n, has 2ⁿ elements.
  • Each subset can be encoded with n bits, like Unix permissions.
  • The Cartesian product contains every ordered pair and has |A| · |B| elements.
  • A CROSS JOIN, or a JOIN without a condition, produces the Cartesian product of the rows.
  • A relation is a subset of the Cartesian product.
MM
Marco Marzaduri

Marco Marzaduri works in cybersecurity, digital forensics and web development. A computer science graduate, he combines rigorous technical analysis with attention to the people who use technology.

Read also