You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1090 lines
						
					
					
						
							37 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1090 lines
						
					
					
						
							37 KiB
						
					
					
				| %* glpk05.tex *% | |
|  | |
| \chapter{Branch-and-Cut API Routines} | |
| 
 | |
| \section{Introduction} | |
| 
 | |
| \subsection{Using the callback routine} | |
| 
 | |
| The GLPK MIP solver based on the branch-and-cut method allows the | |
| application program to control the solution process. This is attained | |
| by means of the user-defined callback routine, which is called by the | |
| solver at various points of the branch-and-cut algorithm. | |
| 
 | |
| The callback routine passed to the MIP solver should be written by the | |
| user and has the following specification:\footnote{The name | |
| {\tt foo\_bar} used here is a placeholder for the callback routine | |
| name.} | |
| 
 | |
| \begin{verbatim} | |
|    void foo_bar(glp_tree *T, void *info); | |
| \end{verbatim} | |
| 
 | |
| \noindent | |
| where \verb|tree| is a pointer to the data structure \verb|glp_tree|, | |
| which should be used on subsequent calls to branch-and-cut interface | |
| routines, and \verb|info| is a transit pointer passed to the routine | |
| \verb|glp_intopt|, which may be used by the application program to pass | |
| some external data to the callback routine. | |
| 
 | |
| The callback routine is passed to the MIP solver through the control | |
| parameter structure \verb|glp_iocp| (see Chapter ``Basic API | |
| Routines'', Section ``Mixed integer programming routines'', Subsection | |
| ``Solve MIP problem with the branch-and-cut method'') as follows: | |
| 
 | |
| \begin{verbatim} | |
|    glp_prob *mip; | |
|    glp_iocp parm; | |
|    . . . | |
|    glp_init_iocp(&parm); | |
|    . . . | |
|    parm.cb_func = foo_bar; | |
|    parm.cb_info = ... ; | |
|    ret = glp_intopt(mip, &parm); | |
|    . . . | |
| \end{verbatim} | |
| 
 | |
| To determine why it is being called by the MIP solver the callback | |
| routine should use the routine \verb|glp_ios_reason| (described in this | |
| section below), which returns a code indicating the reason for calling. | |
| Depending on the reason the callback routine may perform necessary | |
| actions to control the solution process. | |
| 
 | |
| The reason codes, which correspond to various point of the | |
| branch-and-cut algorithm implemented in the MIP solver, are described | |
| in Subsection ``Reasons for calling the callback routine'' below. | |
| 
 | |
| To ignore calls for reasons, which are not processed by the callback | |
| routine, it should simply return to the MIP solver doing nothing. For | |
| example: | |
| 
 | |
| \begin{verbatim} | |
| void foo_bar(glp_tree *T, void *info) | |
| {     . . . | |
|       switch (glp_ios_reason(T)) | |
|       {  case GLP_IBRANCH: | |
|             . . . | |
|             break; | |
|          case GLP_ISELECT: | |
|             . . . | |
|             break; | |
|          default: | |
|             /* ignore call for other reasons */ | |
|             break; | |
|       } | |
|       return; | |
| } | |
| \end{verbatim} | |
| 
 | |
| To control the solution process as well as to obtain necessary | |
| information the callback routine may use the branch-and-cut API | |
| routines described in this chapter. Names of all these routines begin | |
| with `\verb|glp_ios_|'. | |
| 
 | |
| \subsection{Branch-and-cut algorithm} | |
| 
 | |
| This section gives a schematic description of the branch-and-cut | |
| algorithm as it is implemented in the GLPK MIP solver. | |
| 
 | |
| {\it 1. Initialization} | |
| 
 | |
| Set $L:=\{P_0\}$, where $L$ is the {\it active list} (i.e. the list of | |
| active subproblems), $P_0$ is the original MIP problem to be solved. | |
| 
 | |
| Set $z^{\it best}:=+\infty$ (in case of minimization) or | |
| $z^{\it best}:=-\infty$ (in case of maximization), where $z^{\it best}$ | |
| is {\it incumbent value}, i.e. an upper (minimization) or lower | |
| (maximization) global bound for $z^{\it opt}$, the optimal objective | |
| value for $P^0$. | |
| 
 | |
| {\it 2. Subproblem selection} | |
| 
 | |
| If $L=\varnothing$ then GO TO 9. | |
| 
 | |
| Select $P\in L$, i.e. make active subproblem $P$ current. | |
| 
 | |
| \newpage | |
| 
 | |
| {\it 3. Solving LP relaxation} | |
| 
 | |
| Solve $P^{\it LP}$, which is LP relaxation of $P$. | |
| 
 | |
| If $P^{\it LP}$ has no primal feasible solution then GO TO 8. | |
| 
 | |
| Let $z^{\it LP}$ be the optimal objective value for $P^{\it LP}$. | |
| 
 | |
| If $z^{\it LP}\geq z^{\it best}$ (minimization) or | |
| $z^{\it LP}\leq z^{\rm best}$ (), GO TO 8. | |
| 
 | |
| {\it 4. Adding ``lazy'' constraints} | |
| 
 | |
| Let $x^{\it LP}$ be the optimal solution to $P^{\it LP}$. | |
| 
 | |
| If there are ``lazy'' constraints (i.e. essential constraints not | |
| included in the original MIP problem $P_0$), which are violated at the | |
| optimal point $x^{\it LP}$, add them to $P$, and GO TO 3. | |
| 
 | |
| {\it 5. Check for integrality} | |
| 
 | |
| Let $x_j$ be a variable, which is required to be integer, and let | |
| $x^{\it LP}_j\in x^{\it LP}$ be its value in the optimal solution to | |
| $P^{\it LP}$. | |
| 
 | |
| If $x^{\it LP}_j$ are integral for all integer variables, then a better | |
| integer feasible solution is found. Store its components, set | |
| $z^{\it best}:=z^{\it LP}$, and GO TO 8. | |
| 
 | |
| {\it 6. Adding cutting planes} | |
| 
 | |
| If there are cutting planes (i.e. valid constraints for $P$), | |
| which are violated at the optimal point $x^{\it LP}$, add them to $P$, | |
| and GO TO 3. | |
| 
 | |
| {\it 7. Branching} | |
| 
 | |
| Select {\it branching variable} $x_j$, i.e. a variable, which is | |
| required to be integer, and whose value $x^{\it LP}_j\in x^{\it LP}$ is | |
| fractional in the optimal solution to $P^{\it LP}$. | |
| 
 | |
| Create new subproblem $P^D$ (so called {\it down branch}), which is | |
| identical to the current subproblem $P$ with exception that the upper | |
| bound of $x_j$ is replaced by $\lfloor x^{\it LP}_j\rfloor$. (For | |
| example, if $x^{\it LP}_j=3.14$, the new upper bound of $x_j$ in the | |
| down branch will be $\lfloor 3.14\rfloor=3$.) | |
| 
 | |
| Create new subproblem $P^U$ (so called {\it up branch}), which is | |
| identical to the current subproblem $P$ with exception that the lower | |
| bound of $x_j$ is replaced by $\lceil x^{\it LP}_j\rceil$. (For example, | |
| if $x^{\it LP}_j=3.14$, the new lower bound of $x_j$ in the up branch | |
| will be $\lceil 3.14\rceil=4$.) | |
| 
 | |
| Set $L:=(L\backslash\{P\})\cup\{P^D,P^U\}$, i.e. remove the current | |
| subproblem $P$ from the active list $L$ and add two new subproblems | |
| $P^D$ and $P^U$ to it. Then GO TO 2. | |
| 
 | |
| {\it 8. Pruning} | |
| 
 | |
| Remove from the active list $L$ all subproblems (including the current | |
| one), whose local bound $\widetilde{z}$ is not better than the global | |
| bound $z^{\it best}$, i.e. set $L:=L\backslash\{P\}$ for all $P$, where | |
| $\widetilde{z}\geq z^{\it best}$ (in case of minimization) or | |
| $\widetilde{z}\leq z^{\it best}$ (in case of maximization), and then | |
| GO TO 2. | |
| 
 | |
| The local bound $\widetilde{z}$ for subproblem $P$ is an lower | |
| (minimization) or upper (maximization) bound for integer optimal | |
| solution to {\it this} subproblem (not to the original problem). This | |
| bound is local in the sense that only subproblems in the subtree rooted | |
| at node $P$ cannot have better integer feasible solutions. Note that | |
| the local bound is not necessarily the optimal objective value to LP | |
| relaxation $P^{\it LP}$. | |
| 
 | |
| {\it 9. Termination} | |
| 
 | |
| If $z^{\it best}=+\infty$ (in case of minimization) or | |
| $z^{\it best}=-\infty$ (in case of maximization), the original problem | |
| $P_0$ has no integer feasible solution. Otherwise, the last integer | |
| feasible solution stored on step 5 is the integer optimal solution to | |
| the original problem $P_0$ with $z^{\it opt}=z^{\it best}$. STOP. | |
| 
 | |
| \subsection{The search tree} | |
| 
 | |
| On the branching step of the branch-and-cut algorithm the current | |
| subproblem is divided into two\footnote{In more general cases the | |
| current subproblem may be divided into more than two subproblems. | |
| However, currently such feature is not used in GLPK.} new subproblems, | |
| so the set of all subproblems can be represented in the form of a rooted | |
| tree, which is called the {\it search} or {\it branch-and-bound} tree. | |
| An example of the search tree is shown on Fig.~1. Each node of the | |
| search tree corresponds to a subproblem, so the terms `node' and | |
| `subproblem' may be used synonymously. | |
| 
 | |
| \begin{figure}[t] | |
| \noindent\hfil | |
| \xymatrix @R=20pt @C=10pt | |
| {&&&&&&*+<14pt>[o][F=]{A}\ar@{-}[dllll]\ar@{-}[dr]\ar@{-}[drrrr]&&&&\\ | |
| &&*+<14pt>[o][F=]{B}\ar@{-}[dl]\ar@{-}[dr]&&&&&*+<14pt>[o][F=]{C} | |
| \ar@{-}[dll]\ar@{-}[dr]\ar@{-}[drrr]&&&*+<14pt>[o][F-]{\times}\\ | |
| &*+<14pt>[o][F-]{\times}\ar@{-}[dl]\ar@{-}[d]\ar@{-}[dr]&& | |
| *+<14pt>[o][F-]{D}&&*+<14pt>[o][F=]{E}\ar@{-}[dl]\ar@{-}[dr]&&& | |
| *+<14pt>[o][F=]{F}\ar@{-}[dl]\ar@{-}[dr]&&*+<14pt>[o][F-]{G}\\ | |
| *+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times} | |
| &&*+<14pt>[][F-]{H}&&*+<14pt>[o][F-]{I}&*+<14pt>[o][F-]{\times}&& | |
| *+<14pt>[o][F-]{J}&\\} | |
| 
 | |
| \bigskip | |
| 
 | |
| \noindent\hspace{.8in} | |
| \xymatrix @R=11pt | |
| {*+<20pt>[][F-]{}&*\txt{\makebox[1in][l]{Current}}&& | |
| *+<20pt>[o][F-]{}&*\txt{\makebox[1in][l]{Active}}\\ | |
| *+<20pt>[o][F=]{}&*\txt{\makebox[1in][l]{Non-active}}&& | |
| *+<14pt>[o][F-]{\times}&*\txt{\makebox[1in][l]{Fathomed}}\\ | |
| } | |
| 
 | |
| \bigskip | |
| 
 | |
| \begin{center} | |
| Fig. 1. An example of the search tree. | |
| \end{center} | |
| \end{figure} | |
| 
 | |
| In GLPK each node may have one of the following four statuses: | |
| 
 | |
| \vspace*{-8pt} | |
| 
 | |
| \begin{itemize} | |
| \item {\it current node} is the active node currently being | |
| processed; | |
| 
 | |
| \item {\it active node} is a leaf node, which still has to be | |
| processed; | |
| 
 | |
| \item {\it non-active node} is a node, which has been processed, | |
| but not fathomed; | |
| 
 | |
| \item {\it fathomed node} is a node, which has been processed and | |
| fathomed. | |
| \end{itemize} | |
| 
 | |
| \vspace*{-8pt} | |
| 
 | |
| In the data structure representing the search tree GLPK keeps only | |
| current, active, and non-active nodes. Once a node has been fathomed, | |
| it is removed from the tree data structure. | |
| 
 | |
| Being created each node of the search tree is assigned a distinct | |
| positive integer called the {\it subproblem reference number}, which | |
| may be used by the application program to specify a particular node of | |
| the tree. The root node corresponding to the original problem to be | |
| solved is always assigned the reference number 1. | |
| 
 | |
| \subsection{Current subproblem} | |
| 
 | |
| The current subproblem is a MIP problem corresponding to the current | |
| node of the search tree. It is represented as the GLPK problem object | |
| (\verb|glp_prob|) that allows the application program using API | |
| routines to access its content in the standard way. If the MIP | |
| presolver is not used, it is the original problem object passed to the | |
| routine \verb|glp_intopt|; otherwise, it is an internal problem object | |
| built by the MIP presolver. | |
| 
 | |
| Note that the problem object is used by the MIP solver itself during | |
| the solution process for various purposes (to solve LP relaxations, to | |
| perfom branching, etc.), and even if the MIP presolver is not used, the | |
| current content of the problem object may differ from its original | |
| content. For example, it may have additional rows, bounds of some rows | |
| and columns may be changed, etc. In particular, LP segment of the | |
| problem object corresponds to LP relaxation of the current subproblem. | |
| However, on exit from the MIP solver the content of the problem object | |
| is restored to its original state. | |
| 
 | |
| To obtain information from the problem object the application program | |
| may use any API routines, which do not change the object. Using API | |
| routines, which change the problem object, is restricted to stipulated | |
| cases. | |
| 
 | |
| \subsection{The cut pool} | |
| 
 | |
| The {\it cut pool} is a set of cutting plane constraints maintained by | |
| the MIP solver. It is used by the GLPK cut generation routines and may | |
| be used by the application program in the same way, i.e. rather than | |
| to add cutting plane constraints directly to the problem object the | |
| application program may store them to the cut pool. In the latter case | |
| the solver looks through the cut pool, selects efficient constraints, | |
| and adds them to the problem object. | |
| 
 | |
| \subsection{Reasons for calling the callback routine} | |
| 
 | |
| The callback routine may be called by the MIP solver for the following | |
| reasons. | |
| 
 | |
| \para{Request for subproblem selection} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_ISELECT| | |
| if the current subproblem has been fathomed and therefore there is no | |
| current subproblem. | |
| 
 | |
| In response the callback routine may select some subproblem from the | |
| active list and pass its reference number to the solver using the | |
| routine \verb|glp_ios_select_node|, in which case the solver continues | |
| the search from the specified active subproblem. If no selection is | |
| made by the callback routine, the solver uses a backtracking technique | |
| specified by the control parameter \verb|bt_tech|. | |
| 
 | |
| To explore the active list (i.e. active nodes of the branch-and-bound | |
| tree) the callback routine may use the routines \verb|glp_ios_next_node| | |
| and \verb|glp_ios_prev_node|. | |
| 
 | |
| \para{Request for preprocessing} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_IPREPRO| | |
| if the current subproblem has just been selected from the active list | |
| and its LP relaxation is not solved yet. | |
| 
 | |
| In response the callback routine may perform some preprocessing of the | |
| current subproblem like tightening bounds of some variables or removing | |
| bounds of some redundant constraints. | |
| 
 | |
| \para{Request for row generation} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_IROWGEN| | |
| if LP relaxation of the current subproblem has just been solved to | |
| optimality and its objective value is better than the best known | |
| integer feasible solution. | |
| 
 | |
| In response the callback routine may add one or more ``lazy'' | |
| constraints (rows), which are violated by the current optimal solution | |
| of LP relaxation, using API routines \verb|glp_add_rows|, | |
| \verb|glp_set_row_name|, \verb|glp_set_row_bnds|, and | |
| \verb|glp_set_mat_row|, in which case the solver will perform | |
| re-optimization of LP relaxation. If there are no violated constraints, | |
| the callback routine should just return. | |
| 
 | |
| Note that components of optimal solution to LP relaxation can be | |
| obtained with API\linebreak routines \verb|glp_get_obj_val|, | |
| \verb|glp_get_row_prim|, \verb|glp_get_row_dual|, | |
| \verb|glp_get_col_prim|, and\linebreak \verb|glp_get_col_dual|. | |
| 
 | |
| \para{Request for heuristic solution} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_IHEUR| | |
| if LP relaxation of the current subproblem being solved to optimality | |
| is integer infeasible (i.e. values of some structural variables of | |
| integer kind are fractional), though its objective value is better than | |
| the best known integer feasible solution. | |
| 
 | |
| In response the callback routine may try applying a primal heuristic | |
| to find an integer feasible solution,\footnote{Integer feasible to the | |
| original MIP problem, not to the current subproblem.} which is better | |
| than the best known one. In case of success the callback routine may | |
| store such better solution in the problem object using the routine | |
| \verb|glp_ios_heur_sol|. | |
| 
 | |
| \para{Request for cut generation} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_ICUTGEN| | |
| if LP relaxation of the current subproblem being solved to optimality | |
| is integer infeasible (i.e. values of some structural variables of | |
| integer kind are fractional), though its objective value is better than | |
| the best known integer feasible solution. | |
| 
 | |
| In response the callback routine may reformulate the {\it current} | |
| subproblem (before it will be splitted up due to branching) by adding | |
| to the problem object one or more {\it cutting plane constraints}, | |
| which cut off the fractional optimal point from the MIP | |
| polytope.\footnote{Since these constraints are added to the current | |
| subproblem, they may be globally as well as locally valid.} | |
| 
 | |
| Adding cutting plane constraints may be performed in two ways. | |
| One way is the same as for the reason code \verb|GLP_IROWGEN| (see | |
| above), in which case the callback routine adds new rows corresponding | |
| to cutting plane constraints directly to the current subproblem. | |
| 
 | |
| The other way is to add cutting plane constraints to the | |
| {\it cut pool}, a set of cutting plane constraints maintained by the | |
| solver, rather than directly to the current subproblem. In this case | |
| after return from the callback routine the solver looks through the | |
| cut pool, selects efficient cutting plane constraints, adds them to the | |
| current subproblem, drops other constraints, and then performs | |
| re-optimization. | |
| 
 | |
| \para{Request for branching} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_IBRANCH| | |
| if LP relaxation of the current subproblem being solved to optimality | |
| is integer infeasible (i.e. values of some structural variables of | |
| integer kind are fractional), though its objective value is better than | |
| the best known integer feasible solution. | |
| 
 | |
| In response the callback routine may choose some variable suitable for | |
| branching (i.e. integer variable, whose value in optimal solution to | |
| LP relaxation of the current subproblem is fractional) and pass its | |
| ordinal number to the solver using the routine | |
| \verb|glp_ios_branch_upon|, in which case the solver splits the current | |
| subproblem in two new subproblems and continues the search. | |
| If no choice is made by the callback routine, the solver uses | |
| a branching technique specified by the control parameter \verb|br_tech|. | |
| 
 | |
| \para{Better integer solution found} | |
| 
 | |
| The callback routine is called with the reason code \verb|GLP_IBINGO| | |
| if LP relaxation of the current subproblem being solved to optimality | |
| is integer feasible (i.e. values of all structural variables of integer | |
| kind are integral within the working precision) and its objective value | |
| is better than the best known integer feasible solution. | |
| 
 | |
| Optimal solution components for LP relaxation can be obtained in the | |
| same way as for the reason code \verb|GLP_IROWGEN| (see above). | |
| 
 | |
| Components of the new MIP solution can be obtained with API routines | |
| \verb|glp_mip_obj_val|, \verb|glp_mip_row_val|, and | |
| \verb|glp_mip_col_val|. Note, however, that due to row/cut generation | |
| there may be additional rows in the problem object. | |
| 
 | |
| The difference between optimal solution to LP relaxation and | |
| corresponding MIP solution is that in the former case some structural | |
| variables of integer kind (namely, basic variables) may have values, | |
| which are close to nearest integers within the working precision, while | |
| in the latter case all such variables have exact integral values. | |
| 
 | |
| The reason \verb|GLP_IBINGO| is intended only for informational | |
| purposes, so the callback routine should not modify the problem object | |
| in this case. | |
| 
 | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
|  | |
| \newpage | |
| 
 | |
| \section{Basic routines} | |
| 
 | |
| \subsection{glp\_ios\_reason --- determine reason for calling the | |
| callback routine} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_reason(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_reason| returns a code, which indicates why | |
| the user-defined callback routine is being called: | |
| 
 | |
| \verb|GLP_ISELECT| --- request for subproblem selection; | |
| 
 | |
| \verb|GLP_IPREPRO| --- request for preprocessing; | |
| 
 | |
| \verb|GLP_IROWGEN| --- request for row generation; | |
| 
 | |
| \verb|GLP_IHEUR  | --- request for heuristic solution; | |
| 
 | |
| \verb|GLP_ICUTGEN| --- request for cut generation; | |
| 
 | |
| \verb|GLP_IBRANCH| --- request for branching; | |
| 
 | |
| \verb|GLP_IBINGO | --- better integer solution found. | |
| 
 | |
| \subsection{glp\_ios\_get\_prob --- access the problem object} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    glp_prob *glp_ios_get_prob(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_get_prob| can be called from the user-defined | |
| callback routine to access the problem object, which is used by the MIP | |
| solver. It is the original problem object passed to the routine | |
| \verb|glp_intopt| if the MIP presolver is not used; otherwise it is an | |
| internal problem object built by the presolver. | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_get_prob| returns a pointer to the problem | |
| object used by the MIP solver. | |
| 
 | |
| \para{Comments} | |
| 
 | |
| To obtain various information about the problem instance the callback | |
| routine can access the problem object (i.e. the object of type | |
| \verb|glp_prob|) using the routine \verb|glp_ios_get_prob|. It is the | |
| original problem object passed to the routine \verb|glp_intopt| if the | |
| MIP presolver is not used; otherwise it is an internal problem object | |
| built by the presolver. | |
| 
 | |
| \newpage | |
| 
 | |
| \subsection{glp\_ios\_row\_attr --- determine additional row | |
| attributes} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_row_attr| retrieves additional attributes of | |
| $i$-th row of the current subproblem and stores them in the structure | |
| \verb|glp_attr|, which the parameter \verb|attr| points to. | |
| 
 | |
| The structure \verb|glp_attr| has the following fields: | |
| 
 | |
| \medskip | |
| 
 | |
| {\tt int level} | |
| 
 | |
| Subproblem level at which the row was created. (If \verb|level| = 0, | |
| the row was added either to the original problem object passed to the | |
| routine \verb|glp_intopt| or to the root subproblem on generating | |
| ``lazy'' or/and cutting plane constraints.) | |
| 
 | |
| \medskip | |
| 
 | |
| {\tt int origin} | |
| 
 | |
| The row origin flag: | |
| 
 | |
| \verb|GLP_RF_REG | --- regular constraint; | |
| 
 | |
| \verb|GLP_RF_LAZY| --- ``lazy'' constraint; | |
| 
 | |
| \verb|GLP_RF_CUT | --- cutting plane constraint. | |
| 
 | |
| \medskip | |
| 
 | |
| {\tt int klass} | |
| 
 | |
| The row class descriptor, which is a number passed to the routine | |
| \verb|glp_ios_add_row| as its third parameter. If the row is a cutting | |
| plane constraint generated by the solver, its class may be the | |
| following: | |
| 
 | |
| \verb|GLP_RF_GMI | --- Gomory's mixed integer cut; | |
| 
 | |
| \verb|GLP_RF_MIR | --- mixed integer rounding cut; | |
| 
 | |
| \verb|GLP_RF_COV | --- mixed cover cut; | |
| 
 | |
| \verb|GLP_RF_CLQ | --- clique cut. | |
| 
 | |
| \subsection{glp\_ios\_mip\_gap --- compute relative MIP gap} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    double glp_ios_mip_gap(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_mip_gap| computes the relative MIP gap (also | |
| called {\it duality gap}) with the following formula: | |
| $${\tt gap} = \frac{|{\tt best\_mip} - {\tt best\_bnd}|} | |
| {|{\tt best\_mip}| + {\tt DBL\_EPSILON}}$$ | |
| where \verb|best_mip| is the best integer feasible solution found so | |
| far, \verb|best_bnd| is the best (global) bound. If no integer feasible | |
| solution has been found yet, \verb|gap| is set to \verb|DBL_MAX|. | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_mip_gap| returns the relative MIP gap. | |
| 
 | |
| \para{Comments} | |
| 
 | |
| The relative MIP gap is used to measure the quality of the best integer | |
| feasible solution found so far, because the optimal solution value | |
| $z^*$ for the original MIP problem always lies in the range | |
| $${\tt best\_bnd}\leq z^*\leq{\tt best\_mip}$$ | |
| in case of minimization, or in the range | |
| $${\tt best\_mip}\leq z^*\leq{\tt best\_bnd}$$ | |
| in case of maximization. | |
| 
 | |
| To express the relative MIP gap in percents the value returned by the | |
| routine \verb|glp_ios_mip_gap| should be multiplied by 100\%. | |
| 
 | |
| \subsection{glp\_ios\_node\_data --- access application-specific data} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void *glp_ios_node_data(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_node_data| allows the application accessing | |
| a memory block allocated for the subproblem (which may be active or | |
| inactive), whose reference number is $p$. | |
| 
 | |
| The size of the block is defined by the control parameter | |
| \verb|cb_size| passed to the routine \verb|glp_intopt|. The block is | |
| initialized by binary zeros on creating corresponding subproblem, and | |
| its contents is kept until the subproblem will be removed from the | |
| tree. | |
| 
 | |
| The application may use these memory blocks to store specific data for | |
| each subproblem. | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_node_data| returns a pointer to the memory | |
| block for the specified subproblem. Note that if \verb|cb_size| = 0, | |
| the routine returns a null pointer. | |
| 
 | |
| \subsection{glp\_ios\_select\_node --- select subproblem to continue | |
| the search} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_select_node(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_select_node| can be called from the | |
| user-defined callback routine in response to the reason | |
| \verb|GLP_ISELECT| to select an active subproblem, whose reference | |
| number\linebreak is $p$. The search will be continued from the | |
| subproblem selected. | |
| 
 | |
| \newpage | |
| 
 | |
| \subsection{glp\_ios\_heur\_sol --- provide solution found by | |
| heuristic} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_heur_sol(glp_tree *T, const double x[]); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_heur_sol| can be called from the user-defined | |
| callback routine in response to the reason \verb|GLP_IHEUR| to provide | |
| an integer feasible solution found by a primal heuristic. | |
| 
 | |
| Primal values of {\it all} variables (columns) found by the heuristic | |
| should be placed in locations $x[1]$, \dots, $x[n]$, where $n$ is the | |
| number of columns in the original problem object. Note that the routine | |
| \verb|glp_ios_heur_sol| does {\it not} check primal feasibility of the | |
| solution provided. | |
| 
 | |
| Using the solution passed in the array $x$ the routine computes value | |
| of the objective function. If the objective value is better than the | |
| best known integer feasible solution, the routine computes values of | |
| auxiliary variables (rows) and stores all solution components in the | |
| problem object. | |
| 
 | |
| \returns | |
| 
 | |
| If the provided solution is accepted, the routine | |
| \verb|glp_ios_heur_sol| returns zero. Otherwise, if the provided | |
| solution is rejected, the routine returns non-zero. | |
| 
 | |
| \vspace*{-5pt} | |
| 
 | |
| \subsection{glp\_ios\_can\_branch --- check if can branch upon | |
| specified variable} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_can_branch(glp_tree *T, int j); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| If $j$-th variable (column) can be used to branch upon, the routine | |
| returns non-zero, otherwise zero. | |
| 
 | |
| \vspace*{-5pt} | |
| 
 | |
| \subsection{glp\_ios\_branch\_upon --- choose variable to branch upon} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_branch_upon(glp_tree *T, int j, int sel); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_branch_upon| can be called from the | |
| user-defined callback routine in response to the reason | |
| \verb|GLP_IBRANCH| to choose a branching variable, whose ordinal number | |
| \linebreak is $j$. Should note that only variables, for which the | |
| routine \verb|glp_ios_can_branch| returns non-zero, can be used to | |
| branch upon. | |
| 
 | |
| The parameter \verb|sel| is a flag that indicates which branch | |
| (subproblem) should be selected next to continue the search: | |
| 
 | |
| \verb|GLP_DN_BRNCH| --- select down-branch; | |
| 
 | |
| \verb|GLP_UP_BRNCH| --- select up-branch; | |
| 
 | |
| \verb|GLP_NO_BRNCH| --- use general selection technique. | |
| 
 | |
| \para{Comments} | |
| 
 | |
| On branching the solver removes the current active subproblem from the | |
| active list and creates two new subproblems ({\it down-} and {\it | |
| up-branches}), which are added to the end of the active list. Note that | |
| the down-branch is created before the up-branch, so the last active | |
| subproblem will be the up-branch. | |
| 
 | |
| The down- and up-branches are identical to the current subproblem with | |
| exception that in the down-branch the upper bound of $x_j$, the variable | |
| chosen to branch upon, is replaced by $\lfloor x_j^*\rfloor$, while in | |
| the up-branch the lower bound of $x_j$ is replaced by | |
| $\lceil x_j^*\rceil$, where $x_j^*$ is the value of $x_j$ in optimal | |
| solution to LP relaxation of the current subproblem. For example, if | |
| $x_j^*=3.14$, the new upper bound of $x_j$ in the down-branch is | |
| $\lfloor 3.14\rfloor=3$, and the new lower bound in the up-branch is | |
| $\lceil 3.14\rceil=4$.) | |
| 
 | |
| Additionally the callback routine may select either down- or up-branch, | |
| from which the solver will continue the search. If none of the branches | |
| is selected, a general selection technique will be used. | |
| 
 | |
| \subsection{glp\_ios\_terminate --- terminate the solution process} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_terminate(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_terminate| sets a flag indicating that the | |
| MIP solver should prematurely terminate the search. | |
| 
 | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
|  | |
| \newpage | |
| 
 | |
| \section{The search tree exploring routines} | |
| 
 | |
| \subsection{glp\_ios\_tree\_size --- determine size of the search tree} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, int *t_cnt); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_tree_size| stores the following three counts | |
| which characterize the current size of the search tree: | |
| 
 | |
| \verb|a_cnt| is the current number of active nodes, i.e. the current | |
| size of the active list; | |
| 
 | |
| \verb|n_cnt| is the current number of all (active and inactive) nodes; | |
| 
 | |
| \verb|t_cnt| is the total number of nodes including those which have | |
| been already removed from the tree. This count is increased whenever | |
| a new node appears in the tree and never decreased. | |
| 
 | |
| If some of the parameters \verb|a_cnt|, \verb|n_cnt|, \verb|t_cnt| is | |
| a null pointer, the corresponding count is not stored. | |
| 
 | |
| \subsection{glp\_ios\_curr\_node --- determine current active | |
| subproblem} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_curr_node(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_curr_node| returns the reference number of | |
| the current active subproblem. However, if the current subproblem does | |
| not exist, the routine returns zero. | |
| 
 | |
| \subsection{glp\_ios\_next\_node --- determine next active subproblem} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_next_node(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| If the parameter $p$ is zero, the routine \verb|glp_ios_next_node| | |
| returns the reference number of the first active subproblem. However, | |
| if the tree is empty, zero is returned. | |
| 
 | |
| If the parameter $p$ is not zero, it must specify the reference number | |
| of some active subproblem, in which case the routine returns the | |
| reference number of the next active subproblem. However, if there is | |
| no next active subproblem in the list, zero is returned. | |
| 
 | |
| All subproblems in the active list are ordered chronologically, i.e. | |
| subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. | |
| 
 | |
| \newpage | |
| 
 | |
| \subsection{glp\_ios\_prev\_node --- determine previous active | |
| subproblem} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_prev_node(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| If the parameter $p$ is zero, the routine \verb|glp_ios_prev_node| | |
| returns the reference number of the last active subproblem. However, if | |
| the tree is empty, zero is returned. | |
| 
 | |
| If the parameter $p$ is not zero, it must specify the reference number | |
| of some active subproblem, in which case the routine returns the | |
| reference number of the previous active subproblem. However, if there | |
| is no previous active subproblem in the list, zero is returned. | |
| 
 | |
| All subproblems in the active list are ordered chronologically, i.e. | |
| subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. | |
| 
 | |
| \subsection{glp\_ios\_up\_node --- determine parent subproblem} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_up_node(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The parameter $p$ must specify the reference number of some (active or | |
| inactive) subproblem, in which case the routine \verb|iet_get_up_node| | |
| returns the reference number of its parent subproblem. However, if the | |
| specified subproblem is the root of the tree and, therefore, has | |
| no parent, the routine returns zero. | |
| 
 | |
| \subsection{glp\_ios\_node\_level --- determine subproblem level} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_node_level(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_node_level| returns the level of the | |
| subproblem, whose reference number is $p$, in the branch-and-bound | |
| tree. (The root subproblem has level 0, and the level of any other | |
| subproblem is the level of its parent plus one.) | |
| 
 | |
| \subsection{glp\_ios\_node\_bound --- determine subproblem local bound} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    double glp_ios_node_bound(glp_tree *T, int p); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_node_bound| returns the local bound for | |
| (active or inactive) subproblem, whose reference number is $p$. | |
| 
 | |
| \para{Comments} | |
| 
 | |
| The local bound for subproblem $p$ is an lower (minimization) or upper | |
| (maximization) bound for integer optimal solution to {\it this} | |
| subproblem (not to the original problem). This bound is local in the | |
| sense that only subproblems in the subtree rooted at node $p$ cannot | |
| have better integer feasible solutions. | |
| 
 | |
| On creating a subproblem (due to the branching step) its local bound is | |
| inherited from its parent and then may get only stronger (never weaker). | |
| For the root subproblem its local bound is initially set to | |
| \verb|-DBL_MAX| (minimization) or \verb|+DBL_MAX| (maximization) and | |
| then improved as the root LP relaxation has been solved. | |
| 
 | |
| Note that the local bound is not necessarily the optimal objective | |
| value to corresponding LP relaxation. | |
| 
 | |
| \subsection{glp\_ios\_best\_node --- find active subproblem with best | |
| local bound} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_best_node(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_best_node| returns the reference number of | |
| the active subproblem, whose local bound is best (i.e. smallest in case | |
| of minimization or largest in case of maximization). However, if the | |
| tree is empty, the routine returns zero. | |
| 
 | |
| \para{Comments} | |
| 
 | |
| The best local bound is an lower (minimization) or upper (maximization) | |
| bound for integer optimal solution to the original MIP problem. | |
| 
 | |
| %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
|  | |
| \newpage | |
| 
 | |
| \section{The cut pool routines} | |
| 
 | |
| \subsection{glp\_ios\_pool\_size --- determine current size of the cut | |
| pool} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_pool_size(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_pool_size| returns the current size of the | |
| cut pool, that is, the number of cutting plane constraints currently | |
| added to it. | |
| 
 | |
| \subsection{glp\_ios\_add\_row --- add constraint to the cut pool} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    int glp_ios_add_row(glp_tree *T, const char *name, int klass, int flags, | |
|        int len, const int ind[], const double val[], int type, double rhs); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_add_row| adds specified row (cutting plane | |
| constraint) to the cut pool. | |
| 
 | |
| The cutting plane constraint should have the following format: | |
| $$\sum_{j\in J}a_jx_j\left\{\begin{array}{@{}c@{}}\geq\\\leq\\ | |
| \end{array}\right\}b,$$ | |
| where $J$ is a set of indices (ordinal numbers) of structural | |
| variables, $a_j$ are constraint coefficients, $x_j$ are structural | |
| variables, $b$ is the right-hand side. | |
| 
 | |
| The parameter \verb|name| specifies a symbolic name assigned to the | |
| constraint (1 up to 255 characters). If it is \verb|NULL| or an empty | |
| string, no name is assigned. | |
| 
 | |
| The parameter \verb|klass| specifies the constraint class, which must | |
| be either zero or a number in the range from 101 to 200. | |
| The application may use this attribute to distinguish between cutting | |
| plane constraints of different classes.\footnote{Constraint classes | |
| numbered from 1 to 100 are reserved for GLPK cutting plane generators.} | |
| 
 | |
| The parameter \verb|flags| currently is not used and must be zero. | |
| 
 | |
| Ordinal numbers of structural variables (i.e. column indices) $j\in J$ | |
| and numerical values of corresponding constraint coefficients $a_j$ | |
| should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and | |
| \verb|val[1]|, \dots, \verb|val[len]|, respectively, where | |
| ${\tt len}=|J|$ is the number of constraint coefficients, | |
| $0\leq{\tt len}\leq n$, and $n$ is the number of columns in the problem | |
| object. Coefficients with identical column indices are not allowed. | |
| Zero coefficients are allowed, however, they are ignored. | |
| 
 | |
| The parameter \verb|type| specifies the constraint type as follows: | |
| 
 | |
| \verb|GLP_LO| means inequality constraint $\Sigma a_jx_j\geq b$; | |
| 
 | |
| \verb|GLP_UP| means inequality constraint $\Sigma a_jx_j\leq b$; | |
| 
 | |
| The parameter \verb|rhs| specifies the right-hand side $b$. | |
| 
 | |
| All cutting plane constraints in the cut pool are identified by their | |
| ordinal numbers 1, 2, \dots, $size$, where $size$ is the current size | |
| of the cut pool. New constraints are always added to the end of the cut | |
| pool, thus, ordinal numbers of previously added constraints are not | |
| changed. | |
| 
 | |
| \returns | |
| 
 | |
| The routine \verb|glp_ios_add_row| returns the ordinal number of the | |
| cutting plane constraint added, which is the new size of the cut pool. | |
| 
 | |
| \para{Example} | |
| 
 | |
| \begin{verbatim} | |
| /* generate triangle cutting plane: | |
|    x[i] + x[j] + x[k] <= 1 */ | |
| . . . | |
| /* add the constraint to the cut pool */ | |
| ind[1] = i, val[1] = 1.0; | |
| ind[2] = j, val[2] = 1.0; | |
| ind[3] = k, val[3] = 1.0; | |
| glp_ios_add_row(tree, NULL, TRIANGLE_CUT, 0, 3, ind, val, GLP_UP, 1.0); | |
| \end{verbatim} | |
| 
 | |
| \para{Comments} | |
| 
 | |
| Cutting plane constraints added to the cut pool are intended to be then | |
| added only to the {\it current} subproblem, so these constraints can be | |
| globally as well as locally valid. However, adding a constraint to the | |
| cut pool does not mean that it will be added to the current | |
| subproblem---it depends on the solver's decision: if the constraint | |
| seems to be efficient, it is moved from the pool to the current | |
| subproblem, otherwise it is simply dropped.\footnote{Globally valid | |
| constraints could be saved and then re-used for other subproblems, but | |
| currently such feature is not implemented.} | |
| 
 | |
| Normally, every time the callback routine is called for cut generation, | |
| the cut pool is empty. On the other hand, the solver itself can | |
| generate cutting plane constraints (like Gomory's or mixed integer | |
| rounding cuts), in which case the cut pool may be non-empty. | |
| 
 | |
| \subsection{glp\_ios\_del\_row --- remove constraint from the cut pool} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_del_row(glp_tree *T, int i); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_del_row| deletes $i$-th row (cutting plane | |
| constraint) from the cut pool, where $1\leq i\leq size$ is the ordinal | |
| number of the constraint in the pool, $size$ is the current size of the | |
| cut pool. | |
| 
 | |
| Note that deleting a constraint from the cut pool leads to changing | |
| ordinal numbers of other constraints remaining in the pool. New ordinal | |
| numbers of the remaining constraints are assigned under assumption that | |
| the original order of constraints is not changed. Let, for example, | |
| there be four constraints $a$, $b$, $c$ and $d$ in the cut pool, which | |
| have ordinal numbers 1, 2, 3 and 4, respectively, and let constraint | |
| $b$ have been deleted. Then after deletion the remaining constraint $a$, | |
| $c$ and $d$ are assigned new ordinal numbers 1, 2 and 3, respectively. | |
| 
 | |
| To find the constraint to be deleted the routine \verb|glp_ios_del_row| | |
| uses ``smart'' linear search, so it is recommended to remove | |
| constraints in a natural or reverse order and avoid removing them in | |
| a random order. | |
| 
 | |
| \para{Example} | |
| 
 | |
| \begin{verbatim} | |
| /* keep first 10 constraints in the cut pool and remove other | |
|    constraints */ | |
| while (glp_ios_pool_size(tree) > 10) | |
|    glp_ios_del_row(tree, glp_ios_pool_size(tree)); | |
| \end{verbatim} | |
| 
 | |
| \subsection{glp\_ios\_clear\_pool --- remove all constraints from the | |
| cut pool} | |
| 
 | |
| \synopsis | |
| 
 | |
| \begin{verbatim} | |
|    void glp_ios_clear_pool(glp_tree *T); | |
| \end{verbatim} | |
| 
 | |
| \description | |
| 
 | |
| The routine \verb|glp_ios_clear_pool| makes the cut pool empty deleting | |
| all existing rows (cutting plane constraints) from it. | |
| 
 | |
| %* eof *%
 |