*Goal*- The (nondeterministic) search goal
*Cost*- A (usually numeric domain) variable representing the cost
*Options*- A bb_options structure or variable

The possible options are

**strategy:**-
- continue (default)
- after finding a solution, continue search with the newly found bound imposed on Cost
- restart
- after finding a solution, restart the whole search with the newly found bound imposed on Cost
- step
- a synonym for 'restart'
- dichotomic
- after finding a solution, split the remaining cost range and restart search to find a solution in the lower sub-range. If that fails, assume the upper sub-range as the remaining cost range and split again.

**from:**- number - an initial lower bound for the cost (default -1.0Inf). Only useful if Cost is not a domain variable.
**to:**- number - an initial upper bound for the cost (default +1.0Inf). Only useful if Cost is not a domain variable.
**delta:**- number - minimal absolute improvement required for each step (applies to all strategies). The default value of 1.0 is appropriate for integral costs. Any solution that improves on the best solution by less than this value will be missed.
**factor:**- number - minimal improvement ratio (with respect to the lower cost bound) for strategies 'continue' and 'restart' (default 1.0), or split factor for strategy 'dichotomic' (default 0.5)
**solutions:**-
- one (default)
- Compute one (of possibly multiple) optimal solutions.
- all
- Nondeterministically compute all optimal solutions. This has a performance penalty, as the search is restarted one more time after the optimum has been determined.

**timeout:**- number - maximum seconds of cpu time to spend (default: no limit)
**report_success:**- GoalPrefix/N - this specifies a goal to be invoked whenever the branch-and-bound process finds a better solution. GoalPrefix is a callable term (atom or compound) and N is an integer between 0 and 3. The invoked goal is constructed by adding N optional arguments to GoalPrefix: Cost, Handle and Module. Cost is a float number representing the cost of the solution found, Handle is a handle as accepted by bb_cost/2 or bb_solution/2, and Module is the context module of the minimisation. To disable any reporting, choose report_success:true/0. The default handler prints a message to log_output.
**report_failure:**- GoalPrefix/N - this specifies a goal to be invoked whenever the branch-and-bound process cannot find a solution in a cost range. GoalPrefix is a callable term (atom or compound) and N is an integer between 0 and 3. The invoked goal is constructed by adding N optional arguments to GoalPrefix: Cost, Handle and Module. Cost is a From..To structure representing the range of cost in which no solution could be found, Handle is a handle as accepted by bb_cost/2 or bb_solution/2, and Module is the context module of the minimisation. To disable any reporting, choose report_failure:true/0. The default handler prints a message to log_output.
**report_timeout:**- GoalPrefix/N - this specifies a goal to be invoked when the branch-and-bound process times out. GoalPrefix is a callable term (atom or compound) and N is an integer between 0 and 3. The invoked goal is constructed by adding N optional arguments to GoalPrefix: Cost, Handle and Module. Cost is a float number representing the cost of the best solution found, Handle is a handle as accepted by bb_cost/2 or bb_solution/2, and Module is the context module of the minimisation. To disable any reporting, choose report_timeout:true/0. The default handler prints a message to log_output.

bb_min(..., ..., bb_options{strategy:dichotomic, timeout:60})

In order to maximize instead of minimizing, introduce a negated cost variable in your model and minimize that instead, e.g.

% maximize Profit Cost #= -Profit, bb_min(search(...), Cost, bb_options{}),

- bb_min(+, ?, +) is nondet

% simple minimization with default options ?- bb_min(member(X,[9,6,8,4,7,2,4,7]), X, Options). Found a solution with cost 9 Found a solution with cost 6 Found a solution with cost 4 Found a solution with cost 2 Found no solution with cost -1.0Inf .. 1 X = 2 Options = bb_options(continue, -1.0Inf, 1.0Inf, 1, 1, 0, 0, _, _) yes. % coarser granularity: faster, but missing the optimum ?- bb_min(member(X,[9,6,8,4,7,2,4,7]), X, bb_options{delta:4}). Found a solution with cost 9 Found a solution with cost 4 Found no solution with cost -1.0Inf .. 0 X = 4 yes. % alternative strategy based on bisecting the cost space ?- bb_min(member(X,[99,60,80,40,70,30,70]), X, bb_options{strategy:dichotomic, from:0}). Found a solution with cost 99 Found a solution with cost 40 Found no solution with cost 0.0 .. 20.0 Found a solution with cost 30 Found no solution with cost 20.0 .. 25.0 Found no solution with cost 25.0 .. 27.5 Found no solution with cost 27.5 .. 28.75 Found no solution with cost 28.75 .. 29.0 X = 30 yes. % examples with library(ic) constraints ?- [X,Y,Z] :: 1..5, % constraints (model) X+Z #>=Y, C #= 3*X - 5*Y + 7*Z, % objective function bb_min(labeling([X,Y,Z]), C, _). % nondet search + b&b Found a solution with cost 5 Found a solution with cost 0 Found a solution with cost -2 Found a solution with cost -4 Found a solution with cost -6 Found no solution with cost -15.0 .. -7.0 X = 4 Y = 5 Z = 1 C = -6 Yes (0.00s cpu) ?- [X,Y,Z] :: 1..5, X+Z #>=Y, C #= 3*X - 5*Y + 7*Z, bb_min(search([X,Y,Z],0,input_order,indomain_middle,complete,[]), C, _). Found a solution with cost 15 Found a solution with cost 8 Found a solution with cost 1 Found a solution with cost -4 Found a solution with cost -6 Found no solution with cost -15.0 .. -7.0 X = 4 Y = 5 Z = 1 C = -6 Yes (0.00s cpu)