pyomo-pounce 0.2.0__tar.gz

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.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyomo-pounce
3
+ Version: 0.2.0
4
+ Summary: Pyomo solver plugin for the POUNCE interior-point NLP solver
5
+ Author-email: John Kitchin <jkitchin@andrew.cmu.edu>
6
+ License: EPL-2.0
7
+ Project-URL: Homepage, https://github.com/jkitchin/pounce
8
+ Project-URL: Repository, https://github.com/jkitchin/pounce
9
+ Project-URL: Issues, https://github.com/jkitchin/pounce/issues
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: pyomo>=6.0
18
+ Requires-Dist: pounce-solver>=0.1
19
+
20
+ # pyomo-pounce
21
+
22
+ Pyomo solver plugin for [POUNCE](https://github.com/jkitchin/pounce), a
23
+ pure-Rust interior-point NLP solver (a Rust port of IPOPT).
24
+
25
+ POUNCE speaks the AMPL NL/SOL protocol, so Pyomo drives it through the
26
+ AMPL Solver Library interface — exactly how Pyomo integrates with IPOPT.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install pyomo-pounce
32
+ ```
33
+
34
+ That single command pulls in the `pounce-solver` dependency, which
35
+ ships a per-platform wheel bundling the `pounce` executable. After
36
+ install, `pounce` is on your `PATH` and Pyomo finds it automatically.
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ import pyomo_pounce # registers the solver
42
+ from pyomo.environ import *
43
+
44
+ model = ConcreteModel()
45
+ model.x = Var(initialize=0.5)
46
+ model.obj = Objective(expr=(model.x - 2)**2)
47
+
48
+ solver = SolverFactory('pounce')
49
+ result = solver.solve(model, tee=True)
50
+ print(f"x* = {value(model.x)}") # 2.0
51
+ ```
52
+
53
+ ## Solver Options
54
+
55
+ Pass options the same way as IPOPT:
56
+
57
+ ```python
58
+ solver = SolverFactory('pounce')
59
+ solver.options['max_iter'] = 1000
60
+ solver.options['tol'] = 1e-10
61
+ solver.options['print_level'] = 5
62
+ ```
63
+
64
+ Options are forwarded to POUNCE's `OptionsList` (ipopt.opt-compatible
65
+ keys).
66
+
67
+ ## Local development / unsupported platforms
68
+
69
+ If `pounce-solver` does not ship a wheel for your platform, the pip
70
+ install fails on the dependency. Two workarounds:
71
+
72
+ 1. **Build POUNCE from source and put it on `PATH`** — the plugin
73
+ resolves `pounce` via `shutil.which`, so any binary on `PATH`
74
+ works:
75
+
76
+ ```bash
77
+ # in the pounce repo
78
+ cargo build --release --bin pounce
79
+ export PATH="$PWD/target/release:$PATH"
80
+ pip install --no-deps pyomo-pounce pyomo
81
+ ```
82
+
83
+ 2. **Install `pounce-solver` from source** via maturin:
84
+
85
+ ```bash
86
+ cd pounce/python && maturin develop --release
87
+ # then `cargo install --path ../crates/pounce-cli` to get the CLI
88
+ # since maturin develop does not bundle the binary.
89
+ pip install pyomo-pounce
90
+ ```
91
+
92
+ ## License
93
+
94
+ EPL-2.0, same as POUNCE.
@@ -0,0 +1,75 @@
1
+ # pyomo-pounce
2
+
3
+ Pyomo solver plugin for [POUNCE](https://github.com/jkitchin/pounce), a
4
+ pure-Rust interior-point NLP solver (a Rust port of IPOPT).
5
+
6
+ POUNCE speaks the AMPL NL/SOL protocol, so Pyomo drives it through the
7
+ AMPL Solver Library interface — exactly how Pyomo integrates with IPOPT.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install pyomo-pounce
13
+ ```
14
+
15
+ That single command pulls in the `pounce-solver` dependency, which
16
+ ships a per-platform wheel bundling the `pounce` executable. After
17
+ install, `pounce` is on your `PATH` and Pyomo finds it automatically.
18
+
19
+ ## Usage
20
+
21
+ ```python
22
+ import pyomo_pounce # registers the solver
23
+ from pyomo.environ import *
24
+
25
+ model = ConcreteModel()
26
+ model.x = Var(initialize=0.5)
27
+ model.obj = Objective(expr=(model.x - 2)**2)
28
+
29
+ solver = SolverFactory('pounce')
30
+ result = solver.solve(model, tee=True)
31
+ print(f"x* = {value(model.x)}") # 2.0
32
+ ```
33
+
34
+ ## Solver Options
35
+
36
+ Pass options the same way as IPOPT:
37
+
38
+ ```python
39
+ solver = SolverFactory('pounce')
40
+ solver.options['max_iter'] = 1000
41
+ solver.options['tol'] = 1e-10
42
+ solver.options['print_level'] = 5
43
+ ```
44
+
45
+ Options are forwarded to POUNCE's `OptionsList` (ipopt.opt-compatible
46
+ keys).
47
+
48
+ ## Local development / unsupported platforms
49
+
50
+ If `pounce-solver` does not ship a wheel for your platform, the pip
51
+ install fails on the dependency. Two workarounds:
52
+
53
+ 1. **Build POUNCE from source and put it on `PATH`** — the plugin
54
+ resolves `pounce` via `shutil.which`, so any binary on `PATH`
55
+ works:
56
+
57
+ ```bash
58
+ # in the pounce repo
59
+ cargo build --release --bin pounce
60
+ export PATH="$PWD/target/release:$PATH"
61
+ pip install --no-deps pyomo-pounce pyomo
62
+ ```
63
+
64
+ 2. **Install `pounce-solver` from source** via maturin:
65
+
66
+ ```bash
67
+ cd pounce/python && maturin develop --release
68
+ # then `cargo install --path ../crates/pounce-cli` to get the CLI
69
+ # since maturin develop does not bundle the binary.
70
+ pip install pyomo-pounce
71
+ ```
72
+
73
+ ## License
74
+
75
+ EPL-2.0, same as POUNCE.
@@ -0,0 +1,10 @@
1
+ """Pyomo solver plugin for the POUNCE interior-point NLP solver.
2
+
3
+ Usage:
4
+ import pyomo_pounce # registers 'pounce' with SolverFactory
5
+ from pyomo.environ import *
6
+ solver = SolverFactory('pounce')
7
+ """
8
+ from pyomo_pounce.pounce_solver import POUNCE
9
+
10
+ __all__ = ["POUNCE"]
@@ -0,0 +1,36 @@
1
+ """POUNCE solver plugin for Pyomo.
2
+
3
+ Registers 'pounce' with Pyomo's SolverFactory. POUNCE speaks the AMPL
4
+ NL/SOL protocol, so Pyomo drives it through the AMPL Solver Library
5
+ interface exactly as it drives IPOPT.
6
+
7
+ The `pounce` binary is provided by the `pounce-solver` dependency,
8
+ which ships a per-platform wheel that drops the executable into the
9
+ active environment under `<venv>/bin/pounce`. Falls back to any
10
+ `pounce` already on PATH for system installs or local dev builds
11
+ (`cargo install --path crates/pounce-cli`).
12
+
13
+ Usage:
14
+ import pyomo_pounce
15
+ from pyomo.environ import *
16
+ solver = SolverFactory('pounce')
17
+ result = solver.solve(model)
18
+ """
19
+ import shutil
20
+
21
+ from pyomo.opt import SolverFactory
22
+ from pyomo.solvers.plugins.solvers.ASL import ASL
23
+
24
+
25
+ @SolverFactory.register("pounce", doc="The POUNCE interior-point NLP solver")
26
+ class POUNCE(ASL):
27
+ """Pyomo solver interface for POUNCE via the AMPL Solver Library protocol."""
28
+
29
+ def __init__(self, **kwds):
30
+ kwds["type"] = "pounce"
31
+ super().__init__(**kwds)
32
+ self._metasolver = False
33
+ self.options.solver = "pounce"
34
+
35
+ def _default_executable(self):
36
+ return shutil.which("pounce")
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyomo-pounce
3
+ Version: 0.2.0
4
+ Summary: Pyomo solver plugin for the POUNCE interior-point NLP solver
5
+ Author-email: John Kitchin <jkitchin@andrew.cmu.edu>
6
+ License: EPL-2.0
7
+ Project-URL: Homepage, https://github.com/jkitchin/pounce
8
+ Project-URL: Repository, https://github.com/jkitchin/pounce
9
+ Project-URL: Issues, https://github.com/jkitchin/pounce/issues
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: pyomo>=6.0
18
+ Requires-Dist: pounce-solver>=0.1
19
+
20
+ # pyomo-pounce
21
+
22
+ Pyomo solver plugin for [POUNCE](https://github.com/jkitchin/pounce), a
23
+ pure-Rust interior-point NLP solver (a Rust port of IPOPT).
24
+
25
+ POUNCE speaks the AMPL NL/SOL protocol, so Pyomo drives it through the
26
+ AMPL Solver Library interface — exactly how Pyomo integrates with IPOPT.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install pyomo-pounce
32
+ ```
33
+
34
+ That single command pulls in the `pounce-solver` dependency, which
35
+ ships a per-platform wheel bundling the `pounce` executable. After
36
+ install, `pounce` is on your `PATH` and Pyomo finds it automatically.
37
+
38
+ ## Usage
39
+
40
+ ```python
41
+ import pyomo_pounce # registers the solver
42
+ from pyomo.environ import *
43
+
44
+ model = ConcreteModel()
45
+ model.x = Var(initialize=0.5)
46
+ model.obj = Objective(expr=(model.x - 2)**2)
47
+
48
+ solver = SolverFactory('pounce')
49
+ result = solver.solve(model, tee=True)
50
+ print(f"x* = {value(model.x)}") # 2.0
51
+ ```
52
+
53
+ ## Solver Options
54
+
55
+ Pass options the same way as IPOPT:
56
+
57
+ ```python
58
+ solver = SolverFactory('pounce')
59
+ solver.options['max_iter'] = 1000
60
+ solver.options['tol'] = 1e-10
61
+ solver.options['print_level'] = 5
62
+ ```
63
+
64
+ Options are forwarded to POUNCE's `OptionsList` (ipopt.opt-compatible
65
+ keys).
66
+
67
+ ## Local development / unsupported platforms
68
+
69
+ If `pounce-solver` does not ship a wheel for your platform, the pip
70
+ install fails on the dependency. Two workarounds:
71
+
72
+ 1. **Build POUNCE from source and put it on `PATH`** — the plugin
73
+ resolves `pounce` via `shutil.which`, so any binary on `PATH`
74
+ works:
75
+
76
+ ```bash
77
+ # in the pounce repo
78
+ cargo build --release --bin pounce
79
+ export PATH="$PWD/target/release:$PATH"
80
+ pip install --no-deps pyomo-pounce pyomo
81
+ ```
82
+
83
+ 2. **Install `pounce-solver` from source** via maturin:
84
+
85
+ ```bash
86
+ cd pounce/python && maturin develop --release
87
+ # then `cargo install --path ../crates/pounce-cli` to get the CLI
88
+ # since maturin develop does not bundle the binary.
89
+ pip install pyomo-pounce
90
+ ```
91
+
92
+ ## License
93
+
94
+ EPL-2.0, same as POUNCE.
@@ -0,0 +1,11 @@
1
+ README.md
2
+ pyproject.toml
3
+ pyomo_pounce/__init__.py
4
+ pyomo_pounce/pounce_solver.py
5
+ pyomo_pounce.egg-info/PKG-INFO
6
+ pyomo_pounce.egg-info/SOURCES.txt
7
+ pyomo_pounce.egg-info/dependency_links.txt
8
+ pyomo_pounce.egg-info/entry_points.txt
9
+ pyomo_pounce.egg-info/requires.txt
10
+ pyomo_pounce.egg-info/top_level.txt
11
+ tests/test_pounce.py
@@ -0,0 +1,2 @@
1
+ [pyomo.solvers]
2
+ pounce = pyomo_pounce.pounce_solver
@@ -0,0 +1,2 @@
1
+ pyomo>=6.0
2
+ pounce-solver>=0.1
@@ -0,0 +1 @@
1
+ pyomo_pounce
@@ -0,0 +1,39 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyomo-pounce"
7
+ version = "0.2.0"
8
+ description = "Pyomo solver plugin for the POUNCE interior-point NLP solver"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = {text = "EPL-2.0"}
12
+ authors = [{name = "John Kitchin", email = "jkitchin@andrew.cmu.edu"}]
13
+ # Pyomo gives us the SolverFactory machinery; pounce-solver supplies
14
+ # the actual `pounce` executable on PATH (it ships the Rust CLI inside
15
+ # its wheel). Pinning >=0.1 keeps us forward-compatible across POUNCE
16
+ # point releases; tighten if we ever need to coordinate Pyomo/POUNCE
17
+ # API changes.
18
+ dependencies = [
19
+ "pyomo>=6.0",
20
+ "pounce-solver>=0.1",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 4 - Beta",
24
+ "Intended Audience :: Science/Research",
25
+ "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)",
26
+ "Programming Language :: Python :: 3",
27
+ "Topic :: Scientific/Engineering :: Mathematics",
28
+ ]
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/jkitchin/pounce"
32
+ Repository = "https://github.com/jkitchin/pounce"
33
+ Issues = "https://github.com/jkitchin/pounce/issues"
34
+
35
+ [project.entry-points."pyomo.solvers"]
36
+ pounce = "pyomo_pounce.pounce_solver"
37
+
38
+ [tool.setuptools.packages.find]
39
+ include = ["pyomo_pounce*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,68 @@
1
+ """Smoke tests for the pyomo-pounce solver plugin.
2
+
3
+ Run with `pytest`. The `pounce` binary must be on PATH (or bundled).
4
+ """
5
+ import pytest
6
+
7
+ import pyomo_pounce # noqa: F401 (registers 'pounce' with SolverFactory)
8
+ from pyomo.environ import (
9
+ ConcreteModel,
10
+ Constraint,
11
+ NonNegativeReals,
12
+ Objective,
13
+ SolverFactory,
14
+ Var,
15
+ value,
16
+ )
17
+
18
+
19
+ @pytest.fixture(scope="module")
20
+ def solver():
21
+ s = SolverFactory("pounce")
22
+ if not s.available(exception_flag=False):
23
+ pytest.skip("pounce binary not found on PATH")
24
+ return s
25
+
26
+
27
+ def test_registered():
28
+ assert SolverFactory("pounce") is not None
29
+
30
+
31
+ def test_unconstrained(solver):
32
+ """min (x - 2)^2 -> x* = 2."""
33
+ m = ConcreteModel()
34
+ m.x = Var(initialize=0.5)
35
+ m.obj = Objective(expr=(m.x - 2) ** 2)
36
+
37
+ solver.solve(m)
38
+
39
+ assert value(m.x) == pytest.approx(2.0, abs=1e-6)
40
+
41
+
42
+ def test_constrained(solver):
43
+ """min (x-2)^2 + (y-3)^2 s.t. x + y <= 4 -> (1.5, 2.5)."""
44
+ m = ConcreteModel()
45
+ m.x = Var(domain=NonNegativeReals, initialize=1.0)
46
+ m.y = Var(domain=NonNegativeReals, initialize=1.0)
47
+ m.obj = Objective(expr=(m.x - 2) ** 2 + (m.y - 3) ** 2)
48
+ m.budget = Constraint(expr=m.x + m.y <= 4)
49
+
50
+ solver.solve(m)
51
+
52
+ assert value(m.x) == pytest.approx(1.5, abs=1e-5)
53
+ assert value(m.y) == pytest.approx(2.5, abs=1e-5)
54
+
55
+
56
+ def test_options_forwarded(solver):
57
+ """`max_iter` is forwarded; 0 iterations cannot reach optimality."""
58
+ m = ConcreteModel()
59
+ m.x = Var(initialize=0.5)
60
+ m.obj = Objective(expr=(m.x - 2) ** 2)
61
+
62
+ solver.options["max_iter"] = 0
63
+ try:
64
+ result = solver.solve(m)
65
+ finally:
66
+ del solver.options["max_iter"]
67
+
68
+ assert str(result.solver.termination_condition) != "optimal"