Skip to content

PPVM-traits-2 Patch - #219

Merged
JonhasA merged 23 commits into
mainfrom
trait-2/ppvm-traits-2
Oct 1, 2026
Merged

JonhasA merged 23 commits into
mainfrom
trait-2/ppvm-traits-2

Conversation

@JonhasA

@JonhasA JonhasA commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

A patch to move the changes to ppvm-trait from roger's PR #204

Additionally, the following changes were made:

  1. Added arithmetic module for defining traits to numeric types
  2. added gates module for defining traits for Clifford/ channel / measure/ rotation ops
  3. container module now has additional files related to storage or engine configuration
  4. Moved PREFER_MOVED_RKEY outside of coefficient and into storage.rs in containers/. Engine will configure the key rather than having coefficient module be responsible for it.
  5. Added a LossState trait to be associated with word sites rather than having it in PauliBits.
  6. Isolated functionality related to fermionic factors into fermion_factor.rs
  7. Pauli type is used explicitly for rotation operations
  8. Moves container tests beside their implementations and adds regression coverage for batch hash invalidation and Pauli-channel factors.
  9. Moves pauli_error_factors into the optional PauliErrorFactors channel capability, preserving the generic default and numeric specializations.

…em for ppvm. Focused on moving files to more isolated modules to have better appreciation on module responsibility

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

👋 Thanks for opening your first pull request against PPVM!

A quick note on contribution terms: by submitting this PR you
agree that your contribution is licensed under the
Apache License 2.0
and that you accept the
PPVM Contributor License Agreement.
Please skim those before a maintainer reviews — opening this PR
counts as your acceptance.

A few things that will speed up review:

  • Read CONTRIBUTING.md
    for the workflow, build commands, and style notes.
  • Run prek run --all-files locally; CI runs the same checks.
  • Use Conventional Commits
    for commit messages.

We'll get to your PR as soon as we can. Thanks for contributing!

@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-01 22:43 UTC

@david-pl david-pl 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.

Overall a solid first breakdown of the huge PR, but I think we should make some changes here.

Also, on a more general note: while I get that proving things with lean is beneficial, I think this introduces unneeded complexity at points. For example, to fulfill criteria so this is provably a ring we introduce some traits that are sometimes a bit odd, e.g. Halvable.
cc @Roger-luo

Comment thread crates/ppvm-traits-2/src/arithmetic/coefficient.rs Outdated
impl Halvable for f64 {
#[inline]
fn half(&self) -> Self {
*self / 2.0

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.

I'm surprised that this holds up in the exact x.half() + x.half() == x condition.

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.

Actually, there is an edge case here: this doesn't hold for f64::NAN, which is a perfectly valid f64, but x.half() == x if x is NAN.

I'm not saying this bothers me overly much, but as I said I'd also be happy not to go the full formal ring way anyway.

Comment thread crates/ppvm-traits-2/src/containers/batch.rs Outdated
Comment thread crates/ppvm-traits-2/src/containers/batch.rs
Comment thread crates/ppvm-traits-2/src/containers/graded.rs Outdated
Comment thread crates/ppvm-traits-2/src/algebra.rs Outdated
Comment thread crates/ppvm-traits-2/src/fermion_factor.rs Outdated
Comment thread crates/ppvm-traits-2/src/fermion_factor.rs Outdated
Comment thread crates/ppvm-traits-2/src/loss.rs
Comment thread crates/ppvm-traits-2/src/word.rs Outdated
@Roger-luo

Copy link
Copy Markdown
Collaborator

Also, on a more general note: while I get that proving things with lean is beneficial, I think this introduces unneeded complexity at points. For example, to fulfill criteria so this is provably a ring we introduce some traits that are sometimes a bit odd, e.g. Halvable.

For reference, One use case is symbolic expressions. The minimum requirement of a symbolic expression is that it can be divided by half, and it doesn't matter what number that half comes from.

Comment thread crates/ppvm-traits-2/src/gates/channel.rs Outdated
Comment thread crates/ppvm-traits-2/src/gates/clifford.rs
@Roger-luo
Roger-luo requested a review from david-pl September 20, 2026 23:42

@david-pl david-pl 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.

Some minor stuff I still found, and some responses to @Roger-luo here. But it's almost there.

Comment thread crates/ppvm-traits-2/src/gates/channel.rs Outdated

/// Accumulates a borrowed coefficient.
#[inline]
fn add_assign_ref(&mut self, rhs: &Self) {

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.

My point before was to require that trait and then remove this method. It's much more natural to just write *self += rhs and it's also done for the most part (which is why this method was only used once). So, just remove it?

Comment thread crates/ppvm-traits-2/src/containers/batch.rs
Comment thread crates/ppvm-traits-2/src/gates/clifford.rs
Comment thread crates/ppvm-traits-2/src/algebra.rs Outdated
0 => Phase::Pos1,
1 => Phase::PosI,
2 => Phase::Neg1,
_ => Phase::NegI,

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.

This could silently introduce false results if there's a bug somewhere such that k & 3 > 3.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

in #204, Sum<S, P> overrides only cnot_many and inherits the loops for x_many, y_many, and the other _many operators.

@david-pl david-pl 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.

The left-over clones need to go. And I just realized that there's no rng on PauliSum. Why was it added to the trait @Roger-luo ?

Comment thread crates/ppvm-traits-2/src/containers/hash_join.rs Outdated
Comment thread crates/ppvm-traits-2/src/containers/coordinate_list.rs
impl Halvable for f64 {
#[inline]
fn half(&self) -> Self {
*self / 2.0

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.

Actually, there is an edge case here: this doesn't hold for f64::NAN, which is a perfectly valid f64, but x.half() == x if x is NAN.

I'm not saying this bothers me overly much, but as I said I'd also be happy not to go the full formal ring way anyway.

Comment thread crates/ppvm-traits-2/src/gates/channel.rs Outdated
Comment thread crates/ppvm-traits-2/src/gates/channel.rs Outdated
@Roger-luo

Copy link
Copy Markdown
Collaborator

good catch, this is a part I'm not sure - I moved rng out because it's an external state not necessarily (should) be managed by the PauliSum/tableau which is a quantum state, I think it's more natural to have it passed as a argument and let external/global managing it so it's more explicit who is sharing the RNG with what seed.

On the other hand, RNG is technically part of the entire execution state, so it could make sense to let the state object carrying it.

@david-pl

david-pl commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

good catch, this is a part I'm not sure - I moved rng out because it's an external state not necessarily (should) be managed by the PauliSum/tableau which is a quantum state, I think it's more natural to have it passed as a argument and let external/global managing it so it's more explicit who is sharing the RNG with what seed.

I understand, but I don't think this holds if only some of the implementations of the trait actually use an RNG. Making PauliSum submit a dummy rng seems really odd to me and is not worth the abstraction IMO.

Another argument for letting the tableau manage its own rng is that each shot should be seedable and reproducible by a seed. So you'd have to make sure you pass the same rng into the noise as you pass into measurements etc. I think that's easy to forget so having the tableau manage its own rng state centrally is the better approach.

@david-pl

Copy link
Copy Markdown
Collaborator

I made some updates here:

  • Remove PauliErrorFactors, required num::One on Coefficient instead. Note, that Term will still need new AddAssign and MulAssign impls for references. Also, there's a bunch of bugs, see ppvm-sym: Term arithmetic bugs (half, AddAssign<f64>, MulAssign) #232.
  • Consequently, CorrelatedLossChannel did not get the same treatment as PauliErrorFactors.
  • Removed the rng from the traits.

If we are unhappy with any of those decisions, we can undo them.

@JonhasA @Roger-luo this PR would be good to go from my side now. What do you think?

@JonhasA

JonhasA commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

I made some updates here:

  • Remove PauliErrorFactors, required num::One on Coefficient instead. Note, that Term will still need new AddAssign and MulAssign impls for references. Also, there's a bunch of bugs, see ppvm-sym: Term arithmetic bugs (half, AddAssign, MulAssign) #232.
  • Consequently, CorrelatedLossChannel did not get the same treatment as PauliErrorFactors.
  • Removed the rng from the traits.

If we are unhappy with any of those decisions, we can undo them.

@JonhasA @Roger-luo this PR would be good to go from my side now. What do you think?

LGTM! Thank you for the help!

@JonhasA
JonhasA merged commit 7b2e1bc into main Oct 1, 2026
13 checks passed
@JonhasA
JonhasA deleted the trait-2/ppvm-traits-2 branch October 1, 2026 22:43
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.

3 participants