ffsim 0.0.85__tar.gz → 0.0.86__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.85 → ffsim-0.0.86}/.github/workflows/build-and-release.yml +1 -1
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/test-latest-versions.yml +18 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/CONTRIBUTING.md +0 -2
- {ffsim-0.0.85 → ffsim-0.0.86}/PKG-INFO +4 -5
- {ffsim-0.0.85 → ffsim-0.0.86}/README.md +2 -2
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/fermionic-fft.ipynb +34 -39
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/install.md +3 -8
- {ffsim-0.0.85 → ffsim-0.0.86}/pyproject.toml +4 -5
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_cistring.py +1 -1
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/orbital_rotation.py +2 -2
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/hamiltonians/molecular_hamiltonian.py +0 -31
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/double_factorized_decomposition.py +70 -572
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/molecular_data.py +7 -3
- ffsim-0.0.86/python/ffsim/variational/ucj_angles_spin_balanced.py +648 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/hamiltonians/molecular_hamiltonian_test.py +0 -16
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/linalg/double_factorized_decomposition_test.py +13 -277
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/molecular_data_test.py +1 -1
- ffsim-0.0.86/tests/python/variational/ucj_angles_spin_balanced_test.py +500 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/uv.lock +147 -148
- ffsim-0.0.85/python/ffsim/variational/ucj_angles_spin_balanced.py +0 -260
- ffsim-0.0.85/tests/python/variational/ucj_angles_spin_balanced_test.py +0 -236
- {ffsim-0.0.85 → ffsim-0.0.86}/.cargo/config.toml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.dockerignore +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/check.yml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/docker.yml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/docs-dev.yml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/docs-release.yml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.github/workflows/test-minimum-versions.yml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.gitignore +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/.pre-commit-config.yaml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/Cargo.lock +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/Cargo.toml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/Dockerfile +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/LICENSE +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/compose.yaml +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/_static/logo-dark.svg +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/_static/logo.svg +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/_templates/autosummary/class.rst +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/conf.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/execute_notebooks.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/diag-coulomb-hamiltonian.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/double-factorized.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/fermion-operator.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/hamiltonians.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/index.md +1 -1
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/lucj.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/orbital-rotation.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/protocols.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/qubit-gate-decompositions.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/state-vectors-and-gates.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/explanations/variational-ansatzes.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/generate_api_docs.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/compress-orbital-rotation.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/compute-expectation-values.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/entanglement-forging.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/index.md +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/optimize-orbitals.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/qiskit-circuits-sim.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/qiskit-lucj.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/qiskit-merge-orbital-rotations.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/qiskit-trotter.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/sample-from-state-vectors.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/sample-slater.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/simulate-trotter-hubbard.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/simulate-trotter-mol-ham.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/simulate-vqe.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/how-to-guides/ucj-energy.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/index.md +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/tutorials/create-variational-ansatz.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/tutorials/double-factorized-trotter.ipynb +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/docs/tutorials/index.md +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_lib.pyi +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/contract/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/contract/diag_coulomb.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/contract/num_op_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/fermion_operator.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/gates/num_op_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/_slow/gates/orbital_rotation.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/contract/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/contract/diag_coulomb.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/contract/num_op_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/contract/one_body.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/contract/two_body.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/basic_gates.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/num_op_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/gates/quad_ham.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/hamiltonians/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/hamiltonians/diagonal_coulomb_hamiltonian.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/hamiltonians/double_factorized_hamiltonian.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/hamiltonians/single_factorized_hamiltonian.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/init_cache.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/givens.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/linalg.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/predicates.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/linalg/util.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/common_operators.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/coupled_cluster.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/fermi_hubbard.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/fermion_action.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/operators/fermion_operator.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/optimize/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/optimize/_util.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/optimize/linear_method.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/apply_unitary_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/approximate_equality_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/diagonal_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/fermion_operator_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/linear_operator_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/protocols/trace_protocol.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/py.typed +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/diag_coulomb.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/diag_coulomb_trotter_split_op.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/double_factorized_trotter.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/fermionic_fft.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/givens_ansatz.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/num_num_ansatz.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/num_op_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/orbital_rotation.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/slater_determinant.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/gates/ucj.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/jordan_wigner.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/lucj_pass_manager.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/sampler.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/sim.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/transpiler_passes/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/transpiler_passes/drop_negligible.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/transpiler_passes/merge_orbital_rotations.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/transpiler_stages.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/qiskit/util.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/random/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/random/random.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/bitstring.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/dimensions.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/product_state_sum.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/rdm.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/sample_slater.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/slater.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/spin.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/states.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/states/wick.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/testing/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/testing/testing.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/trotter/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/trotter/_util.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/trotter/diagonal_coulomb_split_op.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/trotter/double_factorized.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/trotter/qdrift.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/givens.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/hopgate.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/multireference.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/num_num.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/orbital_optimization.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/uccsd.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/ucj_energy.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/ucj_spin_balanced.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/ucj_spin_unbalanced.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/ucj_spinless.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/python/ffsim/variational/util.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/contract/diag_coulomb.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/contract/fermion_operator.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/contract/mod.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/contract/num_op_sum.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/fermion_operator.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/gates/diag_coulomb.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/gates/mod.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/gates/num_op_sum.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/gates/orbital_rotation.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/gates/phase_shift.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/jordan_wigner.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/lib.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/linalg/givens.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/src/linalg/mod.rs +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/contract/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/contract/diag_coulomb_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/contract/num_op_sum_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/gates/diag_coulomb_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/gates/num_op_sum_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/_slow/gates/orbital_rotation_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/conftest.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/contract/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/contract/diag_coulomb_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/contract/num_op_sum_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/contract/two_body_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/basic_gates_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/diag_coulomb_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/num_op_sum_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/orbital_rotation_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/gates/quad_ham_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/hamiltonians/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/hamiltonians/diagonal_coulomb_hamiltonian_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/hamiltonians/double_factorized_hamiltonian_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/hamiltonians/single_factorized_hamiltonian_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/import_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/linalg/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/linalg/givens_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/linalg/linalg_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/linalg/util_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/common_operators_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/coupled_cluster_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/fermi_hubbard_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/fermion_action_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/operators/fermion_operator_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/optimize/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/optimize/linear_method_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/protocols/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/protocols/trace_protocol_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/diag_coulomb_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/diag_coulomb_trotter_split_op_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/double_factorized_trotter_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/fermionic_fft_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/givens_ansatz_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/num_num_ansatz_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/num_op_sum_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/orbital_rotation_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/slater_determinant_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/gates/ucj_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/jordan_wigner_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/lazy_import_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/lucj_pass_manager_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/sampler_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/sim_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/transpiler_passes/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/transpiler_passes/drop_negligible_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/transpiler_passes/merge_orbital_rotations_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/qiskit/util_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/random_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/bitstring_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/rdm_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/sample_slater_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/slater_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/states_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/states/wick_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/test_data/orbital_rotation-0.npy +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/test_no_warnings.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/testing_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/trotter/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/trotter/diag_coulomb_split_op_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/trotter/double_factorized_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/trotter/qdrift_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/__init__.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/givens_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/hopgate_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/multireference_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/num_num_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/orbital_optimization_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/uccsd_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/ucj_energy_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/ucj_spin_balanced_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/ucj_spin_unbalanced_test.py +0 -0
- {ffsim-0.0.85 → ffsim-0.0.86}/tests/python/variational/ucj_spinless_test.py +0 -0
|
@@ -67,3 +67,21 @@ jobs:
|
|
|
67
67
|
- name: Run tests
|
|
68
68
|
run: |
|
|
69
69
|
tox run -e test-${{ matrix.python-version }}
|
|
70
|
+
test-windows:
|
|
71
|
+
runs-on: windows-latest
|
|
72
|
+
strategy:
|
|
73
|
+
matrix:
|
|
74
|
+
python-version: ["3.11", "3.14"]
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/checkout@v6
|
|
77
|
+
- name: Set up Python
|
|
78
|
+
uses: actions/setup-python@v6
|
|
79
|
+
with:
|
|
80
|
+
python-version: ${{ matrix.python-version }}
|
|
81
|
+
- name: Install tox
|
|
82
|
+
run: |
|
|
83
|
+
python -m pip install --upgrade pip
|
|
84
|
+
pip install tox
|
|
85
|
+
- name: Run tests
|
|
86
|
+
run: |
|
|
87
|
+
tox run -e test-${{ matrix.python-version }}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# Developer guide
|
|
2
2
|
|
|
3
|
-
The instructions on this page won't work natively on Windows. For ffsim development on Windows, we recommend using [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) and doing development within the WSL.
|
|
4
|
-
|
|
5
3
|
## Setup
|
|
6
4
|
|
|
7
5
|
To set up ffsim for development, install it from source in editable mode along with the development requirements:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ffsim
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.86
|
|
4
4
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
5
5
|
Classifier: Programming Language :: Python
|
|
6
6
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -16,9 +16,8 @@ Requires-Dist: jax
|
|
|
16
16
|
Requires-Dist: numpy
|
|
17
17
|
Requires-Dist: opt-einsum
|
|
18
18
|
Requires-Dist: orjson
|
|
19
|
-
Requires-Dist: pyscf>=2.
|
|
19
|
+
Requires-Dist: pyscf>=2.15
|
|
20
20
|
Requires-Dist: scipy
|
|
21
|
-
Requires-Dist: typing-extensions
|
|
22
21
|
Requires-Dist: jax[cuda12] ; extra == 'cuda12'
|
|
23
22
|
Requires-Dist: jax[cuda13] ; extra == 'cuda13'
|
|
24
23
|
Requires-Dist: qiskit>=2.0,<3 ; extra == 'qiskit'
|
|
@@ -48,13 +47,13 @@ Documentation is located at the [project website](https://qiskit-community.githu
|
|
|
48
47
|
|
|
49
48
|
<!-- start installation -->
|
|
50
49
|
|
|
51
|
-
|
|
50
|
+
You can install ffsim using pip:
|
|
52
51
|
|
|
53
52
|
```bash
|
|
54
53
|
pip install ffsim
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for
|
|
56
|
+
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for more details, including instructions for installing from source and running ffsim in a container.
|
|
58
57
|
|
|
59
58
|
<!-- end installation -->
|
|
60
59
|
|
|
@@ -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
|
+
You can install ffsim using pip:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
20
|
pip install ffsim
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for
|
|
23
|
+
See the [installation instructions](https://qiskit-community.github.io/ffsim/install.html) for more details, including instructions for installing from source and running ffsim in a container.
|
|
24
24
|
|
|
25
25
|
<!-- end installation -->
|
|
26
26
|
|
|
@@ -6,13 +6,15 @@
|
|
|
6
6
|
"source": [
|
|
7
7
|
"# Fermionic fast Fourier transform\n",
|
|
8
8
|
"\n",
|
|
9
|
-
"
|
|
9
|
+
"This page explains the fermionic fast Fourier transform, an efficient quantum circuit for the discrete Fourier transform on fermionic modes.\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"The discrete Fourier transform on fermionic creation operators is defined as\n",
|
|
10
12
|
"\n",
|
|
11
13
|
"$$\n",
|
|
12
14
|
"a^\\dagger_k \\mapsto \\frac{1}{\\sqrt{N}} \\sum_{n=0}^{N-1} e^{-i 2\\pi k n / N} a^\\dagger_n\n",
|
|
13
15
|
"$$\n",
|
|
14
16
|
"\n",
|
|
15
|
-
"This is an [orbital rotation](orbital-rotation.ipynb) whose matrix is the unitary DFT matrix $
|
|
17
|
+
"This is an [orbital rotation](orbital-rotation.ipynb) whose matrix is the unitary DFT matrix $\\mathbf{F}_N$ with entries $(\\mathbf{F}_N)_{kn} = \\omega_N^{kn} / \\sqrt{N}$, where $\\omega_N = e^{-i 2\\pi / N}$. Rather than decomposing $\\mathbf{F}_N$ directly into Givens rotations, the **fermionic fast Fourier transform (FFFT)** uses the [Cooley-Tukey](https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm) algorithm to break it into DFTs of prime size."
|
|
16
18
|
]
|
|
17
19
|
},
|
|
18
20
|
{
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
"source": [
|
|
22
24
|
"## Mixed-radix Cooley-Tukey algorithm\n",
|
|
23
25
|
"\n",
|
|
24
|
-
"The circuit follows the general factorization described in the [Variations](https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Variations) section of the Cooley-Tukey FFT algorithm Wikipedia page. First, $N$ is factored into primes using trial division
|
|
26
|
+
"The circuit follows the general factorization described in the [Variations](https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm#Variations) section of the Cooley-Tukey FFT algorithm Wikipedia page. First, $N$ is factored into primes using trial division. Writing $N = N_1 N_2$, where $N_2$ is the smallest prime factor, and splitting the input index as $n = N_1 n_2 + n_1$ and the output index as $k = N_2 k_1 + k_2$, the DFT becomes\n",
|
|
25
27
|
"\n",
|
|
26
28
|
"$$\n",
|
|
27
29
|
"X_{N_2 k_1 + k_2} =\n",
|
|
@@ -42,7 +44,7 @@
|
|
|
42
44
|
"\n",
|
|
43
45
|
"The recursion ends when the size is prime, in which case the DFT is implemented directly as an orbital rotation.\n",
|
|
44
46
|
"\n",
|
|
45
|
-
"Under the Jordan-Wigner transformation, a gate implementing an orbital rotation must act on a contiguous block of qubits, because a hopping term between two modes carries a string of $Z$ operators on all the qubits in between. The DFTs in steps 1 and 3 act on strided subsets of modes, so the circuit inserts fermionic mode permutations (themselves orbital rotations by permutation matrices) that bring each subset onto adjacent qubits before the DFTs are applied."
|
|
47
|
+
"Under the [Jordan-Wigner transformation](https://en.wikipedia.org/wiki/Jordan%E2%80%93Wigner_transformation), a gate implementing an orbital rotation must act on a contiguous block of qubits, because a hopping term between two modes carries a string of $Z$ operators on all the qubits in between. The DFTs in steps 1 and 3 act on strided subsets of modes, so the circuit inserts fermionic mode permutations (themselves orbital rotations by permutation matrices) that bring each subset onto adjacent qubits before the DFTs are applied."
|
|
46
48
|
]
|
|
47
49
|
},
|
|
48
50
|
{
|
|
@@ -51,7 +53,7 @@
|
|
|
51
53
|
"source": [
|
|
52
54
|
"## Quantum circuit implementation\n",
|
|
53
55
|
"\n",
|
|
54
|
-
"
|
|
56
|
+
"ffsim implements the FFFT under the Jordan-Wigner transformation with the [FermionicFFTSpinlessJW](../api/stubs/ffsim.qiskit.FermionicFFTSpinlessJW.rst#ffsim.qiskit.FermionicFFTSpinlessJW) gate for spinless fermions and the [FermionicFFTJW](../api/stubs/ffsim.qiskit.FermionicFFTJW.rst#ffsim.qiskit.FermionicFFTJW) gate for spinful fermions.\n",
|
|
55
57
|
"\n",
|
|
56
58
|
"The following code cell constructs and displays a Qiskit circuit for implementing the fermionic fast Fourier transform on $N = 6$ spatial orbitals, so $N_2 = 2$ and $N_1 = 3$. In the decomposed circuit you can see the mode permutations, the three size-2 DFTs of step 1 and the two size-3 DFTs of step 3 (as orbital rotations), and the twiddle-factor phase gates of step 2."
|
|
57
59
|
]
|
|
@@ -93,32 +95,20 @@
|
|
|
93
95
|
"cell_type": "markdown",
|
|
94
96
|
"metadata": {},
|
|
95
97
|
"source": [
|
|
96
|
-
"We can check that the circuit implements the DFT orbital rotation by comparing it against
|
|
98
|
+
"We can check that the circuit implements the DFT orbital rotation by comparing it against [apply_orbital_rotation](../api/stubs/ffsim.apply_orbital_rotation.rst#ffsim.apply_orbital_rotation) with the DFT matrix on a random state."
|
|
97
99
|
]
|
|
98
100
|
},
|
|
99
101
|
{
|
|
100
102
|
"cell_type": "code",
|
|
101
103
|
"execution_count": 2,
|
|
102
104
|
"metadata": {},
|
|
103
|
-
"outputs": [
|
|
104
|
-
{
|
|
105
|
-
"data": {
|
|
106
|
-
"text/plain": [
|
|
107
|
-
"True"
|
|
108
|
-
]
|
|
109
|
-
},
|
|
110
|
-
"execution_count": 2,
|
|
111
|
-
"metadata": {},
|
|
112
|
-
"output_type": "execute_result"
|
|
113
|
-
}
|
|
114
|
-
],
|
|
105
|
+
"outputs": [],
|
|
115
106
|
"source": [
|
|
116
107
|
"import numpy as np\n",
|
|
117
108
|
"import scipy.linalg\n",
|
|
118
109
|
"from qiskit.quantum_info import Statevector\n",
|
|
119
110
|
"\n",
|
|
120
|
-
"
|
|
121
|
-
"nelec = (nocc, 0)\n",
|
|
111
|
+
"nelec = 3 # spinless, so nelec is an integer\n",
|
|
122
112
|
"vec = ffsim.random.random_state_vector(ffsim.dim(norb, nelec), seed=1234)\n",
|
|
123
113
|
"\n",
|
|
124
114
|
"# Apply the FFFT circuit to the state\n",
|
|
@@ -130,14 +120,14 @@
|
|
|
130
120
|
"dft_mat = scipy.linalg.dft(norb, scale=\"sqrtn\")\n",
|
|
131
121
|
"expected = ffsim.apply_orbital_rotation(vec, dft_mat, norb=norb, nelec=nelec)\n",
|
|
132
122
|
"\n",
|
|
133
|
-
"np.
|
|
123
|
+
"np.testing.assert_allclose(result, expected)"
|
|
134
124
|
]
|
|
135
125
|
},
|
|
136
126
|
{
|
|
137
127
|
"cell_type": "markdown",
|
|
138
128
|
"metadata": {},
|
|
139
129
|
"source": [
|
|
140
|
-
"For spinful
|
|
130
|
+
"For spinful fermions, `FermionicFFTJW` acts on $2N$ qubits and applies the FFFT independently to the spin $\\alpha$ orbitals (the first $N$ qubits) and the spin $\\beta$ orbitals (the last $N$ qubits). The following code cell applies it to the Hartree-Fock state."
|
|
141
131
|
]
|
|
142
132
|
},
|
|
143
133
|
{
|
|
@@ -175,7 +165,7 @@
|
|
|
175
165
|
"source": [
|
|
176
166
|
"## Cost compared with a direct orbital rotation\n",
|
|
177
167
|
"\n",
|
|
178
|
-
"The DFT could also be implemented as a single orbital rotation by passing the DFT matrix to
|
|
168
|
+
"The DFT could also be implemented as a single orbital rotation by passing the DFT matrix to [OrbitalRotationSpinlessJW](../api/stubs/ffsim.qiskit.OrbitalRotationSpinlessJW.rst#ffsim.qiskit.OrbitalRotationSpinlessJW), which decomposes it directly into Givens rotations. The following code cell compiles both circuits to a basis of CZ, $R_Z$, $\\sqrt{X}$, and $X$ gates. For each one it reports the number of CZ gates, the number of $R_Z$ rotations whose angle is not a multiple of $\\pi/2$ (that is, the non-Clifford rotations), and how many distinct angles those rotations use."
|
|
179
169
|
]
|
|
180
170
|
},
|
|
181
171
|
{
|
|
@@ -187,28 +177,32 @@
|
|
|
187
177
|
"name": "stdout",
|
|
188
178
|
"output_type": "stream",
|
|
189
179
|
"text": [
|
|
190
|
-
"
|
|
191
|
-
"
|
|
192
|
-
" 8
|
|
193
|
-
"
|
|
194
|
-
"
|
|
195
|
-
"
|
|
180
|
+
" CZ gates non-Clifford Rz distinct angles \n",
|
|
181
|
+
" N FFFT direct FFFT direct FFFT direct\n",
|
|
182
|
+
" 4 14 12 8 18 1 6\n",
|
|
183
|
+
" 8 72 56 26 105 3 49\n",
|
|
184
|
+
" 16 328 240 74 465 7 175\n",
|
|
185
|
+
" 6 36 30 32 56 6 28\n",
|
|
186
|
+
" 12 174 132 80 253 7 104\n"
|
|
196
187
|
]
|
|
197
188
|
}
|
|
198
189
|
],
|
|
199
190
|
"source": [
|
|
200
191
|
"import math\n",
|
|
201
192
|
"\n",
|
|
202
|
-
"from qiskit import
|
|
193
|
+
"from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
|
|
203
194
|
"\n",
|
|
204
|
-
"basis_gates = [\"
|
|
195
|
+
"basis_gates = [\"cz\", \"id\", \"rz\", \"sx\", \"x\"]\n",
|
|
196
|
+
"pass_manager = generate_preset_pass_manager(\n",
|
|
197
|
+
" optimization_level=1, basis_gates=basis_gates\n",
|
|
198
|
+
")\n",
|
|
205
199
|
"\n",
|
|
206
200
|
"\n",
|
|
207
201
|
"def cost(gate) -> tuple[int, int, int]:\n",
|
|
208
|
-
" \"\"\"Return
|
|
202
|
+
" \"\"\"Return CZ count, non-Clifford Rz count, and number of distinct angles.\"\"\"\n",
|
|
209
203
|
" circuit = QuantumCircuit(gate.num_qubits)\n",
|
|
210
204
|
" circuit.append(gate, range(gate.num_qubits))\n",
|
|
211
|
-
" transpiled =
|
|
205
|
+
" transpiled = pass_manager.run(circuit)\n",
|
|
212
206
|
" angles = []\n",
|
|
213
207
|
" for instruction in transpiled.data:\n",
|
|
214
208
|
" if instruction.operation.name == \"rz\":\n",
|
|
@@ -216,17 +210,18 @@
|
|
|
216
210
|
" remainder = angle % (math.pi / 2)\n",
|
|
217
211
|
" if min(remainder, math.pi / 2 - remainder) > 1e-8:\n",
|
|
218
212
|
" angles.append(round(angle, 8))\n",
|
|
219
|
-
" return transpiled.count_ops().get(\"
|
|
213
|
+
" return transpiled.count_ops().get(\"cz\", 0), len(angles), len(set(angles))\n",
|
|
220
214
|
"\n",
|
|
221
215
|
"\n",
|
|
222
|
-
"print(f\"{'
|
|
216
|
+
"print(f\"{'':>3}{'CZ gates':^18}{'non-Clifford Rz':^18}{'distinct angles':^18}\")\n",
|
|
217
|
+
"print(f\"{'N':>3}\" + f\"{'FFFT':>9}{'direct':>9}\" * 3)\n",
|
|
218
|
+
"# List powers of 2 first, then sizes with an odd prime factor\n",
|
|
223
219
|
"for n in [4, 8, 16, 6, 12]:\n",
|
|
224
220
|
" ffft = cost(ffsim.qiskit.FermionicFFTSpinlessJW(n))\n",
|
|
225
221
|
" direct = cost(\n",
|
|
226
222
|
" ffsim.qiskit.OrbitalRotationSpinlessJW(n, scipy.linalg.dft(n, scale=\"sqrtn\"))\n",
|
|
227
223
|
" )\n",
|
|
228
|
-
"
|
|
229
|
-
" print(f\"{n:>3} {cx:>11} {rz:>17} {angles:>17}\")"
|
|
224
|
+
" print(f\"{n:>3}\" + \"\".join(f\"{f:>9}{d:>9}\" for f, d in zip(ffft, direct)))"
|
|
230
225
|
]
|
|
231
226
|
},
|
|
232
227
|
{
|
|
@@ -235,13 +230,13 @@
|
|
|
235
230
|
"source": [
|
|
236
231
|
"The FFFT needs far fewer non-Clifford rotations than the direct orbital rotation, and those rotations use only a handful of distinct angles. This is most pronounced when $N$ is a power of 2. Then every Givens rotation is either a mode permutation (angle $\\pi/2$) or a DFT of size 2 (angle $\\pi/4$), and the only other angles come from twiddle factors, which are multiples of $2\\pi/N$. The direct orbital rotation, by contrast, needs a generic angle for almost every rotation. On fault-tolerant hardware, where each arbitrary-angle rotation must be synthesized from many expensive non-Clifford gates, this makes the FFFT much cheaper.\n",
|
|
237
232
|
"\n",
|
|
238
|
-
"The price is more
|
|
233
|
+
"The price is more CZ gates, since the mode permutations add two-qubit gates that the direct decomposition doesn't need. When CZ count is the main cost, as on current noisy hardware, the direct orbital rotation is the better choice."
|
|
239
234
|
]
|
|
240
235
|
}
|
|
241
236
|
],
|
|
242
237
|
"metadata": {
|
|
243
238
|
"kernelspec": {
|
|
244
|
-
"display_name": "
|
|
239
|
+
"display_name": ".venv",
|
|
245
240
|
"language": "python",
|
|
246
241
|
"name": "python3"
|
|
247
242
|
},
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
-
ffsim is supported
|
|
4
|
-
|
|
5
|
-
ffsim is not supported directly on Windows. Windows users have two main options:
|
|
6
|
-
|
|
7
|
-
- Use [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/). WSL provides a Linux environment where ffsim can be pip installed from PyPI or from source.
|
|
8
|
-
- Use ffsim within Docker. See [Use within Docker](#use-within-docker).
|
|
3
|
+
ffsim is supported on Linux, macOS, and Windows. On Windows, only x86-64 is supported, because [PySCF](https://pyscf.org/) does not publish wheels for Windows on ARM.
|
|
9
4
|
|
|
10
5
|
## Pip install
|
|
11
6
|
|
|
@@ -15,7 +10,7 @@ ffsim is available on [PyPI](https://pypi.org/project/ffsim/). You can install i
|
|
|
15
10
|
pip install ffsim
|
|
16
11
|
```
|
|
17
12
|
|
|
18
|
-
For improved performance on [x86](https://en.wikipedia.org/wiki/X86) systems,
|
|
13
|
+
For improved performance on [x86-64](https://en.wikipedia.org/wiki/X86-64) systems, consider [installing from source](#install-from-source).
|
|
19
14
|
|
|
20
15
|
### Qiskit interoperability
|
|
21
16
|
|
|
@@ -48,7 +43,7 @@ cd ffsim
|
|
|
48
43
|
pip install .
|
|
49
44
|
```
|
|
50
45
|
|
|
51
|
-
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.
|
|
46
|
+
Installing from source may improve performance on x86-64 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.
|
|
52
47
|
|
|
53
48
|
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.
|
|
54
49
|
|
|
@@ -5,7 +5,7 @@ build-backend = "maturin"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ffsim"
|
|
7
7
|
requires-python = ">=3.11"
|
|
8
|
-
version = "0.0.
|
|
8
|
+
version = "0.0.86"
|
|
9
9
|
description = "Faster simulation of fermionic quantum circuits."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = { file = "LICENSE" }
|
|
@@ -27,9 +27,8 @@ dependencies = [
|
|
|
27
27
|
"numpy",
|
|
28
28
|
"opt_einsum",
|
|
29
29
|
"orjson",
|
|
30
|
-
"pyscf>=2.
|
|
30
|
+
"pyscf>=2.15",
|
|
31
31
|
"scipy",
|
|
32
|
-
"typing-extensions",
|
|
33
32
|
]
|
|
34
33
|
|
|
35
34
|
[project.optional-dependencies]
|
|
@@ -70,7 +69,7 @@ python-source = "python"
|
|
|
70
69
|
module-name = "ffsim._lib"
|
|
71
70
|
|
|
72
71
|
[tool.cibuildwheel]
|
|
73
|
-
build = "cp311-macosx* cp311-manylinux_x86_64 cp311-manylinux_aarch64"
|
|
72
|
+
build = "cp311-macosx* cp311-manylinux_x86_64 cp311-manylinux_aarch64 cp311-win_amd64"
|
|
74
73
|
test-requires = "pytest"
|
|
75
74
|
test-extras = ["qiskit"]
|
|
76
75
|
test-command = "pytest {project}/tests"
|
|
@@ -79,7 +78,7 @@ test-command = "pytest {project}/tests"
|
|
|
79
78
|
before-all = "dnf install -y openssl-devel"
|
|
80
79
|
|
|
81
80
|
[[tool.cibuildwheel.overrides]]
|
|
82
|
-
select = "*-manylinux_x86_64"
|
|
81
|
+
select = "*-manylinux_x86_64 *-win_amd64"
|
|
83
82
|
environment = { RUSTFLAGS = "-C target-cpu=x86-64" }
|
|
84
83
|
|
|
85
84
|
[tool.pytest.ini_options]
|
|
@@ -27,7 +27,7 @@ def make_strings(orbitals: range, nocc: int) -> np.ndarray:
|
|
|
27
27
|
@cache
|
|
28
28
|
def gen_occslst(orbitals: range, nocc: int) -> np.ndarray:
|
|
29
29
|
"""Cached version of pyscf.fci.cistring.gen_occslst."""
|
|
30
|
-
return cistring.gen_occslst(orbitals, nocc).astype(np.
|
|
30
|
+
return cistring.gen_occslst(orbitals, nocc).astype(np.uintp, copy=False)
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
@cache
|
|
@@ -209,7 +209,7 @@ def _zero_one_subspace_indices(
|
|
|
209
209
|
indices = np.argsort(strings)
|
|
210
210
|
n00 = math.comb(norb - 2, nocc)
|
|
211
211
|
n11 = math.comb(norb - 2, nocc - 2) if nocc >= 2 else 0
|
|
212
|
-
return indices[n00 : len(indices) - n11].astype(np.
|
|
212
|
+
return indices[n00 : len(indices) - n11].astype(np.uintp, copy=False)
|
|
213
213
|
|
|
214
214
|
|
|
215
215
|
@cache
|
|
@@ -223,7 +223,7 @@ def _one_subspace_indices(
|
|
|
223
223
|
n0 = math.comb(norb, nocc)
|
|
224
224
|
if nocc >= len(target_orbs):
|
|
225
225
|
n0 -= math.comb(norb - len(target_orbs), nocc - len(target_orbs))
|
|
226
|
-
return indices[n0:].astype(np.
|
|
226
|
+
return indices[n0:].astype(np.uintp, copy=False)
|
|
227
227
|
|
|
228
228
|
|
|
229
229
|
@cache
|
|
@@ -18,7 +18,6 @@ import scipy.linalg
|
|
|
18
18
|
from pyscf.fci.direct_nosym import make_hdiag
|
|
19
19
|
from pyscf.fci.direct_uhf import make_hdiag as make_hdiag_uhf
|
|
20
20
|
from scipy.sparse.linalg import LinearOperator
|
|
21
|
-
from typing_extensions import deprecated
|
|
22
21
|
|
|
23
22
|
from ffsim import protocols
|
|
24
23
|
from ffsim.contract.two_body import two_body_linop, two_body_linop_unrestricted
|
|
@@ -63,36 +62,6 @@ class MolecularHamiltonian(
|
|
|
63
62
|
"""The number of spatial orbitals."""
|
|
64
63
|
return self.one_body_tensor.shape[0]
|
|
65
64
|
|
|
66
|
-
@property
|
|
67
|
-
@deprecated(
|
|
68
|
-
"The MolecularHamiltonian.one_body_tensor_spinless property is deprecated. "
|
|
69
|
-
"Instead, use the to_spinless method and access the one_body_tensor "
|
|
70
|
-
"attribute of the returned MolecularHamiltonianSpinless."
|
|
71
|
-
)
|
|
72
|
-
def one_body_tensor_spinless(self) -> np.ndarray:
|
|
73
|
-
"""The one-body tensor in spinless format.
|
|
74
|
-
|
|
75
|
-
.. warning::
|
|
76
|
-
This property is deprecated. Use
|
|
77
|
-
:meth:`MolecularHamiltonian.to_spinless` instead.
|
|
78
|
-
"""
|
|
79
|
-
return self.to_spinless().one_body_tensor
|
|
80
|
-
|
|
81
|
-
@property
|
|
82
|
-
@deprecated(
|
|
83
|
-
"The MolecularHamiltonian.two_body_tensor_spinless property is deprecated. "
|
|
84
|
-
"Instead, use the to_spinless method and access the two_body_tensor "
|
|
85
|
-
"attribute of the returned MolecularHamiltonianSpinless."
|
|
86
|
-
)
|
|
87
|
-
def two_body_tensor_spinless(self) -> np.ndarray:
|
|
88
|
-
"""The two-body tensor in spinless format.
|
|
89
|
-
|
|
90
|
-
.. warning::
|
|
91
|
-
This property is deprecated. Use
|
|
92
|
-
:meth:`MolecularHamiltonian.to_spinless` instead.
|
|
93
|
-
"""
|
|
94
|
-
return self.to_spinless().two_body_tensor
|
|
95
|
-
|
|
96
65
|
def to_spinless(self) -> MolecularHamiltonianSpinless:
|
|
97
66
|
"""Convert to a spinless molecular Hamiltonian.
|
|
98
67
|
|