solverpilot 0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- solverpilot/__init__.py +250 -0
- solverpilot/_immutability.py +27 -0
- solverpilot/_version.py +3 -0
- solverpilot/applications/__init__.py +3 -0
- solverpilot/applications/routing/__init__.py +19 -0
- solverpilot/applications/routing/compile_milp.py +321 -0
- solverpilot/applications/routing/diagnostics.py +78 -0
- solverpilot/applications/routing/errors.py +14 -0
- solverpilot/applications/routing/heuristics.py +167 -0
- solverpilot/applications/routing/model.py +259 -0
- solverpilot/applications/routing/reference.py +81 -0
- solverpilot/applications/routing/solution.py +89 -0
- solverpilot/applications/routing/timeline.py +79 -0
- solverpilot/applications/routing/validation.py +169 -0
- solverpilot/applications/tsp/__init__.py +41 -0
- solverpilot/applications/tsp/compile_cp.py +121 -0
- solverpilot/applications/tsp/compile_milp.py +139 -0
- solverpilot/applications/tsp/distance.py +60 -0
- solverpilot/applications/tsp/errors.py +17 -0
- solverpilot/applications/tsp/heuristics.py +112 -0
- solverpilot/applications/tsp/model.py +175 -0
- solverpilot/applications/tsp/reference.py +121 -0
- solverpilot/applications/tsp/solution.py +65 -0
- solverpilot/applications/tsp/validation.py +92 -0
- solverpilot/backends/__init__.py +51 -0
- solverpilot/backends/_casadi_highs_worker.py +92 -0
- solverpilot/backends/base.py +28 -0
- solverpilot/backends/bundled_capi.py +910 -0
- solverpilot/backends/casadi_conic.py +303 -0
- solverpilot/backends/health.py +240 -0
- solverpilot/backends/highspy_native.py +217 -0
- solverpilot/backends/nlopt_native.py +237 -0
- solverpilot/backends/osqp_native.py +297 -0
- solverpilot/backends/protocol_v2.py +119 -0
- solverpilot/backends/pyscipopt_native.py +200 -0
- solverpilot/backends/registry.py +38 -0
- solverpilot/backends/scipy_highs.py +138 -0
- solverpilot/backends/scipy_highs_lp.py +195 -0
- solverpilot/backends/scipy_slsqp_qp.py +133 -0
- solverpilot/backends/scipy_vendored_highs_dev.py +363 -0
- solverpilot/benchmark/__init__.py +23 -0
- solverpilot/benchmark/acquire.py +199 -0
- solverpilot/benchmark/baselines.py +70 -0
- solverpilot/benchmark/bundle.py +37 -0
- solverpilot/benchmark/campaign.py +150 -0
- solverpilot/benchmark/environment.py +115 -0
- solverpilot/benchmark/integrity.py +46 -0
- solverpilot/benchmark/model.py +146 -0
- solverpilot/benchmark/policy.py +182 -0
- solverpilot/benchmark/registry.py +38 -0
- solverpilot/benchmark/report.py +44 -0
- solverpilot/benchmark/runner.py +516 -0
- solverpilot/benchmark/slurm.py +55 -0
- solverpilot/benchmark/specs.py +75 -0
- solverpilot/benchmark/splits.py +181 -0
- solverpilot/benchmark/summary.py +384 -0
- solverpilot/benchmark/verify.py +142 -0
- solverpilot/benchmark/worker.py +71 -0
- solverpilot/bridges/__init__.py +19 -0
- solverpilot/bridges/engine.py +44 -0
- solverpilot/bridges/indicator.py +232 -0
- solverpilot/bridges/registry.py +78 -0
- solverpilot/bridges/transformation-tape.schema.json +53 -0
- solverpilot/bridges/types.py +149 -0
- solverpilot/bridges/validation.py +110 -0
- solverpilot/capabilities/__init__.py +32 -0
- solverpilot/capabilities/backend-capability-v2.schema.json +21 -0
- solverpilot/capabilities/conformance.py +151 -0
- solverpilot/capabilities/enums.py +27 -0
- solverpilot/capabilities/manifest.py +19 -0
- solverpilot/capabilities/ontology.py +73 -0
- solverpilot/capabilities/requirements.py +37 -0
- solverpilot/capabilities/resolve.py +30 -0
- solverpilot/capabilities/v2.py +711 -0
- solverpilot/cli/__init__.py +1 -0
- solverpilot/cli/backend_health.py +77 -0
- solverpilot/cli/benchmark.py +331 -0
- solverpilot/cli/benchmark_worker.py +33 -0
- solverpilot/cli/capabilities.py +65 -0
- solverpilot/conic/__init__.py +11 -0
- solverpilot/conic/backend.py +263 -0
- solverpilot/conic/compiler.py +310 -0
- solverpilot/conic/conformance.py +60 -0
- solverpilot/conic/conic-ir-v1.schema.json +24 -0
- solverpilot/conic/ir.py +299 -0
- solverpilot/conic/validation.py +149 -0
- solverpilot/cp/__init__.py +7 -0
- solverpilot/cp/conformance.py +32 -0
- solverpilot/cp/cp-ir-v1.schema.json +13 -0
- solverpilot/cp/ir.py +170 -0
- solverpilot/cp/model.py +143 -0
- solverpilot/cp/ortools_backend.py +423 -0
- solverpilot/cp/ortools_worker.py +75 -0
- solverpilot/cp/reference.py +51 -0
- solverpilot/cp/serialization.py +117 -0
- solverpilot/cp/validate.py +83 -0
- solverpilot/diagnose/__init__.py +33 -0
- solverpilot/diagnose/infeasibility.py +463 -0
- solverpilot/diagnose/model.py +87 -0
- solverpilot/evaluation/__init__.py +53 -0
- solverpilot/evaluation/metrics.py +150 -0
- solverpilot/evaluation/oracle.py +288 -0
- solverpilot/evaluation/proof.py +53 -0
- solverpilot/evaluation/references.py +73 -0
- solverpilot/evaluation/regret.py +281 -0
- solverpilot/exceptions.py +34 -0
- solverpilot/experimental/__init__.py +32 -0
- solverpilot/extensions/__init__.py +56 -0
- solverpilot/extensions/entrypoints.py +34 -0
- solverpilot/extensions/errors.py +35 -0
- solverpilot/extensions/manager.py +651 -0
- solverpilot/extensions/manifest.py +232 -0
- solverpilot/extensions/model.py +101 -0
- solverpilot/extensions/versioning.py +136 -0
- solverpilot/history/__init__.py +22 -0
- solverpilot/history/errors.py +15 -0
- solverpilot/history/model.py +129 -0
- solverpilot/history/sqlite.py +651 -0
- solverpilot/inspect/__init__.py +3 -0
- solverpilot/inspect/fingerprint.py +199 -0
- solverpilot/intelligence/__init__.py +36 -0
- solverpilot/intelligence/errors.py +16 -0
- solverpilot/intelligence/fingerprint.py +108 -0
- solverpilot/intelligence/leakage.py +69 -0
- solverpilot/intelligence/schema.py +314 -0
- solverpilot/intelligence/shift.py +208 -0
- solverpilot/io/__init__.py +41 -0
- solverpilot/io/binary64.py +49 -0
- solverpilot/io/csv.py +230 -0
- solverpilot/io/errors.py +25 -0
- solverpilot/io/hashing.py +111 -0
- solverpilot/io/json.py +90 -0
- solverpilot/io/mapping.py +195 -0
- solverpilot/io/model.py +407 -0
- solverpilot/io/numeric.py +108 -0
- solverpilot/io/provenance.py +114 -0
- solverpilot/io/result.py +45 -0
- solverpilot/io/source.py +104 -0
- solverpilot/io/strict_json.py +133 -0
- solverpilot/minlp/__init__.py +6 -0
- solverpilot/minlp/compiler.py +66 -0
- solverpilot/minlp/conformance.py +34 -0
- solverpilot/minlp/convexity.py +85 -0
- solverpilot/minlp/ir.py +35 -0
- solverpilot/minlp/minlp-ir-v1.schema.json +1 -0
- solverpilot/minlp/orchestrator.py +220 -0
- solverpilot/minlp/validation.py +28 -0
- solverpilot/model/__init__.py +27 -0
- solverpilot/model/compiler.py +1263 -0
- solverpilot/model/errors.py +22 -0
- solverpilot/model/expression.py +373 -0
- solverpilot/model/model.py +716 -0
- solverpilot/model/sets.py +60 -0
- solverpilot/model/types.py +36 -0
- solverpilot/nlp/__init__.py +7 -0
- solverpilot/nlp/ad.py +166 -0
- solverpilot/nlp/backend.py +113 -0
- solverpilot/nlp/compiler.py +116 -0
- solverpilot/nlp/conformance.py +58 -0
- solverpilot/nlp/ir.py +70 -0
- solverpilot/nlp/nlp-ir-v1.schema.json +1 -0
- solverpilot/nlp/validation.py +60 -0
- solverpilot/plan/__init__.py +33 -0
- solverpilot/plan/model.py +79 -0
- solverpilot/plan/planner.py +201 -0
- solverpilot/plan/production.py +627 -0
- solverpilot/plan/selective_lp.py +65 -0
- solverpilot/problem/__init__.py +16 -0
- solverpilot/problem/enums.py +20 -0
- solverpilot/problem/hashing.py +88 -0
- solverpilot/problem/linear.py +196 -0
- solverpilot/problem/mps.py +447 -0
- solverpilot/problem/quadratic.py +192 -0
- solverpilot/reporting/__init__.py +27 -0
- solverpilot/reporting/explain.py +327 -0
- solverpilot/reporting/model.py +264 -0
- solverpilot/reporting/render.py +55 -0
- solverpilot/runtime/__init__.py +19 -0
- solverpilot/runtime/auto.py +193 -0
- solverpilot/runtime/budgeting.py +43 -0
- solverpilot/runtime/executor.py +126 -0
- solverpilot/runtime/portfolio.py +197 -0
- solverpilot/runtime/result.py +72 -0
- solverpilot/session/__init__.py +29 -0
- solverpilot/session/conformance_v2.py +239 -0
- solverpilot/session/mutations.py +115 -0
- solverpilot/session/persistent-session-trace.schema.json +45 -0
- solverpilot/session/persistent.py +491 -0
- solverpilot/session/reuse.py +81 -0
- solverpilot/session/session.py +236 -0
- solverpilot/trace/__init__.py +3 -0
- solverpilot/trace/schema.py +47 -0
- solverpilot/validate/__init__.py +10 -0
- solverpilot/validate/core.py +179 -0
- solverpilot/validate/result.py +55 -0
- solverpilot-0.1.dist-info/METADATA +554 -0
- solverpilot-0.1.dist-info/RECORD +201 -0
- solverpilot-0.1.dist-info/WHEEL +5 -0
- solverpilot-0.1.dist-info/entry_points.txt +4 -0
- solverpilot-0.1.dist-info/licenses/LICENSE +202 -0
- solverpilot-0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from .base import Backend, BackendSolveResult, BackendUnavailableError
|
|
2
|
+
from .registry import BackendRegistry
|
|
3
|
+
from .scipy_highs import ScipyHighsBackend
|
|
4
|
+
from .scipy_highs_lp import ScipyHighsLPBackend
|
|
5
|
+
from .scipy_slsqp_qp import ScipySLSQPQPBackend
|
|
6
|
+
from .highspy_native import HighspyNativeBackend
|
|
7
|
+
from .osqp_native import OSQPNativeBackend
|
|
8
|
+
from .pyscipopt_native import PySCIPOptNativeBackend, SCIPIISResult
|
|
9
|
+
from .nlopt_native import NLoptNativeBackend
|
|
10
|
+
from .casadi_conic import CasadiConicBackend, CasadiOSQPBridgeBackend, CasadiHighsBridgeBackend, CasadiCBCBridgeBackend
|
|
11
|
+
from .bundled_capi import BundledOSQPCAPIBackend, BundledHighsCAPIBackend
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"Backend",
|
|
15
|
+
"BackendRegistry",
|
|
16
|
+
"BackendSolveResult",
|
|
17
|
+
"BackendUnavailableError",
|
|
18
|
+
"ScipyHighsBackend",
|
|
19
|
+
"ScipyHighsLPBackend",
|
|
20
|
+
"ScipySLSQPQPBackend",
|
|
21
|
+
"HighspyNativeBackend",
|
|
22
|
+
"OSQPNativeBackend",
|
|
23
|
+
"PySCIPOptNativeBackend",
|
|
24
|
+
"SCIPIISResult",
|
|
25
|
+
"NLoptNativeBackend",
|
|
26
|
+
"CasadiConicBackend",
|
|
27
|
+
"CasadiOSQPBridgeBackend",
|
|
28
|
+
"CasadiHighsBridgeBackend",
|
|
29
|
+
"CasadiCBCBridgeBackend",
|
|
30
|
+
"BundledOSQPCAPIBackend",
|
|
31
|
+
"BundledHighsCAPIBackend",
|
|
32
|
+
"ScipyVendoredHighsDevBackend",
|
|
33
|
+
"HighsDevIISResult",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
from .scipy_vendored_highs_dev import ScipyVendoredHighsDevBackend, HighsDevIISResult
|
|
37
|
+
|
|
38
|
+
from .health import BackendHealthReport, BackendProbeCheck, BackendProbeStatus, probe_backend, probe_backends
|
|
39
|
+
|
|
40
|
+
__all__ += ["BackendHealthReport", "BackendProbeCheck", "BackendProbeStatus", "probe_backend", "probe_backends"]
|
|
41
|
+
|
|
42
|
+
from .protocol_v2 import (
|
|
43
|
+
BackendArtifactBundle, BackendCallbackControllerV2, BackendCallbackV2, BackendProtocolV2,
|
|
44
|
+
BackendSolveRequestV2, BackendSolveResultV2, CallbackEvent, CallbackEventKind,
|
|
45
|
+
IncrementalBackendProtocolV2, StructuralIncrementalBackendProtocolV2,
|
|
46
|
+
)
|
|
47
|
+
__all__ += [
|
|
48
|
+
"BackendArtifactBundle", "BackendCallbackControllerV2", "BackendCallbackV2", "BackendProtocolV2",
|
|
49
|
+
"BackendSolveRequestV2", "BackendSolveResultV2", "CallbackEvent", "CallbackEventKind",
|
|
50
|
+
"IncrementalBackendProtocolV2", "StructuralIncrementalBackendProtocolV2",
|
|
51
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Process boundary for CasADi's HiGHS plugin; array transport never uses pickle."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from scipy import sparse
|
|
12
|
+
|
|
13
|
+
from solverpilot.problem import LinearProblem, QuadraticProblem
|
|
14
|
+
from solverpilot.problem.quadratic import require_confirmed_convexity
|
|
15
|
+
from .base import BackendSolveResult, BackendUnavailableError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def solve_isolated(backend, problem):
|
|
19
|
+
if not isinstance(problem, (LinearProblem, QuadraticProblem)):
|
|
20
|
+
raise TypeError(f"unsupported problem type: {type(problem)!r}")
|
|
21
|
+
if isinstance(problem, QuadraticProblem):
|
|
22
|
+
require_confirmed_convexity(problem)
|
|
23
|
+
if not backend.is_available():
|
|
24
|
+
raise BackendUnavailableError("CasADi conic plugin is unavailable: highs")
|
|
25
|
+
linear = problem.linear if isinstance(problem, QuadraticProblem) else problem
|
|
26
|
+
with tempfile.TemporaryDirectory(prefix="solverpilot-casadi-highs-") as temporary:
|
|
27
|
+
root = Path(temporary)
|
|
28
|
+
sparse.save_npz(root / "A.npz", linear.A)
|
|
29
|
+
if isinstance(problem, QuadraticProblem):
|
|
30
|
+
sparse.save_npz(root / "P.npz", problem.P)
|
|
31
|
+
np.savez(root / "vectors.npz", c=linear.c, lower=linear.variable_lower,
|
|
32
|
+
upper=linear.variable_upper, row_lower=linear.constraint_lower,
|
|
33
|
+
row_upper=linear.constraint_upper, domains=linear.domains)
|
|
34
|
+
(root / "options.json").write_text(json.dumps({
|
|
35
|
+
"quadratic": isinstance(problem, QuadraticProblem),
|
|
36
|
+
"sense": linear.objective_sense.value, "offset": float(linear.objective_offset),
|
|
37
|
+
"time_limit_s": backend.time_limit_s,
|
|
38
|
+
}), encoding="utf-8")
|
|
39
|
+
timeout = None if backend.time_limit_s is None else backend.time_limit_s + 30.0
|
|
40
|
+
try:
|
|
41
|
+
completed = subprocess.run(
|
|
42
|
+
[sys.executable, "-m", "solverpilot.backends._casadi_highs_worker", str(root)],
|
|
43
|
+
capture_output=True, timeout=timeout,
|
|
44
|
+
)
|
|
45
|
+
except subprocess.TimeoutExpired:
|
|
46
|
+
return BackendSolveResult("solver_error", None, raw_statistics={
|
|
47
|
+
"process_isolated": True, "error": "CasADi HiGHS worker exceeded controller timeout"})
|
|
48
|
+
output = root / "result.json"
|
|
49
|
+
if completed.returncode != 0 or not output.is_file():
|
|
50
|
+
return BackendSolveResult("solver_error", None, raw_statistics={
|
|
51
|
+
"process_isolated": True, "worker_returncode": completed.returncode,
|
|
52
|
+
"error": completed.stderr.decode("utf-8", errors="replace")[-2000:]})
|
|
53
|
+
result = json.loads(output.read_text(encoding="utf-8"))
|
|
54
|
+
statistics = result["raw_statistics"] or {}
|
|
55
|
+
statistics["process_isolated"] = True
|
|
56
|
+
return BackendSolveResult(result["backend_status"],
|
|
57
|
+
None if result["x"] is None else np.asarray(result["x"], dtype=np.float64),
|
|
58
|
+
result["objective_reported"], statistics)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _json_value(value):
|
|
62
|
+
if isinstance(value, np.ndarray):
|
|
63
|
+
return value.tolist()
|
|
64
|
+
if isinstance(value, np.generic):
|
|
65
|
+
return value.item()
|
|
66
|
+
raise TypeError(f"unsupported worker result value: {type(value)!r}")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def main():
|
|
70
|
+
from .casadi_conic import CasadiHighsBridgeBackend
|
|
71
|
+
root = Path(sys.argv[1])
|
|
72
|
+
options = json.loads((root / "options.json").read_text(encoding="utf-8"))
|
|
73
|
+
with np.load(root / "vectors.npz", allow_pickle=False) as vectors:
|
|
74
|
+
linear = LinearProblem.from_data(A=sparse.load_npz(root / "A.npz"), c=vectors["c"],
|
|
75
|
+
variable_lower=vectors["lower"], variable_upper=vectors["upper"],
|
|
76
|
+
constraint_lower=vectors["row_lower"], constraint_upper=vectors["row_upper"],
|
|
77
|
+
domains=vectors["domains"], objective_sense=options["sense"],
|
|
78
|
+
objective_offset=options["offset"])
|
|
79
|
+
problem = linear
|
|
80
|
+
if options["quadratic"]:
|
|
81
|
+
from solverpilot.problem import ConvexityStatus
|
|
82
|
+
problem = QuadraticProblem(linear, sparse.load_npz(root / "P.npz"), ConvexityStatus.CONFIRMED)
|
|
83
|
+
backend = CasadiHighsBridgeBackend(time_limit_s=options["time_limit_s"])
|
|
84
|
+
result = backend._solve_in_process(problem)
|
|
85
|
+
(root / "result.json").write_text(json.dumps({
|
|
86
|
+
"backend_status": result.backend_status, "x": result.x,
|
|
87
|
+
"objective_reported": result.objective_reported, "raw_statistics": result.raw_statistics,
|
|
88
|
+
}, default=_json_value), encoding="utf-8")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
main()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Protocol, runtime_checkable
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
from solverpilot.capabilities import BackendManifest
|
|
9
|
+
from solverpilot.problem import LinearProblem, QuadraticProblem
|
|
10
|
+
from solverpilot.exceptions import BackendUnavailableError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class BackendSolveResult:
|
|
15
|
+
backend_status: str
|
|
16
|
+
x: np.ndarray | None
|
|
17
|
+
objective_reported: float | None = None
|
|
18
|
+
raw_statistics: dict[str, object] | None = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@runtime_checkable
|
|
22
|
+
class Backend(Protocol):
|
|
23
|
+
@property
|
|
24
|
+
def manifest(self) -> BackendManifest: ...
|
|
25
|
+
|
|
26
|
+
def is_available(self) -> bool: ...
|
|
27
|
+
|
|
28
|
+
def solve(self, problem: LinearProblem | QuadraticProblem) -> BackendSolveResult: ...
|