**Combinatorial generation** # Combinatorial generation - "Combinatorics is the study of the ways in which discrete objects can be arranged into various kinds of patterns." wrote Donald Knuth in _The Art of Computer Programming, Vol 4A, Combinatorial Algorithms, Part 1._ - In this lecture note we will touch on the fascinating subject of _Combinatorial Generation_. - Generating a combinatorial object is the basis of various algorithms. - Backtracking can be viewed as a modification of the regular algorithm for generating combinatorial objects. Backtracking takes an algorithm for generating a certain type of combinatorial object and modifies it so that only objects satisfying certain constraints are generated. # Permutations - Let $S$ be a finite set. A permutation on $S$ is a 1-1 and onto function from $S$ into itself. Put simply, it's an arrangement of all the elements of $S$ in a line, taking order into consideration. E.g. if $S = \{ a, b, c \}$ then $bca$ is a permutation of $S$ and $cab$ is another. In fact, these are all the possible permutations of $S$ + $a b c$ + $a c b$ + $b a c$ + $b c a$ + $c a b$ + $c b a$ - E.g., in the $n$-queen puzzle every valid placement of $n$ queens on the $n\times n$ chessboard can be described as a permutation $pi$ of the set $\{ 0, 1, \ldots, n-1 \}$ such that placing queen of row $i$ at column $pi(i)$ for all $0\le i\lt n$, does not put any two queens on mutually-attacking squares. The program `nQueensRandomized.kt` demonstrated in class uses backtracking for the n-queen puzzle in this way. It takes the basic algorithm for generating the permutations on $\{0,1,\ldots, n-1\}$ and modifies it so that any branch of the permutation generation algorithm that will generate a mutually-attacking queen pair is abandoned. # Algorithm to generate all permutations - Here is an algorithm to generate all the permutations on the set $\{ 0, 1, \dots, n-1 \}$. ```kotlin fun main(args: Array< String >) { val n = args[0].toInt() val a = IntArray(n) { it } fun swap(i: Int, k: Int) { val temp = a[i] a[i] = a[k] a[k] = temp } fun perm(k: Int) { if (k == n) println(a.joinToString(separator=" ")) else for (i in k until n) { swap(i, k) perm(k+1) swap(i, k) } } perm(0) } ``` # Combinations - Let $S$ be a finite set. A $k$-combination of $S$ is a subset of $S$ of size $k$. - E.g., if $S = \{a, b, c, d\}$, then all the 2-combinations of $S$ are + $a b$ + $a c$ + $a d$ + $b c$ + $b d$ + $c d$ - Note that order of symbols does not matter in the above listing: $ab$ or $ba$ means the same subset. # Algorithm to generate all k-combinations - Here is an algorithm to generate all the $k$-combinations of the set $\{ 0, 1, \dots, n-1 \}$. ```kotlin fun main(args: Array< String >) { val n = args[0].toInt() val k = args[1].toInt() val b = BooleanArray(n) // Precondition: i is one more than the count of already chosen elements fun comb(start: Int, i: Int) { if (i == k+1) { for (j in b.indices) if (b[j]) print(" $j") println() } else for (j in start until (n-k+i)) { b[j] = true comb(j+1, i+1) b[j] = false } } comb(0, 1) } ``` # Subsets - Let $S$ be a finite set. A subset of $S$ is any set $T$ such that every member of $T$ is also a member of $S$. - E.g., if $S = \{ 0, 1, 2 \}$ then the subsets of $S$ are + $\emptyset$ + $0$ + $1$ + $2$ + $0 1$ + $0 2$ + $1 2$ + $0 1 2$ where order does not matter in the above listing. # Algorithm to generate all subsets of a given set - Here is an algorithm to generate all the subsets of the set $\{ 0, 1, \dots, n-1 \}$. ```kotlin fun main(args: Array< String >) { val n = args[0].toInt() val b = BooleanArray(n) fun subsets(i: Int) { if (i == n) { for (j in b.indices) if (b[j]) print(" $j") println() } else { b[i] = false subsets(i+1) b[i] = true subsets(i+1) } } subsets(0) } ``` _---San Skulrattanakulchai_