Corrections

This commit is contained in:
Antti H S Laaksonen 2017-02-04 22:47:12 +02:00
parent 15f11b09ec
commit dcb69f9a71
1 changed files with 56 additions and 81 deletions

View File

@ -278,26 +278,26 @@ Each subset of a set $\{0,1,2,\ldots,n-1\}$
corresponds to a $n$ bit number corresponds to a $n$ bit number
where the one bits indicate which elements where the one bits indicate which elements
are included in the subset. are included in the subset.
For example, the bit representation for $\{1,3,4,8\}$ For example, the bit representation of $\{1,3,4,8\}$
is 100011010 that equals $2^8+2^4+2^3+2^1=282$. is 100011010 that equals $2^8+2^4+2^3+2^1=282$.
The bit representation of a set uses little memory The benefit in using a bit representation is
because only one bit is needed for the information that the information whether an element belongs
whether an element belongs to the set. to the set requires only one bit of memory.
In addition, we can efficiently manipulate sets In addition, we can implement set operations
that are stored as bits. efficiently as bit operations.
\subsubsection{Set operations} \subsubsection{Set operations}
In the following code, the variable $x$ In the following code, $x$
contains a subset of $\{0,1,2,\ldots,31\}$. contains a subset of $\{0,1,2,\ldots,31\}$.
The code adds elements 1, 3, 4 and 8 The code adds the elements 1, 3, 4 and 8
to the set and then prints the elements in the set. to the set and then prints the elements.
\begin{lstlisting} \begin{lstlisting}
// x is an empty set // x is an empty set
int x = 0; int x = 0;
// add numbers 1, 3, 4 and 8 to the set // add elements 1, 3, 4 and 8 to the set
x |= (1<<1); x |= (1<<1);
x |= (1<<3); x |= (1<<3);
x |= (1<<4); x |= (1<<4);
@ -309,24 +309,13 @@ for (int i = 0; i < 32; i++) {
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
The output of the code is as follows: Set operations can be implemented as follows:
\begin{lstlisting}
1 3 4 8
\end{lstlisting}
Using the bit representation of a set,
we can efficiently implement set operations
using bit operations:
\begin{itemize} \begin{itemize}
\item $a$ \& $b$ is the intersection $a \cap b$ of $a$ and $b$ \item $a$ \& $b$ is the intersection $a \cap b$ of $a$ and $b$
(this contains the elements that are in both the sets)
\item $a$ | $b$ is the union $a \cup b$ of $a$ and $b$ \item $a$ | $b$ is the union $a \cup b$ of $a$ and $b$
(this contains the elements that are at least \item \textasciitilde$a$ is the complement $\bar a$ of $a$
in one of the sets)
\item $a$ \& (\textasciitilde$b$) is the difference \item $a$ \& (\textasciitilde$b$) is the difference
$a \setminus b$ of $a$ and $b$ $a \setminus b$ of $a$ and $b$
(this contains the elements that are in $a$
but not in $b$)
\end{itemize} \end{itemize}
The following code constructs the union The following code constructs the union
@ -346,14 +335,9 @@ for (int i = 0; i < 32; i++) {
cout << "\n"; cout << "\n";
\end{lstlisting} \end{lstlisting}
The output of the code is as follows:
\begin{lstlisting}
1 3 4 6 8 9
\end{lstlisting}
\subsubsection{Iterating through subsets} \subsubsection{Iterating through subsets}
The following code iterates through The following code goes through
the subsets of $\{0,1,\ldots,n-1\}$: the subsets of $\{0,1,\ldots,n-1\}$:
\begin{lstlisting} \begin{lstlisting}
@ -362,7 +346,7 @@ for (int b = 0; b < (1<<n); b++) {
} }
\end{lstlisting} \end{lstlisting}
The following code goes through The following code goes through
subsets with exactly $k$ elements: the subsets with exactly $k$ elements:
\begin{lstlisting} \begin{lstlisting}
for (int b = 0; b < (1<<n); b++) { for (int b = 0; b < (1<<n); b++) {
if (__builtin_popcount(b) == k) { if (__builtin_popcount(b) == k) {
@ -378,51 +362,44 @@ do {
// process subset b // process subset b
} while (b=(b-x)&x); } while (b=(b-x)&x);
\end{lstlisting} \end{lstlisting}
% Esimerkiksi jos $x$ esittää joukkoa $\{2,5,7\}$,
% niin koodi käy läpi osajoukot
% $\emptyset$, $\{2\}$, $\{5\}$, $\{7\}$,
% $\{2,5\}$, $\{2,7\}$, $\{5,7\}$ ja $\{2,5,7\}$.
\section{Dynamic programming} \section{Dynamic programming}
\subsubsection{From permutations to subsets} \subsubsection{From permutations to subsets}
Using dynamic programming, it is often possible Using dynamic programming, it is often possible
to change iteration over permutations into to turn an iteration over permutations into
iteration over subsets. an iteration over subsets so that
In this case, the dynamic programming state the dynamic programming state
contains a subset of a set and possibly contains a subset of a set and possibly
some additional information. some additional information.
The benefit in this technique is that The benefit in this is that
$n!$, the number of permutations of an $n$ element set, $n!$, the number of permutations of an $n$ element set,
is much larger than $2^n$, the number of subsets. is much larger than $2^n$, the number of subsets.
For example, if $n=20$, then For example, if $n=20$, then
$n!=2432902008176640000$ and $2^n=1048576$. $n!=2432902008176640000$ and $2^n=1048576$.
Thus, for certain values of $n$, Hence, for certain values of $n$,
we can go through subsets but not through permutations. we can efficiently go through subsets but not through permutations.
As an example, let's calculate the number of As an example, consider the problem of
permutations of set $\{0,1,\ldots,n-1\}$ calculating the number of
where the difference between any two successive permutations of a set $\{0,1,\ldots,n-1\}$,
where the difference between any two consecutive
elements is larger than one. elements is larger than one.
For example, there are two solutions for $n=4$: For example, when $n=4$, there are two such permutations:
\begin{itemize} $(1,3,0,2)$ and $(2,0,3,1)$.
\item $(1,3,0,2)$
\item $(2,0,3,1)$
\end{itemize}
Let $f(x,k)$ denote the number of permutations Let $f(x,k)$ denote the number of valid permutations
for a subset $x$ of $x$ where the last element is $k$ and
where the last number is $k$ and
the difference between any two successive the difference between any two successive
elements is larger than one. elements is larger than one.
For example, $f(\{0,1,3\},1)=1$ For example, $f(\{0,1,3\},1)=1$,
because there is a permutation $(0,3,1)$, because there is a permutation $(0,3,1)$,
and $f(\{0,1,3\},3)=0$ because 0 and 1 and $f(\{0,1,3\},3)=0$, because 0 and 1
can't be next to each other. cannot be next to each other.
Using $f$, the solution for the problem is the sum Using $f$, the solution to the problem equals
\[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i). \] \[ \sum_{i=0}^{n-1} f(\{0,1,\ldots,n-1\},i). \]
@ -441,7 +418,7 @@ for (int i = 0; i < n; i++) d[1<<i][i] = 1;
\end{lstlisting} \end{lstlisting}
\noindent \noindent
After this, the other values can be calculated Then, the other values can be calculated
as follows: as follows:
\begin{lstlisting} \begin{lstlisting}
@ -457,15 +434,13 @@ for (int b = 0; b < (1<<n); b++) {
\end{lstlisting} \end{lstlisting}
\noindent \noindent
The variable $b$ contains the bit representation The variable $b$ goes through all subsets, and each
of the subset, and the corresponding permutation is of the form $(\ldots,j,i)$
permutation is of the form $(\ldots,j,i)$. where the difference between $i$ and $j$ is
It is required that the difference between larger than one and $i$ and $j$ belong to $b$.
$i$ and $j$ is larger than 1, and the
numbers belong to subset $b$.
Finally, the number of solutions can be Finally, the number of solutions can be
calculated as follows to $s$: calculated as follows:
\begin{lstlisting} \begin{lstlisting}
long long s = 0; long long s = 0;
@ -476,17 +451,17 @@ for (int i = 0; i < n; i++) {
\subsubsection{Sums of subsets} \subsubsection{Sums of subsets}
Let's assume that every subset $x$ Finally, we consider the following problem:
Every subset $x$
of $\{0,1,\ldots,n-1\}$ of $\{0,1,\ldots,n-1\}$
is assigned a value $c(x)$, is assigned a value $c(x)$,
and our task is to calculate for and our task is to calculate for
each subset $x$ the sum each subset $x$ the sum
\[s(x)=\sum_{y \subset x} c(y)\] \[s(x)=\sum_{y \subset x} c(y).\]
that corresponds to the sum Using bit operations, the corresponding sum is
\[s(x)=\sum_{y \& x = y} c(y)\] \[s(x)=\sum_{y \& x = y} c(y).\]
using bit operations. The following table shows an example of
The following table gives an example of the functions when $n=3$:
the values of the functions when $n=3$:
\begin{center} \begin{center}
\begin{tabular}{rrr} \begin{tabular}{rrr}
$x$ & $c(x)$ & $s(x)$ \\ $x$ & $c(x)$ & $s(x)$ \\
@ -505,28 +480,28 @@ For example, $s(110)=c(000)+c(010)+c(100)+c(110)=5$.
The problem can be solved in $O(2^n n)$ time The problem can be solved in $O(2^n n)$ time
by defining a function $f(x,k)$ that calculates by defining a function $f(x,k)$ that calculates
the sum of values $c(y)$ where $x$ can be the sum of $c(y)$ values such that $x$ can be
converted into $y$ by changing any one bits turned into $y$ by changing zero or more one bits
in positions $0,1,\ldots,k$ to zero bits. at positions $0,1,\ldots,k$ to zero bits.
Using this function, the solution for the Using this function, the solution to the
problem is $s(x)=f(x,n-1)$. problem is $s(x)=f(x,n-1)$.
The base cases for the function are: The base cases for the function are:
\begin{equation*} \begin{equation*}
f(x,0) = \begin{cases} f(x,0) = \begin{cases}
c(x) & \textrm{if bit 0 in $x$ is 0}\\ c(x) & \textrm{if bit 0 of $x$ is 0}\\
c(x)+c(x \XOR 1) & \textrm{if bit 0 in $x$ is 1}\\ c(x)+c(x \XOR 1) & \textrm{if bit 0 of $x$ is 1}\\
\end{cases} \end{cases}
\end{equation*} \end{equation*}
For larger values of $k$, the following recursion holds: For larger values of $k$, the following recursion holds:
\begin{equation*} \begin{equation*}
f(x,k) = \begin{cases} f(x,k) = \begin{cases}
f(x,k-1) & \textrm{if bit $k$ in $x$ is 0}\\ f(x,k-1) & \textrm{if bit $k$ of $x$ is 0}\\
f(x,k-1)+f(x \XOR (1 < < k),k-1) & \textrm{if bit $k$ in $x$ is 1}\\ f(x,k-1)+f(x \XOR (1 < < k),k-1) & \textrm{if bit $k$ of $x$ is 1}\\
\end{cases} \end{cases}
\end{equation*} \end{equation*}
Thus, we can calculate the values for the function Thus, we can calculate the values of the function
as follows using dynamic programming. as follows using dynamic programming.
The code assumes that the array \texttt{c} The code assumes that the array \texttt{c}
contains the values for $c$, contains the values for $c$,
@ -546,9 +521,9 @@ for (int k = 1; k < n; k++) {
} }
\end{lstlisting} \end{lstlisting}
Actually, a much shorter implementation is possible Actually, a much shorter implementation is possible,
because we can calculate the results directly because we can calculate the results directly
to array \texttt{s}: into the array \texttt{s}:
\begin{lstlisting} \begin{lstlisting}
for (int x = 0; x < (1<<n); x++) s[x] = c[x]; for (int x = 0; x < (1<<n); x++) s[x] = c[x];
for (int k = 0; k < n; k++) { for (int k = 0; k < n; k++) {