Skip to content

Commit 90a5cea

Browse files
zondmo271
andauthored
feat(CI): handle multi-part Erdős problems in status check (#2327)
For problems with no single `erdos_{N}` theorem (e.g. multi-part problems with `erdos_{N}.parts.i`, `erdos_{N}_cycles`, etc.), collect all non-variant theorems and report open if any part is open. Co-authored-by: Moritz Firsching <firsching@google.com>
1 parent 4aba381 commit 90a5cea

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

scripts/check_erdos_status.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,12 @@
2828
"ErdosProblems",
2929
)
3030

31-
# Matches the category annotation line immediately before a main theorem.
32-
# Captures the status word ("open" or "solved") and the problem number.
33-
# The main theorem is `erdos_{N}` possibly followed by a suffix like `_statement`,
34-
# but NOT containing a dot (which indicates a variant).
31+
# Matches the category annotation line immediately before any erdos theorem.
32+
# Captures the category, the problem number, and the full theorem name suffix.
33+
# Used to find all theorems for a given problem number.
3534
CATEGORY_THEN_THEOREM = re.compile(
3635
r"@\[category research (open|solved|formally solved[^]]*),.*\]\s*\n"
37-
r"theorem erdos_(\d+)\w*[\s:]",
36+
r"theorem erdos_(\d+)([\w.]*)\s",
3837
re.MULTILINE,
3938
)
4039

@@ -84,8 +83,18 @@ def lean_category(cat):
8483
return "solved"
8584

8685

86+
def is_variant(suffix):
87+
"""Check if a theorem name suffix indicates a variant (not a main part)."""
88+
return ".variants." in suffix
89+
90+
8791
def scan_lean_files():
88-
"""Return dict mapping problem number (str) -> 'open', 'solved', or 'formally solved'."""
92+
"""Return dict mapping problem number (str) -> 'open', 'solved', or 'formally solved'.
93+
94+
For multi-part problems (no single `erdos_{N}` theorem), collects all
95+
non-variant theorems. The problem is 'open' if any part is open,
96+
'formally solved' if all parts are formally solved, and 'solved' otherwise.
97+
"""
8998
result = {}
9099
for fname in os.listdir(ERDOS_DIR):
91100
if not fname.endswith(".lean"):
@@ -96,11 +105,35 @@ def scan_lean_files():
96105
filepath = os.path.join(ERDOS_DIR, fname)
97106
with open(filepath) as f:
98107
content = f.read()
99-
# Find the main theorem's category (first match for this problem number)
108+
109+
# Collect all non-variant theorem categories for this problem number
110+
main_categories = []
111+
has_exact_main = False
112+
exact_main_cat = None
100113
for m in CATEGORY_THEN_THEOREM.finditer(content):
101-
if m.group(2) == file_number:
102-
result[file_number] = lean_category(m.group(1))
103-
break
114+
if m.group(2) != file_number:
115+
continue
116+
suffix = m.group(3) # e.g. "", "_cycles", ".parts.i", ".variants.foo"
117+
cat = lean_category(m.group(1))
118+
if suffix == "" or suffix == ":":
119+
# Exact match: `erdos_{N}` with no suffix
120+
has_exact_main = True
121+
exact_main_cat = cat
122+
elif not is_variant(suffix):
123+
main_categories.append(cat)
124+
125+
if has_exact_main:
126+
# Single main theorem exists — use its category directly
127+
result[file_number] = exact_main_cat
128+
elif main_categories:
129+
# Multi-part problem: open if any part is open
130+
if "open" in main_categories:
131+
result[file_number] = "open"
132+
elif all(c == "formally solved" for c in main_categories):
133+
result[file_number] = "formally solved"
134+
else:
135+
result[file_number] = "solved"
136+
104137
return result
105138

106139

0 commit comments

Comments
 (0)