Skip to content

Merge pyAmpliCol into MadGraph7 - #301

Open
theoheimel wants to merge 1100 commits into
mainfrom
merge-pyamplicol
Open

theoheimel wants to merge 1100 commits into
mainfrom
merge-pyamplicol

Conversation

@theoheimel

@theoheimel theoheimel commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Brings pyAmpliCol, the generator behind the [amplicol] matrix-element backend, into MadGraph7 as pyamplicol/, the same way madspace was merged. It keeps its history and gets CI, documentation, a local installer and PyPI releases in lockstep with MadGraph7.

This PR covers the infrastructure only. The [amplicol] backend (feat-madspace-amplicol) can be rebased onto it afterwards and use the new bootstrap helpers.

!!! Important information on releases, please read !!!

The amplicol version is now coupled to the MG7 version and a MG7 release triggers a PyAmplicol release

  • we should consider another release before merging this
  • To be able to release after the merge, @ValentinHirschi needs to add a trusted publisher for the pyamplicol project: repository MadGraphTeam/MadGraph7, workflow release.yml, environment pypi
  • because of the aligned versions, 1.0.0 and 1.0.1 are "burned" as pyamplicol releases already exist on PyPI. So I guess the MG7 release will be 1.1.0

History import

  • The history of MadGraphTeam/pyamplicol main (up to 9404776f) is merged with every commit kept: 1085 commits, after git filter-repo pruned the 4 that became empty.
  • Before the merge, the history was rewritten with git filter-repo:
    • the prepared-model packs (*.pyamplicol-model, 74 commits of 7–18 MB) were removed;
    • the PDFs were removed (they stay reachable through the upstream repository);
    • every path was moved under pyamplicol/.
  • The packed history drops from about 89 MB to about 18 MB.
  • The import is scripted in .github/scripts/import_pyamplicol.sh. The filter is deterministic, so later upstream commits can be imported by running it again and merging pyamplicol-import; commits that were already imported keep their SHAs.
  • The upstream repository is unchanged. The pyamplicol remote has its push URL disabled.

Prepared models

  • Git no longer tracks the packs or their metadata. Each MadGraph7 release attaches one archive, pyamplicol-prepared-models.tar.gz (about 2.4 MB). It holds the metadata plus each distinct bundle once; the x86_64 and aarch64 packs are identical.
  • pyamplicol/tools/release/prepared_models_archive.py has four commands:
    • fetch downloads the archive from the matching release, or else the latest one;
    • unpack writes the files from a local archive;
    • pack creates the archive;
    • regenerate builds a bootstrap wheel and produces the packs on the current host.
  • The installer and CI check the fetched packs against the source tree with the backend's own validation, and regenerate them when they are stale.
  • Today's packs are already attached to v0.2.1.

Build changes for the monorepo

  • Build backend
    • pyamplicol/ is treated as a Git subdirectory for the file inventory, the clean-revision check (only pyamplicol/ counts) and the release store.
    • The untracked packs are included in the build inputs.
    • A symlink to a file shared with the rest of MadGraph7 is copied by content (prepared for umami.h, see the follow-ups).
    • An opt-in local build mode for the installer allows a dirty tree or a release tarball, and uses a persistent build directory and a job count.
    • RUSTUP_HOME passes through to the build, and the build finds maturin when it is installed with pip install --target.
  • Version: pyamplicol now follows MadGraph7's VERSION, currently 0.2.1. tools/release/sync_version.py writes it into Cargo and the release lock, and bin/create_release.py --check-only fails when they are out of sync.
  • Source hash: pyamplicol/source_hash.py computes it; wheel builds record it as pyamplicol._source_hash.

Installation

  • pyamplicol/install.py works like madspace/install.py:
    • --bin installs the PyPI wheel of this MadGraph version and is offered in release tarballs.
    • --source builds into pyamplicol/install and leaves the active environment alone.
    • Other options: -y, -j N, --system, --clean, --build-models.
  • If rustup is missing, the installer puts it in pyamplicol/build/rust; ~/.cargo and ~/.rustup are left alone.
  • Rebuilds reuse the Cargo build tree.
  • After installing, it checks that Symbolica accepts pyAmpliCol's package-scoped library key (see below).
  • The MadGraph prompt gets an install pyamplicol command with help and tab completion. The madspace help and completion also gain the -j, --system, --clean and --docs options they were missing.
  • The bootstrap helpers in mg7/bootstrap.py, for the backend to use:
    • ensure_pyamplicol puts the install first on sys.path, ahead of the MadGraph root, where pyamplicol/ is the source directory.
    • check_pyamplicol_source_hash.
    • check_pyamplicol_license.
  • madspace/install.py now ignores the pyamplicol wheels listed in input/.release.

Symbolica library key

pyamplicol/__init__.py registers an OEM key that is scoped to the package name pyamplicol. The checks run without SYMBOLICA_LICENSE and confirm that the imported package is the installed one:

  • the installer runs the check after every install;
  • the CI installer job runs it from the MadGraph root, the way the worker sees it;
  • the release smoke test runs it through install.py --bin.

CI also warns 90 days before the key expires, which is on 2028-01-01.

CI

  • pyamplicol.yml ports the upstream tests.yml and release-artifacts.yml; every job runs inside pyamplicol/.
    • A changes job skips the heavy jobs when nothing pyamplicol depends on has changed. It is a job rather than a paths: filter, so every commit still has a green run for the release gate.
    • An installer job builds pyamplicol through install.py and checks the library key.
  • pyamplicol-eager-portability.yml ports the check that packs produced on one architecture work on the others.
  • New actions:
    • pyamplicol_prepared_models: fetch and validate, or else regenerate;
    • build_pyamplicol / install_pyamplicol: like the madspace pair.
  • release.yml:
    • builds and validates the pyamplicol sdist and the three abi3 wheels;
    • publishes them in publish_pypi_pyamplicol, which reuses the pypi environment;
    • lists the wheels in input/.release;
    • attaches the prepared-model archive to the release;
    • adds pyamplicol.yml to the green-CI gate.
  • unittest.yml runs the new test_pyamplicol_install.
  • The upstream workflows under pyamplicol/.github would never run in this repository, so they are removed, along with the test that pinned their contents. The remaining workflow tests now read the MadGraph7 workflows.

Documentation

  • "pyAmpliCol" is a new section of the MadGraph7 docs. The pages stay in pyamplicol/docs, because pyamplicol's tests and sdist use them, and are copied into the Sphinx tree at build time.
  • MyST renders the Markdown (myst-parser==5.0.0). Toctrees in the parent pages replace the Jekyll hierarchy.
  • The installation page describes the MadGraph7 installer, and the packaging and release pages describe the archive and the release process.
  • The build gives no warnings for the pyamplicol pages.

Verification

  • python pyamplicol/install.py --source -y -j 8 builds into pyamplicol/install. An incremental rebuild takes about 50 s. The licence check passes, and the installed source hash matches.
  • --build-models regenerates the packs locally (bootstrap wheel, produce, build) in 1 min 45 s, and they pass the backend validation.
  • A source install from a git archive snapshot, the way a release tarball builds it, also works: a cold build took 7 min 48 s, the packs were fetched from v0.2.1, the licence check passed, and the installed source hash matches.
  • ensure_pyamplicol, check_pyamplicol_license and check_pyamplicol_source_hash pass from the MadGraph root.
  • The release sdist builds from the checkout and passes pyamplicol's own audit. It carries the MadGraph7 commit as its source revision, plus the packs and source_hash.py.
  • pyamplicol tests:
    • the source-contract suite: 359 passed;
    • test_build_backend, packaging, dependency gate, release and examples tests: 399 passed, 9 skipped (just is not installed);
    • ruff check is clean on the CI lint scope.
  • MadGraph tests: test_pyamplicol_install (14), test_madspace_install (28) and test_mg7_launch (91) pass.
  • make -C docs html succeeds.
  • Not run locally: the full native runtime suite (release-runtime), the macOS and manylinux wheel builds, and the release workflow itself. They run in CI: the first on this PR, the wheel builds via workflow_dispatch with full_matrix.

Follow-ups

  • UMAMI header symlink. Replace pyamplicol/src/pyamplicol/assets/api_templates/umami/umami.h with a symlink to madspace/include/madspace/umami.h, as for madmatrix. It cannot be done yet: pyamplicol uses UMAMI 1.2, but this branch's madspace header is 1.0, and 1.2 only exists on feat-madspace-amplicol. The build backend already copies the symlink by content.
  • Rebase feat-madspace-amplicol onto this branch and call ensure_pyamplicol and the checks.
  • Gridpacks: decide whether [amplicol] gridpacks need the pyamplicol runtime.
  • Archive MadGraphTeam/pyamplicol once all development has moved here.

Retain transition input-state order, solve the parent-to-side bijection from state/support/source semantics, and fail closed on absent or physically ambiguous mappings. Share the validation across established and on-the-fly tests.
Project source-only process seeds and emit a compact single-member artifact through the existing generation flow.

Reuse the established Runtime APIs with lazy public physics, process-global coupling policy, a one-time prepared grammar, compact retained selector-family state, and complete clear semantics.

Add exact LC work-census tooling plus focused generation, loading, selector, lifecycle, cache, and correctness coverage.
Batch source-only seeds once per model and authenticate crossed execution state. Load compact process PACBINs through closed capability and path checks. Retain, vectorize, and clear warmed selector state. Make the real LC gate fail closed on materialized lanes, fields, sidecars, and container members.
Add feature-only execution diagnostics and seed-domain reconstruction, bind legacy-null massive sources through prepared mass slots, and strengthen the dual-authority n=4 gate.
theoheimel and others added 24 commits October 15, 2026 19:32
Colour orders that differ only by the labels of final-state legs of equal
mass share one phase-space map, but each order had its own channel, e.g.
34 for p p > j j j instead of 4. A contribution now relabels its
final-state legs onto the first order of its channel; the members keep the
physical labels of their processes.
- Provider ids must be plain identifiers before they reach file names and
  providers.mk; integers written into the generated C are type-checked.
- Indexed metadata paths must stay inside the artifact.
- umami_set_parameter loads the first process using a parameter, so an
  invalid value is rejected by the setter rather than at evaluation.
UMAMI 1.2 interface, colour-accuracy reweight providers, lazy process loading, one channel per phase-space pattern, standard UFO fermion spinor order, and regenerated SM+HEFT prepared packs for the MG7 [amplicol] backend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model-independent UMAMI SDK, MadSpace integration examples, and the MG7 [amplicol] backend changes merged from #6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… members

Multiprocess outputs now record which subprocesses share a matrix element,
up to a leg permutation, a rational factor and charge conjugation, in a
declared process-groups.json payload (role process-groups, outside the
artifact identity).

- Flavour profiles: subprocesses are related by a type-preserving flavour
  relabelling exactly when their per-flavour (initial/final, particle/
  antiparticle) counts agree; the profile order gives the leg mapping that
  PDG sorting alone does not.
- --flavor-blind generates one representative per flavour class (optionally
  including charge conjugation) and records the others as members, with a
  warning when the relabelling is not a symmetry of the allowed vertices.
- --analyze-process-groups numerical and the group-processes subcommand merge
  numerically verified relations: f64, three on-shell points with varied
  non-mass parameters, component-wise rational factors with |num|, den <= 99,
  optionally unit factors only.
- Rusticol routes every non-generated member ID or expression, in any side
  order, to its representative with the composed permutation, the exact
  factor and reversed LC flows for conjugated members, in all SDKs.
- UMAMI exports flavour-blind members through their representative's runtime
  and records the assumption.
- UFO expansion enumerates side multisets and drops candidates violating
  charges conserved by every vertex, which renumbers compiled-model process
  IDs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…example

- Generation logs the flavour-blind outcome (subprocesses, generated
  representatives, routed members, charge-conjugated members, warnings) and
  its summary gains a "process grouping" row and a per-process "group"
  column.
- inspect shows the process-group map: an overview, a member-per-row table
  for small maps and a compact per-representative grid for large ones, with
  coloured roles, conjugation markers, non-unit factors, permutations and
  warning notes; --process and --full-physics describe a member's routing.
  A trivial map prints one line; --json carries the full map.
- New example cards for built-in SM p p > j j j j at QED = 0 with
  --flavor-blind and charge conjugation: generate, inspect, evaluate a routed
  member, and group-processes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bump the package and workspace crate versions and record the 1.0.1 release
notes (process grouping, flavour-blind routing, UFO expansion filter).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both features are implemented and documented in docs/correlators.md and
docs/user/umami-api.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repository moved to github.com/MadGraphTeam/pyamplicol and its
documentation to madgraph.org/pyamplicol. Fixture provenance records keep the
repository they were captured from, and the Cargo workspace metadata is left
for the next native change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
We are merging two separate histories together:
- the MadGraph7 history
- the pyamplicol history, moved into the pyamplicol/ subdirectory
All commits from both sides are preserved.

The pyamplicol source code can be found at
https://github.com/MadGraphTeam/pyamplicol
in the branch "main".
The last commit of the original pyamplicol source code is 9404776fefa73c33feda3ec015682d7746ddef1d.

Prior to this merge, the pyamplicol history was rewritten with git filter-repo
(see .github/scripts/import_pyamplicol.sh):
- prepared-model packs (*.pyamplicol-model) were removed from history; they
  are rebuilt in CI and shipped as a single release archive
- PDFs (performance reports, paper drafts) were removed from history; they
  remain available in the upstream repository
- all paths were moved into pyamplicol/
- empty commits (resulting from the cleanup) were automatically pruned
- build backend: treat pyamplicol/ as a Git subdirectory (inventory,
  clean-revision and release-store checks), copy the shared-header symlink
  by content, and add an opt-in local build (PYAMPLICOL_LOCAL_BUILD) with a
  persistent build directory and job count for the MadGraph7 installer
- prepared-model packs and metadata are no longer tracked; they come from
  one release archive (tools/release/prepared_models_archive.py)
- version follows the MadGraph7 VERSION file (tools/release/sync_version.py),
  checked by bin/create_release.py
- install.py, modelled on madspace/install.py: --bin installs the PyPI wheel
  of this MadGraph version, --source builds into pyamplicol/install without
  touching the active environment, with a project-local rustup when none is
  available, an incremental Cargo tree in pyamplicol/build and -j jobs
- prepared models come from the release archive, or are regenerated locally
  when they are stale for the source tree (prepared_models_archive.py
  regenerate)
- after installing, check that Symbolica accepts the package library key
- source_hash.py; wheel builds record it as pyamplicol._source_hash
- 'install pyamplicol' runs pyamplicol/install.py like 'install madspace',
  with help and completion (also adds the missing madspace options there)
- bootstrap: ensure_pyamplicol, check_pyamplicol_source_hash and
  check_pyamplicol_license for the [amplicol] backend
- madspace/install.py only counts madspace wheels in input/.release
- pyamplicol.yml ports pyamplicol's tests and release-artifact workflows; a
  changes job skips the heavy jobs when nothing pyamplicol depends on changed
- an installer job builds through pyamplicol/install.py and checks that
  Symbolica accepts the library key from the MadGraph root
- actions: pyamplicol_prepared_models (fetch, validate, else regenerate),
  build_pyamplicol and install_pyamplicol
- release.yml builds the pyamplicol sdist and wheels, publishes them through
  the shared pypi environment, records the wheels in input/.release and
  attaches the prepared-model archive to the release
- unittest.yml runs the installer unit tests
The pages stay in pyamplicol/docs (its tests and sdist use them) and are
copied into the Sphinx tree at build time; MyST renders the Markdown, and
toctrees in the parent pages replace the Jekyll hierarchy. The installation
page describes the MadGraph7 installer.
The pyamplicol/.github workflows no longer run inside MadGraph7. The tests
and release-artifact workflows were ported to pyamplicol.yml; the
architecture-transfer check becomes pyamplicol-eager-portability.yml. The
prepared-model regeneration is the pyamplicol_prepared_models action and
the publisher is part of release.yml, so candidate.yml,
release-prepared-models.yml and publish-pypi.yml are dropped, together
with the test that pinned their contents. The remaining workflow tests read
the MadGraph7 workflows.
- README mentions install pyamplicol and pyamplicol's own license
- a pre-commit ruff hook with the lint scope of pyamplicol's CI
- CI warns 90 days before the Symbolica library key expires
- the packaging and release pages describe the release archive and the
  MadGraph7 release process
Wheels built from the sdist record the source hash with it.
As for madspace, release.yml relies on main's run for the tests.
The release backend tags Linux wheels manylinux_2_28, which maturin only
accepts when building in a manylinux container; on a newer host (the CI
runner, most user machines) the local build failed its compliance check.
Local installs now pass pyamplicol.host-wheel=true, as upstream's
dependencies/install_dependencies.py does.

@oliviermattelaer oliviermattelaer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi,

This is literally amazing.

One nit picking details, is that this PR likely include a lot of files that we do not want to be part of the release ...

  • Do we need to have a second models directory with plenty of model not shipped in MG.
  • Do we need to have a full process list (like the all examples directory)
  • Do we want to keep all the .md that help the AI to generate this?
  • Do we want to keep all the latex file (of the paper?)?

@ValentinHirschi

Copy link
Copy Markdown

Hi,

This is literally amazing.

One nit picking details, is that this PR likely include a lot of files that we do not want to be part of the release ...

  • Do we need to have a second models directory with plenty of model not shipped in MG.
  • Do we need to have a full process list (like the all examples directory)
  • Do we want to keep all the .md that help the AI to generate this?
  • Do we want to keep all the latex file (of the paper?)?

Hi, yes it's exciting!

I agree with Theo that a monorepo for MG7 will make development far easier, especially for agentic coding.

On the other hand, I think it's great to still have pyAmpliCol be usable standalone outside of MadGraph (that was one of my important design goal). It can be very useful to other generators, and parton showers for MEC, etc...

I think part of my motivation there is that with MadLoop I felt like it was a mistake that it was so tightly integrated within MadGraph, so that no one understood they could easily use it standalone as well, and thus OpenLoops became the default.

I would like to avoid repeating that scenario here and really keeping pyAmpliCol as independent "tree-level ME provider" to MadGraph, which is now made simple thanks to the much more advanced APIs we can build nowadays thanks to agents.

So for example, it is important that pyamplicol remains a pypi installable wheel that can be used independently of madgraph, with its own CLI, python library, SDKs etc...

So some of the files you mentioned are precisely there for that standalone-requirement reason (i.e. example files, some model files). Some other files (like left-over markdowns, old benchmark PDFS) are indeed stale and I agree that they should be removed.

So moving forward and as far as MadGraph7 release go, I think the way to go about it is to have the release CI workflow trim down pyAmpliCol to what's needed by MG7 alone, and remove the rest (e.g. examples and models); but keep these files in the repo so that the release CI workflow for pyAmpliCol itself can ship them properly as intended when releasting the pyAmpliCol pypi wheels.

This branch has not been deployed

No deployments
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.

5 participants