Benchmarks

Experiments need circuits. aigverse can fetch standard benchmark suites on demand and cache them locally, so a script names a benchmark instead of carrying a downloader and a checked-in copy of the data.

Nothing is bundled with aigverse and nothing is downloaded at import time — the first call that needs a file fetches it.

The EPFL suite

The EPFL combinational benchmark suite is the standard yardstick for logic synthesis: twenty circuits split into ten arithmetic and ten random/control designs.

from aigverse.benchmarks import epfl, epfl_names

print(epfl_names("arithmetic"))
print(epfl_names("random_control"))
('adder', 'bar', 'div', 'hyp', 'log2', 'max', 'multiplier', 'sin', 'sqrt', 'square')
('arbiter', 'cavlc', 'ctrl', 'dec', 'i2c', 'int2float', 'mem_ctrl', 'priority', 'router', 'voter')

Loading one gives a NamedAig, which is an Aig that kept the input and output names from the AIGER symbol table, so the names come along at no cost:

from aigverse.networks import DepthAig

aig = epfl("ctrl")
print(f"{aig.num_pis} inputs, {aig.num_pos} outputs")
print(f"{aig.num_gates} AND gates, {DepthAig(aig).num_levels} levels")
7 inputs, 26 outputs
174 AND gates, 10 levels

Sweeping part of the suite is then a loop:

for name in epfl_names("random_control"):
    design = epfl(name)
    print(
        f"{name:12s} {design.num_gates:6d} gates  {DepthAig(design).num_levels:4d} levels"
    )

Warning

The suite spans four orders of magnitude. ctrl has 174 AND gates; hyp has over 214,000 and is a several-hundred-megabyte proposition once loaded and optimized. Start small.

If only the AIGER file is wanted — to hand to another tool, say — use epfl_path(), which downloads and returns the path without parsing.

Revisions

The benchmark repository is versioned by commit rather than by release. Its circuits don’t usually change. The loader defaults to a pinned commit rather than to master, so that two people running the same code get the same circuits.

That is not only about reproducibility across machines. A moving default would not even be self-consistent: whoever already had a warm cache would keep the old circuit forever, while a newcomer downloaded the new one, and the two would silently disagree.

Ask for something else when you want it:

aig = epfl("adder", revision="master")  # whatever is current
aig = epfl("adder", revision="9e5d0ec")  # some other commit

Each revision is cached separately, so switching between them does not re-download anything you already have. The pin itself is kept current by Renovate.

Where downloads are cached

By default, benchmarks land in a per-user cache directory — ~/.cache/aigverse/benchmarks on Linux, ~/Library/Caches/aigverse/benchmarks on macOS, and %LOCALAPPDATA% on Windows. Notably not the working directory, so a sweep run inside a repository checkout does not scatter circuits through it.

Override it in whichever way suits:

from aigverse.benchmarks import set_benchmark_cache

set_benchmark_cache("/scratch/benchmarks")  # process-wide
aig = epfl("adder", cache_dir="/tmp/here")  # this call only

or set AIGVERSE_BENCHMARK_CACHE in the environment. The precedence is the per-call cache_dir, then set_benchmark_cache(), then the environment variable, then the platform default.