Introduction
Callback functions are a useful tool for adapting the Xpress Optimizer to the solution of various classes of problems, in particular Mixed Integer Programming (MIP) problems, with linear or nonlinear constraints. Their main purpose is to provide the user with a point of entry into the branch-and-bound, which is the workhorse algorithm for MIPs.
Using callback functions is simple: the user first defines a function (say myfunction) that is to be run every time the branch-and-bound reaches a well-specified point; second, the user calls a function (such as addcbpreintsol) with myfunction as its argument. Finally, the user runs the solve command that launches the branch-and-bound, the simplex solver, or the barrier solver; it is while these are run that myfunction is called.
A callback function, hence, is passed once as an argument and used possibly many times. It is called while a solver is running, and it is passed the following:
- a problem object, of the same class as an object declared with p = xpress.problem();
- a data object.
The data object is user-defined and is given to the problem when adding the callback function. It can be used to store information that the user can read and/or modify within the callback. For instance, the following code shows how to add a callback function, preintsolcb, that is called every time a new integer solution is found.
import xpress as xp class foo: "Simple class" bar = 0 def __init__(self): self.bar = 1 def update(self): self.bar += 1 def preintsolcb(prob, data, isheuristic, cutoff): """ Callback to be used when an integer solution is found. The "data" parameter is of class foo """ p = xp.problem() p.read('myprob.lp') # reads in a problem, let's say a MIP baz = foo() p.addcbpreintsol(preintsolcb, baz, 3) p.solve()
While the function argument is necessary for all addcb* functions, the data object can be specified as None. In that case, the callback will be run with None as its data argument. The call also specifies a priority with which the callback should be called: the larger the (positive) priority, the more urgently it is called.
Any call to an addcb* function, as the names imply, only adds a function to a list of callback functions for that specific point of the BB algorithm. For instance, two calls to addcbpreintsol with two functions preint1 and preint2, respectively with priority 3 and 5, puts the two functions in a list. The two functions will be called (preint2 first) whenever the BB algorithm finds an integer solution.
In order to remove a callback function that was added with addcb*, a corresponding removecb* function is provided, for instance removecbpreintsol. This function takes two arguments, i.e., the callback function and the data object, and deletes all elements of the list of callbacks that were added with the corresponding addcb function that match the function and the data.
The None keyword acts as a wildcard that matches any function/data object: if removecb* is called with None as the function, then all callbacks matching the data will be deleted. If the data is also None, all callback functions of that type are deleted; this can be obtained by passing no argument to removecb*.
The arguments and return value of the callback functions reflect those in the C API, and this holds for parameter names as well. As for the other API functions of the Python interface, there are a few exceptions:
- If a function in the C API requires a parameter n to indicate the size of an array argument to follow, n is not required in the corresponding Python function;
- If a function in the C API uses passing by reference as a means to allow for modifying a value and returning it as an output, the Python counterpart will have this as the return value of the function. Where multiple output values are comprised in the list of parameters, the return value is a tuple composed of the returned values. Elements of this tuple can be None if no change was made to that output value.
Most callback functions refer to a problem, therefore the addcb* method is called from a problem object. The only exception is the function xpress.addcbmsghandler(), which is called on the Xpress module itself and allows for providing a function that is called every time any output is produced within the Optimizer.
We refer to the Reference chapter of this manual for all information regarding callback functions and how to add/remove them from a problem.
© 2001-2019 Fair Isaac Corporation. All rights reserved. This documentation is the property of Fair Isaac Corporation (“FICO”). Receipt or possession of this documentation does not convey rights to disclose, reproduce, make derivative works, use, or allow others to use it except solely for internal evaluation purposes to determine whether to purchase a license to the software described in this documentation, or as otherwise set forth in a written software license agreement between you and FICO (or a FICO affiliate). Use of this documentation and the software described in it must conform strictly to the foregoing permitted uses, and no other use is permitted.