Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

`update_initial_operator` keeps old identity term even when the new operator doesn't have it

Open
#392 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
cpp, python
Domain
backend

Research direction

Start with MajoranaPropagator.update_initial_operator and the identity core_term handling mentioned in detail/monomial_propagator/MonomialPropagator.inl around line 150. Run the reproduction in the issue in both Schrödinger and Heisenberg modes, then check the relevant tests for omitted operator terms. Done means updating without an identity term produces the expected value of 1.0 in both modes.

Written by the indexing model from the issue text.

Description

bug
Bug description

Summary: MajoranaPropagator.update_initial_operator drops every term of the old initial operator that is missing from new_operator, except the identity term (). Any constant in the original operator then leaks into every later expectation_value(). This happens in both the Schrödinger and the Heisenberg picture.

Likely cause: the constructor stores the identity separately as core_term ("Store the core term separately…" in detail/monomial_propagator/MonomialPropagator.inl, around line 150). The update path appears to replace only the non-identity terms and never resets core_term.

Workaround: always include (): 0.0 (or the intended constant) in new_operator.

Suggested fix: reset the identity coefficient to new_operator.terms.get((), 0) on update, consistent with how other omitted terms are treated. Alternatively, document the asymmetry in the update_initial_operator docstring.

Steps to reproduce
from monoprop import MajoranaOperator, MajoranaPropagator
from monoprop.circuit import Circuit

n, hf = 2, [0]  # 2 modes, mode 0 occupied, so <i g0 g1> = +1
for sc in (4, None):  # Schrodinger, Heisenberg
    mp = MajoranaPropagator(MajoranaOperator({(): 5.0, (0, 1): 1j}, n), hf,
                            cutoff=4, schrodinger_cutoff=sc)
    mp.propagate(Circuit([], n))
    mp.update_initial_operator(MajoranaOperator({(0, 1): 1j}, n))
    print(mp.expectation_value())  # prints 6.0, expected 1.0
Expected behavior

Expected a full update of the initial observable, but instead you get your new observable + identity, and this has an effect on e.g expectation values, as show below.

Initial operator Update to Expected Actual
{(): 5, (0,1): 1j} {(0,1): 1j} 1.0 6.0 (both pictures)
{(): 5, (0,1): 1j} {(): 0, (0,1): 1j} 1.0 1.0 (removing identity manually)
{(0,1): 1j, (2,3): 1j} {(0,1): 1j} 1.0 1.0 (since non-identity terms are correctly dropped)

So omitted terms are dropped, but the identity is treated differently.

Operating system

macOS (Apple Silicon)

monoprop version

0.9.2a1

Python version

3.11.15

Additional context

No response

Dominant language
C++
Stars
52
Forks
2
Avg merge
17h 30m
Merged PRs (30d)
29

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Algorithmiq/monoprop

All issues in Algorithmiq/monoprop

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.