Skip to content

Conversation

@XPRSc4v4
Copy link

@XPRSc4v4 XPRSc4v4 commented Dec 4, 2025

Hi!

This PR adds support for the FICO Xpress Optimizer to PyOptInterface. The implementation follows the established patterns from the Gurobi and COPT backends, adapting Xpress-specific features to fit the PyOptInterface design.

Supported Features

  • Linear and mixed-integer linear programming (LP/MILP)
  • Quadratic objectives and constraints (QP/QCP/MIQP/MIQCP)
  • Second-order cone constraints (mapped to quadratic constraints, auto-detected by Xpress)
  • Exponential cone constraints (mapped to nonlinear formulas)
  • Nonlinear programming via formula-based modeling (NLP)
  • Special Ordered Sets (SOS1/SOS2)
  • Optimization callbacks with the APIs currently supported by the other solvers

Implementation Notes

Xpress-Specific Adaptations:

  1. Global Environment Management: Xpress requires global initialization/cleanup via XPRSinit/XPRSfree. This is handled through a reference-counted XpressEnv class to ensure proper lifecycle management across multiple model instances.

  2. Quadratic Term Scaling: Xpress uses different conventions for quadratic terms:

    • Objectives: 0.5 * x'Qx (diagonal coefficients need 2x scaling)
    • Constraints: x'Qx (off-diagonal coefficients need 0.5x scaling)

    The implementation handles this transparently in set_objective and add_quadratic_constraint.

  3. Callback Threading: Xpress callbacks receive thread-local problem clones. The implementation uses a swap mechanism to ensure the user interacts with the correct problem instance, with proper GIL management. Callbacks are serialized via XPRS_MUTEXCALLBACKS=1 to avoid race conditions. Note: this implementation does not support Python's new free-threading feature (PEP 703). If you plan to add free-threading support to PyOptInterface, we can adapt the Xpress backend to enable parallel callbacks, which Xpress supports natively.

  4. Callback Interface: PyOptInterface's single callback with context enumeration is mapped to Xpress's native multi-callback interface internally, maintaining consistency with other backends. Xpress provides additional callback contexts and APIs that allow customization of other optimization aspects (e.g., branching rules). Let me know if you're interested in extending PyOptInterface to support these advanced features.

  5. Parameter Access: The implementation preserves Xpress naming conventions: "controls" for read/write optimizer parameters, "attributes" for read-only model and optimization status information.

Testing

All existing PyOptInterface tests pass with the Xpress backend. Additionally, a TSP callback example demonstrates the integration of optimization callbacks with lazy constraint generation.

Documentation

User documentation has been added in docs/source/xpress.md, covering installation, basic usage, and Xpress-specific considerations.

Please let me know if any design choices need adjustment to better align with PyOptInterface conventions, or if you have questions about the implementation. Happy to discuss further details or make modifications as needed.

Thanks for the great library!

Best,
Francesco

XPRSc4v4 and others added 2 commits December 4, 2025 15:16
- 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
@metab0t
Copy link
Owner

metab0t commented Dec 4, 2025

Thanks for your hard work on this heroic PR!

I will look into your PR next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants