planteo 0.1.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.
- planteo-0.1.0/LICENSE +21 -0
- planteo-0.1.0/PKG-INFO +180 -0
- planteo-0.1.0/README.md +150 -0
- planteo-0.1.0/pyproject.toml +67 -0
- planteo-0.1.0/setup.cfg +4 -0
- planteo-0.1.0/src/planteo/__init__.py +134 -0
- planteo-0.1.0/src/planteo/canonical.py +252 -0
- planteo-0.1.0/src/planteo/dimensions.py +212 -0
- planteo-0.1.0/src/planteo/emit/__init__.py +34 -0
- planteo-0.1.0/src/planteo/emit/pyomo.py +320 -0
- planteo-0.1.0/src/planteo/expressions.py +324 -0
- planteo-0.1.0/src/planteo/problem.py +283 -0
- planteo-0.1.0/src/planteo/py.typed +0 -0
- planteo-0.1.0/src/planteo/relations.py +255 -0
- planteo-0.1.0/src/planteo/spans.py +145 -0
- planteo-0.1.0/src/planteo/validate.py +299 -0
- planteo-0.1.0/src/planteo.egg-info/PKG-INFO +180 -0
- planteo-0.1.0/src/planteo.egg-info/SOURCES.txt +28 -0
- planteo-0.1.0/src/planteo.egg-info/dependency_links.txt +1 -0
- planteo-0.1.0/src/planteo.egg-info/requires.txt +7 -0
- planteo-0.1.0/src/planteo.egg-info/top_level.txt +1 -0
- planteo-0.1.0/tests/test_canonical.py +149 -0
- planteo-0.1.0/tests/test_emit_pyomo.py +113 -0
- planteo-0.1.0/tests/test_family_optimization.py +65 -0
- planteo-0.1.0/tests/test_schema.py +83 -0
- planteo-0.1.0/tests/test_types.py +63 -0
- planteo-0.1.0/tests/test_validate_closure.py +113 -0
- planteo-0.1.0/tests/test_validate_determinacy.py +135 -0
- planteo-0.1.0/tests/test_validate_dimensions.py +128 -0
- planteo-0.1.0/tests/test_validate_spans.py +64 -0
planteo-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Felipe Santibanez-Leal
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
planteo-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: planteo
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A typed representation for a problem after it has been read and before it is solved: dimensions on every quantity, provenance on every element, and a record of what the narrative left open.
|
|
5
|
+
Author-email: Felipe Santibanez-Leal <fsantibanez@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/fsantibanezleal/CAOS_Planteo
|
|
8
|
+
Project-URL: Source, https://github.com/fsantibanezleal/CAOS_Planteo
|
|
9
|
+
Project-URL: Issues, https://github.com/fsantibanezleal/CAOS_Planteo/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/fsantibanezleal/CAOS_Planteo/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: optimization,formalization,autoformalization,operations-research,units,dimensional-analysis,modeling
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Provides-Extra: pyomo
|
|
25
|
+
Requires-Dist: pyomo>=6.7; extra == "pyomo"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# planteo
|
|
32
|
+
|
|
33
|
+
[](https://pypi.org/project/planteo/)
|
|
34
|
+
[](LICENSE)
|
|
35
|
+
|
|
36
|
+
A typed representation for a problem **after it has been read and before it is solved**.
|
|
37
|
+
|
|
38
|
+
A narrative problem statement is ambiguous, under-specified and unit-bearing. Turning it into a
|
|
39
|
+
solver model is usually done by writing code straight from the text, and that loses the two things
|
|
40
|
+
that decide whether the result is right: **which words produced which symbol**, and **what the words
|
|
41
|
+
did not say**.
|
|
42
|
+
|
|
43
|
+
`planteo` holds the object in between. It does not read natural language and it does not solve
|
|
44
|
+
anything. It defines the object, checks it, and emits it.
|
|
45
|
+
|
|
46
|
+
## Why this exists
|
|
47
|
+
|
|
48
|
+
Across four different fields, the reported check is that the artifact **ran**, and the measured
|
|
49
|
+
faithfulness is much lower:
|
|
50
|
+
|
|
51
|
+
| Field | What gets reported | What was measured |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| Optimization modelling | the solver reached the reference objective | objective correctness does not imply a correct model; compensating errors pass ([survey](https://arxiv.org/abs/2508.10047)) |
|
|
54
|
+
| Statement formalization | it compiles | a 3.0 to 29.0 point compile-to-faithfulness gap; the strongest agent compiled 89.5% and was faithful 60.5% ([study](https://arxiv.org/abs/2606.31002)) |
|
|
55
|
+
| Experiment design | the plan looks complete | every model tested is weak at datasets, baselines and metrics ([benchmark](https://arxiv.org/abs/2608.03501)) |
|
|
56
|
+
| Simulation modelling | the model runs | tools do well at qualitative work, badly at causal reasoning and quantitative fixes ([benchmark](https://arxiv.org/abs/2605.28994)) |
|
|
57
|
+
|
|
58
|
+
A model that runs is not a model that is right. This package makes the difference inspectable.
|
|
59
|
+
|
|
60
|
+
## The two design commitments
|
|
61
|
+
|
|
62
|
+
**Every quantity carries a dimension.** Not optional, and dimensionless is a dimension that must be
|
|
63
|
+
stated. Adding metres to seconds is rejected before a solver ever sees it, and a unit is compared by
|
|
64
|
+
its exponent vector rather than by its label, so tonnes and kilograms are compatible while a
|
|
65
|
+
string comparison would say otherwise.
|
|
66
|
+
|
|
67
|
+
**Every element carries its provenance.** A `Span` records the offsets *and* the text it covered, so
|
|
68
|
+
a document that has been stored or moved can be checked against its narrative rather than trusted. An
|
|
69
|
+
element with no span states that it was inferred, and why.
|
|
70
|
+
|
|
71
|
+
And one thing no surveyed representation carries: **`open_questions`**. When the narrative does not
|
|
72
|
+
determine something, the question is recorded with the span that raised it and the choice that was
|
|
73
|
+
taken, instead of being silently resolved.
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install planteo # the representation, zero dependencies
|
|
79
|
+
pip install "planteo[pyomo]" # plus the Pyomo emitter
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Use
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from planteo import (
|
|
86
|
+
Comparator, Compare, Dimension, Domain, Family, Narrative,
|
|
87
|
+
Objective, Problem, Product, Quantity, Ref, Role, Sense, Span, Sum, validate,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
text = Narrative(
|
|
91
|
+
"A plant blends ore from two pits. Pit A costs 12 USD per tonne and pit B "
|
|
92
|
+
"costs 9 USD per tonne. Together they must deliver at least 100 tonnes. "
|
|
93
|
+
"Minimise the total cost."
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
TONNE = Dimension.of("t", mass=1)
|
|
97
|
+
PER_TONNE = Dimension.of("USD/t", currency=1, mass=-1)
|
|
98
|
+
|
|
99
|
+
problem = Problem(
|
|
100
|
+
narrative=text,
|
|
101
|
+
family=Family.OPTIMIZATION,
|
|
102
|
+
quantities=(
|
|
103
|
+
Quantity("x_a", Role.VARIABLE, TONNE, lower=0.0, span=Span.find(text, "Pit A")),
|
|
104
|
+
Quantity("x_b", Role.VARIABLE, TONNE, lower=0.0, span=Span.find(text, "pit B")),
|
|
105
|
+
Quantity("c_a", Role.PARAMETER, PER_TONNE, value=12.0),
|
|
106
|
+
Quantity("c_b", Role.PARAMETER, PER_TONNE, value=9.0),
|
|
107
|
+
Quantity("demand", Role.PARAMETER, TONNE, value=100.0),
|
|
108
|
+
),
|
|
109
|
+
relations=(
|
|
110
|
+
Compare(Sum((Ref("x_a"), Ref("x_b"))), Comparator.GE, Ref("demand"), name="meet_demand"),
|
|
111
|
+
),
|
|
112
|
+
objectives=(
|
|
113
|
+
Objective(Sense.MINIMISE, Sum((
|
|
114
|
+
Product((Ref("c_a"), Ref("x_a"))),
|
|
115
|
+
Product((Ref("c_b"), Ref("x_b"))),
|
|
116
|
+
)), name="total_cost"),
|
|
117
|
+
),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
report = validate(problem)
|
|
121
|
+
assert report.ok, report
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Emit it:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from planteo.emit import pyomo as emit
|
|
128
|
+
|
|
129
|
+
print(emit.emit_source(problem)) # a runnable Pyomo script, with provenance comments
|
|
130
|
+
model = emit.build_model(problem) # or a live ConcreteModel
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The emitted source carries the narrative alongside the code, so a reader can check the formalization
|
|
134
|
+
against the words:
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# tonnes taken from pit A
|
|
138
|
+
# from the narrative: "Pit A"
|
|
139
|
+
model.x_a = pyo.Var(domain=pyo.Reals, bounds=(0.0, None)) # t
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Compare two formalizations:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from planteo import compare
|
|
146
|
+
|
|
147
|
+
compare(mine, yours).verdict # Verdict.EQUIVALENT | Verdict.NOT_PROVEN_EQUIVALENT
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
There is deliberately no `DIFFERENT` verdict. Equal canonical form proves equivalence; unequal
|
|
151
|
+
canonical form proves nothing, and a vocabulary that pretended otherwise would produce confident
|
|
152
|
+
false negatives.
|
|
153
|
+
|
|
154
|
+
## What it validates
|
|
155
|
+
|
|
156
|
+
1. **Dimensions.** Every relation is checked term by term; both sides of a comparator must agree.
|
|
157
|
+
2. **Closure.** No free symbol.
|
|
158
|
+
3. **Determinacy.** Every quantity is given, chosen, derived by exactly one relation, or observed.
|
|
159
|
+
4. **Span integrity.** Every span still covers the text it recorded.
|
|
160
|
+
5. **Family completeness.** The family's required structure is present.
|
|
161
|
+
|
|
162
|
+
The validator reports every finding rather than stopping at the first, and each finding names the
|
|
163
|
+
element it is about.
|
|
164
|
+
|
|
165
|
+
## What it is not
|
|
166
|
+
|
|
167
|
+
- Not a translator. Producing a `Problem` from text is the job of a harness; this defines the target.
|
|
168
|
+
- Not a solver or a solver wrapper.
|
|
169
|
+
- Not a modelling language. It emits to Pyomo and MiniZinc rather than competing with them.
|
|
170
|
+
- Not an equivalence oracle. See the verdict vocabulary above.
|
|
171
|
+
|
|
172
|
+
## Documentation
|
|
173
|
+
|
|
174
|
+
The wiki is in [`docs/`](docs/). The design document that governs this package, written before any
|
|
175
|
+
code, is [`docs/design/SDD.md`](docs/design/SDD.md); every requirement in it names the test that
|
|
176
|
+
verifies it.
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT. See [LICENSE](LICENSE).
|
planteo-0.1.0/README.md
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# planteo
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/planteo/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
A typed representation for a problem **after it has been read and before it is solved**.
|
|
7
|
+
|
|
8
|
+
A narrative problem statement is ambiguous, under-specified and unit-bearing. Turning it into a
|
|
9
|
+
solver model is usually done by writing code straight from the text, and that loses the two things
|
|
10
|
+
that decide whether the result is right: **which words produced which symbol**, and **what the words
|
|
11
|
+
did not say**.
|
|
12
|
+
|
|
13
|
+
`planteo` holds the object in between. It does not read natural language and it does not solve
|
|
14
|
+
anything. It defines the object, checks it, and emits it.
|
|
15
|
+
|
|
16
|
+
## Why this exists
|
|
17
|
+
|
|
18
|
+
Across four different fields, the reported check is that the artifact **ran**, and the measured
|
|
19
|
+
faithfulness is much lower:
|
|
20
|
+
|
|
21
|
+
| Field | What gets reported | What was measured |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Optimization modelling | the solver reached the reference objective | objective correctness does not imply a correct model; compensating errors pass ([survey](https://arxiv.org/abs/2508.10047)) |
|
|
24
|
+
| Statement formalization | it compiles | a 3.0 to 29.0 point compile-to-faithfulness gap; the strongest agent compiled 89.5% and was faithful 60.5% ([study](https://arxiv.org/abs/2606.31002)) |
|
|
25
|
+
| Experiment design | the plan looks complete | every model tested is weak at datasets, baselines and metrics ([benchmark](https://arxiv.org/abs/2608.03501)) |
|
|
26
|
+
| Simulation modelling | the model runs | tools do well at qualitative work, badly at causal reasoning and quantitative fixes ([benchmark](https://arxiv.org/abs/2605.28994)) |
|
|
27
|
+
|
|
28
|
+
A model that runs is not a model that is right. This package makes the difference inspectable.
|
|
29
|
+
|
|
30
|
+
## The two design commitments
|
|
31
|
+
|
|
32
|
+
**Every quantity carries a dimension.** Not optional, and dimensionless is a dimension that must be
|
|
33
|
+
stated. Adding metres to seconds is rejected before a solver ever sees it, and a unit is compared by
|
|
34
|
+
its exponent vector rather than by its label, so tonnes and kilograms are compatible while a
|
|
35
|
+
string comparison would say otherwise.
|
|
36
|
+
|
|
37
|
+
**Every element carries its provenance.** A `Span` records the offsets *and* the text it covered, so
|
|
38
|
+
a document that has been stored or moved can be checked against its narrative rather than trusted. An
|
|
39
|
+
element with no span states that it was inferred, and why.
|
|
40
|
+
|
|
41
|
+
And one thing no surveyed representation carries: **`open_questions`**. When the narrative does not
|
|
42
|
+
determine something, the question is recorded with the span that raised it and the choice that was
|
|
43
|
+
taken, instead of being silently resolved.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install planteo # the representation, zero dependencies
|
|
49
|
+
pip install "planteo[pyomo]" # plus the Pyomo emitter
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Use
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from planteo import (
|
|
56
|
+
Comparator, Compare, Dimension, Domain, Family, Narrative,
|
|
57
|
+
Objective, Problem, Product, Quantity, Ref, Role, Sense, Span, Sum, validate,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
text = Narrative(
|
|
61
|
+
"A plant blends ore from two pits. Pit A costs 12 USD per tonne and pit B "
|
|
62
|
+
"costs 9 USD per tonne. Together they must deliver at least 100 tonnes. "
|
|
63
|
+
"Minimise the total cost."
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
TONNE = Dimension.of("t", mass=1)
|
|
67
|
+
PER_TONNE = Dimension.of("USD/t", currency=1, mass=-1)
|
|
68
|
+
|
|
69
|
+
problem = Problem(
|
|
70
|
+
narrative=text,
|
|
71
|
+
family=Family.OPTIMIZATION,
|
|
72
|
+
quantities=(
|
|
73
|
+
Quantity("x_a", Role.VARIABLE, TONNE, lower=0.0, span=Span.find(text, "Pit A")),
|
|
74
|
+
Quantity("x_b", Role.VARIABLE, TONNE, lower=0.0, span=Span.find(text, "pit B")),
|
|
75
|
+
Quantity("c_a", Role.PARAMETER, PER_TONNE, value=12.0),
|
|
76
|
+
Quantity("c_b", Role.PARAMETER, PER_TONNE, value=9.0),
|
|
77
|
+
Quantity("demand", Role.PARAMETER, TONNE, value=100.0),
|
|
78
|
+
),
|
|
79
|
+
relations=(
|
|
80
|
+
Compare(Sum((Ref("x_a"), Ref("x_b"))), Comparator.GE, Ref("demand"), name="meet_demand"),
|
|
81
|
+
),
|
|
82
|
+
objectives=(
|
|
83
|
+
Objective(Sense.MINIMISE, Sum((
|
|
84
|
+
Product((Ref("c_a"), Ref("x_a"))),
|
|
85
|
+
Product((Ref("c_b"), Ref("x_b"))),
|
|
86
|
+
)), name="total_cost"),
|
|
87
|
+
),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
report = validate(problem)
|
|
91
|
+
assert report.ok, report
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Emit it:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from planteo.emit import pyomo as emit
|
|
98
|
+
|
|
99
|
+
print(emit.emit_source(problem)) # a runnable Pyomo script, with provenance comments
|
|
100
|
+
model = emit.build_model(problem) # or a live ConcreteModel
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The emitted source carries the narrative alongside the code, so a reader can check the formalization
|
|
104
|
+
against the words:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# tonnes taken from pit A
|
|
108
|
+
# from the narrative: "Pit A"
|
|
109
|
+
model.x_a = pyo.Var(domain=pyo.Reals, bounds=(0.0, None)) # t
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Compare two formalizations:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from planteo import compare
|
|
116
|
+
|
|
117
|
+
compare(mine, yours).verdict # Verdict.EQUIVALENT | Verdict.NOT_PROVEN_EQUIVALENT
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
There is deliberately no `DIFFERENT` verdict. Equal canonical form proves equivalence; unequal
|
|
121
|
+
canonical form proves nothing, and a vocabulary that pretended otherwise would produce confident
|
|
122
|
+
false negatives.
|
|
123
|
+
|
|
124
|
+
## What it validates
|
|
125
|
+
|
|
126
|
+
1. **Dimensions.** Every relation is checked term by term; both sides of a comparator must agree.
|
|
127
|
+
2. **Closure.** No free symbol.
|
|
128
|
+
3. **Determinacy.** Every quantity is given, chosen, derived by exactly one relation, or observed.
|
|
129
|
+
4. **Span integrity.** Every span still covers the text it recorded.
|
|
130
|
+
5. **Family completeness.** The family's required structure is present.
|
|
131
|
+
|
|
132
|
+
The validator reports every finding rather than stopping at the first, and each finding names the
|
|
133
|
+
element it is about.
|
|
134
|
+
|
|
135
|
+
## What it is not
|
|
136
|
+
|
|
137
|
+
- Not a translator. Producing a `Problem` from text is the job of a harness; this defines the target.
|
|
138
|
+
- Not a solver or a solver wrapper.
|
|
139
|
+
- Not a modelling language. It emits to Pyomo and MiniZinc rather than competing with them.
|
|
140
|
+
- Not an equivalence oracle. See the verdict vocabulary above.
|
|
141
|
+
|
|
142
|
+
## Documentation
|
|
143
|
+
|
|
144
|
+
The wiki is in [`docs/`](docs/). The design document that governs this package, written before any
|
|
145
|
+
code, is [`docs/design/SDD.md`](docs/design/SDD.md); every requirement in it names the test that
|
|
146
|
+
verifies it.
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "planteo"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A typed representation for a problem after it has been read and before it is solved: dimensions on every quantity, provenance on every element, and a record of what the narrative left open."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Felipe Santibanez-Leal", email = "fsantibanez@gmail.com" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"optimization",
|
|
15
|
+
"formalization",
|
|
16
|
+
"autoformalization",
|
|
17
|
+
"operations-research",
|
|
18
|
+
"units",
|
|
19
|
+
"dimensional-analysis",
|
|
20
|
+
"modeling",
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 3 - Alpha",
|
|
24
|
+
"Intended Audience :: Science/Research",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
31
|
+
"Typing :: Typed",
|
|
32
|
+
]
|
|
33
|
+
dependencies = []
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
pyomo = ["pyomo>=6.7"]
|
|
37
|
+
dev = ["pytest>=8.0", "ruff>=0.6"]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/fsantibanezleal/CAOS_Planteo"
|
|
41
|
+
Source = "https://github.com/fsantibanezleal/CAOS_Planteo"
|
|
42
|
+
Issues = "https://github.com/fsantibanezleal/CAOS_Planteo/issues"
|
|
43
|
+
Changelog = "https://github.com/fsantibanezleal/CAOS_Planteo/blob/main/CHANGELOG.md"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["src"]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.package-data]
|
|
49
|
+
planteo = ["py.typed"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
addopts = "-q"
|
|
54
|
+
|
|
55
|
+
[tool.ruff]
|
|
56
|
+
line-length = 100
|
|
57
|
+
target-version = "py311"
|
|
58
|
+
|
|
59
|
+
[tool.ruff.lint]
|
|
60
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
61
|
+
ignore = [
|
|
62
|
+
"E501",
|
|
63
|
+
# UP042 wants StrEnum. These enums inherit str deliberately: their .value is what
|
|
64
|
+
# lands in the JSON document and in canonical form, and StrEnum changes str() behaviour in a
|
|
65
|
+
# way that would alter serialised output. The mixin is the contract, not an oversight.
|
|
66
|
+
"UP042",
|
|
67
|
+
]
|
planteo-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""planteo: a typed representation for a problem after it has been read and before it is solved.
|
|
2
|
+
|
|
3
|
+
A narrative problem statement is ambiguous, under-specified and unit-bearing. Turning it into a
|
|
4
|
+
solver model, a simulation, an experiment design or a learning task is usually done by writing code
|
|
5
|
+
straight from the text, which loses the two things that decide whether the result is right: which
|
|
6
|
+
words produced which symbol, and what the words did not say.
|
|
7
|
+
|
|
8
|
+
This package holds the object in between. Quantities carry dimensions, elements carry the span of
|
|
9
|
+
text they came from, and what the narrative failed to determine is recorded as an open question
|
|
10
|
+
rather than silently resolved.
|
|
11
|
+
|
|
12
|
+
It does not read natural language and it does not solve anything. It defines the object, validates
|
|
13
|
+
it, and emits it.
|
|
14
|
+
|
|
15
|
+
>>> from planteo import Narrative, Problem, Family, Quantity, Role, Dimension
|
|
16
|
+
>>> text = Narrative("Buy at most 10 tonnes.")
|
|
17
|
+
>>> problem = Problem(narrative=text, family=Family.OPTIMIZATION)
|
|
18
|
+
>>> problem.family.value
|
|
19
|
+
'optimization'
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from .canonical import Comparison, Verdict, canonical_form, compare, digest
|
|
25
|
+
from .dimensions import (
|
|
26
|
+
AXES,
|
|
27
|
+
COUNT,
|
|
28
|
+
CURRENCY,
|
|
29
|
+
DIMENSIONLESS,
|
|
30
|
+
ENERGY,
|
|
31
|
+
LENGTH,
|
|
32
|
+
MASS,
|
|
33
|
+
MASS_RATE,
|
|
34
|
+
POWER,
|
|
35
|
+
TIME,
|
|
36
|
+
Dimension,
|
|
37
|
+
DimensionError,
|
|
38
|
+
)
|
|
39
|
+
from .emit import NotRepresentable
|
|
40
|
+
from .expressions import (
|
|
41
|
+
BigSum,
|
|
42
|
+
Conditional,
|
|
43
|
+
Constant,
|
|
44
|
+
Expression,
|
|
45
|
+
Power,
|
|
46
|
+
Product,
|
|
47
|
+
Ref,
|
|
48
|
+
Sum,
|
|
49
|
+
expression_from_json,
|
|
50
|
+
)
|
|
51
|
+
from .problem import (
|
|
52
|
+
SCHEMA_VERSION,
|
|
53
|
+
Assumption,
|
|
54
|
+
Domain,
|
|
55
|
+
Family,
|
|
56
|
+
Metadata,
|
|
57
|
+
OpenQuestion,
|
|
58
|
+
Problem,
|
|
59
|
+
Quantity,
|
|
60
|
+
Role,
|
|
61
|
+
)
|
|
62
|
+
from .relations import (
|
|
63
|
+
Comparator,
|
|
64
|
+
Compare,
|
|
65
|
+
ForAll,
|
|
66
|
+
Logical,
|
|
67
|
+
Objective,
|
|
68
|
+
Relation,
|
|
69
|
+
Sense,
|
|
70
|
+
relation_from_json,
|
|
71
|
+
)
|
|
72
|
+
from .spans import Narrative, Span, SpanError
|
|
73
|
+
from .validate import Finding, Report, Severity, ValidationError, validate
|
|
74
|
+
|
|
75
|
+
__version__ = "0.1.0"
|
|
76
|
+
#: The padded display form used in the CHANGELOG, the tag and any UI string.
|
|
77
|
+
__display_version__ = "0.01.000"
|
|
78
|
+
|
|
79
|
+
__all__ = [
|
|
80
|
+
"AXES",
|
|
81
|
+
"Assumption",
|
|
82
|
+
"BigSum",
|
|
83
|
+
"COUNT",
|
|
84
|
+
"CURRENCY",
|
|
85
|
+
"Comparator",
|
|
86
|
+
"Comparison",
|
|
87
|
+
"Compare",
|
|
88
|
+
"Conditional",
|
|
89
|
+
"Constant",
|
|
90
|
+
"DIMENSIONLESS",
|
|
91
|
+
"Dimension",
|
|
92
|
+
"DimensionError",
|
|
93
|
+
"Domain",
|
|
94
|
+
"ENERGY",
|
|
95
|
+
"Expression",
|
|
96
|
+
"Family",
|
|
97
|
+
"Finding",
|
|
98
|
+
"ForAll",
|
|
99
|
+
"LENGTH",
|
|
100
|
+
"Logical",
|
|
101
|
+
"MASS",
|
|
102
|
+
"MASS_RATE",
|
|
103
|
+
"Metadata",
|
|
104
|
+
"Narrative",
|
|
105
|
+
"NotRepresentable",
|
|
106
|
+
"Objective",
|
|
107
|
+
"OpenQuestion",
|
|
108
|
+
"POWER",
|
|
109
|
+
"Power",
|
|
110
|
+
"Problem",
|
|
111
|
+
"Product",
|
|
112
|
+
"Quantity",
|
|
113
|
+
"Ref",
|
|
114
|
+
"Relation",
|
|
115
|
+
"Report",
|
|
116
|
+
"Role",
|
|
117
|
+
"SCHEMA_VERSION",
|
|
118
|
+
"Sense",
|
|
119
|
+
"Severity",
|
|
120
|
+
"Span",
|
|
121
|
+
"SpanError",
|
|
122
|
+
"Sum",
|
|
123
|
+
"TIME",
|
|
124
|
+
"ValidationError",
|
|
125
|
+
"Verdict",
|
|
126
|
+
"__display_version__",
|
|
127
|
+
"__version__",
|
|
128
|
+
"canonical_form",
|
|
129
|
+
"compare",
|
|
130
|
+
"digest",
|
|
131
|
+
"expression_from_json",
|
|
132
|
+
"relation_from_json",
|
|
133
|
+
"validate",
|
|
134
|
+
]
|