cdclkit 0.1.0__tar.gz → 0.1.2__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.
- {cdclkit-0.1.0 → cdclkit-0.1.2}/PKG-INFO +22 -7
- {cdclkit-0.1.0 → cdclkit-0.1.2}/README.md +19 -6
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/__init__.py +1 -1
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/pipeline.py +1 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/portfolio.py +3 -1
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit.egg-info/PKG-INFO +22 -7
- cdclkit-0.1.2/cdclkit.egg-info/requires.txt +4 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/pyproject.toml +7 -1
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_native_solver.py +79 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_packaging.py +33 -0
- cdclkit-0.1.0/cdclkit.egg-info/requires.txt +0 -1
- {cdclkit-0.1.0 → cdclkit-0.1.2}/LICENSE +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/__main__.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/brute.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/cli.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/encodings.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/heap.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/model.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/mus.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/native.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/preprocess.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/pyeq.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit/solver.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit.egg-info/SOURCES.txt +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit.egg-info/dependency_links.txt +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit.egg-info/entry_points.txt +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/cdclkit.egg-info/top_level.txt +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/setup.cfg +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_core.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_encodings.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_integration.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_mus.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_native.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_pipeline.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_portfolio.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_preprocess.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_proof.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_pyeq.py +0 -0
- {cdclkit-0.1.0 → cdclkit-0.1.2}/tests/test_solver.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cdclkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate.
|
|
5
5
|
Author: Carlo Perassi
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -23,6 +23,8 @@ Requires-Python: >=3.10
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: dratify>=0.1.1
|
|
26
|
+
Provides-Extra: native
|
|
27
|
+
Requires-Dist: cdclkit-native==0.1.2; extra == "native"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
# cdclkit
|
|
@@ -33,9 +35,17 @@ library and a modelling layer — written from scratch in readable Python.**
|
|
|
33
35
|
Every answer comes with a certificate, and the certificate gets checked.
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
pip install cdclkit
|
|
38
|
+
pip install cdclkit # pure Python
|
|
39
|
+
pip install "cdclkit[native]" # plus the Rust engine, ~18x faster
|
|
37
40
|
```
|
|
38
41
|
|
|
42
|
+
Three packages, and no third-party code:
|
|
43
|
+
[`cdclkit`](https://pypi.org/project/cdclkit/),
|
|
44
|
+
[`dratify`](https://pypi.org/project/dratify/) (the proof checker, zero
|
|
45
|
+
dependencies), and optionally
|
|
46
|
+
[`cdclkit-native`](https://pypi.org/project/cdclkit-native/) (abi3 wheels for
|
|
47
|
+
Linux and macOS).
|
|
48
|
+
|
|
39
49
|
```bash
|
|
40
50
|
python3 -m cdclkit solve instance.cnf --self-check --check-model
|
|
41
51
|
```
|
|
@@ -77,16 +87,19 @@ puzzle, graph colouring, bounded model checking, circuit equivalence.
|
|
|
77
87
|
| `portfolio` | parallel configurations |
|
|
78
88
|
| `pyeq` | **experimental** — bounded equivalence of two Python integer functions |
|
|
79
89
|
|
|
80
|
-
An optional Rust engine (
|
|
81
|
-
|
|
90
|
+
An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-native/))
|
|
91
|
+
is roughly 18x faster
|
|
82
92
|
and **bit-exact** with the Python one: identical conflicts, decisions and
|
|
83
93
|
propagations on every instance. The pure-Python path has zero third-party
|
|
84
94
|
dependencies and is the one that must never break.
|
|
85
95
|
|
|
86
96
|
## Relationship to dratify
|
|
87
97
|
|
|
88
|
-
Proof checking lives in a separate package,
|
|
89
|
-
|
|
98
|
+
Proof checking lives in a separate package,
|
|
99
|
+
[`dratify`](https://pypi.org/project/dratify/)
|
|
100
|
+
([source](https://github.com/carlok/dratify), also a
|
|
101
|
+
[Rust crate](https://crates.io/crates/dratify)), which `cdclkit` depends on.
|
|
102
|
+
That split is deliberate:
|
|
90
103
|
|
|
91
104
|
- You should not have to install a SAT solver to verify a proof someone else
|
|
92
105
|
produced.
|
|
@@ -95,7 +108,9 @@ which `cdclkit` depends on. That split is deliberate:
|
|
|
95
108
|
solver rather than only by its own suite.
|
|
96
109
|
|
|
97
110
|
`dratify` has no dependencies of its own, so installing `cdclkit` pulls in no
|
|
98
|
-
third-party code.
|
|
111
|
+
third-party code. With `[native]`, `cdclkit-native` hands its compiled checker
|
|
112
|
+
to `dratify` through `register_native()`, so proof checking gets the Rust
|
|
113
|
+
implementation too rather than only the solver.
|
|
99
114
|
|
|
100
115
|
## Performance
|
|
101
116
|
|
|
@@ -6,9 +6,17 @@ library and a modelling layer — written from scratch in readable Python.**
|
|
|
6
6
|
Every answer comes with a certificate, and the certificate gets checked.
|
|
7
7
|
|
|
8
8
|
```bash
|
|
9
|
-
pip install cdclkit
|
|
9
|
+
pip install cdclkit # pure Python
|
|
10
|
+
pip install "cdclkit[native]" # plus the Rust engine, ~18x faster
|
|
10
11
|
```
|
|
11
12
|
|
|
13
|
+
Three packages, and no third-party code:
|
|
14
|
+
[`cdclkit`](https://pypi.org/project/cdclkit/),
|
|
15
|
+
[`dratify`](https://pypi.org/project/dratify/) (the proof checker, zero
|
|
16
|
+
dependencies), and optionally
|
|
17
|
+
[`cdclkit-native`](https://pypi.org/project/cdclkit-native/) (abi3 wheels for
|
|
18
|
+
Linux and macOS).
|
|
19
|
+
|
|
12
20
|
```bash
|
|
13
21
|
python3 -m cdclkit solve instance.cnf --self-check --check-model
|
|
14
22
|
```
|
|
@@ -50,16 +58,19 @@ puzzle, graph colouring, bounded model checking, circuit equivalence.
|
|
|
50
58
|
| `portfolio` | parallel configurations |
|
|
51
59
|
| `pyeq` | **experimental** — bounded equivalence of two Python integer functions |
|
|
52
60
|
|
|
53
|
-
An optional Rust engine (
|
|
54
|
-
|
|
61
|
+
An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-native/))
|
|
62
|
+
is roughly 18x faster
|
|
55
63
|
and **bit-exact** with the Python one: identical conflicts, decisions and
|
|
56
64
|
propagations on every instance. The pure-Python path has zero third-party
|
|
57
65
|
dependencies and is the one that must never break.
|
|
58
66
|
|
|
59
67
|
## Relationship to dratify
|
|
60
68
|
|
|
61
|
-
Proof checking lives in a separate package,
|
|
62
|
-
|
|
69
|
+
Proof checking lives in a separate package,
|
|
70
|
+
[`dratify`](https://pypi.org/project/dratify/)
|
|
71
|
+
([source](https://github.com/carlok/dratify), also a
|
|
72
|
+
[Rust crate](https://crates.io/crates/dratify)), which `cdclkit` depends on.
|
|
73
|
+
That split is deliberate:
|
|
63
74
|
|
|
64
75
|
- You should not have to install a SAT solver to verify a proof someone else
|
|
65
76
|
produced.
|
|
@@ -68,7 +79,9 @@ which `cdclkit` depends on. That split is deliberate:
|
|
|
68
79
|
solver rather than only by its own suite.
|
|
69
80
|
|
|
70
81
|
`dratify` has no dependencies of its own, so installing `cdclkit` pulls in no
|
|
71
|
-
third-party code.
|
|
82
|
+
third-party code. With `[native]`, `cdclkit-native` hands its compiled checker
|
|
83
|
+
to `dratify` through `register_native()`, so proof checking gets the Rust
|
|
84
|
+
implementation too rather than only the solver.
|
|
72
85
|
|
|
73
86
|
## Performance
|
|
74
87
|
|
|
@@ -52,7 +52,7 @@ from .preprocess import Preprocessor, preprocess
|
|
|
52
52
|
from dratify.proof import DRATChecker, MemoryProof, ProofWriter, check_proof
|
|
53
53
|
from .solver import Config, SAT, Solver, Stats, UNKNOWN, UNSAT
|
|
54
54
|
|
|
55
|
-
__version__ = "0.1.
|
|
55
|
+
__version__ = "0.1.2"
|
|
56
56
|
|
|
57
57
|
__all__ = [
|
|
58
58
|
"CNF",
|
|
@@ -92,6 +92,7 @@ def _solve(f: CNF, cfg: Config, budget: int | None, engine: str,
|
|
|
92
92
|
cla_decay=cfg.cla_decay, luby_base=float(cfg.luby_base),
|
|
93
93
|
first_reduce=cfg.first_reduce, reduce_inc=cfg.reduce_inc,
|
|
94
94
|
glue_keep=cfg.glue_keep, block_restart=cfg.block_restart,
|
|
95
|
+
rnd_freq=cfg.rnd_freq, rnd_seed=cfg.rnd_seed,
|
|
95
96
|
)
|
|
96
97
|
for c in f.clauses:
|
|
97
98
|
if not s.add_clause(list(c)):
|
|
@@ -235,6 +235,7 @@ def _worker_native(index, nvars, clauses, cfg_kwargs, want_proof):
|
|
|
235
235
|
cla_decay=cfg.cla_decay, luby_base=float(cfg.luby_base),
|
|
236
236
|
first_reduce=cfg.first_reduce, reduce_inc=cfg.reduce_inc,
|
|
237
237
|
glue_keep=cfg.glue_keep, block_restart=cfg.block_restart,
|
|
238
|
+
rnd_freq=cfg.rnd_freq, rnd_seed=cfg.rnd_seed,
|
|
238
239
|
)
|
|
239
240
|
if want_proof:
|
|
240
241
|
s.enable_proof() # must precede the first clause
|
|
@@ -416,7 +417,8 @@ def _config_tuples(configs):
|
|
|
416
417
|
var_decay=c.var_decay, var_decay_max=c.var_decay_max,
|
|
417
418
|
cla_decay=c.cla_decay, luby_base=float(c.luby_base),
|
|
418
419
|
first_reduce=c.first_reduce, reduce_inc=c.reduce_inc,
|
|
419
|
-
glue_keep=c.glue_keep, block_restart=c.block_restart
|
|
420
|
+
glue_keep=c.glue_keep, block_restart=c.block_restart,
|
|
421
|
+
rnd_freq=c.rnd_freq, rnd_seed=c.rnd_seed)
|
|
420
422
|
for c in configs
|
|
421
423
|
]
|
|
422
424
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cdclkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate.
|
|
5
5
|
Author: Carlo Perassi
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -23,6 +23,8 @@ Requires-Python: >=3.10
|
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: dratify>=0.1.1
|
|
26
|
+
Provides-Extra: native
|
|
27
|
+
Requires-Dist: cdclkit-native==0.1.2; extra == "native"
|
|
26
28
|
Dynamic: license-file
|
|
27
29
|
|
|
28
30
|
# cdclkit
|
|
@@ -33,9 +35,17 @@ library and a modelling layer — written from scratch in readable Python.**
|
|
|
33
35
|
Every answer comes with a certificate, and the certificate gets checked.
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
pip install cdclkit
|
|
38
|
+
pip install cdclkit # pure Python
|
|
39
|
+
pip install "cdclkit[native]" # plus the Rust engine, ~18x faster
|
|
37
40
|
```
|
|
38
41
|
|
|
42
|
+
Three packages, and no third-party code:
|
|
43
|
+
[`cdclkit`](https://pypi.org/project/cdclkit/),
|
|
44
|
+
[`dratify`](https://pypi.org/project/dratify/) (the proof checker, zero
|
|
45
|
+
dependencies), and optionally
|
|
46
|
+
[`cdclkit-native`](https://pypi.org/project/cdclkit-native/) (abi3 wheels for
|
|
47
|
+
Linux and macOS).
|
|
48
|
+
|
|
39
49
|
```bash
|
|
40
50
|
python3 -m cdclkit solve instance.cnf --self-check --check-model
|
|
41
51
|
```
|
|
@@ -77,16 +87,19 @@ puzzle, graph colouring, bounded model checking, circuit equivalence.
|
|
|
77
87
|
| `portfolio` | parallel configurations |
|
|
78
88
|
| `pyeq` | **experimental** — bounded equivalence of two Python integer functions |
|
|
79
89
|
|
|
80
|
-
An optional Rust engine (
|
|
81
|
-
|
|
90
|
+
An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-native/))
|
|
91
|
+
is roughly 18x faster
|
|
82
92
|
and **bit-exact** with the Python one: identical conflicts, decisions and
|
|
83
93
|
propagations on every instance. The pure-Python path has zero third-party
|
|
84
94
|
dependencies and is the one that must never break.
|
|
85
95
|
|
|
86
96
|
## Relationship to dratify
|
|
87
97
|
|
|
88
|
-
Proof checking lives in a separate package,
|
|
89
|
-
|
|
98
|
+
Proof checking lives in a separate package,
|
|
99
|
+
[`dratify`](https://pypi.org/project/dratify/)
|
|
100
|
+
([source](https://github.com/carlok/dratify), also a
|
|
101
|
+
[Rust crate](https://crates.io/crates/dratify)), which `cdclkit` depends on.
|
|
102
|
+
That split is deliberate:
|
|
90
103
|
|
|
91
104
|
- You should not have to install a SAT solver to verify a proof someone else
|
|
92
105
|
produced.
|
|
@@ -95,7 +108,9 @@ which `cdclkit` depends on. That split is deliberate:
|
|
|
95
108
|
solver rather than only by its own suite.
|
|
96
109
|
|
|
97
110
|
`dratify` has no dependencies of its own, so installing `cdclkit` pulls in no
|
|
98
|
-
third-party code.
|
|
111
|
+
third-party code. With `[native]`, `cdclkit-native` hands its compiled checker
|
|
112
|
+
to `dratify` through `register_native()`, so proof checking gets the Rust
|
|
113
|
+
implementation too rather than only the solver.
|
|
99
114
|
|
|
100
115
|
## Performance
|
|
101
116
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cdclkit"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -31,6 +31,12 @@ classifiers = [
|
|
|
31
31
|
# test run here as well as by its own suite.
|
|
32
32
|
dependencies = ["dratify>=0.1.1"]
|
|
33
33
|
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
# The Rust accelerator, as abi3 wheels for Linux and macOS. Pinned exactly:
|
|
36
|
+
# the two are bit-exact by construction and a mismatched pair is a divergence
|
|
37
|
+
# nobody would look for. tests/test_packaging.py enforces the pin.
|
|
38
|
+
native = ["cdclkit-native==0.1.2"]
|
|
39
|
+
|
|
34
40
|
[project.scripts]
|
|
35
41
|
cdclkit = "cdclkit.__main__:main"
|
|
36
42
|
|
|
@@ -160,6 +160,85 @@ class TestDefaultsAgree(unittest.TestCase):
|
|
|
160
160
|
self.assertEqual(py.stats.propagations, rs.propagations)
|
|
161
161
|
|
|
162
162
|
|
|
163
|
+
@requires_native
|
|
164
|
+
class TestRandomBranchingAgrees(unittest.TestCase):
|
|
165
|
+
"""`rnd_freq` and `rnd_seed` must reach the native engine and match.
|
|
166
|
+
|
|
167
|
+
These two knobs had no Rust counterpart at all: the native side accepted
|
|
168
|
+
the rest of the configuration and silently dropped these, so a Python run
|
|
169
|
+
at rnd_freq=0.02 took 4,987 conflicts where the native one took 3,171.
|
|
170
|
+
|
|
171
|
+
That was not a cosmetic gap. `portfolio.py` builds worker diversity from
|
|
172
|
+
exactly these two fields, and sets a per-worker seed specifically "so
|
|
173
|
+
duplicated recipes still diverge" -- which on the native path they did not,
|
|
174
|
+
because every worker got the same search. Duplicate recipes became
|
|
175
|
+
bit-identical duplicate workers doing the same work in parallel.
|
|
176
|
+
|
|
177
|
+
The existing bit-exactness tests could not have caught this: none of them
|
|
178
|
+
set either knob.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
def _native(self, f, rnd_freq, rnd_seed):
|
|
182
|
+
n = native.require()
|
|
183
|
+
d = Config()
|
|
184
|
+
rs = n.Solver(
|
|
185
|
+
f.nvars, restart=d.restart, ccmin=d.ccmin,
|
|
186
|
+
phase_saving=d.phase_saving, init_phase=d.init_phase,
|
|
187
|
+
target_phase=d.target_phase, target_reset=d.target_reset,
|
|
188
|
+
walk_flips=d.walk_flips, walk_interval=d.walk_interval,
|
|
189
|
+
walk_patience=d.walk_patience,
|
|
190
|
+
walk_min_conflicts=d.walk_min_conflicts,
|
|
191
|
+
var_decay=d.var_decay, var_decay_max=d.var_decay_max,
|
|
192
|
+
cla_decay=d.cla_decay, luby_base=float(d.luby_base),
|
|
193
|
+
first_reduce=d.first_reduce, reduce_inc=d.reduce_inc,
|
|
194
|
+
glue_keep=d.glue_keep, block_restart=d.block_restart,
|
|
195
|
+
rnd_freq=rnd_freq, rnd_seed=rnd_seed)
|
|
196
|
+
for c in f.clauses:
|
|
197
|
+
rs.add_clause(list(c))
|
|
198
|
+
rs.solve(None)
|
|
199
|
+
return rs.conflicts, rs.decisions, rs.propagations
|
|
200
|
+
|
|
201
|
+
def _python(self, f, rnd_freq, rnd_seed):
|
|
202
|
+
from cdclkit.solver import Solver as PySolver
|
|
203
|
+
|
|
204
|
+
cfg = Config()
|
|
205
|
+
cfg.rnd_freq = rnd_freq
|
|
206
|
+
cfg.rnd_seed = rnd_seed
|
|
207
|
+
py = PySolver(f.nvars, config=cfg)
|
|
208
|
+
py.add_cnf(f)
|
|
209
|
+
py.solve()
|
|
210
|
+
return py.stats.conflicts, py.stats.decisions, py.stats.propagations
|
|
211
|
+
|
|
212
|
+
def test_engines_agree_across_frequencies_and_seeds(self):
|
|
213
|
+
f = php(6)
|
|
214
|
+
for freq, seed in [(0.0, 91648253), (0.02, 91648253), (0.02, 12345),
|
|
215
|
+
(0.10, 7), (0.05, 999983)]:
|
|
216
|
+
with self.subTest(rnd_freq=freq, rnd_seed=seed):
|
|
217
|
+
self.assertEqual(
|
|
218
|
+
self._python(f, freq, seed), self._native(f, freq, seed),
|
|
219
|
+
f"engines diverge at rnd_freq={freq}, rnd_seed={seed}")
|
|
220
|
+
|
|
221
|
+
def test_a_zero_frequency_does_not_touch_the_random_stream(self):
|
|
222
|
+
"""The short-circuit is load-bearing, not an optimisation.
|
|
223
|
+
|
|
224
|
+
Python tests `rnd_freq > 0.0` before drawing, so the default
|
|
225
|
+
configuration never advances the PRNG. If the native side drew first,
|
|
226
|
+
the walk -- which shares the stream -- would desynchronise and the two
|
|
227
|
+
engines would diverge on instances long enough to reach it.
|
|
228
|
+
"""
|
|
229
|
+
f = php(6)
|
|
230
|
+
self.assertEqual(self._python(f, 0.0, 91648253),
|
|
231
|
+
self._native(f, 0.0, 91648253))
|
|
232
|
+
|
|
233
|
+
def test_the_seed_actually_changes_the_search(self):
|
|
234
|
+
"""A knob that is wired up but inert would pass the tests above."""
|
|
235
|
+
f = php(6)
|
|
236
|
+
runs = {self._native(f, 0.05, seed) for seed in (1, 7, 12345, 999983)}
|
|
237
|
+
self.assertGreater(len(runs), 1,
|
|
238
|
+
"every seed produced an identical search, so the "
|
|
239
|
+
"seed is not reaching the engine")
|
|
240
|
+
|
|
241
|
+
|
|
163
242
|
@requires_native
|
|
164
243
|
class TestTier2Faithfulness(unittest.TestCase):
|
|
165
244
|
"""Bit-exact agreement with the Python solver."""
|
|
@@ -157,6 +157,39 @@ class TestPublicAPISurface(unittest.TestCase):
|
|
|
157
157
|
self.assertNotIn(internal, cdclkit.__all__)
|
|
158
158
|
|
|
159
159
|
|
|
160
|
+
class TestWorkflowsAreWellFormed(unittest.TestCase):
|
|
161
|
+
"""Every top-level line in a workflow must be a known key or a comment.
|
|
162
|
+
|
|
163
|
+
A comment in release.yml lost its leading "# " during an edit. The result
|
|
164
|
+
was still valid YAML -- it simply became a mapping key -- so a
|
|
165
|
+
`yaml.safe_load` check passed it, and GitHub then refused the whole file
|
|
166
|
+
with "this run likely failed because of a workflow file issue". Zero jobs
|
|
167
|
+
ran, and the tag had to be deleted and re-cut.
|
|
168
|
+
|
|
169
|
+
Deliberately does not import yaml: the dependency-free test path is the one
|
|
170
|
+
that must never break, and this failure mode does not need a parser.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
#: https://docs.github.com/actions/reference/workflow-syntax-for-github-actions
|
|
174
|
+
ALLOWED = {"name", "on", "permissions", "env", "defaults", "concurrency",
|
|
175
|
+
"jobs", "run-name"}
|
|
176
|
+
|
|
177
|
+
def test_no_stray_top_level_keys(self):
|
|
178
|
+
workflows = sorted((ROOT / ".github" / "workflows").glob("*.yml"))
|
|
179
|
+
self.assertTrue(workflows, "no workflows found")
|
|
180
|
+
for wf in workflows:
|
|
181
|
+
with self.subTest(workflow=wf.name):
|
|
182
|
+
for n, line in enumerate(wf.read_text().splitlines(), 1):
|
|
183
|
+
if not line or line[0] in " \t#":
|
|
184
|
+
continue
|
|
185
|
+
key = line.split(":", 1)[0].strip()
|
|
186
|
+
self.assertIn(
|
|
187
|
+
key, self.ALLOWED,
|
|
188
|
+
f"{wf.name}:{n} starts a top-level key {key!r} that "
|
|
189
|
+
f"GitHub does not recognise -- most likely a comment "
|
|
190
|
+
f"that lost its '# '")
|
|
191
|
+
|
|
192
|
+
|
|
160
193
|
class TestLicenceConsistency(unittest.TestCase):
|
|
161
194
|
"""The tree is Apache-2.0; every place that states a licence must agree.
|
|
162
195
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dratify>=0.1.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|