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): Andrew Eremin, IC-Parc 20% 21% END LICENSE BLOCK 22 23:- comment(desc, html("\ 24<P> 25 This library lets you use customisable branch-and-bound search. It 26 is primarily intended for use with the colgen library in implementing 27 branch-and-price algorithms, but can be used with arbitrary 28 user-defined node solution, separation and selection goals. 29 When application specific methods are not required for node 30 separation and/or selection the use of built-in depth-first 31 and best-first node selection, and branching on most fractional 32 variable or generalised upper bound constraint may be specified. 33 When the relaxed problem to be solved at a node involves an eplex 34 instance branching may additionally be specified by built-in 35 objective coefficient, estimate- or lower-bounding based methods, 36 and best-estimate node selection may be used. 37</P> 38")). 39 40:- comment(statistics/0, [ 41template: "BfsInstance:statistics", 42summary: "Display search tree statistics for bfs instance BfsInstance.", 43see_also:[solver_setup/2, solver_setup/3, solve/1 44 ], 45desc: html("\ 46<P> 47 Display statistics for the search tree associated with the bfs 48 instance BfsInstance: total number of nodes created, total search 49 time, number of nodes solved, node solution time, number of nodes 50 separated, node separation time, total number of global feasible 51 solutions found, first and optimal global solution solution time. 52</P> 53") 54]). 55 56:- comment(solver_setup/2, [ 57template: "BfsInstance:solver_setup(+OptSense, +Solver)", 58args: ["OptSense": "Optimisation direction: min or max", 59 "Solver": "Node relaxation solver"], 60summary: "Setup a bfs solver tree for bfs instance BfsInstance.", 61see_also:[integers/1, bfs_branch/1, node_info/5, 62 solver_setup/3, solve/1, 63 get/2, var_get/3, bfs:statistics/0 64 ], 65desc: html("\ 66<P> 67 Setup a new solver tree for the bfs instance BfsInstance. The tree 68 will be associated with BfsInstance; BfsInstance must not already 69 have a solver tree associated with it. Once the solver tree is setup, 70 it can be optimised via solve/1. 71</P><P> 72 This is a simplified version of solver_setup/3, it is equivalent to 73 calling solver_setup/3 with the following default options: 74<PRE> 75 solver_setup(OptSense, Solver, []) 76</PRE> 77") 78]). 79 80:- comment(solver_setup/3, [ 81template: "BfsInstance:solver_setup(+OptSense, +Solver, ++ListOfOptions)", 82args: ["OptSense": "Optimisation direction: min or max", 83 "Solver": "Node relaxation solver", 84 "ListOfOptions": "List of solver options" 85 ], 86summary: "Setup a bfs solver tree for bfs instance BfsInstance.", 87see_also:[integers/1, bfs_branch/1, node_info/5, 88 solver_setup/2, solve/1, 89 get/2, var_get/3, bfs:statistics/0 90 ], 91desc: html("\ 92<P> 93 Setup a new solver tree for the bfs instance BfsInstance. The tree 94 will be associated with BfsInstance; BfsInstance must not already 95 have a solver tree associated with it. Once the solver tree is setup, 96 it can be optimised via solve/1. This predicate allow various 97 options to be specified when setting up the solver state via 98 <TT>ListOfOptions</TT>. 99</P><P> 100 <TT>OptSense</TT> is the optimisation direction. <B>Note</B> that this 101 is assumed to be the same as the sense of optimisation used in 102 <TT>Solver</TT>. It is the user's responsibility to ensure 103 that this is in fact the case. <TT>OptSense</TT> is used internally 104 for bound updates and pruning, and for node ordering with the built-in 105 best-first and best-estimate node selection methods. 106</P><P> 107 <TT>Solver</TT> is the node relaxed problem solver. It is either a 108 user-defined predicate or an eplex instance or handle, for which a 109 built-in node relaxation solver is available. 110 111</P><P> 112ListOfOptions are: 113 114<DL> 115 116<P> 117<DT><STRONG><TT>separation(+Separation)</TT></STRONG> 118 <DD>Use the specified method to separate the current node. 119 <TT>Separation</TT> is either a user-defined predicate, or one of 120 the atoms <TT>fracvar, enhanced, strong, deg_est</TT> 121 corresponding to the built-in separation methods. Note that the 122 methods <TT>enhanced, strong, deg_est</TT> are only available when 123 the node relaxation solver involves an eplex instance. 124 <TT>Separation</TT> defaults to fracvar. 125 126<P> 127<DT><STRONG><TT>node_select(+Select)</TT></STRONG> 128 <DD>Use the specified method (<TT>depth_first, best_first, 129 best_estimate</TT>) to select the next open node for solution and 130 separation. <TT>Select</TT> defaults to best_first. 131 132<P> 133<DT><STRONG><TT>alpha(?AlphaMin, ?AlphaMax)</TT></STRONG> 134 <DD>When using estimate- or lower-bounding based dichotomic node 135 separation methods the overall value assigned to branching on a 136 particular variable or constraint is calculated as a weighted sum 137 of the estimates obtained for the two branches it would produce. 138 AlphaMin is the weighting given to the minimum of the two estimates 139 and AlphaMax to the maximum. <TT>AlphaMin</TT> and <TT>AlphaMax</TT> 140 are numbers and default to 2 and 1 respectively. 141 142<P> 143<DT><STRONG><TT>beta(?BetaConst, ?BetaPC, ?BetaLB)</TT></STRONG> 144 <DD>When using estimate- or lower-bounding based node separation 145 methods with a problem involving an eplex instance the estimate 146 assigned to each branch produced by branching on a particular 147 variable or constraint is calculated as a weighted sum of the 148 pseudo-cost estimate and the lower bound. BetaPC is the weighting 149 given to the pseudo-cost estimate and BetaLB to the lower bound. 150 BetaConst is a constant offset only used when linear regression is 151 employed to update these values during search. <TT>BetaConst</TT>, 152 <TT>BetaPC</TT>, <TT>BetaLB</TT> are numbers and default to 0, 1, 153 1 respectively. 154 155<P> 156<DT><STRONG><TT>pseudo_cost(?PCInit, ?PCUpdate, ?PCRatio)</TT></STRONG> 157 <DD> 158 <P>When using estimate-based dichotomic node separation methods 159 with a problem involving an eplex instance up and down pseudo-costs 160 are assigned to each variable and generalised upper bound constraint 161 branch-point representing the estimated degradation in objective 162 cost per unit change in variable or constraint value incurred on 163 that branch. 164 </P><P><TT>PCInit</TT> specifies the method used to initialise these 165 values when a variable or constraint branch-point is first considered 166 for branching: 167 <DL> 168 <DD><TT>average</TT> : the pseudocosts are initialised to the average 169 of the observed changes in cost of all up or down branches in the 170 search tree. 171 <DD><TT>cost</TT> : variable pseudocosts are initialised to the 172 objective cost coefficient of the variable, constraint branch-point 173 pseudocosts to the average of the cost coefficients of variables 174 involved. 175 <DD><TT>calculated</TT> : the pseudocosts are initialised to a 176 value calculated by performing a number of external solver iterations 177 equal to <TT>(PCRatio * #iterations in root node)/(2* #fractional 178 vars in root node)</TT>. 179 </DL> 180 The default is <TT>calculated</TT>. 181 </P><P><TT>PCUpdate</TT> is an atom specifying the method used to 182 update these values throughout the search tree once the variable 183 or constraint has been branched on: 184 <DL> 185 <DD><TT>average</TT> : the pseudocosts are updated to the average 186 of the observed changes in cost of all up or down branches in the 187 search tree for that variable or constraint. 188 <DD><TT>first</TT> : the pseudocosts are fixed to the observed 189 change in cost at the first up or down branch in the search tree for 190 that variable or constraint. 191 <DD><TT>last</TT> : the pseudocosts are fixed to the observed 192 change in cost at the last up or down branch in the search tree for 193 that variable or constraint. 194 </DL> 195 The default is <TT>average</TT>. 196 </P><P><TT>PCRatio</TT> is a float between 0 and 1 and is used in 197 calculating the number of external solver iterations to perform 198 when explicitly calculating initial pseudo-cost estimates; the 199 default value is 0.05. Setting small ratios will result in faster 200 node separation, but the initial estimates for variables and 201 constraints on which the branching decisions are taken will be less 202 accurate. Setting larger values will result in more work being performed 203 in node separation and better estimates for the branching 204 decisions. The optimum value will be problem specific, although in 205 general the overhead of performing a total number of iterations 206 more than a small ratio of the root node iterations will outweigh the 207 benefit obtained. 208 209<P> 210<DT><STRONG><TT>lower_bound(+Limit)</TT></STRONG> 211 <DD>When using lower-bounding based node separation methods with a 212 problem involving an eplex instance, specify how many external solver 213 iterations should be performed to calculate the lower bound. 214 <TT>Limit</TT> is an integer and defaults to 1. Setting small 215 values of iterations will result in faster node separation, but the 216 lower bounds on which the branching decisions are taken will be less 217 tight. Setting larger values will result in more work being performed 218 in node separation and tighter lower bounds for the branching 219 decisions. The optimum value will be problem specific, although in 220 general the overhead of performing more than a few iterations will 221 outweigh the benefit obtained. 222 223<P> 224<DT><STRONG><TT>int_tolerance(+IntTol)</TT></STRONG> 225 <DD>Specify how far from integrality an integer variable's node 226 solution can fall before it is considered for separation by the 227 built-in separation methods. <TT>IntTol</TT> is a float and 228 defaults to 0.00001. 229<P> 230<DT><STRONG><TT>info_messages(+OnOff)</TT></STRONG> 231 <DD>Specify whether information messages should be output at 232 various points during solution. This option is most useful for 233 debugging purposes. OnOff is one of the atoms <TT>on</TT> or 234 <TT>off</TT>, the default is <TT>off</TT>. 235 236</DL> 237</P>") 238]). 239 240:- comment(bfs_branch/1, [ 241template: "BfsInstance:bfs_branch(+Branch)", 242args: ["Branch": "Prolog term" 243 ], 244summary: "Post a branching constraint to the bfs instance BfsInstance.", 245see_also: [solver_setup/2, solver_setup/3, get/2], 246desc: html("\ 247<P> 248 Post a new branching constraint <TT>Branch</TT> to the bfs instance 249 BfsInstance. The constraint will be used to create a new child node 250 of the current open node in the search tree for BfsInstance. 251 <TT>Branch</TT> may be any prolog term, but clearly should be an 252 appropriate constraint for the node relaxation solver associated with 253 BfsInstance. 254</P>") 255]). 256 257 258:- comment(solve/1, [ 259template: "BfsInstance:solve(-Cost)", 260args: ["Cost": "The optimal solution cost of the problem" 261 " associated with BfsInstance" 262 ], 263summary: "Optimise the problem associated with BfsInstance.", 264fail_if: "No solution exists satisfying the global feasibility conditions.", 265see_also: [solver_setup/2, solver_setup/3, get/2, var_get/3, bfs:statistics/0], 266desc: html("\ 267<P> 268 A solver setup with solver_setup/2 or solver_setup/3 is triggered 269 using this predicate. 270</P><P> 271 The node relaxation and separation solvers are applied to the next 272 selected node of the problem represented by Handle repeatedly until 273 no more open nodes remain. The criteria for node selection order 274 depends on the options given to solver_setup/2,3. solve/1 fails if 275 there is no solution or succeeds if an optimal solution is found, 276 returning the solution's cost in Cost. After a success, various 277 solution information and statistics can be retrieved using get/2, 278 var_get/3 and statistics/0. 279</P>") 280]). 281 282:- comment(node_cost/1, [ 283template: "BfsInstance:node_cost(+Val)", 284args: ["Val": "Solution cost for problem (number)" 285 ], 286summary: "Set solution cost for the problem at a node.", 287desc: html("\ 288<P> 289 Set the solution cost for the problem at the current open node of 290 the search tree associated with the bfs instance BfsInstance. 291</P>") 292]). 293 294:- comment(node_info/5, [ 295template: "BfsInstance:node_info(+Var, ?Lo, ?Hi, ?Val, ?RC)", 296args: ["Var": "A solver problem variable for solver the associated with BfsInstance", 297 "Lo": "Lower bound for Var (number)", 298 "Hi": "Upper bound for Var (number)", 299 "Val": "Solution value for Var (number)", 300 "RC": "Reduced cost for Var (number)" 301 ], 302summary: "Get or set node bounds and solution information for an individual" 303 " solver problem variable Var.", 304desc: html("\ 305<P> 306 Retrieve or update bounds and solution information for an 307 individual solver problem variable Var for the current open node of 308 the search tree associated with the bfs instance BfsInstance. If Var 309 was not already a problem variable for BfsInstance it will now be 310 considered one. If reduced costs are available in problems 311 involving eplex instances supplying these to the bfs solver can lead 312 to improved pruning. 313</P>") 314]). 315 316:- comment(var_get/3, [ 317template: "BfsInstance:var_get(+Var, ++What, -Value)", 318args: ["Var": "A solver problem variable for the solver associated with BfsInstance", 319 "What": "Specification for information wanted (atom)", 320 "Value": "Returned value of What" 321 ], 322summary: "Obtain information for an individual solver problem variable Var.", 323exceptions: [6: "What is not a valid value."], 324desc: html("\ 325<P> 326 Retrieve information about solver results related to a particular 327 variable, for the bfs instance BfsInstance. Fails if Var is not a 328 problem variable for BfsInstance. What can take one of the following 329 values: 330 331<DL> 332 <DT><TT>optimal_val</TT> 333 <DD>Returns the floating-point solution for variable Var. 334<P> 335 336 <DT><TT>node_val</TT> 337 <DD>Returns the floating-point solution for variable Var for the 338 current node in the search tree of this instance. 339<P> 340 341 <DT><TT>type</TT> 342 <DD>Returns the type real or integer of Var in this instance. 343</DL>") 344]). 345 346:- comment(get/2, [ 347template: "BfsInstance:get(++What, -Value)", 348args: ["What": "Specification for information wanted (atom)", 349 "Value": "Returned value of What" 350 ], 351summary: "Obtain information for the problem associated with BfsInstance.", 352exceptions: [6: "What is not a valid value."], 353desc: html("\ 354<P> 355 Retrieve information about the problem associated with the bfs 356 instance BfsInstance. What can take one of the following values: 357 358<DL> 359 <DT><TT>frac_vars</TT> 360 <DD>Returns the list of variables declared as integer for 361 BfsInstance which have fractional solution values in the current node 362 of the search tree. 363<P> 364 365 <DT><TT>branches</TT> 366 <DD>Returns the branching decisions taken from the root to the 367 current node of the search tree. 368<P> 369 370 <DT><TT>data</TT> 371 <DD>Returns the user-defined data associated with the instance. 372<P> 373 374 <DT><TT>node_count</TT> 375 <DD>Returns the total number of nodes in the search tree. 376</DL>") 377]). 378 379:- comment(integers/1, [ 380template: "BfsInstance:integers(+Ints)", 381args: ["Ints": "A variable or list of variables" 382 ], 383summary: "Declare Ints as integers in BfsInstance.", 384desc: html("\ 385<P> 386 The variable or list of variables Ints will be considered integers 387 when solving the problem associated with BfsInstance. Note that 388 this does not mean that they will be treated as integers by the 389 specified node relaxation solver, rather that they will be considered 390 as candidates for branching decisions in nodes where their solution 391 value is not integral (to within a tolerance parameter set in the 392 options list of BfsInstance:solver_setup/3). The predefined 393 node separation schemes will branch on these variables. User-defined 394 node separation predicates may access the fractional variables 395 at the current node via a call to BfsInstance:get/2"), 396see_also: [solver_setup/3, get/2] 397]). 398 399:- comment(bfs_instance/1, [ 400amode:bfs_instance(++), 401args: ["BfsInstance": "Bfs instance name (atom)" 402 ], 403summary: "Initialises the bfs instance BfsInstance.", 404desc: html("\ 405 <P> 406 Initialises the bfs instance BfsInstance. A bfs instance is an 407 instance of the best first search solver, with which node 408 relaxation and separation solvers can be associated and used to 409 optimise the problem constraints posted to the relaxed node solver 410 with respect to its objective using a specified node ordering scheme. 411 In particular best-first and best-estimate search schemes are 412 supported and application-specific schemes may be easily defined by 413 the user. 414 </P><P> 415 If BfsInstance is not an already existing bfs instance, a new bfs 416 instance will be created and initialised. If it is an existing bfs 417 instance, and it is not currently being used (having no associated 418 solvers), it is effectively reinitialised. Otherwise, the predicate 419 aborts with an error. Note that a bfs instance is a module, and each 420 bfs instance can be associated with at most one relaxation and one 421 separation solver at any time and vice versa. 422 </P> 423 "), 424see_also: [integers/1, bfs_branch/1, node_info/5, 425 solver_setup/2, solver_setup/3, solve/1, 426 get/2, var_get/3, bfs:statistics/0] 427]). 428 429 430 431 432