[ library(gfd) | Reference Manual | Alphabetic Index ]

# search(+L, ++Arg, ++Select, +Choice, ++Method, +Option)

Interface to gecode search-engines to perform search in gecode.

L
  is a collection (a la collection_to_list/2) of (domain) variables (Arg = 0) or a collection of terms (Arg > 0)
Arg
  is an integer, which is 0 if L is a collection of domain variables or greater than 0 if L consists of terms of arity greater than Arg, the value Arg indicates the selected argument of the term
Select
  is a predefined variable selection method. Available methods are input_order, first_fail, anti_first_fail, smallest, largest, occurrence, anti_occurrence, most_constrained, most_constrained_per_value, least_constrained_per_value, max_regret, max_regret_lwb, min_regret_lwb, max_regret_upb, min_regret_upb, random, random(+Seed), max_weighted_degree, max_weighted_degree_per_value, min_weighted_degree, min_weighted_degree_per_value, max_activity, max_activity_per_value, min_activity, min_activity_per_value, max_weighted_degree(+WP), max_weighted_degree_per_value(+WP), min_weighted_degree(+WP), min_weighted_degree_per_value(+WP), max_activity(+AP), max_activity_per_value(+AP), min_activity(+AP), min_activity_per_value(+AP)
Choice
  is the name of a predefine value choice method for choosing the value to try for a variable; Predefined choice methods are: indomain, indomain_reverse_enum, min, max, median, split, reverse_split, random, random(+Seed), interval_min, interval_max, from_smaller(P,Vals), from_larger(P,Vals), from_down(P,Vals), from_up(P,Vals)
Method
  is one of the following: complete, bb_min(Cost:domain variable), restart_min(Cost:domain variable), restart_min(Cost:domain variable,Cutoff), restart_min(Cost:domain variable,Cutoff,Lim), restart(Cutoff), restart(Cutoff,Lim)
Option
  is a list of option terms. Currently recognized are: tiebreak(+Select), stats(+Stats), limits(+Stop), timeout(+Seconds), control(+Control), backtrack(-N), nodes(+N), ldsb_syms(+Syms)

## Description

Search/6 provides an interface to gecode's search-engine, allowing search to be performed by gecode. It is designed to have the same arguments as the generic search/6 routine available for integer domain solvers. so that for common cases, the call will work for both search/6. The generic search/6 is available in the gfd_search module. The difference is that here the search is performed by gecode, and is an atomic step when viewed from ECLiPSe. In addition, this predicat support features of gecode's search engine not in generic search, such as variable selection methods based on propagation history, optimising and restart-based search methods, symmetry breaking with LDSB and searching in parallel. L, using the search method specified by Method, with variable and value selection methods specified by Select and Choice,respectively. For search methods that cab produce multiple solutions, backtracking into the predicate will produce the next solution if it exists. The search can be controlled further via the terms specified in Options.

In order to allow more structure in the application program, L can be a collection of compound terms rather than just domain variables. In this way all information about some entity can be easily grouped together. The terms can include items that are associated with the domain variable needed in some of the labelling methods. In addition, to allow L to reflect structures in the problem, it can be a nested collection such as a matrix.

Search methods are implmeneted by gecode's search engines. These include optimising and restart based search methods, which are not available in generic search. The optimising search methods provide some of the functionality in.lib(branch_and_bound), and is likely to be faster, but less flexible. The optimising search methods returns a single optimal solution by finding succesively better feasible solutions until no better solution can be found. If the search is terminated early, e.g. because of time-out, the best feasible solution, will be returned.

Symmetry breaking using Lightweight Dynamic Symmetry Breaking (LDSB) can be specified in the Option argument, and can be used with all search methods and most variable selection methods.

The variable selection and value choice methods are defined by gecode. They are mapped to the closest matching methods in the generic search/6 (or with a name following the same convention if the method have no correspondence). Note that except for indomain and indomain_reverse_enum, the indomain style selection methods of generic search, are not supported. Instead, most value choice methods makes a two-way choice like the methods in try_value/2. At each choice, a variable is selected, and two alternatives are created that reduces the variable's domain in complementary ways.

For source compatibility with code written for the IC and FD solvers, the generic search's indomain style method names are also accepted, but are mapped to the closest two-way choice method, e.g.indomain_min is translated to min.

For variable selection, if several entries have the same heuristic value, then a tiebreak selection method, specified by the tiebreak option term, can be used to chose from these entries.

Several of the variable selection methods makes use of one of two dynamic measurements of gecode's constraint propagation performed by the program so far: 1) Weighted degree, called AFC (accumulated failure count) in gecode; 2) Activity. These two measurements may make better variable selection in many programs because it is based on actual constraint propagation performed.

Weighted degree is a count of the number of failures so far of propagators associated with the variable. By default, the starting count is set to the number of propagator attached to the variable, to give reasonable starting values for variable selection.

Activity is a count of the number of domain reductions on the variable during propagation so far.

A decay factor (between 0 and 1) can be specified for both measure so that the count for a variable can be reduced by the Factor if it is not incremented.

The pre-defined selection methods (with the gecode name in brackets) use the following criteria:

- input_order (INT_VAR_NONE) the first entry in the list is selected
- random (INT_VAR_RND) an entry is selected at random.
- random(+Seed) (INT_VAR_RND) an entry is selected at random, with the random seed Seed. Seed is a non-negative integer.
- anti_occurrence (INT_VAR_DEGREE_MIN) the entry whose corresponding gecode variable with the smallest number of attached propagators is selected
- occurrence (INT_VAR_DEGREE_MAX) the entry whose corresponding gecode variable with the largest number of attached propagators is selected
- max_weighted_degree max_weighted_degree(+WDParams) (INT_VAR_AFC_MAX) the entry with the largest weighted degree is selected. The optional WDParams argument is a list of parameters for initialising the weighted degree.
- max_weighted_degree_per_value max_weighted_degree_per_value(+WDParams) (INT_VAR_AFC_SIZE_MIN) the entry with the smallest weighted degree divided by domain size is selected. The optional WDParams argument is a list of parameters for initialising the weighted degree. The parameters are:
  - decay(Decay) specify the decay factor (number between 0 and 1, where 1 is no decay). Default is the existing decay factor for weighted degree (normally 1, unless explicitly changed).
  - init(Init) re-initialise the weighted degree values before starting the search according to Init. Init can be:
    - degree(+Factor) set the value of the weighted degree for a problem variable to Factor*degree for the variable. Factor is a non-negative number. If Factor is 1, then the weighted degree for each variable will be its degree, the default initial value for weighted degree.
    - none no initialisation is done. This is the default.
- min_weighted_degree min_weighted_degree(+WDParams) (INT_VAR_AFC_MIN) the entry with the smallest weighted degree is selected. The optional WDParams argument is a list of parameters for initialising the weighted degree.
- min_weighted_degree_per_value min_weighted_degree_per_value(+WDParams) (INT_VAR_AFC_SIZE_MAX) the entry with the largest weighted degree divided by domain size is selected. The optional WDParams argument is a list of parameters for initialising the weighted degree.
- max_activity max_activity(+AParams) (INT_VAR_ACTIVITY_MAX) the entry with the largest activity is selected. Activity for a variable Activity is a measure of how much that variable was involved in constraint propagation. Note that activity is maintained by gecode's search engine for the search variables, and is not available outside.

  The parameters are:

  - decay(Decay) specify the decay factor (number between 0 and 1, where 1 is no decay). Default is 1.
  - init(Init) set the start values for activity for the search variables according to Init. Init can be:
    - degree(+Factor) set the start value to Factor*degree for the variable. Factor is a non-negative number.
    - vals(Pos,Starts) set the start values to those specified in Starts. Starts is a collection of either the start values (Pos=0), or compound terms containing the value, in the Pos'th argument. The number of start values is the same as the number of variable, and each value is a non-negative number.
    - none no initialisation (default)
- max_activity_per_value max_activity_per_value(+AParams) (INT_VAR_ACTIVITY_SIZE_MAX) the entry with the largest activity divided by domain size is selected.
- min_activity min_activity(+AParams) (INT_VAR_ACTIVITY_MIN) the entry with the smallest activity is selected. min_activity_per_value min_activity_per_value(+AParams) (INT_VAR_ACTIVITY_SIZE_MIN) the entry with the smallest activity divided by domain size is selected.
- smallest (INT_VAR_MIN_MIN) the entry with the smallest value in the domain is selected
- smallest_upb (INT_VAR_MIN_MAX) the entry with the smallest upper bound in the domain is selected
- largest_lwb (INT_VAR_MAX_MIN) the entry with the largest lower bound in the domain is selected
- largest (INT_VAR_MAX_MAX) the entry with the largest value in the domain is selected
- first_fail (INT_VAR_SIZE_MIN) the entry with the smallest domain size is selected
- anti_first_fail (INT_VAR_SIZE_MAX) the entry with the largest domain size is selected
- least_constrained_per_value (INT_VAR_DEGREE_SIZE_MAX) the entry with the largest number of attached propagators divided by domain size.
- most_constrained_per_value (INT_VAR_DEGREE_SIZE_MIN) the entry with the smallest number of attached propagators divided by the domain size.
- min_regret_lwb (INT_VAR_REGRET_MIN_MIN) the entry with the smallest difference between the smallest and second smallest value in the domain is selected.
- max_regret (INT_VAR_REGRET_MIN_MAX) the entry with the largest difference between the smallest and second smallest value in the domain is selected. This method is typically used if the variable represents a cost, and we are interested in the choice which could increase overall cost the most if the best possibility is not taken. Unfortunately, the implementation sometimes does not always work. If two decision variables incur the same minimal cost, the regret is not calculated as zero, but as the difference from this minimal value to the next greater value. Note this is an alias for max_regret_lwb
- max_regret_lwb (INT_VAR_REGRET_MIN_MAX) is an alias to max_regret.
- min_regret_upb (INT_VAR_REGRET_MAX_MIN) the entry with the smallest difference between the largest and second largest value in the domain is selected.
- max_regret_upb (INT_VAR_REGRET_MAX_MAX) the entry with the largest difference between the largest and second largest value in the domain is selected.
- most_constrained (INT_VAR_SIZE_MIN, INT_VAR_DEGREE_MAX) the entry with the smallest domain size is selected. If several entries have the same domain size, the entry with the largest number of attached constraints is selected. This is provided for compatibility, as this define a tiebreak method (occurrence). Any tiebreak method defined in options is ignored.

The pre-defined choice methods (with gecode name in brackets) have the following meaning:

- indomain (INT_VALUES_MIN) Values are tried in increasing order.
- indomain_reverse_enum (INT_VALUES_MAX) Values are tried in decreasing order.
- min (INT_VAL_MIN) Minimum value in the domain (alias: indomain_min).
- max (INT_VAL_MAX) Maximum value in the domain (alias: indomain_max).
- median(INT_VAL_MED) Median value of the domain Note median is defined differently from IC (alias: indomain_median).
- random (INT_VAL_RND) Random element in the domain is selected (alias: indomain_random).
- random(+Seed) (INT_VAL_RND) Random element in the domain is selected The random sequence is initialised with seed Seed, which is a non-negative integer.
- split (INT_VAL_SPLIT_MIN) try first the lower domain half, then the upper (alias: indomain_split).
- reverse_split (INT_VAL_SPLIT_MAX) try first the upper domain half, then the lower (alias: indomain_reverse_split).
- interval_min (INT_VAL_RANGE_MIN) If the domain consists of several intervals, chose the smallest interval. For one interval, split is used. (alias: indomain_interval)
- interval_max (INT_VAL_RANGE_MAX) If the domain consists of several intervals, chose the largest interval. the interval, choosing the largest interval. For one interval, reverse_split is used
- from_larger(+Pos,+Suggestions) (INT_VAL_NEAR_MAX) Suggestions is a collection containing suggested values, one for each search variable. For each variable, pick the domain value nearest its corresponding suggested value. If there is a tie, chose the larger value.

  If Pos is 0, then Suggestions is a collection of values. If Pos > 0, then Suggestions is a collection of structures, with the suggested value in the Pos'th argument of the structure. The idea is that the same structure can be used to store both the variable and its suggested value, e.g. as a pair Var-2.

- from_smaller(+Pos,+Suggestions) (INT_VAL_NEAR_MAX) similar to from_larger, except chose the smaller value if there is a tie.
- from_down(+Pos,+Suggestions) (INT_VAL_NEAR_DEC) similar to from_larger, except chose values smaller than the suggested value first.
- from_up(+Pos,+Suggestions) (INT_VAL_NEAR_INCC) similar go from_down, except chose values larger than its suggested value first.

The different search methods are

- complete (DFS) a complete search routine which explores all alternative choices. Alternative solutions are returned on backtracking
- bb_min(Cost) (BAB) Branch-and-bound search to find the minimal value for the cost variable Cost. This should be a domain variable that is instantiated at the end of the search. The search will return an optimal solution, unless terminated early, in which case, the best solution found (if there is one) is returned. If Cost variable is not instantiated at the end of the search, the search is aborted. This provide some of the functionality of branch-and-bound search in lib(branch_and_bound), but is less flexible (no user defined search) but is likely to be faster. Will only return one optimal solution.
- restart(+Cutoff [,+Nogoodslim]) (RBS with DFS) Restart search will restart the search when the number of nodes searched exceeds the cutoff threshold. The threshold can change with successive restart, and is specified by Cutoff. Nogoodslim is an optional argument, which if supplied, nogoods learning will be performed during the search, and no-good constraints learned from the old search are posted before restarting the search.

  Cutoff specifies the cutoff threshold sequence. The following are available:

  - geo(+S, +Base) Geometric cutoff with a scale factor S and base Base (both non-negative integers). The cutoff thresholds are defined by S*(Base^N), where N is the Nth restart.
  - luby(+S) the cutoff sequence is based on the Luby sequence, multiplied by the scale factor S (non-negative integer). The Luby sequence is a sequence of restart thresholds suggested by Luby and others in 1993.
  - random(+Min,+Max,+N,+Seed) the cutoff value is chosen randomly between Min and Max, with only N+1 values distributed evenly in the range are available for selection, to make sure that values chosen are significantly different from each other.
  - con(+C) the same cutoff value C (positive integer) is used for all restarts.
  - lin(+S) The cutoff value is increased by S (positive integer) for each restart.

  Nogoodslim (non-negative integer) specifies the depth limit in the search-tree to which no-goods will be learned. Setting this to 0 (zero) is the same as not using no-goods.

- restart_min(Cost [,+Cutoff [,+Nogoodslim]]) (RBS with BAB) Branch-and-bound search as in bb_min, but the search is restarted after finding a new solution and imposing the new bound. Optionally, if Cutoff is supplied, the search will also restart when the number of nodes searched exceed the given Cutoff. An additional optional argument NogoodsLim can also be supplied that will use no-good learning.

The option list is used to pass additional parameters to and from the procedure. The currently recognized options are:

- tiebreak(+Selection) Selection is one of the variable selection methods, and is used as a tie-break if the primary selection method yields more than one candidate. Obviously not all combinations of selection methods makes sense (e.g. it should not be the same as the primary), but no check is done, they are simply passed to gecode.
- stats(+Stats) Stats is a named gfd_stats structure, defined as:

      :- export struct(gfd_stats(prop,fail,node,depth,mem)).

  The fields of the structure should be uninstantiated, and the search predicate will instantiate the fields with statistics obtained from gecode for the search: prop for the number of propagations, fail for the number of failed nodes, node for number of nodes expanded, depth for maximum depth of search stack, mem for peak memory allocated (in bytes).
- timeout(+Seconds) Specify the number of seconds that the search will be performed before it is terminated. Seconds can be a real or integer number, and 0 means there is no timeout. For multi-solution search, the timer is reset each time a new solution is obtained. For optimising search, the best feasible solution found so far, if any, is returned.
- limits(+Stats) Specify limits to stop the search. Stats is the same gfd_stats struct used for obtaining statistics. To specify a limit for a particular statistics, the corresponding field should be instantiated to the limit. Only the prop, node, fail and mem fields are significant. Entries in the other fields are ignored. For optimising search, the best feasible solution found so far, if any, is returned.
- control(+Control) Control is a named gfd_control structure, defined as:

       :- export struct(gfd_control(commit_distance,adaptive_distance,threads)).

  This is used to pass information to gecode to control the search. The corresponding field should be instantiated to the value passed to gecode. threads may be of most interest as if threads is set to a value >= 2, this will allow parallel search. See the gecode manual for more details on the options.
- backtrack(-N) Provided for compatibility with generic search/6. Returns the number of fail nodes (fail field of statistics.
- nodes(++N) Provided for compatibility with generic search/6. Equivalent to setting the node field of limits. The node field will be unified with N
- ldsb_syms(+Syms) Use Lightweight Dynamic Symmetry Breaking (LDSB) to reduce the search-space. The symmetries for the problem are specified in Syms, which is a list of symmetry specifications. The syntax for the symmetry specifications are compatible with the ones used in ip{ldsb_initialise/2} of lib(ldsb), the LDSB library for IC.

  Some of the symmetry specifications expect a matrix of NRows rows by NCols columns. Such an argument should be supplied as a 2-D collection, i.e. either as a Matrix M with dimensions dim(M, [NRows,NCols]), or a list of NRows lists, where the sub-lists are all the same length of NCols items.

  Some of the symmetry specifications can be applied to all the search variables (i.e. the first argument (L) of the predicate), or to a subset. For such specifications, if the specification includes a collection of variables, these will be used; otherwise it is applied to all search variables. Note that the same form is expected for variables given with the specification and those in L, i.e. the variables will be in the same Arg'th position of the items in the collection given for L and in any symmetry specifications.

  The following are available:

  - value_interchange(+Vars) specifies that the variables in collection Vars are interchangeable.
  - variable_interchange(++Vals) specifies that the values in collection Vals are interchangeable.
  - variables_interchange specifies that all search variables are interchangeable.
  - parallel_variable_interchange(+Vars) Vars is a 2-D collection of search variables. This specifies that the variables in the sub-list or sub-vector are interchangeable, e.g. parallel_variable_interchange([]([](A,B),[](C,D),[](E,F))) says that the sequence A-B can be interchanged with the sequence C-D and E-F.
  - parallel_value_interchange(++Vals) Vals is a 2-D collection of values. This specifies that the value sequences in each sub-vector or sub-list in Vals are interchangeable.
  - value_reflection(+L,+U) specifies the values L..U can be reflected, i.e. vale L+i maps to U-1.
  - rows_interchange rows_interchange(+MatVars) specifies that the rows of the matrix is interchangeable. The matrix is either given in MatVars, or is all the search variables (L), and must be in matrix form.
  - columns_interchange columns_interchange(+MatVars) specifies that the columns of matrix are interchangeable. The matrix is either given in MatVars, or is all the search variables L, and must be in matrix form.
  - row_reflection rows_reflection(+MatVars) specifies that the rows of the matrix can be reflected around their centre. The matrix is either given in MatVars, or is all the search variables L), and must be in matrix form.
  - column_reflection columns_reflection(+MatVars) specifies that the columns of the matrix can be reflected around their centre. The matrix must be a square matrix, and can be either given in MatVars, or is all the search variables (L), and must be in matrix form.
  - diagonal_reflection diagonal_reflection(+MatVars) specifies that the variables of the matrix can be reflected around the main diagonal of the matrix. The matrix must be a square matrix, and is either given in MatVars, or is all the search variables (L), and must be in matrix form.

### Modes and Determinism

- search(+, ++, ++, +, ++, +) is nondet

### Fail Conditions

Fails if the search engine does not find any solution. For partial search methods, this does not mean that the problem does not have a solution.

### Resatisfiable

yes (non-optimising and non-restart searches)

## Examples

    top:-
    	length(L,8),
    	L :: 1..8,
    	search(L,0,input_order,indomain,complete,[]).

    top:-
            length(L,8),
            L::1..8,
            L = [Cost|L],
            search(L,0,input_order,indomain_max,bb_min(Cost),[]).

    :- local struct(data(var,start)).
    top(Ds) :-
    	length(L, 8),
    	L :: 1..8,
    	(foreach(V, L),
     	 count(I, 1, _),
    	 foreach(D, Ds) do
    		D = data{var:V,start:I}
    	),
    	search(Ds, var of data, input_order,
    	       from_larger(start of data,Ds), complete, []).

## See Also

indomain / 1, gfd_search : indomain / 2, labeling / 1, gfd_search : delete / 5, gfd_search : search / 6