Skip to content

Add reinterpret for PauliOperators and Tableaux/Stabilizers/etc - #740

Open
arnavk23 wants to merge 11 commits into
QuantumSavory:masterfrom
arnavk23:reinterpret
Open

Add reinterpret for PauliOperators and Tableaux/Stabilizers/etc#740
arnavk23 wants to merge 11 commits into
QuantumSavory:masterfrom
arnavk23:reinterpret

Conversation

@arnavk23

@arnavk23 arnavk23 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Supersedes #620 (closed due to the git merge issues)

Please address only one topic or issue per pull request! Many small PRs are much easier to review and merge than one large PR.

If this is your first submission to this organization and you are not a developer known in the Julia ecosystem, do not use LLMs -- we need to trust you first before we trust the LLM under your control.

If you want to submit an unfinished piece of work in order to get comments and discuss, please mark the pull request as a draft and ping the repository maintainer.

Before merging, all changes and new functionality should be marked in the CHANGELOG file, but feel free to just leave your CHANGELOG notes in the PR description, to avoid merge conflicts with other requests modifying that file. The maintainer will add these CHANGELOG notes for you if you do so.

Before considering your pull request ready for review and merging, make sure that all of the following are completed (please keep the clecklist as part of your PR):

  • The code is properly formatted and commented.
  • Substantial new functionality is documented within the docs.
  • All new functionality is tested.
  • All of the automated tests on github pass.
  • We recently started enforcing formatting checks. If formatting issues are reported in the new code you have written, please correct them. There will be plenty of old code that is flagged as we are slowly transitioning to enforced formatting. Please do not worry about or address older formatting issues -- keep your PR just focused on your planned contribution.

If you are submitting for a bug bounty:

If possible, keep your git history not too wild (rebase and squash commits, keep commits small and semantically separated) so that review is easier.

@arnavk23
arnavk23 marked this pull request as draft June 9, 2026 10:57
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results (Julia v1)

Time benchmarks
master 1330cf1... master / 1330cf1...
circuitsim/compactification/compact 7.09 ± 0.03 ms 6.9 ± 0.018 ms 1.03 ± 0.0051
circuitsim/compactification/no_compact 7.08 ± 0.04 ms 6.92 ± 0.031 ms 1.02 ± 0.0074
circuitsim/mctrajectories/q1001_r1 16.8 ± 0.5 ms 15.6 ± 0.28 ms 1.08 ± 0.038
circuitsim/mctrajectories/q101_r1 0.176 ± 0.012 ms 0.174 ± 0.011 ms 1.01 ± 0.094
circuitsim/mctrajectories_sumtype/q1001_r1 15.3 ± 0.67 ms 13.8 ± 1.2 ms 1.11 ± 0.11
circuitsim/mctrajectories_sumtype/q101_r1 0.123 ± 0.0038 ms 0.121 ± 0.0038 ms 1.02 ± 0.045
circuitsim/mctrajectories_union/q1001_r1 15.4 ± 0.89 ms 13.5 ± 0.22 ms 1.14 ± 0.068
circuitsim/mctrajectories_union/q101_r1 0.121 ± 0.0035 ms 0.12 ± 0.0032 ms 1.02 ± 0.04
circuitsim/pftrajectories/q1001_r1 0.0786 ± 0.037 ms 0.0781 ± 0.035 ms 1.01 ± 0.65
circuitsim/pftrajectories/q1001_r100 0.198 ± 0.013 ms 0.194 ± 0.013 ms 1.02 ± 0.094
circuitsim/pftrajectories/q1001_r10000 1.25 ± 0.012 ms 1.16 ± 0.012 ms 1.08 ± 0.015
circuitsim/pftrajectories/q101_r1 8.05 ± 3.1 μs 7.98 ± 3.1 μs 1.01 ± 0.55
circuitsim/pftrajectories_sumtype/q1001_r1 0.166 ± 0.0017 ms 0.166 ± 0.00098 ms 0.995 ± 0.012
circuitsim/pftrajectories_sumtype/q1001_r100 0.284 ± 0.011 ms 0.28 ± 0.01 ms 1.01 ± 0.053
circuitsim/pftrajectories_sumtype/q1001_r10000 1.33 ± 0.016 ms 1.24 ± 0.015 ms 1.07 ± 0.018
circuitsim/pftrajectories_sumtype/q1001_r10000_fastrow 6.13 ± 0.077 ms 6.1 ± 0.041 ms 1.01 ± 0.014
circuitsim/pftrajectories_sumtype/q101_r1 16.7 ± 0.061 μs 16.7 ± 0.12 μs 0.999 ± 0.0081
circuitsim/pftrajectories_union/q1001_r1 23 ± 0.08 μs 22.7 ± 0.071 μs 1.01 ± 0.0047
circuitsim/pftrajectories_union/q1001_r100 0.142 ± 0.00076 ms 0.136 ± 0.00076 ms 1.05 ± 0.0081
circuitsim/pftrajectories_union/q1001_r10000 1.18 ± 0.012 ms 1.09 ± 0.0096 ms 1.08 ± 0.015
circuitsim/pftrajectories_union/q101_r1 2.38 ± 0.02 μs 2.35 ± 0.02 μs 1.01 ± 0.012
clifford/dense/cnot250_on_dense500_destab 11.2 ± 0.039 ms 11.2 ± 0.056 ms 1.01 ± 0.0061
clifford/dense/cnot250_on_dense500_stab 5.54 ± 0.031 ms 5.61 ± 0.023 ms 0.987 ± 0.0069
clifford/dense/cnot250_on_diag500_destab 1.13 ± 0.0064 ms 1.13 ± 0.0069 ms 0.998 ± 0.0083
clifford/dense/cnot250_on_diag500_stab 0.57 ± 0.011 ms 0.496 ± 0.013 ms 1.15 ± 0.038
clifford/dense/cnot_on_dense500_destab 0.0457 ± 0.00071 ms 0.0446 ± 0.00039 ms 1.02 ± 0.018
clifford/dense/cnot_on_dense500_stab 20.9 ± 0.2 μs 22.9 ± 0.24 μs 0.91 ± 0.013
clifford/dense/cnot_on_diag500_destab 27.8 ± 0.38 μs 26.9 ± 0.64 μs 1.03 ± 0.028
clifford/dense/cnot_on_diag500_stab 13.3 ± 0.31 μs 13.9 ± 0.33 μs 0.963 ± 0.032
clifford/dense/dense500_on_dense500_destab 11.1 ± 0.039 ms 11.2 ± 0.047 ms 0.996 ± 0.0055
clifford/dense/dense500_on_dense500_stab 5.54 ± 0.024 ms 5.67 ± 0.021 ms 0.977 ± 0.0055
clifford/dense/dense500_on_diag500_destab 1.13 ± 0.0046 ms 0.979 ± 0.0062 ms 1.15 ± 0.0087
clifford/dense/dense500_on_diag500_stab 0.57 ± 0.011 ms 0.494 ± 0.012 ms 1.15 ± 0.036
clifford/symbolic/cnot250_on_dense500_destab 1.51 ± 0.013 ms 1.5 ± 0.011 ms 1 ± 0.011
clifford/symbolic/cnot250_on_dense500_stab 0.749 ± 0.0075 ms 0.762 ± 0.0054 ms 0.983 ± 0.012
clifford/symbolic/cnot250_on_diag500_destab 1.23 ± 0.016 ms 1.23 ± 0.015 ms 1 ± 0.018
clifford/symbolic/cnot250_on_diag500_stab 0.622 ± 0.011 ms 0.634 ± 0.0091 ms 0.98 ± 0.022
clifford/symbolic/cnot_on_dense500_destab 4.94 ± 0.071 μs 4.95 ± 0.069 μs 0.998 ± 0.02
clifford/symbolic/cnot_on_dense500_stab 2.6 ± 0.04 μs 2.56 ± 0.05 μs 1.02 ± 0.025
clifford/symbolic/cnot_on_diag500_destab 4.94 ± 0.07 μs 4.89 ± 0.05 μs 1.01 ± 0.018
clifford/symbolic/cnot_on_diag500_stab 2.48 ± 0.03 μs 2.53 ± 0.03 μs 0.981 ± 0.017
ecc/evaluate_decoder/shor_bp_comm 2.11 ± 0.066 ms 2.23 ± 0.074 ms 0.944 ± 0.043
ecc/evaluate_decoder/shor_bp_naivesyn 4.61 ± 0.14 ms 4.93 ± 0.18 ms 0.935 ± 0.045
ecc/evaluate_decoder/shor_bp_shorsyn 5 ± 0.12 ms 5.24 ± 0.13 ms 0.954 ± 0.032
ecc/evaluate_decoder/shor_pybp_comm 22 ± 1 ms 22.5 ± 1.2 ms 0.98 ± 0.068
ecc/evaluate_decoder/shor_pybp_naivesyn 0.0442 ± 0.0021 s 0.0451 ± 0.0023 s 0.979 ± 0.068
ecc/evaluate_decoder/shor_pybp_shorsyn 0.0452 ± 0.002 s 0.0456 ± 0.002 s 0.99 ± 0.062
ecc/evaluate_decoder/shor_pybposd_comm 22.3 ± 0.94 ms 22.2 ± 0.99 ms 1 ± 0.061
ecc/evaluate_decoder/shor_pybposd_naivesyn 0.045 ± 0.0016 s 0.0448 ± 0.0025 s 1 ± 0.066
ecc/evaluate_decoder/shor_pybposd_shorsyn 0.0451 ± 0.0021 s 0.0463 ± 0.0024 s 0.975 ± 0.068
ecc/evaluate_decoder/shor_table_comm 0.299 ± 0.03 ms 0.291 ± 0.025 ms 1.03 ± 0.13
ecc/evaluate_decoder/shor_table_naivesyn 0.982 ± 0.006 ms 0.976 ± 0.0076 ms 1.01 ± 0.01
ecc/evaluate_decoder/shor_table_shorsyn 1.37 ± 0.014 ms 1.36 ± 0.054 ms 1.01 ± 0.042
ecc/evaluate_decoder/toric8_bp_comm 0.764 ± 0.029 s 0.753 ± 0.055 s 1.01 ± 0.083
ecc/evaluate_decoder/toric8_bp_naivesyn 1.48 ± 0.052 s 1.54 ± 0.05 s 0.956 ± 0.046
ecc/evaluate_decoder/toric8_bp_shorsyn 1.51 ± 0.087 s 1.53 ± 0.031 s 0.99 ± 0.061
ecc/evaluate_decoder/toric8_pybp_comm 0.0657 ± 0.0022 s 0.0664 ± 0.0022 s 0.988 ± 0.047
ecc/evaluate_decoder/toric8_pybp_naivesyn 0.137 ± 0.0051 s 0.14 ± 0.0059 s 0.978 ± 0.055
ecc/evaluate_decoder/toric8_pybp_shorsyn 0.144 ± 0.0042 s 0.148 ± 0.0041 s 0.973 ± 0.039
ecc/evaluate_decoder/toric8_pybposd_comm 0.0661 ± 0.0027 s 0.0673 ± 0.0023 s 0.982 ± 0.053
ecc/evaluate_decoder/toric8_pybposd_naivesyn 0.139 ± 0.0061 s 0.142 ± 0.0054 s 0.978 ± 0.057
ecc/evaluate_decoder/toric8_pybposd_shorsyn 0.147 ± 0.004 s 0.152 ± 0.0087 s 0.967 ± 0.061
ecc/evaluate_decoder/toric8_pymatch_comm 3.42 ± 0.046 ms 3.45 ± 0.093 ms 0.994 ± 0.03
ecc/evaluate_decoder/toric8_pymatch_naivesyn 13.4 ± 0.15 ms 13.3 ± 0.37 ms 1.01 ± 0.03
ecc/evaluate_decoder/toric8_pymatch_shorsyn 22.2 ± 1.3 ms 21.9 ± 1.1 ms 1.01 ± 0.078
ecc/evaluate_decoder/toric8_table_comm 3.71 ± 0.038 ms 3.71 ± 0.044 ms 1 ± 0.016
ecc/evaluate_decoder/toric8_table_naivesyn 13.5 ± 0.2 ms 13.3 ± 0.13 ms 1.02 ± 0.018
ecc/evaluate_decoder/toric8_table_shorsyn 21.8 ± 0.14 ms 21.9 ± 0.2 ms 0.995 ± 0.011
pauli/mul/100 0.04 ± 0 μs 0.04 ± 0 μs 1 ± 0
pauli/mul/1000 0.05 ± 0.01 μs 0.05 ± 0.01 μs 1 ± 0.28
pauli/mul/100000 0.851 ± 0.06 μs 0.832 ± 0.1 μs 1.02 ± 0.14
pauli/mul/20000000 0.195 ± 0.015 ms 0.187 ± 0.016 ms 1.04 ± 0.12
stabilizer/canon/cano500 3.21 ± 0.029 ms 3.15 ± 0.039 ms 1.02 ± 0.016
stabilizer/canon/diag_cano500 0.65 ± 0.012 ms 0.65 ± 0.013 ms 1 ± 0.028
stabilizer/canon/diag_gott500 2.55 ± 0.066 ms 2.54 ± 0.039 ms 1.01 ± 0.03
stabilizer/canon/diag_rref500 0.606 ± 0.018 ms 0.605 ± 0.0089 ms 1 ± 0.034
stabilizer/canon/gott500 5.14 ± 0.24 ms 5.14 ± 0.22 ms 1 ± 0.063
stabilizer/canon/md_cano500 1.19 ± 0.017 ms 1.21 ± 0.018 ms 0.976 ± 0.02
stabilizer/canon/md_rref500 1.18 ± 0.019 ms 1.19 ± 0.014 ms 0.987 ± 0.02
stabilizer/canon/rref500 3.19 ± 0.028 ms 3.15 ± 0.029 ms 1.01 ± 0.013
stabilizer/project/destabilizer 16.6 ± 0.28 μs 16.7 ± 0.21 μs 0.992 ± 0.021
stabilizer/project/stabilizer 9.03 ± 0.16 μs 8.88 ± 0.17 μs 1.02 ± 0.027
stabilizer/tensor/diag_pow5_20 2.4 ± 0.18 ms 2.43 ± 1.2 ms 0.99 ± 0.48
stabilizer/tensor/pow5_20 3.14 ± 0.28 μs 3.27 ± 0.28 μs 0.961 ± 0.12
stabilizer/trace/destabilizer 21.3 ± 0.47 μs 22.3 ± 0.43 μs 0.958 ± 0.028
stabilizer/trace/stabilizer 26.4 ± 0.43 μs 23.9 ± 0.45 μs 1.1 ± 0.027
time_to_load 1.54 ± 0.026 s 1.42 ± 0.0097 s 1.08 ± 0.02
Memory benchmarks
master 1330cf1... master / 1330cf1...
circuitsim/compactification/compact 0 allocs: 0 B 0 allocs: 0 B
circuitsim/compactification/no_compact 6 k allocs: 0.275 MB 6 k allocs: 0.275 MB 1
circuitsim/mctrajectories/q1001_r1 18 k allocs: 0.489 MB 18 k allocs: 0.489 MB 1
circuitsim/mctrajectories/q101_r1 1.82 k allocs: 0.0493 MB 1.82 k allocs: 0.0493 MB 1
circuitsim/mctrajectories_sumtype/q1001_r1 9 allocs: 0.484 kB 9 allocs: 0.484 kB 1
circuitsim/mctrajectories_sumtype/q101_r1 8 allocs: 0.25 kB 8 allocs: 0.25 kB 1
circuitsim/mctrajectories_union/q1001_r1 9 allocs: 0.484 kB 9 allocs: 0.484 kB 1
circuitsim/mctrajectories_union/q101_r1 8 allocs: 0.25 kB 8 allocs: 0.25 kB 1
circuitsim/pftrajectories/q1001_r1 2 k allocs: 0.0916 MB 2 k allocs: 0.0916 MB 1
circuitsim/pftrajectories/q1001_r100 2 k allocs: 0.0916 MB 2 k allocs: 0.0916 MB 1
circuitsim/pftrajectories/q1001_r10000 2 k allocs: 0.0916 MB 2 k allocs: 0.0916 MB 1
circuitsim/pftrajectories/q101_r1 0.201 k allocs: 9.42 kB 0.201 k allocs: 9.42 kB 1
circuitsim/pftrajectories_sumtype/q1001_r1 0 allocs: 0 B 0 allocs: 0 B
circuitsim/pftrajectories_sumtype/q1001_r100 0 allocs: 0 B 0 allocs: 0 B
circuitsim/pftrajectories_sumtype/q1001_r10000 0 allocs: 0 B 0 allocs: 0 B
circuitsim/pftrajectories_sumtype/q1001_r10000_fastrow 0 allocs: 0 B 0 allocs: 0 B
circuitsim/pftrajectories_sumtype/q101_r1 0 allocs: 0 B 0 allocs: 0 B
circuitsim/pftrajectories_union/q1001_r1 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
circuitsim/pftrajectories_union/q1001_r100 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
circuitsim/pftrajectories_union/q1001_r10000 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
circuitsim/pftrajectories_union/q101_r1 2 allocs: 0.0938 kB 2 allocs: 0.0938 kB 1
clifford/dense/cnot250_on_dense500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/cnot250_on_dense500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/cnot250_on_diag500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/cnot250_on_diag500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/cnot_on_dense500_destab 3 allocs: 0.0938 kB 3 allocs: 0.0938 kB 1
clifford/dense/cnot_on_dense500_stab 3 allocs: 0.0938 kB 3 allocs: 0.0938 kB 1
clifford/dense/cnot_on_diag500_destab 3 allocs: 0.0938 kB 3 allocs: 0.0938 kB 1
clifford/dense/cnot_on_diag500_stab 3 allocs: 0.0938 kB 3 allocs: 0.0938 kB 1
clifford/dense/dense500_on_dense500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/dense500_on_dense500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/dense500_on_diag500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/dense/dense500_on_diag500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot250_on_dense500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot250_on_dense500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot250_on_diag500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot250_on_diag500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot_on_dense500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot_on_dense500_stab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot_on_diag500_destab 0 allocs: 0 B 0 allocs: 0 B
clifford/symbolic/cnot_on_diag500_stab 0 allocs: 0 B 0 allocs: 0 B
ecc/evaluate_decoder/shor_bp_comm 0.0395 M allocs: 1.6 MB 0.0395 M allocs: 1.6 MB 1
ecc/evaluate_decoder/shor_bp_naivesyn 0.0749 M allocs: 3.15 MB 0.0747 M allocs: 3.15 MB 1
ecc/evaluate_decoder/shor_bp_shorsyn 0.0757 M allocs: 3.22 MB 0.0747 M allocs: 3.19 MB 1.01
ecc/evaluate_decoder/shor_pybp_comm 0.0935 M allocs: 3.29 MB 0.0935 M allocs: 3.29 MB 1
ecc/evaluate_decoder/shor_pybp_naivesyn 0.182 M allocs: 6.49 MB 0.182 M allocs: 6.49 MB 1
ecc/evaluate_decoder/shor_pybp_shorsyn 0.182 M allocs: 6.55 MB 0.182 M allocs: 6.55 MB 1
ecc/evaluate_decoder/shor_pybposd_comm 0.0935 M allocs: 3.29 MB 0.0935 M allocs: 3.29 MB 1
ecc/evaluate_decoder/shor_pybposd_naivesyn 0.182 M allocs: 6.49 MB 0.182 M allocs: 6.49 MB 1
ecc/evaluate_decoder/shor_pybposd_shorsyn 0.182 M allocs: 6.55 MB 0.182 M allocs: 6.55 MB 1
ecc/evaluate_decoder/shor_table_comm 3.98 k allocs: 0.17 MB 3.98 k allocs: 0.17 MB 1
ecc/evaluate_decoder/shor_table_naivesyn 2.8 k allocs: 0.185 MB 2.8 k allocs: 0.185 MB 1
ecc/evaluate_decoder/shor_table_shorsyn 3.28 k allocs: 0.247 MB 3.28 k allocs: 0.247 MB 1
ecc/evaluate_decoder/toric8_bp_comm 1.01 M allocs: 0.166 GB 1.02 M allocs: 0.168 GB 0.99
ecc/evaluate_decoder/toric8_bp_naivesyn 2.07 M allocs: 0.339 GB 2.12 M allocs: 0.347 GB 0.977
ecc/evaluate_decoder/toric8_bp_shorsyn 2.03 M allocs: 0.331 GB 2.1 M allocs: 0.342 GB 0.968
ecc/evaluate_decoder/toric8_pybp_comm 0.103 M allocs: 4.18 MB 0.103 M allocs: 4.18 MB 1
ecc/evaluate_decoder/toric8_pybp_naivesyn 0.218 M allocs: 9.04 MB 0.218 M allocs: 9.04 MB 1
ecc/evaluate_decoder/toric8_pybp_shorsyn 0.233 M allocs: 10.7 MB 0.233 M allocs: 10.7 MB 1
ecc/evaluate_decoder/toric8_pybposd_comm 0.103 M allocs: 4.18 MB 0.103 M allocs: 4.18 MB 1
ecc/evaluate_decoder/toric8_pybposd_naivesyn 0.218 M allocs: 9.04 MB 0.218 M allocs: 9.04 MB 1
ecc/evaluate_decoder/toric8_pybposd_shorsyn 0.233 M allocs: 10.7 MB 0.233 M allocs: 10.7 MB 1
ecc/evaluate_decoder/toric8_pymatch_comm 14 k allocs: 1.05 MB 14 k allocs: 1.05 MB 1
ecc/evaluate_decoder/toric8_pymatch_naivesyn 0.0389 M allocs: 2.71 MB 0.0389 M allocs: 2.71 MB 1
ecc/evaluate_decoder/toric8_pymatch_shorsyn 0.054 M allocs: 4.41 MB 0.054 M allocs: 4.41 MB 1
ecc/evaluate_decoder/toric8_table_comm 13.9 k allocs: 0.835 MB 13.9 k allocs: 0.835 MB 1
ecc/evaluate_decoder/toric8_table_naivesyn 0.0388 M allocs: 2.28 MB 0.0388 M allocs: 2.28 MB 1
ecc/evaluate_decoder/toric8_table_shorsyn 0.0538 M allocs: 3.98 MB 0.0538 M allocs: 3.98 MB 1
pauli/mul/100 0 allocs: 0 B 0 allocs: 0 B
pauli/mul/1000 0 allocs: 0 B 0 allocs: 0 B
pauli/mul/100000 0 allocs: 0 B 0 allocs: 0 B
pauli/mul/20000000 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/cano500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/diag_cano500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/diag_gott500 14.5 k allocs: 0.853 MB 14.5 k allocs: 0.853 MB 1
stabilizer/canon/diag_rref500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/gott500 14.5 k allocs: 0.854 MB 14.5 k allocs: 0.854 MB 1
stabilizer/canon/md_cano500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/md_rref500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/canon/rref500 0 allocs: 0 B 0 allocs: 0 B
stabilizer/project/destabilizer 5 allocs: 0.281 kB 5 allocs: 0.281 kB 1
stabilizer/project/stabilizer 2 allocs: 0.0781 kB 2 allocs: 0.0781 kB 1
stabilizer/tensor/diag_pow5_20 0.032 k allocs: 24 MB 0.032 k allocs: 24 MB 1
stabilizer/tensor/pow5_20 29 allocs: 5.48 kB 29 allocs: 5.48 kB 1
stabilizer/trace/destabilizer 2 allocs: 0.0781 kB 2 allocs: 0.0781 kB 1
stabilizer/trace/stabilizer 3 allocs: 0.109 kB 3 allocs: 0.109 kB 1
time_to_load 0.149 k allocs: 11.1 kB 0.149 k allocs: 11.1 kB 1

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 46.80851% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.12%. Comparing base (ce8c432) to head (1330cf1).
⚠️ Report is 37 commits behind head on master.

Files with missing lines Patch % Lines
src/throws.jl 0.00% 25 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master     #740   +/-   ##
=======================================
  Coverage   74.12%   74.12%           
=======================================
  Files         111      113    +2     
  Lines        7791     7838   +47     
=======================================
+ Hits         5775     5810   +35     
- Misses       2016     2028   +12     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@arnavk23
arnavk23 marked this pull request as ready for review June 10, 2026 13:01

@Krastanov Krastanov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I vaguely remember the previous implementation in #620 looking much simpler than this -- am I misremembering, is this the same as #620?

There are a few other issues (upcoming post from a bot will list them) that I believe we had previously addressed in 620.

Comment thread src/reinterpret.jl Outdated
@Krastanov
Krastanov marked this pull request as draft June 12, 2026 04:30
@Krastanov-agent

Copy link
Copy Markdown
Collaborator

I reviewed this after reading through the comments on the earlier version in #620. The main open issues I see are below, with concrete examples.

  1. src/reinterpret.jl:17 and src/reinterpret.jl:23: tableau chunk counts are doubled. _nchunks(q, T) already includes both X and Z halves; zero(Tableau, r, q) uses it directly.
using QuantumClifford

t = zero(Tableau, 3, 64)

# Existing invariant from QuantumClifford:
@assert size(t.xzs, 1) == QuantumClifford._nchunks(nqubits(t), eltype(t.xzs))

# PR 740 expects this instead, so normal tableaus fail:
@assert size(t.xzs, 1) != 2 * QuantumClifford._nchunks(nqubits(t), eltype(t.xzs))

reinterpret(UInt8, t)  # should work, but currently throws

This also breaks Stabilizer, Destabilizer, mixed stabilizers, and PauliFrame, since they all go through tab(...).

  1. test/test_reinterpret.jl:122, :141, :162, :184, :206, :229, :253: positive-path tests accept exceptions as success, masking broken behavior.
t = zero(Tableau, 3, 64)

try
    reinterpret(UInt8, t)
    @test true
catch e
    # This makes a broken valid reinterpret pass the test.
    reinterpret_error_matches(e, "Unable to reinterpret tableau storage")
end

These should instead assert success directly:

t2 = reinterpret(UInt8, t)
t3 = reinterpret(eltype(t.xzs), t2)
@test t == t3

Only invalid alignment/size cases should use @test_throws.

  1. src/reinterpret.jl:13: fast-column layout is handled by stripping Adjoint and then treating the parent’s first axis as the chunk axis. For fastcolumn, the parent axes are transposed.
using LinearAlgebra
using QuantumClifford

t = fastcolumn(zero(Tableau, 3, 7))

@assert t.xzs isa Adjoint
@show size(t.xzs)          # logical tableau storage axes
@show size(parent(t.xzs))  # parent axes are reversed

reinterpret(UInt8, t)      # should preserve fast-column behavior, but line 13 reads parent axes incorrectly

This is one of the cases explicitly requested in the #620 discussion: the tests should prove both fastrow and fastcolumn work.

  1. src/reinterpret.jl:37 and src/reinterpret.jl:103: the implementation copies/collects storage, which violates reinterpret’s expected shared-storage behavior.
t = zero(Tableau, 2, 64)
t2 = reinterpret(UInt8, t)

t2.xzs[1, 1] = 0xff

# For reinterpret-like behavior, mutating t2 should affect t's backing storage.
# The copy at src/reinterpret.jl:37 prevents that.
@test !all(iszero, t.xzs)

One of the main points from #620 was that this should be allocation-free and should reuse the same backing memory where possible.

  1. src/reinterpret.jl:104: PauliFrame reconstructs with the original frame type after changing the tableau storage type. That can fail conversion back to the old type.
pf = PauliFrame(3, 4, 2)

new_frame = reinterpret(UInt8, pf.frame)

# PR code effectively does this:
typeof(pf.frame)(tab(new_frame))

# But typeof(pf.frame) still encodes the old tableau/xzs storage type.
# The result should use new_frame directly, not force the old frame type.

The test currently hides this by accepting conversion errors:

reinterpret_error_matches(e, (
    "Unable to reinterpret pauliframe storage",
    "Unable to reinterpret tableau storage",
    "Cannot `convert`",
))

I was not able to run local Julia probes to completion because the temporary checkout environment was not instantiated and Pkg.instantiate() stalled during artifact installation. GitHub CI reports the main unit/docs jobs passing, but these are static behavioral issues in the new code and tests.

-- Reviewed with OpenAI Codex CLI, GPT-5-based coding agent.

Comment thread src/reinterpret.jl Outdated
@Krastanov

Copy link
Copy Markdown
Member

@arnavk23 , it seems this PR is very different from the #620 that HA and I had reviewed some time ago. If that is indeed the case and we are not misremembering, please close this PR and consider reopening the older one or resubmitting the older one from a newly named branch. The branch of the old one seems to be deleted.

@Krastanov

Copy link
Copy Markdown
Member

@arnavk23 , is it possible to explicitly bring back the previous version that was already reviewed. Otherwise we have to review it again, which is a lot of work and I probably will struggle to find the motivation to repeat work that was already done.

@arnavk23

Copy link
Copy Markdown
Contributor Author

@arnavk23 , is it possible to explicitly bring back the previous version that was already reviewed. Otherwise we have to review it again, which is a lot of work and I probably will struggle to find the motivation to repeat work that was already done.

I have done just that, Stefan but wanted to go through all the comments once more on this code, specially the llm reply to see if the reviewed version has any faults before I asked you or HA for review.

@Krastanov

Copy link
Copy Markdown
Member

I meant doing that in some machine-verifiable form, e.g. seeing that this has the same hash or same branch or reviving the previous PR. Otherwise we still need to put in a lot of work to do a full review because there is no proof that this is actually exactly the same code as the one we had review already.

@arnavk23

arnavk23 commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

I meant doing that in some machine-verifiable form, e.g. seeing that this has the same hash or same branch or reviving the previous PR. Otherwise we still need to put in a lot of work to do a full review because there is no proof that this is actually exactly the same code as the one we had review already.

That can be seen in pr #696 , the pr is on a different issue but it contains all the information of the reinterpret branch before commits focused on the issue. Can be seen at 652d50a

@Hamiltonian-Action

Copy link
Copy Markdown
Contributor

@Krastanov, just as a curiosity. Is there any reason that QuantumClifford would even like to have a reinterpret call?

From my understanding, the underlying implementation details should be transparent to any project or user the employs the library. In so far as they are concerned, we could be storing states on actual quantum hardware and they would be none the wiser.
If someone is concerned about performance differences between the various underlying unsigned types, I believe that there are other mechanisms available to produce that effect starting at the constructor level. There is also the Adapt.jl utility that I mentioned earlier, which does suitable zero-padding in order to always produce a copy of the desired typing -- the garbage collector will come and reap the old object if it is no longer in use, hence memory should not be too much of a concern except for some highly specific edge cases.

@Krastanov

Copy link
Copy Markdown
Member

@Hamiltonian-Action , I agree with your logic, this is not a super important feature. It is a well defined feature that is not unreasonable to exist, but it would not see wide use -- as such, if it gets implemented and reviewed, great, we can merge it, but probably it would not be a high priority to review for me.

@arnavk23
arnavk23 marked this pull request as ready for review June 22, 2026 21:53
@arnavk23

Copy link
Copy Markdown
Contributor Author

@Krastanov this is safe to review and merge. All the files (except test_reinterpret.jl) are the same to the previous pr on the topic and I have also mentioned your particular commit which I referenced. And the file test_reinterpret.jl was changed to follow reinterpret.jl properly and for the tests to pass on the current setup.

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.

4 participants