\myheading{Kangaroo: Optimizing production of a cardboard toy using SAT-solver}

\renewcommand{\CURPATH}{other/tiling/kangaroo}

This is a do-it-yourself toy kangaroo I once bought, made of cardboard parts:

\begin{figure}[H]
\centering
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/3.jpg}
  \caption{Final view}
\end{subfigure}%
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/2.jpg}
  \caption{Assembly guide}
\end{subfigure}
\end{figure}


\clearpage
All parts came in 3 plates:

\begin{figure}[H]
\centering
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/1.jpg}
  \caption{A guide}
\end{subfigure}%
\begin{subfigure}{.5\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/4.jpg}
  \caption{3 cardboards}
\end{subfigure}
\end{figure}

Now the question: can we put all the parts needed on smaller plates?
To save some cardboard material?

\clearpage
I \textit{digitized} all parts using usual notebook:

\begin{figure}[H]
\centering
\includegraphics[width=0.5\linewidth]{\CURPATH/digitized-25.jpg}
\end{figure}

\begin{figure}[H]
\centering
\begin{subfigure}{.25\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/digitized-20-24.jpg}
\end{subfigure}%
\begin{subfigure}{.25\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/digitized-36.jpg}
\end{subfigure}%
\begin{subfigure}{.25\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/digitized-26.jpg}
\end{subfigure}%
\begin{subfigure}{.25\textwidth}
  \centering
  \includegraphics[width=0.9\linewidth]{\CURPATH/digitized-35.jpg}
\end{subfigure}
\end{figure}

I don't know a real size of a square in notebook, probably, ~5mm.
I would call it \textit{one [square] unit}.

Then I took the same piece of Python code I used before: \ref{tiling_SAT}.

It was easy: there are just (a big) pack of Boolean variables and AMO1/ALO1 constraints,
or, as I called them before, POPCNT1.

Thanks to parallelized Plingeling SAT-solver, I could
find a solution for a 43*34 [units] plate in ~10 minutes\footnote{4 threads on Intel Xeon CPU E3-1270 v3 @ 3.50GHz}:

\begin{figure}[H]
\centering
\includegraphics[width=0.7\linewidth]{\CURPATH/1plate.png}
\caption{All parts on a single 43*34 plate}
\end{figure}

Probably this is smallest plate possible. When I try smaller dimensions, SAT solver stuck.
But if you wish, you can decrease dimensions and run it again and again...

Now the question: the toy factory wants to ship all parts in several (smaller) plates.
Like, 3 of them.
Because one plate is impractical for shipping, handling, etc.

To put all parts on 3 plates, I can just add 2 borders between them:

\begin{lstlisting}[style=custompy]
board=["*"*BOARD_SMALL_WIDTH + " " + "*"*BOARD_SMALL_WIDTH + " " + "*"*BOARD_SMALL_WIDTH]*BOARD_SMALL_HEIGHT
\end{lstlisting}

Smallest (3) plates I found: 19*27 [units]:

\begin{figure}[H]
\centering
\includegraphics[width=\linewidth]{\CURPATH/3plates.png}
\caption{All parts on a three 19*27 plates}
\end{figure}

This is slightly better than what was produced by the toy factory (20*30 [units], as measured by my notebook).

Now you can see there are two $2 \cdot 1$ notches at each \textit{plate}:

\begin{figure}[H]
\centering
\includegraphics[width=\linewidth]{\CURPATH/5.jpg}
\caption{Note notches: upper left and bottom left}
\end{figure}

I don't know why they been cut. Probably for easier stacking at factory? Who knows.
Anyway, I think I can add this constraint to my solver.
These are 3 initial plates:

\begin{lstlisting}[style=custompy]
board=["*****************   *****************   *****************  ",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       " ******************  ******************  ******************",
       " ******************  ******************  ******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************",
       "******************* ******************* *******************"]
\end{lstlisting}

\begin{figure}[H]
\centering
\includegraphics[width=\linewidth]{\CURPATH/3plates_notches.png}
\caption{All parts on a three 19*27 plates with notches}
\end{figure}

Keep in mind, how coarse my \textit{units} are (~5mm).
You can \textit{digitize} better if you use a
millimeter paper\footnote{\url{https://en.wikipedia.org/wiki/Graph_paper}}, but such a problem
would be more hard for SAT solver, of course.

What I also did: this problem required huge AMO1/ALO1 constraints (several thousands
Boolean variables).
Naive quadratic encoding can't manage this, also, CNF instances growing greatly.

I used \textit{commander} encoding this time.
For example, you need to add AMO1/ALO1 constraint to 100 variables.
Divide them by 10 parts.
Add naive/quadratic AMO1/ALO1 for each of these 10 parts.
Add \textit{OR} for each parts.
Then you get 10 \textit{OR result}.
Each \textit{OR result} is a \textit{commander}, like, a commander of a squad.
Join them together with quadratic AMO1/ALO1 constraint again.

I do this recursively, so it looks like a multi-tiered tree of \textit{commanders}.
Also, changing these constants (5 and 10) influences SAT solver's performance significantly,
probably, tuning is required for each type of task...

(The constants defines breadth and depth of a tree.)

\begin{lstlisting}[style=custompy]
    # naive/pairwise/quadratic encoding
    def AtMost1_pairwise(self, lst:List[str]):
        for pair in itertools.combinations(lst, r=2):
            self.add_clause([self.neg(pair[0]), self.neg(pair[1])])

    # "commander" (?) encoding
    def AtMost1_commander(self, lst:List[str]) -> str:
        parts=my_utils.partition(lst, 5)
        c=[] # type: List[str]
        for part in parts:
            if len(part)<10:
                self.AtMost1_pairwise(part)
                c.append(self.OR_list(part))
            else:
                c.append(self.AtMost1_commander(part))
        self.AtMost1_pairwise(c)
        return self.OR_list(c)

    def AtMost1(self, lst:List[str]):
        if len(lst)<=10:
            self.AtMost1_pairwise(lst)
        else:
            self.AtMost1_commander(lst)

    # previously named POPCNT1 
    # make one-hot (AKA unitary) variable
    def make_one_hot(self, lst:List[str]):
        self.AtMost1(lst)
        self.OR_always(lst)
\end{lstlisting}
( \url{\RepoURL/libs/SAT_lib.py} )

The files: \url{\RepoURL/\CURPATH}.

