Capital-pi notation¶


  • Author: Diego Inácio
  • GitHub: github.com/diegoinacio
  • Notebook: capital-pi-notation.ipynb

Brief notes and practical examples with the product operator.

In [1]:
import numpy as np

Product notation¶


From the Greek alphabet, the capital Pi letter, represented by the symbol $\large \Pi$, is mathematical notation for product. This operator has as function the product or multiplication of multiples elements of a sequence. It is commonly associated to another mathematical symbol (greek capital Sigma, $\large \Sigma$), but its functionality is easily memorized by the sound of the word "product": Ppproduct = Pppi.

$$ \large \prod_{i=m}^n x_i = x_m \cdot x_{m+1} \cdot x_{m+2} \cdot \cdots \cdot x_{n-2} \cdot x_{n-1} \cdot x_{n} $$

where:

  • $i$ is the index of product;
  • $m$ is the lower bound of product;
  • $n$ is the upper bound of product;
  • $x_i$ is the indexed variable.

For example, given the explicit sequence [1, 3, 7, 9, 13], the summation of all 5 elements is denoted as:

$$ \large \begin{aligned} \prod_{i=1}^5 x_i &= x_1 + x_2 + x_3 + x_4 + x_5 \\ &= 1 \cdot 3 \cdot 7 \cdot 9 \cdot 13 \\ &= 2457 \end{aligned} $$
In [2]:
seq = [1, 3, 7, 9, 13]

result = 1
for x in seq:
    result *= x

print(result)
2457

Notice that in many algorithms the lower and the upper bounds are represented by the interval $[0,N-1]$, which denote the index bound of a digital array. Although, the main idea is still the same.

$$ \large \prod_{k=0}^{N-1} = \prod_{k}^N $$
In [3]:
x = [1, 3, 7, 9, 13]

result = x[0] * x[1] * x[2] * x[3] * x[4]

print(result)
2457

The library Numpy has a very convenient method that makes the summing process easier and much more readable.

In [4]:
x = np.array([1, 3, 7, 9, 13])

result = x.prod()  # or np.prod(x)

print(result)
2457

Multidimensional¶


This operator can be nested:

$$ \large \begin{aligned} \prod_{i=2}^4 \prod_{j=5}^6 (i + j) &= [(2 + 5) \cdot (2 + 6)] \cdot [(3 + 5) \cdot (3 + 6)] \cdot [(4 + 5) \cdot (4 + 6)] \\ &= (7 \cdot 8) \cdot (8 \cdot 9) \cdot (9 \cdot 10) \\ &= 56 \cdot 72 \cdot 90 \\ &= 362880 \end{aligned} $$
In [5]:
result = 1
for i in range(2, 4+1):
    for j in range(5, 6+1):
        result *= i + j

print(result)
362880

Nested product are very commonly used to notate multidimensional isotropic or anisotropic objects. For example, given the matrix:

$$ \large M = \begin{bmatrix} 1 & 2 \\ 2 & 3 \\ 3 & 4 \end{bmatrix} $$

The product of all elements can be expressed as:

$$ \large \begin{aligned} \prod_i^M \prod_j^N M_{ij} &= 1 \cdot 2 \cdot 2 \cdot 3 \cdot 3 \cdot 4 \\ &= 144 \end{aligned} $$
In [6]:
matrix = np.array([
    [1, 2], 
    [2, 3], 
    [3, 4]
])

M = len(matrix)
N = len(matrix[0])

result = 1
for i in range(M):
    for j in range(N):
        result *= matrix[i][j]

print(result, np.prod(matrix))
144 144

Properties¶


Follow some basic properties and identities.

  • If all elements are identical, the product is the same as exponentiation:
$$ \large \prod_i^N x_i = \prod_i^N x = x \cdot x \cdot ... \cdot x = x^N $$
In [7]:
x = 10
N = 4

print(np.prod([x for _ in range(N)]))
print(x**N)
print(np.prod([x]*N))
10000
10000
10000
  • The commutativity and associative properties are denoted as:
$$ \large \prod_i^N x_i \cdot y_i = \left(\prod_i^N x_i\right) \cdot \left(\prod_i^N y_i\right) $$
In [8]:
x = np.array([1, 20, 3, 40])
y = np.array([10, 2, 30, 4])

print(np.prod(x) * np.prod(y))
print(np.prod(x * y))
5760000
5760000

Examples¶


Follow some example of product operator applications.

  • Factorials: One of the most common application of the product operator is in factorials, where:
$$ \large n! = \prod_{k=0}^{n-1}=n \cdot (n-1) \cdot (n-2) \cdot \dots \cdot 2 \cdot 1 $$
In [9]:
n = 5
N = np.arange(n) + 1

print(np.prod(N))
120

Infinity product: An infinite product is when the upper bound is infinity and its product result converges to a known theoretical number. For example, the John Wallis product:

$$ \large \lim_{k \rightarrow \infty} \prod_{n=1}^k \frac{4n^2}{4n^2 - 1} = \frac{\pi}{2} $$
In [10]:
N = np.arange(1e6) + 1.

result = np.prod(4*N**2/(4*N**2 - 1))

print(result, np.pi/2)
1.5707959340960744 1.5707963267948966