ffsim 0.0.80__tar.gz → 0.0.81__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/test-latest-versions.yml +3 -3
  2. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/test-minimum-versions.yml +1 -1
  3. {ffsim-0.0.80 → ffsim-0.0.81}/CONTRIBUTING.md +1 -1
  4. {ffsim-0.0.80 → ffsim-0.0.81}/Cargo.toml +1 -1
  5. {ffsim-0.0.80 → ffsim-0.0.81}/PKG-INFO +4 -5
  6. {ffsim-0.0.80 → ffsim-0.0.81}/pyproject.toml +6 -10
  7. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_lib.pyi +1 -1
  8. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/fermion_operator.py +31 -18
  9. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/double_factorized_decomposition.py +232 -148
  10. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/util.py +12 -11
  11. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/random/random.py +46 -26
  12. {ffsim-0.0.80 → ffsim-0.0.81}/src/fermion_operator.rs +64 -30
  13. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/fermion_operator_test.py +52 -0
  14. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/random_test.py +43 -0
  15. {ffsim-0.0.80 → ffsim-0.0.81}/uv.lock +95 -865
  16. {ffsim-0.0.80 → ffsim-0.0.81}/.cargo/config.toml +0 -0
  17. {ffsim-0.0.80 → ffsim-0.0.81}/.dockerignore +0 -0
  18. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/build-and-release.yml +0 -0
  19. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/check.yml +0 -0
  20. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/docker.yml +0 -0
  21. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/docs-dev.yml +0 -0
  22. {ffsim-0.0.80 → ffsim-0.0.81}/.github/workflows/docs-release.yml +0 -0
  23. {ffsim-0.0.80 → ffsim-0.0.81}/.gitignore +0 -0
  24. {ffsim-0.0.80 → ffsim-0.0.81}/.pre-commit-config.yaml +0 -0
  25. {ffsim-0.0.80 → ffsim-0.0.81}/Cargo.lock +0 -0
  26. {ffsim-0.0.80 → ffsim-0.0.81}/Dockerfile +0 -0
  27. {ffsim-0.0.80 → ffsim-0.0.81}/LICENSE +0 -0
  28. {ffsim-0.0.80 → ffsim-0.0.81}/README.md +0 -0
  29. {ffsim-0.0.80 → ffsim-0.0.81}/compose.yaml +0 -0
  30. {ffsim-0.0.80 → ffsim-0.0.81}/docs/_static/logo-dark.svg +0 -0
  31. {ffsim-0.0.80 → ffsim-0.0.81}/docs/_static/logo.svg +0 -0
  32. {ffsim-0.0.80 → ffsim-0.0.81}/docs/_templates/autosummary/class.rst +0 -0
  33. {ffsim-0.0.80 → ffsim-0.0.81}/docs/conf.py +0 -0
  34. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/diag-coulomb-hamiltonian.ipynb +0 -0
  35. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/double-factorized.ipynb +0 -0
  36. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/fermion-operator.ipynb +0 -0
  37. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/hamiltonians.ipynb +0 -0
  38. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/index.md +0 -0
  39. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/lucj.ipynb +0 -0
  40. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/orbital-rotation.ipynb +0 -0
  41. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/protocols.ipynb +0 -0
  42. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/qubit-gate-decompositions.ipynb +0 -0
  43. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/state-vectors-and-gates.ipynb +0 -0
  44. {ffsim-0.0.80 → ffsim-0.0.81}/docs/explanations/variational-ansatzes.ipynb +0 -0
  45. {ffsim-0.0.80 → ffsim-0.0.81}/docs/generate_api_docs.py +0 -0
  46. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/compute-expectation-values.ipynb +0 -0
  47. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/entanglement-forging.ipynb +0 -0
  48. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/index.md +0 -0
  49. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/qiskit-circuits-sim.ipynb +0 -0
  50. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/qiskit-lucj.ipynb +0 -0
  51. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/qiskit-merge-orbital-rotations.ipynb +0 -0
  52. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/qiskit-trotter.ipynb +0 -0
  53. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/sample-from-state-vectors.ipynb +0 -0
  54. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/sample-slater.ipynb +0 -0
  55. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/simulate-trotter-hubbard.ipynb +0 -0
  56. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/simulate-trotter-mol-ham.ipynb +0 -0
  57. {ffsim-0.0.80 → ffsim-0.0.81}/docs/how-to-guides/simulate-vqe.ipynb +0 -0
  58. {ffsim-0.0.80 → ffsim-0.0.81}/docs/index.md +0 -0
  59. {ffsim-0.0.80 → ffsim-0.0.81}/docs/install.md +0 -0
  60. {ffsim-0.0.80 → ffsim-0.0.81}/docs/tutorials/double-factorized-trotter.ipynb +0 -0
  61. {ffsim-0.0.80 → ffsim-0.0.81}/docs/tutorials/index.md +0 -0
  62. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/__init__.py +0 -0
  63. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_cistring.py +0 -0
  64. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/__init__.py +0 -0
  65. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/contract/__init__.py +0 -0
  66. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/contract/diag_coulomb.py +0 -0
  67. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/contract/num_op_sum.py +0 -0
  68. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/gates/__init__.py +0 -0
  69. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/gates/diag_coulomb.py +0 -0
  70. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/gates/num_op_sum.py +0 -0
  71. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/_slow/gates/orbital_rotation.py +0 -0
  72. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/contract/__init__.py +0 -0
  73. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/contract/diag_coulomb.py +0 -0
  74. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/contract/num_op_sum.py +0 -0
  75. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/contract/one_body.py +0 -0
  76. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/contract/two_body.py +0 -0
  77. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/__init__.py +0 -0
  78. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/basic_gates.py +0 -0
  79. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/diag_coulomb.py +0 -0
  80. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/num_op_sum.py +0 -0
  81. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/orbital_rotation.py +0 -0
  82. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/gates/quad_ham.py +0 -0
  83. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/hamiltonians/__init__.py +0 -0
  84. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/hamiltonians/diagonal_coulomb_hamiltonian.py +0 -0
  85. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/hamiltonians/double_factorized_hamiltonian.py +0 -0
  86. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/hamiltonians/molecular_hamiltonian.py +0 -0
  87. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/hamiltonians/single_factorized_hamiltonian.py +0 -0
  88. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/init_cache.py +0 -0
  89. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/__init__.py +0 -0
  90. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/givens.py +0 -0
  91. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/linalg.py +0 -0
  92. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/linalg/predicates.py +0 -0
  93. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/molecular_data.py +0 -0
  94. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/__init__.py +0 -0
  95. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/common_operators.py +0 -0
  96. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/coupled_cluster.py +0 -0
  97. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/fermi_hubbard.py +0 -0
  98. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/fermion_action.py +0 -0
  99. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/operators/fermion_operator.py +0 -0
  100. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/optimize/__init__.py +0 -0
  101. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/optimize/_util.py +0 -0
  102. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/optimize/linear_method.py +0 -0
  103. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/__init__.py +0 -0
  104. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/apply_unitary_protocol.py +0 -0
  105. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/approximate_equality_protocol.py +0 -0
  106. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/diagonal_protocol.py +0 -0
  107. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/fermion_operator_protocol.py +0 -0
  108. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/linear_operator_protocol.py +0 -0
  109. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/protocols/trace_protocol.py +0 -0
  110. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/py.typed +0 -0
  111. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/__init__.py +0 -0
  112. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/__init__.py +0 -0
  113. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/diag_coulomb.py +0 -0
  114. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/diag_coulomb_trotter_split_op.py +0 -0
  115. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/double_factorized_trotter.py +0 -0
  116. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/givens_ansatz.py +0 -0
  117. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/num_num_ansatz.py +0 -0
  118. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/num_op_sum.py +0 -0
  119. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/orbital_rotation.py +0 -0
  120. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/slater_determinant.py +0 -0
  121. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/gates/ucj.py +0 -0
  122. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/jordan_wigner.py +0 -0
  123. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/lucj_pass_manager.py +0 -0
  124. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/sampler.py +0 -0
  125. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/sim.py +0 -0
  126. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/transpiler_passes/__init__.py +0 -0
  127. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/transpiler_passes/drop_negligible.py +0 -0
  128. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/transpiler_passes/merge_orbital_rotations.py +0 -0
  129. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/transpiler_stages.py +0 -0
  130. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/qiskit/util.py +0 -0
  131. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/random/__init__.py +0 -0
  132. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/__init__.py +0 -0
  133. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/bitstring.py +0 -0
  134. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/dimensions.py +0 -0
  135. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/product_state_sum.py +0 -0
  136. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/rdm.py +0 -0
  137. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/sample_slater.py +0 -0
  138. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/slater.py +0 -0
  139. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/spin.py +0 -0
  140. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/states.py +0 -0
  141. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/states/wick.py +0 -0
  142. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/testing/__init__.py +0 -0
  143. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/testing/testing.py +0 -0
  144. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/trotter/__init__.py +0 -0
  145. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/trotter/_util.py +0 -0
  146. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/trotter/diagonal_coulomb_split_op.py +0 -0
  147. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/trotter/double_factorized.py +0 -0
  148. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/trotter/qdrift.py +0 -0
  149. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/__init__.py +0 -0
  150. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/givens.py +0 -0
  151. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/hopgate.py +0 -0
  152. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/multireference.py +0 -0
  153. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/num_num.py +0 -0
  154. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/orbital_optimization.py +0 -0
  155. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/uccsd.py +0 -0
  156. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/ucj_angles_spin_balanced.py +0 -0
  157. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/ucj_spin_balanced.py +0 -0
  158. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/ucj_spin_unbalanced.py +0 -0
  159. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/ucj_spinless.py +0 -0
  160. {ffsim-0.0.80 → ffsim-0.0.81}/python/ffsim/variational/util.py +0 -0
  161. {ffsim-0.0.80 → ffsim-0.0.81}/src/contract/diag_coulomb.rs +0 -0
  162. {ffsim-0.0.80 → ffsim-0.0.81}/src/contract/mod.rs +0 -0
  163. {ffsim-0.0.80 → ffsim-0.0.81}/src/contract/num_op_sum.rs +0 -0
  164. {ffsim-0.0.80 → ffsim-0.0.81}/src/gates/diag_coulomb.rs +0 -0
  165. {ffsim-0.0.80 → ffsim-0.0.81}/src/gates/mod.rs +0 -0
  166. {ffsim-0.0.80 → ffsim-0.0.81}/src/gates/num_op_sum.rs +0 -0
  167. {ffsim-0.0.80 → ffsim-0.0.81}/src/gates/orbital_rotation.rs +0 -0
  168. {ffsim-0.0.80 → ffsim-0.0.81}/src/gates/phase_shift.rs +0 -0
  169. {ffsim-0.0.80 → ffsim-0.0.81}/src/jordan_wigner.rs +0 -0
  170. {ffsim-0.0.80 → ffsim-0.0.81}/src/lib.rs +0 -0
  171. {ffsim-0.0.80 → ffsim-0.0.81}/src/linalg/givens.rs +0 -0
  172. {ffsim-0.0.80 → ffsim-0.0.81}/src/linalg/mod.rs +0 -0
  173. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/__init__.py +0 -0
  174. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/__init__.py +0 -0
  175. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/contract/__init__.py +0 -0
  176. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/contract/diag_coulomb_test.py +0 -0
  177. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/contract/num_op_sum_test.py +0 -0
  178. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/gates/__init__.py +0 -0
  179. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/gates/diag_coulomb_test.py +0 -0
  180. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/gates/num_op_sum_test.py +0 -0
  181. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/_slow/gates/orbital_rotation_test.py +0 -0
  182. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/contract/__init__.py +0 -0
  183. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/contract/diag_coulomb_test.py +0 -0
  184. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/contract/num_op_sum_test.py +0 -0
  185. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/contract/two_body_test.py +0 -0
  186. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/__init__.py +0 -0
  187. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/basic_gates_test.py +0 -0
  188. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/diag_coulomb_test.py +0 -0
  189. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/num_op_sum_test.py +0 -0
  190. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/orbital_rotation_test.py +0 -0
  191. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/gates/quad_ham_test.py +0 -0
  192. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/hamiltonians/__init__.py +0 -0
  193. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/hamiltonians/diagonal_coulomb_hamiltonian_test.py +0 -0
  194. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/hamiltonians/double_factorized_hamiltonian_test.py +0 -0
  195. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/hamiltonians/molecular_hamiltonian_test.py +0 -0
  196. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/hamiltonians/single_factorized_hamiltonian_test.py +0 -0
  197. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/linalg/__init__.py +0 -0
  198. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/linalg/double_factorized_decomposition_test.py +0 -0
  199. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/linalg/givens_test.py +0 -0
  200. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/linalg/linalg_test.py +0 -0
  201. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/linalg/util_test.py +0 -0
  202. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/molecular_data_test.py +0 -0
  203. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/__init__.py +0 -0
  204. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/common_operators_test.py +0 -0
  205. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/coupled_cluster_test.py +0 -0
  206. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/fermi_hubbard_test.py +0 -0
  207. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/operators/fermion_action_test.py +0 -0
  208. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/optimize/__init__.py +0 -0
  209. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/optimize/linear_method_test.py +0 -0
  210. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/protocols/__init__.py +0 -0
  211. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/protocols/trace_protocol_test.py +0 -0
  212. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/__init__.py +0 -0
  213. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/__init__.py +0 -0
  214. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/diag_coulomb_test.py +0 -0
  215. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/diag_coulomb_trotter_split_op_test.py +0 -0
  216. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/double_factorized_trotter_test.py +0 -0
  217. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/givens_ansatz_test.py +0 -0
  218. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/num_num_ansatz_test.py +0 -0
  219. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/num_op_sum_test.py +0 -0
  220. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/orbital_rotation_test.py +0 -0
  221. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/slater_determinant_test.py +0 -0
  222. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/gates/ucj_test.py +0 -0
  223. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/jordan_wigner_test.py +0 -0
  224. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/lucj_pass_manager_test.py +0 -0
  225. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/sampler_test.py +0 -0
  226. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/sim_test.py +0 -0
  227. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/transpiler_passes/__init__.py +0 -0
  228. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/transpiler_passes/drop_negligible_test.py +0 -0
  229. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/transpiler_passes/merge_orbital_rotations_test.py +0 -0
  230. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/qiskit/util_test.py +0 -0
  231. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/__init__.py +0 -0
  232. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/bitstring_test.py +0 -0
  233. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/rdm_test.py +0 -0
  234. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/sample_slater_test.py +0 -0
  235. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/slater_test.py +0 -0
  236. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/states_test.py +0 -0
  237. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/states/wick_test.py +0 -0
  238. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/test_data/orbital_rotation-0.npy +0 -0
  239. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/test_no_warnings.py +0 -0
  240. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/testing_test.py +0 -0
  241. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/trotter/__init__.py +0 -0
  242. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/trotter/diag_coulomb_split_op_test.py +0 -0
  243. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/trotter/double_factorized_test.py +0 -0
  244. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/trotter/qdrift_test.py +0 -0
  245. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/__init__.py +0 -0
  246. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/givens_test.py +0 -0
  247. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/hopgate_test.py +0 -0
  248. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/multireference_test.py +0 -0
  249. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/num_num_test.py +0 -0
  250. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/orbital_optimization_test.py +0 -0
  251. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/uccsd_test.py +0 -0
  252. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/ucj_angles_spin_balanced_test.py +0 -0
  253. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/ucj_spin_balanced_test.py +0 -0
  254. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/ucj_spin_unbalanced_test.py +0 -0
  255. {ffsim-0.0.80 → ffsim-0.0.81}/tests/python/variational/ucj_spinless_test.py +0 -0
@@ -17,7 +17,7 @@ jobs:
17
17
  runs-on: ubuntu-latest
18
18
  strategy:
19
19
  matrix:
20
- python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
20
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
21
21
  steps:
22
22
  - uses: actions/checkout@v6
23
23
  - name: Set up Python
@@ -35,7 +35,7 @@ jobs:
35
35
  runs-on: ubuntu-24.04-arm
36
36
  strategy:
37
37
  matrix:
38
- python-version: ["3.10", "3.14"]
38
+ python-version: ["3.11", "3.14"]
39
39
  steps:
40
40
  - uses: actions/checkout@v6
41
41
  - name: Set up Python
@@ -53,7 +53,7 @@ jobs:
53
53
  runs-on: macos-latest
54
54
  strategy:
55
55
  matrix:
56
- python-version: ["3.10", "3.14"]
56
+ python-version: ["3.11", "3.14"]
57
57
  steps:
58
58
  - uses: actions/checkout@v6
59
59
  - name: Set up Python
@@ -17,7 +17,7 @@ jobs:
17
17
  runs-on: ubuntu-latest
18
18
  strategy:
19
19
  matrix:
20
- python-version: ["3.10"]
20
+ python-version: ["3.11"]
21
21
  steps:
22
22
  - uses: actions/checkout@v6
23
23
  - name: Set up Python
@@ -47,7 +47,7 @@ tox run -e <environment name>
47
47
 
48
48
  substituting `<environment name>` with the name of the tox environment for the check. The following environments are available:
49
49
 
50
- - `test-3.10`, `test-3.11`, `test-3.12`, `test-3.13`, `test-3.14`: Run tests for a specific Python version
50
+ - `test-3.11`, `test-3.12`, `test-3.13`, `test-3.14`: Run tests for a specific Python version
51
51
  - `coverage`: Code coverage
52
52
  - `type`: Type check
53
53
  - `lint`: Lint check
@@ -16,6 +16,6 @@ numpy = "0.27"
16
16
  pyo3 = { version = "0.27", features = [
17
17
  "extension-module",
18
18
  "num-complex",
19
- "abi3-py310",
19
+ "abi3-py311",
20
20
  ] }
21
21
  rayon = "1.11"
@@ -1,10 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ffsim
3
- Version: 0.0.80
3
+ Version: 0.0.81
4
4
  Classifier: License :: OSI Approved :: Apache Software License
5
5
  Classifier: Programming Language :: Python
6
6
  Classifier: Programming Language :: Python :: 3 :: Only
7
- Classifier: Programming Language :: Python :: 3.10
8
7
  Classifier: Programming Language :: Python :: 3.11
9
8
  Classifier: Programming Language :: Python :: 3.12
10
9
  Classifier: Programming Language :: Python :: 3.13
@@ -14,16 +13,16 @@ Classifier: Topic :: Scientific/Engineering :: Chemistry
14
13
  Classifier: Topic :: Scientific/Engineering :: Physics
15
14
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
15
  Requires-Dist: jax
17
- Requires-Dist: numpy<=2.3
16
+ Requires-Dist: numpy
18
17
  Requires-Dist: opt-einsum
19
18
  Requires-Dist: orjson
20
- Requires-Dist: pyscf>=2.9
19
+ Requires-Dist: pyscf>=2.12
21
20
  Requires-Dist: qiskit>=2.0
22
21
  Requires-Dist: scipy
23
22
  Requires-Dist: typing-extensions
24
23
  License-File: LICENSE
25
24
  Summary: Faster simulation of fermionic quantum circuits.
26
- Requires-Python: >=3.10
25
+ Requires-Python: >=3.11
27
26
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
28
27
  Project-URL: Documentation, https://qiskit-community.github.io/ffsim/
29
28
  Project-URL: Homepage, https://github.com/qiskit-community/ffsim
@@ -4,8 +4,8 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "ffsim"
7
- requires-python = ">=3.10"
8
- version = "0.0.80"
7
+ requires-python = ">=3.11"
8
+ version = "0.0.81"
9
9
  description = "Faster simulation of fermionic quantum circuits."
10
10
  readme = "README.md"
11
11
  license = { file = "LICENSE" }
@@ -13,7 +13,6 @@ classifiers = [
13
13
  "License :: OSI Approved :: Apache Software License",
14
14
  "Programming Language :: Python",
15
15
  "Programming Language :: Python :: 3 :: Only",
16
- "Programming Language :: Python :: 3.10",
17
16
  "Programming Language :: Python :: 3.11",
18
17
  "Programming Language :: Python :: 3.12",
19
18
  "Programming Language :: Python :: 3.13",
@@ -25,12 +24,10 @@ classifiers = [
25
24
  ]
26
25
  dependencies = [
27
26
  "jax",
28
- # restrict Numpy version due to https://github.com/pyscf/pyscf/issues/3079
29
- # TODO remove this when it's fixed
30
- "numpy <= 2.3",
27
+ "numpy",
31
28
  "opt_einsum",
32
29
  "orjson",
33
- "pyscf >= 2.9",
30
+ "pyscf >= 2.12",
34
31
  "qiskit >= 2.0",
35
32
  "scipy",
36
33
  "typing-extensions",
@@ -66,7 +63,7 @@ python-source = "python"
66
63
  module-name = "ffsim._lib"
67
64
 
68
65
  [tool.cibuildwheel]
69
- build = "cp310-macosx* cp310-manylinux_x86_64 cp310-manylinux_aarch64"
66
+ build = "cp311-macosx* cp311-manylinux_x86_64 cp311-manylinux_aarch64"
70
67
  test-requires = "pytest"
71
68
  test-command = "pytest {project}/tests"
72
69
 
@@ -112,7 +109,6 @@ ket = "ket"
112
109
  [tool.tox]
113
110
  requires = ["tox>=4.50"]
114
111
  env_list = [
115
- "test-3.10",
116
112
  "test-3.11",
117
113
  "test-3.12",
118
114
  "test-3.13",
@@ -136,7 +132,7 @@ pass_env = [
136
132
 
137
133
  [tool.tox.env_base.test]
138
134
  description = "run tests"
139
- factors = [["3.10", "3.11", "3.12", "3.13", "3.14"]]
135
+ factors = [["3.11", "3.12", "3.13", "3.14"]]
140
136
  deps = ["pytest"]
141
137
  commands = [["pytest"]]
142
138
 
@@ -7,7 +7,7 @@ class FermionOperator(MutableMapping[tuple[tuple[bool, bool, int], ...], complex
7
7
  self, coeffs: dict[tuple[tuple[bool, bool, int], ...], complex]
8
8
  ) -> None: ...
9
9
  def adjoint(self) -> "FermionOperator": ...
10
- def normal_ordered(self) -> "FermionOperator": ...
10
+ def normal_ordered(self, group_by_spin: bool = ...) -> "FermionOperator": ...
11
11
  def conserves_particle_number(self) -> bool: ...
12
12
  def conserves_spin_z(self) -> bool: ...
13
13
  def many_body_order(self) -> int: ...
@@ -135,10 +135,10 @@ class FermionOperator(MutableMapping):
135
135
  return result
136
136
  return NotImplemented
137
137
 
138
- def normal_ordered(self) -> "FermionOperator":
138
+ def normal_ordered(self, group_by_spin: bool = False) -> "FermionOperator":
139
139
  result = FermionOperator({})
140
140
  for term, coeff in self.coeffs.items():
141
- result += _normal_ordered_term(term, coeff)
141
+ result += _normal_ordered_term(term, coeff, group_by_spin)
142
142
  return result
143
143
 
144
144
  def conserves_particle_number(self) -> bool:
@@ -220,8 +220,23 @@ class FermionOperator(MutableMapping):
220
220
  )
221
221
 
222
222
 
223
+ def _order_key(op: FermionAction, group_by_spin: bool) -> tuple[bool, bool, int]:
224
+ """The sort key used to normal order a term.
225
+
226
+ Terms are reordered into descending order of this key. By default the key is
227
+ ``(action, spin, orb)`` (creations before annihilations). When ``group_by_spin``
228
+ is True the key is ``(spin, action, orb)`` (spin beta before spin alpha). In
229
+ both cases, a creation operator precedes the annihilation operator on the same
230
+ spin-orbital.
231
+ """
232
+ action, spin, orb = op
233
+ if group_by_spin:
234
+ return (spin, action, orb)
235
+ return (action, spin, orb)
236
+
237
+
223
238
  def _normal_ordered_term(
224
- term: Iterable[FermionAction], coeff: complex
239
+ term: Iterable[FermionAction], coeff: complex, group_by_spin: bool = False
225
240
  ) -> FermionOperator:
226
241
  coeffs: dict[tuple[FermionAction, ...], complex] = {}
227
242
  stack = [(list(term), coeff)]
@@ -232,22 +247,20 @@ def _normal_ordered_term(
232
247
  for i in range(1, len(term)):
233
248
  # shift operator at index i to the left until it's in the correct location
234
249
  for j in range(i, 0, -1):
235
- action_right, spin_right, index_right = term[j]
236
- action_left, spin_left, index_left = term[j - 1]
237
- if action_right == action_left:
238
- # both create or both destroy
239
- if (spin_right, index_right) == (spin_left, index_left):
240
- # operators are the same, so product is zero
241
- zero = True
242
- break
243
- elif (spin_right, index_right) > (spin_left, index_left):
244
- # swap operators and update sign
245
- term[j - 1], term[j] = term[j], term[j - 1]
246
- parity = not parity
247
- elif action_right and not action_left:
248
- # create on right and destroy on left
250
+ right = term[j]
251
+ left = term[j - 1]
252
+ if right == left:
253
+ # operators are the same, so product is zero
254
+ zero = True
255
+ break
256
+ if _order_key(right, group_by_spin) > _order_key(left, group_by_spin):
257
+ _, spin_right, index_right = right
258
+ _, spin_left, index_left = left
259
+ # the operator on the right belongs to the left, so swap them
249
260
  if (spin_right, index_right) == (spin_left, index_left):
250
- # add new term
261
+ # conjugate pair on the same spin-orbital: the creation operator
262
+ # is moving to the left past its annihilation operator, which
263
+ # produces an additional term from the anticommutation relation
251
264
  new_term = term[: j - 1] + term[j + 1 :]
252
265
  sign = -1 if parity else 1
253
266
  stack.append((new_term, sign * coeff))