Skip to content

engine/generators: Add RecordGenerator abstraction - #368

Merged
apaolillo merged 2 commits into
mainfrom
generator
Sep 2, 2026
Merged

engine/generators: Add RecordGenerator abstraction#368
apaolillo merged 2 commits into
mainfrom
generator

Conversation

@apaolillo

Copy link
Copy Markdown
Collaborator

Second slice of the new-API refactor: parameter-space exploration becomes a first-class, pluggable value instead of being hardwired into the campaign classes. A RecordGenerator protocol (structural typing, like the core Benchmark and Executor protocols) produces the records a campaign explores; each records() call returns a fresh iteration.

Three finite generators land: CartesianGenerator wraps the existing cartesian_product utility, ListGenerator iterates pre-built records in order, and FilteredGenerator composes with any generator to keep only records passing a predicate, so a filtered cartesian campaign still declares what it explores instead of degrading to a flat record list.

Campaigns now build their records through a generator: CampaignTemplate accepts exactly one of variables or record_generator (falling back to a ListGenerator around the former), CampaignCartesianProduct declares a CartesianGenerator (wrapped in FilteredGenerator when filter_func is set), and every campaign exposes a record_generator property for the engine and later slices to read. Records are still materialized once at campaign construction, exactly where list(variables) happened before, so duration estimation keeps working and behavior is preserved; lazy, engine-driven generation (required for adaptive exploration, where the record stream depends on previous results) comes with a later phase.

The generators are re-exported from the top-level package as public API. Tests cover the generator implementations, the campaign wiring (including record equality with the legacy cartesian path), and an end-to-end run of a campaign built from an explicit generator.

Second slice of the new-API refactor: parameter-space exploration
becomes a first-class, pluggable value instead of being hardwired into
the campaign classes. A RecordGenerator protocol (structural typing,
like the core Benchmark and Executor protocols) produces the records a
campaign explores; each records() call returns a fresh iteration.

Three finite generators land: CartesianGenerator wraps the existing
cartesian_product utility, ListGenerator iterates pre-built records in
order, and FilteredGenerator composes with any generator to keep only
records passing a predicate, so a filtered cartesian campaign still
declares what it explores instead of degrading to a flat record list.

Campaigns now build their records through a generator: CampaignTemplate
accepts exactly one of variables or record_generator (falling back to a
ListGenerator around the former), CampaignCartesianProduct declares a
CartesianGenerator (wrapped in FilteredGenerator when filter_func is
set), and every campaign exposes a record_generator property for the
engine and later slices to read. Records are still materialized once at
campaign construction, exactly where list(variables) happened before,
so duration estimation keeps working and behavior is preserved; lazy,
engine-driven generation (required for adaptive exploration, where the
record stream depends on previous results) comes with a later phase.

The generators are re-exported from the top-level package as public
API. Tests cover the generator implementations, the campaign wiring
(including record equality with the legacy cartesian path), and an
end-to-end run of a campaign built from an explicit generator.

Signed-off-by: Antonio Paolillo <apaolill@gmail.com>
@apaolillo apaolillo self-assigned this Sep 1, 2026
Signed-off-by: Antonio Paolillo <apaolill@gmail.com>

@matsvanmolle matsvanmolle left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@apaolillo
apaolillo merged commit 97c8939 into main Sep 2, 2026
2 checks passed
@apaolillo
apaolillo deleted the generator branch September 2, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants