Skip to content

Commit

Permalink
fix docs?
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 committed Dec 19, 2024
1 parent c1bf430 commit 1b8e8da
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 20 deletions.
15 changes: 10 additions & 5 deletions src/ilpy/_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from .solver_backends import Preference

if TYPE_CHECKING:
from collections.abc import Iterable, Mapping, Sequence
from collections.abc import Iterable, Sequence

from .event_data import EventData

ConstraintTuple = tuple[list[float], Relation | str, float]
SenseType = Sense | Literal["minimize", "maximize"]
Expand All @@ -24,7 +26,7 @@ def solve(
variable_type: VariableTypeType = VariableType.Continuous,
verbose: bool = False,
preference: PreferenceType = Preference.Any,
on_event: Callable[[Mapping], None] | None = None,
on_event: Callable[[EventData], None] | None = None,
) -> Solution:
"""Solve an objective subject to constraints.
Expand Down Expand Up @@ -58,7 +60,7 @@ def solve(
preference : Preference | Literal["any", "cplex", "gurobi", "scip"]
Backend preference, either an `ilpy.Preference` or a string in
{"any", "cplex", "gurobi", "scip"}. By default, `Preference.Any`.
on_event : Callable[[Mapping], None], optional
on_event : Callable[[EventData], None], optional
A callback function that is called when an event occurs, by default None. The
callback function should accept a dict which will contain statics about the
solving or presolving process. You can import `ilpy.EventData` from ilpy and use
Expand All @@ -76,13 +78,16 @@ def solve(
def callback(data: EventData) -> None:
# backend and event_type are guaranteed to be present
# they will narrow down the available keys
if data["backend"] == "gurobi" and data["event_type"] == "MIP":
print(data["gap"])
ilpy.solve(..., on_event=callback)
Returns
-------
Solution
The solution to the problem.
"""
if isinstance(sense, str):
sense = Sense[sense.title()]
Expand Down
7 changes: 3 additions & 4 deletions src/ilpy/_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
from .solver_backends import Preference, SolverBackend, create_solver_backend

if TYPE_CHECKING:
from collections.abc import Iterator, Mapping, Sequence
from collections.abc import Iterator, Sequence

import numpy as np

from ._components import Constraint, Constraints, Objective
from ._constants import SolverStatus, VariableType
from .event_data import EventData


@dataclass
Expand Down Expand Up @@ -82,9 +83,7 @@ def set_num_threads(self, num_threads: int) -> None:
def set_verbose(self, verbose: bool) -> None:
self._backend.set_verbose(verbose)

def set_event_callback(
self, callback: Callable[[Mapping[str, float | str]], None] | None
) -> None:
def set_event_callback(self, callback: Callable[[EventData], None] | None) -> None:
self._backend.set_event_callback(callback)

def solve(self) -> Solution:
Expand Down
30 changes: 24 additions & 6 deletions src/ilpy/event_data.pyi → src/ilpy/event_data.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
from typing import Literal, TypeAlias, TypedDict
from __future__ import annotations

Check warning on line 1 in src/ilpy/event_data.py

View check run for this annotation

Codecov / codecov/patch

src/ilpy/event_data.py#L1

Added line #L1 was not covered by tests

from typing import TYPE_CHECKING, TypedDict

Check warning on line 3 in src/ilpy/event_data.py

View check run for this annotation

Codecov / codecov/patch

src/ilpy/event_data.py#L3

Added line #L3 was not covered by tests

__all__ = ["EventData", "GurobiData", "SCIPData"]

GurobiEventType: TypeAlias = Literal[
"PRESOLVE", "SIMPLEX", "MIP", "MIPSOL", "MIPNODE", "MESSAGE", "UNKNOWN"
]
SCIPEventType: TypeAlias = Literal["PRESOLVEROUND", "BESTSOLFOUND"]
EventType: TypeAlias = GurobiEventType | SCIPEventType
if TYPE_CHECKING:
from typing import Literal, TypeAlias

GurobiEventType: TypeAlias = Literal[
"PRESOLVE", "SIMPLEX", "MIP", "MIPSOL", "MIPNODE", "MESSAGE", "UNKNOWN"
]
SCIPEventType: TypeAlias = Literal["PRESOLVEROUND", "BESTSOLFOUND"]
EventType: TypeAlias = GurobiEventType | SCIPEventType


class _GurobiData(TypedDict, total=False):
backend: Literal["gurobi"]
runtime: float # Elapsed solver runtime (seconds).
work: float # Elapsed solver work (work units).


class GurobiPresolve(_GurobiData):
event_type: Literal["PRESOLVE"]
pre_coldel: int
Expand All @@ -21,6 +28,7 @@ class GurobiPresolve(_GurobiData):
pre_bndchg: int
pre_coechg: int


class GurobiSimplex(_GurobiData):
event_type: Literal["SIMPLEX"]
itrcnt: float
Expand All @@ -29,6 +37,7 @@ class GurobiSimplex(_GurobiData):
dualinf: float
ispert: int


class _GurobiMipData(_GurobiData):
objbst: float
objbnd: float
Expand All @@ -40,24 +49,29 @@ class _GurobiMipData(_GurobiData):
dualbound: float # alias for objbnd
gap: float # calculated manually from objbst and objbnd


class GurobiMip(_GurobiMipData):
event_type: Literal["MIP"]
cutcnt: int
nodlft: float
itrcnt: float


class GurobiMipSol(_GurobiMipData):
event_type: Literal["MIPSOL"]
obj: float


class GurobiMipNode(_GurobiMipData):
event_type: Literal["MIPNODE"]
status: int


class GurobiMessage(_GurobiData):
event_type: Literal["MESSAGE"]
message: str


GurobiData = (
GurobiPresolve
| GurobiSimplex
Expand All @@ -67,10 +81,12 @@ class GurobiMessage(_GurobiData):
| GurobiMessage
)


class _SCIPData(TypedDict, total=False):
backend: Literal["scip"]
deterministictime: float


class SCIPPresolve(_SCIPData):
event_type: Literal["PRESOLVEROUND"]
nativeconss: int
Expand All @@ -83,6 +99,7 @@ class SCIPPresolve(_SCIPData):
cutoffbound: float
nfixedvars: int


class SCIPBestSol(_SCIPData):
event_type: Literal["BESTSOLFOUND"]
avgdualbound: float
Expand All @@ -100,6 +117,7 @@ class SCIPBestSol(_SCIPData):
nlps: int
nnzs: int


SCIPData = SCIPPresolve | SCIPBestSol

EventData = GurobiData | SCIPData
8 changes: 3 additions & 5 deletions src/ilpy/solver_backends/_base.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Any, Callable, cast
from typing import TYPE_CHECKING, Any, Callable

if TYPE_CHECKING:
from collections.abc import Mapping
Expand All @@ -16,10 +16,8 @@ class SolverBackend(ABC):
def __init__(self) -> None:
self._event_callback: Callable[[EventData], None] | None = None

def set_event_callback(
self, callback: Callable[[Mapping[str, float | str]], None] | None
) -> None:
self._event_callback = cast("Callable[[EventData], None] | None", callback)
def set_event_callback(self, callback: Callable[[EventData], None] | None) -> None:
self._event_callback = callback

def emit_event_data(self, data: EventData) -> None:
if self._event_callback:
Expand Down

0 comments on commit 1b8e8da

Please sign in to comment.