Skip to content

ppvm-sym: Term arithmetic bugs (half, AddAssign<f64>, MulAssign) #232

Description

@david-pl

Found while looking at Term as a Coefficient for #219. All four reproduce on main (da073eb); tests below fail today.

1. Term::half() ignores self

coeff.rs#L9 returns Term::from_f64(0.5) instead of self / 2. PauliSum projections call v.half() (proj.rs#L16, #L35), so symbolic measurement projections replace the coefficient with the constant 0.5.

Fix: self.clone() * 0.5.

2. AddAssign<f64>: One + const is a no-op

add.rs#L24: the Inner::One arm builds a Sum but never assigns it to self.inner, so sin(x) += 1.0 leaves sin(x) unchanged.

3. MulAssign<Term>: One * Sum is a no-op

mul.rs#L172: new_sum.mul_term(...) result is dropped, self keeps its One value.

4. MulAssign<Term>: Sum * Sum drops negative constants

mul.rs#L114 and #L121 guard with c0 > min_eps instead of c0.abs() > min_eps, so cross terms with a negative constant vanish, e.g. (sin x − 1)(cos x − 1). The guard can simply be removed: Sum::add_term already drops |coeff| < min_eps.

5. (not verified by a test) MulAssign<Prod> drops phase

mul.rs#L64 merges sin/cos powers but never combines phase, which would affect the ComplexCoefficient path.

Reproducing tests
use ppvm_sym::Term;
const X: [f64; 1] = [0.3];
fn v(t: &Term) -> f64 { t.eval(&X).unwrap() }

#[test]
fn half_ignores_self() {
    use ppvm_traits::traits::Coefficient;
    assert!((v(&Term::from_f64(4.0).half()) - 2.0).abs() < 1e-12);
}

#[test]
fn one_plus_const() {
    let mut t = Term::var(0).sin();
    t += 1.0;
    assert!((v(&t) - (X[0].sin() + 1.0)).abs() < 1e-12);
}

#[test]
fn one_times_sum() {
    let mut s = Term::var(0).sin();
    s += Term::var(0).cos();
    let mut t = Term::var(0).sin();
    t *= s;
    assert!((v(&t) - X[0].sin() * (X[0].sin() + X[0].cos())).abs() < 1e-12);
}

#[test]
fn sum_times_sum_negative_const() {
    let mut a = Term::var(0).sin();
    a += Term::from_f64(-1.0);
    let mut b = Term::var(0).cos();
    b += Term::from_f64(-1.0);
    assert!((v(&(a * b)) - (X[0].sin() - 1.0) * (X[0].cos() - 1.0)).abs() < 1e-12);
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions