\chapter{Constraint Satisfaction Problems}

\section{Formalism}

\begin{minipage}[t]{0.45\linewidth} \begin{itemize}
    \item Use \itblue{problem-specific} state representations and heuristics
    \item Generally concerned about determining \itblue{paths} from the current state to the goal states
    \item View states as black boxes with \itblue{no internal structure}
\end{itemize} \end{minipage}
\hfil%
\begin{minipage}[t]{0.45\linewidth} \begin{itemize}
    \item Care less bout paths and more about final goal \itblue{representations}
    \item Take advantage of a \bred{general state representation} and \bred{general heuristics}
    \item The uniform state representation allows design or \itblue{more efficient algorithms}
\end{itemize} \end{minipage}

{~~~}

{~~~}

In constraint satisfaction problems, we represent \bred{states} as \itblue{values} assigned to \itblue{vectors of features}\footnote{Feature vectors provide a general state representation that is useful in many other areas of AI, particularly Machine Learning, Reasoning under Uncertainty, and Computer Vision.}. 
\begin{itemize}
    \item A set of k variables (known as features).
    \item Each variable has a domain of different values.
    \item A state is specified by an assignment of values to all variables.
    \item A partial state is specified by an assignment of a value to some of the variables.
\end{itemize}

A \bred{goal} is specified as \itblue{conditions} on the vector of feature values. To solve a CSP, we need to find a set of values for the features (\itblue{variables}) that \bred{satisfies} the goal conditions (\itblue{constraints}).

\begin{example}[Sudoku]
    Consider the Sudoku problem. The state is represented by a $9 \times 9$ matrix of integers. The goal is to fill in the matrix so that each row, each column, and each $3 \times 3$ subgrid contains all of the integers from 1 to 9.

    \begin{itemize}
        \item Each variable represent a cell.
        \item Domain: a single value for cells already filled in; the set {1, ..., 9} for empty cells.
        \item State: any completed board given by specifying the value in each cell.
        \item Partial State: some incomplete filling out of the board.
        \item Constrains: The variables that form 
        \begin{itemize}
            \item a column must be distinct;
            \item a row must be distinct;
            \item a sub-square must be distinct.
        \end{itemize}
    \end{itemize}
\end{example}

\begin{definition}[Constraint Satisfaction Problem]\index{Constraint Satisfaction Problem}\label{def:csp}
    A \term{Constraint Satisfaction Problem} (CSP) is a problem consists of
    \begin{itemize}
        \item A set of \itblue{variables} $V_1, \dots, V_n$
        \item A (finite) \itblue{domains} of possible values $Dom[V_i]$ for each variable $V_i$
        \item A set of \itblue{constraints} $C_1, \dots, C_m$ that specify allowable combinations of values for subsets of the variables
    \end{itemize}

    Each variable $V_i$ can be assigned nay value from its domain \[
        V_i \in Dom[V_i]
    \] and each constraint $C$ has a set of variables it operates over, called its scope.
    % Example: The scope of C(V1, V2, V4) is {V1, V2, V4}

    {~~~}

    {~~~}

    Given an assignment to variables, $C$ is $\begin{cases}
        \text{\texttt{True} if the assignment satisfies the constraint;} \\
        \text{\texttt{False} if the assignment falsifies the constraint.}
    \end{cases}$

    The solution to a CSP is an \itblue{assignment of a value} to all of the variables such that \bred{every} constraint is \itblue{satisfied}. A CSP is \term{unstisfiable} if no such assignment exists.
\end{definition}

There are different types of constraints, including \itblue{unary}, \itblue{binary}, and \itblue{higher-order} constraints.
\begin{itemize}
    \item A \term{unary} constraint involves a \itblue{single} variable. \[
        C(X): X = 2; \quad C(Y): Y > 3
    \]

    \item A \term{binary} constraint involves \itblue{two} variables. \[
        C(X, Y): X \neq Y; \quad C(X, Y): X + Y  5
    \]

    \item A \term{higher-order} constraint involves \itblue{three or more} variables. \[
        \textsc{All-Diff}(V_1, \dots, V_n): V_1 \neq V_2, V_1 \neq V_3, \dots, V_{n-1} \neq V_n
    \]
\end{itemize}

We can specify the constraints with a \itblue{constraint table}, but it is not the best way to represent constraints. 

\begin{example}[N-Queens]
    Place $N$ queens on an $N \times N$ chessboard so that no two queens attack each other. 
    
    \begin{itemize}
        \item \textbf{Variables}: $Q_1, \dots, Q_N$, where $Q_i$ is the column number of the queen in the $i$-th row.
        \item \textbf{Domains}: $Dom[Q_i] = \{1, \dots, N\}$ for all $i$.
        \item \textbf{Constraints}:
        \begin{itemize}
            \item Cannot put two Queens in the same column: for all $i, j \in \{1, \dots, N\}$, $i \neq j \implies Q_i \neq Q_j$.
            \item Diagonal constraints: for all $i, j \in \{1, \dots, N\}$, $i \neq j \implies abs(Q_i - Q_j) \neq abs(i - j)$.
        \end{itemize}
    \end{itemize}

    This is a very famous CSP problem.
\end{example}

\section{Backtracking Search}

A constraint satisfaction problem can be formulated as a \itblue{search problem} in the following way:
\begin{itemize}
    \item \textbf{Initial State}: \itblue{Empty} assignment.
    \item \textbf{Successor Function}: \itblue{Assign a value} to an unsigned variable.
    \item \textbf{Goal Test}: 
    \begin{itemize}
        \item \itblue{All variables} are assigned a value, and
        \item \itblue{All constraints} are satisfied.
    \end{itemize}
\end{itemize}

\subsection{Backtracking Search}

\begin{remark}
    CSPs do NOT require finding a path (to a goal). They only need the \bred{configuration} of the goal state. CSPs are best solved by a specialized version search called \itblue{Backtracking Search}\index{Backtracking Search}.
\end{remark}

\begin{itemize}
    \item Searching through the space of partial assignments, rather than paths.

    \item Decide on a suitable value for one variable at a time. 
    
    Order in which we assign the variables does not matter.

    \item If a constraint is falsified during the process of partial assignment, immediately reject the current partial assignment. 
\end{itemize}

\subsubsection{CSP Search Tree}

\begin{itemize}
    \item The \textbf{root} is the \itblue{empty} assignment.
    \item The \textbf{Children} of a node are all possible values assignments for a \itblue{particular unassigned variable}.
    \item The tree \textbf{stops descending} if an assignment \itblue{violates} a constraint.
    \item We reach the \textbf{goal nodes} when the assignment is \itblue{complete} and \itblue{satisfies} all constraints.
\end{itemize}

\begin{example}[4-Queens]
    The search tree for the 4-Queens problem is shown below. 
    
    \begin{center}
        \includegraphics[width=0.45\linewidth]{figures/bt-1.png}
        \hfil%
        \includegraphics[width=0.45\linewidth]{figures/bt-2.png}

        \includegraphics[width=0.45\linewidth]{figures/bt-3.png}
        \hfil%
        \includegraphics[width=0.45\linewidth]{figures/bt-4.png}
    \end{center}
\end{example}

\subsection{Backtracking Algorithm}

We will apply a \itblue{recursive} implementation.

\begin{itemize}
    \item If all variables are assigned, return the assignment.
    \item Otherwise, 
    \begin{itemize}
        \item Pick an unassigned variable $V$ and assign it a value $v$.
        \item Test the constraints corresponding with $V$ and all other assigned variables.
        \item If a constraint is violated, \itblue{backtrack} and try another value for $V$.
        \item Otherwise, go one level deeper by calling the function recursively.
    \end{itemize}
\end{itemize}

\begin{algorithm}[ht!]
    \begin{algorithmic}[1]
        \Function{BT}{Level}
            \If{all Variables are assigned}
                \State \Call{Print}{value of each Variable}
                \State \Return \texttt{Success}, or \textsc{Exit}
                \Comment{Exit if only one solution is needed}
            \EndIf

            {~~~}

            \State $V \gets$ an unassigned Variable
            \State $Assigned[V] \gets \texttt{True}$

            \For{$d \in Dom[V]$}
                \State $Value[V] \gets d$
                \State $Valid \gets \texttt{True}$

                \For{$C \in Constraints$}
                \Comment{(i) $V$ is a variable of $C$ and (ii) all other variables of $C$ are assigned}
                    \If{$C$ is violated}
                        \State $Valid \gets \texttt{False}$
                        \State \textbf{break}
                    \EndIf
                \EndFor

                \If{$Valid$}
                    \State \Call{BT}{Level + 1}
                \EndIf
            \EndFor

            {~~~}
            
            \State $Assigned[V] \gets \texttt{False}$
            \Comment{UNDO as we have tried all of $V$'s values}
            \State \Return \texttt{Failure}
        \EndFunction
    \end{algorithmic}
\end{algorithm}

\section{Backtracking with Inference}

Backtracking search runs in exponential time, which is very expensive. Especially, if the space of possible configurations is large, the search tree can be very deep. Moreover, in CSPs, there might be variables that have no possible value, but BT doesn't detect this until it tries to assign them a value.

\begin{example}
    Suppose the variable representing the cell $(1, 3)$ is assigned to value $3$.

    \begin{center}
        \includegraphics[width=0.25\linewidth]{figures/problems-with-plain-bt.png}
    \end{center}

    The backtracking search won't detect that the cell $(3, 3)$ has no possible value until all variables of the corresponding row/column/sub-square are assigned.
\end{example}

\subsection{Inference}

The idea behind using an \term{inference} is that after assigning a value to a variable, we infer the \itblue{obvious\footnote{``Obvious'' means things we can test/detect \bred{efficiently}.} restrictions imposed} by the \bred{current assignments} on values that unassigned variables can take and \itblue{reduce} their domains accordingly. Even if a failure is not detected, it might \bred{prune some parte} of the search tree. 

Inference can be applied \itblue{during the search}; potentially at \bred{every node} of the search tree. An inference step needs some resources (in particular, \bred{time}). If the inference procedure is slow, this can slow the search down to the point where using it makes finding a solution take longer.

{~~~}

Every time we \bred{assign} a value to a variable $V$, we check \itblue{all constraints over $V$} and prune values from the \bred{current domain} of the \itblue{unassigned variables} of the constraints.

Let $C$ be a constraint that includes $V$ in its scope and $V_i$ be a variable (other than $V$) in the scope of $C$. All values in the current domain of $V_i$ must have a \itblue{supporting assignment}. If a value \bred{doesn't} have any \bred{supports}, it must be \bred{pruned}.

\begin{definition}[Supporting Assignment]\index{Supporting Assignment}
    A value $d$ in the current domain of $V_i$ has a \term{supporting assignment} if there exists \itblue{at least one value assignment} for other variables of $C$ such that $C$ is \bred{satisfied} under $V_i = d$ and that value assignment.

    \begin{itemize}
        \item Value assignments must be from the \itblue{current} partial assignment.
        \item If a variable $V$ is assigned to a value $t$, then $CurrDom[V] = \{t\}$.
    \end{itemize}
\end{definition}

\begin{example}
    Consider the constraint $C$ over variables $X, Y, Z$ \[
        C_1(X, Y): X > Y \quad \text{and} \quad C_2(Y, Z): Y > Z
    \] with the domains \[
        Dom[X] = \{1, 5, 11\}, \quad Dom[Y] = \{3, 8, 5\}, \quad Dom[Z] = \{4, 6\}.
    \] Suppose now we assign $Y = 8$. That is, \[
        CurrDom[Y] = \{8\}
    \]

    By the constraint $C_1(X, Y): X > Y$, we can prune the value $1$ and $5$ from the domain of $X$ because they don't have any supporting assignment. That is, \[
        CurrDom[X] = \{11\}
    \]

    All value in the domain of $Z$ has a supporting assignment, so we don't prune any value from the domain of $Z$.
\end{example}

It is important to notice that removing a value from a variable domain may remove a support for other domain values. We should \bred{repeat} the procedure until \bred{all remaining values have a support}.

\begin{example}
    Suppose now that we assign $X = 5$. That is, \[
        CurrDom[X] = \{5\}
    \]

    There are no constraints between $X$ and $Z$, so we don't prune any value from the domain of $Z$.

    By inspecting the domain of $Y$, we can prune the values $8$ and $5$. Note that this will affect the domain of $Z$ as well.

    We could stop here, but we can also re-check the constrains over the variables that have been pruned. This might lead to further pruning.

    Here, $CurrDom[Y] = \{3\}$, which means no value in the domain of $Z$ has a supporting assignment. 
\end{example}

To achieve this, we need to keep track of the changes in the domains of the variables.
\begin{itemize}
    \item Have a \itblue{queue of variables} that need to be checked. 
    \item A variable is added (back) to the queue if its domain is changed. 
    \item The process stops when the queue is empty. 
\end{itemize}

After backtracking from the current assignment the values that were pruned (as a result of that assignment) must be restored. Some bookkeeping needs to be done to remember which values were pruned by which assignment.

\begin{example}[Map Colouring]
    Suppose we want to colour the following map with 3 colours, such that no two adjacent regions have the same colour.  
    \begin{center} \begin{tikzpicture}
        \node[draw,circle,fill=red,text=white] (WA)  at (0,0)  {WA};
        \node[draw,circle]                     (NT)  at (2,1)  {NT};
        \node[draw,circle]                     (SA)  at (2,-1) {SA};
        \node[draw,circle]                     (Q)   at (4,1)  {Q};
        \node[draw,circle]                     (NSW) at (5,-1) {NSW};
        \node[draw,circle]                     (V)   at (4,-2) {V};
        \node[draw,circle]                     (T)   at (4,-3) {T};

        \draw (WA) -- (NT) -- (Q) -- (NSW) -- (V) -- (SA) -- (WA);
        \draw (NT) -- (SA) -- (NSW);
        \draw (SA) -- (Q);
    \end{tikzpicture} \end{center}
    
    \[
        \begin{matrix}[lll]
            C_1(SA, WA): SA \neq WA, & C_2(NT, W A): NT \neq WA,  & C_3(SA, NT): SA \neq NT \\
            C_4(SA, Q):  SA \neq Q,  & C_5(SA, NSW): SA \neq NSW, & C_6(SA, V):  SA \neq V  \\
            C_7(NT, Q):  NT \neq Q,  & C_8(Q, NSW):  Q  \neq NSW, & C_9(NSW, V): NSW \neq V
        \end{matrix}
    \] \begin{itemize}
        \item \textbf{Value assignments:} $WA = R$. 
        
        That is, $CurrDom[WA] = \{R\}$.

        Then, $SA$ and $NT$ must be put on the queue. 

        \item \textbf{Current Domains:} \[
            \begin{matrix}[ll]
                CurDom[SA] = \{R, G, B\}, & CurDom[NT] = \{R, G, B\}  \\
                CurDom[Q] = \{R, G, B\},  & CurDom[NSW] = \{R, G, B\} \\
                CurDom[V] = \{R, G, B\}   & CurDom[T] = \{R, G, B\}
            \end{matrix}
        \]
    \end{itemize}

    The queue is now $\{SA, NT\}$.
    \begin{itemize}
        \item We pop $SA$ from the queue. 
        
        $SA = R$ has no supporting assignment, we prune $R$ from the domain of $NT$.
        
        Now, we append the variables that are affected by the change to the queue: $\{NT, Q, NSW, V\}$.

        The queue is now $\{NT, Q, NSW, V\}$.

        \item We pop $NT$ from the queue. 
        
        $NT = R$ has no supporting assignment, we prune $R$ from the domain of $Q$ and $NSW$.
        
        Now, we append the variables that are affected by the change to the queue: $\{WA, SA, Q\}$.

        The queue is now $\{Q, NSW, V, SA\}$ (we do not place $WA$ since it is already assigned).

        \item Every other variable in the queue is not affected by the change, so we stop here.
    \end{itemize}

    \begin{center} \begin{tikzpicture}
        \node[draw,circle,fill=red,text=white]       (WA)  at (0,0)  {WA};
        \node[draw,circle]                           (NT)  at (2,1)  {NT};
        \node[draw,circle]                           (SA)  at (2,-1) {SA};
        \node[draw,circle,fill=darkGreen,text=white] (Q)   at (4,1)  {Q};
        \node[draw,circle]                           (NSW) at (5,-1) {NSW};
        \node[draw,circle]                           (V)   at (4,-2) {V};
        \node[draw,circle]                           (T)   at (4,-3) {T};

        \draw (WA) -- (NT) -- (Q) -- (NSW) -- (V) -- (SA) -- (WA);
        \draw (NT) -- (SA) -- (NSW);
        \draw (SA) -- (Q);
    \end{tikzpicture} \end{center}

    \begin{itemize}
        \item \textbf{Value assignments:} $WA = R$, $Q = G$.

        Then, $SA$, $NT$ and $NSW$ must be put on the queue.

        \item \textbf{Current Domains:} \[
            \begin{matrix}[ll]
                CurDom[SA] = \{G, B\},   & CurDom[NT] = \{G, B\}     \\
                CurDom[Q] = \{R, G, B\}, & CurDom[NSW] = \{R, G, B\} \\
                CurDom[V] = \{R, G, B\}  & CurDom[T] = \{R, G, B\}
            \end{matrix}
        \]
    \end{itemize}

    The queue is now $\{SA, NT, NSW\}$.

    {~~~}

    $G$ is purned from the domain of $SA$ and $NT$. Then, both $SA$ and $NT$ can only be assigned to $B$. However, by constraint $C_3$, $SA$ and $NT$ cannot be assigned to the same value. Thus, we have a \term{Domain Wipe-Out} (DWO). \[
        \begin{matrix}[ll]
            CurDom[SA] = \{B\},      & CurDom[NT] = \{\} \leftarrow \text{\color{red}DWO} \\
            CurDom[Q] = \{R, G, B\}, & CurDom[NSW] = \{R, G, B\}                          \\
            CurDom[V] = \{R, G, B\}  & CurDom[T] = \{R, G, B\}
        \end{matrix}
    \]
\end{example}

% \begin{example}[4-Queens]
%     % TODO: Complete this example
% \end{example}

The outcome of an inference step is one of the followings:
\begin{itemize}
    \item Each domain has a \itblue{single value}.

    We can \itblue{immediately} assign the value to the variable and continue with the search.

    \item At least one domain is \itblue{empty}.

    We have a \term{Dead-End} or \term{DWO} (Domain Wipe-Out). We need to \itblue{backtrack} and try another value for the variable that caused the DWO.

    \item Some domains have \itblue{more than one value}.

    We now need to solve this new (usually) simpler CSP problem: same constraints, domains have been reduced
\end{itemize}

\subsection{Backtracking with Inference Algorithm}

\begin{algorithm}[ht!]\label{alg:bt-with-inference}
    \begin{algorithmic}[1]
        \Function{Inference}{var}
            \State VarQueue.\Call{push}{var}
            \While{\Call{Not-Empty}{VarQueue}}
                \State $W \gets \text{VarQueue}.Call{Extract}$
                \For{constraint $C$ where $W \in \text{scope}(C)$}
                    \For{$V$ in scope($C$)$\setminus W$}
                        \State $S \gets CurrDom[V]$
                        \For{$d \in CurrDom[V]$}
                            \State Find assignment $A$ for all other variables in scope($C$) such that $C(A \cup V=d)$ is satisfied
                            \If{no such assignment $A$}
                                \State $CurrDom[V] \gets CurrDom[V] - d$
                                \Comment{Remove $d$ from the domain of $V$}
                                \If{$|CurrDom[V]| = 0$}
                                \Comment{DWO for $V$}
                                    \State \Call{Empty}{VarQueue}
                                    \State \Return \texttt{DWO}
                                    \Comment{Return immediately}
                                \EndIf
                            \EndIf
                        \EndFor

                        \If{$CurrDom[V] \neq S$}
                        \Comment{If the domain of $V$ is changed}
                            \State \textsc{VarQueue}.\Call{push}{V}
                        \EndIf
                    \EndFor
                \EndFor
            \EndWhile

            \State \Return \texttt{Success}
            \Comment{Loop exited without DWO}
        \EndFunction
%     \end{algorithmic}
% \end{algorithm}
        \State
% \begin{algorithm}[ht!]
%     \begin{algorithmic}[1]
        \Function{BT-with-Inference}{Level}
            \If{all Variables are assigned}
                \State \Call{Print}{value of each Variable}
                \State \Return \texttt{Success}, or \textsc{Exit}
                \Comment{Exit if only one solution is needed}
            \EndIf

            \State $V \gets$ an unassigned Variable
            \State $Assigned[V] \gets \texttt{True}$

            \For{$d \in Dom[V]$}
                \State $Value[V] \gets d$
                \State Prune all values other than $d$ from $CurrDom[V]$
                \If{\Call{Inference}{V} $\neq$ \texttt{DWO}}
                    \State \Call{BT-with-Inference}{Level + 1}
                    \Comment{All remaining domain in values have a support}
                \EndIf
                \State \Call{Restore-All-Values-Purned-by-Inference}{ }
            \EndFor

            \State $Assigned[V] \gets \texttt{False}$
            \Comment{UNDO as we have tried all of $V$'s values}
            \State \Return \texttt{Failure}
        \EndFunction
    \end{algorithmic}
\end{algorithm}

\subsection{Alternatives to Inference}

The computation required for the inference function can be \bred{expensive}, and may \bred{potentially slow down} the search. Alternative implementation attempts to \itblue{limit the depth oft he inference} in order to reduce computational cost. There is a \itblue{trade-off} between n the information that can be derived from deeper levels of inference and run-time effcienc

\subsubsection{Forward Checking}

In \term{Forward Checking}, we only perform inference on the \itblue{immediate neighbours} of the variable that has been assigned a value, and we do not add the variable to the queue if its domain is changed. This is a \itblue{less expensive} form of inference. The algorithm $\textsc{FC-Inference}$ is very similar to $\textsc{Inference}$, with lines 15 and 16 removed.

\begin{example}
    % TODO: Complete this example
\end{example}

\subsubsection{Other Alternatives}

Forward Checking can rule out many inconsistencies but it does not infer further ahead to ensure consistency for all the other variables. An alternative may be to replace the $CurrDom[V] \neq S$ condition (Line 15 of \hyperref[alg:bt-with-inference]{\textsc{Inference}}) with \itblue{$CurrDom[V] == 1$}. 

That is, we find inference for variables that have \bred{only one valid value} in the current domain. This goes one step further from Forward Checking, and allows for further inferences for the variables that have one valid value in the domain. 

Depending on the complexity of the problem, the condition can be set to any particular value, such as $CurrDom[V] \leq k$ for some $k$.

\subsubsection{Time Efficiency}

In general, solving a CSP problem in the worst-case can take \bred{exponential} time. In fact, the general class of CSPs is \bred{NP-complete}. But, typically, every NP-complete family contains large \itblue{sub-classes} of \itblue{simpler} problems. The purpose of developing \bred{inference techniques} and \bred{heuristics} is to solve those \itblue{simpler sub-classes} faster. 

\begin{example}
    {~~~}

    \begin{itemize}
        \item FC often is about 100 times faster than plain BT.  

        \item FC with the MRV heuristic (Minimal Remaining Values) often 10000 times faster.

        \item On some problems the speed up can be much greater.
        
        Converts problems that are not solvable to problems that are solvable.
    \end{itemize}
\end{example}

\section{Heuristics}