.. _using-custom-solvers: Using Custom Solvers ==================== GraphCalc can use many MILP solvers via `PuLP `_. This page shows **all the ways** you can pick or configure a solver when calling GraphCalc functions (e.g., :func:`graphcalc.invariants.classics.maximum_independent_set`). .. contents:: :local: :depth: 2 Overview -------- - If you **do nothing**, GraphCalc will auto-detect a solver in this order: 1. ``HiGHS`` (Python API) if the package ``highspy`` is installed. 2. A command-line solver found on ``PATH`` (in order): ``highs`` → ``cbc`` → ``glpsol``. - You can **override** the choice: - per-call via the ``solver=...`` argument (several forms supported), - or globally via environment variables (``GRAPHCALC_SOLVER``, ``GRAPHCALC_SOLVER_PATH``). - Extra arguments for solver configuration can be passed through ``solver_options={...}`` (when applicable; see below). Accepted Forms for ``solver=...`` --------------------------------- You can pass any of the following to the ``solver=`` parameter. **1) ``None`` (default / auto-detect)** .. code-block:: python S = gc.maximum_independent_set(G) # auto-detect **2) String name** (friendly names or PuLP registry names) .. code-block:: python S = gc.maximum_independent_set(G, solver="cbc") # doctest: +SKIP S = gc.maximum_independent_set(G, solver="highs") # doctest: +SKIP S = gc.maximum_independent_set(G, solver="glpk") # doctest: +SKIP # also works with official PuLP names, e.g. "GUROBI_CMD" (if available) **3) Dict: ``{"name": , "options": {...}}``** (forwarded to ``pulp.getSolver``) .. code-block:: python S = gc.maximum_independent_set( G, solver={"name": "GUROBI_CMD", "options": {"timeLimit": 10}}, # doctest: +SKIP ) **4) Class** (a PuLP solver class; GraphCalc instantiates it for you) .. code-block:: python from pulp import PULP_CBC_CMD S = gc.maximum_independent_set(G, solver=PULP_CBC_CMD) # doctest: +SKIP **5) Instance** (an already-constructed PuLP solver) .. code-block:: python from pulp import PULP_CBC_CMD S = gc.maximum_independent_set(G, solver=PULP_CBC_CMD(msg=True)) # doctest: +SKIP **6) Callable** (returning a PuLP solver instance) .. code-block:: python from pulp import PULP_CBC_CMD S = gc.maximum_independent_set(G, solver=lambda: PULP_CBC_CMD(msg=False, threads=2)) # doctest: +SKIP Passing ``solver_options`` -------------------------- When you pass a **string** or a **class**, you can also provide ``solver_options={...}``. These are forwarded to the underlying solver constructor (e.g., ``pulp.getSolver("cbc", **opts)`` or ``PULP_CBC_CMD(**opts)``). .. code-block:: python # String + solver_options S = gc.maximum_independent_set( G, solver="cbc", solver_options={"msg": False, "timeLimit": 5, "threads": 2}, # doctest: +SKIP ) # Class + solver_options from pulp import HiGHS_CMD S = gc.maximum_independent_set( G, solver=HiGHS_CMD, solver_options={"msg": True, "timeLimit": 10}, # doctest: +SKIP ) **Notes** - If you pass an **instance** or a **callable**, ``solver_options`` is **ignored** (because your instance already encodes its settings). - The exact option names vary by solver. Common, widely-supported keys include: - ``msg`` (bool): turn solver logging on/off. - ``timeLimit`` (seconds): wall-clock limit. - ``threads`` (int): limit solver threads. - Gap keys (CBC often uses ``fracGap`` or ``gapRel``; check PuLP docs). - If an option isn’t recognized by the selected solver, PuLP may ignore it silently. Environment Variables (Global Overrides) ---------------------------------------- You can choose a solver globally, without changing code: .. code-block:: bash # one of: highs | cbc | glpk | auto export GRAPHCALC_SOLVER=cbc # optional: force an exact executable path for CMD-style solvers export GRAPHCALC_SOLVER_PATH=/usr/bin/cbc On Windows PowerShell: .. code-block:: powershell $env:GRAPHCALC_SOLVER = "cbc" $env:GRAPHCALC_SOLVER_PATH = "C:\Program Files\cbc\bin\cbc.exe" See What GraphCalc Will Use --------------------------- Use the built-in doctor to print the detection decision: .. code-block:: python from graphcalc.solvers import doctor print(doctor()) Example: .. code-block:: text GraphCalc Solver Doctor ----------------------- Preferred (env) : GRAPHCALC_SOLVER=(none) Forced path : GRAPHCALC_SOLVER_PATH=(none) Selected : PULP_CBC_CMD [cbc] Path trial(s) : - highs : (not found) - cbc : /usr/bin/cbc - glpsol: (not found) Practical Examples ------------------ **Disable logs and cap runtime** .. code-block:: python S = gc.maximum_clique( G, solver="cbc", solver_options={"msg": False, "timeLimit": 10}, # doctest: +SKIP ) **Ask HiGHS (Python API) first, otherwise HiGHS_CMD if installed** .. code-block:: python # If you installed `highspy` (pip), `solver="highs"` will prefer the python API. # Without highspy but with the `highs` executable on PATH, it uses HiGHS_CMD. S = gc.independence_number(G, solver="highs") # doctest: +SKIP **Callable to centralize tuning** .. code-block:: python def tuned_cbc(): from pulp import PULP_CBC_CMD return PULP_CBC_CMD(msg=False, threads=2, timeLimit=5) chi = gc.chromatic_number(G, solver=tuned_cbc) # doctest: +SKIP Troubleshooting --------------- **“The solver highs does not exist in PuLP.”** - You passed a string that PuLP doesn’t recognize in your version, or you used the wrong case. Try ``"highs"`` or the registered name ``"HiGHS"`` (via PuLP). Alternatively, import the class: ``from pulp import HiGHS_CMD``. **“PuLP: cannot execute highs.”** - You selected ``HiGHS_CMD`` but the ``highs`` executable is not on ``PATH``. Install it (see :doc:`installation`) or use the Python package ``highspy`` and set ``GRAPHCALC_SOLVER=highs``. As a quick fix, force CBC: ``GRAPHCALC_SOLVER=cbc``. **Windows PATH quirks** - Prefer ``pip install highspy`` (HiGHS Python API), or ``conda install -c conda-forge coincbc`` for CBC. **Silencing solver output** - Pass ``verbose=False`` (default) to GraphCalc functions, or set ``msg=False`` via ``solver_options`` (when using string/class forms). **CI stability** - On Ubuntu 22.04 GitHub runners, install ``coinor-cbc`` and set ``GRAPHCALC_SOLVER=cbc``. Or install ``highspy`` and set ``GRAPHCALC_SOLVER=highs``. See :doc:`installation` for ready-to-use YAML. See Also -------- - :doc:`installation` — how to install solvers on your platform. - PuLP solver docs for detailed option names/behavior.