discopt.gams.daemon#

Warm solver daemon for the discopt GAMS link.

GAMS launches a solver as a fresh process per solve, so each solve otherwise re-pays Python + JAX import and first-JIT warmup (seconds), even though a warm solve is ~10 ms. This module keeps a single long-lived process warm and turns the per-solve launch into a thin socket round-trip.

The generic protocol / lifecycle / robustness machinery now lives in discopt._daemon_core; this module is the GAMS-specific layer (the control-file solve_fn, the discopt-gams socket name, and the (control_file, sysdir) -> int client contract the GAMS link relies on). It re-exports the core helpers under their historical names so existing imports keep working.

Classes#

DaemonServer

Warm GAMS solver server.

Functions#

default_socket_path(→ pathlib.Path)

Per-user socket path (honours DISCOPT_GAMS_SOCKET / XDG_RUNTIME_DIR).

ping(→ dict | None)

Return the running daemon's handshake, or None if not reachable.

stop_daemon(→ bool)

Ask a running daemon to shut down. Returns True if it acknowledged.

spawn_daemon(→ bool)

Start a detached GAMS daemon and wait until its socket answers.

solve_via_daemon(→ int | None)

Solve control_file through the warm daemon, spawning it if needed.

main(→ int)

python -m discopt.gams.daemon {serve,stop,status}.

Module Contents#

discopt.gams.daemon.default_socket_path() → pathlib.Path#

Per-user socket path (honours DISCOPT_GAMS_SOCKET / XDG_RUNTIME_DIR).

class discopt.gams.daemon.DaemonServer(socket_path: pathlib.Path | None = None, solve_fn=None, idle_timeout: float | None = None, max_lifetime: float | None = None, max_solves: int | None = None, max_rss_mb: int | None = None, jax_clear_every: int | None = None, version: str = _FINGERPRINT)#

Bases: discopt._daemon_core.DaemonServer

Warm GAMS solver server.

Wraps the historical (control_file, sysdir) -> int solve callback into the core’s request -> reply contract so the GAMS link and its tests keep their signature.

discopt.gams.daemon.ping(socket_path: pathlib.Path | None = None) → dict | None#

Return the running daemon’s handshake, or None if not reachable.

discopt.gams.daemon.stop_daemon(socket_path: pathlib.Path | None = None) → bool#

Ask a running daemon to shut down. Returns True if it acknowledged.

discopt.gams.daemon.spawn_daemon(socket_path: pathlib.Path | None = None, wait: float = _SPAWN_WAIT) → bool#

Start a detached GAMS daemon and wait until its socket answers.

discopt.gams.daemon.solve_via_daemon(control_file: str, sysdir: str | None = None, socket_path: pathlib.Path | None = None) → int | None#

Solve control_file through the warm daemon, spawning it if needed.

Returns the solver exit code, or None if the daemon is unreachable and could not be started – the caller should then solve in-process.

discopt.gams.daemon.main(argv: list[str] | None = None) → int#

python -m discopt.gams.daemon {serve,stop,status}.