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.
Files changed (201) hide show
  1. solverpilot/__init__.py +250 -0
  2. solverpilot/_immutability.py +27 -0
  3. solverpilot/_version.py +3 -0
  4. solverpilot/applications/__init__.py +3 -0
  5. solverpilot/applications/routing/__init__.py +19 -0
  6. solverpilot/applications/routing/compile_milp.py +321 -0
  7. solverpilot/applications/routing/diagnostics.py +78 -0
  8. solverpilot/applications/routing/errors.py +14 -0
  9. solverpilot/applications/routing/heuristics.py +167 -0
  10. solverpilot/applications/routing/model.py +259 -0
  11. solverpilot/applications/routing/reference.py +81 -0
  12. solverpilot/applications/routing/solution.py +89 -0
  13. solverpilot/applications/routing/timeline.py +79 -0
  14. solverpilot/applications/routing/validation.py +169 -0
  15. solverpilot/applications/tsp/__init__.py +41 -0
  16. solverpilot/applications/tsp/compile_cp.py +121 -0
  17. solverpilot/applications/tsp/compile_milp.py +139 -0
  18. solverpilot/applications/tsp/distance.py +60 -0
  19. solverpilot/applications/tsp/errors.py +17 -0
  20. solverpilot/applications/tsp/heuristics.py +112 -0
  21. solverpilot/applications/tsp/model.py +175 -0
  22. solverpilot/applications/tsp/reference.py +121 -0
  23. solverpilot/applications/tsp/solution.py +65 -0
  24. solverpilot/applications/tsp/validation.py +92 -0
  25. solverpilot/backends/__init__.py +51 -0
  26. solverpilot/backends/_casadi_highs_worker.py +92 -0
  27. solverpilot/backends/base.py +28 -0
  28. solverpilot/backends/bundled_capi.py +910 -0
  29. solverpilot/backends/casadi_conic.py +303 -0
  30. solverpilot/backends/health.py +240 -0
  31. solverpilot/backends/highspy_native.py +217 -0
  32. solverpilot/backends/nlopt_native.py +237 -0
  33. solverpilot/backends/osqp_native.py +297 -0
  34. solverpilot/backends/protocol_v2.py +119 -0
  35. solverpilot/backends/pyscipopt_native.py +200 -0
  36. solverpilot/backends/registry.py +38 -0
  37. solverpilot/backends/scipy_highs.py +138 -0
  38. solverpilot/backends/scipy_highs_lp.py +195 -0
  39. solverpilot/backends/scipy_slsqp_qp.py +133 -0
  40. solverpilot/backends/scipy_vendored_highs_dev.py +363 -0
  41. solverpilot/benchmark/__init__.py +23 -0
  42. solverpilot/benchmark/acquire.py +199 -0
  43. solverpilot/benchmark/baselines.py +70 -0
  44. solverpilot/benchmark/bundle.py +37 -0
  45. solverpilot/benchmark/campaign.py +150 -0
  46. solverpilot/benchmark/environment.py +115 -0
  47. solverpilot/benchmark/integrity.py +46 -0
  48. solverpilot/benchmark/model.py +146 -0
  49. solverpilot/benchmark/policy.py +182 -0
  50. solverpilot/benchmark/registry.py +38 -0
  51. solverpilot/benchmark/report.py +44 -0
  52. solverpilot/benchmark/runner.py +516 -0
  53. solverpilot/benchmark/slurm.py +55 -0
  54. solverpilot/benchmark/specs.py +75 -0
  55. solverpilot/benchmark/splits.py +181 -0
  56. solverpilot/benchmark/summary.py +384 -0
  57. solverpilot/benchmark/verify.py +142 -0
  58. solverpilot/benchmark/worker.py +71 -0
  59. solverpilot/bridges/__init__.py +19 -0
  60. solverpilot/bridges/engine.py +44 -0
  61. solverpilot/bridges/indicator.py +232 -0
  62. solverpilot/bridges/registry.py +78 -0
  63. solverpilot/bridges/transformation-tape.schema.json +53 -0
  64. solverpilot/bridges/types.py +149 -0
  65. solverpilot/bridges/validation.py +110 -0
  66. solverpilot/capabilities/__init__.py +32 -0
  67. solverpilot/capabilities/backend-capability-v2.schema.json +21 -0
  68. solverpilot/capabilities/conformance.py +151 -0
  69. solverpilot/capabilities/enums.py +27 -0
  70. solverpilot/capabilities/manifest.py +19 -0
  71. solverpilot/capabilities/ontology.py +73 -0
  72. solverpilot/capabilities/requirements.py +37 -0
  73. solverpilot/capabilities/resolve.py +30 -0
  74. solverpilot/capabilities/v2.py +711 -0
  75. solverpilot/cli/__init__.py +1 -0
  76. solverpilot/cli/backend_health.py +77 -0
  77. solverpilot/cli/benchmark.py +331 -0
  78. solverpilot/cli/benchmark_worker.py +33 -0
  79. solverpilot/cli/capabilities.py +65 -0
  80. solverpilot/conic/__init__.py +11 -0
  81. solverpilot/conic/backend.py +263 -0
  82. solverpilot/conic/compiler.py +310 -0
  83. solverpilot/conic/conformance.py +60 -0
  84. solverpilot/conic/conic-ir-v1.schema.json +24 -0
  85. solverpilot/conic/ir.py +299 -0
  86. solverpilot/conic/validation.py +149 -0
  87. solverpilot/cp/__init__.py +7 -0
  88. solverpilot/cp/conformance.py +32 -0
  89. solverpilot/cp/cp-ir-v1.schema.json +13 -0
  90. solverpilot/cp/ir.py +170 -0
  91. solverpilot/cp/model.py +143 -0
  92. solverpilot/cp/ortools_backend.py +423 -0
  93. solverpilot/cp/ortools_worker.py +75 -0
  94. solverpilot/cp/reference.py +51 -0
  95. solverpilot/cp/serialization.py +117 -0
  96. solverpilot/cp/validate.py +83 -0
  97. solverpilot/diagnose/__init__.py +33 -0
  98. solverpilot/diagnose/infeasibility.py +463 -0
  99. solverpilot/diagnose/model.py +87 -0
  100. solverpilot/evaluation/__init__.py +53 -0
  101. solverpilot/evaluation/metrics.py +150 -0
  102. solverpilot/evaluation/oracle.py +288 -0
  103. solverpilot/evaluation/proof.py +53 -0
  104. solverpilot/evaluation/references.py +73 -0
  105. solverpilot/evaluation/regret.py +281 -0
  106. solverpilot/exceptions.py +34 -0
  107. solverpilot/experimental/__init__.py +32 -0
  108. solverpilot/extensions/__init__.py +56 -0
  109. solverpilot/extensions/entrypoints.py +34 -0
  110. solverpilot/extensions/errors.py +35 -0
  111. solverpilot/extensions/manager.py +651 -0
  112. solverpilot/extensions/manifest.py +232 -0
  113. solverpilot/extensions/model.py +101 -0
  114. solverpilot/extensions/versioning.py +136 -0
  115. solverpilot/history/__init__.py +22 -0
  116. solverpilot/history/errors.py +15 -0
  117. solverpilot/history/model.py +129 -0
  118. solverpilot/history/sqlite.py +651 -0
  119. solverpilot/inspect/__init__.py +3 -0
  120. solverpilot/inspect/fingerprint.py +199 -0
  121. solverpilot/intelligence/__init__.py +36 -0
  122. solverpilot/intelligence/errors.py +16 -0
  123. solverpilot/intelligence/fingerprint.py +108 -0
  124. solverpilot/intelligence/leakage.py +69 -0
  125. solverpilot/intelligence/schema.py +314 -0
  126. solverpilot/intelligence/shift.py +208 -0
  127. solverpilot/io/__init__.py +41 -0
  128. solverpilot/io/binary64.py +49 -0
  129. solverpilot/io/csv.py +230 -0
  130. solverpilot/io/errors.py +25 -0
  131. solverpilot/io/hashing.py +111 -0
  132. solverpilot/io/json.py +90 -0
  133. solverpilot/io/mapping.py +195 -0
  134. solverpilot/io/model.py +407 -0
  135. solverpilot/io/numeric.py +108 -0
  136. solverpilot/io/provenance.py +114 -0
  137. solverpilot/io/result.py +45 -0
  138. solverpilot/io/source.py +104 -0
  139. solverpilot/io/strict_json.py +133 -0
  140. solverpilot/minlp/__init__.py +6 -0
  141. solverpilot/minlp/compiler.py +66 -0
  142. solverpilot/minlp/conformance.py +34 -0
  143. solverpilot/minlp/convexity.py +85 -0
  144. solverpilot/minlp/ir.py +35 -0
  145. solverpilot/minlp/minlp-ir-v1.schema.json +1 -0
  146. solverpilot/minlp/orchestrator.py +220 -0
  147. solverpilot/minlp/validation.py +28 -0
  148. solverpilot/model/__init__.py +27 -0
  149. solverpilot/model/compiler.py +1263 -0
  150. solverpilot/model/errors.py +22 -0
  151. solverpilot/model/expression.py +373 -0
  152. solverpilot/model/model.py +716 -0
  153. solverpilot/model/sets.py +60 -0
  154. solverpilot/model/types.py +36 -0
  155. solverpilot/nlp/__init__.py +7 -0
  156. solverpilot/nlp/ad.py +166 -0
  157. solverpilot/nlp/backend.py +113 -0
  158. solverpilot/nlp/compiler.py +116 -0
  159. solverpilot/nlp/conformance.py +58 -0
  160. solverpilot/nlp/ir.py +70 -0
  161. solverpilot/nlp/nlp-ir-v1.schema.json +1 -0
  162. solverpilot/nlp/validation.py +60 -0
  163. solverpilot/plan/__init__.py +33 -0
  164. solverpilot/plan/model.py +79 -0
  165. solverpilot/plan/planner.py +201 -0
  166. solverpilot/plan/production.py +627 -0
  167. solverpilot/plan/selective_lp.py +65 -0
  168. solverpilot/problem/__init__.py +16 -0
  169. solverpilot/problem/enums.py +20 -0
  170. solverpilot/problem/hashing.py +88 -0
  171. solverpilot/problem/linear.py +196 -0
  172. solverpilot/problem/mps.py +447 -0
  173. solverpilot/problem/quadratic.py +192 -0
  174. solverpilot/reporting/__init__.py +27 -0
  175. solverpilot/reporting/explain.py +327 -0
  176. solverpilot/reporting/model.py +264 -0
  177. solverpilot/reporting/render.py +55 -0
  178. solverpilot/runtime/__init__.py +19 -0
  179. solverpilot/runtime/auto.py +193 -0
  180. solverpilot/runtime/budgeting.py +43 -0
  181. solverpilot/runtime/executor.py +126 -0
  182. solverpilot/runtime/portfolio.py +197 -0
  183. solverpilot/runtime/result.py +72 -0
  184. solverpilot/session/__init__.py +29 -0
  185. solverpilot/session/conformance_v2.py +239 -0
  186. solverpilot/session/mutations.py +115 -0
  187. solverpilot/session/persistent-session-trace.schema.json +45 -0
  188. solverpilot/session/persistent.py +491 -0
  189. solverpilot/session/reuse.py +81 -0
  190. solverpilot/session/session.py +236 -0
  191. solverpilot/trace/__init__.py +3 -0
  192. solverpilot/trace/schema.py +47 -0
  193. solverpilot/validate/__init__.py +10 -0
  194. solverpilot/validate/core.py +179 -0
  195. solverpilot/validate/result.py +55 -0
  196. solverpilot-0.1.dist-info/METADATA +554 -0
  197. solverpilot-0.1.dist-info/RECORD +201 -0
  198. solverpilot-0.1.dist-info/WHEEL +5 -0
  199. solverpilot-0.1.dist-info/entry_points.txt +4 -0
  200. solverpilot-0.1.dist-info/licenses/LICENSE +202 -0
  201. 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: ...