1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22 23\chapter{Tree Search Methods} 24\label{chapsearch} 25%HEVEA\cutdef[1]{section} 26%---------------------------------------------------------------------- 27\section{Introduction} 28%---------------------------------------------------------------------- 29In this chapter we will take a closer look at the principles and 30\index{alternative search methods} 31alternative methods of searching for solutions in the presence of 32constraints. Let us first recall what we are talking about. 33We assume we have the standard pattern of a constraint program: 34\begin{code} 35solve(Data) :- 36 model(Data, Variables), 37 search(Variables), 38 print_solution(Variables). 39\end{code} 40The model part contains the logical {\em model} of our problem. It defines 41the variables and the constraints. 42Every variable has a {\em domain} of values that it can take 43(in this context, we only consider domains with a finite number of values). 44 45Once the model is set up, we go into the search phase. 46Search is necessary since generally the implementation of the constraints 47is not complete, i.e.\ not strong enough to logically infer directly 48the solution to the problem. Also, there may be multiple solutions 49which have to be located by search, e.g.\ in order to find the best one. 50In the following, we will use the following terminology: 51\begin{itemize} 52\item If a variable is given a value (from its domain, of course), 53 \index{assignment} 54 we call this an {\em assignment}. If every problem variable is given 55 a value, we call this a {\em total assignment}. 56\item A total assignment is a {\em solution} if it satisfies all the 57 constraints. 58\item The {\em search space} is the set of all possible total assignments. 59 \index{search space} 60 The search space is usually very large because it grows exponentially 61 with the problem size: 62 \begin{displaymath} 63 SearchSpaceSize = {DomainSize}^{NumberOfVariables} 64 \end{displaymath} 65\end{itemize} 66 67 68% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 69\subsection{Overview of Search Methods} 70% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 71 72\begin{figure} 73\begin{center} 74\resizebox{0.55\textwidth}{!}{\includegraphics{../search/search3.eps}} 75\end{center} 76\caption{A search space of size 16} 77\label{figsearchspace} 78\end{figure} 79Figure \ref{figsearchspace} shows a search space with N (here 16) 80possible total assignments, some of which are solutions. 81Search methods now differ in the way in which these assignments 82are visited. 83We can classify search methods according to different criteria: 84\begin{description} 85\item[Complete vs incomplete exploration] complete search means that the search space 86 \index{complete search} 87 \index{incomplete search} 88 is investigated in such a way that all solutions are guaranteed to be found. 89 This is necessary when the optimal solution is needed (one has to prove 90 that no better solution exists). Incomplete search may be sufficient when 91 just some solution or a relatively good solution is needed. 92\item[Constructive vs move-based] this indicates whether the method advances 93 \index{constructive search} 94 \index{move-based search} 95 by incrementally constructing assignments (thereby reasoning about partial 96 assignments which represent subsets of the search space) or by moving 97 between total assignments (usually by modifying previously explored 98 assignments). 99\item[Randomness] some methods have a random element while others follow 100 \index{random search} 101 fixed rules. 102\end{description} 103Here is a selection of search methods together with their properties: 104 105\begin{center} 106\begin{tabular}{|l|lll|} 107\hline 108Method& exploration& assignments& random\\ 109\hline 110Full tree search& complete& constructive& no\\ 111Credit search& incomplete& constructive& no\\ 112Bounded backtrack& incomplete& constructive& no\\ 113Limited discrepancy& complete& constructive& no\\ 114Hill climbing& incomplete& move-based& possibly\\ 115Simulated annealing& incomplete& move-based& yes\\ 116Tabu search& incomplete& move-based& possibly\\ 117Weak commitment& complete& hybrid& no\\ 118\hline 119\end{tabular} 120\end{center} 121 122\index{tree search} 123\index{search tree} 124The constructive search methods usually organise the search space by 125partitioning it systematically. This can be done naturally with a 126search tree (Figure \ref{figsearchtree}). The nodes in this tree 127represent choices which partition the remaining search space into two 128or more (usually disjoint) sub-spaces. Using such 129a tree structure, the search space can be traversed systematically and 130completely (with as little as O(N) memory requirements). 131 132\begin{figure} 133\begin{center} 134\resizebox{0.55\textwidth}{!}{\includegraphics{../search/search4.eps}} 135\end{center} 136\caption{Search space structured using a search tree} 137\label{figsearchtree} 138\end{figure} 139Figure \ref{figtreesearch} shows a sample tree search, namely a depth-first 140incomplete traversal. 141As opposed to that, figure \ref{figmovesearch} shows an example of an 142incomplete move-based search which does not follow a fixed search space 143structure. Of course, it will have to take other precautions to avoid 144looping and ensure termination. 145\begin{figure} 146\begin{center} 147\resizebox{0.55\textwidth}{!}{\includegraphics{../search/search5.eps}} 148\end{center} 149\caption{A move-based search} 150\label{figmovesearch} 151\end{figure} 152 153\begin{figure} 154\begin{center} 155\resizebox{0.55\textwidth}{!}{\includegraphics{../search/search6.eps}} 156\end{center} 157\caption{A tree search (depth-first)} 158\label{figtreesearch} 159\end{figure} 160 161A few further observations: 162Move-based methods are usually incomplete. This is not surprising given 163typical sizes of search spaces. 164A complete exploration of a huge search space 165is only possible if large sub-spaces can be excluded a priori, and this 166is only possible with constructive methods which allow one to reason about 167whole classes of similar assignments. 168Moreover, a complete search method must remember which parts of the 169search space have already been visited. 170This can only be implemented with 171acceptable memory requirements if there is a simple structuring of the 172space that allows compact encoding of sub-spaces. 173 174 175% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 176\subsection{Optimisation and Search} 177% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 178\label{secbboptsearch} 179\index{optimisation} 180Many practical problems are in fact optimisation problems, ie.\ we are 181not just interested in some solution or all solutions, but in 182the best solution. 183 184Fortunately, there is a general method to find the optimal solution 185based on the ability to find all solutions. 186\index{branch-and-bound} 187The {\em branch-and-bound} technique works as follows: 188\begin{enumerate} 189\item Find a first solution 190\item Add a constraint requiring a better solution than the best 191 one we have so far (e.g.\ require lower cost) 192\item Find a solution which satisfies this new constraint. 193 If one exists, we have a new best solution and we repeat step 2. 194 If not, the last solution found is the proven optimum. 195\end{enumerate} 196The {\em branch\_and\_bound} library provides generic predicates 197which implement this technique: 198\begin{description} 199\item[minimize(+Goal,-Cost)] 200This is the simplest predicate in the {\em branch_and_bound} library: 201A solution of the goal {\it Goal} is found that minimizes the value of 202{\em Cost}. {\em Cost} should be a variable that is affected, and 203eventually instantiated, by the execution of {\it Goal}. Usually, {\it Goal} 204is the search procedure of a constraint problem and {\it Cost} is the variable 205representing the cost. 206 207\item[bb_min(+Goal, -Cost, ++Options)] 208A more flexible version where the programmer can take more control 209over the branch and bound behaviour and choose between different 210strategies and parameter settings. 211\end{description} 212 213 214% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 215\subsection{Heuristics} 216% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 217 218Since search space sizes grow exponentially with problem size, 219it is not possible to explore all assignments except for the 220very smallest problems. 221The only way out is {\em not} to look at the whole search space. 222There are only two ways to do this: 223\begin{itemize} 224\item {\bf Prove} that certain areas of the space contain no solutions. 225 This can be done with the help of constraints. This is often referred 226 to as {\em pruning}\index{pruning}. 227\item {\bf Ignore} parts of the search space that are unlikely to contain 228 solutions (i.e.\ do incomplete search), or at least postpone their exploration. 229 This is done by using {\em heuristics}\index{heuristics}. 230 A heuristic is a particular traversal order of the search space 231 which explores promising areas first. 232\end{itemize} 233 234In the following sections we will first investigate the considerable 235degrees of freedom that are available for heuristics within the framework of 236systematic tree search, which is the traditional search method 237in the Constraint Logic Programming world. 238 239Subsequently, we will turn our attention to move-based methods 240which in {\eclipse} can be implemented using the facilities of the 241{\tt repair} library. 242 243 244%---------------------------------------------------------------------- 245\section{Complete Tree Search with Heuristics} 246%---------------------------------------------------------------------- 247 248\index{complete search} 249There is one form of tree search which is especially economic: 250depth-first, left-to-right search by backtracking. It allows 251a search tree to be traversed systematically while requiring only a stack 252of maximum depth N for bookkeeping. Most other strategies of tree 253search (e.g. breadth-first) have exponential memory requirements. 254This unique property is the reason why backtracking is a built feature 255of {\eclipse}. Note that the main disadvantage of the depth-first 256strategy (the danger of going down an infinite branch) does not come 257into play here because we deal with finite search trees. 258 259\index{depth-first search} 260Sometimes depth-first search and heuristic search are treated as antonyms. 261This is only justified when the shape of the search tree is statically fixed. 262Our case is different: we have the freedom of deciding on the shape of every 263sub-tree before we start to traverse it depth-first. While this does not 264allow for absolutely {\em any} order of visiting the leaves of the search tree, 265it does provide considerable flexibility. This flexibility can be exploited 266by variable and value selection strategies. 267 268% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 269\subsection{Search Trees} 270% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 271 272In general, the nodes of a search tree represent {\em choices}. 273\index{choice} 274These choices should be mutually exclusive and therefore partition the 275\index{partition a search space} 276search space into two or more disjoint sub-spaces. 277In other words, the original problem is reduced to a disjunction 278of simpler sub-problems. 279 280In the case of finite-domain problems, the most common form of choice 281is to choose a particular value for a problem variable 282(this technique is often called 283\index{labeling} 284{\em labeling}). 285For a boolean variable, this means setting the variable to 0 in one 286branch of the search tree and to 1 in the other. 287In {\eclipse}, this can be written as a disjunction 288(which is implemented by backtracking): 289\begin{quote}\begin{alltt} 290( X1=0 ; X1=1 ) 291\end{alltt}\end{quote} 292Other forms of choices are possible. If X2 is a variable that can take 293integer values from 0 to 3 (assume it has been declared as \verb'X2::0..3'), 294we can make a n-ary search tree node by writing 295\begin{quote}\begin{alltt} 296( X2=0 ; X2=1 ; X2=2 ; X2=3 ) 297\end{alltt}\end{quote} 298or more compactly 299\begin{quote}\begin{alltt} 300indomain(X2) 301\end{alltt}\end{quote} 302However, choices do not necessarily involve choosing a concrete value 303for a variable. It is also possible to make disjoint choices by 304\index{domain splitting} 305{\em domain splitting}, e.g. 306\begin{quote}\begin{alltt} 307( X2 #=< 1 ; X2 #>= 2 ) 308\end{alltt}\end{quote} 309or by choosing a value in one branch and excluding it in the other: 310\begin{quote}\begin{alltt} 311( X2 = 0 ; X2 #>= 1 ) 312\end{alltt}\end{quote} 313In the following examples, we will mainly use simple labeling, 314which means that the search tree nodes correspond to a variable 315and a node's branches correspond to the different values that the 316variable can take. 317 318 319% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 320\subsection{Variable Selection} 321\index{variable selection} 322% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 323 324\begin{figure} 325\begin{center} 326\resizebox{0.5\textwidth}{!}{\includegraphics{../search/search1.eps}} 327\end{center} 328\caption{The effect of variable selection} 329\label{figvarsel} 330\end{figure} 331 332Figure \ref{figvarsel} shows how variable selection reshapes a search tree. 333If we decide to choose values for X1 first (at the root of the search tree) 334and values for X2 second, then the search tree has one particular shape. 335If we now assume a depth-first, left-to-right traversal by backtracking, 336this corresponds to one particular order of visiting the leaves of the tree: 337(0,0), (0,1), (0,2), (0,3), (1,0), (1,1), (1,2), (1,3). 338 339If we decide to choose values for X2 first and X1 second, then the tree and 340consequently the order of visiting the leaves is different: 341(0,0), (1,0), (0,1), (1,1), (0,2), (1,2), (0,3), (1,3). 342 343While with 2 variables there are only 2 variable selection strategies, 344this number grows exponentially with the number of variables. For 5 345variables there are already $2^{2^{5}-1} = 2147483648$ different variable selection 346strategies to choose from. 347 348Note that the example shows something else: If the domains of the variables 349are different, then the variable selection can change the number of internal 350nodes in the tree (but not the number of leaves). To keep the number of nodes 351down, variables with small domains should be selected first. 352 353 354% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 355\subsection{Value Selection} 356\index{value selection} 357% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 358 359The other way to change the search tree is value selection, i.e. reordering 360the child nodes of a node by choosing the 361values from the domain of a variable in a particular order. 362Figure \ref{figvalsel} shows how this can change the order of visiting the 363leaves: 364(1,2), (1,1), (1,0), (1,3), (0,1), (0,3), (0,0), (0,2). 365 366\begin{figure} 367\begin{center} 368\resizebox{0.5\textwidth}{!}{\includegraphics{../search/search2.eps}} 369\end{center} 370\caption{The effect of value selection} 371\label{figvalsel} 372\end{figure} 373 374By combining variable and value selection alone, a large number of different 375heuristics can be implemented. 376To give an idea of the numbers involved, table \ref{visits} shows the search 377space sizes, the number of possible search space traversal orderings, 378and the number of orderings 379that can be obtained by variable and value selection (assuming domain size 2). 380 381\begin{figure}[t] 382\enableunderscores 383\begin{center} 384\begin{tabular}{|l|l|l|l|} 385\hline 386Variables& Search space& Visiting orders& Selection Strategies\\ 387\hline 3881& 2& 2& 2\\ 3892& 4& 24& 16\\ 3903& 8& 40320& 336\\ 3914& 16& $2.1*10^{13}$& $1.8*10^7$\\ 3925& 32& $2.6*10^{35}$& $3.5*10^{15}$\\ 393n& $2^n$& $2^n!$& 394 $2^{{2^n}-1} \prod_{i=0}^{n-1} (n-1)^{2^i}$\\ 395\hline 396\end{tabular} 397\end{center} 398\caption{Flexibility of Variable/Value Selection Strategies} 399\label{visits} 400\disableunderscores 401\end{figure} 402 403% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 404\subsection{Example} 405% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 406 407\index{queens} 408We use the famous N-Queens problem to illustrate how heuristics can be applied 409to backtrack search through variable and value selection. 410We model the problem with one variable per queen, assuming that each queen 411occupies one colunm. The variables range from 1 to N and indicate the row 412in which the queen is being placed. The constraints ensure that no two 413queens occupy the same row or diagonal: 414\label{queenscode} 415\begin{code} 416:- lib(ic). 417 418queens(N, Board) :- 419 length(Board, N), 420 Board :: 1..N, 421 ( fromto(Board, [Q1|Cols], Cols, []) do 422 ( foreach(Q2, Cols), count(Dist,1,_), param(Q1) do 423 noattack(Q1, Q2, Dist) 424 ) 425 ). 426 427 noattack(Q1,Q2,Dist) :- 428 Q2 #\verb.\.= Q1, 429 Q2 - Q1 #\verb.\.= Dist, 430 Q1 - Q2 #\verb.\.= Dist. 431\end{code} 432We are looking for a first solution to the 16-queens problem by calling 433\begin{quote}\begin{alltt} 434?- queens(16, Vars), % model 435 labeling(Vars). % search 436\end{alltt}\end{quote} 437We start naively, using the pre-defined labeling-predicate that comes with the 438{\em ic} library. It is defined as follows: 439\begin{code} 440labeling(AllVars) :- 441 ( foreach(Var, AllVars) do 442 indomain(Var) % select value 443 ). 444\end{code} 445The strategy here is simply to select the variables 446from left to right as they occur in the list, and they are 447assigned values starting from the lowest to the numerically highest they can 448take (this is the definition of indomain/1). 449A solution is found after 542 backtracks 450(see section \ref{countbt} below for how to count backtracks). 451 452A first improvement is to employ a 453{\bf general-purpose variable-selection heuristic}, 454\index{first-fail principle} 455the so called first-fail principle. It requires to label the 456variables with the smallest domain first. This reduces the branching 457factor at the root of the search tree and the total number of internal nodes. 458\index{ic_search} 459The delete/5 predicate from the {\em ic_search} library 460implements this strategy for finite integer domains. 461Using delete/5, we can redefine our labeling-routine as follows: 462\begin{code} 463:- lib(ic_search). 464labeling_b(AllVars) :- 465 ( fromto(AllVars, Vars, VarsRem, []) do 466 delete(Var, Vars, VarsRem, 0, first_fail), % dynamic var-select 467 indomain(Var) % select value 468 ). 469\end{code} 470Indeed, for the 16-queens example, this leads to a dramatic improvement, 471the first solution is found with only 3 backtracks now. 472But caution is necessary: The 256-queens instance for example solves 473nicely with the naive strategy, but our improvement leads to a 474disappointment: the time increases dramatically! 475This is not uncommmon with heuristics: one has to keep in mind that the 476search space is not reduced, just re-shaped. Heuristics that yield good 477results with some problems can be useless or counter-productive with others. 478Even different instances of the same problem can exhibit widely different 479characteristics. 480 481Let us try to employ a {\bf problem-specific heuristic}: 482\index{problem-specific heuristic} 483Chess players know that pieces in the middle of the board are more 484useful because they can attack more fields. We could therefore start 485placing queens in the middle of the board to reduce the number of 486unattacked fields earlier. We can achieve that simply by pre-ordering the 487variables such that the middle ones are first in the list: 488\begin{code} 489labeling_c(AllVars) :- 490 middle_first(AllVars, AllVarsPreOrdered), % static var-select 491 ( foreach(Var, AllVarsPreOrdered) do 492 indomain(Var) % select value 493 ). 494\end{code} 495The implementation of middle\_first/2 requries a bit of list manipulation 496\index{middle-first} 497and uses primitives from the lists-library: 498\begin{code} 499:- lib(lists). 500 501middle_first(List, Ordered) :- 502 halve(List, Front, Back), 503 reverse(Front, RevFront), 504 splice(Back, RevFront, Ordered). 505\end{code} 506This strategy also improves things for the 16-queens instance, the 507first solution requires 17 backtracks. 508 509We can now improve things further by {\bf combining} the two 510variable-selection strategies: 511When we pre-order the variables such that the middle ones are first, 512\index{delete/5} 513the delete/5 predicate will prefer middle variables when several 514have the same domain size: 515\begin{code} 516labeling_d(AllVars) :- 517 middle_first(AllVars, AllVarsPreOrdered), % static var-select 518 ( fromto(AllVarsPreOrdered, Vars, VarsRem, []) do 519 delete(Var, Vars, VarsRem, 0, first_fail), % dynamic var-select 520 indomain(Var) % select value 521 ). 522\end{code} 523The result is positive: for the 16-queens instance, 524the number of backtracks goes down to zero, 525and more difficult instances become solvable! 526 527Actually, we have not yet implemented our intuitive heuristics properly. 528We start placing queens in the middle columns, but not on the middle rows. 529With our model, that can only be achieved by {\bf changing the value selection}, 530ie.\ setting the variables to values in the middle of their domain first. 531For this we can use indomain/2, a more flexible variant of indomain/1, 532provided by the {\em ic_search} library. 533It allows us to specify that we want to start labeling with the middle value 534in the domain: 535\begin{code} 536labeling_e(AllVars) :- 537 middle_first(AllVars, AllVarsPreOrdered), % static var-select 538 ( fromto(AllVarsPreOrdered, Vars, VarsRem, []) do 539 delete(Var, Vars, VarsRem, 0, first_fail), % dynamic var-select 540 indomain(Var, middle) % select value 541 ). 542\end{code} 543Surprisingly, this improvement again increases the backtrack count for 54416-queens again to 3. 545However, when looking at a number of different instances of the problem, 546we can observe that the overall behaviour has improved and the 547performance has become more predictable than with the 548initial more naive strategies. 549Figure \ref{queensresult} shows the behaviour of the different 550strategies on various problem sizes. 551\begin{figure} 552\begin{center} 553\begin{tabular}{l|l|l|l|l|l|l|l|l} 554N = &8 &12 &14 &16 &32 &64 &128 &256\\ 555\hline 556labeling_a &10 &15 &103 &542 & & & &\\ 557labeling_b &10 &16 &11 &3 &4 &148 & &\\ 558labeling_c &0 &3 &22 &17 & & & &\\ 559labeling_d &0 &0 &1 &0 &1 &1 & &\\ 560labeling_e &3 &3 &38 &3 &7 &1 &0 &0\\ 561\end{tabular} 562\end{center} 563\label{queensresult} 564\caption{N-Queens with different labeling strategies: Number of backtracks} 565\end{figure} 566 567 568 569% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 570\subsection{Counting Backtracks} 571\index{backtrack count} 572% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 573 574%The size of the (remaining) search space can be computed easily 575%in finite-domain problems. All we have to do is to multiply the 576%sizes of all the (remaining) variable's domains: 577%\begin{quote}\begin{alltt} 578%search_space(Vars, Size) :- 579% ( foreach(V,Vars), fromto(1,S0,S1,Size) do 580% dvar_domain(V,D), S1 is S0*dom_size(D) 581% ). 582%\end{alltt}\end{quote} 583 584\label{countbt} 585An interesting piece of information during program development is the 586number of backtracks. It is a good measure for the quality of 587both constraint propagation and search heuristics. 588We can instrument our labeling routine as follows: 589\begin{code} 590labeling(AllVars) :- 591 init_backtracks, 592 ( foreach(Var, AllVars) do 593 count_backtracks, % insert this before choice! 594 indomain(Var) 595 ), 596 get_backtracks(B), 597 printf("Solution found after %d backtracks%n", [B]). 598\end{code} 599The backtrack counter itself can be implemented by the code below. 600It uses a non-logical counter variable (backtracks) and an additional 601flag (deep\_fail) which ensures that backtracking to exhausted choices 602does not increment the count. 603\begin{code} 604:- local variable(backtracks), variable(deep_fail). 605 606init_backtracks :- 607 setval(backtracks,0). 608 609get_backtracks(B) :- 610 getval(backtracks,B). 611 612count_backtracks :- 613 setval(deep_fail,false). 614count_backtracks :- 615 getval(deep_fail,false), % may fail 616 setval(deep_fail,true), 617 incval(backtracks), 618 fail. 619\end{code} 620Note that there are other possible ways of defining the number of backtracks. 621However, the one suggested here has the following useful properties: 622\begin{itemize} 623\item Shallow backtracking (an attempt to instantiate a variable which 624 \index{shallow backtrack} 625 causes immediate failure due to constraint propagation) is not counted. 626 If constraint propagation works well, the count is therefore zero. 627\item With a perfect heuristic, the first solution is found with zero 628 backtracks. 629\item If there are N solutions, the best achievable value is N (one backtrack 630 per solution). Higher values indicate an opportunity to improve pruning 631 by constraints. 632\end{itemize} 633 634The search/6 predicates from the libary {\tt ic_search} 635have this backtrack counter built-in. 636 637 638%---------------------------------------------------------------------- 639\section{Incomplete Tree Search} 640\index{incomplete search} 641%---------------------------------------------------------------------- 642 643The library {\tt ic_search} contains a flexible 644search routine 645\bipref{search/6}{../bips/lib/ic_search/search-6.html}, 646which implements several variants of incomplete tree search. 647 648For demonstration, we will use the N-queens problem from above. 649The following use of search/6 is equivalent to labeling(Xs) and 650will print all 92 solutions: 651\begin{quote}\begin{verbatim} 652?- queens(8, Xs), 653 search(Xs, 0, input_order, indomain, complete, []), 654 writeln(Xs), 655 fail. 656[1, 5, 8, 6, 3, 7, 2, 4] 657... 658[8, 4, 1, 3, 6, 2, 7, 5] 659No. 660\end{verbatim}\end{quote} 661 662 663% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 664\subsection{First Solution} 665% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 666 667One of the easiest ways to do incomplete search is to simply stop after 668the first solution has been found. This is simply programmed using cut or 669\index{first solution} 670\index{once/1} 671once/1: 672\begin{quote}\begin{verbatim} 673?- queens(8, Xs), 674 once search(Xs, 0, input_order, indomain, complete, []), 675 writeln(Xs), 676 fail. 677[1, 5, 8, 6, 3, 7, 2, 4] 678No. 679\end{verbatim}\end{quote} 680This will of course not speed up the finding of the first solution. 681 682 683% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 684\subsection{Bounded Backtrack Search} 685\index{bounded backtrack search} 686% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 687 688Another way to limit the scope of backtrack search is to keep a 689record of the number of backtracks, and curtail the search when this 690limit is exceeded. 691\begin{figure} 692\begin{center} 693\resizebox{0.6\textwidth}{!}{\includegraphics{bbs.eps}} 694\end{center} 695\caption{Bounded-backtrack search} 696\label{figbbs} 697\end{figure} 698The {\em bbs} option of the search/6 predicate implements this: 699\begin{quote}\begin{verbatim} 700?- queens(8, Xs), 701 search(Xs, 0, input_order, indomain, bbs(20), []), 702 writeln(Xs), 703 fail. 704[1, 5, 8, 6, 3, 7, 2, 4] 705[1, 6, 8, 3, 7, 4, 2, 5] 706[1, 7, 4, 6, 8, 2, 5, 3] 707[1, 7, 5, 8, 2, 4, 6, 3] 708No. 709\end{verbatim}\end{quote} 710Only the first 4 solutions are found, the next solution would have 711required more backtracks than were allowed. 712Note that the solutions that are found are all located on the left hand 713side of the search tree. This often makes sense because with a good 714search heuristic, the solutions tend to be towards the left hand side. 715Figure \ref{figbbs} illustrates the effect of bbs (note that the diagram 716does not correspond to the queens example, it shows an unconstrained search 717tree with 5 binary variables). 718 719 720% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 721\subsection{Depth Bounded Search} 722\index{depth-bounded search} 723% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 724 725A simple method of limiting search is to limit the depth of the search 726tree. In many constraint problems with a fixed number of variables 727this is not very useful, since all solutions occur at the same depth 728of the tree. However, one may want to explore the tree completely 729up to a certain depth and switch to an incomplete search method below this 730depth. The search/6 predicate allows for instance the combination of 731depth-bounded search with bounded-backtrack search. The following 732explores the first 2 levels of the search tree completely, and does not 733allow any backtracking below this level. 734\begin{figure} 735\begin{center} 736\resizebox{0.6\textwidth}{!}{\includegraphics{dbsbbs.eps}} 737\end{center} 738\caption{Depth-bounded, combined with bounded-backtrack search} 739\label{figdbsbbs} 740\end{figure} 741This gives 16 solutions, equally distributed over the search tree: 742\begin{quote}\begin{verbatim} 743?- queens(8, Xs), 744 search(Xs, 0, input_order, indomain, dbs(2,bbs(0)), []), 745 writeln(Xs), 746 fail. 747[3, 5, 2, 8, 1, 7, 4, 6] 748[3, 6, 2, 5, 8, 1, 7, 4] 749[4, 2, 5, 8, 6, 1, 3, 7] 750[4, 7, 1, 8, 5, 2, 6, 3] 751[4, 8, 1, 3, 6, 2, 7, 5] 752[5, 1, 4, 6, 8, 2, 7, 3] 753[5, 2, 4, 6, 8, 3, 1, 7] 754[5, 3, 1, 6, 8, 2, 4, 7] 755[5, 7, 1, 3, 8, 6, 4, 2] 756[6, 4, 1, 5, 8, 2, 7, 3] 757[7, 1, 3, 8, 6, 4, 2, 5] 758[7, 2, 4, 1, 8, 5, 3, 6] 759[7, 3, 1, 6, 8, 5, 2, 4] 760[8, 2, 4, 1, 7, 5, 3, 6] 761[8, 3, 1, 6, 2, 5, 7, 4] 762[8, 4, 1, 3, 6, 2, 7, 5] 763No (0.18s cpu) 764\end{verbatim}\end{quote} 765 766 767% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 768\subsection{Credit Search} 769\index{credit search} 770% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 771 772Credit search\cite{beldiceanu:credit} 773is a tree search method where the number of 774nondeterministic choices is limited a priori. This is achieved by 775starting the search at the tree root with a certain integral amount of 776credit. This credit is split between the child nodes, their credit 777between their child nodes, and so on. A single unit of credit cannot 778be split any further: subtrees provided with only a single credit unit 779are not allowed any nondeterministics choices, only one path though these 780subtrees can be explored, i.e. only one leaf in the subtree can be visited. 781Subtrees for which no credit is left are pruned, 782i.e.\ not visited. 783 784The following code (a replacement for labeling/1) 785implements credit search. For ease of understanding, it is 786limited to boolean variables: 787\begin{code} 788% Credit search (for boolean variables only) 789credit_search(Credit, Xs) :- 790 ( 791 foreach(X, Xs), 792 fromto(Credit, ParentCredit, ChildCredit, _) 793 do 794 ( var(X) -> 795 ParentCredit > 0, % possibly cut-off search here 796 ( % Choice 797 X = 0, ChildCredit is (ParentCredit+1)//2 798 ; 799 X = 1, ChildCredit is ParentCredit//2 800 ) 801 ; 802 ChildCredit = ParentCredit 803 ) 804 ). 805\end{code} 806Note that the leftmost alternative (here X=0) 807gets slightly more credit than the rightmost one (here X=1) 808by rounding the child node's credit up rather than down. 809This is especially relevant when the leftover credit is down to 1: 810from then on, only the leftmost alternatives will be taken until a 811leaf of the search tree is reached. The leftmost alternative should 812therefore be the one favoured by the search heuristics. 813 814What is a reasonable amount of credit to give to a search? 815In an unconstrained search tree, the credit is equivalent to the 816number of leaf nodes that will be reached. 817The number of leaf nodes grows exponentially with the number of 818labelled variables, while tractable computations should have 819polynomial runtimes. A good rule of thumb could therefore be to 820use as credit the number of variables squared or cubed, thus enforcing 821polynomial runtime. 822 823Note that this method in its pure form allows choices only close to the 824root of the search tree, and disallows choices completely below a certain 825tree depth. This is too restrictive when the value selection strategy 826is not good enough. A possible remedy is to combine credit search with 827bounded backtrack search. 828 829 830The implementation of credit search in the search/6 predicate works for 831arbitrary domain variables: Credit is distributed by giving half to the 832leftmost child node, half of the remaining credit to the second child node 833and so on. Any remaining credit after the last child node is lost. 834\begin{figure} 835\begin{center} 836\resizebox{0.6\textwidth}{!}{\includegraphics{credit.eps}} 837\end{center} 838\caption{Credit-based incomplete search} 839\label{figcredit} 840\end{figure} 841In this implementation, credit search is always combined with another 842search method which is to be used when the credit runs out. 843 844When we use credit search in the queens example, we get a limited number 845of solutions, but these solutions are not the leftmost ones (like with 846bounded-backtrack search), they are 847from different parts of the search tree, although biased towards the left: 848\begin{quote}\begin{verbatim} 849?- queens(8, Xs), 850 search(Xs, 0, input_order, indomain, credit(20,bbs(0)), []), 851 writeln(Xs), 852 fail. 853[2, 4, 6, 8, 3, 1, 7, 5] 854[2, 6, 1, 7, 4, 8, 3, 5] 855[3, 5, 2, 8, 1, 7, 4, 6] 856[5, 1, 4, 6, 8, 2, 7, 3] 857No. 858\end{verbatim}\end{quote} 859We have used a credit limit of 20. When credit runs out, we switch to 860bounded backtrack search with a limit of 0 backtracks. 861 862 863 864% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 865\subsection{Timeout} 866\index{timeout} 867% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 868 869Another form of incomplete tree search is simply to use time-outs. 870\index{bb_min/3} 871\index{bb_min/6} 872The branch-and-bound primitives {\tt bb_min/3,6} allow 873a maximal runtime to be specified. If a timeout occurs, the best solution 874found so far is returned instead of the proven optimum. 875 876A general timeout is available from the library {\tt test_util}. 877It has parameters {\tt timeout(Goal, Seconds, TimeOutGoal)}. 878When {\tt Goal} has run for 879more than {\tt Seconds} seconds, it is aborted and {\tt TimeOutGoal} 880is called instead. 881 882%---------------------------------------------------------------------- 883\subsection{Limited Discrepancy Search} 884\index{limited discrepancy search} 885%---------------------------------------------------------------------- 886 887% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 888%\subsubsection{Introduction} 889% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 890 891Limited discrepancy search ({\em LDS}) is a search method that assumes 892the user has a good heuristic for directing the search. A perfect 893heuristic would, of course, not require any search. However most 894heuristics are occasionally misleading. Limited Discrepancy Search 895follows the heuristic on almost every decision. The 896``discrepancy'' is a measure of the degree to which it fails to follow 897the heuristic. LDS starts searching with a discrepancy of $0$ (which 898means it follows the heuristic exactly). Each time LDS fails to find 899a solution with a given discrepancy, the discrepancy is increased and 900search restarts. In theory the search is complete, as eventually the 901discrepancy will become large enough to admit a solution, or cover 902the whole search space. In practice, however, it is only beneficial 903to apply LDS with small discrepancies. Subsequently, if no solution 904is found, other search methods should be tried. 905The definitive reference to LDS is \cite{harvey95:lds:inp} 906%\begin{quote} 907%Limited Discrepancy Search, Harvey and Ginsberg, 908%pp.607-613, Proc. IJCAI'95 909%\end{quote} 910 911\index{discrepancy} 912There are different possible ways of measuring discrepancies. 913The one implemented in the search/6 predicate is a variant of the 914original proposal. It considers the first 915value selection choice as the heuristically best value with 916discrepancy 0, the first alternative has a discrepancy of 1, the 917second a discrepancy of 2 and so on. 918\begin{figure} 919\begin{center} 920\resizebox{0.6\textwidth}{!}{\includegraphics{lds.eps}} 921\end{center} 922\caption{Incomplete search with LDS} 923\label{figlds} 924\end{figure} 925 926As LDS relies on a good heuristic, it only makes sense for the queens 927problem if we use a good heuristic, e.g. first-fail variable selection 928and indomain-middle value selection. Allowing a discrepancy of 1 yields 9294 solutions: 930\begin{quote}\begin{verbatim} 931?- queens(8, Xs), 932 search(Xs, 0, first_fail, indomain_middle, lds(1), []), 933 writeln(Xs), 934 fail. 935[4, 6, 1, 5, 2, 8, 3, 7] 936[4, 6, 8, 3, 1, 7, 5, 2] 937[4, 2, 7, 5, 1, 8, 6, 3] 938[5, 3, 1, 6, 8, 2, 4, 7] 939No. 940\end{verbatim}\end{quote} 941 942The reference also suggests that combining LDS with Bounded Backtrack 943Search ({\em BBS}) yields good behaviour. The search/6 predicate 944accordingly supports the combination of LDS with BBS and DBS. 945The rationale for this is that heuristic choices typically get 946more reliable deeper down in the search tree. 947 948 949%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 950%\subsubsection{Limited Discrepancy Search using a Static Heuristic} 951%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 952% 953%We start by assuming a static heuristic, which is a complete 954%assignment to the problem variables specified in advance of the 955%search. The predicate supporting static LDS takes a list of variables 956%(those which are to be labelled) and a list of values (one heuristic 957%value for each variable, respectively). Each variable has a finite 958%domain, and its heuristic value should belong to its domain (though 959%the LDS search can still succeed even if this is not the case). 960% 961%The measure of discrepancy, in this case, is simply the number of 962%variables labelled differently to the heuristic. Thus the maximum 963%discrepancy is just the number of variables to be 964%labelled. 965% 966%LDS search is implemented in the file 967%{\tt lds.ecl} in the {\tt doc/examples} directory of your 968%{\eclipse} installation. You can copy this file and load it with 969%\begin{quote}\begin{alltt} 970%:- use_module(lds). 971%\end{alltt}\end{quote} 972%Static LDS search is then available via the predicate 973%{\bf static_lds(Var, Vals, Discrepancy)} whose arguments are 974%\begin{description} 975%\item[Vars] the list of problem variables. Some of the 976%variables may already be instantiated. The others 977%must have associated finite domains. 978%\item[Vals] the list of values according to the heuristic. It 979%must be the same length as Vars, and the heuristic 980%must match the value, in case the variable is 981%already instantiated. 982%\item[Discrepancy] the discrepancy of the solution returned. Typically this 983%is an output of the search (an integer between $0$ and the number of 984%variables), but it can also be used as an input. 985%\end{description} 986%The finite domain library must be loaded, and the variables must have 987%finite domains. An example invocation is: 988%\begin{quote}\begin{alltt} 989%?- [X,Y,Z]::1..3, X+Y+Z#=5, static_lds([X,Y,Z],[1,2,3],D). 990%\end{alltt}\end{quote} 991%The answers are returned on backtracking in the following order: 992%\begin{itemize} 993%\item 994%X = 1 995%Y = 2 996%Z = 2 997%D = 1 998%\item 999%X = 1 1000%Y = 1 1001%Z = 3 1002%D = 1 1003%\item 1004%X = 1 1005%Y = 3 1006%Z = 1 1007%D = 2 1008%\item 1009%X = 2 1010%Y = 2 1011%Z = 1 1012%D = 2 1013%\item 1014%X = 2 1015%Y = 1 1016%Z = 2 1017%D = 3 1018%\item 1019%X = 3 1020%Y = 1 1021%Z = 1 1022%D = 3 1023%\end{itemize} 1024% 1025% 1026%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1027%\subsubsection{Limited Discrepancy Search using a Dynamic Heuristic} 1028%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1029% 1030%Often the heuristic value is calculated on the fly, during search. To 1031%cope with this we use the {\eclipse} ``tentative value'' facility in 1032%{\eclipse}'s {\em repair} library. 1033%The heuristic is stored with the variable as its tentative value. 1034% 1035%The tentative value may be changed during search. For example if a 1036%variable is instantiated as a consequence of constraint propagation 1037%during search, its tentative value is automatically changed to its 1038%actual value. 1039% 1040%Dynamic LDS search is available in {\eclipse} via the predicate 1041%{\bf dynamic_lds(Vars, Discrepancy)}. 1042%Each variable in the list of variables {\em Vars} 1043%must have a tentative value. 1044% 1045%An example invocation is: 1046%\begin{quote}\begin{alltt} 1047%?- [X,Y,Z]::1..3, [X,Y,Z] tent_set [1,2,3], X+Y+Z#=5, 1048% dynamic_lds([X,Y,Z],D). 1049%\end{alltt}\end{quote} 1050%The answers are returned on backtracking in the following order. 1051%Notice that the first solution has a discrepancy of $0$, because 1052%constraint propagation instantiates the third variable to $2$, 1053%thus changing its tentative value from $3$ to $2$. 1054%\begin{itemize} 1055%\item 1056%X = 1 1057%Y = 2 1058%Z = 2 1059%D = 0 1060%\item 1061%X = 1 1062%Y = 1 1063%Z = 3 1064%D = 1 1065%\item 1066%X = 1 1067%Y = 3 1068%Z = 1 1069%D = 1 1070%\item 1071%X = 2 1072%Y = 2 1073%Z = 1 1074%D = 1 1075%\item 1076%X = 3 1077%Y = 1 1078%Z = 1 1079%D = 1 1080%\item 1081%X = 2 1082%Y = 1 1083%Z = 2 1084%D = 2 1085%\end{itemize} 1086% 1087%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1088%\subsubsection{LDS and BBS Combined} 1089%% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1090% 1091%The two search techniques, BBS and LDS, can be merged quite simply in 1092%{\eclipse}, so that for each discrepancy level only a limited number of 1093%backtracks are allowed. 1094% 1095%An example invocation is: 1096%\begin{quote}\begin{alltt} 1097%?- Vars=[X,Y,Z], Vars::1..3, Vars tent_set [1,2,3], X+Y+Z#=6, 1098% bbs_dynamic_lds(Vars,4,D). 1099%\end{alltt}\end{quote} 1100%The answers are returned on backtracking in the following order: 1101%\begin{itemize} 1102%\item 1103%X = 1 1104%Y = 2 1105%Z = 3 1106%D = 0 1107%\item 1108%X = 1 1109%Y = 3 1110%Z = 2 1111%D = 1 1112%\item 1113%X = 2 1114%Y = 2 1115%Z = 2 1116%D = 1 1117%\item 1118%X = 3 1119%Y = 2 1120%Z = 1 1121%D = 1 \\ 1122%Backtrack limit exceeded 1123%\item 1124%X = 2 1125%Y = 1 1126%Z = 3 1127%D = 2 \\ 1128%Backtrack limit exceeded 1129%\end{itemize} 1130 1131%---------------------------------------------------------------------- 1132\section{Exercises} 1133%---------------------------------------------------------------------- 1134 1135For exercises 1-3, start from the constraint model for the queens problem 1136given in section \ref{queenscode}. It is available in the examples directory 1137as queens_ic.ecl. 1138 1139\begin{enumerate} 1140 1141\item Use the search/6 predicate from the ic_search library and the 1142standard model for the queens problem (given below) to find ONE 1143solution to the 42-queens problem. 1144With a naive search strategy this requires millions of backtracks. 1145Using heuristics and/or incomplete search, try to find a solution 1146in less than 100 backtracks! 1147 1148 1149\item How many solutions does the 9-queens problem have? 1150 1151 1152\item Solve the "8 sticky queens problem": Assume that the queens 1153in neighbouring columns want to stick together as close as possible. 1154Minimize the sum of the vertical distances between neighbouring queens. 1155What is the best and what is the worst solution for this problem? 1156 1157 1158\item For given N, create a list of length N whose members are numbers 1159between 1 and N (inclusive), which are all different (easy so far) 1160and satisfy the following constraint. 1161For each element E of the list, its successors are divided into two sets, 1162 \begin{itemize} 1163 \item BiggerE: the successors which are greater than E and 1164 \item SmallerE: the successors less than E. 1165 \end{itemize} 1166(Thus no successor takes the same value as E). 1167The cardinalities of the sets BiggerE and SmallerE differ by at most 1. 1168 1169 1170\item A harder version of the problem is similar. 1171For given N, create a list of length N whose members are numbers 1172between 1 and some upper bound Max (start with, say Max = $N^2$), 1173which are all different (easy so far) 1174and satisfy the following (more complex) constraint. 1175For each K from 1..N, call the Kth element of the list Ek. 1176Its successors are divided into two sets, as before: 1177 \begin{itemize} 1178 \item BiggerEk: the successors which are greater than or equal to Ek + K and 1179 \item SmallerEk: the successors less than or equal to Ek - K. 1180 \end{itemize} 1181(Thus no successor takes a value between Ek-K+1 and Ek+K-1.) 1182The cardinalities of the sets BiggerEk and SmallerEk differ 1183by at most 1. 1184 1185What is the smallest upper bound Max for which there is a feasible solution? 1186 1187\end{enumerate} 1188 1189%HEVEA\cutend 1190