Research source · python
verify_wqo_pumping.py
site/public/research-artifacts/scaffold-pumping-certificates/verify_wqo_pumping.py
97 lines. Source is displayed for inspection; it is not executed by this page.
File fingerprint
SHA-256: 4d4c930fdbe054c9ed98524385ee1e40d07969e4b925333b643f5177f329c79b
#!/usr/bin/env python3
"""Finite calibration for the abstract WQO one-sided pumping theorem."""
import itertools
import json
from pathlib import Path
def monotone_maps(size):
return tuple(itertools.combinations_with_replacement(range(size), size))
def run(initial, word, actions):
states = [initial]
state = initial
for letter in word:
state = actions[letter][state]
states.append(state)
return states
def first_increasing_pair(states):
return next(
(i, j)
for j in range(1, len(states))
for i in range(j)
if states[i] <= states[j]
)
def main():
map_count = machine_pairs = accepted_words = pump_checks = 0
for size in range(1, 5):
maps = monotone_maps(size)
map_count += len(maps)
for action_a in maps:
for action_b in maps:
machine_pairs += 1
actions = {"a": action_a, "b": action_b}
for initial in range(size):
for threshold in range(size + 1):
for letters in itertools.product("ab", repeat=size):
word = "".join(letters)
states = run(initial, word, actions)
if states[-1] < threshold:
continue
accepted_words += 1
i, j = first_increasing_pair(states)
x, y, z = word[:i], word[i:j], word[j:]
assert y
for repeats in range(1, 6):
pumped = run(initial, x + y * repeats + z, actions)[-1]
assert pumped >= threshold
pump_checks += 1
# Deletion is not supplied by a one-way comparison: 0 <= 1, y is
# accepted by the upward set {1,2,...}, but the zero-copy word is not.
deletion_actions = {"y": (1, 1)}
assert run(0, "y", deletion_actions)[-1] == 1
assert run(0, "", deletion_actions)[-1] == 0
# Monotonicity is essential: swapping 0 and 1 turns the accepted first
# copy into a rejected second copy despite 0 <= 1 at the first cut.
swap = {"y": (1, 0)}
assert run(0, "y", swap)[-1] == 1
assert run(0, "yy", swap)[-1] == 0
# Upward closure is essential: increment is monotone, but accepting only
# state 1 accepts one copy and rejects two.
increment = {"y": (1, 2, 2)}
assert run(0, "y", increment)[-1] == 1
assert run(0, "yy", increment)[-1] == 2
result = {
"status": "pass",
"scope": "all pairs of monotone actions on finite chains through size four",
"monotone_maps": map_count,
"two_letter_action_pairs": machine_pairs,
"accepted_length_bound_words": accepted_words,
"one_sided_pump_checks": pump_checks,
"deletion_counterexample": {"states": [0, 1], "zero_copy_rejected": True},
"nonmonotone_counterexample": {"states": [0, 1, 0], "second_copy_rejected": True},
"non_upward_acceptance_counterexample": {"states": [0, 1, 2], "second_copy_rejected": True},
"does_not_verify": [
"the infinite WQO recurrence argument",
"a compatible WQO for unrestricted scaffolding automata",
"an effective or elementary pumping-length bound",
"zero-copy pumping from a strict comparison",
],
}
output = json.dumps(result, indent=2) + "\n"
Path(__file__).with_name("wqo-pumping-checker-output.json").write_text(output)
print(output, end="")
if __name__ == "__main__":
main()