ffsim 0.0.78__tar.gz → 0.0.79__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.
- {ffsim-0.0.78 → ffsim-0.0.79}/CONTRIBUTING.md +3 -8
- {ffsim-0.0.78 → ffsim-0.0.79}/PKG-INFO +3 -3
- {ffsim-0.0.78 → ffsim-0.0.79}/README.md +2 -2
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/_templates/autosummary/class.rst +4 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/conf.py +0 -1
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/install.md +6 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/pyproject.toml +26 -25
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/__init__.py +1 -6
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/givens.py +0 -44
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/diag_coulomb_trotter_split_op.py +12 -2
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/double_factorized_trotter.py +12 -2
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/ucj.py +47 -18
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/trotter/qdrift.py +6 -8
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/ucj_spin_unbalanced.py +2 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/ucj_spinless.py +2 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/contract/diag_coulomb_test.py +14 -14
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/contract/num_op_sum_test.py +6 -5
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/gates/diag_coulomb_test.py +17 -18
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/gates/num_op_sum_test.py +6 -5
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/gates/orbital_rotation_test.py +7 -6
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/contract/diag_coulomb_test.py +15 -18
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/contract/num_op_sum_test.py +12 -12
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/basic_gates_test.py +29 -43
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/diag_coulomb_test.py +22 -25
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/num_op_sum_test.py +9 -10
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/orbital_rotation_test.py +22 -28
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/hamiltonians/single_factorized_hamiltonian_test.py +13 -19
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/linalg/givens_test.py +6 -8
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/linalg/linalg_test.py +5 -5
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/fermion_operator_test.py +6 -7
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/optimize/linear_method_test.py +4 -3
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/diag_coulomb_test.py +20 -21
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/diag_coulomb_trotter_split_op_test.py +23 -3
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/double_factorized_trotter_test.py +26 -3
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/givens_ansatz_test.py +10 -10
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/num_num_ansatz_test.py +5 -4
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/num_op_sum_test.py +19 -20
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/orbital_rotation_test.py +21 -26
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/slater_determinant_test.py +7 -9
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/ucj_test.py +51 -9
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/jordan_wigner_test.py +26 -12
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/sampler_test.py +50 -64
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/sim_test.py +62 -70
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/transpiler_passes/merge_orbital_rotations_test.py +25 -41
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/util_test.py +3 -2
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/random_test.py +20 -20
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/bitstring_test.py +4 -4
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/sample_slater_test.py +13 -15
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/slater_test.py +19 -33
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/wick_test.py +8 -10
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/testing_test.py +4 -3
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/trotter/diag_coulomb_split_op_test.py +8 -10
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/trotter/double_factorized_test.py +6 -6
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/trotter/qdrift_test.py +58 -42
- {ffsim-0.0.78 → ffsim-0.0.79}/uv.lock +13 -9
- {ffsim-0.0.78 → ffsim-0.0.79}/.cargo/config.toml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.dockerignore +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/build-and-release.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/check.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/docker.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/docs-dev.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/docs-release.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/test-latest-versions.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.github/workflows/test-minimum-versions.yml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.gitignore +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/.pre-commit-config.yaml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/Cargo.lock +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/Cargo.toml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/Dockerfile +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/LICENSE +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/compose.yaml +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/_static/logo-dark.svg +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/_static/logo.svg +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/diag-coulomb-hamiltonian.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/double-factorized.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/fermion-operator.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/hamiltonians.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/index.md +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/lucj.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/orbital-rotation.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/protocols.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/qubit-gate-decompositions.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/state-vectors-and-gates.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/explanations/variational-ansatzes.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/generate_api_docs.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/compute-expectation-values.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/entanglement-forging.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/index.md +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/qiskit-circuits-sim.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/qiskit-lucj.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/qiskit-merge-orbital-rotations.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/qiskit-trotter.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/sample-from-state-vectors.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/sample-slater.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/simulate-trotter-hubbard.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/simulate-trotter-mol-ham.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/how-to-guides/simulate-vqe.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/index.md +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/tutorials/double-factorized-trotter.ipynb +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/docs/tutorials/index.md +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_cistring.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_lib.pyi +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/contract/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/contract/diag_coulomb.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/contract/num_op_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/fermion_operator.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/gates/num_op_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/_slow/gates/orbital_rotation.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/contract/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/contract/diag_coulomb.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/contract/num_op_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/contract/one_body.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/contract/two_body.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/basic_gates.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/num_op_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/orbital_rotation.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/gates/quad_ham.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/hamiltonians/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/hamiltonians/diagonal_coulomb_hamiltonian.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/hamiltonians/double_factorized_hamiltonian.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/hamiltonians/molecular_hamiltonian.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/hamiltonians/single_factorized_hamiltonian.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/init_cache.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/double_factorized_decomposition.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/linalg.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/predicates.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/linalg/util.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/molecular_data.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/common_operators.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/coupled_cluster.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/fermi_hubbard.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/fermion_action.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/operators/fermion_operator.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/optimize/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/optimize/_util.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/optimize/linear_method.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/apply_unitary_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/approximate_equality_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/diagonal_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/fermion_operator_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/linear_operator_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/protocols/trace_protocol.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/py.typed +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/givens_ansatz.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/num_num_ansatz.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/num_op_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/orbital_rotation.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/gates/slater_determinant.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/jordan_wigner.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/lucj_pass_manager.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/sampler.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/sim.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/transpiler_passes/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/transpiler_passes/drop_negligible.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/transpiler_passes/merge_orbital_rotations.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/transpiler_stages.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/qiskit/util.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/random/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/random/random.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/bitstring.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/dimensions.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/product_state_sum.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/rdm.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/sample_slater.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/slater.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/spin.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/states.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/states/wick.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/testing/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/testing/testing.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/trotter/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/trotter/_util.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/trotter/diagonal_coulomb_split_op.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/trotter/double_factorized.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/givens.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/hopgate.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/multireference.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/num_num.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/orbital_optimization.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/uccsd.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/ucj_angles_spin_balanced.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/ucj_spin_balanced.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/python/ffsim/variational/util.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/contract/diag_coulomb.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/contract/mod.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/contract/num_op_sum.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/fermion_operator.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/gates/diag_coulomb.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/gates/mod.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/gates/num_op_sum.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/gates/orbital_rotation.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/gates/phase_shift.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/jordan_wigner.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/lib.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/linalg/givens.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/src/linalg/mod.rs +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/contract/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/_slow/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/contract/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/contract/two_body_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/gates/quad_ham_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/hamiltonians/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/hamiltonians/diagonal_coulomb_hamiltonian_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/hamiltonians/double_factorized_hamiltonian_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/hamiltonians/molecular_hamiltonian_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/linalg/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/linalg/double_factorized_decomposition_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/linalg/util_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/molecular_data_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/common_operators_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/coupled_cluster_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/fermi_hubbard_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/operators/fermion_action_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/optimize/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/protocols/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/protocols/trace_protocol_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/gates/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/lucj_pass_manager_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/transpiler_passes/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/qiskit/transpiler_passes/drop_negligible_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/rdm_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/states/states_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/test_data/orbital_rotation-0.npy +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/test_no_warnings.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/trotter/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/__init__.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/givens_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/hopgate_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/multireference_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/num_num_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/orbital_optimization_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/uccsd_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/ucj_angles_spin_balanced_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/ucj_spin_balanced_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/ucj_spin_unbalanced_test.py +0 -0
- {ffsim-0.0.78 → ffsim-0.0.79}/tests/python/variational/ucj_spinless_test.py +0 -0
|
@@ -7,7 +7,7 @@ The instructions on this page won't work natively on Windows. For ffsim developm
|
|
|
7
7
|
To set up ffsim for development, install it from source in editable mode along with the development requirements:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pip install -e
|
|
10
|
+
pip install -e . --group dev
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
To install the git pre-commit hooks, run
|
|
@@ -57,10 +57,7 @@ substituting `<environment name>` with the name of the tox environment for the c
|
|
|
57
57
|
|
|
58
58
|
## Run code checks directly
|
|
59
59
|
|
|
60
|
-
Running the code checks directly using the corresponding software tool
|
|
61
|
-
|
|
62
|
-
- Automatically fix lint and formatting errors.
|
|
63
|
-
- Build the documentation without deleting cached files.
|
|
60
|
+
Running the code checks directly using the corresponding software tool gives you more flexibility and allows you to automatically fix lint and formatting errors.
|
|
64
61
|
|
|
65
62
|
### Run tests
|
|
66
63
|
|
|
@@ -101,6 +98,4 @@ sphinx-build -b html -W docs/ docs/_build/html
|
|
|
101
98
|
|
|
102
99
|
## View locally built documentation
|
|
103
100
|
|
|
104
|
-
After building the
|
|
105
|
-
Building the documentation can consume significant CPU because the tutorial notebooks are executed.
|
|
106
|
-
The tox command deletes cached files so it will execute all the notebooks every time, while the sphinx command only executes notebooks if they were modified from the previous run.
|
|
101
|
+
After building the documentation, open the file `docs/_build/html/index.html` in your web browser.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ffsim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.79
|
|
4
4
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
5
5
|
Classifier: Programming Language :: Python
|
|
6
6
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -44,13 +44,13 @@ Documentation is located at the [project website](https://qiskit-community.githu
|
|
|
44
44
|
|
|
45
45
|
<!-- start installation -->
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
On Linux and macOS, you can install ffsim using pip:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
50
|
pip install ffsim
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for information about using ffsim on Windows, as well as instructions for installing from source and running ffsim in a container.
|
|
54
54
|
|
|
55
55
|
<!-- end installation -->
|
|
56
56
|
|
|
@@ -14,13 +14,13 @@ Documentation is located at the [project website](https://qiskit-community.githu
|
|
|
14
14
|
|
|
15
15
|
<!-- start installation -->
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
On Linux and macOS, you can install ffsim using pip:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pip install ffsim
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for information about using ffsim on Windows, as well as instructions for installing from source and running ffsim in a container.
|
|
24
24
|
|
|
25
25
|
<!-- end installation -->
|
|
26
26
|
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
~{{ name }}.{{ item }}
|
|
27
27
|
{%- endfor %}
|
|
28
28
|
{% endif %}
|
|
29
|
+
{%- for item in methods if item not in inherited_members and item != '__init__' %}
|
|
30
|
+
|
|
31
|
+
.. automethod:: {{ item }}
|
|
32
|
+
{%- endfor %}
|
|
29
33
|
{%- for item in ns.protocol_methods %}
|
|
30
34
|
|
|
31
35
|
.. automethod:: {{ item }}
|
|
@@ -15,6 +15,8 @@ ffsim is available on [PyPI](https://pypi.org/project/ffsim/). You can install i
|
|
|
15
15
|
pip install ffsim
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
For improved performance on [x86](https://en.wikipedia.org/wiki/X86) systems, considering [installing from source](#install-from-source).
|
|
19
|
+
|
|
18
20
|
## Install from source
|
|
19
21
|
|
|
20
22
|
You can use pip to install ffsim from source. For example:
|
|
@@ -25,6 +27,10 @@ cd ffsim
|
|
|
25
27
|
pip install .
|
|
26
28
|
```
|
|
27
29
|
|
|
30
|
+
Installing from source may improve performance on x86 systems because the Rust extensions in the PyPI wheels are compiled with `-C target-cpu=x86-64`, which targets the baseline x86-64 instruction set for broad compatibility. When you build from source, ffsim is configured to compile its Rust extensions with `-C target-cpu=native`, so the Rust compiler can emit optimized instructions (e.g., AVX2, AVX-512) for your specific CPU.
|
|
31
|
+
|
|
32
|
+
Similarly, you can install [PySCF](https://pyscf.org/) from source with `-DBUILD_MARCH_NATIVE=ON` to enable CPU-specific optimizations in PySCF's C extensions. See [PySCF's installation instructions](https://pyscf.org/user/install.html#build-from-source) for details.
|
|
33
|
+
|
|
28
34
|
## Use within Docker
|
|
29
35
|
|
|
30
36
|
We provide a [Dockerfile](https://github.com/qiskit-community/ffsim/blob/main/Dockerfile) and a [compose.yaml](https://github.com/qiskit-community/ffsim/blob/main/compose.yaml) file, which you can use to build a [Docker](https://www.docker.com/) image with just a few simple commands:
|
|
@@ -5,7 +5,7 @@ build-backend = "maturin"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ffsim"
|
|
7
7
|
requires-python = ">=3.10"
|
|
8
|
-
version = "0.0.
|
|
8
|
+
version = "0.0.79"
|
|
9
9
|
description = "Faster simulation of fermionic quantum circuits."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = { file = "LICENSE" }
|
|
@@ -45,17 +45,19 @@ dev = [
|
|
|
45
45
|
"coverage",
|
|
46
46
|
"maturin",
|
|
47
47
|
"mypy",
|
|
48
|
+
"pre-commit",
|
|
49
|
+
"pytest",
|
|
50
|
+
"ruff",
|
|
51
|
+
"typos",
|
|
52
|
+
]
|
|
53
|
+
docs = [
|
|
48
54
|
"myst-parser",
|
|
49
55
|
"nbmake",
|
|
50
56
|
"nbsphinx",
|
|
51
|
-
"pre-commit",
|
|
52
|
-
"pytest",
|
|
53
57
|
"qiskit[visualization]",
|
|
54
58
|
"qiskit-sphinx-theme",
|
|
55
|
-
"ruff",
|
|
56
59
|
"sphinx",
|
|
57
60
|
"sphinx-autodoc-typehints",
|
|
58
|
-
"typos",
|
|
59
61
|
]
|
|
60
62
|
|
|
61
63
|
[tool.maturin]
|
|
@@ -140,7 +142,7 @@ commands = [["pytest"]]
|
|
|
140
142
|
|
|
141
143
|
[tool.tox.env.coverage]
|
|
142
144
|
description = "check test coverage"
|
|
143
|
-
|
|
145
|
+
deps = ["coverage", "pytest"]
|
|
144
146
|
commands = [
|
|
145
147
|
[
|
|
146
148
|
"coverage",
|
|
@@ -157,48 +159,43 @@ commands = [
|
|
|
157
159
|
],
|
|
158
160
|
]
|
|
159
161
|
|
|
160
|
-
[tool.tox.env.
|
|
161
|
-
description = "
|
|
162
|
-
dependency_groups = ["dev"]
|
|
163
|
-
commands = [["mypy"]]
|
|
164
|
-
|
|
165
|
-
[tool.tox.env.lint]
|
|
166
|
-
description = "check for lint"
|
|
162
|
+
[tool.tox.env.format]
|
|
163
|
+
description = "check formatting"
|
|
167
164
|
skip_install = true
|
|
168
165
|
deps = ["ruff"]
|
|
169
166
|
allowlist_externals = ["cargo"]
|
|
170
167
|
commands = [
|
|
171
168
|
[
|
|
172
169
|
"ruff",
|
|
173
|
-
"
|
|
170
|
+
"format",
|
|
171
|
+
"--check",
|
|
174
172
|
],
|
|
175
173
|
[
|
|
176
174
|
"cargo",
|
|
177
|
-
"
|
|
175
|
+
"fmt",
|
|
178
176
|
"--all",
|
|
179
177
|
"--",
|
|
180
|
-
"
|
|
181
|
-
"warnings",
|
|
178
|
+
"--check",
|
|
182
179
|
],
|
|
183
180
|
]
|
|
184
181
|
|
|
185
|
-
[tool.tox.env.
|
|
186
|
-
description = "check
|
|
182
|
+
[tool.tox.env.lint]
|
|
183
|
+
description = "check for lint"
|
|
187
184
|
skip_install = true
|
|
188
185
|
deps = ["ruff"]
|
|
189
186
|
allowlist_externals = ["cargo"]
|
|
190
187
|
commands = [
|
|
191
188
|
[
|
|
192
189
|
"ruff",
|
|
193
|
-
"
|
|
194
|
-
"--check",
|
|
190
|
+
"check",
|
|
195
191
|
],
|
|
196
192
|
[
|
|
197
193
|
"cargo",
|
|
198
|
-
"
|
|
194
|
+
"clippy",
|
|
199
195
|
"--all",
|
|
200
196
|
"--",
|
|
201
|
-
"
|
|
197
|
+
"-D",
|
|
198
|
+
"warnings",
|
|
202
199
|
],
|
|
203
200
|
]
|
|
204
201
|
|
|
@@ -208,10 +205,14 @@ skip_install = true
|
|
|
208
205
|
deps = ["typos"]
|
|
209
206
|
commands = [["typos"]]
|
|
210
207
|
|
|
208
|
+
[tool.tox.env.type]
|
|
209
|
+
description = "run type check"
|
|
210
|
+
deps = ["mypy"]
|
|
211
|
+
commands = [["mypy"]]
|
|
212
|
+
|
|
211
213
|
[tool.tox.env.docs]
|
|
212
214
|
description = "build docs"
|
|
213
|
-
dependency_groups = ["
|
|
214
|
-
set_env = { SPHINX_APIDOC_OPTIONS = "members,show-inheritance" }
|
|
215
|
+
dependency_groups = ["docs"]
|
|
215
216
|
commands = [
|
|
216
217
|
[
|
|
217
218
|
"python",
|
|
@@ -16,11 +16,7 @@ from ffsim.linalg.double_factorized_decomposition import (
|
|
|
16
16
|
double_factorized_t2_alpha_beta,
|
|
17
17
|
modified_cholesky,
|
|
18
18
|
)
|
|
19
|
-
from ffsim.linalg.givens import
|
|
20
|
-
GivensRotation,
|
|
21
|
-
apply_matrix_to_slices,
|
|
22
|
-
givens_decomposition,
|
|
23
|
-
)
|
|
19
|
+
from ffsim.linalg.givens import apply_matrix_to_slices, givens_decomposition
|
|
24
20
|
from ffsim.linalg.linalg import (
|
|
25
21
|
expm_multiply_taylor,
|
|
26
22
|
lup,
|
|
@@ -38,7 +34,6 @@ from ffsim.linalg.predicates import (
|
|
|
38
34
|
)
|
|
39
35
|
|
|
40
36
|
__all__ = [
|
|
41
|
-
"GivensRotation",
|
|
42
37
|
"apply_matrix_to_slices",
|
|
43
38
|
"double_factorized",
|
|
44
39
|
"double_factorized_t2",
|
|
@@ -12,37 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
-
import cmath
|
|
16
|
-
from typing import NamedTuple
|
|
17
|
-
|
|
18
15
|
import numpy as np
|
|
19
|
-
from scipy.linalg.blas import zrotg as zrotg_
|
|
20
16
|
|
|
21
17
|
from ffsim import _lib
|
|
22
18
|
|
|
23
19
|
|
|
24
|
-
class GivensRotation(NamedTuple):
|
|
25
|
-
r"""A Givens rotation.
|
|
26
|
-
|
|
27
|
-
A Givens rotation acts on the two-dimensional subspace spanned by the :math:`i`-th
|
|
28
|
-
and :math:`j`-th basis vectors as
|
|
29
|
-
|
|
30
|
-
.. math::
|
|
31
|
-
|
|
32
|
-
\begin{pmatrix}
|
|
33
|
-
c & s \\
|
|
34
|
-
-s^* & c \\
|
|
35
|
-
\end{pmatrix}
|
|
36
|
-
|
|
37
|
-
where :math:`c` is a real number and :math:`s` is a complex number.
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
c: float
|
|
41
|
-
s: complex
|
|
42
|
-
i: int
|
|
43
|
-
j: int
|
|
44
|
-
|
|
45
|
-
|
|
46
20
|
def apply_matrix_to_slices(
|
|
47
21
|
target: np.ndarray,
|
|
48
22
|
mat: np.ndarray,
|
|
@@ -73,24 +47,6 @@ def apply_matrix_to_slices(
|
|
|
73
47
|
return out
|
|
74
48
|
|
|
75
49
|
|
|
76
|
-
def zrotg(a: complex, b: complex, tol=1e-12) -> tuple[float, complex]:
|
|
77
|
-
r"""Safe version of the zrotg BLAS function.
|
|
78
|
-
|
|
79
|
-
The BLAS implementation of zrotg can return NaN values if either a or b is very
|
|
80
|
-
close to zero. This function detects if either a or b is close to zero up to the
|
|
81
|
-
specified tolerance, in which case it behaves as if it were exactly zero.
|
|
82
|
-
|
|
83
|
-
Note that in contrast to ``scipy.linalg.blas.zrotg``, this function returns c as a
|
|
84
|
-
float rather than a complex.
|
|
85
|
-
"""
|
|
86
|
-
if cmath.isclose(b, 0.0, abs_tol=tol):
|
|
87
|
-
return 1.0, 0j
|
|
88
|
-
if cmath.isclose(a, 0.0, abs_tol=tol):
|
|
89
|
-
return 0.0, 1 + 0j
|
|
90
|
-
c, s = zrotg_(a, b)
|
|
91
|
-
return c.real, s
|
|
92
|
-
|
|
93
|
-
|
|
94
50
|
def givens_decomposition(
|
|
95
51
|
mat: np.ndarray, tol: float = 1e-12
|
|
96
52
|
) -> tuple[list[tuple[float, complex, int, int]], np.ndarray]:
|
|
@@ -46,6 +46,7 @@ class SimulateTrotterDiagCoulombSplitOpJW(Gate):
|
|
|
46
46
|
*,
|
|
47
47
|
n_steps: int = 1,
|
|
48
48
|
order: int = 0,
|
|
49
|
+
tol: float = 1e-12,
|
|
49
50
|
label: str | None = None,
|
|
50
51
|
):
|
|
51
52
|
r"""Create diagonal Coulomb split-operator Trotter evolution gate.
|
|
@@ -56,6 +57,8 @@ class SimulateTrotterDiagCoulombSplitOpJW(Gate):
|
|
|
56
57
|
time: The evolution time.
|
|
57
58
|
n_steps: The number of Trotter steps.
|
|
58
59
|
order: The order of the Trotter decomposition.
|
|
60
|
+
tol: Tolerance for the Givens decomposition of the orbital rotations.
|
|
61
|
+
Matrix entries smaller than this value will be treated as equal to zero.
|
|
59
62
|
label: The label of the gate.
|
|
60
63
|
"""
|
|
61
64
|
if order < 0:
|
|
@@ -66,6 +69,7 @@ class SimulateTrotterDiagCoulombSplitOpJW(Gate):
|
|
|
66
69
|
self.time = time
|
|
67
70
|
self.n_steps = n_steps
|
|
68
71
|
self.order = order
|
|
72
|
+
self.tol = tol
|
|
69
73
|
super().__init__(
|
|
70
74
|
"dc_trotter_split_op_jw", 2 * self.hamiltonian.norb, [], label=label
|
|
71
75
|
)
|
|
@@ -80,6 +84,7 @@ class SimulateTrotterDiagCoulombSplitOpJW(Gate):
|
|
|
80
84
|
time=self.time,
|
|
81
85
|
n_steps=self.n_steps,
|
|
82
86
|
order=self.order,
|
|
87
|
+
tol=self.tol,
|
|
83
88
|
),
|
|
84
89
|
qubits=qubits,
|
|
85
90
|
)
|
|
@@ -91,6 +96,7 @@ def _simulate_trotter_diag_coulomb_split_op(
|
|
|
91
96
|
time: float,
|
|
92
97
|
n_steps: int = 1,
|
|
93
98
|
order: int = 0,
|
|
99
|
+
tol: float = 1e-12,
|
|
94
100
|
) -> Iterator[CircuitInstruction]:
|
|
95
101
|
if n_steps == 0:
|
|
96
102
|
return
|
|
@@ -106,10 +112,11 @@ def _simulate_trotter_diag_coulomb_split_op(
|
|
|
106
112
|
step_time,
|
|
107
113
|
norb=hamiltonian.norb,
|
|
108
114
|
order=order,
|
|
115
|
+
tol=tol,
|
|
109
116
|
)
|
|
110
117
|
if not np.all(np.diagonal(current_basis) == 1):
|
|
111
118
|
yield CircuitInstruction(
|
|
112
|
-
OrbitalRotationJW(hamiltonian.norb, current_basis), qubits
|
|
119
|
+
OrbitalRotationJW(hamiltonian.norb, current_basis, tol=tol), qubits
|
|
113
120
|
)
|
|
114
121
|
yield CircuitInstruction(GlobalPhaseGate(-time * hamiltonian.constant), [])
|
|
115
122
|
|
|
@@ -122,6 +129,7 @@ def _simulate_trotter_step_diag_coulomb_split_op(
|
|
|
122
129
|
time: float,
|
|
123
130
|
norb: int,
|
|
124
131
|
order: int,
|
|
132
|
+
tol: float = 1e-12,
|
|
125
133
|
) -> Generator[CircuitInstruction, None, np.ndarray]:
|
|
126
134
|
diag_coulomb_aa, diag_coulomb_ab = diag_coulomb_mats
|
|
127
135
|
eye = np.eye(norb)
|
|
@@ -131,7 +139,9 @@ def _simulate_trotter_step_diag_coulomb_split_op(
|
|
|
131
139
|
scipy.linalg.expm(-1j * time * one_body_tensor) @ current_basis
|
|
132
140
|
)
|
|
133
141
|
else:
|
|
134
|
-
yield CircuitInstruction(
|
|
142
|
+
yield CircuitInstruction(
|
|
143
|
+
OrbitalRotationJW(norb, current_basis, tol=tol), qubits
|
|
144
|
+
)
|
|
135
145
|
yield CircuitInstruction(
|
|
136
146
|
DiagCoulombEvolutionJW(
|
|
137
147
|
norb,
|
|
@@ -46,6 +46,7 @@ class SimulateTrotterDoubleFactorizedJW(Gate):
|
|
|
46
46
|
*,
|
|
47
47
|
n_steps: int = 1,
|
|
48
48
|
order: int = 0,
|
|
49
|
+
tol: float = 1e-12,
|
|
49
50
|
label: str | None = None,
|
|
50
51
|
):
|
|
51
52
|
r"""Create double-factorized Trotter evolution gate.
|
|
@@ -56,6 +57,8 @@ class SimulateTrotterDoubleFactorizedJW(Gate):
|
|
|
56
57
|
time: The evolution time.
|
|
57
58
|
n_steps: The number of Trotter steps.
|
|
58
59
|
order: The order of the Trotter decomposition.
|
|
60
|
+
tol: Tolerance for the Givens decomposition of the orbital rotations.
|
|
61
|
+
Matrix entries smaller than this value will be treated as equal to zero.
|
|
59
62
|
label: The label of the gate.
|
|
60
63
|
"""
|
|
61
64
|
if order < 0:
|
|
@@ -66,6 +69,7 @@ class SimulateTrotterDoubleFactorizedJW(Gate):
|
|
|
66
69
|
self.time = time
|
|
67
70
|
self.n_steps = n_steps
|
|
68
71
|
self.order = order
|
|
72
|
+
self.tol = tol
|
|
69
73
|
super().__init__("df_trotter_jw", 2 * self.hamiltonian.norb, [], label=label)
|
|
70
74
|
|
|
71
75
|
def _define(self):
|
|
@@ -78,6 +82,7 @@ class SimulateTrotterDoubleFactorizedJW(Gate):
|
|
|
78
82
|
time=self.time,
|
|
79
83
|
n_steps=self.n_steps,
|
|
80
84
|
order=self.order,
|
|
85
|
+
tol=self.tol,
|
|
81
86
|
),
|
|
82
87
|
qubits=qubits,
|
|
83
88
|
)
|
|
@@ -89,6 +94,7 @@ def _simulate_trotter_double_factorized(
|
|
|
89
94
|
time: float,
|
|
90
95
|
n_steps: int = 1,
|
|
91
96
|
order: int = 0,
|
|
97
|
+
tol: float = 1e-12,
|
|
92
98
|
) -> Iterator[CircuitInstruction]:
|
|
93
99
|
if n_steps == 0:
|
|
94
100
|
return
|
|
@@ -106,10 +112,11 @@ def _simulate_trotter_double_factorized(
|
|
|
106
112
|
norb=hamiltonian.norb,
|
|
107
113
|
order=order,
|
|
108
114
|
z_representation=hamiltonian.z_representation,
|
|
115
|
+
tol=tol,
|
|
109
116
|
)
|
|
110
117
|
if not np.all(np.diagonal(current_basis) == 1):
|
|
111
118
|
yield CircuitInstruction(
|
|
112
|
-
OrbitalRotationJW(hamiltonian.norb, current_basis), qubits
|
|
119
|
+
OrbitalRotationJW(hamiltonian.norb, current_basis, tol=tol), qubits
|
|
113
120
|
)
|
|
114
121
|
yield CircuitInstruction(GlobalPhaseGate(-time * hamiltonian.constant), [])
|
|
115
122
|
|
|
@@ -124,6 +131,7 @@ def _simulate_trotter_step_double_factorized(
|
|
|
124
131
|
norb: int,
|
|
125
132
|
order: int,
|
|
126
133
|
z_representation: bool,
|
|
134
|
+
tol: float = 1e-12,
|
|
127
135
|
) -> Generator[CircuitInstruction, None, np.ndarray]:
|
|
128
136
|
for term_index, time in simulate_trotter_step_iterator(
|
|
129
137
|
1 + len(diag_coulomb_mats), time, order
|
|
@@ -135,7 +143,9 @@ def _simulate_trotter_step_double_factorized(
|
|
|
135
143
|
else:
|
|
136
144
|
orbital_rotation = orbital_rotations[term_index - 1]
|
|
137
145
|
yield CircuitInstruction(
|
|
138
|
-
OrbitalRotationJW(
|
|
146
|
+
OrbitalRotationJW(
|
|
147
|
+
norb, orbital_rotation.T.conj() @ current_basis, tol=tol
|
|
148
|
+
),
|
|
139
149
|
qubits,
|
|
140
150
|
)
|
|
141
151
|
yield CircuitInstruction(
|
|
@@ -44,35 +44,42 @@ class UCJOpSpinBalancedJW(Gate):
|
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
46
|
def __init__(
|
|
47
|
-
self,
|
|
47
|
+
self,
|
|
48
|
+
ucj_op: variational.UCJOpSpinBalanced,
|
|
49
|
+
*,
|
|
50
|
+
tol: float = 1e-12,
|
|
51
|
+
label: str | None = None,
|
|
48
52
|
):
|
|
49
53
|
"""Create a new spin-balanced unitary cluster Jastrow (UCJ) gate.
|
|
50
54
|
|
|
51
55
|
Args:
|
|
52
56
|
ucj_op: The UCJ operator.
|
|
57
|
+
tol: Tolerance for the Givens decomposition of the orbital rotations.
|
|
58
|
+
Matrix entries smaller than this value will be treated as equal to zero.
|
|
53
59
|
label: The label of the gate.
|
|
54
60
|
"""
|
|
55
61
|
self.ucj_op = ucj_op
|
|
62
|
+
self.tol = tol
|
|
56
63
|
super().__init__("ucj_balanced_jw", 2 * ucj_op.norb, [], label=label)
|
|
57
64
|
|
|
58
65
|
def _define(self):
|
|
59
66
|
"""Gate decomposition."""
|
|
60
67
|
qubits = QuantumRegister(self.num_qubits)
|
|
61
68
|
self.definition = QuantumCircuit.from_instructions(
|
|
62
|
-
_ucj_op_spin_balanced_jw(qubits, self.ucj_op),
|
|
69
|
+
_ucj_op_spin_balanced_jw(qubits, self.ucj_op, tol=self.tol),
|
|
63
70
|
qubits=qubits,
|
|
64
71
|
name=self.name,
|
|
65
72
|
)
|
|
66
73
|
|
|
67
74
|
|
|
68
75
|
def _ucj_op_spin_balanced_jw(
|
|
69
|
-
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinBalanced
|
|
76
|
+
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinBalanced, tol: float = 1e-12
|
|
70
77
|
) -> Iterator[CircuitInstruction]:
|
|
71
78
|
for (diag_coulomb_mat_aa, diag_coulomb_mat_ab), orbital_rotation in zip(
|
|
72
79
|
ucj_op.diag_coulomb_mats, ucj_op.orbital_rotations
|
|
73
80
|
):
|
|
74
81
|
yield CircuitInstruction(
|
|
75
|
-
OrbitalRotationJW(ucj_op.norb, orbital_rotation.T.conj()),
|
|
82
|
+
OrbitalRotationJW(ucj_op.norb, orbital_rotation.T.conj(), tol=tol),
|
|
76
83
|
qubits,
|
|
77
84
|
)
|
|
78
85
|
yield CircuitInstruction(
|
|
@@ -84,11 +91,12 @@ def _ucj_op_spin_balanced_jw(
|
|
|
84
91
|
qubits,
|
|
85
92
|
)
|
|
86
93
|
yield CircuitInstruction(
|
|
87
|
-
OrbitalRotationJW(ucj_op.norb, orbital_rotation), qubits
|
|
94
|
+
OrbitalRotationJW(ucj_op.norb, orbital_rotation, tol=tol), qubits
|
|
88
95
|
)
|
|
89
96
|
if ucj_op.final_orbital_rotation is not None:
|
|
90
97
|
yield CircuitInstruction(
|
|
91
|
-
OrbitalRotationJW(ucj_op.norb, ucj_op.final_orbital_rotation),
|
|
98
|
+
OrbitalRotationJW(ucj_op.norb, ucj_op.final_orbital_rotation, tol=tol),
|
|
99
|
+
qubits,
|
|
92
100
|
)
|
|
93
101
|
|
|
94
102
|
|
|
@@ -103,35 +111,44 @@ class UCJOpSpinUnbalancedJW(Gate):
|
|
|
103
111
|
"""
|
|
104
112
|
|
|
105
113
|
def __init__(
|
|
106
|
-
self,
|
|
114
|
+
self,
|
|
115
|
+
ucj_op: variational.UCJOpSpinUnbalanced,
|
|
116
|
+
*,
|
|
117
|
+
tol: float = 1e-12,
|
|
118
|
+
label: str | None = None,
|
|
107
119
|
):
|
|
108
120
|
"""Create a new spin-unbalanced unitary cluster Jastrow (UCJ) gate.
|
|
109
121
|
|
|
110
122
|
Args:
|
|
111
123
|
ucj_op: The UCJ operator.
|
|
124
|
+
tol: Tolerance for the Givens decomposition of the orbital rotations.
|
|
125
|
+
Matrix entries smaller than this value will be treated as equal to zero.
|
|
112
126
|
label: The label of the gate.
|
|
113
127
|
"""
|
|
114
128
|
self.ucj_op = ucj_op
|
|
129
|
+
self.tol = tol
|
|
115
130
|
super().__init__("ucj_unbalanced_jw", 2 * ucj_op.norb, [], label=label)
|
|
116
131
|
|
|
117
132
|
def _define(self):
|
|
118
133
|
"""Gate decomposition."""
|
|
119
134
|
qubits = QuantumRegister(self.num_qubits)
|
|
120
135
|
self.definition = QuantumCircuit.from_instructions(
|
|
121
|
-
_ucj_op_spin_unbalanced_jw(qubits, self.ucj_op),
|
|
136
|
+
_ucj_op_spin_unbalanced_jw(qubits, self.ucj_op, tol=self.tol),
|
|
122
137
|
qubits=qubits,
|
|
123
138
|
name=self.name,
|
|
124
139
|
)
|
|
125
140
|
|
|
126
141
|
|
|
127
142
|
def _ucj_op_spin_unbalanced_jw(
|
|
128
|
-
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinUnbalanced
|
|
143
|
+
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinUnbalanced, tol: float = 1e-12
|
|
129
144
|
) -> Iterator[CircuitInstruction]:
|
|
130
145
|
for diag_colomb_mat, orbital_rotation in zip(
|
|
131
146
|
ucj_op.diag_coulomb_mats, ucj_op.orbital_rotations
|
|
132
147
|
):
|
|
133
148
|
yield CircuitInstruction(
|
|
134
|
-
OrbitalRotationJW(
|
|
149
|
+
OrbitalRotationJW(
|
|
150
|
+
ucj_op.norb, orbital_rotation.transpose(0, 2, 1).conj(), tol=tol
|
|
151
|
+
),
|
|
135
152
|
qubits,
|
|
136
153
|
)
|
|
137
154
|
yield CircuitInstruction(
|
|
@@ -139,11 +156,12 @@ def _ucj_op_spin_unbalanced_jw(
|
|
|
139
156
|
qubits,
|
|
140
157
|
)
|
|
141
158
|
yield CircuitInstruction(
|
|
142
|
-
OrbitalRotationJW(ucj_op.norb, orbital_rotation), qubits
|
|
159
|
+
OrbitalRotationJW(ucj_op.norb, orbital_rotation, tol=tol), qubits
|
|
143
160
|
)
|
|
144
161
|
if ucj_op.final_orbital_rotation is not None:
|
|
145
162
|
yield CircuitInstruction(
|
|
146
|
-
OrbitalRotationJW(ucj_op.norb, ucj_op.final_orbital_rotation),
|
|
163
|
+
OrbitalRotationJW(ucj_op.norb, ucj_op.final_orbital_rotation, tol=tol),
|
|
164
|
+
qubits,
|
|
147
165
|
)
|
|
148
166
|
|
|
149
167
|
|
|
@@ -153,34 +171,43 @@ class UCJOpSpinlessJW(Gate):
|
|
|
153
171
|
See :class:`ffsim.UCJOpSpinless` for a description of this gate's unitary.
|
|
154
172
|
"""
|
|
155
173
|
|
|
156
|
-
def __init__(
|
|
174
|
+
def __init__(
|
|
175
|
+
self,
|
|
176
|
+
ucj_op: variational.UCJOpSpinless,
|
|
177
|
+
*,
|
|
178
|
+
tol: float = 1e-12,
|
|
179
|
+
label: str | None = None,
|
|
180
|
+
):
|
|
157
181
|
"""Create a new spinless unitary cluster Jastrow (UCJ) gate.
|
|
158
182
|
|
|
159
183
|
Args:
|
|
160
184
|
ucj_op: The UCJ operator.
|
|
185
|
+
tol: Tolerance for the Givens decomposition of the orbital rotations.
|
|
186
|
+
Matrix entries smaller than this value will be treated as equal to zero.
|
|
161
187
|
label: The label of the gate.
|
|
162
188
|
"""
|
|
163
189
|
self.ucj_op = ucj_op
|
|
190
|
+
self.tol = tol
|
|
164
191
|
super().__init__("ucj_spinless_jw", ucj_op.norb, [], label=label)
|
|
165
192
|
|
|
166
193
|
def _define(self):
|
|
167
194
|
"""Gate decomposition."""
|
|
168
195
|
qubits = QuantumRegister(self.num_qubits)
|
|
169
196
|
self.definition = QuantumCircuit.from_instructions(
|
|
170
|
-
_ucj_op_spinless_jw(qubits, self.ucj_op),
|
|
197
|
+
_ucj_op_spinless_jw(qubits, self.ucj_op, tol=self.tol),
|
|
171
198
|
qubits=qubits,
|
|
172
199
|
name=self.name,
|
|
173
200
|
)
|
|
174
201
|
|
|
175
202
|
|
|
176
203
|
def _ucj_op_spinless_jw(
|
|
177
|
-
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinless
|
|
204
|
+
qubits: Sequence[Qubit], ucj_op: variational.UCJOpSpinless, tol: float = 1e-12
|
|
178
205
|
) -> Iterator[CircuitInstruction]:
|
|
179
206
|
for diag_coulomb_mat, orbital_rotation in zip(
|
|
180
207
|
ucj_op.diag_coulomb_mats, ucj_op.orbital_rotations
|
|
181
208
|
):
|
|
182
209
|
yield CircuitInstruction(
|
|
183
|
-
OrbitalRotationSpinlessJW(ucj_op.norb, orbital_rotation.T.conj()),
|
|
210
|
+
OrbitalRotationSpinlessJW(ucj_op.norb, orbital_rotation.T.conj(), tol=tol),
|
|
184
211
|
qubits,
|
|
185
212
|
)
|
|
186
213
|
yield CircuitInstruction(
|
|
@@ -188,10 +215,12 @@ def _ucj_op_spinless_jw(
|
|
|
188
215
|
qubits,
|
|
189
216
|
)
|
|
190
217
|
yield CircuitInstruction(
|
|
191
|
-
OrbitalRotationSpinlessJW(ucj_op.norb, orbital_rotation), qubits
|
|
218
|
+
OrbitalRotationSpinlessJW(ucj_op.norb, orbital_rotation, tol=tol), qubits
|
|
192
219
|
)
|
|
193
220
|
if ucj_op.final_orbital_rotation is not None:
|
|
194
221
|
yield CircuitInstruction(
|
|
195
|
-
OrbitalRotationSpinlessJW(
|
|
222
|
+
OrbitalRotationSpinlessJW(
|
|
223
|
+
ucj_op.norb, ucj_op.final_orbital_rotation, tol=tol
|
|
224
|
+
),
|
|
196
225
|
qubits,
|
|
197
226
|
)
|
|
@@ -405,18 +405,16 @@ def spectral_norm_diag_coulomb(
|
|
|
405
405
|
# decompose the diag Coulomb mat as a sum of squared one-body operators
|
|
406
406
|
one_body_tensors = one_body_square_decomposition(diag_coulomb_mat)
|
|
407
407
|
|
|
408
|
-
# for a rank-1 diag Coulomb mat, we can compute the exact spectral norm
|
|
408
|
+
# for a rank-1 diag Coulomb mat, we can compute the exact spectral norm in the
|
|
409
|
+
# number representation. In the Z representation we return an upper bound instead.
|
|
409
410
|
if len(one_body_tensors) == 1:
|
|
410
411
|
one_body_tensor = one_body_tensors[0]
|
|
411
412
|
if z_representation:
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
spectral_norm_one_body_tensor(
|
|
415
|
-
one_body_tensor, nelec=nelec, z_representation=True
|
|
416
|
-
)
|
|
417
|
-
** 2
|
|
418
|
-
- 0.25 * np.trace(diag_coulomb_mat)
|
|
413
|
+
norm_bound = spectral_norm_one_body_tensor(
|
|
414
|
+
one_body_tensor, nelec=nelec, z_representation=True
|
|
419
415
|
)
|
|
416
|
+
quarter_trace = 0.25 * np.trace(diag_coulomb_mat)
|
|
417
|
+
return max(quarter_trace, norm_bound**2 - quarter_trace)
|
|
420
418
|
return spectral_norm_one_body_tensor(one_body_tensor, nelec=nelec) ** 2
|
|
421
419
|
|
|
422
420
|
# when the rank is greater than one, we only know how to return an upper bound
|
|
@@ -527,6 +527,8 @@ class UCJOpSpinUnbalanced(
|
|
|
527
527
|
ValueError: Interaction pairs list contained duplicate interactions.
|
|
528
528
|
ValueError: Interaction pairs list for alpha-alpha or beta-beta interactions
|
|
529
529
|
contained lower triangular pairs.
|
|
530
|
+
|
|
531
|
+
.. _scipy.optimize.minimize: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
|
|
530
532
|
"""
|
|
531
533
|
if isinstance(n_reps, int) and n_reps <= 0:
|
|
532
534
|
raise ValueError(f"n_reps must be at least 1. Got {n_reps}.")
|