Skip to content

Commit 8bc62ae

Browse files
committed
Merge remote-tracking branch 'origin/2025_final_execution' into presentation-derived-solver
2 parents 7ef410f + 643a6e7 commit 8bc62ae

File tree

11 files changed

+99
-94
lines changed

11 files changed

+99
-94
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ The step from Single Query can be followed with the model validation results whe
257257
Tasks for unsat core validation can be generated by:
258258

259259
```
260-
smtcomp generate-unsatcore-validation-files ../tmp/execution SCRAMBLER_EXECUTABLE UNSAT_CORE_RESULT_DIR/*/*
260+
smtcomp generate-unsatcore-validation-files ../tmp/execution SCRAMBLER_EXECUTABLE UNSAT_CORE_RESULT_DIR
261261
```
262262

263263
---

data/latex-certificates/gen_certificates_ornament.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
\node [circular drop shadow={shadow scale=1.05},
137137
decorate, decoration=zigzag,
138138
fill=blue!20,draw,thick,circle,text width=3.5cm,align=center,xshift=2cm]
139-
{\large\textbf{SMT-COMP\\ 2024}};
139+
{\large\textbf{SMT-COMP\\ 2025}};
140140
\end{tikzpicture}
141141
\end{minipage}
142142

data/latex-certificates/solvers_pretty_name.csv

Lines changed: 0 additions & 20 deletions
This file was deleted.

data/results-uc-2025.json.gz

4.51 MB
Binary file not shown.

smtcomp/certificates.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import smtcomp.defs as defs
1111
import smtcomp.results as results
1212
import smtcomp.generate_website_page as page
13+
import smtcomp.submission as submission
1314

1415
show_experimental = False
1516

@@ -70,11 +71,13 @@ def withtrack(l: list[str], name: str, category: category) -> None:
7071
class overall:
7172

7273
def __init__(self) -> None:
74+
self.best = category()
7375
self.biggest = category()
7476
self.largest = category()
7577

7678
def latex(self) -> str:
7779
l: list[str] = []
80+
withtrack(l, "Best Overall", self.best)
7881
withtrack(l, "Biggest Lead", self.biggest)
7982
withtrack(l, "Largest Contribution", self.largest)
8083
return ", ".join(l)
@@ -83,7 +86,7 @@ def __str__(self) -> str:
8386
return self.latex()
8487

8588
def isNotEmpty(self) -> bool:
86-
return self.biggest.isNotEmpty() and self.largest.isNotEmpty()
89+
return self.best.isNotEmpty() or self.biggest.isNotEmpty() or self.largest.isNotEmpty()
8790

8891

8992
class info:
@@ -132,7 +135,7 @@ def __repr__(self) -> str:
132135
def update(
133136
solvers: defaultdict[str, info],
134137
select: Callable[[info, str], None],
135-
podium: page.PodiumDivision | page.PodiumBiggestLead | page.PodiumLargestContribution,
138+
podium: page.PodiumDivision | page.PodiumBestOverall | page.PodiumBiggestLead | page.PodiumLargestContribution,
136139
) -> None:
137140
if podium.track == defs.Track.SingleQuery:
138141
select(solvers[podium.winner_seq], "sq_seq")
@@ -173,12 +176,10 @@ def add_logic(logics: dict[Tuple[str, defs.Track], bool], list: dict[str, int],
173176
logics[v, track] = True
174177

175178

176-
def parse_pretty_names(solvers: defaultdict[str, info], pretty_names: Path) -> None:
177-
with open(pretty_names, newline="") as input:
178-
input = csv.DictReader(input) # type: ignore
179-
180-
for row in input:
181-
solvers[row["Solver Name"]].members = int(row["Members"]) # type: ignore
179+
def process_submissions(solvers: defaultdict[str, info], submissions: list[defs.Submission]) -> None:
180+
for s in submissions:
181+
if s.competitive:
182+
solvers[s.name].members = len(s.contributors)
182183

183184

184185
def parse_experimental_division(solvers: Any, experimental_division: Path) -> dict[str, bool]:
@@ -192,11 +193,14 @@ def parse_experimental_division(solvers: Any, experimental_division: Path) -> di
192193

193194

194195
def generate_certificates(
195-
website_results: Path, input_for_certificates: Path, pretty_names: Path, experimental_division: Path
196+
website_results: Path, input_for_certificates: Path, submission_dir: Path, experimental_division: Path
196197
) -> None:
197198
solvers: defaultdict[str, info] = defaultdict(info)
198199

199-
parse_pretty_names(solvers, pretty_names)
200+
submissions = [submission.read_submission_or_exit(f)
201+
for f in submission_dir.glob("*.json")]
202+
203+
process_submissions(solvers, submissions)
200204
solvers["-"].members = 0
201205

202206
# Remove experimental division
@@ -223,6 +227,8 @@ def generate_certificates(
223227
continue
224228
case page.PodiumCrossDivision():
225229
match result.root:
230+
case page.PodiumBestOverall():
231+
update(solvers, (lambda x, k: x.overall.best.update(k, True)), result.root)
226232
case page.PodiumBiggestLead():
227233
update(solvers, (lambda x, k: x.overall.biggest.update(k, True)), result.root)
228234
case page.PodiumLargestContribution():

smtcomp/defs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,8 +1471,8 @@ class Config:
14711471
cpuCores_test = 2
14721472
cpuCores_parallel = 128
14731473
cpuCores_parallel_test = 8
1474-
unsatcore_validation_timelimit_s = 60 * 5
1475-
unsatcore_validation_memlimit_M = 1024 * 30
1474+
unsatcore_validation_timelimit_s = 60 * 20
1475+
unsatcore_validation_memlimit_M = 1024 * 15
14761476
unsatcore_validation_cpuCores = 4
14771477
min_used_benchmarks = 300
14781478
ratio_of_used_benchmarks = 0.5

smtcomp/generate_website_page.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class PodiumLargestContribution(BaseModel):
232232

233233

234234
class PodiumCrossDivision(RootModel):
235-
root: PodiumLargestContribution | PodiumBiggestLead = Field(..., discriminator="recognition")
235+
root: PodiumBestOverall | PodiumLargestContribution | PodiumBiggestLead = Field(..., discriminator="recognition")
236236

237237

238238
class Podium(RootModel):

smtcomp/main.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,8 @@ def store_results(
239239
on=["file"],
240240
defaults={"logic": -1, "family": "", "name": ""},
241241
)
242-
.join(removed_results, on=["logic", "family", "name"], how="anti")
243-
.sort("file", "solver")
244-
.collect()
242+
# .join(removed_results, on=["logic", "family", "name"], how="anti")
243+
.sort("file", "solver").collect()
245244
)
246245
if len(df) > 0:
247246
results_track = defs.Results(
@@ -1060,10 +1059,9 @@ def keyfunc(
10601059

10611060

10621061
@app.command()
1063-
def generate_unsatcore_validation_files(
1064-
cachedir: Path, scrambler: Path, resultdirs: list[Path], max_workers: int = 8
1065-
) -> None:
1066-
unsat_core_validation.generate_validation_files(cachedir, resultdirs, scrambler)
1062+
def generate_unsatcore_validation_files(cachedir: Path, scrambler: Path, resultdir: Path) -> None:
1063+
1064+
unsat_core_validation.generate_validation_files(cachedir, resultdir, scrambler)
10671065

10681066

10691067
@app.command()
@@ -1134,12 +1132,12 @@ def build_dolmen(data: Path) -> None:
11341132
def generate_certificates(
11351133
website_results: Path = Path("web/content/results"),
11361134
input_for_certificates: Path = Path("data/latex-certificates/input_for_certificates.tex"),
1137-
pretty_names: Path = Path("data/latex-certificates/solvers_pretty_name.csv"),
1135+
submission_dir: Path = Path("submissions"),
11381136
experimental_division: Path = Path("data/latex-certificates/experimental.csv"),
11391137
) -> None:
11401138
"""
11411139
generates the input data for the tex certificate generator.
11421140
"""
11431141
smtcomp.certificates.generate_certificates(
1144-
website_results, input_for_certificates, pretty_names, experimental_division
1142+
website_results, input_for_certificates, submission_dir, experimental_division
11451143
)

smtcomp/results.py

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def convert_run(r: ET.Element) -> Run | None:
124124
parts = r.attrib["name"].split("/")
125125
logic = defs.Logic(parts[-2])
126126
benchmark_yml = parts[-1]
127-
benchmark_file = int(benchmark_yml.split("_", 1)[0])
127+
benchmark_file = smtcomp.scramble_benchmarks.unscramble_yml_basename(benchmark_yml)
128128
cputime_s: Optional[float] = None
129129
memory_B: Optional[int] = None
130130
answer: Optional[defs.Answer] = None
@@ -367,17 +367,17 @@ def parse_mapping(p: Path) -> pl.LazyFrame:
367367
return pl.LazyFrame(
368368
(
369369
(
370-
smtcomp.scramble_benchmarks.unscramble_yml_basename(Path(k).name),
370+
int(file),
371371
sorted(v["core"]),
372372
smtcomp.scramble_benchmarks.unscramble_yml_basename(Path(v["file"]).name),
373373
)
374-
for k, l in d.items()
375-
for v in l
374+
for file, cores in d.items()
375+
for v in cores
376376
),
377377
{
378-
"scramble_id_orig": pl.Int64,
378+
"orig_file": pl.Int64,
379379
"unsat_core": pl.List(pl.Int64),
380-
"scramble_id": pl.Int64,
380+
"file": pl.Int64,
381381
},
382382
)
383383

@@ -402,35 +402,44 @@ def parse_dir(dir: Path, no_cache: bool) -> pl.LazyFrame:
402402
l_parsed = list(track((parse_to_pl(f, no_cache) for f in l), total=len(l)))
403403
results = pl.concat(l_parsed)
404404

405-
ucvr = dir / "../unsat_core_validation_results" / "parsed.feather"
406-
if (dir.name).endswith("unsatcore"):
407-
json = dir / json_mapping_name
408-
if not json.exists():
409-
raise (ValueError(f"No file {json!s} in the directory"))
405+
uc_validation_results = dir / "../unsat_core_validation_results" / "parsed.feather"
406+
407+
json = dir / json_mapping_name
408+
if json.exists():
409+
# add information about the original benchmark to each UC validation run
410410
lf = parse_mapping(json)
411-
defaults = {"unsat_core": [], "scramble_id_orig": -1}
411+
results = add_columns(results.drop("unsat_core"), lf, on=["file"], defaults={"unsat_core": [], "orig_file": -1})
412412

413-
if ucvr.is_file():
414-
vr = pl.read_ipc(ucvr).lazy()
413+
if (dir.name).endswith("unsatcore"):
414+
if uc_validation_results.is_file():
415+
# compute stats of validated and refuted cores
416+
vr = pl.read_ipc(uc_validation_results).lazy()
415417
vr = (
416-
vr.select("answer", "unsat_core", scramble_id="scramble_id_orig")
417-
.group_by("scramble_id", "unsat_core")
418+
vr.select("answer", "unsat_core", file="orig_file")
419+
.group_by("file", "unsat_core")
418420
.agg(
419-
sat=(pl.col("answer") == int(defs.Answer.Sat)).count(),
420-
unsat=(pl.col("answer") == int(defs.Answer.Unsat)).count(),
421+
sat=(pl.col("answer") == int(defs.Answer.Sat)).sum(),
422+
unsat=(pl.col("answer") == int(defs.Answer.Unsat)).sum(),
421423
validation_attempted=True,
422424
)
423425
)
426+
424427
results = add_columns(
425428
results,
426429
vr,
427-
on=["scramble_id", "unsat_core"],
430+
on=["file", "unsat_core"],
428431
defaults={"sat": 0, "unsat": 0, "validation_attempted": False},
429432
)
433+
434+
# change answer according to the validity of the core
430435
results = results.with_columns(
431-
answer=pl.when((pl.col("answer") == int(defs.Answer.Unsat)) & (pl.col("sat") > pl.col("unsat")))
432-
.then(int(defs.Answer.UnsatCoreInvalidated))
433-
.otherwise("answer")
436+
answer=pl.when((pl.col("answer") == int(defs.Answer.Unsat)) & (pl.col("sat") >= pl.col("unsat")))
437+
.then(
438+
pl.when(pl.col("sat") == 0)
439+
.then(int(defs.Answer.Unknown)) # sat == unsat == 0
440+
.otherwise(int(defs.Answer.UnsatCoreInvalidated))
441+
)
442+
.otherwise("answer") # sat < unsat
434443
).drop("sat", "unsat", "unsat_core")
435444
else:
436445
results = results.with_columns(validation_attempted=False)

smtcomp/scramble_benchmarks.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,18 @@ def scramble_basename(id: int, suffix: str = "smt2") -> str:
2121

2222

2323
def unscramble_yml_basename(basename: str) -> int:
24-
# We are unscrabling scrambled%i.yml
25-
assert basename[0:9] == "scrambled"
26-
# assert basename[-4:] == ".yml"
24+
# We are unscrabling {i}.yml or scrambled{i}_{core}.smt2
2725
if basename[-4:] == ".yml":
28-
return int(basename[9:-4])
26+
parts = basename.split("_")
27+
file_id = parts[0]
28+
return int(file_id)
2929
else:
30+
assert basename[0:9] == "scrambled"
3031
assert basename[-5:] == ".smt2"
3132
s = basename[9:-5]
32-
l = list(map(int, s.split("_")))
33-
i = l[0]
34-
if len(l) > 1:
35-
i += l[1] * 10_000_000 # Hack for unsat_core_verification
36-
return i
33+
file_id, core = list(map(int, s.split("_")))
34+
file_id += core * 10_000_000 # Hack for unsat_core_verification
35+
return file_id
3736

3837

3938
def benchmark_files_dir(cachedir: Path, track: defs.Track) -> Path:

0 commit comments

Comments
 (0)