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 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
+ [![PyPI](https://img.shields.io/pypi/v/planteo.svg)](https://pypi.org/project/planteo/)
34
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](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).
@@ -0,0 +1,150 @@
1
+ # planteo
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/planteo.svg)](https://pypi.org/project/planteo/)
4
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](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
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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
+ ]