You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- added status enums
- added support for string attribute/controls ids
- kept int attribute/controls id for internal use
- fixed broken defaults in binded arguments
- added missing _add_linear_constraint overloads
- added missing get_value overloads
- added missing pprint overloads
- added missing set_objective overloads
- fixed a whole lot of defect during initial testing
- implemented xpress.py model
- added a simple partial implementation of the tsp example
- callback system
- license error message
- default message cb
- OUTPUTLOG 1 by default
- CB from main thread to avoid issues with Python GIL
- Made XpressModel CALLBACK mode more explicit and checked
- cb_get_* queries
- Lazy and usercut mapped to XPRSaddcuts
- Auto submit solution after CB end
- xpress.Model wrap of RawModel in python CB
- XpressModel move ctor to enable wrapping-unwrapping
- Removed deprecated attribute
- Flatten out XpressModel fields
- Fixed repeated set_callback calls
- Removed mutex (not used)
- Original XpressModel used also in cbs
- Added forgotte cb bindings
- Complete tsp_xpress.py callback test
- xpress_model.hpp comments
- Cleaned up xpress_model*.cpp
- NLP objective + SOC + Exp Cones
- Postsolve and minor fixing
- Version check
- Ptr ownership bugfix + stream flushing
Copy file name to clipboardExpand all lines: docs/source/callback.md
+36-9Lines changed: 36 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,26 +6,28 @@ The behavior of callback function highly depends on the optimizer and the specif
6
6
7
7
In most optimization problems, we build the model, set the parameters, and then call the optimizer to solve the problem. However, in some cases, we may want to monitor the optimization process and intervene in the optimization process. For example, we may want to stop the optimization process when a certain condition is met, or we may want to record the intermediate results of the optimization process. In these cases, we can use the callback function. The callback function is a user-defined function that is called by the optimizer at specific points during the optimization process. Callback is especially useful for mixed-integer programming problems, where we can control the branch and bound process in callback functions.
8
8
9
-
Callback is not supported for all optimizers. Currently, we only support callback for Gurobiand COPT optimizer. Because callback is tightly coupled with the optimizer, we choose not to implement a strictly unified API for callback. Instead, we try to unify the common parts of the callback API of Gurobi and COPT and aims to provide all callback features included in vendored Python bindings of Gurobi and COPT.
9
+
Callback is not supported for all optimizers. Currently, we only support callback for Gurobi, COPT, and Xpress optimizer. Because callback is tightly coupled with the optimizer, we choose not to implement a strictly unified API for callback. Instead, we try to unify the common parts of the callback API and aim to provide all callback features included in the vendored Python bindings.
10
10
11
11
In PyOptInterface, the callback function is simply a Python function that takes two arguments:
12
12
-`model`: The instance of the [optimization model](model.md)
13
-
-`where`: The flag indicates the stage of optimization process when our callback function is invoked. For Gurobi, the value of `where` is [CallbackCodes](https://www.gurobi.com/documentation/current/refman/cb_codes.html#sec:CallbackCodes). For COPT, the value of `where` is called as [callback contexts](https://guide.coap.online/copt/en-doc/callback.html) such as `COPT.CBCONTEXT_MIPNODE` and `COPT.CBCONTEXT_MIPRELAX`.
13
+
-`where`: The flag indicates the stage of optimization process when our callback function is invoked. For Gurobi, the value of `where` is [CallbackCodes](https://www.gurobi.com/documentation/current/refman/cb_codes.html#sec:CallbackCodes). For COPT, the value of `where` is called as [callback contexts](https://guide.coap.online/copt/en-doc/callback.html) such as `COPT.CBCONTEXT_MIPNODE` and `COPT.CBCONTEXT_MIPRELAX`. For Xpress, the `where` value corresponds to specific callback points such as `XPRS.CB_CONTEXT.PREINTSOL` or `XPRS.CB_CONTEXT.OPTNODE`. A description of supported Xpress callbacks can be found [here](https://www.fico.com/fico-xpress-optimization/docs/latest/solver/optimizer/HTML/chapter5.html?scroll=section5002).
14
14
15
15
In the function body of the callback function, we can do the following four kinds of things:
16
-
- Query the current information of the optimization process. For scalar information, we can use `model.cb_get_info` function to get the information, and its argument is the value of [`what`](https://www.gurobi.com/documentation/current/refman/cb_codes.html) in Gurobi and the value of [callback information](https://guide.coap.online/copt/en-doc/information.html#chapinfo-cbc) in COPT. For array information such as the MIP solution or relaxation, PyOptInterface provides special functions such as `model.cb_get_solution` and `model.cb_get_relaxation`.
16
+
- Query the current information of the optimization process. For scalar information, we can use `model.cb_get_info` function to get the information, and its argument is the value of [`what`](https://www.gurobi.com/documentation/current/refman/cb_codes.html) in Gurobi and the value of [callback information](https://guide.coap.online/copt/en-doc/information.html#chapinfo-cbc) in COPT. For Xpress, use regular attribute access methods such as `model.get_raw_attribute`. For array information such as the MIP solution or relaxation, PyOptInterface provides special functions such as `model.cb_get_solution` and `model.cb_get_relaxation`.
17
17
- Add lazy constraint: Use `model.cb_add_lazy_constraint` just like `model.add_linear_constraint` except for the `name` argument.
18
18
- Add user cut: Use `model.cb_add_user_cut` just like `model.add_linear_constraint` except for the `name` argument.
19
-
- Set a heuristic solution: Use `model.set_solution` to set individual values of variables and use `model.cb_submit_solution` to submit the solution to the optimizer immediately (`model.cb_submit_solution` will be called automatically in the end of callback if `model.set_solution` is called).
19
+
- Set a heuristic solution: Use `model.cb_set_solution` to set individual values of variables and use `model.cb_submit_solution` to submit the solution to the optimizer immediately (`model.cb_submit_solution` will be called automatically in the end of callback if `model.cb_set_solution` is called).
20
20
- Terminate the optimizer: Use `model.cb_exit`.
21
21
22
22
Here is an example of a callback function that stops the optimization process when the objective value reaches a certain threshold:
23
23
24
24
```python
25
25
import pyoptinterface as poi
26
-
from pyoptinterface import gurobi, copt
26
+
from pyoptinterface import gurobi, copt, xpress
27
+
27
28
GRB= gurobi.GRB
28
29
COPT= copt.COPT
30
+
XPRS= xpress.XPRS
29
31
30
32
defcb_gurobi(model, where):
31
33
if where ==GRB.Callback.MIPSOL:
@@ -38,9 +40,15 @@ def cb_copt(model, where):
38
40
obj = model.cb_get_info("MipCandObj")
39
41
if obj <10:
40
42
model.cb_exit()
43
+
44
+
defcb_xpress(model, where):
45
+
if where ==XPRS.CB_CONTEXT.PREINTSOL:
46
+
obj = model.get_raw_attribute("LPOBJVAL")
47
+
if obj <10:
48
+
model.cb_exit()
41
49
```
42
50
43
-
To use the callback function, we need to call `model.set_callback(cb)` to pass the callback function to the optimizer. For COPT, `model.set_callback` needs an additional argument `where` to specify the context where the callback function is invoked. For Gurobi, the `where` argument is not needed.
51
+
To use the callback function, we need to call `model.set_callback(cb)` to pass the callback function to the optimizer. For COPT and Xpress, `model.set_callback` needs an additional argument `where` to specify the context where the callback function is invoked. For Gurobi, the `where` argument is not needed.
For a detailed example to use callbacks in PyOptInterface, we provide a [concrete callback example](https://github.com/metab0t/PyOptInterface/blob/master/tests/tsp_cb.py) to solve the Traveling Salesman Problem (TSP) with callbacks in PyOptInterface, gurobipyand coptpy. The example is adapted from the official Gurobi example [tsp.py](https://www.gurobi.com/documentation/current/examples/tsp_py.html).
119
+
For a detailed example to use callbacks in PyOptInterface, we provide a [concrete callback example](https://github.com/metab0t/PyOptInterface/blob/master/tests/tsp_cb.py) to solve the Traveling Salesman Problem (TSP) with callbacks in PyOptInterface, gurobipy, coptpy, and Xpress Python. The example is adapted from the official Gurobi example [tsp.py](https://www.gurobi.com/documentation/current/examples/tsp_py.html).
Copy file name to clipboardExpand all lines: docs/source/constraint.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -197,7 +197,9 @@ $$
197
197
variables=(t,s,r) \in \mathbb{R}^{3} : t \ge -r \exp(\frac{s}{r} - 1), r \le 0
198
198
$$
199
199
200
-
Currently, only COPT(after 7.1.4), Mosek support exponential cone constraint. It can be added to the model using the `add_exp_cone_constraint` method of the `Model` class.
200
+
Currently, only COPT(after 7.1.4), Mosek support exponential cone constraint natively.
201
+
Xpress supports exponential cones by mapping them into generic NLP formulas at the API level.
202
+
It can be added to the model using the `add_exp_cone_constraint` method of the `Model` class.
Copy file name to clipboardExpand all lines: docs/source/infeasibility.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,7 +11,7 @@ The optimization model is not ways feasible, and the optimizer may tell us some
11
11
- Find the IIS (Irreducible Infeasible Set) to identify the minimal set of constraints that cause the infeasibility.
12
12
- Relax the constraints and solve a weaker problem to find out which constraints are violated and how much.
13
13
14
-
PyOptInterface currently supports the first method to find the IIS (only with Gurobi and COPT). The following code snippet shows how to find the IIS of an infeasible model:
14
+
PyOptInterface currently supports the first method to find the IIS (only with Gurobi, Xpress, and COPT). The following code snippet shows how to find the IIS of an infeasible model:
0 commit comments