diff --git a/.gitignore b/.gitignore index d02120205..339809b29 100644 --- a/.gitignore +++ b/.gitignore @@ -135,6 +135,7 @@ dmypy.json mod_exp_bloq.json mod_exp_cbloq.json musical_score_example.json +ui_export/ # Jupyter jupyter_kernel.lock diff --git a/dev_tools/autogenerate-bloqs-notebooks-v2.py b/dev_tools/autogenerate-bloqs-notebooks-v2.py index 8d7bb9620..92e68c5ba 100644 --- a/dev_tools/autogenerate-bloqs-notebooks-v2.py +++ b/dev_tools/autogenerate-bloqs-notebooks-v2.py @@ -14,18 +14,15 @@ """Autogeneration of Jupyter notebooks. -For each notebook spec listed in the various global variables (in this file) -we write a notebook with a title, module docstring, -standard imports, and information on each bloq listed in the +For each notebook spec listed in the various global variables imported from +`qualtran_dev_tools.notebook_specs` we write a notebook with a title, module +docstring, standard imports, and information on each bloq listed in the `bloq_specs` field. For each bloq, we render a docstring and diagrams. ## Adding a new bloq. - 1. Create a qualtran.BloqExample perhaps using the `@bloq_example` decorator. Wrap it in a - `qualtran.BloqDocSpec`. This code should live alongside the bloq. - 2. If this is a new module: add a new entry to the appropriate notebook spec global variable - in this file (according to its category/organization). - 3. Update the `NotebookSpec` `bloq_specs` field to include the `BloqDocSpec` for your new bloq. +Follow the instructions in `dev_tools/qualtran_dev_tools/notebook_specs.py` to +add a new bloq. ## Autogen behavior. @@ -49,832 +46,8 @@ from typing import Iterable, List from qualtran_dev_tools.bloq_finder import get_bloqdocspecs -from qualtran_dev_tools.git_tools import get_git_root from qualtran_dev_tools.jupyter_autogen import NotebookSpecV2, render_notebook - -import qualtran.bloqs.arithmetic.addition -import qualtran.bloqs.arithmetic.bitwise -import qualtran.bloqs.arithmetic.comparison -import qualtran.bloqs.arithmetic.controlled_add_or_subtract -import qualtran.bloqs.arithmetic.controlled_addition -import qualtran.bloqs.arithmetic.conversions -import qualtran.bloqs.arithmetic.multiplication -import qualtran.bloqs.arithmetic.negate -import qualtran.bloqs.arithmetic.permutation -import qualtran.bloqs.arithmetic.sorting -import qualtran.bloqs.arithmetic.subtraction -import qualtran.bloqs.arithmetic.trigonometric -import qualtran.bloqs.basic_gates.swap -import qualtran.bloqs.block_encoding.block_encoding_base -import qualtran.bloqs.block_encoding.chebyshev_polynomial -import qualtran.bloqs.block_encoding.lcu_block_encoding -import qualtran.bloqs.block_encoding.linear_combination -import qualtran.bloqs.block_encoding.phase -import qualtran.bloqs.block_encoding.product -import qualtran.bloqs.block_encoding.sparse_matrix -import qualtran.bloqs.block_encoding.tensor_product -import qualtran.bloqs.block_encoding.unitary -import qualtran.bloqs.bookkeeping -import qualtran.bloqs.bookkeeping.allocate -import qualtran.bloqs.bookkeeping.auto_partition -import qualtran.bloqs.bookkeeping.cast -import qualtran.bloqs.bookkeeping.free -import qualtran.bloqs.bookkeeping.join -import qualtran.bloqs.bookkeeping.partition -import qualtran.bloqs.bookkeeping.split -import qualtran.bloqs.chemistry.df.double_factorization -import qualtran.bloqs.chemistry.hubbard_model.qubitization -import qualtran.bloqs.chemistry.pbc.first_quantization.prepare_t -import qualtran.bloqs.chemistry.pbc.first_quantization.prepare_uv -import qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare -import qualtran.bloqs.chemistry.pbc.first_quantization.select_t -import qualtran.bloqs.chemistry.pbc.first_quantization.select_uv -import qualtran.bloqs.chemistry.quad_fermion.givens_bloq -import qualtran.bloqs.chemistry.sf.single_factorization -import qualtran.bloqs.chemistry.sparse.prepare -import qualtran.bloqs.chemistry.sparse.walk_operator -import qualtran.bloqs.chemistry.thc.prepare -import qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt -import qualtran.bloqs.chemistry.trotter.grid_ham.qvr -import qualtran.bloqs.chemistry.trotter.hubbard.hopping -import qualtran.bloqs.chemistry.trotter.hubbard.interaction -import qualtran.bloqs.chemistry.trotter.ising.unitaries -import qualtran.bloqs.chemistry.trotter.trotterized_unitary -import qualtran.bloqs.data_loading.qrom -import qualtran.bloqs.data_loading.qrom_base -import qualtran.bloqs.data_loading.select_swap_qrom -import qualtran.bloqs.factoring.ecc -import qualtran.bloqs.factoring.mod_exp -import qualtran.bloqs.gf_arithmetic.gf2_add_k -import qualtran.bloqs.gf_arithmetic.gf2_addition -import qualtran.bloqs.gf_arithmetic.gf2_inverse -import qualtran.bloqs.gf_arithmetic.gf2_multiplication -import qualtran.bloqs.gf_arithmetic.gf2_square -import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp -import qualtran.bloqs.mcmt.and_bloq -import qualtran.bloqs.mcmt.controlled_via_and -import qualtran.bloqs.mcmt.ctrl_spec_and -import qualtran.bloqs.mcmt.multi_control_pauli -import qualtran.bloqs.mcmt.multi_target_cnot -import qualtran.bloqs.mod_arithmetic.mod_addition -import qualtran.bloqs.multiplexers.apply_gate_to_lth_target -import qualtran.bloqs.multiplexers.apply_lth_bloq -import qualtran.bloqs.multiplexers.black_box_select -import qualtran.bloqs.multiplexers.select_base -import qualtran.bloqs.multiplexers.select_pauli_lcu -import qualtran.bloqs.phase_estimation.lp_resource_state -import qualtran.bloqs.phase_estimation.qubitization_qpe -import qualtran.bloqs.phase_estimation.text_book_qpe -import qualtran.bloqs.qft.approximate_qft -import qualtran.bloqs.qft.qft_phase_gradient -import qualtran.bloqs.qft.qft_text_book -import qualtran.bloqs.qft.two_bit_ffft -import qualtran.bloqs.qsp.generalized_qsp -import qualtran.bloqs.qubitization.qubitization_walk_operator -import qualtran.bloqs.reflections -import qualtran.bloqs.reflections.prepare_identity -import qualtran.bloqs.reflections.reflection_using_prepare -import qualtran.bloqs.rotations.hamming_weight_phasing -import qualtran.bloqs.rotations.phase_gradient -import qualtran.bloqs.rotations.phasing_via_cost_function -import qualtran.bloqs.rotations.programmable_rotation_gate_array -import qualtran.bloqs.rotations.quantum_variable_rotation -import qualtran.bloqs.state_preparation.black_box_prepare -import qualtran.bloqs.state_preparation.prepare_base -import qualtran.bloqs.state_preparation.prepare_uniform_superposition -import qualtran.bloqs.state_preparation.state_preparation_alias_sampling -import qualtran.bloqs.state_preparation.state_preparation_via_rotation -import qualtran.bloqs.swap_network.cswap_approx -import qualtran.bloqs.swap_network.multiplexed_cswap -import qualtran.bloqs.swap_network.swap_with_zero - -GIT_ROOT = get_git_root() -SOURCE_DIR = GIT_ROOT / 'qualtran/' - -# -------------------------------------------------------------------------- -# ----- Basic Gates ---------------------------------------------------- -# -------------------------------------------------------------------------- -BASIC_GATES: List[NotebookSpecV2] = [ - NotebookSpecV2( - title='T Gate', - module=qualtran.bloqs.basic_gates.t_gate, - bloq_specs=[qualtran.bloqs.basic_gates.t_gate._T_GATE_DOC], - ), - NotebookSpecV2( - title='Toffoli', - module=qualtran.bloqs.basic_gates.toffoli, - bloq_specs=[qualtran.bloqs.basic_gates.toffoli._TOFFOLI_DOC], - ), - NotebookSpecV2( - title='Hadamard', - module=qualtran.bloqs.basic_gates.hadamard, - bloq_specs=[ - qualtran.bloqs.basic_gates.hadamard._HADAMARD_DOC, - qualtran.bloqs.basic_gates.hadamard._CHADAMARD_DOC, - ], - ), - NotebookSpecV2( - title='CNOT', - module=qualtran.bloqs.basic_gates.cnot, - bloq_specs=[qualtran.bloqs.basic_gates.cnot._CNOT_DOC], - ), - NotebookSpecV2( - title='Z, S, and CZ', - module=qualtran.bloqs.basic_gates.z_basis, - path_stem='diag_gates', - bloq_specs=[ - qualtran.bloqs.basic_gates.z_basis._Z_GATE_DOC, - qualtran.bloqs.basic_gates.s_gate._S_GATE_DOC, - qualtran.bloqs.basic_gates.z_basis._CZ_DOC, - ], - ), - NotebookSpecV2( - title='Y Gate', - module=qualtran.bloqs.basic_gates.y_gate, - bloq_specs=[ - qualtran.bloqs.basic_gates.y_gate._Y_GATE_DOC, - qualtran.bloqs.basic_gates.y_gate._CY_GATE_DOC, - ], - ), - NotebookSpecV2( - title='And', - module=qualtran.bloqs.mcmt.and_bloq, - bloq_specs=[ - qualtran.bloqs.mcmt.and_bloq._AND_DOC, - qualtran.bloqs.mcmt.and_bloq._MULTI_AND_DOC, - ], - ), - NotebookSpecV2( - title='States and Effects', - module=qualtran.bloqs.basic_gates.z_basis, - path_stem='states_and_effects', - bloq_specs=[ - qualtran.bloqs.basic_gates.z_basis._ZERO_STATE_DOC, - qualtran.bloqs.basic_gates.z_basis._ZERO_EFFECT_DOC, - qualtran.bloqs.basic_gates.z_basis._ONE_STATE_DOC, - qualtran.bloqs.basic_gates.z_basis._ONE_EFFECT_DOC, - qualtran.bloqs.basic_gates.z_basis._INT_STATE_DOC, - qualtran.bloqs.basic_gates.z_basis._INT_EFFECT_DOC, - qualtran.bloqs.basic_gates.x_basis._PLUS_STATE_DOC, - qualtran.bloqs.basic_gates.x_basis._PLUS_EFFECT_DOC, - qualtran.bloqs.basic_gates.x_basis._MINUS_STATE_DOC, - qualtran.bloqs.basic_gates.x_basis._MINUS_EFFECT_DOC, - ], - ), - NotebookSpecV2( - title='Basic Swaps', - module=qualtran.bloqs.basic_gates.swap, - bloq_specs=[ - qualtran.bloqs.basic_gates.swap._TWO_BIT_SWAP_DOC, - qualtran.bloqs.basic_gates.swap._TWO_BIT_CSWAP_DOC, - qualtran.bloqs.basic_gates.swap._SWAP_DOC, - qualtran.bloqs.basic_gates.swap._CSWAP_DOC, - ], - ), - NotebookSpecV2( - title='Swap Networks', - module=qualtran.bloqs.swap_network, - bloq_specs=[ - qualtran.bloqs.swap_network.cswap_approx._APPROX_CSWAP_DOC, - qualtran.bloqs.swap_network.swap_with_zero._SWZ_DOC, - qualtran.bloqs.swap_network.multiplexed_cswap._MULTIPLEXED_CSWAP_DOC, - ], - ), - NotebookSpecV2( - title='Global Phase', - module=qualtran.bloqs.basic_gates.global_phase, - bloq_specs=[qualtran.bloqs.basic_gates.global_phase._GLOBAL_PHASE_DOC], - ), - NotebookSpecV2( - title='Identity Gate', - module=qualtran.bloqs.basic_gates.identity, - bloq_specs=[qualtran.bloqs.basic_gates.identity._IDENTITY_DOC], - ), - NotebookSpecV2( - title='Bookkeeping Bloqs', - module=qualtran.bloqs.bookkeeping, - bloq_specs=[ - qualtran.bloqs.bookkeeping.allocate._ALLOC_DOC, - qualtran.bloqs.bookkeeping.free._FREE_DOC, - qualtran.bloqs.bookkeeping.split._SPLIT_DOC, - qualtran.bloqs.bookkeeping.join._JOIN_DOC, - qualtran.bloqs.bookkeeping.partition._PARTITION_DOC, - qualtran.bloqs.bookkeeping.auto_partition._AUTO_PARTITION_DOC, - qualtran.bloqs.bookkeeping.cast._CAST_DOC, - ], - ), - NotebookSpecV2( - title='Control Specification (And)', - module=qualtran.bloqs.mcmt.ctrl_spec_and, - bloq_specs=[qualtran.bloqs.mcmt.ctrl_spec_and._CTRLSPEC_AND_DOC], - ), - NotebookSpecV2( - title='Multi control bloq via single control bloq and `And` ladder', - module=qualtran.bloqs.mcmt.controlled_via_and, - bloq_specs=[qualtran.bloqs.mcmt.controlled_via_and._CONTROLLED_VIA_AND_DOC], - ), -] - - -# -------------------------------------------------------------------------- -# ----- Chemistry ------------------------------------------------------ -# -------------------------------------------------------------------------- -CHEMISTRY: List[NotebookSpecV2] = [ - NotebookSpecV2( - title='Sparse', - module=qualtran.bloqs.chemistry.sparse, - bloq_specs=[ - qualtran.bloqs.chemistry.sparse.prepare._SPARSE_PREPARE, - qualtran.bloqs.chemistry.sparse.select_bloq._SPARSE_SELECT, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/sparse', - ), - NotebookSpecV2( - title='Single Factorization', - module=qualtran.bloqs.chemistry.sf.single_factorization, - bloq_specs=[ - qualtran.bloqs.chemistry.sf.single_factorization._SF_ONE_BODY, - qualtran.bloqs.chemistry.sf.single_factorization._SF_BLOCK_ENCODING, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/sf', - ), - NotebookSpecV2( - title='Double Factorization', - module=qualtran.bloqs.chemistry.df.double_factorization, - bloq_specs=[ - qualtran.bloqs.chemistry.df.double_factorization._DF_ONE_BODY, - qualtran.bloqs.chemistry.df.double_factorization._DF_BLOCK_ENCODING, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/df', - ), - NotebookSpecV2( - title='Tensor Hypercontraction', - module=qualtran.bloqs.chemistry.thc, - bloq_specs=[ - qualtran.bloqs.chemistry.thc.prepare._THC_UNI_PREP, - qualtran.bloqs.chemistry.thc.prepare._THC_PREPARE, - qualtran.bloqs.chemistry.thc.select_bloq._THC_SELECT, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/thc', - ), - NotebookSpecV2( - title='First Quantized Hamiltonian', - module=qualtran.bloqs.chemistry.pbc.first_quantization, - bloq_specs=[ - qualtran.bloqs.chemistry.pbc.first_quantization.select_and_prepare._FIRST_QUANTIZED_PREPARE_DOC, - qualtran.bloqs.chemistry.pbc.first_quantization.select_and_prepare._FIRST_QUANTIZED_SELECT_DOC, - qualtran.bloqs.chemistry.pbc.first_quantization.prepare_t._PREPARE_T, - qualtran.bloqs.chemistry.pbc.first_quantization.prepare_uv._PREPARE_UV, - qualtran.bloqs.chemistry.pbc.first_quantization.select_t._SELECT_T, - qualtran.bloqs.chemistry.pbc.first_quantization.select_uv._SELECT_UV, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/pbc/first_quantization', - ), - NotebookSpecV2( - title='First Quantized Hamiltonian with Quantum Projectile', - module=qualtran.bloqs.chemistry.pbc.first_quantization.projectile, - bloq_specs=[ - qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare._FIRST_QUANTIZED_WITH_PROJ_PREPARE_DOC, - qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare._FIRST_QUANTIZED_WITH_PROJ_SELECT_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/pbc/first_quantization/projectile', - ), - NotebookSpecV2( - title='Trotter Bloqs', - module=qualtran.bloqs.chemistry.trotter.grid_ham, - bloq_specs=[ - qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt._POLY_INV_SQRT, - qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt._NR_INV_SQRT, - qualtran.bloqs.chemistry.trotter.grid_ham.qvr._QVR, - qualtran.bloqs.chemistry.trotter.grid_ham.kinetic._KINETIC_ENERGY, - qualtran.bloqs.chemistry.trotter.grid_ham.potential._PAIR_POTENTIAL, - qualtran.bloqs.chemistry.trotter.grid_ham.potential._POTENTIAL_ENERGY, - ], - path_stem='trotter', - ), - NotebookSpecV2( - title='Trotterization', - module=qualtran.bloqs.chemistry.trotter.trotterized_unitary, - bloq_specs=[qualtran.bloqs.chemistry.trotter.trotterized_unitary._TROTT_UNITARY_DOC], - directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter', - ), - NotebookSpecV2( - title='Ising Trotter Bloqs', - module=qualtran.bloqs.chemistry.trotter.ising, - bloq_specs=[ - qualtran.bloqs.chemistry.trotter.ising.unitaries._ISING_X_UNITARY_DOC, - qualtran.bloqs.chemistry.trotter.ising.unitaries._ISING_ZZ_UNITARY_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter/ising', - ), - NotebookSpecV2( - title='Trotterized Hubbard', - module=qualtran.bloqs.chemistry.trotter.hubbard, - bloq_specs=[ - qualtran.bloqs.chemistry.trotter.hubbard.hopping._HOPPING_DOC, - qualtran.bloqs.chemistry.trotter.hubbard.hopping._PLAQUETTE_DOC, - qualtran.bloqs.chemistry.trotter.hubbard.hopping._HOPPING_TILE_HWP_DOC, - qualtran.bloqs.chemistry.trotter.hubbard.interaction._INTERACTION_DOC, - qualtran.bloqs.chemistry.trotter.hubbard.interaction._INTERACTION_HWP_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter/hubbard', - ), - NotebookSpecV2( - title='Givens Rotations', - module=qualtran.bloqs.chemistry.quad_fermion.givens_bloq, - bloq_specs=[ - qualtran.bloqs.chemistry.quad_fermion.givens_bloq._REAL_GIVENS_DOC, - qualtran.bloqs.chemistry.quad_fermion.givens_bloq._CPLX_GIVENS_DOC, - ], - ), -] - -# -------------------------------------------------------------------------- -# ----- Arithmetic ----------------------------------------------------- -# -------------------------------------------------------------------------- -ARITHMETIC = [ - NotebookSpecV2( - title='Addition', - module=qualtran.bloqs.arithmetic.addition, - bloq_specs=[ - qualtran.bloqs.arithmetic.addition._ADD_DOC, - qualtran.bloqs.arithmetic.addition._ADD_OOP_DOC, - qualtran.bloqs.arithmetic.addition._ADD_K_DOC, - ], - ), - NotebookSpecV2( - title='Controlled Addition', - module=qualtran.bloqs.arithmetic.controlled_addition, - bloq_specs=[qualtran.bloqs.arithmetic.controlled_addition._CADD_DOC], - ), - NotebookSpecV2( - title='Negation', - module=qualtran.bloqs.arithmetic.negate, - bloq_specs=[qualtran.bloqs.arithmetic.negate._NEGATE_DOC], - ), - NotebookSpecV2( - title='Subtraction', - module=qualtran.bloqs.arithmetic.subtraction, - bloq_specs=[ - qualtran.bloqs.arithmetic.subtraction._SUB_DOC, - qualtran.bloqs.arithmetic.subtraction._SUB_FROM_DOC, - ], - ), - NotebookSpecV2( - title='Controlled Add-or-Subtract', - module=qualtran.bloqs.arithmetic.controlled_add_or_subtract, - bloq_specs=[ - qualtran.bloqs.arithmetic.controlled_add_or_subtract._CONTROLLED_ADD_OR_SUBTRACT_DOC - ], - ), - NotebookSpecV2( - title='Multiplication', - module=qualtran.bloqs.arithmetic.multiplication, - bloq_specs=[ - qualtran.bloqs.arithmetic.multiplication._PLUS_EQUALS_PRODUCT_DOC, - qualtran.bloqs.arithmetic.multiplication._PRODUCT_DOC, - qualtran.bloqs.arithmetic.multiplication._SQUARE_DOC, - qualtran.bloqs.arithmetic.multiplication._SUM_OF_SQUARES_DOC, - qualtran.bloqs.arithmetic.multiplication._SCALE_INT_BY_REAL_DOC, - qualtran.bloqs.arithmetic.multiplication._MULTIPLY_TWO_REALS_DOC, - qualtran.bloqs.arithmetic.multiplication._SQUARE_REAL_NUMBER_DOC, - qualtran.bloqs.arithmetic.multiplication._INVERT_REAL_NUMBER_DOC, - ], - ), - NotebookSpecV2( - title='Comparison', - module=qualtran.bloqs.arithmetic.comparison, - bloq_specs=[ - qualtran.bloqs.arithmetic.comparison._LT_K_DOC, - qualtran.bloqs.arithmetic.comparison._GREATER_THAN_DOC, - qualtran.bloqs.arithmetic.comparison._GREATER_THAN_K_DOC, - qualtran.bloqs.arithmetic.comparison._EQUALS_DOC, - qualtran.bloqs.arithmetic.comparison._EQUALS_K_DOC, - qualtran.bloqs.arithmetic.comparison._BI_QUBITS_MIXER_DOC, - qualtran.bloqs.arithmetic.comparison._SQ_CMP_DOC, - qualtran.bloqs.arithmetic.comparison._LEQ_DOC, - qualtran.bloqs.arithmetic.comparison._CLinearDepthGreaterThan_DOC, - ], - ), - NotebookSpecV2( - title='Integer Conversions', - module=qualtran.bloqs.arithmetic.conversions, - bloq_specs=[ - qualtran.bloqs.arithmetic.conversions.ones_complement_to_twos_complement._SIGNED_TO_TWOS, - qualtran.bloqs.arithmetic.conversions.sign_extension._SIGN_EXTEND_DOC, - qualtran.bloqs.arithmetic.conversions.sign_extension._SIGN_TRUNCATE_DOC, - ], - ), - NotebookSpecV2( - title='Sorting', - module=qualtran.bloqs.arithmetic.sorting, - bloq_specs=[ - qualtran.bloqs.arithmetic.sorting._COMPARATOR_DOC, - qualtran.bloqs.arithmetic.sorting._PARALLEL_COMPARATORS_DOC, - qualtran.bloqs.arithmetic.sorting._BITONIC_MERGE_DOC, - qualtran.bloqs.arithmetic.sorting._BITONIC_SORT_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/arithmetic/', - ), - NotebookSpecV2( - title='Indexing', - module=qualtran.bloqs.arithmetic.conversions.contiguous_index, - bloq_specs=[qualtran.bloqs.arithmetic.conversions.contiguous_index._TO_CONTG_INDX], - ), - NotebookSpecV2( - title='Permutations', - module=qualtran.bloqs.arithmetic.permutation, - bloq_specs=[ - qualtran.bloqs.arithmetic.permutation._PERMUTATION_DOC, - qualtran.bloqs.arithmetic.permutation._PERMUTATION_CYCLE_DOC, - ], - ), - NotebookSpecV2( - title='Bitwise Operations', - module=qualtran.bloqs.arithmetic.bitwise, - bloq_specs=[ - qualtran.bloqs.arithmetic.bitwise._XOR_DOC, - qualtran.bloqs.arithmetic.bitwise._BITWISE_NOT_DOC, - ], - ), - NotebookSpecV2( - title='Trigonometric Functions', - module=qualtran.bloqs.arithmetic.trigonometric, - bloq_specs=[qualtran.bloqs.arithmetic.trigonometric.arcsin._ARCSIN_DOC], - ), -] - -MOD_ARITHMETIC = [ - NotebookSpecV2( - title='Modular Addition', - module=qualtran.bloqs.mod_arithmetic.mod_addition, - bloq_specs=[ - qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_DOC, - qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_K_DOC, - qualtran.bloqs.mod_arithmetic.mod_addition._C_MOD_ADD_DOC, - ], - ), - NotebookSpecV2( - title='Modular Subtraction', - module=qualtran.bloqs.mod_arithmetic.mod_subtraction, - bloq_specs=[ - qualtran.bloqs.mod_arithmetic.mod_subtraction._MOD_NEG_DOC, - qualtran.bloqs.mod_arithmetic.mod_subtraction._CMOD_NEG_DOC, - qualtran.bloqs.mod_arithmetic.mod_subtraction._MOD_SUB_DOC, - qualtran.bloqs.mod_arithmetic.mod_subtraction._CMOD_SUB_DOC, - ], - ), - NotebookSpecV2( - title='Modular Multiplication', - module=qualtran.bloqs.mod_arithmetic.mod_multiplication, - bloq_specs=[ - qualtran.bloqs.mod_arithmetic.mod_multiplication._MOD_DBL_DOC, - qualtran.bloqs.mod_arithmetic.mod_multiplication._C_MOD_MUL_K_DOC, - qualtran.bloqs.mod_arithmetic.mod_multiplication._DIRTY_OUT_OF_PLACE_MONTGOMERY_MOD_MUL_DOC, - ], - ), - NotebookSpecV2( - title='Modular Exponentiation', - module=qualtran.bloqs.factoring.mod_exp, - bloq_specs=[qualtran.bloqs.factoring.mod_exp._MODEXP_DOC], - directory=f'{SOURCE_DIR}/bloqs/factoring', - ), - NotebookSpecV2( - title='Elliptic Curve Addition', - module=qualtran.bloqs.factoring.ecc.ec_add, - bloq_specs=[qualtran.bloqs.factoring.ecc.ec_add._EC_ADD_DOC], - ), - NotebookSpecV2( - title='Elliptic Curve Cryptography', - module=qualtran.bloqs.factoring.ecc, - bloq_specs=[ - qualtran.bloqs.factoring.ecc.find_ecc_private_key._ECC_BLOQ_DOC, - qualtran.bloqs.factoring.ecc.ec_phase_estimate_r._EC_PE_BLOQ_DOC, - qualtran.bloqs.factoring.ecc.ec_add_r._ECC_ADD_R_BLOQ_DOC, - qualtran.bloqs.factoring.ecc.ec_add_r._EC_WINDOW_ADD_BLOQ_DOC, - ], - ), -] - -GF_ARITHMETIC = [ - # -------------------------------------------------------------------------- - # ----- Galois Fields (GF) Arithmetic --------------------------------- - # -------------------------------------------------------------------------- - NotebookSpecV2( - title='GF($2^m$) Multiplication', - module=qualtran.bloqs.gf_arithmetic.gf2_multiplication, - bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_multiplication._GF2_MULTIPLICATION_DOC], - ), - NotebookSpecV2( - title='GF($2^m$) Addition', - module=qualtran.bloqs.gf_arithmetic.gf2_addition, - bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_addition._GF2_ADDITION_DOC], - ), - NotebookSpecV2( - title='GF($2^m$) Add Constant', - module=qualtran.bloqs.gf_arithmetic.gf2_add_k, - bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_add_k._GF2_ADD_K_DOC], - ), - NotebookSpecV2( - title='GF($2^m$) Square', - module=qualtran.bloqs.gf_arithmetic.gf2_square, - bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_square._GF2_SQUARE_DOC], - ), - NotebookSpecV2( - title='GF($2^m$) Inverse', - module=qualtran.bloqs.gf_arithmetic.gf2_inverse, - bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_inverse._GF2_INVERSE_DOC], - ), -] - - -ROT_QFT_PE = [ - # -------------------------------------------------------------------------- - # ----- Rotations ----------------------------------------------------- - # -------------------------------------------------------------------------- - NotebookSpecV2( - title='Basic Rotation Gates', - module=qualtran.bloqs.basic_gates.rotation, - bloq_specs=[ - qualtran.bloqs.basic_gates.rotation._X_POW_DOC, - qualtran.bloqs.basic_gates.rotation._Y_POW_DOC, - qualtran.bloqs.basic_gates.rotation._Z_POW_DOC, - ], - ), - NotebookSpecV2( - title='SU2 Rotation', - module=qualtran.bloqs.basic_gates.su2_rotation, - bloq_specs=[qualtran.bloqs.basic_gates.su2_rotation._SU2_ROTATION_GATE_DOC], - ), - NotebookSpecV2( - title='Quantum Variable Rotation', - module=qualtran.bloqs.rotations.quantum_variable_rotation, - bloq_specs=[ - qualtran.bloqs.rotations.quantum_variable_rotation._QVR_ZPOW, - qualtran.bloqs.rotations.quantum_variable_rotation._QVR_PHASE_GRADIENT, - ], - directory=f'{SOURCE_DIR}/bloqs/rotations/', - ), - NotebookSpecV2( - title='Phasing via Cost function', - module=qualtran.bloqs.rotations.phasing_via_cost_function, - bloq_specs=[qualtran.bloqs.rotations.phasing_via_cost_function._PHASING_VIA_COST_FUNCTION], - directory=f'{SOURCE_DIR}/bloqs/rotations/', - ), - NotebookSpecV2( - title='Rotations via Phase Gradients', - module=qualtran.bloqs.rotations.phase_gradient, - bloq_specs=[ - qualtran.bloqs.rotations.phase_gradient._PHASE_GRADIENT_UNITARY_DOC, - qualtran.bloqs.rotations.phase_gradient._PHASE_GRADIENT_STATE_DOC, - qualtran.bloqs.rotations.phase_gradient._ADD_INTO_PHASE_GRAD_DOC, - qualtran.bloqs.rotations.phase_gradient._ADD_SCALED_VAL_INTO_PHASE_REG_DOC, - ], - ), - NotebookSpecV2( - title='Z Rotations via Hamming Weight Phasing', - module=qualtran.bloqs.rotations.hamming_weight_phasing, - bloq_specs=[ - qualtran.bloqs.rotations.hamming_weight_phasing._HAMMING_WEIGHT_PHASING_DOC, - qualtran.bloqs.rotations.hamming_weight_phasing._HAMMING_WEIGHT_PHASING_VIA_PHASE_GRADIENT_DOC, - ], - ), - NotebookSpecV2( - title='Programmable Rotation Gate Array', - module=qualtran.bloqs.rotations.programmable_rotation_gate_array, - bloq_specs=[ - qualtran.bloqs.rotations.programmable_rotation_gate_array._PROGRAMMABLE_ROTATAION_GATE_ARRAY_DOC - ], - ), - # -------------------------------------------------------------------------- - # ----- QFT ----------------------------------------------------- - # -------------------------------------------------------------------------- - NotebookSpecV2( - title='Two Bit FFFT Gate', - module=qualtran.bloqs.qft.two_bit_ffft, - bloq_specs=[qualtran.bloqs.qft.two_bit_ffft._TWO_BIT_FFFT_DOC], - ), - NotebookSpecV2( - title='Approximate QFT', - module=qualtran.bloqs.qft.approximate_qft, - bloq_specs=[qualtran.bloqs.qft.approximate_qft._CC_AQFT_DOC], - ), - NotebookSpecV2( - title='Textbook QFT', - module=qualtran.bloqs.qft.qft_text_book, - bloq_specs=[qualtran.bloqs.qft.qft_text_book._QFT_TEXT_BOOK_DOC], - ), - NotebookSpecV2( - title='Phase Gradient QFT', - module=qualtran.bloqs.qft.qft_phase_gradient, - bloq_specs=[qualtran.bloqs.qft.qft_phase_gradient._QFT_PHASE_GRADIENT_DOC], - ), - # -------------------------------------------------------------------------- - # ----- Phase Estimation ---------------------------------------- - # -------------------------------------------------------------------------- - NotebookSpecV2( - title='Optimal resource states for Phase Estimation by A. Luis and J. Peřina', - module=qualtran.bloqs.phase_estimation.lp_resource_state, - bloq_specs=[ - qualtran.bloqs.phase_estimation.lp_resource_state._CC_LPRS_INTERIM_PREP_DOC, - qualtran.bloqs.phase_estimation.lp_resource_state._CC_LP_RESOURCE_STATE_DOC, - ], - ), - NotebookSpecV2( - title='Textbook Quantum Phase Estimation', - module=qualtran.bloqs.phase_estimation.text_book_qpe, - bloq_specs=[ - qualtran.bloqs.phase_estimation.qpe_window_state._CC_RECTANGULAR_WINDOW_STATE_DOC, - qualtran.bloqs.phase_estimation.text_book_qpe._CC_TEXTBOOK_PHASE_ESTIMATION_DOC, - ], - ), - NotebookSpecV2( - title='Kaiser Window State for Quantum Phase Estimation', - module=qualtran.bloqs.phase_estimation.kaiser_window_state, - bloq_specs=[ - qualtran.bloqs.phase_estimation.kaiser_window_state._CC_KAISER_WINDOW_STATE_DOC - ], - ), - NotebookSpecV2( - title='Qubitization Walk Operator', - module=qualtran.bloqs.qubitization.qubitization_walk_operator, - bloq_specs=[qualtran.bloqs.qubitization.qubitization_walk_operator._QUBITIZATION_WALK_DOC], - ), - NotebookSpecV2( - title='Qubitization Phase Estimation', - module=qualtran.bloqs.phase_estimation.qubitization_qpe, - bloq_specs=[qualtran.bloqs.phase_estimation.qubitization_qpe._QUBITIZATION_QPE_DOC], - ), -] - -# -------------------------------------------------------------------------- -# ----- Block Encoding ---------------------------------------------------------- -# -------------------------------------------------------------------------- -BLOCK_ENCODING: List[NotebookSpecV2] = [ - NotebookSpecV2( - title='Block Encoding Interface', - module=qualtran.bloqs.block_encoding, - bloq_specs=[qualtran.bloqs.block_encoding.block_encoding_base._BLOCK_ENCODING_DOC], - ), - NotebookSpecV2( - title='Unitary', - module=qualtran.bloqs.block_encoding.unitary, - bloq_specs=[qualtran.bloqs.block_encoding.unitary._UNITARY_DOC], - ), - NotebookSpecV2( - title='Tensor Product', - module=qualtran.bloqs.block_encoding.tensor_product, - bloq_specs=[qualtran.bloqs.block_encoding.tensor_product._TENSOR_PRODUCT_DOC], - ), - NotebookSpecV2( - title='Product', - module=qualtran.bloqs.block_encoding.product, - bloq_specs=[qualtran.bloqs.block_encoding.product._PRODUCT_DOC], - ), - NotebookSpecV2( - title='Phase', - module=qualtran.bloqs.block_encoding.phase, - bloq_specs=[qualtran.bloqs.block_encoding.phase._PHASE_DOC], - ), - NotebookSpecV2( - title='Linear Combination', - module=qualtran.bloqs.block_encoding.linear_combination, - bloq_specs=[qualtran.bloqs.block_encoding.linear_combination._LINEAR_COMBINATION_DOC], - ), - NotebookSpecV2( - title='Sparse Matrix', - module=qualtran.bloqs.block_encoding.sparse_matrix, - bloq_specs=[qualtran.bloqs.block_encoding.sparse_matrix._SPARSE_MATRIX_DOC], - ), - NotebookSpecV2( - title='Chebyshev Polynomial', - module=qualtran.bloqs.block_encoding.chebyshev_polynomial, - bloq_specs=[ - qualtran.bloqs.block_encoding.chebyshev_polynomial._CHEBYSHEV_BLOQ_DOC, - qualtran.bloqs.block_encoding.chebyshev_polynomial._SCALED_CHEBYSHEV_BLOQ_DOC, - ], - ), - NotebookSpecV2( - title='LCU Select/Prepare Oracles', - module=qualtran.bloqs.block_encoding.lcu_block_encoding, - bloq_specs=[ - qualtran.bloqs.block_encoding.lcu_block_encoding._SELECT_BLOCK_ENCODING_DOC, - qualtran.bloqs.block_encoding.lcu_block_encoding._LCU_BLOCK_ENCODING_DOC, - qualtran.bloqs.multiplexers.select_base._SELECT_ORACLE_DOC, - qualtran.bloqs.state_preparation.prepare_base._PREPARE_ORACLE_DOC, - qualtran.bloqs.multiplexers.black_box_select._BLACK_BOX_SELECT_DOC, - qualtran.bloqs.state_preparation.black_box_prepare._BLACK_BOX_PREPARE_DOC, - ], - ), -] - -# -------------------------------------------------------------------------- -# ----- Other ---------------------------------------------------------- -# -------------------------------------------------------------------------- -OTHER: List[NotebookSpecV2] = [ - NotebookSpecV2( - title='Prepare Uniform Superposition', - module=qualtran.bloqs.state_preparation.prepare_uniform_superposition, - bloq_specs=[ - qualtran.bloqs.state_preparation.prepare_uniform_superposition._PREP_UNIFORM_DOC - ], - ), - NotebookSpecV2( - title='Qubitized Hubbard Model', - module=qualtran.bloqs.chemistry.hubbard_model.qubitization, - path_stem='hubbard_model', - bloq_specs=[ - qualtran.bloqs.chemistry.hubbard_model.qubitization.select_hubbard._SELECT_HUBBARD, - qualtran.bloqs.chemistry.hubbard_model.qubitization.prepare_hubbard._PREPARE_HUBBARD, - ], - ), - NotebookSpecV2( - title='Apply to Lth Target', - module=qualtran.bloqs.multiplexers.apply_gate_to_lth_target, - bloq_specs=[qualtran.bloqs.multiplexers.apply_gate_to_lth_target._APPLY_TO_LTH_TARGET_DOC], - ), - NotebookSpecV2( - title='Apply Lth Bloq', - module=qualtran.bloqs.multiplexers.apply_lth_bloq, - bloq_specs=[qualtran.bloqs.multiplexers.apply_lth_bloq._APPLY_LTH_BLOQ_DOC], - ), - NotebookSpecV2( - title='QROM', - module=qualtran.bloqs.data_loading.qrom, - bloq_specs=[ - qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, - qualtran.bloqs.data_loading.qrom._QROM_DOC, - ], - ), - NotebookSpecV2( - title='SelectSwapQROM', - module=qualtran.bloqs.data_loading.select_swap_qrom, - bloq_specs=[ - qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, - qualtran.bloqs.data_loading.select_swap_qrom._SELECT_SWAP_QROM_DOC, - ], - ), - NotebookSpecV2( - title='Advanced QROM (aka QROAM) using clean ancilla', - module=qualtran.bloqs.data_loading.qroam_clean, - bloq_specs=[ - qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, - qualtran.bloqs.data_loading.qroam_clean._QROAM_CLEAN_DOC, - ], - ), - NotebookSpecV2( - title='Reflections', - module=qualtran.bloqs.reflections, - bloq_specs=[ - qualtran.bloqs.reflections.prepare_identity._PREPARE_IDENTITY_DOC, - qualtran.bloqs.reflections.reflection_using_prepare._REFL_USING_PREP_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/reflections', - ), - NotebookSpecV2( - title='Multi-Paulis', - module=qualtran.bloqs.mcmt, - bloq_specs=[ - qualtran.bloqs.mcmt.multi_target_cnot._C_MULTI_NOT_DOC, - qualtran.bloqs.mcmt.multi_control_pauli._CC_PAULI_DOC, - ], - directory=f'{SOURCE_DIR}/bloqs/mcmt/', - path_stem='multi_control_multi_target_pauli', - ), - NotebookSpecV2( - title='Generic Select', - module=qualtran.bloqs.multiplexers.select_pauli_lcu, - bloq_specs=[qualtran.bloqs.multiplexers.select_pauli_lcu._SELECT_PAULI_LCU_DOC], - ), - NotebookSpecV2( - title='State Preparation via Alias Sampling', - module=qualtran.bloqs.state_preparation.state_preparation_alias_sampling, - bloq_specs=[ - qualtran.bloqs.state_preparation.state_preparation_alias_sampling._STATE_PREP_ALIAS_DOC, - qualtran.bloqs.state_preparation.state_preparation_alias_sampling._SPARSE_STATE_PREP_ALIAS_DOC, - ], - ), - NotebookSpecV2( - title='State Preparation Using Rotations', - module=qualtran.bloqs.state_preparation.state_preparation_via_rotation, - bloq_specs=[ - qualtran.bloqs.state_preparation.state_preparation_via_rotation._STATE_PREP_VIA_ROTATIONS_DOC - ], - directory=f'{SOURCE_DIR}/bloqs/state_preparation/', - ), - NotebookSpecV2( - title='Generalized Quantum Signal Processing', - module=qualtran.bloqs.qsp.generalized_qsp, - bloq_specs=[qualtran.bloqs.qsp.generalized_qsp._Generalized_QSP_DOC], - ), - NotebookSpecV2( - title='Hamiltonian Simulation by Generalized Quantum Signal Processing', - module=qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp, - bloq_specs=[ - qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp._Hamiltonian_Simulation_by_GQSP_DOC - ], - ), -] +from qualtran_dev_tools.notebook_specs import GIT_ROOT, NB_BY_SECTION, SOURCE_DIR # -------------------------------------------------------------------------- # ----- Concepts ------------------------------------------------------- @@ -894,17 +67,6 @@ 'state_preparation/state_preparation_via_rotation_tutorial.ipynb', ] -NB_BY_SECTION = [ - ('Basic Gates', BASIC_GATES), - ('Chemistry', CHEMISTRY), - ('Arithmetic', ARITHMETIC), - ('Modular Arithmetic', MOD_ARITHMETIC), - ('GF Arithmetic', GF_ARITHMETIC), - ('Rotations', ROT_QFT_PE), - ('Block Encoding', BLOCK_ENCODING), - ('Other', OTHER), -] - def _all_nbspecs() -> Iterable[NotebookSpecV2]: for _, nbspecs in NB_BY_SECTION: diff --git a/dev_tools/bibliography.ipynb b/dev_tools/bibliography.ipynb index 038aaabfa..f91482a3f 100644 --- a/dev_tools/bibliography.ipynb +++ b/dev_tools/bibliography.ipynb @@ -129,7 +129,7 @@ "metadata": {}, "outputs": [], "source": [ - "for url, clss in backrefs.items():\n", + "for url, clss in sorted(backrefs.items(), key=lambda x: -len(x[1])):\n", " text = f'### [{titles[url]}]({url})\\n'\n", " for cls in clss:\n", " text += f' - {cls.__name__}\\n'\n", diff --git a/dev_tools/qualtran_dev_tools/notebook_specs.py b/dev_tools/qualtran_dev_tools/notebook_specs.py new file mode 100644 index 000000000..f96b511e4 --- /dev/null +++ b/dev_tools/qualtran_dev_tools/notebook_specs.py @@ -0,0 +1,869 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""List of Jupyter notebooks. + +The notebooks listed in this file are used to generate Jupyter notebooks that +document and provide examples for each of the bloqs. This list is also used to +generate the static exports for the Qualtran web UI. + +## Adding a new bloq. + + 1. Create a qualtran.BloqExample perhaps using the `@bloq_example` decorator. Wrap it in a + `qualtran.BloqDocSpec`. This code should live alongside the bloq. + 2. If this is a new module: add a new entry to the appropriate notebook spec global variable + in this file (according to its category/organization). + 3. Update the `NotebookSpec` `bloq_specs` field to include the `BloqDocSpec` for your new bloq. +""" + +from typing import List + +from qualtran_dev_tools.git_tools import get_git_root + +import qualtran.bloqs.arithmetic.addition +import qualtran.bloqs.arithmetic.bitwise +import qualtran.bloqs.arithmetic.comparison +import qualtran.bloqs.arithmetic.controlled_add_or_subtract +import qualtran.bloqs.arithmetic.controlled_addition +import qualtran.bloqs.arithmetic.conversions +import qualtran.bloqs.arithmetic.multiplication +import qualtran.bloqs.arithmetic.negate +import qualtran.bloqs.arithmetic.permutation +import qualtran.bloqs.arithmetic.sorting +import qualtran.bloqs.arithmetic.subtraction +import qualtran.bloqs.arithmetic.trigonometric +import qualtran.bloqs.basic_gates.swap +import qualtran.bloqs.block_encoding.block_encoding_base +import qualtran.bloqs.block_encoding.chebyshev_polynomial +import qualtran.bloqs.block_encoding.lcu_block_encoding +import qualtran.bloqs.block_encoding.linear_combination +import qualtran.bloqs.block_encoding.phase +import qualtran.bloqs.block_encoding.product +import qualtran.bloqs.block_encoding.sparse_matrix +import qualtran.bloqs.block_encoding.tensor_product +import qualtran.bloqs.block_encoding.unitary +import qualtran.bloqs.bookkeeping +import qualtran.bloqs.bookkeeping.allocate +import qualtran.bloqs.bookkeeping.auto_partition +import qualtran.bloqs.bookkeeping.cast +import qualtran.bloqs.bookkeeping.free +import qualtran.bloqs.bookkeeping.join +import qualtran.bloqs.bookkeeping.partition +import qualtran.bloqs.bookkeeping.split +import qualtran.bloqs.chemistry.df.double_factorization +import qualtran.bloqs.chemistry.hubbard_model.qubitization +import qualtran.bloqs.chemistry.pbc.first_quantization.prepare_t +import qualtran.bloqs.chemistry.pbc.first_quantization.prepare_uv +import qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare +import qualtran.bloqs.chemistry.pbc.first_quantization.select_t +import qualtran.bloqs.chemistry.pbc.first_quantization.select_uv +import qualtran.bloqs.chemistry.quad_fermion.givens_bloq +import qualtran.bloqs.chemistry.sf.single_factorization +import qualtran.bloqs.chemistry.sparse.prepare +import qualtran.bloqs.chemistry.sparse.walk_operator +import qualtran.bloqs.chemistry.thc.prepare +import qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt +import qualtran.bloqs.chemistry.trotter.grid_ham.qvr +import qualtran.bloqs.chemistry.trotter.hubbard.hopping +import qualtran.bloqs.chemistry.trotter.hubbard.interaction +import qualtran.bloqs.chemistry.trotter.ising.unitaries +import qualtran.bloqs.chemistry.trotter.trotterized_unitary +import qualtran.bloqs.data_loading.qrom +import qualtran.bloqs.data_loading.qrom_base +import qualtran.bloqs.data_loading.select_swap_qrom +import qualtran.bloqs.factoring.ecc +import qualtran.bloqs.factoring.mod_exp +import qualtran.bloqs.gf_arithmetic.gf2_add_k +import qualtran.bloqs.gf_arithmetic.gf2_addition +import qualtran.bloqs.gf_arithmetic.gf2_inverse +import qualtran.bloqs.gf_arithmetic.gf2_multiplication +import qualtran.bloqs.gf_arithmetic.gf2_square +import qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp +import qualtran.bloqs.mcmt.and_bloq +import qualtran.bloqs.mcmt.controlled_via_and +import qualtran.bloqs.mcmt.ctrl_spec_and +import qualtran.bloqs.mcmt.multi_control_pauli +import qualtran.bloqs.mcmt.multi_target_cnot +import qualtran.bloqs.mod_arithmetic.mod_addition +import qualtran.bloqs.multiplexers.apply_gate_to_lth_target +import qualtran.bloqs.multiplexers.apply_lth_bloq +import qualtran.bloqs.multiplexers.black_box_select +import qualtran.bloqs.multiplexers.select_base +import qualtran.bloqs.multiplexers.select_pauli_lcu +import qualtran.bloqs.phase_estimation.lp_resource_state +import qualtran.bloqs.phase_estimation.qubitization_qpe +import qualtran.bloqs.phase_estimation.text_book_qpe +import qualtran.bloqs.qft.approximate_qft +import qualtran.bloqs.qft.qft_phase_gradient +import qualtran.bloqs.qft.qft_text_book +import qualtran.bloqs.qft.two_bit_ffft +import qualtran.bloqs.qsp.generalized_qsp +import qualtran.bloqs.qubitization.qubitization_walk_operator +import qualtran.bloqs.reflections +import qualtran.bloqs.reflections.prepare_identity +import qualtran.bloqs.reflections.reflection_using_prepare +import qualtran.bloqs.rotations.hamming_weight_phasing +import qualtran.bloqs.rotations.phase_gradient +import qualtran.bloqs.rotations.phasing_via_cost_function +import qualtran.bloqs.rotations.programmable_rotation_gate_array +import qualtran.bloqs.rotations.quantum_variable_rotation +import qualtran.bloqs.state_preparation.black_box_prepare +import qualtran.bloqs.state_preparation.prepare_base +import qualtran.bloqs.state_preparation.prepare_uniform_superposition +import qualtran.bloqs.state_preparation.state_preparation_alias_sampling +import qualtran.bloqs.state_preparation.state_preparation_via_rotation +import qualtran.bloqs.swap_network.cswap_approx +import qualtran.bloqs.swap_network.multiplexed_cswap +import qualtran.bloqs.swap_network.swap_with_zero + +from .jupyter_autogen import NotebookSpecV2 + +GIT_ROOT = get_git_root() +SOURCE_DIR = GIT_ROOT / 'qualtran/' + +# -------------------------------------------------------------------------- +# ----- Basic Gates ---------------------------------------------------- +# -------------------------------------------------------------------------- +BASIC_GATES: List[NotebookSpecV2] = [ + NotebookSpecV2( + title='T Gate', + module=qualtran.bloqs.basic_gates.t_gate, + bloq_specs=[qualtran.bloqs.basic_gates.t_gate._T_GATE_DOC], + ), + NotebookSpecV2( + title='Toffoli', + module=qualtran.bloqs.basic_gates.toffoli, + bloq_specs=[qualtran.bloqs.basic_gates.toffoli._TOFFOLI_DOC], + ), + NotebookSpecV2( + title='Hadamard', + module=qualtran.bloqs.basic_gates.hadamard, + bloq_specs=[ + qualtran.bloqs.basic_gates.hadamard._HADAMARD_DOC, + qualtran.bloqs.basic_gates.hadamard._CHADAMARD_DOC, + ], + ), + NotebookSpecV2( + title='CNOT', + module=qualtran.bloqs.basic_gates.cnot, + bloq_specs=[qualtran.bloqs.basic_gates.cnot._CNOT_DOC], + ), + NotebookSpecV2( + title='Z, S, and CZ', + module=qualtran.bloqs.basic_gates.z_basis, + path_stem='diag_gates', + bloq_specs=[ + qualtran.bloqs.basic_gates.z_basis._Z_GATE_DOC, + qualtran.bloqs.basic_gates.s_gate._S_GATE_DOC, + qualtran.bloqs.basic_gates.z_basis._CZ_DOC, + ], + ), + NotebookSpecV2( + title='Y Gate', + module=qualtran.bloqs.basic_gates.y_gate, + bloq_specs=[ + qualtran.bloqs.basic_gates.y_gate._Y_GATE_DOC, + qualtran.bloqs.basic_gates.y_gate._CY_GATE_DOC, + ], + ), + NotebookSpecV2( + title='And', + module=qualtran.bloqs.mcmt.and_bloq, + bloq_specs=[ + qualtran.bloqs.mcmt.and_bloq._AND_DOC, + qualtran.bloqs.mcmt.and_bloq._MULTI_AND_DOC, + ], + ), + NotebookSpecV2( + title='States and Effects', + module=qualtran.bloqs.basic_gates.z_basis, + path_stem='states_and_effects', + bloq_specs=[ + qualtran.bloqs.basic_gates.z_basis._ZERO_STATE_DOC, + qualtran.bloqs.basic_gates.z_basis._ZERO_EFFECT_DOC, + qualtran.bloqs.basic_gates.z_basis._ONE_STATE_DOC, + qualtran.bloqs.basic_gates.z_basis._ONE_EFFECT_DOC, + qualtran.bloqs.basic_gates.z_basis._INT_STATE_DOC, + qualtran.bloqs.basic_gates.z_basis._INT_EFFECT_DOC, + qualtran.bloqs.basic_gates.x_basis._PLUS_STATE_DOC, + qualtran.bloqs.basic_gates.x_basis._PLUS_EFFECT_DOC, + qualtran.bloqs.basic_gates.x_basis._MINUS_STATE_DOC, + qualtran.bloqs.basic_gates.x_basis._MINUS_EFFECT_DOC, + ], + ), + NotebookSpecV2( + title='Basic Swaps', + module=qualtran.bloqs.basic_gates.swap, + bloq_specs=[ + qualtran.bloqs.basic_gates.swap._TWO_BIT_SWAP_DOC, + qualtran.bloqs.basic_gates.swap._TWO_BIT_CSWAP_DOC, + qualtran.bloqs.basic_gates.swap._SWAP_DOC, + qualtran.bloqs.basic_gates.swap._CSWAP_DOC, + ], + ), + NotebookSpecV2( + title='Swap Networks', + module=qualtran.bloqs.swap_network, + bloq_specs=[ + qualtran.bloqs.swap_network.cswap_approx._APPROX_CSWAP_DOC, + qualtran.bloqs.swap_network.swap_with_zero._SWZ_DOC, + qualtran.bloqs.swap_network.multiplexed_cswap._MULTIPLEXED_CSWAP_DOC, + ], + ), + NotebookSpecV2( + title='Global Phase', + module=qualtran.bloqs.basic_gates.global_phase, + bloq_specs=[qualtran.bloqs.basic_gates.global_phase._GLOBAL_PHASE_DOC], + ), + NotebookSpecV2( + title='Identity Gate', + module=qualtran.bloqs.basic_gates.identity, + bloq_specs=[qualtran.bloqs.basic_gates.identity._IDENTITY_DOC], + ), + NotebookSpecV2( + title='Bookkeeping Bloqs', + module=qualtran.bloqs.bookkeeping, + bloq_specs=[ + qualtran.bloqs.bookkeeping.allocate._ALLOC_DOC, + qualtran.bloqs.bookkeeping.free._FREE_DOC, + qualtran.bloqs.bookkeeping.split._SPLIT_DOC, + qualtran.bloqs.bookkeeping.join._JOIN_DOC, + qualtran.bloqs.bookkeeping.partition._PARTITION_DOC, + qualtran.bloqs.bookkeeping.auto_partition._AUTO_PARTITION_DOC, + qualtran.bloqs.bookkeeping.cast._CAST_DOC, + ], + ), + NotebookSpecV2( + title='Control Specification (And)', + module=qualtran.bloqs.mcmt.ctrl_spec_and, + bloq_specs=[qualtran.bloqs.mcmt.ctrl_spec_and._CTRLSPEC_AND_DOC], + ), + NotebookSpecV2( + title='Multi control bloq via single control bloq and `And` ladder', + module=qualtran.bloqs.mcmt.controlled_via_and, + bloq_specs=[qualtran.bloqs.mcmt.controlled_via_and._CONTROLLED_VIA_AND_DOC], + ), +] + + +# -------------------------------------------------------------------------- +# ----- Chemistry ------------------------------------------------------ +# -------------------------------------------------------------------------- +CHEMISTRY: List[NotebookSpecV2] = [ + NotebookSpecV2( + title='Sparse', + module=qualtran.bloqs.chemistry.sparse, + bloq_specs=[ + qualtran.bloqs.chemistry.sparse.prepare._SPARSE_PREPARE, + qualtran.bloqs.chemistry.sparse.select_bloq._SPARSE_SELECT, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/sparse', + ), + NotebookSpecV2( + title='Single Factorization', + module=qualtran.bloqs.chemistry.sf.single_factorization, + bloq_specs=[ + qualtran.bloqs.chemistry.sf.single_factorization._SF_ONE_BODY, + qualtran.bloqs.chemistry.sf.single_factorization._SF_BLOCK_ENCODING, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/sf', + ), + NotebookSpecV2( + title='Double Factorization', + module=qualtran.bloqs.chemistry.df.double_factorization, + bloq_specs=[ + qualtran.bloqs.chemistry.df.double_factorization._DF_ONE_BODY, + qualtran.bloqs.chemistry.df.double_factorization._DF_BLOCK_ENCODING, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/df', + ), + NotebookSpecV2( + title='Tensor Hypercontraction', + module=qualtran.bloqs.chemistry.thc, + bloq_specs=[ + qualtran.bloqs.chemistry.thc.prepare._THC_UNI_PREP, + qualtran.bloqs.chemistry.thc.prepare._THC_PREPARE, + qualtran.bloqs.chemistry.thc.select_bloq._THC_SELECT, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/thc', + ), + NotebookSpecV2( + title='First Quantized Hamiltonian', + module=qualtran.bloqs.chemistry.pbc.first_quantization, + bloq_specs=[ + qualtran.bloqs.chemistry.pbc.first_quantization.select_and_prepare._FIRST_QUANTIZED_PREPARE_DOC, + qualtran.bloqs.chemistry.pbc.first_quantization.select_and_prepare._FIRST_QUANTIZED_SELECT_DOC, + qualtran.bloqs.chemistry.pbc.first_quantization.prepare_t._PREPARE_T, + qualtran.bloqs.chemistry.pbc.first_quantization.prepare_uv._PREPARE_UV, + qualtran.bloqs.chemistry.pbc.first_quantization.select_t._SELECT_T, + qualtran.bloqs.chemistry.pbc.first_quantization.select_uv._SELECT_UV, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/pbc/first_quantization', + ), + NotebookSpecV2( + title='First Quantized Hamiltonian with Quantum Projectile', + module=qualtran.bloqs.chemistry.pbc.first_quantization.projectile, + bloq_specs=[ + qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare._FIRST_QUANTIZED_WITH_PROJ_PREPARE_DOC, + qualtran.bloqs.chemistry.pbc.first_quantization.projectile.select_and_prepare._FIRST_QUANTIZED_WITH_PROJ_SELECT_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/pbc/first_quantization/projectile', + ), + NotebookSpecV2( + title='Trotter Bloqs', + module=qualtran.bloqs.chemistry.trotter.grid_ham, + bloq_specs=[ + qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt._POLY_INV_SQRT, + qualtran.bloqs.chemistry.trotter.grid_ham.inverse_sqrt._NR_INV_SQRT, + qualtran.bloqs.chemistry.trotter.grid_ham.qvr._QVR, + qualtran.bloqs.chemistry.trotter.grid_ham.kinetic._KINETIC_ENERGY, + qualtran.bloqs.chemistry.trotter.grid_ham.potential._PAIR_POTENTIAL, + qualtran.bloqs.chemistry.trotter.grid_ham.potential._POTENTIAL_ENERGY, + ], + path_stem='trotter', + ), + NotebookSpecV2( + title='Trotterization', + module=qualtran.bloqs.chemistry.trotter.trotterized_unitary, + bloq_specs=[qualtran.bloqs.chemistry.trotter.trotterized_unitary._TROTT_UNITARY_DOC], + directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter', + ), + NotebookSpecV2( + title='Ising Trotter Bloqs', + module=qualtran.bloqs.chemistry.trotter.ising, + bloq_specs=[ + qualtran.bloqs.chemistry.trotter.ising.unitaries._ISING_X_UNITARY_DOC, + qualtran.bloqs.chemistry.trotter.ising.unitaries._ISING_ZZ_UNITARY_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter/ising', + ), + NotebookSpecV2( + title='Trotterized Hubbard', + module=qualtran.bloqs.chemistry.trotter.hubbard, + bloq_specs=[ + qualtran.bloqs.chemistry.trotter.hubbard.hopping._HOPPING_DOC, + qualtran.bloqs.chemistry.trotter.hubbard.hopping._PLAQUETTE_DOC, + qualtran.bloqs.chemistry.trotter.hubbard.hopping._HOPPING_TILE_HWP_DOC, + qualtran.bloqs.chemistry.trotter.hubbard.interaction._INTERACTION_DOC, + qualtran.bloqs.chemistry.trotter.hubbard.interaction._INTERACTION_HWP_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/chemistry/trotter/hubbard', + ), + NotebookSpecV2( + title='Givens Rotations', + module=qualtran.bloqs.chemistry.quad_fermion.givens_bloq, + bloq_specs=[ + qualtran.bloqs.chemistry.quad_fermion.givens_bloq._REAL_GIVENS_DOC, + qualtran.bloqs.chemistry.quad_fermion.givens_bloq._CPLX_GIVENS_DOC, + ], + ), +] + +# -------------------------------------------------------------------------- +# ----- Arithmetic ----------------------------------------------------- +# -------------------------------------------------------------------------- +ARITHMETIC = [ + NotebookSpecV2( + title='Addition', + module=qualtran.bloqs.arithmetic.addition, + bloq_specs=[ + qualtran.bloqs.arithmetic.addition._ADD_DOC, + qualtran.bloqs.arithmetic.addition._ADD_OOP_DOC, + qualtran.bloqs.arithmetic.addition._ADD_K_DOC, + ], + ), + NotebookSpecV2( + title='Controlled Addition', + module=qualtran.bloqs.arithmetic.controlled_addition, + bloq_specs=[qualtran.bloqs.arithmetic.controlled_addition._CADD_DOC], + ), + NotebookSpecV2( + title='Negation', + module=qualtran.bloqs.arithmetic.negate, + bloq_specs=[qualtran.bloqs.arithmetic.negate._NEGATE_DOC], + ), + NotebookSpecV2( + title='Subtraction', + module=qualtran.bloqs.arithmetic.subtraction, + bloq_specs=[ + qualtran.bloqs.arithmetic.subtraction._SUB_DOC, + qualtran.bloqs.arithmetic.subtraction._SUB_FROM_DOC, + ], + ), + NotebookSpecV2( + title='Controlled Add-or-Subtract', + module=qualtran.bloqs.arithmetic.controlled_add_or_subtract, + bloq_specs=[ + qualtran.bloqs.arithmetic.controlled_add_or_subtract._CONTROLLED_ADD_OR_SUBTRACT_DOC + ], + ), + NotebookSpecV2( + title='Multiplication', + module=qualtran.bloqs.arithmetic.multiplication, + bloq_specs=[ + qualtran.bloqs.arithmetic.multiplication._PLUS_EQUALS_PRODUCT_DOC, + qualtran.bloqs.arithmetic.multiplication._PRODUCT_DOC, + qualtran.bloqs.arithmetic.multiplication._SQUARE_DOC, + qualtran.bloqs.arithmetic.multiplication._SUM_OF_SQUARES_DOC, + qualtran.bloqs.arithmetic.multiplication._SCALE_INT_BY_REAL_DOC, + qualtran.bloqs.arithmetic.multiplication._MULTIPLY_TWO_REALS_DOC, + qualtran.bloqs.arithmetic.multiplication._SQUARE_REAL_NUMBER_DOC, + qualtran.bloqs.arithmetic.multiplication._INVERT_REAL_NUMBER_DOC, + ], + ), + NotebookSpecV2( + title='Comparison', + module=qualtran.bloqs.arithmetic.comparison, + bloq_specs=[ + qualtran.bloqs.arithmetic.comparison._LT_K_DOC, + qualtran.bloqs.arithmetic.comparison._GREATER_THAN_DOC, + qualtran.bloqs.arithmetic.comparison._GREATER_THAN_K_DOC, + qualtran.bloqs.arithmetic.comparison._EQUALS_DOC, + qualtran.bloqs.arithmetic.comparison._EQUALS_K_DOC, + qualtran.bloqs.arithmetic.comparison._BI_QUBITS_MIXER_DOC, + qualtran.bloqs.arithmetic.comparison._SQ_CMP_DOC, + qualtran.bloqs.arithmetic.comparison._LEQ_DOC, + qualtran.bloqs.arithmetic.comparison._CLinearDepthGreaterThan_DOC, + ], + ), + NotebookSpecV2( + title='Integer Conversions', + module=qualtran.bloqs.arithmetic.conversions, + bloq_specs=[ + qualtran.bloqs.arithmetic.conversions.ones_complement_to_twos_complement._SIGNED_TO_TWOS, + qualtran.bloqs.arithmetic.conversions.sign_extension._SIGN_EXTEND_DOC, + qualtran.bloqs.arithmetic.conversions.sign_extension._SIGN_TRUNCATE_DOC, + ], + ), + NotebookSpecV2( + title='Sorting', + module=qualtran.bloqs.arithmetic.sorting, + bloq_specs=[ + qualtran.bloqs.arithmetic.sorting._COMPARATOR_DOC, + qualtran.bloqs.arithmetic.sorting._PARALLEL_COMPARATORS_DOC, + qualtran.bloqs.arithmetic.sorting._BITONIC_MERGE_DOC, + qualtran.bloqs.arithmetic.sorting._BITONIC_SORT_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/arithmetic/', + ), + NotebookSpecV2( + title='Indexing', + module=qualtran.bloqs.arithmetic.conversions.contiguous_index, + bloq_specs=[qualtran.bloqs.arithmetic.conversions.contiguous_index._TO_CONTG_INDX], + ), + NotebookSpecV2( + title='Permutations', + module=qualtran.bloqs.arithmetic.permutation, + bloq_specs=[ + qualtran.bloqs.arithmetic.permutation._PERMUTATION_DOC, + qualtran.bloqs.arithmetic.permutation._PERMUTATION_CYCLE_DOC, + ], + ), + NotebookSpecV2( + title='Bitwise Operations', + module=qualtran.bloqs.arithmetic.bitwise, + bloq_specs=[ + qualtran.bloqs.arithmetic.bitwise._XOR_DOC, + qualtran.bloqs.arithmetic.bitwise._BITWISE_NOT_DOC, + ], + ), + NotebookSpecV2( + title='Trigonometric Functions', + module=qualtran.bloqs.arithmetic.trigonometric, + bloq_specs=[qualtran.bloqs.arithmetic.trigonometric.arcsin._ARCSIN_DOC], + ), +] + +MOD_ARITHMETIC = [ + NotebookSpecV2( + title='Modular Addition', + module=qualtran.bloqs.mod_arithmetic.mod_addition, + bloq_specs=[ + qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_DOC, + qualtran.bloqs.mod_arithmetic.mod_addition._MOD_ADD_K_DOC, + qualtran.bloqs.mod_arithmetic.mod_addition._C_MOD_ADD_DOC, + ], + ), + NotebookSpecV2( + title='Modular Subtraction', + module=qualtran.bloqs.mod_arithmetic.mod_subtraction, + bloq_specs=[ + qualtran.bloqs.mod_arithmetic.mod_subtraction._MOD_NEG_DOC, + qualtran.bloqs.mod_arithmetic.mod_subtraction._CMOD_NEG_DOC, + qualtran.bloqs.mod_arithmetic.mod_subtraction._MOD_SUB_DOC, + qualtran.bloqs.mod_arithmetic.mod_subtraction._CMOD_SUB_DOC, + ], + ), + NotebookSpecV2( + title='Modular Multiplication', + module=qualtran.bloqs.mod_arithmetic.mod_multiplication, + bloq_specs=[ + qualtran.bloqs.mod_arithmetic.mod_multiplication._MOD_DBL_DOC, + qualtran.bloqs.mod_arithmetic.mod_multiplication._C_MOD_MUL_K_DOC, + qualtran.bloqs.mod_arithmetic.mod_multiplication._DIRTY_OUT_OF_PLACE_MONTGOMERY_MOD_MUL_DOC, + ], + ), + NotebookSpecV2( + title='Modular Exponentiation', + module=qualtran.bloqs.factoring.mod_exp, + bloq_specs=[qualtran.bloqs.factoring.mod_exp._MODEXP_DOC], + directory=f'{SOURCE_DIR}/bloqs/factoring', + ), + NotebookSpecV2( + title='Elliptic Curve Addition', + module=qualtran.bloqs.factoring.ecc.ec_add, + bloq_specs=[qualtran.bloqs.factoring.ecc.ec_add._EC_ADD_DOC], + ), + NotebookSpecV2( + title='Elliptic Curve Cryptography', + module=qualtran.bloqs.factoring.ecc, + bloq_specs=[ + qualtran.bloqs.factoring.ecc.find_ecc_private_key._ECC_BLOQ_DOC, + qualtran.bloqs.factoring.ecc.ec_phase_estimate_r._EC_PE_BLOQ_DOC, + qualtran.bloqs.factoring.ecc.ec_add_r._ECC_ADD_R_BLOQ_DOC, + qualtran.bloqs.factoring.ecc.ec_add_r._EC_WINDOW_ADD_BLOQ_DOC, + ], + ), +] + +GF_ARITHMETIC = [ + # -------------------------------------------------------------------------- + # ----- Galois Fields (GF) Arithmetic --------------------------------- + # -------------------------------------------------------------------------- + NotebookSpecV2( + title='GF($2^m$) Multiplication', + module=qualtran.bloqs.gf_arithmetic.gf2_multiplication, + bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_multiplication._GF2_MULTIPLICATION_DOC], + ), + NotebookSpecV2( + title='GF($2^m$) Addition', + module=qualtran.bloqs.gf_arithmetic.gf2_addition, + bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_addition._GF2_ADDITION_DOC], + ), + NotebookSpecV2( + title='GF($2^m$) Add Constant', + module=qualtran.bloqs.gf_arithmetic.gf2_add_k, + bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_add_k._GF2_ADD_K_DOC], + ), + NotebookSpecV2( + title='GF($2^m$) Square', + module=qualtran.bloqs.gf_arithmetic.gf2_square, + bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_square._GF2_SQUARE_DOC], + ), + NotebookSpecV2( + title='GF($2^m$) Inverse', + module=qualtran.bloqs.gf_arithmetic.gf2_inverse, + bloq_specs=[qualtran.bloqs.gf_arithmetic.gf2_inverse._GF2_INVERSE_DOC], + ), +] + + +ROT_QFT_PE = [ + # -------------------------------------------------------------------------- + # ----- Rotations ----------------------------------------------------- + # -------------------------------------------------------------------------- + NotebookSpecV2( + title='Basic Rotation Gates', + module=qualtran.bloqs.basic_gates.rotation, + bloq_specs=[ + qualtran.bloqs.basic_gates.rotation._X_POW_DOC, + qualtran.bloqs.basic_gates.rotation._Y_POW_DOC, + qualtran.bloqs.basic_gates.rotation._Z_POW_DOC, + ], + ), + NotebookSpecV2( + title='SU2 Rotation', + module=qualtran.bloqs.basic_gates.su2_rotation, + bloq_specs=[qualtran.bloqs.basic_gates.su2_rotation._SU2_ROTATION_GATE_DOC], + ), + NotebookSpecV2( + title='Quantum Variable Rotation', + module=qualtran.bloqs.rotations.quantum_variable_rotation, + bloq_specs=[ + qualtran.bloqs.rotations.quantum_variable_rotation._QVR_ZPOW, + qualtran.bloqs.rotations.quantum_variable_rotation._QVR_PHASE_GRADIENT, + ], + directory=f'{SOURCE_DIR}/bloqs/rotations/', + ), + NotebookSpecV2( + title='Phasing via Cost function', + module=qualtran.bloqs.rotations.phasing_via_cost_function, + bloq_specs=[qualtran.bloqs.rotations.phasing_via_cost_function._PHASING_VIA_COST_FUNCTION], + directory=f'{SOURCE_DIR}/bloqs/rotations/', + ), + NotebookSpecV2( + title='Rotations via Phase Gradients', + module=qualtran.bloqs.rotations.phase_gradient, + bloq_specs=[ + qualtran.bloqs.rotations.phase_gradient._PHASE_GRADIENT_UNITARY_DOC, + qualtran.bloqs.rotations.phase_gradient._PHASE_GRADIENT_STATE_DOC, + qualtran.bloqs.rotations.phase_gradient._ADD_INTO_PHASE_GRAD_DOC, + qualtran.bloqs.rotations.phase_gradient._ADD_SCALED_VAL_INTO_PHASE_REG_DOC, + ], + ), + NotebookSpecV2( + title='Z Rotations via Hamming Weight Phasing', + module=qualtran.bloqs.rotations.hamming_weight_phasing, + bloq_specs=[ + qualtran.bloqs.rotations.hamming_weight_phasing._HAMMING_WEIGHT_PHASING_DOC, + qualtran.bloqs.rotations.hamming_weight_phasing._HAMMING_WEIGHT_PHASING_VIA_PHASE_GRADIENT_DOC, + ], + ), + NotebookSpecV2( + title='Programmable Rotation Gate Array', + module=qualtran.bloqs.rotations.programmable_rotation_gate_array, + bloq_specs=[ + qualtran.bloqs.rotations.programmable_rotation_gate_array._PROGRAMMABLE_ROTATAION_GATE_ARRAY_DOC + ], + ), + # -------------------------------------------------------------------------- + # ----- QFT ----------------------------------------------------- + # -------------------------------------------------------------------------- + NotebookSpecV2( + title='Two Bit FFFT Gate', + module=qualtran.bloqs.qft.two_bit_ffft, + bloq_specs=[qualtran.bloqs.qft.two_bit_ffft._TWO_BIT_FFFT_DOC], + ), + NotebookSpecV2( + title='Approximate QFT', + module=qualtran.bloqs.qft.approximate_qft, + bloq_specs=[qualtran.bloqs.qft.approximate_qft._CC_AQFT_DOC], + ), + NotebookSpecV2( + title='Textbook QFT', + module=qualtran.bloqs.qft.qft_text_book, + bloq_specs=[qualtran.bloqs.qft.qft_text_book._QFT_TEXT_BOOK_DOC], + ), + NotebookSpecV2( + title='Phase Gradient QFT', + module=qualtran.bloqs.qft.qft_phase_gradient, + bloq_specs=[qualtran.bloqs.qft.qft_phase_gradient._QFT_PHASE_GRADIENT_DOC], + ), + # -------------------------------------------------------------------------- + # ----- Phase Estimation ---------------------------------------- + # -------------------------------------------------------------------------- + NotebookSpecV2( + title='Optimal resource states for Phase Estimation by A. Luis and J. Peřina', + module=qualtran.bloqs.phase_estimation.lp_resource_state, + bloq_specs=[ + qualtran.bloqs.phase_estimation.lp_resource_state._CC_LPRS_INTERIM_PREP_DOC, + qualtran.bloqs.phase_estimation.lp_resource_state._CC_LP_RESOURCE_STATE_DOC, + ], + ), + NotebookSpecV2( + title='Textbook Quantum Phase Estimation', + module=qualtran.bloqs.phase_estimation.text_book_qpe, + bloq_specs=[ + qualtran.bloqs.phase_estimation.qpe_window_state._CC_RECTANGULAR_WINDOW_STATE_DOC, + qualtran.bloqs.phase_estimation.text_book_qpe._CC_TEXTBOOK_PHASE_ESTIMATION_DOC, + ], + ), + NotebookSpecV2( + title='Kaiser Window State for Quantum Phase Estimation', + module=qualtran.bloqs.phase_estimation.kaiser_window_state, + bloq_specs=[ + qualtran.bloqs.phase_estimation.kaiser_window_state._CC_KAISER_WINDOW_STATE_DOC + ], + ), + NotebookSpecV2( + title='Qubitization Walk Operator', + module=qualtran.bloqs.qubitization.qubitization_walk_operator, + bloq_specs=[qualtran.bloqs.qubitization.qubitization_walk_operator._QUBITIZATION_WALK_DOC], + ), + NotebookSpecV2( + title='Qubitization Phase Estimation', + module=qualtran.bloqs.phase_estimation.qubitization_qpe, + bloq_specs=[qualtran.bloqs.phase_estimation.qubitization_qpe._QUBITIZATION_QPE_DOC], + ), +] + +# -------------------------------------------------------------------------- +# ----- Block Encoding ---------------------------------------------------------- +# -------------------------------------------------------------------------- +BLOCK_ENCODING: List[NotebookSpecV2] = [ + NotebookSpecV2( + title='Block Encoding Interface', + module=qualtran.bloqs.block_encoding, + bloq_specs=[qualtran.bloqs.block_encoding.block_encoding_base._BLOCK_ENCODING_DOC], + ), + NotebookSpecV2( + title='Unitary', + module=qualtran.bloqs.block_encoding.unitary, + bloq_specs=[qualtran.bloqs.block_encoding.unitary._UNITARY_DOC], + ), + NotebookSpecV2( + title='Tensor Product', + module=qualtran.bloqs.block_encoding.tensor_product, + bloq_specs=[qualtran.bloqs.block_encoding.tensor_product._TENSOR_PRODUCT_DOC], + ), + NotebookSpecV2( + title='Product', + module=qualtran.bloqs.block_encoding.product, + bloq_specs=[qualtran.bloqs.block_encoding.product._PRODUCT_DOC], + ), + NotebookSpecV2( + title='Phase', + module=qualtran.bloqs.block_encoding.phase, + bloq_specs=[qualtran.bloqs.block_encoding.phase._PHASE_DOC], + ), + NotebookSpecV2( + title='Linear Combination', + module=qualtran.bloqs.block_encoding.linear_combination, + bloq_specs=[qualtran.bloqs.block_encoding.linear_combination._LINEAR_COMBINATION_DOC], + ), + NotebookSpecV2( + title='Sparse Matrix', + module=qualtran.bloqs.block_encoding.sparse_matrix, + bloq_specs=[qualtran.bloqs.block_encoding.sparse_matrix._SPARSE_MATRIX_DOC], + ), + NotebookSpecV2( + title='Chebyshev Polynomial', + module=qualtran.bloqs.block_encoding.chebyshev_polynomial, + bloq_specs=[ + qualtran.bloqs.block_encoding.chebyshev_polynomial._CHEBYSHEV_BLOQ_DOC, + qualtran.bloqs.block_encoding.chebyshev_polynomial._SCALED_CHEBYSHEV_BLOQ_DOC, + ], + ), + NotebookSpecV2( + title='LCU Select/Prepare Oracles', + module=qualtran.bloqs.block_encoding.lcu_block_encoding, + bloq_specs=[ + qualtran.bloqs.block_encoding.lcu_block_encoding._SELECT_BLOCK_ENCODING_DOC, + qualtran.bloqs.block_encoding.lcu_block_encoding._LCU_BLOCK_ENCODING_DOC, + qualtran.bloqs.multiplexers.select_base._SELECT_ORACLE_DOC, + qualtran.bloqs.state_preparation.prepare_base._PREPARE_ORACLE_DOC, + qualtran.bloqs.multiplexers.black_box_select._BLACK_BOX_SELECT_DOC, + qualtran.bloqs.state_preparation.black_box_prepare._BLACK_BOX_PREPARE_DOC, + ], + ), +] + +# -------------------------------------------------------------------------- +# ----- Other ---------------------------------------------------------- +# -------------------------------------------------------------------------- +OTHER: List[NotebookSpecV2] = [ + NotebookSpecV2( + title='Prepare Uniform Superposition', + module=qualtran.bloqs.state_preparation.prepare_uniform_superposition, + bloq_specs=[ + qualtran.bloqs.state_preparation.prepare_uniform_superposition._PREP_UNIFORM_DOC + ], + ), + NotebookSpecV2( + title='Qubitized Hubbard Model', + module=qualtran.bloqs.chemistry.hubbard_model.qubitization, + path_stem='hubbard_model', + bloq_specs=[ + qualtran.bloqs.chemistry.hubbard_model.qubitization.select_hubbard._SELECT_HUBBARD, + qualtran.bloqs.chemistry.hubbard_model.qubitization.prepare_hubbard._PREPARE_HUBBARD, + ], + ), + NotebookSpecV2( + title='Apply to Lth Target', + module=qualtran.bloqs.multiplexers.apply_gate_to_lth_target, + bloq_specs=[qualtran.bloqs.multiplexers.apply_gate_to_lth_target._APPLY_TO_LTH_TARGET_DOC], + ), + NotebookSpecV2( + title='Apply Lth Bloq', + module=qualtran.bloqs.multiplexers.apply_lth_bloq, + bloq_specs=[qualtran.bloqs.multiplexers.apply_lth_bloq._APPLY_LTH_BLOQ_DOC], + ), + NotebookSpecV2( + title='QROM', + module=qualtran.bloqs.data_loading.qrom, + bloq_specs=[ + qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, + qualtran.bloqs.data_loading.qrom._QROM_DOC, + ], + ), + NotebookSpecV2( + title='SelectSwapQROM', + module=qualtran.bloqs.data_loading.select_swap_qrom, + bloq_specs=[ + qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, + qualtran.bloqs.data_loading.select_swap_qrom._SELECT_SWAP_QROM_DOC, + ], + ), + NotebookSpecV2( + title='Advanced QROM (aka QROAM) using clean ancilla', + module=qualtran.bloqs.data_loading.qroam_clean, + bloq_specs=[ + qualtran.bloqs.data_loading.qrom_base._QROM_BASE_DOC, + qualtran.bloqs.data_loading.qroam_clean._QROAM_CLEAN_DOC, + ], + ), + NotebookSpecV2( + title='Reflections', + module=qualtran.bloqs.reflections, + bloq_specs=[ + qualtran.bloqs.reflections.prepare_identity._PREPARE_IDENTITY_DOC, + qualtran.bloqs.reflections.reflection_using_prepare._REFL_USING_PREP_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/reflections', + ), + NotebookSpecV2( + title='Multi-Paulis', + module=qualtran.bloqs.mcmt, + bloq_specs=[ + qualtran.bloqs.mcmt.multi_target_cnot._C_MULTI_NOT_DOC, + qualtran.bloqs.mcmt.multi_control_pauli._CC_PAULI_DOC, + ], + directory=f'{SOURCE_DIR}/bloqs/mcmt/', + path_stem='multi_control_multi_target_pauli', + ), + NotebookSpecV2( + title='Generic Select', + module=qualtran.bloqs.multiplexers.select_pauli_lcu, + bloq_specs=[qualtran.bloqs.multiplexers.select_pauli_lcu._SELECT_PAULI_LCU_DOC], + ), + NotebookSpecV2( + title='State Preparation via Alias Sampling', + module=qualtran.bloqs.state_preparation.state_preparation_alias_sampling, + bloq_specs=[ + qualtran.bloqs.state_preparation.state_preparation_alias_sampling._STATE_PREP_ALIAS_DOC, + qualtran.bloqs.state_preparation.state_preparation_alias_sampling._SPARSE_STATE_PREP_ALIAS_DOC, + ], + ), + NotebookSpecV2( + title='State Preparation Using Rotations', + module=qualtran.bloqs.state_preparation.state_preparation_via_rotation, + bloq_specs=[ + qualtran.bloqs.state_preparation.state_preparation_via_rotation._STATE_PREP_VIA_ROTATIONS_DOC + ], + directory=f'{SOURCE_DIR}/bloqs/state_preparation/', + ), + NotebookSpecV2( + title='Generalized Quantum Signal Processing', + module=qualtran.bloqs.qsp.generalized_qsp, + bloq_specs=[qualtran.bloqs.qsp.generalized_qsp._Generalized_QSP_DOC], + ), + NotebookSpecV2( + title='Hamiltonian Simulation by Generalized Quantum Signal Processing', + module=qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp, + bloq_specs=[ + qualtran.bloqs.hamiltonian_simulation.hamiltonian_simulation_by_gqsp._Hamiltonian_Simulation_by_GQSP_DOC + ], + ), +] + +NB_BY_SECTION = [ + ('Basic Gates', BASIC_GATES), + ('Chemistry', CHEMISTRY), + ('Arithmetic', ARITHMETIC), + ('Modular Arithmetic', MOD_ARITHMETIC), + ('GF Arithmetic', GF_ARITHMETIC), + ('Rotations', ROT_QFT_PE), + ('Block Encoding', BLOCK_ENCODING), + ('Other', OTHER), +] diff --git a/dev_tools/qualtran_dev_tools/parse_docstrings.py b/dev_tools/qualtran_dev_tools/parse_docstrings.py index f20917960..36321bece 100644 --- a/dev_tools/qualtran_dev_tools/parse_docstrings.py +++ b/dev_tools/qualtran_dev_tools/parse_docstrings.py @@ -109,7 +109,7 @@ def _template(name, desc_lines): ] -def get_markdown_docstring_lines(cls: Type) -> List[str]: +def get_markdown_docstring(cls: Type) -> List[str]: """From a class `cls`, return its docstring as Markdown lines.""" # 1. Sphinx incantation @@ -117,11 +117,20 @@ def get_markdown_docstring_lines(cls: Type) -> List[str]: docstring = cls.__doc__ if cls.__doc__ else "" gds = _GoogleDocstringToMarkdown(inspect.cleandoc(docstring), config=config, what='class') - # 2. Pre-pend a header. - lines = [f'## `{cls.__name__}`'] + gds.lines() + # 2. Substitute restructured text inline-code blocks to markdown-style backticks. + lines = [re.sub(r':py:func:`(\w+)`', r'`\1`', line) for line in gds.lines()] + + return lines + - # 3. Substitute restructured text inline-code blocks to markdown-style backticks. - lines = [re.sub(r':py:func:`(\w+)`', r'`\1`', line) for line in lines] +def get_markdown_docstring_lines(cls: Type) -> List[str]: + """From a class `cls`, return its docstring as Markdown lines with a header.""" + + # 1. Get documentation lines + lines = get_markdown_docstring(cls) + + # 2. Pre-pend a header. + lines = [f'## `{cls.__name__}`'] + lines return lines diff --git a/dev_tools/qualtran_dev_tools/tensor_report_card.py b/dev_tools/qualtran_dev_tools/tensor_report_card.py new file mode 100644 index 000000000..c2e3fa2df --- /dev/null +++ b/dev_tools/qualtran_dev_tools/tensor_report_card.py @@ -0,0 +1,152 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import multiprocessing.connection +import time +from typing import Any, Callable, Dict, List, Optional, Tuple + +from attrs import define + +from qualtran import Bloq +from qualtran.simulation.tensor import cbloq_to_quimb + + +@define +class _Pending: + """Helper dataclass to track currently executing processes in `ExecuteWithTimeout`.""" + + p: multiprocessing.Process + recv: multiprocessing.connection.Connection + start_time: float + kwargs: Dict[str, Any] + + +class ExecuteWithTimeout: + """Execute tasks in processes where each task will be killed if it exceeds `timeout`. + + Seemingly all the existing "timeout" parameters in the various built-in concurrency + primitives in Python won't actually terminate the process. This one does. + """ + + def __init__(self, timeout: float, max_workers: int): + self.timeout = timeout + self.max_workers = max_workers + + self.queued: List[Tuple[Callable, Dict[str, Any]]] = [] + self.pending: List[_Pending] = [] + + @property + def work_to_be_done(self) -> int: + """The number of tasks currently executing or queued.""" + return len(self.queued) + len(self.pending) + + def submit(self, func: Callable, kwargs: Dict[str, Any]) -> None: + """Add a task to the queue. + + `func` must be a callable that can accept `kwargs` in addition to + a keyword argument `cxn` which is a multiprocessing `Connection` object that forms + the sending-half of a `mp.Pipe`. The callable must call `cxn.send(...)` + to return a result. + """ + self.queued.append((func, kwargs)) + + def _submit_from_queue(self): + # helper method that takes an item from the queue, launches a process, + # and records it in the `pending` attribute. This must only be called + # if we're allowed to spawn a new process. + func, kwargs = self.queued.pop(0) + recv, send = multiprocessing.Pipe(duplex=False) + kwargs['cxn'] = send + p = multiprocessing.Process(target=func, kwargs=kwargs) + start_time = time.time() + p.start() + self.pending.append(_Pending(p=p, recv=recv, start_time=start_time, kwargs=kwargs)) + + def _scan_pendings(self) -> Optional[_Pending]: + # helper method that goes through the currently pending tasks, terminates the ones + # that have been going on too long, and accounts for ones that have finished. + # Returns the `_Pending` of the killed or completed job or `None` if each pending + # task is still running but none have exceeded the timeout. + for i in range(len(self.pending)): + pen = self.pending[i] + + if not pen.p.is_alive(): + self.pending.pop(i) + pen.p.join() + return pen + + if time.time() - pen.start_time > self.timeout: + pen.p.terminate() + self.pending.pop(i) + return pen + + return None + + def next_result(self) -> Tuple[Dict[str, Any], Optional[Any]]: + """Get the next available result. + + This call is blocking, but should never take longer than `self.timeout`. This should + be called in a loop to make sure the queue continues to be processed. + + Returns: + task kwargs: The keyword arguments used to submit the task. + result: If the process finished successfully, this is the object that was + sent through the multiprocessing pipe as the result. Otherwise, the result + is None. + """ + while len(self.queued) > 0 and len(self.pending) < self.max_workers: + self._submit_from_queue() + + while True: + finished = self._scan_pendings() + if finished is not None: + break + + if finished.p.exitcode == 0: + result = finished.recv.recv() + else: + result = None + + finished.recv.close() + + while len(self.queued) > 0 and len(self.pending) < self.max_workers: + self._submit_from_queue() + + return (finished.kwargs, result) + + +def report_on_tensors(name: str, cls_name: str, bloq: Bloq, cxn) -> None: + """Get timing information for tensor functionality. + + This should be used with `ExecuteWithTimeout`. The resultant + record dictionary is sent over `cxn`. + """ + record: Dict[str, Any] = {'name': name, 'cls': cls_name} + + try: + start = time.perf_counter() + flat = bloq.as_composite_bloq().flatten() + record['flat_dur'] = time.perf_counter() - start + + start = time.perf_counter() + tn = cbloq_to_quimb(flat) + record['tn_dur'] = time.perf_counter() - start + + start = time.perf_counter() + record['width'] = tn.contraction_width() + record['width_dur'] = time.perf_counter() - start + + except Exception as e: # pylint: disable=broad-exception-caught + record['err'] = str(e) + + cxn.send(record) diff --git a/dev_tools/tensor-report-card.ipynb b/dev_tools/tensor-report-card.ipynb new file mode 100644 index 000000000..49d08b1f9 --- /dev/null +++ b/dev_tools/tensor-report-card.ipynb @@ -0,0 +1,262 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "9a9335f1", + "metadata": {}, + "source": [ + "# Tensor Report Card\n", + "\n", + "Not all bloq examples support tensor simulation. This report card automatically determines which bloq examples should be tensor simulable.\n", + "\n", + " - State vector simulation uses $2^n$ numbers to simulate a quantum state. The tensor protocol uses quimb to try to find more efficient contraction orderings. Quimb reports the contraction width, which is the minimum size of any intermediate tensor encountered in the contraciton. The simulation uses $2^w$ numbers, where $w$ is the width. We consider a width under 25 qubits as simulable.\n", + " - Qualtran requires \"flattening\" out the bloq to turn it into an efficient tensor network. This may take too much time itself for large algorithms with many levels of abstraction. If the process of turning a bloq into a quimb tensor network and finding a contraction ordering takes longer than 8 seconds, we don't consider the bloq simulable.\n", + " - The flattened structure needs to have explicit tensors. For bloqs with symbolic parameters, we either can't decompose & flatten them, or the tensors would be symbolic, which we don't support." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d2bf2bc-1b55-4f68-b0f4-68f62dd68bae", + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran_dev_tools.bloq_finder import get_bloq_examples\n", + "from qualtran_dev_tools.tensor_report_card import report_on_tensors, ExecuteWithTimeout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86168342-d740-446a-bc88-06eaec8ae3a8", + "metadata": {}, + "outputs": [], + "source": [ + "bes = get_bloq_examples()\n", + "\n", + "# Imports to exclude certain bloqs, see following comment\n", + "from qualtran.bloqs.multiplexers.apply_gate_to_lth_target import ApplyGateToLthQubit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51781740-6417-4b3b-b5d8-86f51340a016", + "metadata": {}, + "outputs": [], + "source": [ + "exec = ExecuteWithTimeout(timeout=8., max_workers=4)\n", + "for i, be in enumerate(bes):\n", + "\n", + " if be.bloq_cls == ApplyGateToLthQubit:\n", + " # This bloq uses a lambda function as one of its attributes, which\n", + " # can't be pickled and used with multiprocessing.\n", + " continue\n", + " \n", + " exec.submit(report_on_tensors, kwargs=dict(name=be.name, cls_name=be.bloq_cls.__name__, bloq=be.make()))\n", + "\n", + "records = []\n", + "while exec.work_to_be_done:\n", + " kwargs, record = exec.next_result()\n", + " #print(kwargs['name'], end=' ', flush=True)\n", + " print('\\r', f'{exec.work_to_be_done:5d} remaining', end='', flush=True)\n", + " \n", + " if record is None:\n", + " records.append({\n", + " 'name': kwargs['name'],\n", + " 'cls': kwargs['cls_name'],\n", + " 'err': 'Timeout',\n", + " })\n", + " else:\n", + " records.append(record)\n", + "\n", + "import pandas as pd\n", + "df = pd.DataFrame(records)" + ] + }, + { + "cell_type": "markdown", + "id": "393a5aad-7a78-4167-8dd5-407d8a0b3241", + "metadata": {}, + "source": [ + "## Number of bloq examples considered" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d674962-27d7-40d1-9916-f0aba3457934", + "metadata": {}, + "outputs": [], + "source": [ + "print(len(df))" + ] + }, + { + "cell_type": "markdown", + "id": "6a59804e-afc6-4227-b74f-cbf82f14b773", + "metadata": {}, + "source": [ + "## Number of bloq examples successfully flattened" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8b048464-083a-4e04-8135-176f449450ca", + "metadata": {}, + "outputs": [], + "source": [ + "print(len(df[df['flat_dur'] > 0]))" + ] + }, + { + "cell_type": "markdown", + "id": "a4194f99-1551-4a5e-b93d-fb043cc56f9e", + "metadata": {}, + "source": [ + "## Number of bloq examples with tensors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5cdfa4e3-e1db-4869-832c-63695a3fd3f4", + "metadata": {}, + "outputs": [], + "source": [ + "print(len(df[df['width'] > 0]))" + ] + }, + { + "cell_type": "markdown", + "id": "05bffa4b-6bbe-4901-b1de-aba1abebe552", + "metadata": {}, + "source": [ + "## Bloqs that are tensor simulable" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "578fd2b5-9f7e-4edc-81b2-a8aad989be68", + "metadata": {}, + "outputs": [], + "source": [ + "print(len(df[df['width'] <= 25]))\n", + "df[df['width'] <= 25]" + ] + }, + { + "cell_type": "markdown", + "id": "4ef49322-cffb-4ff9-8cb1-6e5a87749492", + "metadata": {}, + "source": [ + "## Bloqs whose tensor network is too big" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d529d144-b3c5-45e5-ae14-f6d3fb86f153", + "metadata": {}, + "outputs": [], + "source": [ + "df[df['width'] > 25].sort_values(by='width')" + ] + }, + { + "cell_type": "markdown", + "id": "41141f6f-4377-4cee-9ca7-d2981c94d2e4", + "metadata": {}, + "source": [ + "## Bloqs without tensors\n", + "\n", + "Due to errors encountered in flattening or if the bloq's callees don't support tensor simulation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c3386091-491a-404f-b13d-72b401d2c267", + "metadata": {}, + "outputs": [], + "source": [ + "df[df['width'].isna()]" + ] + }, + { + "cell_type": "markdown", + "id": "46a79e7f-0715-4007-8c11-d959f8f2255b", + "metadata": {}, + "source": [ + "## Slowest to flatten\n", + "\n", + "Within the overall timeout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df522d3f-4392-46ea-851e-321d0fdfd52f", + "metadata": {}, + "outputs": [], + "source": [ + "df.sort_values(by='flat_dur', ascending=False).head()" + ] + }, + { + "cell_type": "markdown", + "id": "48f419ef-2723-42ea-8670-81a729164cf7", + "metadata": {}, + "source": [ + "## Flattening is the rate-limiting step.\n", + "\n", + "For bloqs that have been successfully flattened, the maximum tensor-network-construction and tensor-contraction-ordering durations are less than 0.5s. Note: the contraction finding code uses the fast, naive approach. One can choose more expensive approaches where the contraciton-ordering-finding is more expensive." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eae32349-ad93-4072-9704-044ef390e59e", + "metadata": {}, + "outputs": [], + "source": [ + "# Slowest tn_dur\n", + "df.sort_values(by='tn_dur', ascending=False).head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9249f813-1d42-47f4-bd1a-f198b79298f6", + "metadata": {}, + "outputs": [], + "source": [ + "# Slowest width_dur\n", + "df.sort_values(by='width_dur', ascending=False).head()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/dev_tools/ui-export.ipynb b/dev_tools/ui-export.ipynb new file mode 100644 index 000000000..c1d9d416f --- /dev/null +++ b/dev_tools/ui-export.ipynb @@ -0,0 +1,189 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from qualtran.bloqs.factoring.mod_exp import ModExp\n", + "from qualtran.drawing import get_musical_score_data, draw_musical_score\n", + "\n", + "modexp_small = ModExp(base=3, mod=16, exp_bitsize=3, x_bitsize=2048)\n", + "ms = get_musical_score_data(modexp_small.decompose_bloq())\n", + "\n", + "draw_musical_score(ms)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from sympy import Symbol\n", + "from typing import Any\n", + "\n", + "from qualtran.drawing.musical_score import MusicalScoreEncoder\n", + "from qualtran._infra.registers import Side\n", + "\n", + "class BloqEncoder(MusicalScoreEncoder):\n", + "\n", + " def default(self, o: Any) -> Any:\n", + " if isinstance(o, (Symbol)):\n", + " return f'Symbol({o})'\n", + " if isinstance(o, complex):\n", + " return f'{o.real}+{o.imag}i'\n", + " if isinstance(o, Side):\n", + " return 'Side.LEFT' if o == Side.LEFT else 'Side.RIGHT' if o == Side.RIGHT else 'Side.THRU'\n", + "\n", + " try:\n", + " return super().default(o)\n", + " except:\n", + " return 'NOT_SERIALIZABLE'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import attrs\n", + "import hashlib\n", + "\n", + "from qualtran import CompositeBloq\n", + "from qualtran.bloqs.rotations.programmable_rotation_gate_array import ProgrammableRotationGateArray\n", + "\n", + "def bloq_attrs(bloq):\n", + " if isinstance(bloq, CompositeBloq):\n", + " return {}\n", + " if isinstance(bloq, ProgrammableRotationGateArray):\n", + " return {}\n", + "\n", + " return attrs.asdict(bloq)\n", + "\n", + "def bloq_filename(bloq):\n", + " unhashed = json.dumps(bloq_attrs(bloq), cls=BloqEncoder)\n", + "\n", + " return hashlib.md5(unhashed.encode(), usedforsecurity=False).hexdigest() + '.json'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from pathlib import Path\n", + "\n", + "from qualtran_dev_tools.notebook_specs import NB_BY_SECTION\n", + "\n", + "docs_by_section = {\n", + " section[0]: {\n", + " notebook_spec.title: list(\n", + " {\n", + " 'name': bloq_spec.bloq_cls.__name__,\n", + " 'examples': list(\n", + " {\n", + " 'name': example.name,\n", + " 'filename': bloq_filename(example.make())\n", + " }\n", + " for example in bloq_spec.examples\n", + " )\n", + " }\n", + " for bloq_spec in notebook_spec.bloq_specs\n", + " )\n", + " for notebook_spec in section[1]\n", + " }\n", + " for section in NB_BY_SECTION\n", + "}\n", + "\n", + "Path('ui_export').mkdir(parents=True, exist_ok=True)\n", + "\n", + "with open('ui_export/navigation.json', 'w') as f:\n", + " json.dump(docs_by_section, f, indent=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "from pathlib import Path\n", + "\n", + "from qualtran_dev_tools.notebook_specs import NB_BY_SECTION\n", + "from qualtran_dev_tools.parse_docstrings import get_markdown_docstring\n", + "from qualtran.drawing.musical_score import get_musical_score_data\n", + "\n", + "def bloq_score(bloq):\n", + " try:\n", + " return get_musical_score_data(bloq.decompose_bloq())\n", + " except:\n", + " return None\n", + "\n", + "def write_example(bloq):\n", + " call_graph, _ = bloq.call_graph(max_depth=1)\n", + "\n", + " for child_bloq, _ in call_graph.succ[bloq].items():\n", + " write_example(child_bloq)\n", + "\n", + " Path(f'ui_export/{bloq.__class__.__name__}').mkdir(parents=True, exist_ok=True)\n", + "\n", + " doc_name = f'ui_export/{bloq.__class__.__name__}/docs.txt'\n", + " if not os.path.isfile(doc_name):\n", + " with open(doc_name, 'w') as doc_file:\n", + " doc_file.write('\\n'.join(get_markdown_docstring(bloq.__class__)))\n", + "\n", + " file_name = f'ui_export/{bloq.__class__.__name__}/{bloq_filename(bloq)}'\n", + " if not os.path.isfile(file_name):\n", + " bloq_dict = {\n", + " 'name': bloq.__class__.__name__,\n", + " 'attrs': bloq_attrs(bloq),\n", + " 'score': bloq_score(bloq),\n", + " 'callees': list(\n", + " {\n", + " 'name': child_bloq.__class__.__name__,\n", + " 'filename': bloq_filename(child_bloq)\n", + " }\n", + " for child_bloq, _ in call_graph.succ[bloq].items()\n", + " )\n", + " }\n", + "\n", + " with open(file_name, 'w') as f:\n", + " json.dump(bloq_dict, f, indent=2, cls=BloqEncoder)\n", + "\n", + "for section in NB_BY_SECTION:\n", + " for notebook_spec in section[1]:\n", + " for bloq_spec in notebook_spec.bloq_specs:\n", + " for example in bloq_spec.examples:\n", + " write_example(example.make())" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "qualtran", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/qualtran/Autodoc.ipynb b/qualtran/Autodoc.ipynb index d98a5a948..b70bf764b 100644 --- a/qualtran/Autodoc.ipynb +++ b/qualtran/Autodoc.ipynb @@ -61,7 +61,7 @@ "\n", "### References\n", "\n", - "We provide custom support for a \"References\" section where you should reference the source(s) of the construction. References are newline seperated. They must start with a markdown-style link of `[title](url)`. This can optionally be followed by a period and any additional information in standard markdown format. To balance structure vs. readability, reference links should be kept to a single line and need not respect the 100-character line limit.\n", + "We provide custom support for a \"References\" section where you should reference the source(s) of the construction. References are newline seperated. They must start with a markdown-style link of `[title](url)`. This can optionally be followed by a period and any additional information in standard markdown format. To balance structure vs. readability, reference links should be kept to a single line and need not respect the 100-character line limit. Canonically, the next line should include one or two author last names, the first year of publication, and specific figures or equations relevant to the bloq. Prefer arxiv links. Link to the abstract page; not directly to the pdf.\n", "\n", "```python\n", "class QROM(Bloq):\n", @@ -137,7 +137,7 @@ "\n", "This code should be located in the module defining the bloq class.\n", "\n", - "Each bloq class has one `BloqDocSpec` which may have multiple bloq examples. Each jupyter notebook roughly corresponds to one module or package and can document multiple bloq classes in it, so the final step is to plumb through the `BloqDocSpec` into a `NotebookSpec`. In `dev_tools/autogenerate-bloqs-notebooks-v2.py`, you can add a new `NotebookSpecV2` to the big list or add your `BloqDocSpec` to an existing one. If you execute this script, it will generate a new notebook or new cells in an existing notebook with documentation for your bloq. You may need to manually `git add` the new notebook.\n", + "Each bloq class has one `BloqDocSpec` which may have multiple bloq examples. Each jupyter notebook roughly corresponds to one module or package and can document multiple bloq classes in it, so the final step is to plumb through the `BloqDocSpec` into a `NotebookSpec`. In `dev_tools/qualtran_dev_tools/notebook_specs.py`, you can add a new `NotebookSpecV2` to the big list or add your `BloqDocSpec` to an existing one. If you execute this script, it will generate a new notebook or new cells in an existing notebook with documentation for your bloq. You may need to manually `git add` the new notebook.\n", "\n", "\n", "```python\n", @@ -166,7 +166,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.7" + "version": "3.11.8" } }, "nbformat": 4, diff --git a/qualtran/_infra/adjoint.py b/qualtran/_infra/adjoint.py index 4fa14ff4e..0601a6248 100644 --- a/qualtran/_infra/adjoint.py +++ b/qualtran/_infra/adjoint.py @@ -16,7 +16,6 @@ from functools import cached_property from typing import Dict, List, Optional, Tuple, TYPE_CHECKING -import cirq from attrs import frozen from .composite_bloq import _binst_to_cxns, _cxns_to_soq_dict, _map_soqs, _reg_to_soq, BloqBuilder @@ -25,6 +24,8 @@ from .registers import Signature if TYPE_CHECKING: + import cirq + from qualtran import Bloq, CompositeBloq, Register, Signature, SoquetT from qualtran.drawing import WireSymbol from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator @@ -144,7 +145,9 @@ def decompose_bloq(self) -> 'CompositeBloq': def _circuit_diagram_info_( self, args: 'cirq.CircuitDiagramInfoArgs' - ) -> cirq.CircuitDiagramInfo: + ) -> 'cirq.CircuitDiagramInfo': + import cirq + sub_info = cirq.circuit_diagram_info(self.subbloq, args, default=NotImplemented) if sub_info is NotImplemented: return NotImplemented @@ -181,21 +184,3 @@ def wire_symbol( return self.subbloq.wire_symbol(reg=None).adjoint() return self.subbloq.wire_symbol(reg=reg.adjoint(), idx=idx).adjoint() - - def _t_complexity_(self): - """The cirq-style `_t_complexity_` delegates to the subbloq's method with a special shim. - - The cirq-style t complexity protocol does not leverage the heirarchical decomposition - of high-level bloqs, so we need to shim in an extra `adjoint` boolean flag. - """ - # TODO: https://github.com/quantumlib/Qualtran/issues/735 - if not hasattr(self.subbloq, '_t_complexity_'): - return NotImplemented - - try: - return self.subbloq._t_complexity_(adjoint=True) # type: ignore[call-arg] - except TypeError as e: - if 'adjoint' in str(e): - return self.subbloq._t_complexity_() - else: - raise e diff --git a/qualtran/_infra/bloq.py b/qualtran/_infra/bloq.py index 880224f38..7ccd20037 100644 --- a/qualtran/_infra/bloq.py +++ b/qualtran/_infra/bloq.py @@ -432,9 +432,6 @@ def t_complexity(self) -> 'TComplexity': return t_complexity(self) - def _t_complexity_(self) -> 'TComplexity': - return NotImplemented - def as_cirq_op( self, qubit_manager: 'cirq.QubitManager', **cirq_quregs: 'CirqQuregT' ) -> Tuple[Union['cirq.Operation', None], Dict[str, 'CirqQuregT']]: diff --git a/qualtran/_infra/composite_bloq_test.py b/qualtran/_infra/composite_bloq_test.py index 58972c9d9..ffe39213c 100644 --- a/qualtran/_infra/composite_bloq_test.py +++ b/qualtran/_infra/composite_bloq_test.py @@ -16,7 +16,6 @@ from typing import Dict, List, Tuple import attrs -import cirq import networkx as nx import numpy as np import pytest @@ -164,7 +163,8 @@ def test_map_soqs(): assert isinstance(cbloq, CompositeBloq) -def test_bb_composite_bloq(): +def test_to_from_cirq_circuit(): + cirq = pytest.importorskip('cirq') cbloq_auto = TestTwoCNOT().decompose_bloq() circuit, _ = cbloq_auto.to_cirq_circuit_and_quregs( q1=[cirq.LineQubit(1)], q2=[cirq.LineQubit(2)] @@ -348,6 +348,7 @@ def build_composite_bloq( def test_complicated_target_register(): + cirq = pytest.importorskip('cirq') bloq = TestMultiCNOT() cbloq = qlt_testing.assert_valid_bloq_decomposition(bloq) assert len(cbloq.bloq_instances) == 2 * 3 diff --git a/qualtran/_infra/controlled.py b/qualtran/_infra/controlled.py index f417bc2b4..e43a2d2b9 100644 --- a/qualtran/_infra/controlled.py +++ b/qualtran/_infra/controlled.py @@ -27,7 +27,6 @@ ) import attrs -import cirq import numpy as np from numpy.typing import NDArray @@ -37,6 +36,7 @@ from .registers import Register, Side, Signature if TYPE_CHECKING: + import cirq import quimb.tensor as qtn from qualtran import Bloq, BloqBuilder, CompositeBloq, ConnectionT, SoquetT @@ -203,8 +203,10 @@ def __eq__(self, other: Any) -> bool: def __hash__(self): return hash((self.qdtypes, self.shapes, self._cvs_tuple)) - def to_cirq_cv(self) -> cirq.SumOfProducts: + def to_cirq_cv(self) -> 'cirq.SumOfProducts': """Convert CtrlSpec to cirq.SumOfProducts representation of control values.""" + import cirq + cirq_cv = [] for qdtype, cv in zip(self.qdtypes, self.cvs): for idx in Register('', qdtype, cv.shape).all_idxs(): @@ -214,7 +216,7 @@ def to_cirq_cv(self) -> cirq.SumOfProducts: @classmethod def from_cirq_cv( cls, - cirq_cv: cirq.ops.AbstractControlValues, + cirq_cv: 'cirq.ops.AbstractControlValues', *, qdtypes: Optional[Sequence[QDType]] = None, shapes: Optional[Sequence[Tuple[int, ...]]] = None, @@ -438,6 +440,8 @@ def _tensor_data(self): def _unitary_(self): if isinstance(self.subbloq, GateWithRegisters): # subbloq is a cirq gate, use the cirq-style API to derive a unitary. + import cirq + return cirq.unitary( cirq.ControlledGate(self.subbloq, control_values=self.ctrl_spec.to_cirq_cv()) ) @@ -494,7 +498,11 @@ def as_cirq_op( cirq_quregs | ctrl_regs, ) - def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo: + def _circuit_diagram_info_( + self, args: 'cirq.CircuitDiagramInfoArgs' + ) -> 'cirq.CircuitDiagramInfo': + import cirq + from qualtran.cirq_interop._bloq_to_cirq import _wire_symbol_to_cirq_diagram_info if isinstance(self.subbloq, cirq.Gate): diff --git a/qualtran/_infra/controlled_test.py b/qualtran/_infra/controlled_test.py index b25201b25..34b26def8 100644 --- a/qualtran/_infra/controlled_test.py +++ b/qualtran/_infra/controlled_test.py @@ -14,7 +14,6 @@ from typing import Dict, List, Tuple, TYPE_CHECKING import attrs -import cirq import numpy as np import pytest @@ -55,6 +54,8 @@ from qualtran.simulation.tensor import cbloq_to_quimb, get_right_and_left_inds if TYPE_CHECKING: + import cirq + from qualtran import SoquetT @@ -84,6 +85,7 @@ def test_ctrl_spec_shape(): def test_ctrl_spec_to_cirq_cv_roundtrip(): + cirq = pytest.importorskip('cirq') cirq_cv = cirq.ProductOfSums([0, 1, 0, 1]) assert CtrlSpec.from_cirq_cv(cirq_cv) == CtrlSpec(cvs=[0, 1, 0, 1]) @@ -98,17 +100,21 @@ def test_ctrl_spec_to_cirq_cv_roundtrip(): assert CtrlSpec.from_cirq_cv(cirq_cv, qdtypes=ctrl_spec.qdtypes, shapes=ctrl_spec.shapes) +def _test_cirq_equivalence(bloq: Bloq, gate: 'cirq.Gate'): + import cirq + + left_quregs = get_named_qubits(bloq.signature.lefts()) + circuit1 = bloq.as_composite_bloq().to_cirq_circuit(cirq_quregs=left_quregs) + circuit2 = cirq.Circuit( + gate.on(*merge_qubits(bloq.signature, **get_named_qubits(bloq.signature))) + ) + cirq.testing.assert_same_circuits(circuit1, circuit2) + + def test_ctrl_bloq_as_cirq_op(): + cirq = pytest.importorskip('cirq') subbloq = XGate() - def _test_cirq_equivalence(bloq: Bloq, gate: cirq.Gate): - left_quregs = get_named_qubits(bloq.signature.lefts()) - circuit1 = bloq.as_composite_bloq().to_cirq_circuit(cirq_quregs=left_quregs) - circuit2 = cirq.Circuit( - gate.on(*merge_qubits(bloq.signature, **get_named_qubits(bloq.signature))) - ) - cirq.testing.assert_same_circuits(circuit1, circuit2) - # Simple ctrl spec _test_cirq_equivalence(subbloq, cirq.X) _test_cirq_equivalence(subbloq.controlled(), cirq.X.controlled()) @@ -340,7 +346,9 @@ def test_notebook(): qlt_testing.execute_notebook('../Controlled') -def _verify_ctrl_tensor_for_unitary(ctrl_spec: CtrlSpec, bloq: Bloq, gate: cirq.Gate): +def _verify_ctrl_tensor_for_unitary(ctrl_spec: CtrlSpec, bloq: Bloq, gate: 'cirq.Gate'): + import cirq + ctrl_bloq = Controlled(bloq, ctrl_spec) cgate = cirq.ControlledGate(gate, control_values=ctrl_spec.to_cirq_cv()) np.testing.assert_allclose(ctrl_bloq.tensor_contract(), cirq.unitary(cgate), atol=1e-8) @@ -357,6 +365,7 @@ def _verify_ctrl_tensor_for_unitary(ctrl_spec: CtrlSpec, bloq: Bloq, gate: cirq. @pytest.mark.parametrize('ctrl_spec', interesting_ctrl_specs) def test_controlled_tensor_for_unitary(ctrl_spec: CtrlSpec): + cirq = pytest.importorskip('cirq') # Test one qubit unitaries _verify_ctrl_tensor_for_unitary(ctrl_spec, XGate(), cirq.X) _verify_ctrl_tensor_for_unitary(ctrl_spec, YGate(), cirq.Y) @@ -366,6 +375,7 @@ def test_controlled_tensor_for_unitary(ctrl_spec: CtrlSpec): def test_controlled_tensor_without_decompose(): + cirq = pytest.importorskip('cirq') ctrl_spec = CtrlSpec() bloq = TwoBitCSwap() ctrl_bloq = Controlled(bloq, ctrl_spec) @@ -442,6 +452,7 @@ def test_controlled_tensor_for_and_bloq(ctrl_spec: CtrlSpec): def test_controlled_diagrams(): + cirq = pytest.importorskip('cirq') ctrl_gate = XPowGate(0.25).controlled() cirq.testing.assert_has_diagram( cirq.Circuit(ctrl_gate.on_registers(**get_named_qubits(ctrl_gate.signature))), diff --git a/qualtran/_infra/data_types_test.py b/qualtran/_infra/data_types_test.py index 227c8de7b..10347b702 100644 --- a/qualtran/_infra/data_types_test.py +++ b/qualtran/_infra/data_types_test.py @@ -15,7 +15,6 @@ import random from typing import Any, Sequence, Union -import cirq import numpy as np import pytest import sympy @@ -312,6 +311,7 @@ def test_quint_to_and_from_bits(): def test_bits_to_int(): + cirq = pytest.importorskip('cirq') rs = np.random.RandomState(52) bitstrings = rs.choice([0, 1], size=(100, 23)) @@ -328,6 +328,7 @@ def test_bits_to_int(): def test_int_to_bits(): + cirq = pytest.importorskip('cirq') rs = np.random.RandomState(52) nums = rs.randint(0, 2**23 - 1, size=(100,), dtype=np.uint64) bitstrings = QUInt(23).to_bits_array(nums) diff --git a/qualtran/_infra/gate_with_registers.py b/qualtran/_infra/gate_with_registers.py index 219f3e995..e59bd4a20 100644 --- a/qualtran/_infra/gate_with_registers.py +++ b/qualtran/_infra/gate_with_registers.py @@ -49,8 +49,8 @@ def total_bits(registers: Iterable[Register]) -> int: def split_qubits( - registers: Iterable[Register], qubits: Sequence[cirq.Qid] -) -> Dict[str, NDArray[cirq.Qid]]: # type: ignore[type-var] + registers: Iterable[Register], qubits: Sequence['cirq.Qid'] +) -> Dict[str, NDArray['cirq.Qid']]: # type: ignore[type-var] """Splits the flat list of qubits into a dictionary of appropriately shaped qubit arrays.""" qubit_regs = {} @@ -65,11 +65,11 @@ def split_qubits( def merge_qubits( registers: Iterable[Register], - **qubit_regs: Union[cirq.Qid, Sequence[cirq.Qid], NDArray[cirq.Qid]], -) -> List[cirq.Qid]: + **qubit_regs: Union['cirq.Qid', Sequence['cirq.Qid'], NDArray['cirq.Qid']], +) -> List['cirq.Qid']: """Merges the dictionary of appropriately shaped qubit arrays into a flat list of qubits.""" - ret: List[cirq.Qid] = [] + ret: List['cirq.Qid'] = [] for reg in registers: if reg.name not in qubit_regs: raise ValueError(f"All qubit registers must be present. {reg.name} not in qubit_regs") @@ -84,7 +84,7 @@ def merge_qubits( return ret -def get_named_qubits(registers: Iterable[Register]) -> Dict[str, NDArray[cirq.Qid]]: +def get_named_qubits(registers: Iterable[Register]) -> Dict[str, NDArray['cirq.Qid']]: """Returns a dictionary of appropriately shaped named qubit signature for input `signature`.""" def _qubit_array(reg: Register): @@ -114,7 +114,7 @@ def _qubits_for_reg(reg: Register): def _get_all_and_output_quregs_from_input( registers: Iterable[Register], - qubit_manager: cirq.QubitManager, + qubit_manager: 'cirq.QubitManager', in_quregs: Dict[str, 'CirqQuregT'], ) -> Tuple[Dict[str, 'CirqQuregT'], Dict[str, 'CirqQuregT']]: """Takes care of necessary (de-/)allocations to obtain output & all qubit registers from input. @@ -171,7 +171,7 @@ def _get_cirq_cv( num_controls: Optional[int] = None, control_values=None, control_qid_shape: Optional[Tuple[int, ...]] = None, -) -> cirq.ops.AbstractControlValues: +) -> 'cirq.ops.AbstractControlValues': """Logic copied from `cirq.ControlledGate` to help convert cirq-style spec to `CtrlSpec`""" if isinstance(control_values, cirq.SumOfProducts) and len(control_values._conjunctions) == 1: control_values = control_values._conjunctions[0] @@ -325,13 +325,13 @@ def _num_qubits_(self) -> int: return total_bits(self.signature) def decompose_from_registers( - self, *, context: cirq.DecompositionContext, **quregs: NDArray[cirq.Qid] - ) -> cirq.OP_TREE: + self, *, context: 'cirq.DecompositionContext', **quregs: NDArray['cirq.Qid'] + ) -> 'cirq.OP_TREE': raise DecomposeNotImplementedError(f"{self} does not declare a decomposition.") def _decompose_with_context_( - self, qubits: Sequence[cirq.Qid], context: Optional[cirq.DecompositionContext] = None - ) -> cirq.OP_TREE: + self, qubits: Sequence['cirq.Qid'], context: Optional['cirq.DecompositionContext'] = None + ) -> 'cirq.OP_TREE': from qualtran.cirq_interop._bloq_to_cirq import _cirq_style_decompose_from_decompose_bloq quregs = split_qubits(self.signature, qubits) @@ -349,7 +349,7 @@ def _decompose_with_context_( pass return NotImplemented - def _decompose_(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE: + def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE': return self._decompose_with_context_(qubits) def on(self, *qubits) -> 'cirq.Operation': @@ -359,8 +359,8 @@ def on(self, *qubits) -> 'cirq.Operation': return cirq.Gate.on(self, *qubits) def on_registers( - self, **qubit_regs: Union[cirq.Qid, Sequence[cirq.Qid], NDArray[cirq.Qid]] - ) -> cirq.Operation: + self, **qubit_regs: Union['cirq.Qid', Sequence['cirq.Qid'], NDArray['cirq.Qid']] + ) -> 'cirq.Operation': return self.on(*merge_qubits(self.signature, **qubit_regs)) def __pow__(self, power: int) -> 'GateWithRegisters': @@ -441,7 +441,7 @@ def controlled( self, num_controls: Optional[int] = None, control_values: Optional[ - Union[cirq.ops.AbstractControlValues, Sequence[Union[int, Collection[int]]]] + Union['cirq.ops.AbstractControlValues', Sequence[Union[int, Collection[int]]]] ] = None, control_qid_shape: Optional[Tuple[int, ...]] = None, ) -> 'GateWithRegisters': @@ -456,7 +456,7 @@ def controlled( self, num_controls: Union[Optional[int], 'CtrlSpec'] = None, control_values: Optional[ - Union[cirq.ops.AbstractControlValues, Sequence[Union[int, Collection[int]]]] + Union['cirq.ops.AbstractControlValues', Sequence[Union[int, Collection[int]]]] ] = None, control_qid_shape: Optional[Tuple[int, ...]] = None, *, @@ -518,7 +518,9 @@ def my_tensors( else: return super().my_tensors(incoming=incoming, outgoing=outgoing) - def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo: + def _circuit_diagram_info_( + self, args: 'cirq.CircuitDiagramInfoArgs' + ) -> 'cirq.CircuitDiagramInfo': """Default diagram info that uses register names to name the boxes in multi-qubit gates. Descendants can override this method with more meaningful circuit diagram information. diff --git a/qualtran/_infra/registers_test.py b/qualtran/_infra/registers_test.py index 8beb0163a..f52b1af7a 100644 --- a/qualtran/_infra/registers_test.py +++ b/qualtran/_infra/registers_test.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import cirq import numpy as np import pytest import sympy @@ -100,6 +99,13 @@ def test_signature(): assert list(signature) == [r1, r2, r3] + +def test_get_named_qubits(): + cirq = pytest.importorskip('cirq') + r1 = Register("r1", QAny(5)) + r2 = Register("r2", QAny(2)) + r3 = Register("r3", QBit()) + signature = Signature([r1, r2, r3]) expected_named_qubits = { "r1": cirq.NamedQubit.range(5, prefix="r1"), "r2": cirq.NamedQubit.range(2, prefix="r2"), @@ -179,6 +185,7 @@ def test_agg_split(): def test_get_named_qubits_multidim(): + cirq = pytest.importorskip('cirq') regs = Signature([Register('q', shape=(2, 3), dtype=QAny(4))]) quregs = get_named_qubits(regs.lefts()) assert quregs['q'].shape == (2, 3, 4) diff --git a/qualtran/bloqs/arithmetic/comparison.ipynb b/qualtran/bloqs/arithmetic/comparison.ipynb index 537c80f36..4a0c8ad6d 100644 --- a/qualtran/bloqs/arithmetic/comparison.ipynb +++ b/qualtran/bloqs/arithmetic/comparison.ipynb @@ -485,7 +485,7 @@ "https://github.com/quantumlib/Qualtran/issues/389\n", "\n", "#### References\n", - " - Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf\n" + " - [Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians](https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf).\n" ] }, { @@ -702,7 +702,7 @@ "\n", "#### References\n", " - [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). \n", - " - Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians. https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf\n" + " - [Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians](https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf).\n" ] }, { diff --git a/qualtran/bloqs/arithmetic/comparison.py b/qualtran/bloqs/arithmetic/comparison.py index 272ea8abe..c546aee77 100644 --- a/qualtran/bloqs/arithmetic/comparison.py +++ b/qualtran/bloqs/arithmetic/comparison.py @@ -233,8 +233,7 @@ class BiQubitsMixer(GateWithRegisters): https://github.com/quantumlib/Qualtran/issues/389 References: - Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians - https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf + [Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians](https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf). """ is_adjoint: bool = False @@ -432,8 +431,7 @@ class LessThanEqual(GateWithRegisters, cirq.ArithmeticGate): # type: ignore[mis References: [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). - Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians. - https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf + [Supplementary Materials: Improved Techniques for Preparing Eigenstates of Fermionic Hamiltonians](https://static-content.springer.com/esm/art%3A10.1038%2Fs41534-018-0071-5/MediaObjects/41534_2018_71_MOESM1_ESM.pdf). """ x_bitsize: 'SymbolicInt' diff --git a/qualtran/bloqs/arithmetic/conversions/contiguous_index.py b/qualtran/bloqs/arithmetic/conversions/contiguous_index.py index 5444e62d3..79f552805 100644 --- a/qualtran/bloqs/arithmetic/conversions/contiguous_index.py +++ b/qualtran/bloqs/arithmetic/conversions/contiguous_index.py @@ -18,7 +18,6 @@ from qualtran import Bloq, bloq_example, BloqDocSpec, QUInt, Register, Signature from qualtran.bloqs.basic_gates import Toffoli -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import WireSymbol from qualtran.drawing.musical_score import Text, TextBox @@ -70,10 +69,6 @@ def on_classical_vals( ) -> Dict[str, 'ClassicalValT']: return {'mu': mu, 'nu': nu, 's': nu * (nu + 1) // 2 + mu} - def _t_complexity_(self) -> 'TComplexity': - num_toffoli = self.bitsize**2 + self.bitsize - 1 - return TComplexity(t=4 * num_toffoli) - def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -> WireSymbol: if reg is None: return Text('') diff --git a/qualtran/bloqs/arithmetic/multiplication.ipynb b/qualtran/bloqs/arithmetic/multiplication.ipynb index 0909cd39a..40eff7a98 100644 --- a/qualtran/bloqs/arithmetic/multiplication.ipynb +++ b/qualtran/bloqs/arithmetic/multiplication.ipynb @@ -474,7 +474,7 @@ " - `result`: a r_bitsize sized output fixed-point register. \n", "\n", "#### References\n", - " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization]( https://arxiv.org/pdf/2007.07391.pdf) pg 70.\n" + " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). pg 70.\n" ] }, { diff --git a/qualtran/bloqs/arithmetic/multiplication.py b/qualtran/bloqs/arithmetic/multiplication.py index 464eacf0c..efed2d665 100644 --- a/qualtran/bloqs/arithmetic/multiplication.py +++ b/qualtran/bloqs/arithmetic/multiplication.py @@ -315,9 +315,8 @@ class Product(Bloq): result: A 2*`max(a_bitsize, b_bitsize)` bit-sized output register to store the result a*b. References: - [Fault-Tolerant Quantum Simulations of Chemistry in First - Quantization](https://arxiv.org/abs/2105.12767) pg 81 gives a Toffoli - complexity for multiplying two numbers. + [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). + pg 81 gives a Toffoli complexity for multiplying two numbers. """ a_bitsize: SymbolicInt @@ -377,8 +376,8 @@ class ScaleIntByReal(Bloq): result: a r_bitsize sized output fixed-point register. References: - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization]( - https://arxiv.org/pdf/2007.07391.pdf) pg 70. + [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). + pg 70. """ r_bitsize: SymbolicInt diff --git a/qualtran/bloqs/arithmetic/subtraction.ipynb b/qualtran/bloqs/arithmetic/subtraction.ipynb index 584a0dce4..ce9e32211 100644 --- a/qualtran/bloqs/arithmetic/subtraction.ipynb +++ b/qualtran/bloqs/arithmetic/subtraction.ipynb @@ -53,7 +53,7 @@ " - `b`: A b_dtype.bitsize-sized input/output register (register b above). \n", "\n", "#### References\n", - " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization, page 9](https://arxiv.org/pdf/2007.07391). \n" + " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Page 9.\n" ] }, { diff --git a/qualtran/bloqs/arithmetic/subtraction.py b/qualtran/bloqs/arithmetic/subtraction.py index f9bb91437..ef5cb5199 100644 --- a/qualtran/bloqs/arithmetic/subtraction.py +++ b/qualtran/bloqs/arithmetic/subtraction.py @@ -68,7 +68,8 @@ class Subtract(Bloq): b: A b_dtype.bitsize-sized input/output register (register b above). References: - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization, page 9](https://arxiv.org/pdf/2007.07391) + [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). + Page 9. """ a_dtype: Union[QInt, QUInt, QMontgomeryUInt] = field() diff --git a/qualtran/bloqs/basic_gates/cnot.py b/qualtran/bloqs/basic_gates/cnot.py index bf19f090c..a6e762803 100644 --- a/qualtran/bloqs/basic_gates/cnot.py +++ b/qualtran/bloqs/basic_gates/cnot.py @@ -33,7 +33,6 @@ Signature, SoquetT, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, ModPlus, Text, WireSymbol if TYPE_CHECKING: @@ -132,9 +131,6 @@ def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) - return ModPlus() raise ValueError(f'Unknown wire symbol register name: {reg.name}') - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) - @bloq_example def _cnot() -> CNOT: diff --git a/qualtran/bloqs/basic_gates/global_phase.py b/qualtran/bloqs/basic_gates/global_phase.py index 7fcf2bafd..cae67a2fa 100644 --- a/qualtran/bloqs/basic_gates/global_phase.py +++ b/qualtran/bloqs/basic_gates/global_phase.py @@ -32,7 +32,6 @@ ) from qualtran.bloqs.basic_gates.rotation import ZPowGate from qualtran.cirq_interop import CirqGateAsBloqBase -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.symbolics import pi, sarg, sexp, SymbolicComplex, SymbolicFloat if TYPE_CHECKING: @@ -109,9 +108,6 @@ def _add_ctrled( def __str__(self) -> str: return f'GPhase({self.coefficient})' - def _t_complexity_(self) -> 'TComplexity': - return TComplexity() - @bloq_example def _global_phase() -> GlobalPhase: diff --git a/qualtran/bloqs/basic_gates/hadamard.ipynb b/qualtran/bloqs/basic_gates/hadamard.ipynb index 1315f0a15..60247421e 100644 --- a/qualtran/bloqs/basic_gates/hadamard.ipynb +++ b/qualtran/bloqs/basic_gates/hadamard.ipynb @@ -40,10 +40,12 @@ "\n", "This converts between the X and Z basis.\n", "\n", - "$$\\begin{aligned}\n", + "$$\n", + "\\begin{aligned}\n", "H |0\\rangle = |+\\rangle \\\\\n", "H |-\\rangle = |1\\rangle\n", - "\\end{aligned}$$\n", + "\\end{aligned}\n", + "$$\n", "\n", "#### Registers\n", " - `q`: The qubit\n" diff --git a/qualtran/bloqs/basic_gates/hadamard.py b/qualtran/bloqs/basic_gates/hadamard.py index eca9c99e8..5efa9c2f5 100644 --- a/qualtran/bloqs/basic_gates/hadamard.py +++ b/qualtran/bloqs/basic_gates/hadamard.py @@ -32,7 +32,6 @@ Signature, SoquetT, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, Text, TextBox, WireSymbol if TYPE_CHECKING: @@ -51,10 +50,12 @@ class Hadamard(Bloq): This converts between the X and Z basis. - $$\begin{aligned} + $$ + \begin{aligned} H |0\rangle = |+\rangle \\ H |-\rangle = |1\rangle - \end{aligned}$$ + \end{aligned} + $$ Registers: q: The qubit @@ -104,9 +105,6 @@ def as_cirq_op( (q,) = q return cirq.H(q), {'q': np.array([q])} - def _t_complexity_(self): - return TComplexity(clifford=1) - def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -> 'WireSymbol': if reg is None: return Text('') @@ -173,14 +171,6 @@ def as_cirq_op( 'target': np.array([target]), } - def _t_complexity_(self) -> 'TComplexity': - # This is based on the decomposition provided by `cirq.decompose_multi_controlled_rotation` - # which uses three cirq.MatrixGate's to do a controlled version of any single-qubit gate. - # The first MatrixGate happens to be a clifford, Hadamard operation in this case. - # The other two are considered 'rotations'. - # https://github.com/quantumlib/Qualtran/issues/237 - return TComplexity(rotations=2, clifford=4) - def my_static_costs(self, cost_key: 'CostKey'): from qualtran.resource_counting import GateCounts, QECGatesCost diff --git a/qualtran/bloqs/basic_gates/identity.py b/qualtran/bloqs/basic_gates/identity.py index 434cf1b8b..c5eeafa1a 100644 --- a/qualtran/bloqs/basic_gates/identity.py +++ b/qualtran/bloqs/basic_gates/identity.py @@ -32,7 +32,6 @@ Signature, SoquetT, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Text, TextBox, WireSymbol from qualtran.symbolics import is_symbolic, SymbolicInt @@ -89,9 +88,6 @@ def as_cirq_op( return cirq.IdentityGate(self.bitsize).on(*q), {'q': q} - def _t_complexity_(self): - return TComplexity() - def wire_symbol(self, reg: Optional[Register], idx: Tuple[int, ...] = tuple()) -> 'WireSymbol': if reg is None: return Text('') diff --git a/qualtran/bloqs/basic_gates/rotation.py b/qualtran/bloqs/basic_gates/rotation.py index 28a0c9bb3..9adb439e1 100644 --- a/qualtran/bloqs/basic_gates/rotation.py +++ b/qualtran/bloqs/basic_gates/rotation.py @@ -22,7 +22,6 @@ from qualtran import bloq_example, BloqDocSpec, CompositeBloq, DecomposeTypeError, Register from qualtran.cirq_interop import CirqGateAsBloqBase -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Text, TextBox, WireSymbol from qualtran.symbolics import SymbolicFloat @@ -120,11 +119,6 @@ def decompose_bloq(self) -> 'CompositeBloq': def cirq_gate(self) -> cirq.Gate: return cirq.CZPowGate(exponent=self.exponent, global_shift=self.global_shift) - def _t_complexity_(self) -> 'TComplexity': - if cirq.has_stabilizer_effect(self.cirq_gate): - return TComplexity(clifford=1) - return TComplexity(rotations=1) - def __pow__(self, power): g = self.cirq_gate**power return CZPowGate(g.exponent, g.global_shift, self.eps) diff --git a/qualtran/bloqs/basic_gates/s_gate.py b/qualtran/bloqs/basic_gates/s_gate.py index b6a4d9678..3971f59d0 100644 --- a/qualtran/bloqs/basic_gates/s_gate.py +++ b/qualtran/bloqs/basic_gates/s_gate.py @@ -20,7 +20,6 @@ from attrs import frozen from qualtran import Bloq, bloq_example, BloqDocSpec, ConnectionT, Register, Signature -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Text, TextBox, WireSymbol if TYPE_CHECKING: @@ -57,9 +56,6 @@ class SGate(Bloq): def signature(self) -> 'Signature': return Signature.build(q=1) - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) - def my_tensors( self, incoming: Dict[str, 'ConnectionT'], outgoing: Dict[str, 'ConnectionT'] ) -> List['qtn.Tensor']: diff --git a/qualtran/bloqs/basic_gates/swap.py b/qualtran/bloqs/basic_gates/swap.py index 62b104f26..dc8d27e24 100644 --- a/qualtran/bloqs/basic_gates/swap.py +++ b/qualtran/bloqs/basic_gates/swap.py @@ -15,7 +15,6 @@ from functools import cached_property from typing import Dict, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union -import cirq import numpy as np import sympy from attrs import frozen @@ -36,14 +35,15 @@ SoquetT, ) from qualtran.cirq_interop import CirqQuregT -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, Text, TextBox, WireSymbol from qualtran.resource_counting.generalizers import ignore_split_join if TYPE_CHECKING: + import cirq import quimb.tensor as qtn from qualtran import AddControlledT, CompositeBloq + from qualtran.cirq_interop import CirqQuregT from qualtran.resource_counting import BloqCountDictT, SympySymbolAllocator from qualtran.simulation.classical_sim import ClassicalValT @@ -82,10 +82,9 @@ def as_cirq_op( ) -> Tuple['cirq.Operation', Dict[str, 'CirqQuregT']]: # type: ignore[type-var] (x,) = x (y,) = y - return cirq.SWAP.on(x, y), {'x': np.asarray([x]), 'y': np.asarray([y])} + import cirq - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) + return cirq.SWAP.on(x, y), {'x': np.asarray([x]), 'y': np.asarray([y])} def my_tensors( self, incoming: Dict[str, 'ConnectionT'], outgoing: Dict[str, 'ConnectionT'] @@ -154,6 +153,8 @@ def decompose_bloq(self) -> 'CompositeBloq': raise DecomposeTypeError(f"{self} is atomic.") def to_clifford_t_circuit(self) -> 'cirq.FrozenCircuit': + import cirq + ctrl = cirq.NamedQubit('ctrl') x = cirq.NamedQubit('x') y = cirq.NamedQubit('y') @@ -354,12 +355,16 @@ def on_classical_vals( @classmethod def make_on( - cls, **quregs: Union[Sequence[cirq.Qid], NDArray[cirq.Qid]] # type: ignore[type-var] - ) -> cirq.Operation: + cls, **quregs: Union[Sequence['cirq.Qid'], NDArray['cirq.Qid']] # type: ignore[type-var] + ) -> 'cirq.Operation': """Helper constructor to automatically deduce bitsize attributes.""" return cls(bitsize=len(quregs['x'])).on_registers(**quregs) - def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo: + def _circuit_diagram_info_( + self, args: 'cirq.CircuitDiagramInfoArgs' + ) -> 'cirq.CircuitDiagramInfo': + import cirq + if not args.use_unicode_characters: return cirq.CircuitDiagramInfo( ("@",) + ("swap_x",) * self.bitsize + ("swap_y",) * self.bitsize diff --git a/qualtran/bloqs/basic_gates/toffoli.py b/qualtran/bloqs/basic_gates/toffoli.py index ee3b96ae6..597193856 100644 --- a/qualtran/bloqs/basic_gates/toffoli.py +++ b/qualtran/bloqs/basic_gates/toffoli.py @@ -30,7 +30,6 @@ Register, Signature, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity if TYPE_CHECKING: import cirq @@ -66,9 +65,6 @@ def adjoint(self) -> 'Bloq': def decompose_bloq(self) -> 'CompositeBloq': raise DecomposeTypeError(f"{self} is atomic") - def _t_complexity_(self): - return TComplexity(t=4) - def my_tensors( self, incoming: Dict[str, NDArray[Connection]], # type: ignore[type-var] diff --git a/qualtran/bloqs/basic_gates/x_basis.py b/qualtran/bloqs/basic_gates/x_basis.py index 76fd85dcb..c215a4ad2 100644 --- a/qualtran/bloqs/basic_gates/x_basis.py +++ b/qualtran/bloqs/basic_gates/x_basis.py @@ -32,7 +32,6 @@ Signature, SoquetT, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import directional_text_box, Text, WireSymbol if TYPE_CHECKING: @@ -257,9 +256,6 @@ def as_cirq_op( (q,) = q return cirq.X(q), {'q': np.asarray([q])} - def _t_complexity_(self): - return TComplexity(clifford=1) - def wire_symbol(self, reg: Register, idx: Tuple[int, ...] = tuple()) -> 'WireSymbol': from qualtran.drawing import ModPlus diff --git a/qualtran/bloqs/basic_gates/y_gate.py b/qualtran/bloqs/basic_gates/y_gate.py index e4819a235..b418fc406 100644 --- a/qualtran/bloqs/basic_gates/y_gate.py +++ b/qualtran/bloqs/basic_gates/y_gate.py @@ -32,7 +32,6 @@ Signature, SoquetT, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, Text, TextBox, WireSymbol if TYPE_CHECKING: @@ -98,9 +97,6 @@ def as_cirq_op( (q,) = q return cirq.Y(q), {'q': np.asarray([q])} - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) - def wire_symbol( self, reg: Optional['Register'], idx: Tuple[int, ...] = tuple() ) -> 'WireSymbol': diff --git a/qualtran/bloqs/basic_gates/z_basis.py b/qualtran/bloqs/basic_gates/z_basis.py index e7b017eeb..b0f39b132 100644 --- a/qualtran/bloqs/basic_gates/z_basis.py +++ b/qualtran/bloqs/basic_gates/z_basis.py @@ -41,7 +41,6 @@ SoquetT, ) from qualtran.bloqs.bookkeeping import ArbitraryClifford -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, directional_text_box, Text, TextBox, WireSymbol if TYPE_CHECKING: @@ -277,9 +276,6 @@ def as_cirq_op( (q,) = q return cirq.Z(q), {'q': np.asarray([q])} - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) - def wire_symbol( self, reg: Optional['Register'], idx: Tuple[int, ...] = tuple() ) -> 'WireSymbol': diff --git a/qualtran/bloqs/block_encoding/linear_combination.ipynb b/qualtran/bloqs/block_encoding/linear_combination.ipynb index 085c41cda..415f99e84 100644 --- a/qualtran/bloqs/block_encoding/linear_combination.ipynb +++ b/qualtran/bloqs/block_encoding/linear_combination.ipynb @@ -64,7 +64,7 @@ " - `resource`: The resource register (present only if bitsize > 0). \n", "\n", "#### References\n", - " - [Quantum algorithms: A survey of applications and end-to-end complexities]( https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2.\n" + " - [Quantum algorithms: A survey of applications and end-to-end complexities](https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2.\n" ] }, { diff --git a/qualtran/bloqs/block_encoding/linear_combination.py b/qualtran/bloqs/block_encoding/linear_combination.py index f890166d6..16586cf61 100644 --- a/qualtran/bloqs/block_encoding/linear_combination.py +++ b/qualtran/bloqs/block_encoding/linear_combination.py @@ -75,8 +75,8 @@ class LinearCombination(BlockEncoding): resource: The resource register (present only if bitsize > 0). References: - [Quantum algorithms: A survey of applications and end-to-end complexities]( - https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2. + [Quantum algorithms: A survey of applications and end-to-end complexities](https://arxiv.org/abs/2310.03011). + Dalzell et al. (2023). Ch. 10.2. """ _block_encodings: Tuple[BlockEncoding, ...] = field( diff --git a/qualtran/bloqs/block_encoding/product.ipynb b/qualtran/bloqs/block_encoding/product.ipynb index 7e097923d..727fb156b 100644 --- a/qualtran/bloqs/block_encoding/product.ipynb +++ b/qualtran/bloqs/block_encoding/product.ipynb @@ -69,7 +69,7 @@ " - `resource`: The resource register (present only if bitsize > 0). \n", "\n", "#### References\n", - " - [Quantum algorithms: A survey of applications and end-to-end complexities]( https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2.\n" + " - [Quantum algorithms: A survey of applications and end-to-end complexities](https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2.\n" ] }, { diff --git a/qualtran/bloqs/block_encoding/product.py b/qualtran/bloqs/block_encoding/product.py index 0dc50007d..aa2507f99 100644 --- a/qualtran/bloqs/block_encoding/product.py +++ b/qualtran/bloqs/block_encoding/product.py @@ -81,8 +81,8 @@ class Product(BlockEncoding): resource: The resource register (present only if bitsize > 0). References: - [Quantum algorithms: A survey of applications and end-to-end complexities]( - https://arxiv.org/abs/2310.03011). Dalzell et al. (2023). Ch. 10.2. + [Quantum algorithms: A survey of applications and end-to-end complexities](https://arxiv.org/abs/2310.03011). + Dalzell et al. (2023). Ch. 10.2. """ block_encodings: Tuple[BlockEncoding, ...] = field( diff --git a/qualtran/bloqs/bookkeeping/_bookkeeping_bloq.py b/qualtran/bloqs/bookkeeping/_bookkeeping_bloq.py index 5e2dab7ec..32b9b7498 100644 --- a/qualtran/bloqs/bookkeeping/_bookkeeping_bloq.py +++ b/qualtran/bloqs/bookkeeping/_bookkeeping_bloq.py @@ -16,7 +16,6 @@ from typing import Dict, Iterable, Optional, Sequence, Tuple, TYPE_CHECKING from qualtran import Bloq, BloqBuilder, SoquetT -from qualtran.cirq_interop.t_complexity_protocol import TComplexity if TYPE_CHECKING: @@ -42,6 +41,3 @@ def add_controlled( return ctrl_soqs, out_soqs return self, add_controlled - - def _t_complexity_(self) -> 'TComplexity': - return TComplexity() diff --git a/qualtran/bloqs/bookkeeping/arbitrary_clifford.py b/qualtran/bloqs/bookkeeping/arbitrary_clifford.py index e9f7a751c..619ac9275 100644 --- a/qualtran/bloqs/bookkeeping/arbitrary_clifford.py +++ b/qualtran/bloqs/bookkeeping/arbitrary_clifford.py @@ -18,7 +18,6 @@ from sympy import Expr from qualtran import Bloq, QAny, Register, Signature -from qualtran.cirq_interop.t_complexity_protocol import TComplexity @frozen @@ -40,8 +39,5 @@ class ArbitraryClifford(Bloq): def signature(self) -> Signature: return Signature([Register('x', QAny(bitsize=self.n))]) - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(clifford=1) - def __str__(self): return f'ArbitraryClifford(n={self.n})' diff --git a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_t.py b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_t.py index d305b6a93..211c6cc15 100644 --- a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_t.py +++ b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/prepare_t.py @@ -110,10 +110,11 @@ class PrepareTFirstQuantizationWithProj(Bloq): s: a register encoding bits for each component of the momenta. References: - [Quantum computation of stopping power for inertial fusion target design]( - https://arxiv.org/abs/2308.12352) page 11, C3 also page 31 App A. Sec 2 b. - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization]( - https://arxiv.org/abs/2105.12767) page 19, section B + [Quantum computation of stopping power for inertial fusion target design](https://arxiv.org/abs/2308.12352). + page 11, C3 also page 31 App A. Sec 2 b. + + [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). + page 19, section B """ num_bits_p: int diff --git a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/projectile.ipynb b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/projectile.ipynb index b9a407ca6..3184e60fe 100644 --- a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/projectile.ipynb +++ b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/projectile.ipynb @@ -128,7 +128,7 @@ " - `flags`: A 4 qubit flag register indicating which component of the Hamiltonian to apply. \n", "\n", "#### References\n", - " - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization]( https://arxiv.org/abs/2105.12767)\n" + " - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). \n" ] }, { @@ -260,7 +260,7 @@ " - `proj`: The system register. Will store a single register (x, y and z) components of size num_bits_n. \n", "\n", "#### References\n", - " - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization]( https://arxiv.org/abs/2105.12767)\n" + " - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). \n" ] }, { diff --git a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/select_and_prepare.py b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/select_and_prepare.py index 581e30295..dde8e7eb6 100644 --- a/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/select_and_prepare.py +++ b/qualtran/bloqs/chemistry/pbc/first_quantization/projectile/select_and_prepare.py @@ -233,8 +233,7 @@ class PrepareFirstQuantizationWithProj(PrepareOracle): flags: A 4 qubit flag register indicating which component of the Hamiltonian to apply. References: - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization]( - https://arxiv.org/abs/2105.12767) + [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). """ num_bits_p: int @@ -409,8 +408,7 @@ class SelectFirstQuantizationWithProj(SelectOracle): components of size num_bits_n. References: - [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization]( - https://arxiv.org/abs/2105.12767) + [Fault-Tolerant Quantum Simulations of Chemistry in First Quantization](https://arxiv.org/abs/2105.12767). """ num_bits_p: int diff --git a/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.ipynb b/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.ipynb index beaf8caba..c0f4c81e2 100644 --- a/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.ipynb +++ b/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.ipynb @@ -98,7 +98,7 @@ " - `phase_gradient`: QFxp data type representing the phase gradient register \n", "\n", "#### References\n", - " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization]( https://arxiv.org/abs/2007.07391). Section II-C: Oracles for phasing by cost function. Appendix A: Addition for controlled rotations\n" + " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Section II-C: Oracles for phasing by cost function. Appendix A: Addition for controlled rotations.\n" ] }, { diff --git a/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.py b/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.py index 75a7690f1..8546f518d 100644 --- a/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.py +++ b/qualtran/bloqs/chemistry/quad_fermion/givens_bloq.py @@ -86,10 +86,9 @@ class RealGivensRotationByPhaseGradient(Bloq): phase_gradient: QFxp data type representing the phase gradient register References: - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization]( - https://arxiv.org/abs/2007.07391). + [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Section II-C: Oracles for phasing by cost function. Appendix A: Addition for controlled - rotations + rotations. """ phasegrad_bitsize: int diff --git a/qualtran/bloqs/chemistry/trotter/grid_ham/inverse_sqrt.py b/qualtran/bloqs/chemistry/trotter/grid_ham/inverse_sqrt.py index 1434f8760..d9beebf87 100644 --- a/qualtran/bloqs/chemistry/trotter/grid_ham/inverse_sqrt.py +++ b/qualtran/bloqs/chemistry/trotter/grid_ham/inverse_sqrt.py @@ -200,8 +200,7 @@ class PolynmomialEvaluationInverseSquareRoot(Bloq): out: Output register to store polynomial approximation to inverse square root. References: - [Quantum computation of stopping power for inertial fusion target design]( - https://arxiv.org/pdf/2308.12352.pdf) + [Quantum computation of stopping power for inertial fusion target design](https://arxiv.org/abs/2308.12352). """ x_sq_bitsize: int diff --git a/qualtran/bloqs/chemistry/trotter/grid_ham/trotter.ipynb b/qualtran/bloqs/chemistry/trotter/grid_ham/trotter.ipynb index 1a9d0dda8..27a61ad02 100644 --- a/qualtran/bloqs/chemistry/trotter/grid_ham/trotter.ipynb +++ b/qualtran/bloqs/chemistry/trotter/grid_ham/trotter.ipynb @@ -49,7 +49,7 @@ " - `out`: Output register to store polynomial approximation to inverse square root. \n", "\n", "#### References\n", - " - [Quantum computation of stopping power for inertial fusion target design]( https://arxiv.org/pdf/2308.12352.pdf)\n" + " - [Quantum computation of stopping power for inertial fusion target design](https://arxiv.org/abs/2308.12352). \n" ] }, { diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py b/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py index b5806ed41..7e9a93856 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/hopping.py @@ -174,8 +174,8 @@ class HoppingTileHWP(HoppingTile): system: The system register of size 2 `length`. References: - [Early fault-tolerant simulations of the Hubbard model]( - https://arxiv.org/abs/2012.09238) see Eq. 21 and App E. + [Early fault-tolerant simulations of the Hubbard model](https://arxiv.org/abs/2012.09238). + Eq. 21 and App E. """ def short_name(self) -> str: diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/hubbard.ipynb b/qualtran/bloqs/chemistry/trotter/hubbard/hubbard.ipynb index d0f82b9ab..54fab69e6 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/hubbard.ipynb +++ b/qualtran/bloqs/chemistry/trotter/hubbard/hubbard.ipynb @@ -463,7 +463,7 @@ " - `system`: The system register of size 2 `length`. \n", "\n", "#### References\n", - " - [Early fault-tolerant simulations of the Hubbard model]( https://arxiv.org/abs/2012.09238) see Eq. 21 and App E.\n" + " - [Early fault-tolerant simulations of the Hubbard model](https://arxiv.org/abs/2012.09238). Eq. 21 and App E.\n" ] }, { @@ -581,7 +581,7 @@ " - `system`: The system register of size 2 `length`. \n", "\n", "#### References\n", - " - [Early fault-tolerant simulations of the Hubbard model]( https://arxiv.org/abs/2012.09238) Eq. page 13 paragraph 1, and page 14 paragraph 3 right column. The apply 2 batches of $L^2/2$ rotations.\n" + " - [Early fault-tolerant simulations of the Hubbard model](https://arxiv.org/abs/2012.09238). Eq. page 13 paragraph 1, and page 14 paragraph 3 right column. They apply 2 batches of $L^2/2$ rotations.\n" ] }, { diff --git a/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py b/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py index 30b515299..9783ee833 100644 --- a/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py +++ b/qualtran/bloqs/chemistry/trotter/hubbard/interaction.py @@ -91,9 +91,9 @@ class InteractionHWP(Bloq): system: The system register of size 2 `length`. References: - [Early fault-tolerant simulations of the Hubbard model]( - https://arxiv.org/abs/2012.09238) Eq. page 13 paragraph 1, and page - 14 paragraph 3 right column. The apply 2 batches of $L^2/2$ rotations. + [Early fault-tolerant simulations of the Hubbard model](https://arxiv.org/abs/2012.09238). + Eq. page 13 paragraph 1, and page 14 paragraph 3 right column. + They apply 2 batches of $L^2/2$ rotations. """ length: SymbolicInt diff --git a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.ipynb b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.ipynb index 2dbaea6e4..c31c756fd 100644 --- a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.ipynb +++ b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.ipynb @@ -85,8 +85,8 @@ " - `system`: The system register to which to apply the unitary. \n", "\n", "#### References\n", - " - [Theory of Trotter Error with Commutator Scaling]( https://journals.aps.org/prx/abstract/10.1103/PhysRevX.11.011020) Eq. 12 page 7.\n", - " - [Trotter error with commutator scaling for the Fermi-Hubbard model]( https://arxiv.org/abs/2306.10603) see github repo for software to produce splittings.\n" + " - [Theory of Trotter Error with Commutator Scaling](https://journals.aps.org/prx/abstract/10.1103/PhysRevX.11.011020). Eq. 12 page 7.\n", + " - [Trotter error with commutator scaling for the Fermi-Hubbard model](https://arxiv.org/abs/2306.10603). See github repo for software to produce splittings.\n" ] }, { diff --git a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py index 91dd0736a..f362ad22e 100644 --- a/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py +++ b/qualtran/bloqs/chemistry/trotter/trotterized_unitary.py @@ -74,11 +74,11 @@ class TrotterizedUnitary(Bloq): system: The system register to which to apply the unitary. References: - [Theory of Trotter Error with Commutator Scaling]( - https://journals.aps.org/prx/abstract/10.1103/PhysRevX.11.011020) Eq. 12 page 7. + [Theory of Trotter Error with Commutator Scaling](https://journals.aps.org/prx/abstract/10.1103/PhysRevX.11.011020) + Eq. 12 page 7. - [Trotter error with commutator scaling for the Fermi-Hubbard model]( - https://arxiv.org/abs/2306.10603) see github repo for software to produce splittings. + [Trotter error with commutator scaling for the Fermi-Hubbard model](https://arxiv.org/abs/2306.10603). + See github repo for software to produce splittings. """ bloqs: Sequence[Bloq] diff --git a/qualtran/bloqs/for_testing/atom.py b/qualtran/bloqs/for_testing/atom.py index c7e998611..210ede7e8 100644 --- a/qualtran/bloqs/for_testing/atom.py +++ b/qualtran/bloqs/for_testing/atom.py @@ -27,7 +27,6 @@ GateWithRegisters, Signature, ) -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.resource_counting import CostKey, GateCounts, QECGatesCost if TYPE_CHECKING: @@ -72,9 +71,6 @@ def my_static_costs(self, cost_key: 'CostKey'): return GateCounts(t=100) return NotImplemented - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(100) - def __repr__(self): if self.tag: return f'TestAtom({self.tag!r})' @@ -154,8 +150,10 @@ def _unitary_(self): def adjoint(self) -> 'TestGWRAtom': return attrs.evolve(self, is_adjoint=not self.is_adjoint) - def _t_complexity_(self) -> 'TComplexity': - return TComplexity(100) + def my_static_costs(self, cost_key: 'CostKey'): + if isinstance(cost_key, QECGatesCost): + return GateCounts(t=100) + return NotImplemented def __repr__(self): tag = f'{self.tag!r}' if self.tag else '' diff --git a/qualtran/bloqs/mcmt/and_bloq.py b/qualtran/bloqs/mcmt/and_bloq.py index 9ca197238..e1da7fff5 100644 --- a/qualtran/bloqs/mcmt/and_bloq.py +++ b/qualtran/bloqs/mcmt/and_bloq.py @@ -48,7 +48,6 @@ from qualtran.bloqs.basic_gates import TGate, XGate from qualtran.bloqs.bookkeeping import ArbitraryClifford from qualtran.cirq_interop import decompose_from_cirq_style_method -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.drawing import Circle, directional_text_box, Text, WireSymbol from qualtran.resource_counting import ( big_O, @@ -126,19 +125,6 @@ def build_call_graph(self, ssa: 'SympySymbolAllocator') -> 'BloqCountDictT': return {ArbitraryClifford(n=2): 9 + 2 * pre_post_cliffords, TGate(): 4} - def _t_complexity_(self) -> 'TComplexity': - if not FLAG_AND_AS_LEAF: - return NotImplemented - - if isinstance(self.cv1, sympy.Expr) or isinstance(self.cv2, sympy.Expr): - pre_post_cliffords: Union[sympy.Order, int] = 0 - else: - pre_post_cliffords = 2 - self.cv1 - self.cv2 - if self.uncompute: - return TComplexity(clifford=4 + 2 * pre_post_cliffords) - - return TComplexity(t=4, clifford=9 + 2 * pre_post_cliffords) - def on_classical_vals( self, *, ctrl: NDArray[np.uint8], target: Optional[int] = None ) -> Dict[str, ClassicalValT]: diff --git a/qualtran/bloqs/multiplexers/apply_lth_bloq.ipynb b/qualtran/bloqs/multiplexers/apply_lth_bloq.ipynb index 3e6cdbf17..ff8d6499f 100644 --- a/qualtran/bloqs/multiplexers/apply_lth_bloq.ipynb +++ b/qualtran/bloqs/multiplexers/apply_lth_bloq.ipynb @@ -56,7 +56,7 @@ " - `[user_spec]`: The output registers of the bloqs in `ops`. \n", "\n", "#### References\n", - " - [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity]( https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.A. and Figure 7.\n" + " - [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.A. and Figure 7.\n" ] }, { diff --git a/qualtran/bloqs/multiplexers/apply_lth_bloq.py b/qualtran/bloqs/multiplexers/apply_lth_bloq.py index 8cb4888a5..a0de211a6 100644 --- a/qualtran/bloqs/multiplexers/apply_lth_bloq.py +++ b/qualtran/bloqs/multiplexers/apply_lth_bloq.py @@ -51,8 +51,8 @@ class ApplyLthBloq(UnaryIterationGate, SpecializedSingleQubitControlledExtension [user_spec]: The output registers of the bloqs in `ops`. References: - [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity]( - https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.A. and Figure 7. + [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). + Babbush et al. (2018). Section III.A. and Figure 7. """ # type ignore needed here for Bloq as NDArray parameter diff --git a/qualtran/bloqs/phase_estimation/lp_resource_state.py b/qualtran/bloqs/phase_estimation/lp_resource_state.py index d17866a49..53cadba44 100644 --- a/qualtran/bloqs/phase_estimation/lp_resource_state.py +++ b/qualtran/bloqs/phase_estimation/lp_resource_state.py @@ -106,11 +106,10 @@ class LPResourceState(QPEWindowStateBase): References: - [Optimum phase-shift estimation and the quantum description of the phase - difference](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.54.4564) + [Optimum phase-shift estimation and the quantum description of the phase difference](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.54.4564). - [Encoding Electronic Spectra in Quantum Circuits with Linear T - Complexity](https://arxiv.org/abs/1805.03662) Section II-B + [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). + Section II-B """ bitsize: SymbolicInt diff --git a/qualtran/bloqs/rotations/hamming_weight_phasing.ipynb b/qualtran/bloqs/rotations/hamming_weight_phasing.ipynb index 6d718e094..3279a78ef 100644 --- a/qualtran/bloqs/rotations/hamming_weight_phasing.ipynb +++ b/qualtran/bloqs/rotations/hamming_weight_phasing.ipynb @@ -199,7 +199,7 @@ " - `phase_grad`: Phase gradient THRU register of size `O(log2(1/eps))`, to be used to apply the phasing via addition. \n", "\n", "#### References\n", - " - 1. [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization] (https://arxiv.org/abs/2007.07391), Appendix A: Addition for controlled rotations\n" + " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Appendix A: Addition for controlled rotations\n" ] }, { diff --git a/qualtran/bloqs/rotations/hamming_weight_phasing.py b/qualtran/bloqs/rotations/hamming_weight_phasing.py index dce327221..1bfbe5e4b 100644 --- a/qualtran/bloqs/rotations/hamming_weight_phasing.py +++ b/qualtran/bloqs/rotations/hamming_weight_phasing.py @@ -154,8 +154,8 @@ class HammingWeightPhasingViaPhaseGradient(GateWithRegisters): apply the phasing via addition. References: - 1. [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization] - (https://arxiv.org/abs/2007.07391), Appendix A: Addition for controlled rotations + [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). + Appendix A: Addition for controlled rotations """ bitsize: int diff --git a/qualtran/bloqs/rotations/phase_gradient.ipynb b/qualtran/bloqs/rotations/phase_gradient.ipynb index 0245fccf8..ffe411603 100644 --- a/qualtran/bloqs/rotations/phase_gradient.ipynb +++ b/qualtran/bloqs/rotations/phase_gradient.ipynb @@ -70,7 +70,7 @@ "\n", "#### References\n", " - [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391). Appendix A: Addition for controlled rotations\n", - " - [Halving the cost of quantum addition](https://quantum-journal.org/papers/q-2018-06-18-74/pdf/). \n" + " - [Halving the cost of quantum addition](https://arxiv.org/abs/1709.06648). Gidney (2017).\n" ] }, { diff --git a/qualtran/bloqs/rotations/phase_gradient.py b/qualtran/bloqs/rotations/phase_gradient.py index 5a1d481fb..0a6dded65 100644 --- a/qualtran/bloqs/rotations/phase_gradient.py +++ b/qualtran/bloqs/rotations/phase_gradient.py @@ -88,7 +88,8 @@ class PhaseGradientUnitary(GateWithRegisters): [Compilation of Fault-Tolerant Quantum Heuristics for Combinatorial Optimization](https://arxiv.org/abs/2007.07391) Appendix A: Addition for controlled rotations - [Halving the cost of quantum addition](https://quantum-journal.org/papers/q-2018-06-18-74/pdf/) + [Halving the cost of quantum addition](https://arxiv.org/abs/1709.06648). + Gidney (2017). """ bitsize: 'SymbolicInt' diff --git a/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.ipynb b/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.ipynb index fd94fe55f..081add39d 100644 --- a/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.ipynb +++ b/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.ipynb @@ -241,7 +241,8 @@ "Total space will be $(2 \\log(L) + \\log(d) + 2 \\mu + 1)$ work qubits + $log(L)$ ancillas for QROM.\n", "\n", "#### References\n", - " - [1] [Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization](https://arxiv.org/pdf/1902.02134#page=15.30) Berry et al. (2019). Section 5, Eqs. 43, 44. [2] [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.D. and Figure 11.\n" + " - [Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization](https://arxiv.org/abs/1902.02134). Berry et al. (2019). Section 5, Eqs. 43, 44.\n", + " - [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.D. and Figure 11.\n" ] }, { diff --git a/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.py b/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.py index 258a33c87..4850ef95d 100644 --- a/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.py +++ b/qualtran/bloqs/state_preparation/state_preparation_alias_sampling.py @@ -348,9 +348,10 @@ class SparseStatePreparationAliasSampling(PrepareOracle): Total space will be $(2 \log(L) + \log(d) + 2 \mu + 1)$ work qubits + $log(L)$ ancillas for QROM. References: - [1] [Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization](https://arxiv.org/pdf/1902.02134#page=15.30) + [Qubitization of Arbitrary Basis Quantum Chemistry Leveraging Sparsity and Low Rank Factorization](https://arxiv.org/abs/1902.02134). Berry et al. (2019). Section 5, Eqs. 43, 44. - [2] [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). + + [Encoding Electronic Spectra in Quantum Circuits with Linear T Complexity](https://arxiv.org/abs/1805.03662). Babbush et al. (2018). Section III.D. and Figure 11. """ diff --git a/qualtran/cirq_interop/_bloq_to_cirq.py b/qualtran/cirq_interop/_bloq_to_cirq.py index 61475b8c8..70f6d122c 100644 --- a/qualtran/cirq_interop/_bloq_to_cirq.py +++ b/qualtran/cirq_interop/_bloq_to_cirq.py @@ -122,10 +122,6 @@ def bloq_on( ) return BloqAsCirqGate(bloq=bloq).on_registers(**all_quregs), out_quregs - def _t_complexity_(self): - """Delegate to the bloq's t complexity.""" - return self._bloq.t_complexity() - def _num_qubits_(self) -> int: return total_bits(self.signature) diff --git a/qualtran/cirq_interop/_bloq_to_cirq_test.py b/qualtran/cirq_interop/_bloq_to_cirq_test.py index 8ecc6a59b..95dae1cef 100644 --- a/qualtran/cirq_interop/_bloq_to_cirq_test.py +++ b/qualtran/cirq_interop/_bloq_to_cirq_test.py @@ -25,7 +25,6 @@ from qualtran.bloqs.mcmt.and_bloq import And, MultiAnd from qualtran.bloqs.state_preparation import PrepareUniformSuperposition from qualtran.cirq_interop._bloq_to_cirq import BloqAsCirqGate, CirqQuregT -from qualtran.cirq_interop.t_complexity_protocol import t_complexity_compat from qualtran.testing import execute_notebook if TYPE_CHECKING: @@ -235,7 +234,6 @@ def test_bloq_as_cirq_gate_for_mod_exp(): # newly allocated RIGHT registers in the decomposition to the one's specified by the user # when constructing the original operation (in this case, register `x`). circuit = cirq.Circuit(op, cirq.decompose_once(op)) - assert t_complexity_compat(circuit) == 2 * mod_exp.t_complexity() cirq.testing.assert_has_diagram( circuit, ''' @@ -260,7 +258,6 @@ def test_bloq_as_cirq_gate_for_mod_exp(): # Whereas when directly applying a cirq gate on qubits to get an operations, we need to # specify both input and output registers. circuit = cirq.Circuit(gate.on_registers(**out_regs), decomposed_circuit) - assert t_complexity_compat(circuit) == 2 * mod_exp.t_complexity() # Notice the newly allocated qubits _C(0) and _C(1) for output register x. cirq.testing.assert_has_diagram( circuit, diff --git a/qualtran/cirq_interop/_cirq_to_bloq.py b/qualtran/cirq_interop/_cirq_to_bloq.py index 7dd96fc7c..f71810df9 100644 --- a/qualtran/cirq_interop/_cirq_to_bloq.py +++ b/qualtran/cirq_interop/_cirq_to_bloq.py @@ -47,7 +47,7 @@ split_qubits, ) from qualtran.cirq_interop._interop_qubit_manager import InteropQubitManager -from qualtran.cirq_interop.t_complexity_protocol import _from_directly_countable_cirq, TComplexity +from qualtran.cirq_interop.t_complexity_protocol import _from_directly_countable_cirq from qualtran.resource_counting import CostKey, GateCounts, QECGatesCost if TYPE_CHECKING: @@ -147,12 +147,6 @@ def __str__(self) -> str: def cirq_gate(self) -> cirq.Gate: return self.gate - def _t_complexity_(self) -> 'TComplexity': - t_count = _from_directly_countable_cirq(self.cirq_gate) - if t_count is None: - raise ValueError(f"Cirq gate must be directly countable, not {self.cirq_gate}") - return t_count - def my_static_costs(self, cost_key: 'CostKey'): if isinstance(cost_key, QECGatesCost): t_count = _from_directly_countable_cirq(self.cirq_gate) diff --git a/qualtran/cirq_interop/t_complexity_protocol.py b/qualtran/cirq_interop/t_complexity_protocol.py index 00114bf17..64e3da56f 100644 --- a/qualtran/cirq_interop/t_complexity_protocol.py +++ b/qualtran/cirq_interop/t_complexity_protocol.py @@ -11,15 +11,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import warnings -from typing import Any, Callable, Iterable, Optional, Protocol, Union +from typing import Any, Callable, Iterable, Optional, Union import attrs import cachetools import cirq -from qualtran import Bloq, DecomposeNotImplementedError, DecomposeTypeError -from qualtran.resource_counting import BloqCountT, SympySymbolAllocator +from qualtran import Bloq from qualtran.symbolics import ceil, log2, SymbolicFloat, SymbolicInt from .decompose_protocol import _decompose_once_considering_known_decomposition @@ -72,17 +70,6 @@ def __str__(self) -> str: ) -class SupportsTComplexity(Protocol): - """An object whose TComplexity can be computed. - - An object whose TComplexity can be computed either implements the `_t_complexity_` function - or is of a type that SupportsDecompose. - """ - - def _t_complexity_(self) -> TComplexity: - """Returns the TComplexity.""" - - def _from_explicit_annotation(stc: Any) -> Optional[TComplexity]: """Returns TComplexity of stc by calling `stc._t_complexity_()` method, if it exists.""" estimator = getattr(stc, '_t_complexity_', None) @@ -95,24 +82,6 @@ def _from_explicit_annotation(stc: Any) -> Optional[TComplexity]: return None -def _from_directly_countable_bloqs(bloq: Bloq) -> Optional[TComplexity]: - """Directly count a clifford, T or Rotation (if it is one).""" - from qualtran.bloqs.basic_gates import TGate - from qualtran.resource_counting.classify_bloqs import bloq_is_clifford, bloq_is_rotation - - if isinstance(bloq, TGate): - return TComplexity(t=1) - - if bloq_is_clifford(bloq): - return TComplexity(clifford=1) - - if bloq_is_rotation(bloq): - return TComplexity(rotations=1) - - # Else - return None - - def _from_directly_countable_cirq(stc: Any) -> Optional[TComplexity]: """Directly count a clifford, T or Rotation (if it is one).""" if not isinstance(stc, (cirq.Gate, cirq.Operation)): @@ -156,28 +125,6 @@ def _from_iterable(it: Any) -> Optional[TComplexity]: return t -def _from_bloq_build_call_graph(bloq: Bloq) -> Optional[TComplexity]: - # Uses the depth 1 call graph of Bloq `stc` to recursively compute the complexity. - try: - callee_counts = bloq.build_call_graph(ssa=SympySymbolAllocator()) - except (DecomposeNotImplementedError, DecomposeTypeError): - # We must explicitly catch these exceptions rather than using `get_bloq_callee_counts` - # to distinguish between no decomposition and an empty list of callees. - return None - - ret = TComplexity() - if isinstance(callee_counts, set): - callee_iterator: Iterable[BloqCountT] = callee_counts - else: - callee_iterator = callee_counts.items() - for callee, n in callee_iterator: - r = t_complexity(callee) - if r is None: - return None - ret += n * r - return ret - - def _from_cirq_decomposition(stc: Any) -> Optional[TComplexity]: # Decompose the object and recursively compute the complexity. decomposition = _decompose_once_considering_known_decomposition(stc) @@ -233,19 +180,6 @@ def _t_complexity_for_gate_or_op( return _t_complexity_from_strategies(gate_or_op, strategies) -@cachetools.cached(cachetools.LRUCache(128), key=_get_hash, info=True) -def _t_complexity_for_bloq(bloq: Bloq) -> Optional[TComplexity]: - strategies = [ - _from_explicit_annotation, - _from_bloq_build_call_graph, - _from_directly_countable_bloqs, - ] - return _t_complexity_from_strategies(bloq, strategies) - - -USE_NEW_GATE_COUNTING_FLAG = True - - def t_complexity(bloq: Bloq) -> TComplexity: """Returns the TComplexity of a bloq. @@ -258,17 +192,9 @@ def t_complexity(bloq: Bloq) -> TComplexity: Raises: TypeError: if none of the strategies can derive the t complexity. """ - if USE_NEW_GATE_COUNTING_FLAG: - from qualtran.resource_counting import get_cost_value, QECGatesCost + from qualtran.resource_counting import get_cost_value, QECGatesCost - return get_cost_value(bloq, QECGatesCost(legacy_shims=True)).to_legacy_t_complexity() - - ret = _t_complexity_for_bloq(bloq) - if ret is None: - raise TypeError( - "couldn't compute TComplexity of:\n" f"type: {type(bloq)}\n" f"value: {bloq}" - ) - return ret + return get_cost_value(bloq, QECGatesCost(legacy_shims=True)).to_legacy_t_complexity() def t_complexity_compat(stc: Any) -> TComplexity: @@ -287,18 +213,7 @@ def t_complexity_compat(stc: Any) -> TComplexity: Raises: TypeError: if the methods fails to compute TComplexity. """ - from qualtran.cirq_interop import BloqAsCirqGate - - if isinstance(stc, Bloq): - warnings.warn("Please use `t_complexity`, not the _compat version.") - ret = _t_complexity_for_bloq(stc) - elif isinstance(stc, BloqAsCirqGate): - ret = _t_complexity_for_bloq(stc.bloq) - elif isinstance(stc, cirq.Operation) and isinstance(stc.gate, Bloq): - ret = _t_complexity_for_bloq(stc.gate) - elif isinstance(stc, cirq.Operation) and isinstance(stc.gate, BloqAsCirqGate): - ret = _t_complexity_for_bloq(stc.gate.bloq) - elif isinstance(stc, (cirq.AbstractCircuit, cirq.Moment, list)): + if isinstance(stc, (cirq.AbstractCircuit, cirq.Moment, list)): ret = _from_iterable(stc) elif isinstance(stc, (cirq.Gate, cirq.Operation)): ret = _t_complexity_for_gate_or_op(stc) @@ -308,8 +223,3 @@ def t_complexity_compat(stc: Any) -> TComplexity: if ret is None: raise TypeError("couldn't compute TComplexity of:\n" f"type: {type(stc)}\n" f"value: {stc}") return ret - - -t_complexity.cache_clear = _t_complexity_for_bloq.cache_clear # type: ignore[attr-defined] -t_complexity.cache_info = _t_complexity_for_bloq.cache_info # type: ignore[attr-defined] -t_complexity.cache = _t_complexity_for_bloq.cache # type: ignore[attr-defined] diff --git a/qualtran/cirq_interop/t_complexity_protocol_test.py b/qualtran/cirq_interop/t_complexity_protocol_test.py index cf5d9166f..99496f4d7 100644 --- a/qualtran/cirq_interop/t_complexity_protocol_test.py +++ b/qualtran/cirq_interop/t_complexity_protocol_test.py @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Set, TYPE_CHECKING import cirq import pytest @@ -30,9 +29,6 @@ from qualtran.cirq_interop.testing import GateHelper from qualtran.testing import execute_notebook -if TYPE_CHECKING: - from qualtran.resource_counting import BloqCountT, SympySymbolAllocator - class DoesNotSupportTComplexity: ... @@ -66,21 +62,9 @@ def signature(self) -> 'Signature': return Signature.build(q=1) -@frozen -class SupportsTComplexityBloqViaBuildCallGraph(Bloq): - @property - def signature(self) -> 'Signature': - return Signature.build(q=1) - - def build_call_graph(self, ssa: 'SympySymbolAllocator') -> Set['BloqCountT']: - return {(SupportsTComplexityGateWithRegisters(), 5)} - - -def test_t_complexity_for_bloq_via_build_call_graph(): - bloq = SupportsTComplexityBloqViaBuildCallGraph() - _, sigma = bloq.call_graph(max_depth=1) - assert sigma != {} - assert t_complexity(bloq) == TComplexity(t=5, clifford=10) +def test_legacy_t_complexity_annotation(): + # Test the deprecated `getattr(.., '_t_complexity_') + assert SupportsTComplexityGateWithRegisters().t_complexity() == TComplexity(t=1, clifford=2) def test_t_complexity_for_bloq_does_not_support(): @@ -100,7 +84,7 @@ def test_t_complexity_compat(): g = GateHelper(SupportsTComplexityGateWithRegisters()) assert g.gate._decompose_with_context_(g.operation.qubits) is NotImplemented # type: ignore[attr-defined] - assert t_complexity(g.gate) == TComplexity(t=1, clifford=2) + assert t_complexity_compat(g.gate) == TComplexity(t=1, clifford=2) assert t_complexity_compat(g.operation) == TComplexity(t=1, clifford=2) assert t_complexity_compat([cirq.T, cirq.X]) == TComplexity(t=1, clifford=1) diff --git a/qualtran/cirq_interop/testing.py b/qualtran/cirq_interop/testing.py index 34428b838..203207f75 100644 --- a/qualtran/cirq_interop/testing.py +++ b/qualtran/cirq_interop/testing.py @@ -20,7 +20,7 @@ import numpy as np from numpy.typing import NDArray -from qualtran import Bloq, DecomposeNotImplementedError, DecomposeTypeError, Signature +from qualtran import Bloq, Signature from qualtran._infra.gate_with_registers import get_named_qubits, merge_qubits from qualtran.cirq_interop import t_complexity_protocol from qualtran.cirq_interop.decompose_protocol import _decompose_once_considering_known_decomposition @@ -126,21 +126,19 @@ def get_circuit_inp_out_cirqsim( def assert_decompose_is_consistent_with_t_complexity(val: Any): + if isinstance(val, Bloq): + raise ValueError( + f"Use `qlt_testing.assert_equivalent_bloq_counts` for testing bloqs: {val}." + ) + t_complexity_method = getattr(val, '_t_complexity_', None) expected = NotImplemented if t_complexity_method is None else t_complexity_method() if expected is NotImplemented or expected is None: raise AssertionError("No consistent t_complexity: no _t_complexity_.") - if isinstance(val, Bloq): - try: - cbloq = val.decompose_bloq() - except (DecomposeNotImplementedError, DecomposeTypeError) as e: - raise AssertionError("No consistent t_complexity: no decomposition.") from e - from_decomposition = t_complexity_protocol._from_bloq_build_call_graph(cbloq) - else: - decomposition = _decompose_once_considering_known_decomposition(val) - if decomposition is None: - raise AssertionError("No consistent t_complexity: no decomposition.") - from_decomposition = t_complexity_protocol._from_iterable(decomposition) + decomposition = _decompose_once_considering_known_decomposition(val) + if decomposition is None: + raise AssertionError("No consistent t_complexity: no decomposition.") + from_decomposition = t_complexity_protocol._from_iterable(decomposition) assert expected == from_decomposition, f'{expected} != {from_decomposition}' diff --git a/qualtran/cirq_interop/testing_test.py b/qualtran/cirq_interop/testing_test.py index 72c75e75c..cc35f145e 100644 --- a/qualtran/cirq_interop/testing_test.py +++ b/qualtran/cirq_interop/testing_test.py @@ -11,14 +11,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Iterator +from typing import Iterator import cirq import numpy as np import pytest -from qualtran import Bloq, BloqBuilder, QBit, Register, Side, Signature, SoquetT -from qualtran.bloqs.basic_gates import XGate +from qualtran import QBit, Register, Side, Signature from qualtran.bloqs.mcmt.and_bloq import MultiAnd from qualtran.cirq_interop import testing from qualtran.cirq_interop.t_complexity_protocol import TComplexity @@ -59,9 +58,6 @@ def test_gate_helper(): class DoesNotDecompose(cirq.Operation): - def _t_complexity_(self) -> TComplexity: - return TComplexity(t=1, clifford=2, rotations=3) - @property def qubits(self): return [] @@ -85,23 +81,5 @@ def with_qubits(self, _): pass -class InconsistentDecompostion(Bloq): - @property - def signature(self) -> 'Signature': - return Signature.build(q=1) - - def _t_complexity_(self) -> TComplexity: - return TComplexity(rotations=1) - - def build_composite_bloq(self, bb: 'BloqBuilder', q: 'SoquetT') -> Dict[str, 'SoquetT']: - q = bb.add(XGate(), q=q) - return {'q': q} - - def test_assert_decompose_is_consistent_with_t_complexity(): testing.assert_decompose_is_consistent_with_t_complexity(ConsistentDecompostion()) - - -def test_assert_decompose_is_consistent_with_t_complexity_raises(): - with pytest.raises(AssertionError): - testing.assert_decompose_is_consistent_with_t_complexity(InconsistentDecompostion()) diff --git a/qualtran/linalg/matrix.py b/qualtran/linalg/matrix.py index cc800bbec..d87eb7e1e 100644 --- a/qualtran/linalg/matrix.py +++ b/qualtran/linalg/matrix.py @@ -13,12 +13,13 @@ # limitations under the License. import numpy as np -from cirq.testing.lin_alg_utils import random_orthogonal from numpy.typing import NDArray def random_hermitian_matrix(dim: int, random_state: np.random.RandomState) -> NDArray: """Return a random Hermitian matrix of given dimension and norm <= 1.""" + from cirq.testing.lin_alg_utils import random_orthogonal + a = random_orthogonal(dim, random_state=random_state) return (a + a.conj().T) / 2 diff --git a/qualtran/resource_counting/_bloq_counts.py b/qualtran/resource_counting/_bloq_counts.py index 24a9bc672..02ad3c404 100644 --- a/qualtran/resource_counting/_bloq_counts.py +++ b/qualtran/resource_counting/_bloq_counts.py @@ -297,7 +297,10 @@ def compute(self, bloq: 'Bloq', get_callee_cost: Callable[['Bloq'], GateCounts]) from qualtran.bloqs.mcmt import And, MultiTargetCNOT if self.legacy_shims: - legacy_val = bloq._t_complexity_() + if hasattr(bloq, '_t_complexity_'): + legacy_val = bloq._t_complexity_() + else: + legacy_val = NotImplemented if legacy_val is not NotImplemented: warnings.warn( "Please migrate explicit cost annotations to the general " diff --git a/qualtran/resource_counting/t_counts_from_sigma.py b/qualtran/resource_counting/t_counts_from_sigma.py index 3eaf867cf..02c6673c6 100644 --- a/qualtran/resource_counting/t_counts_from_sigma.py +++ b/qualtran/resource_counting/t_counts_from_sigma.py @@ -14,8 +14,6 @@ import warnings from typing import Mapping -import cirq - from qualtran import Bloq, Controlled from qualtran.symbolics import ceil, SymbolicInt @@ -23,6 +21,9 @@ def t_counts_from_sigma(sigma: Mapping['Bloq', SymbolicInt]) -> SymbolicInt: """Aggregates T-counts from a sigma dictionary by summing T-costs for all rotation bloqs.""" warnings.warn("This function is deprecated. Use `get_cost_value`.", DeprecationWarning) + # TODO: remove dependence on cirq.has_stabilizer_effect. + import cirq + from qualtran.bloqs.basic_gates import TGate, Toffoli, TwoBitCSwap from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.resource_counting.classify_bloqs import bloq_is_rotation diff --git a/qualtran/serialization/bloq_test.py b/qualtran/serialization/bloq_test.py index 5964908ee..218206d7f 100644 --- a/qualtran/serialization/bloq_test.py +++ b/qualtran/serialization/bloq_test.py @@ -26,7 +26,6 @@ from qualtran.bloqs.factoring.mod_exp import ModExp from qualtran.cirq_interop import CirqGateAsBloq from qualtran.cirq_interop._cirq_to_bloq_test import TestCNOT as TestCNOTCirq -from qualtran.cirq_interop.t_complexity_protocol import TComplexity from qualtran.protos import registers_pb2 from qualtran.resource_counting import CostKey, GateCounts, QECGatesCost from qualtran.serialization import bloq as bloq_serialization @@ -96,9 +95,6 @@ class TestCSwap(Bloq): def signature(self) -> 'Signature': return Signature.build(ctrl=1, x=self.bitsize, y=self.bitsize) - def _t_complexity_(self) -> TComplexity: - return TComplexity(t=7 * self.bitsize, clifford=10 * self.bitsize) - def my_static_costs(self, cost_key: 'CostKey'): if isinstance(cost_key, QECGatesCost): return GateCounts(t=7 * self.bitsize, clifford=10 * self.bitsize) diff --git a/qualtran/simulation/tensor/_dense_test.py b/qualtran/simulation/tensor/_dense_test.py index 991d68df9..45f1e4223 100644 --- a/qualtran/simulation/tensor/_dense_test.py +++ b/qualtran/simulation/tensor/_dense_test.py @@ -15,8 +15,8 @@ from functools import cached_property from typing import Dict, List -import cirq import numpy as np +import pytest import quimb.tensor as qtn from attrs import frozen @@ -121,6 +121,7 @@ def build_composite_bloq(self, bb: 'BloqBuilder', s: 'SoquetT') -> Dict[str, 'So def test_nest(): + cirq = pytest.importorskip('cirq') x = XNest() should_be = cirq.unitary(cirq.X) np.testing.assert_allclose(should_be, x.tensor_contract()) @@ -128,6 +129,7 @@ def test_nest(): def test_double_nest(): + cirq = pytest.importorskip('cirq') xx = XDoubleNest() should_be = cirq.unitary(cirq.X) np.testing.assert_allclose(should_be, xx.tensor_contract()) @@ -150,6 +152,7 @@ def build_composite_bloq( def test_bloq_with_non_trivial_inds(): + cirq = pytest.importorskip('cirq') bloq = BloqWithNonTrivialInds() assert_valid_bloq_decomposition(bloq) cirq_qubits = cirq.LineQubit.range(2) diff --git a/qualtran/symbolics/types.py b/qualtran/symbolics/types.py index b9f017fc0..18714b6f8 100644 --- a/qualtran/symbolics/types.py +++ b/qualtran/symbolics/types.py @@ -15,17 +15,16 @@ import sympy from attrs import field, frozen, validators -from cirq._doc import document from typing_extensions import TypeIs SymbolicFloat = Union[float, sympy.Expr] -document(SymbolicFloat, """A floating point value or a sympy expression.""") +"""A floating point value or a sympy expression.""" SymbolicInt = Union[int, sympy.Expr] -document(SymbolicFloat, """A floating point value or a sympy expression.""") +"""An integer value or a sympy expression.""" SymbolicComplex = Union[complex, sympy.Expr] -document(SymbolicComplex, """A complex value or a sympy expression.""") +"""A complex value or a sympy expression.""" @frozen