From a66c4169be7e723c9d9e676356d000ef283cb36f Mon Sep 17 00:00:00 2001 From: Classiq Bot Date: Mon, 15 Apr 2024 11:33:49 +0000 Subject: [PATCH] Updates for 0.40.0 --- CONTRIBUTING.md | 42 - README.md | 12 +- .../algebraic/discrete_log/discrete_log.ipynb | 399 ++++++++++ .../algebraic/discrete_log/discrete_log.json | 6 + .../algebraic/discrete_log/discrete_log.qmod | 24 + .../discrete_log.synthesis_options.json | 5 + .../algebraic/hidden_shift/hidden_shift.ipynb | 1 - .../shor/doubly_controlled_modular_adder.qmod | 12 +- algorithms/algebraic/shor/shor.ipynb | 8 +- .../shor/shor_modular_exponentiation.ipynb | 40 +- .../shor/shor_modular_exponentiation.qmod | 20 +- .../qmc_user_defined/qmc_user_defined.ipynb | 7 +- .../qmc_user_defined/qmc_user_defined.qmod | 4 +- .../quantum_counting/quantum_counting.ipynb | 8 +- .../quantum_counting_iqae.qmod | 6 +- .../quantum_counting_qpe.qmod | 4 +- .../bernstein_vazirani.ipynb | 10 +- .../bernstein_vazirani_example.qmod | 2 +- .../grover/3_sat_grover/3_sat_grover.ipynb | 6 +- .../3_sat_grover_large.ipynb | 8 +- .../grover_max_cut/grover_max_cut.ipynb | 6 +- algorithms/hhl/hhl/hhl.ipynb | 32 +- algorithms/hhl/hhl/hhl.qmod | 2 +- .../qml/qgan/qgan_bars_and_strips.ipynb | 208 ++--- .../quantum_autoencoder.ipynb | 39 +- .../qpe/qpe_for_matrix/qpe_for_matrix.ipynb | 24 +- ..._fixed_point_amplitude_amplification.ipynb | 46 +- ...t_fixed_point_amplitude_amplification.qmod | 4 +- .../qsvt_matrix_inversion.ipynb | 42 +- .../qsvt_matrix_inversion.qmod | 4 +- algorithms/simon/simon.ipynb | 6 +- algorithms/simon/simon_shallow_example.qmod | 8 +- algorithms/swap_test/swap_test.ipynb | 4 +- .../quantum_volume/quantum_volume.ipynb | 204 ++--- .../randomized_benchmarking.ipynb | 9 +- .../molecular_energy_curve.qmod | 4 +- .../molecule_eigensolver.ipynb | 13 +- .../molecule_eigensolver.qmod | 4 +- .../protein_folding/protein_folding.qmod | 4 +- .../qpe_for_molecules/qpe_for_molecules.ipynb | 8 +- .../qpe_for_molecules/qpe_for_molecules.qmod | 2 +- .../second_quantized_hamiltonian.qmod | 4 +- .../link_monitoring/link_monitoring.qmod | 4 +- .../patch_min_vertex_cover.qmod | 4 +- .../whitebox_fuzzing/whitebox_fuzzing.ipynb | 12 +- .../whitebox_fuzzing/whitebox_fuzzing.qmod | 4 +- .../option_pricing/option_pricing.qmod | 4 +- .../portfolio_optimization.qmod | 4 +- .../facility_location/facility_location.qmod | 4 +- .../task_scheduling_problem.qmod | 4 +- .../task_scheduling_problem_large.qmod | 4 +- .../traveling_saleman_problem.qmod | 4 +- .../electric_grid_optimization.qmod | 4 +- .../integer_linear_programming.qmod | 4 +- .../knapsack_binary/knapsack_binary.qmod | 4 +- .../knapsack_integer/knapsack_integer.qmod | 4 +- .../optimization/max_clique/max_clique.qmod | 4 +- .../optimization/max_cut/max_cut.qmod | 4 +- .../max_independent_set.qmod | 4 +- .../max_induced_k_color_subgraph.qmod | 4 +- .../max_k_vertex_cover.qmod | 4 +- .../min_graph_coloring.qmod | 4 +- .../minimum_dominating_set.qmod | 4 +- .../optimization/set_cover/set_cover.qmod | 4 +- .../set_partition/set_partition.qmod | 4 +- .../ising_model/ising_model.qmod | 4 +- built_in_apps/chemistry/chemistry.ipynb | 9 +- built_in_apps/chemistry/chemistry.qmod | 4 +- built_in_apps/grover/grover.ipynb | 8 +- .../option_pricing/option_pricing.ipynb | 4 +- .../option_pricing/option_pricing.qmod | 4 +- .../function_declarations/core_lib_decls.qmod | 34 +- .../function_declarations/open_lib_decls.qmod | 9 + .../amplitude_loading_example.ipynb | 109 +++ .../amplitude_loading_example.json | 6 + .../amplitude_loading_example.qmod | 5 + ...de_loading_example.synthesis_options.json} | 0 .../arithmetic/addition.json | 7 - .../arithmetic/addition.qmod | 17 - .../arithmetic/addition_two_regs.json | 7 - .../arithmetic/addition_two_regs.qmod | 16 - .../arithmetic/arithmetic_expression.json | 7 - .../arithmetic/arithmetic_expression.qmod | 28 - .../arithmetic_expression_example.ipynb | 133 ++++ .../arithmetic_expression_example.json | 6 + .../arithmetic_expression_example.qmod | 6 + ..._expression_example.synthesis_options.json | 1 + .../arithmetic/bitwise_and.json | 7 - .../arithmetic/bitwise_and.qmod | 16 - .../bitwise_and_2vars_example.json | 6 + .../bitwise_and_2vars_example.qmod | 5 + ...e_and_2vars_example.synthesis_options.json | 1 + .../bitwise_and/bitwise_and_example.ipynb | 177 +++++ .../bitwise_and_integer_example.json | 6 + .../bitwise_and_integer_example.qmod | 4 + ...and_integer_example.synthesis_options.json | 1 + .../arithmetic/bitwise_and_two_regs.json | 7 - .../arithmetic/bitwise_and_two_regs.qmod | 16 - .../arithmetic/bitwise_invert.qmod | 16 - .../bitwise_invert_example.ipynb | 88 +++ .../bitwise_invert_example.json} | 3 +- .../bitwise_invert_example.qmod | 4 + ...wise_invert_example.synthesis_options.json | 1 + .../arithmetic/bitwise_or.json | 7 - .../arithmetic/bitwise_or.qmod | 16 - .../bitwise_or/bitwise_or_2vars_example.json | 6 + .../bitwise_or/bitwise_or_2vars_example.qmod | 7 + ...se_or_2vars_example.synthesis_options.json | 1 + .../bitwise_or/bitwise_or_example.ipynb | 188 +++++ .../bitwise_or_integer_example.json | 6 + .../bitwise_or_integer_example.qmod | 4 + ..._or_integer_example.synthesis_options.json | 1 + .../arithmetic/bitwise_or_two_regs.json | 7 - .../arithmetic/bitwise_or_two_regs.qmod | 21 - .../arithmetic/bitwise_xor.json | 7 - .../arithmetic/bitwise_xor.qmod | 16 - .../bitwise_xor_2vars_example.json | 6 + .../bitwise_xor_2vars_example.qmod | 7 + ...e_xor_2vars_example.synthesis_options.json | 1 + .../bitwise_xor/bitwise_xor_example.ipynb | 188 +++++ .../bitwise_xor_integer_example.json | 6 + .../bitwise_xor_integer_example.qmod | 4 + ...xor_integer_example.synthesis_options.json | 1 + .../arithmetic/bitwise_xor_two_regs.json | 7 - .../arithmetic/bitwise_xor_two_regs.qmod | 21 - .../comparator/comparator_2vars_example.json | 6 + .../comparator/comparator_2vars_example.qmod | 5 + ...rator_2vars_example.synthesis_options.json | 1 + .../comparator/comparator_example.ipynb | 178 +++++ .../comparator_integer_example.json | 6 + .../comparator_integer_example.qmod | 5 + ...tor_integer_example.synthesis_options.json | 1 + .../arithmetic/comparators_ex1.json | 7 - .../arithmetic/comparators_ex1.qmod | 21 - .../arithmetic/comparators_ex2.json | 7 - .../arithmetic/comparators_ex2.qmod | 18 - .../extremum/extremum_example.ipynb | 193 +++++ .../extremum/maximum_float_example.json | 6 + .../extremum/maximum_float_example.qmod | 5 + ...ximum_float_example.synthesis_options.json | 1 + .../extremum/maximum_integer_example.qmod | 5 + ...mum_integer_example.synthesis_options.json | 1 + .../extremum/minimum_2vars_example.json | 6 + .../extremum/minimum_2vars_example.qmod | 6 + ...nimum_2vars_example.synthesis_options.json | 1 + .../arithmetic/minimum_and_maximum_ex1.json | 7 - .../arithmetic/minimum_and_maximum_ex1.qmod | 16 - .../arithmetic/minimum_and_maximum_ex2.json | 7 - .../arithmetic/minimum_and_maximum_ex2.qmod | 16 - .../arithmetic/modulo/modulo_example.ipynb | 123 +++ .../modulo_example.json} | 3 +- .../arithmetic/modulo/modulo_example.qmod | 7 + .../modulo_example.synthesis_options.json | 1 + .../arithmetic/modulo_ex1.qmod | 17 - .../arithmetic/modulo_ex2.json | 7 - .../arithmetic/modulo_ex2.qmod | 16 - .../multiplication/multiplication.ipynb | 191 +++++ .../multiplication_2vars_example.json | 6 + .../multiplication_2vars_example.qmod | 5 + ...ation_2vars_example.synthesis_options.json | 1 + .../multiplication_float_example.json | 6 + .../multiplication_float_example.qmod | 5 + ...ation_float_example.synthesis_options.json | 1 + .../arithmetic/multiplication_ex1.json | 7 - .../arithmetic/multiplication_ex1.qmod | 16 - .../arithmetic/multiplication_ex2.json | 7 - .../arithmetic/multiplication_ex2.qmod | 18 - .../arithmetic/negation.json | 7 - .../arithmetic/negation.qmod | 16 - .../negation/negation_example.ipynb | 109 +++ .../arithmetic/negation/negation_example.json | 6 + .../arithmetic/negation/negation_example.qmod | 5 + .../negation_example.synthesis_options.json | 1 + .../subtraction_2vars_example.json | 6 + .../subtraction_2vars_example.qmod | 5 + ...ction_2vars_example.synthesis_options.json | 1 + .../subtraction/subtraction_example.ipynb | 164 ++++ .../subtraction_float_example.json | 6 + .../subtraction_float_example.qmod | 4 + ...ction_float_example.synthesis_options.json | 1 + .../arithmetic/subtraction_ex1.json | 7 - .../arithmetic/subtraction_ex1.qmod | 16 - .../arithmetic/subtraction_ex2.json | 7 - .../arithmetic/subtraction_ex2.qmod | 16 - .../grover_operator_example.ipynb | 252 ++++++ .../grover_operator_example.json | 6 + .../grover_operator_example.qmod | 19 + ...er_operator_example.synthesis_options.json | 5 + .../hadamard_transform.ipynb | 100 +++ .../hadamard_transform_example.json | 6 + .../hadamard_transform_example.qmod | 4 + ...d_transform_example.synthesis_options.json | 1 + .../exponentiation/exponentiation.ipynb | 144 ++++ .../exponentiation_example.json | 6 + .../exponentiation_example.qmod | 41 + ...onentiation_example.synthesis_options.json | 1 + .../hamiltonian_evolution/qdrift/qdrift.ipynb | 105 +++ .../qdrift/qdrift_example.json | 6 + .../qdrift/qdrift_example.qmod | 13 + .../qdrift_example.synthesis_options.json | 1 + .../suzuki_trotter/suzuki_trotter.ipynb | 106 +++ .../suzuki_trotter_example.json | 6 + .../suzuki_trotter_example.qmod | 21 + ...uki_trotter_example.synthesis_options.json | 1 + .../linear_pauli_rotations_example.ipynb | 144 ++++ .../linear_pauli_rotations_example.json | 6 + .../linear_pauli_rotations_example.qmod | 5 + ...i_rotations_example.synthesis_options.json | 1 + .../mcx/mcx_example.ipynb | 134 ++++ .../mcx/mcx_example.json | 6 + .../mcx/mcx_example.qmod | 7 + .../mcx/mcx_example.synthesis_options.json | 1 + .../function_usage_examples/qft/qft.ipynb | 2 +- ...ft_usage_example.json => qft_example.json} | 0 ...ft_usage_example.qmod => qft_example.qmod} | 0 .../qft/qft_example.synthesis_options.json | 1 + .../function_usage_examples/qpe/qpe.json | 7 - .../function_usage_examples/qpe/qpe.qmod | 36 - .../qpe/qpe_custom_function.json | 7 - .../qpe/qpe_custom_function.qmod | 32 - .../qpe/qpe_example.ipynb | 299 +++++++ .../qpe/qpe_example.json | 6 + .../qpe/qpe_example.qmod | 8 + .../qpe/qpe_example.synthesis_options.json | 1 + .../qpe/qpe_flexible_example.json | 6 + .../qpe/qpe_flexible_example.qmod | 21 + ...pe_flexible_example.synthesis_options.json | 1 + .../standard_gates/CRX_example.json | 7 + .../standard_gates/CRX_example.qmod | 7 + .../CRX_example.synthesis_options.json | 1 + .../standard_gates/CX_example.json | 7 + .../standard_gates/CX_example.qmod | 7 + .../CX_example.synthesis_options.json | 1 + .../standard_gates/PHASE_example.json | 7 + .../standard_gates/PHASE_example.qmod | 5 + .../PHASE_example.synthesis_options.json | 1 + .../standard_gates/RZZ_example.json | 7 + .../standard_gates/RZZ_example.qmod | 5 + .../RZZ_example.synthesis_options.json | 1 + .../standard_gates/RZ_example.json | 7 + .../standard_gates/RZ_example.qmod | 5 + .../RZ_example.synthesis_options.json | 1 + .../standard_gates/R_example.json | 7 + .../standard_gates/R_example.qmod | 5 + .../R_example.synthesis_options.json | 1 + .../standard_gates/SWAP_example.json | 7 + .../standard_gates/SWAP_example.qmod | 7 + .../SWAP_example.synthesis_options.json | 1 + .../standard_gates/U_example.json | 7 + .../standard_gates/U_example.qmod | 5 + .../U_example.synthesis_options.json | 1 + .../standard_gates/X_example.json | 7 + .../standard_gates/X_example.qmod | 5 + .../X_example.synthesis_options.json | 1 + .../standard_gates_example.ipynb | 520 +++++++++++++ .../bell_state_preparation.json | 7 - .../bell_state_preparation.qmod | 15 - .../computational_state_preparation.json | 7 - .../computational_state_preparation.qmod | 15 - .../exponential_state_preparation.json | 7 - .../exponential_state_preparation.qmod | 16 - .../inplace_prepare_int_example.json | 7 + .../inplace_prepare_int_example.qmod | 4 + ...prepare_int_example.synthesis_options.json | 1 + .../prepare_amplitudes_example.json | 7 + .../prepare_amplitudes_example.qmod | 12 + ..._amplitudes_example.synthesis_options.json | 1 + .../prepare_bell_state_example.ipynb | 14 +- .../prepare_bell_state_example.json | 10 +- .../prepare_bell_state_example.qmod | 1 - ..._bell_state_example.synthesis_options.json | 2 +- .../prepare_exponential_state_example.ipynb | 113 +++ .../prepare_exponential_state_example.json | 7 + .../prepare_exponential_state_example.qmod | 4 + ...ntial_state_example.synthesis_options.json | 1 + .../prepare_ghz_state_example.ipynb | 43 +- .../prepare_ghz_state_example.json | 10 +- .../prepare_ghz_state_example.qmod | 1 - ...e_ghz_state_example.synthesis_options.json | 2 +- .../prepare_int_example.ipynb | 159 ++++ .../prepare_int_example.json | 7 + .../prepare_int_example.qmod | 3 + ...prepare_int_example.synthesis_options.json | 1 + .../prepare_state_example.ipynb | 309 ++++++++ .../prepare_state_example.json | 7 + .../prepare_state_example.qmod | 12 + ...epare_state_example.synthesis_options.json | 1 + ...niform_distribution_state_preparation.json | 7 - ...niform_distribution_state_preparation.qmod | 15 - .../w_state_preparation.json | 7 - .../w_state_preparation.qmod | 15 - .../unitary/unitary_example.ipynb | 19 +- .../unitary/unitary_example.qmod | 1 - .../unitary_example.synthesis_options.json | 2 +- .../open_library_definitions/_check_msb.qmod | 9 + .../open_library_definitions/_ctrl_x.qmod | 5 + .../apply_to_all.qmod | 2 +- .../c_modular_multiply.qmod | 9 + .../cc_modular_add.qmod | 24 + .../open_library_definitions/full_hea.qmod | 12 +- .../inplace_c_modular_multiply.qmod | 12 + .../inplace_prepare_int.qmod | 4 +- .../linear_pauli_rotations.qmod | 2 +- .../open_library_definitions/modular_exp.qmod | 8 + .../open_library_definitions/multiswap.qmod | 5 + .../prepare_exponential_state.qmod | 2 +- .../prepare_ghz_state.qmod | 4 +- .../open_library_definitions/qaoa_init.qmod | 2 +- .../qaoa_mixer_layer.qmod | 2 +- .../qaoa_penalty.qmod | 2 +- functions/open_library_definitions/qft.qmod | 8 +- .../open_library_definitions/qft_no_swap.qmod | 5 + .../qft_space_add_const.qmod | 5 + .../open_library_definitions/qft_step.qmod | 4 +- .../qpe_flexible.qmod | 2 +- .../reflect_about_zero.qmod | 4 +- .../single_pauli.qmod | 2 +- .../open_library_definitions/swap_test.qmod | 2 +- .../classiq_concepts/repeat/repeat.ipynb | 155 ++++ tutorials/classiq_concepts/repeat/repeat.json | 7 + tutorials/classiq_concepts/repeat/repeat.qmod | 9 + .../repeat/repeat.synthesis_options.json | 1 + tutorials/exponentiation/exponentiation.ipynb | 4 +- ...rithmetic.ipynb => part1_arithmetic.ipynb} | 73 +- ...on.ipynb => part2_state_preparation.ipynb} | 59 +- ..._Jozsa.ipynb => part3_deutsch_jozsa.ipynb} | 69 +- ..._GHZ_state.ipynb => part4_ghz_state.ipynb} | 45 +- ...{Part5_Grover.ipynb => part5_grover.ipynb} | 123 ++- .../hardware_aware_mcx.ipynb | 2 +- .../high_level_modeling_flexible_qpe.ipynb | 14 +- tutorials/mcx/mcx.ipynb | 4 +- .../optimization/learning_optimization.ipynb | 4 +- tutorials/phase_kickback/phase_kickback.ipynb | 12 +- tutorials/prepare_state/prepare_state.ipynb | 7 +- tutorials/prepare_state/prepare_state.json | 2 +- .../hamiltonian_evolution.ipynb | 2 +- .../technology_demonstrations/hhl/hhl.ipynb | 22 +- .../qpe_for_grover_operator.ipynb | 13 +- .../QMOD_workshop/QMOD_Workshop_Part_1.ipynb | 619 --------------- .../QMOD_workshop/QMOD_Workshop_Part_2.ipynb | 735 ------------------ .../QMOD_workshop/QMOD_Workshop_Part_3.ipynb | 276 ------- 341 files changed, 6369 insertions(+), 3164 deletions(-) delete mode 100644 CONTRIBUTING.md create mode 100644 algorithms/algebraic/discrete_log/discrete_log.ipynb create mode 100644 algorithms/algebraic/discrete_log/discrete_log.json create mode 100644 algorithms/algebraic/discrete_log/discrete_log.qmod create mode 100644 algorithms/algebraic/discrete_log/discrete_log.synthesis_options.json create mode 100644 functions/function_usage_examples/amplitude_loading/amplitude_loading_example.ipynb create mode 100644 functions/function_usage_examples/amplitude_loading/amplitude_loading_example.json create mode 100644 functions/function_usage_examples/amplitude_loading/amplitude_loading_example.qmod rename functions/function_usage_examples/{qft/qft_usage_example.synthesis_options.json => amplitude_loading/amplitude_loading_example.synthesis_options.json} (100%) delete mode 100644 functions/function_usage_examples/arithmetic/addition.json delete mode 100644 functions/function_usage_examples/arithmetic/addition.qmod delete mode 100644 functions/function_usage_examples/arithmetic/addition_two_regs.json delete mode 100644 functions/function_usage_examples/arithmetic/addition_two_regs.qmod delete mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression.json delete mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression.qmod create mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.json create mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_and.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_and.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_and_two_regs.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_and_two_regs.qmod delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_invert.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.ipynb rename functions/function_usage_examples/arithmetic/{bitwise_invert.json => bitwise_invert/bitwise_invert_example.json} (67%) create mode 100644 functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_or.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_or.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_or_two_regs.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_or_two_regs.qmod delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.json create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.json delete mode 100644 functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.qmod create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.json create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/comparators_ex1.json delete mode 100644 functions/function_usage_examples/arithmetic/comparators_ex1.qmod delete mode 100644 functions/function_usage_examples/arithmetic/comparators_ex2.json delete mode 100644 functions/function_usage_examples/arithmetic/comparators_ex2.qmod create mode 100644 functions/function_usage_examples/arithmetic/extremum/extremum_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/extremum/maximum_float_example.json create mode 100644 functions/function_usage_examples/arithmetic/extremum/maximum_float_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/extremum/maximum_float_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.json delete mode 100644 functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.qmod delete mode 100644 functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.json delete mode 100644 functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.qmod create mode 100644 functions/function_usage_examples/arithmetic/modulo/modulo_example.ipynb rename functions/function_usage_examples/arithmetic/{modulo_ex1.json => modulo/modulo_example.json} (64%) create mode 100644 functions/function_usage_examples/arithmetic/modulo/modulo_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/modulo/modulo_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/modulo_ex1.qmod delete mode 100644 functions/function_usage_examples/arithmetic/modulo_ex2.json delete mode 100644 functions/function_usage_examples/arithmetic/modulo_ex2.qmod create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication.ipynb create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.json create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/multiplication_ex1.json delete mode 100644 functions/function_usage_examples/arithmetic/multiplication_ex1.qmod delete mode 100644 functions/function_usage_examples/arithmetic/multiplication_ex2.json delete mode 100644 functions/function_usage_examples/arithmetic/multiplication_ex2.qmod delete mode 100644 functions/function_usage_examples/arithmetic/negation.json delete mode 100644 functions/function_usage_examples/arithmetic/negation.qmod create mode 100644 functions/function_usage_examples/arithmetic/negation/negation_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/negation/negation_example.json create mode 100644 functions/function_usage_examples/arithmetic/negation/negation_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/negation/negation_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.json create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.synthesis_options.json create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_example.ipynb create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.json create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.qmod create mode 100644 functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/arithmetic/subtraction_ex1.json delete mode 100644 functions/function_usage_examples/arithmetic/subtraction_ex1.qmod delete mode 100644 functions/function_usage_examples/arithmetic/subtraction_ex2.json delete mode 100644 functions/function_usage_examples/arithmetic/subtraction_ex2.qmod create mode 100644 functions/function_usage_examples/grover_operator/grover_operator_example.ipynb create mode 100644 functions/function_usage_examples/grover_operator/grover_operator_example.json create mode 100644 functions/function_usage_examples/grover_operator/grover_operator_example.qmod create mode 100644 functions/function_usage_examples/grover_operator/grover_operator_example.synthesis_options.json create mode 100644 functions/function_usage_examples/hadamard_transform/hadamard_transform.ipynb create mode 100644 functions/function_usage_examples/hadamard_transform/hadamard_transform_example.json create mode 100644 functions/function_usage_examples/hadamard_transform/hadamard_transform_example.qmod create mode 100644 functions/function_usage_examples/hadamard_transform/hadamard_transform_example.synthesis_options.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation.ipynb create mode 100644 functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.qmod create mode 100644 functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.synthesis_options.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift.ipynb create mode 100644 functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.qmod create mode 100644 functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.synthesis_options.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter.ipynb create mode 100644 functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.json create mode 100644 functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.qmod create mode 100644 functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.synthesis_options.json create mode 100644 functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.ipynb create mode 100644 functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.json create mode 100644 functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.qmod create mode 100644 functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.synthesis_options.json create mode 100644 functions/function_usage_examples/mcx/mcx_example.ipynb create mode 100644 functions/function_usage_examples/mcx/mcx_example.json create mode 100644 functions/function_usage_examples/mcx/mcx_example.qmod create mode 100644 functions/function_usage_examples/mcx/mcx_example.synthesis_options.json rename functions/function_usage_examples/qft/{qft_usage_example.json => qft_example.json} (100%) rename functions/function_usage_examples/qft/{qft_usage_example.qmod => qft_example.qmod} (100%) create mode 100644 functions/function_usage_examples/qft/qft_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/qpe/qpe.json delete mode 100644 functions/function_usage_examples/qpe/qpe.qmod delete mode 100644 functions/function_usage_examples/qpe/qpe_custom_function.json delete mode 100644 functions/function_usage_examples/qpe/qpe_custom_function.qmod create mode 100644 functions/function_usage_examples/qpe/qpe_example.ipynb create mode 100644 functions/function_usage_examples/qpe/qpe_example.json create mode 100644 functions/function_usage_examples/qpe/qpe_example.qmod create mode 100644 functions/function_usage_examples/qpe/qpe_example.synthesis_options.json create mode 100644 functions/function_usage_examples/qpe/qpe_flexible_example.json create mode 100644 functions/function_usage_examples/qpe/qpe_flexible_example.qmod create mode 100644 functions/function_usage_examples/qpe/qpe_flexible_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/CRX_example.json create mode 100644 functions/function_usage_examples/standard_gates/CRX_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/CRX_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/CX_example.json create mode 100644 functions/function_usage_examples/standard_gates/CX_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/CX_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/PHASE_example.json create mode 100644 functions/function_usage_examples/standard_gates/PHASE_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/PHASE_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/RZZ_example.json create mode 100644 functions/function_usage_examples/standard_gates/RZZ_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/RZZ_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/RZ_example.json create mode 100644 functions/function_usage_examples/standard_gates/RZ_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/RZ_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/R_example.json create mode 100644 functions/function_usage_examples/standard_gates/R_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/R_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/SWAP_example.json create mode 100644 functions/function_usage_examples/standard_gates/SWAP_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/SWAP_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/U_example.json create mode 100644 functions/function_usage_examples/standard_gates/U_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/U_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/X_example.json create mode 100644 functions/function_usage_examples/standard_gates/X_example.qmod create mode 100644 functions/function_usage_examples/standard_gates/X_example.synthesis_options.json create mode 100644 functions/function_usage_examples/standard_gates/standard_gates_example.ipynb delete mode 100644 functions/function_usage_examples/state_preparation/bell_state_preparation.json delete mode 100644 functions/function_usage_examples/state_preparation/bell_state_preparation.qmod delete mode 100644 functions/function_usage_examples/state_preparation/computational_state_preparation.json delete mode 100644 functions/function_usage_examples/state_preparation/computational_state_preparation.qmod delete mode 100644 functions/function_usage_examples/state_preparation/exponential_state_preparation.json delete mode 100644 functions/function_usage_examples/state_preparation/exponential_state_preparation.qmod create mode 100644 functions/function_usage_examples/state_preparation/inplace_prepare_int_example.json create mode 100644 functions/function_usage_examples/state_preparation/inplace_prepare_int_example.qmod create mode 100644 functions/function_usage_examples/state_preparation/inplace_prepare_int_example.synthesis_options.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_amplitudes_example.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_amplitudes_example.qmod create mode 100644 functions/function_usage_examples/state_preparation/prepare_amplitudes_example.synthesis_options.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_exponential_state_example.ipynb create mode 100644 functions/function_usage_examples/state_preparation/prepare_exponential_state_example.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_exponential_state_example.qmod create mode 100644 functions/function_usage_examples/state_preparation/prepare_exponential_state_example.synthesis_options.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_int_example.ipynb create mode 100644 functions/function_usage_examples/state_preparation/prepare_int_example.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_int_example.qmod create mode 100644 functions/function_usage_examples/state_preparation/prepare_int_example.synthesis_options.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_state_example.ipynb create mode 100644 functions/function_usage_examples/state_preparation/prepare_state_example.json create mode 100644 functions/function_usage_examples/state_preparation/prepare_state_example.qmod create mode 100644 functions/function_usage_examples/state_preparation/prepare_state_example.synthesis_options.json delete mode 100644 functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.json delete mode 100644 functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.qmod delete mode 100644 functions/function_usage_examples/state_preparation/w_state_preparation.json delete mode 100644 functions/function_usage_examples/state_preparation/w_state_preparation.qmod create mode 100644 functions/open_library_definitions/_check_msb.qmod create mode 100644 functions/open_library_definitions/_ctrl_x.qmod create mode 100644 functions/open_library_definitions/c_modular_multiply.qmod create mode 100644 functions/open_library_definitions/cc_modular_add.qmod create mode 100644 functions/open_library_definitions/inplace_c_modular_multiply.qmod create mode 100644 functions/open_library_definitions/modular_exp.qmod create mode 100644 functions/open_library_definitions/multiswap.qmod create mode 100644 functions/open_library_definitions/qft_no_swap.qmod create mode 100644 functions/open_library_definitions/qft_space_add_const.qmod create mode 100644 tutorials/classiq_concepts/repeat/repeat.ipynb create mode 100644 tutorials/classiq_concepts/repeat/repeat.json create mode 100644 tutorials/classiq_concepts/repeat/repeat.qmod create mode 100644 tutorials/classiq_concepts/repeat/repeat.synthesis_options.json rename tutorials/getting_started/{Part1_Arithmetic.ipynb => part1_arithmetic.ipynb} (98%) rename tutorials/getting_started/{Part2_State_preparation.ipynb => part2_state_preparation.ipynb} (65%) rename tutorials/getting_started/{Part3_Deutsch_Jozsa.ipynb => part3_deutsch_jozsa.ipynb} (95%) rename tutorials/getting_started/{Part4_GHZ_state.ipynb => part4_ghz_state.ipynb} (95%) rename tutorials/getting_started/{Part5_Grover.ipynb => part5_grover.ipynb} (98%) delete mode 100644 tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_1.ipynb delete mode 100644 tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_2.ipynb delete mode 100644 tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_3.ipynb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 9da6e0f1..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,42 +0,0 @@ -# Contributing to Classiq - -We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: -- Creating a new algorithm, application or function 🚀 -- Submitting your research done with Classiq 👩🏻‍💻 -- Reporting a bug 🐞 -- Discussing the current state of the code - -## We Develop with Github - -We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. - -## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests - -Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests: - -1. Create an issue to discuss what you will be submitting. We will reply swiftly with comments and feedback. -2. Fork the repo and create your branch from `main`. -3. Ensure your code runs with the latest Classiq version. -4. Issue that pull request! - -## Any contributions you make will be under the MIT Software License - -In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://opensource.org/licenses/MIT) that covers the project. Feel free to contact the maintainers if that's a concern. - -## Report bugs using Github's [issues](https://github.com/[YourRepo]/issues) - -We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/[YourRepo]/issues/new); it's that easy! - -Write bug reports with detail, background, and sample code - -## License - -By contributing, you agree that your contributions will be licensed under its MIT License. - -## References - -Here are a few references you might find helpful: - -- [How to Contribute to an Open Source Project on GitHub](https://opensource.guide/how-to-contribute/) -- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/) -- [GitHub Flow](https://guides.github.com/introduction/flow/) diff --git a/README.md b/README.md index 1b7a551e..ea5e2ea5 100644 --- a/README.md +++ b/README.md @@ -93,13 +93,13 @@ def main(res: Output[QBit]): X(res) ``` -The 1st line states that the function will be a quantum one. [Further documentation](https://docs.classiq.io/latest/user-guide/platform/qmod/python/functions/). +The 1st line states that the function will be a quantum one. [Further documentation](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/functions/). -The 2nd line defines the type of the output. [Further examples on types](https://docs.classiq.io/latest/user-guide/platform/qmod/python/types/) +The 2nd line defines the type of the output. [Further examples on types](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/) -The 3rd line allocates several qubits (in this example, only 1) in this quantum variable. [Further details on allocate](https://docs.classiq.io/latest/user-guide/platform/qmod/python/quantum-expressions/) +The 3rd line allocates several qubits (in this example, only 1) in this quantum variable. [Further details on allocate](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-variables/) -The 4th line applies an `X` operator on the quantum variable. [Further details on quantum operators](https://docs.classiq.io/latest/user-guide/platform/qmod/python/operators/) +The 4th line applies an `X` operator on the quantum variable. [Further details on quantum operators](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/operators/) ### More Examples @@ -127,9 +127,7 @@ A part of a QML encoder (see the full algirthm [here](/algorithms/qml/quantum_au ```python @qfunc -def angle_encoding( - exe_params: QParam[List[float]], qbv: Output[QArray[QBit, "len(exe_params)"]] -) -> None: +def angle_encoding(exe_params: CArray[CReal], qbv: Output[QArray[QBit]]) -> None: allocate(exe_params.len, qbv) repeat( count=exe_params.len, diff --git a/algorithms/algebraic/discrete_log/discrete_log.ipynb b/algorithms/algebraic/discrete_log/discrete_log.ipynb new file mode 100644 index 00000000..e105e916 --- /dev/null +++ b/algorithms/algebraic/discrete_log/discrete_log.ipynb @@ -0,0 +1,399 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d6f83f81-aceb-42e3-ad75-f5978c201cdc", + "metadata": {}, + "source": [ + "# Discrete Logarithm" + ] + }, + { + "cell_type": "markdown", + "id": "d5201d9c-44c5-47e8-a742-3b562c3a7f6d", + "metadata": {}, + "source": [ + "The Discrete Logarithm Problem [[1](#DiscreteLog)] was shown by Shor [[2](#Shor)] to be solved in a polynomial time using quantum computers, while the fastest classical algorithms take a superpolynomial time. The problem is at least as hard as the factoring problem. In fact, the hardness of the problem is the basis for the Diffie-Hellman [[3](#DiffieHellman)]] protocol for key exchange. \n", + "\n", + "### Problem formulation\n", + "\n", + "* **Input:** A cyclic group $G = \\langle g \\rangle$ with $g$ as a generator, and an element $x\\in G$.\n", + "\n", + "* **Promise:** There is a number $s$ such that $g^s = x$.\n", + "\n", + "* **Output:** $s$, the discrete logarithm: $s = \\log_gx$\n", + "\n", + "*** \n", + "\n", + "In Shor's implementation the order of $g$ is assumed to be known beforehand (for example using the order finding algorithm). We will also assume it in the demonstration. \n", + "\n", + "The Discrete Log problem is a specific example for the Abelian Hidden Subgroup Problem [[4](#HSP)], for the case where G is the additive group $\\mathbb{Z}_N \\times \\mathbb{Z}_N$, with the function:\n", + "$$\n", + "f(\\alpha, \\beta) = x^\\alpha g^\\beta\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "8ab4be3d-dbd8-41d4-be9d-d025deebf713", + "metadata": {}, + "source": [ + "## How to build the Algorithm with Classiq" + ] + }, + { + "cell_type": "markdown", + "id": "b14cfda4-29fa-45e5-a59c-f4c798f09172", + "metadata": {}, + "source": [ + "The heart of the algorithm's logic is the implementation of the function:\n", + "$$\n", + "|x_1\\rangle|x_2\\rangle|1\\rangle \\rightarrow |x_1\\rangle|x_2\\rangle|x^{x_1} g^{x_2}\\rangle \n", + "$$\n", + "\n", + "This is done using 2 applications of the modular exponentiation function, which was described in detail in the [Shor's Factoring Algorithm](https://github.com/Classiq/classiq-library/blob/main/algorithms/algebraic/shor/shor_modular_exponentiation.ipynb) notebook. So here we will just import it from the classiq's library.\n", + "\n", + "The function `modular_exp` accepts the following arguments:\n", + "- `n: CInt` - modulo number\n", + "- `a: CInt` - base of the exponentiation\n", + "- `x: QArray[QBit]` - unsigned integer to multiply be the exponentiation\n", + "- `power: QArray[QBit]`- power of the exponentiation\n", + "\n", + "So that the function implements:\n", + "$|power\\rangle|x\\rangle \\rightarrow |power\\rangle|x \\cdot a ^ {power}\\mod n\\rangle$" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2bbc4aa3-8f61-433d-a1cd-c58df445a2fd", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq.qmod import (\n", + " CInt,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " inplace_prepare_int,\n", + " modular_exp,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def discrete_log_oracle(\n", + " g: CInt,\n", + " x: CInt,\n", + " N: CInt,\n", + " order: CInt,\n", + " x1: QArray[QBit],\n", + " x2: QArray[QBit],\n", + " func_res: Output[QArray[QBit]],\n", + ") -> None:\n", + "\n", + " allocate(ceiling(log(N, 2)), func_res)\n", + "\n", + " inplace_prepare_int(1, func_res)\n", + " modular_exp(N, x, func_res, x1)\n", + " modular_exp(N, g, func_res, x2)" + ] + }, + { + "cell_type": "markdown", + "id": "23cf730e-17d2-4a76-b4d6-d39d4c9b865a", + "metadata": {}, + "source": [ + "### The full algorithm:\n", + "1. Prepare uniform superposition over the first 2 quantum variables `x1`, `x2`. Each variable should be with size $\\lceil \\log r\\rceil + \\log({1/{\\epsilon}})$. In the special case where $r$ is a power of 2, $\\log r$ is enough.\n", + "3. Compute `discrete_log_oracle` on the `func_res` variable. `func_res` should be of size $\\lceil \\log N\\rceil$.\n", + "4. Apply inverse Fourier transform `x1`, `x2`.\n", + "5. Measure." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "d7fb63ac-023d-40ac-9395-13c1274d446f", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq.qmod import hadamard_transform, invert, qft\n", + "from classiq.qmod.symbolic import ceiling, log\n", + "\n", + "\n", + "@qfunc\n", + "def discrete_log(\n", + " g: CInt,\n", + " x: CInt,\n", + " N: CInt,\n", + " order: CInt,\n", + " x1: Output[QArray[QBit]],\n", + " x2: Output[QArray[QBit]],\n", + " func_res: Output[QArray[QBit]],\n", + ") -> None:\n", + " reg_len = ceiling(log(order, 2))\n", + " allocate(reg_len, x1)\n", + " allocate(reg_len, x2)\n", + "\n", + " hadamard_transform(x1)\n", + " hadamard_transform(x2)\n", + "\n", + " discrete_log_oracle(g, x, N, order, x1, x2, func_res)\n", + "\n", + " invert(lambda: qft(x1))\n", + " invert(lambda: qft(x2))" + ] + }, + { + "cell_type": "markdown", + "id": "56b2c254-8894-4b05-9cf1-deded6ab15cc", + "metadata": {}, + "source": [ + "After the inverse QFTs, we get in the variables (under the assumption of $r=2^m$ for some $m$):\n", + "$$|\\psi\\rangle = \\sum_{\\nu\\in\\mathbb{Z}_r, \\delta\\in G}\\omega^{\\nu\\delta}|\\nu log_gx\\rangle_{x_1}|\\nu\\rangle_{x_2}|\\delta>_{func\\_res}$$\n", + "\n", + "For every $\\nu$ that has a mutplicative inverse in $\\mathbb{Z}_r$, we can extract $s=\\log_xg$ by multiplying the first variable result by its inverse.\n", + "\n", + "In the case where $r$ is not a power of 2, we get in the variables and approximation of: |$ \\log_g(x) \\nu/ r\\rangle_{x_1} |\\nu / r\\rangle_{x_2}$. So we can use the continued fractions algorithm [[5](#ContinuedFraction)] to compute $\\nu/r$, then using the same technique to calculate $\\log_gx$.\n", + "\n", + "*Note: Alternatively, one might implement the $QFT_{\\mathbb{Z}_r}$ over general $r$, and instead of the uniform superposition prepare the states: $\\frac{1}{\\sqrt{r}}\\sum_{x\\in\\mathbb{r}}|x\\rangle$ in `x1`, `x2`. Then again no continued fractions post-process is required.*" + ] + }, + { + "attachments": { + "0df89caa-9909-4177-a19f-bb5c4e232fbb.png": { + "image/png": "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95iPj/YhPnr6Mv74oY8AP/ZngOof9A/6B/2D/iGyDPD00D/oH8pXBOgf9Y/6R/2j/lH/aHyQhkcDPnB+0flX55+df0/HS0kQ6Tk/8AM/8EPyAT/0EUg8+JEf282PKhgkS5kigAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAQFUClRUM+jPrBzJiPC9n2uORf48aXHBxrx736uEBHuABHuABHuABHuABHuABHuABHuABHuABHuABHuABHuABHuCB4nhABYOquRdmIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggEAioIJB6V54MmqKk1Ejg057F+/inQd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAeG5gEVDFKqhSkCCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIVCWggoEKBio49MjQkqE1tAwt3HCT4cqfPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADRfKACgZVcy/MQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAIFEoLKCQenV3tJfyrAYeFO6wtt8fLQP8dHvA37oI5B82cOP/MiP/MiPkWVqpwc/9mfu6x/0D/oH/YP+Qf+gf0zDgwEfOH5y/s35R+df0/FCEkR6zg/8wA/8kHzAD30EEg9+5Ed+5Mfkg3bwowoGaS+YIoAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggEBVApUVDFKlAtPyFRYpE8TUvXPcO8e9c3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB3iAB4ruARUMquZemIEAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACiYAKBqV7Ico0kmlU9Ewj288DPMiDPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADPMADtTyggkFKtTBFAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAgaoEVDBQwUAFhx6ZSLUykcyXsShjkSd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAd4gAdUMKiae2EGAggggAACCCCAAAIIIIAAAggg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" + } + }, + "cell_type": "markdown", + "id": "1b9aebdf-295f-4560-8b5c-37bdcc7edeb2", + "metadata": {}, + "source": [ + "![image.png](attachment:0df89caa-9909-4177-a19f-bb5c4e232fbb.png)" + ] + }, + { + "cell_type": "markdown", + "id": "d7f5e1b8-9bfc-4aad-a1dd-2c41d151e148", + "metadata": {}, + "source": [ + "## Example: $G = \\mathbb{Z}_5^\\times$" + ] + }, + { + "cell_type": "markdown", + "id": "c8c1edc5-0271-48c6-ac7d-7bdc17598568", + "metadata": {}, + "source": [ + "For this specific demonstration, we choose $G = \\mathbb{Z}_5^\\times$, with $g=3$ and $x=2$. Under this setting, $log_gx=3$.\n", + "\n", + "We choose this specific example as the order of of the group $r=4$ is a power of $2$, and so we can get exactly the discrete logarithm, without continued-fractions post processing. In other cases, one has to use larger quantum variable for the exponents so the continued fractions post-processing will converge." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "8ef24bb4-b063-42d6-a5ea-ddcd5310ae13", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Constraints, create_model\n", + "\n", + "MODULU_NUM = 5\n", + "G = 3\n", + "X = 2\n", + "ORDER = MODULU_NUM - 1 # as 5 is prime\n", + "\n", + "\n", + "@qfunc\n", + "def main(\n", + " x1: Output[QNum],\n", + " x2: Output[QNum],\n", + " func_res: Output[QNum],\n", + ") -> None:\n", + " discrete_log(G, X, MODULU_NUM, ORDER, x1, x2, func_res)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8e9d0b08-f3f8-4e95-a468-bfeec010d97c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/e3dcf0d1-74ff-494d-b958-9337fb1f32ef?version=0.0.0\n" + ] + } + ], + "source": [ + "from classiq import Preferences, show, synthesize, write_qmod\n", + "\n", + "constraints = Constraints(max_width=13)\n", + "qmod = create_model(main, constraints=constraints)\n", + "write_qmod(qmod, \"discrete_log\")\n", + "\n", + "qprog = synthesize(qmod)\n", + "show(qprog)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "0aef2760-aa9a-4710-8c60-08333a0a9b0b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'x1': 0.0, 'x2': 0.0, 'func_res': 3.0}: 81,\n", + " {'x1': 0.0, 'x2': 0.0, 'func_res': 4.0}: 75,\n", + " {'x1': 1.0, 'x2': 3.0, 'func_res': 1.0}: 69,\n", + " {'x1': 0.0, 'x2': 0.0, 'func_res': 1.0}: 68,\n", + " {'x1': 3.0, 'x2': 1.0, 'func_res': 1.0}: 67,\n", + " {'x1': 3.0, 'x2': 1.0, 'func_res': 2.0}: 66,\n", + " {'x1': 1.0, 'x2': 3.0, 'func_res': 4.0}: 65,\n", + " {'x1': 3.0, 'x2': 1.0, 'func_res': 4.0}: 63,\n", + " {'x1': 2.0, 'x2': 2.0, 'func_res': 3.0}: 61,\n", + " {'x1': 2.0, 'x2': 2.0, 'func_res': 2.0}: 59,\n", + " {'x1': 0.0, 'x2': 0.0, 'func_res': 2.0}: 59,\n", + " {'x1': 2.0, 'x2': 2.0, 'func_res': 4.0}: 58,\n", + " {'x1': 3.0, 'x2': 1.0, 'func_res': 3.0}: 58,\n", + " {'x1': 2.0, 'x2': 2.0, 'func_res': 1.0}: 57,\n", + " {'x1': 1.0, 'x2': 3.0, 'func_res': 3.0}: 48,\n", + " {'x1': 1.0, 'x2': 3.0, 'func_res': 2.0}: 46]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute\n", + "\n", + "results = execute(qprog).result()\n", + "res = results[0].value\n", + "res.parsed_counts" + ] + }, + { + "cell_type": "markdown", + "id": "c405feed-408f-4d91-a22c-0b445b2ff6c2", + "metadata": {}, + "source": [ + "Notice that `func_res` is uncorrelated to the other variables, and we get uniform distribution, as expected. \n", + "\n", + "We take only the `x2` that are co-prime to $r=4$, so they have a multiplicative-inverse. Hence `x2=1,3` are the relevant results.\n", + "So we get 2 relevant results (for all different $\\delta$s): $|1\\rangle|3\\rangle$, $|3\\rangle|1\\rangle$. All left to do to get the logarithm is to multiply `x1` by the inverse of `x2`:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4aa286cd-7e4e-408f-90ed-910485becd71", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "print(3 * pow(1, -1, 4))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "444d0916-e611-49fa-afc4-324e65240b34", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3\n" + ] + } + ], + "source": [ + "print(1 * pow(3, -1, 4))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "cbb1b0b3-6091-421b-85bb-7b9b8da0b724", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2\n" + ] + } + ], + "source": [ + "print(3**3 % 5)" + ] + }, + { + "cell_type": "markdown", + "id": "3fd236be-032d-4513-806c-086a8623a40d", + "metadata": {}, + "source": [ + "And indeed in both cases the same result, which is exactly the discrete logarithm: $\\log_32 \\mod 5 = 3$" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "169a1e57-fed2-4e27-a4c1-9206fa5ba021", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1]: [Discrete Logarithm (Wikipedia)](https://en.wikipedia.org/wiki/Discrete_logarithm)\n", + "\n", + "[2]: [Shor, Peter W. \"Algorithms for quantum computation: discrete logarithms and factoring.\" Proceedings 35th annual symposium on foundations of computer science. Ieee, 1994.](https://ieeexplore.ieee.org/abstract/document/365700)\n", + "\n", + "[3]: [Diffie-Hellman Key Exchange (Wikipedia)](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)\n", + "\n", + "[4]: [Hidden Subgroup Problem (Wikipedia)](https://en.wikipedia.org/wiki/Hidden_subgroup_problem)\n", + "\n", + "[5]: [Continued Fraction (Wikipedia)](https://en.wikipedia.org/wiki/Continued_fraction)\n" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/algorithms/algebraic/discrete_log/discrete_log.json b/algorithms/algebraic/discrete_log/discrete_log.json new file mode 100644 index 00000000..4d5a5d66 --- /dev/null +++ b/algorithms/algebraic/discrete_log/discrete_log.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Discrete Logarithm", + "description": "Solving Discrete Logarithm Problem using Shor's Algorithm", + "qmod_type": ["algorithms"], + "level": ["advanced"] +} diff --git a/algorithms/algebraic/discrete_log/discrete_log.qmod b/algorithms/algebraic/discrete_log/discrete_log.qmod new file mode 100644 index 00000000..51c9e0f4 --- /dev/null +++ b/algorithms/algebraic/discrete_log/discrete_log.qmod @@ -0,0 +1,24 @@ +qfunc discrete_log_oracle(x1: qbit[], x2: qbit[], output func_res: qbit[]) { + allocate(func_res); + inplace_prepare_int<1>(func_res); + modular_exp(func_res, x1); + modular_exp(func_res, x2); +} + +qfunc discrete_log(output x1: qbit[], output x2: qbit[], output func_res: qbit[]) { + allocate(x1); + allocate(x2); + hadamard_transform(x1); + hadamard_transform(x2); + discrete_log_oracle(x1, x2, func_res); + invert { + qft(x1); + } + invert { + qft(x2); + } +} + +qfunc main(output x1: qnum, output x2: qnum, output func_res: qnum) { + discrete_log<3, 2, 5, 4>(x1, x2, func_res); +} diff --git a/algorithms/algebraic/discrete_log/discrete_log.synthesis_options.json b/algorithms/algebraic/discrete_log/discrete_log.synthesis_options.json new file mode 100644 index 00000000..0e8b9f6a --- /dev/null +++ b/algorithms/algebraic/discrete_log/discrete_log.synthesis_options.json @@ -0,0 +1,5 @@ +{ + "constraints": { + "max_width": 13 + } +} diff --git a/algorithms/algebraic/hidden_shift/hidden_shift.ipynb b/algorithms/algebraic/hidden_shift/hidden_shift.ipynb index fa7c2561..473babde 100644 --- a/algorithms/algebraic/hidden_shift/hidden_shift.ipynb +++ b/algorithms/algebraic/hidden_shift/hidden_shift.ipynb @@ -74,7 +74,6 @@ " QBit,\n", " QCallable,\n", " QNum,\n", - " QParam,\n", " allocate,\n", " bind,\n", " create_model,\n", diff --git a/algorithms/algebraic/shor/doubly_controlled_modular_adder.qmod b/algorithms/algebraic/shor/doubly_controlled_modular_adder.qmod index d2c4de07..13fd4c1f 100644 --- a/algorithms/algebraic/shor/doubly_controlled_modular_adder.qmod +++ b/algorithms/algebraic/shor/doubly_controlled_modular_adder.qmod @@ -1,24 +1,24 @@ qfunc phase_lad(phi_b: qbit[]) { - repeat (index: len(phi_b)) { - PHASE(phi_b[index]); + repeat (index: phi_b.len) { + PHASE(phi_b[index]); } } qfunc my_qft_step(qbv: qbit[]) { H(qbv[0]); - repeat (index: len(qbv) - 1) { + repeat (index: qbv.len - 1) { CPHASE(qbv[0], qbv[(index) + 1]); } } qfunc qft_ns(qbv: qbit[]) { - repeat (index: len(qbv)) { - my_qft_step(qbv[index:len(qbv)]); + repeat (index: qbv.len) { + my_qft_step(qbv[index:qbv.len]); } } qfunc ctrl_x(ctrl: qnum, aux: qbit) { - quantum_if (ctrl == ref) { + control (ctrl == ref) { X(aux); } } diff --git a/algorithms/algebraic/shor/shor.ipynb b/algorithms/algebraic/shor/shor.ipynb index ae0af14a..d84c475a 100644 --- a/algorithms/algebraic/shor/shor.ipynb +++ b/algorithms/algebraic/shor/shor.ipynb @@ -96,10 +96,10 @@ "outputs": [], "source": [ "from classiq import (\n", + " CInt,\n", " Output,\n", " QArray,\n", " QBit,\n", - " QParam,\n", " X,\n", " allocate,\n", " control,\n", @@ -140,7 +140,7 @@ "\n", "@qfunc\n", "def modular_exponentiation(\n", - " exponent: QParam[int], target: QArray[QBit, num_auxilliary_qubits]\n", + " exponent: CInt, target: QArray[QBit, num_auxilliary_qubits]\n", ") -> None:\n", " power(2**exponent, lambda: unitary(elements=MODULAR_MUL_UNITARY, target=target))" ] @@ -202,8 +202,8 @@ " repeat(\n", " count=num_auxilliary_qubits,\n", " iteration=lambda index: control(\n", - " operand=lambda: modular_exponentiation(index, qv_auxilliary),\n", " ctrl=qv_counting[index],\n", + " operand=lambda: modular_exponentiation(index, qv_auxilliary),\n", " ),\n", " ) # ! not working with qv[a:]\n", "\n", @@ -470,7 +470,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/algorithms/algebraic/shor/shor_modular_exponentiation.ipynb b/algorithms/algebraic/shor/shor_modular_exponentiation.ipynb index 0390bb6b..012a5173 100644 --- a/algorithms/algebraic/shor/shor_modular_exponentiation.ipynb +++ b/algorithms/algebraic/shor/shor_modular_exponentiation.ipynb @@ -143,12 +143,12 @@ " CPHASE,\n", " CX,\n", " PHASE,\n", + " CInt,\n", " H,\n", " Output,\n", " Preferences,\n", " QArray,\n", " QBit,\n", - " QParam,\n", " X,\n", " allocate,\n", " apply_to_all,\n", @@ -188,7 +188,7 @@ "id": "28304e01-3f61-47a9-bf39-42ce35016ee1", "metadata": {}, "source": [ - "The function `ccmod_add` implements the modular adder which adds the (classical) number $a$ to the b-register modulo $N$ in the QFT space. the function recieves $a$ and $N$ as `QParams` of integers. The un-controlled, controlled and doubly controlled adders in the QFT space are implemented by the function `phase_lad`. The functions which check the msb of the b-register and conditionally flip the auxiliary qubit is `check_msb`. Notice that at this stage, as we don't use SWAP after the QFT, the msb is the first qubit." + "The function `ccmod_add` implements the modular adder which adds the (classical) number $a$ to the b-register modulo $N$ in the QFT space. The function receives $a$ and $N$ as `CInt`s: classical integers parameters. The un-controlled, controlled and doubly controlled adders in the QFT space are implemented by the function `phase_lad`. The functions which check the msb of the b-register and conditionally flip the auxiliary qubit is `check_msb`. Notice that at this stage, as we don't use SWAP after the QFT, the msb is the first qubit." ] }, { @@ -198,13 +198,13 @@ "metadata": {}, "outputs": [], "source": [ - "from classiq.qmod import QNum, bind, quantum_if, within_apply\n", + "from classiq.qmod import QNum, bind, control, within_apply\n", "from classiq.qmod.builtins.classical_functions import qft_const_adder_phase\n", "\n", "\n", "@qfunc\n", "def phase_lad(\n", - " value: QParam[int],\n", + " value: CInt,\n", " phi_b: QArray[QBit],\n", ") -> None:\n", " repeat(\n", @@ -216,19 +216,19 @@ "\n", "\n", "@qfunc\n", - "def ctrl_x(ref: QParam[int], ctrl: QNum, aux: QBit) -> None:\n", - " quantum_if(ctrl == ref, lambda: X(aux))\n", + "def ctrl_x(ref: CInt, ctrl: QNum, aux: QBit) -> None:\n", + " control(ctrl == ref, lambda: X(aux))\n", "\n", "\n", "@qfunc\n", - "def check_msb(ref: QParam[int], x: QArray[QBit], aux: QBit) -> None:\n", + "def check_msb(ref: CInt, x: QArray[QBit], aux: QBit) -> None:\n", " within_apply(lambda: invert(lambda: qft_ns(x)), lambda: ctrl_x(ref, x[0], aux))\n", "\n", "\n", "@qfunc\n", "def ccmod_add(\n", - " N: QParam[int],\n", - " a: QParam[int],\n", + " N: CInt,\n", + " a: CInt,\n", " phi_b: QArray[QBit], # b in fourier basis\n", " c1: QBit,\n", " c2: QBit,\n", @@ -236,12 +236,12 @@ ") -> None:\n", " ctrl = QArray(\"ctrl\")\n", " bind([c1, c2], ctrl)\n", - " control(lambda: phase_lad(a, phi_b), ctrl)\n", + " control(ctrl, lambda: phase_lad(a, phi_b))\n", " invert(lambda: phase_lad(N, phi_b))\n", " check_msb(1, phi_b, aux)\n", - " control(lambda: phase_lad(N, phi_b), aux)\n", + " control(aux, lambda: phase_lad(N, phi_b))\n", " within_apply(\n", - " lambda: invert(lambda: control(lambda: phase_lad(a, phi_b), ctrl)),\n", + " lambda: invert(lambda: control(ctrl, lambda: phase_lad(a, phi_b))),\n", " lambda: check_msb(0, phi_b, aux),\n", " )\n", " bind(ctrl, [c1, c2])" @@ -345,7 +345,7 @@ "id": "20ac31c9-e566-4149-a398-3a843c22538f", "metadata": {}, "source": [ - "We now can execute the synthesized circuit on a simulator (we use the default aer-simulator) and check the outcome. " + "We now can execute the synthesized circuit on a simulator (we use the default simulator) and check the outcome." ] }, { @@ -418,8 +418,8 @@ "source": [ "@qfunc\n", "def cmod_mult(\n", - " N: QParam[int],\n", - " a: QParam[int],\n", + " N: CInt,\n", + " a: CInt,\n", " b: QArray[QBit],\n", " x: QArray[QBit],\n", " ctrl: QBit,\n", @@ -489,8 +489,8 @@ "\n", "@qfunc\n", "def cmod_mult_pair(\n", - " N: QParam[int],\n", - " a: QParam[int],\n", + " N: CInt,\n", + " a: CInt,\n", " x: QArray[QBit],\n", " ctrl: QBit,\n", " aux: QBit,\n", @@ -506,7 +506,7 @@ " ctrl,\n", " aux,\n", " )\n", - " control(lambda: multi_swap(x, b), ctrl)\n", + " control(ctrl, lambda: multi_swap(x, b))\n", " pass\n", " invert(\n", " lambda: cmod_mult(\n", @@ -540,8 +540,8 @@ "source": [ "@qfunc\n", "def mod_exp_func(\n", - " N: QParam[int],\n", - " a: QParam[int],\n", + " N: CInt,\n", + " a: CInt,\n", " x: QArray[QBit],\n", " m: QArray[QBit],\n", " aux: QBit,\n", diff --git a/algorithms/algebraic/shor/shor_modular_exponentiation.qmod b/algorithms/algebraic/shor/shor_modular_exponentiation.qmod index 506cc615..70dc665d 100644 --- a/algorithms/algebraic/shor/shor_modular_exponentiation.qmod +++ b/algorithms/algebraic/shor/shor_modular_exponentiation.qmod @@ -1,24 +1,24 @@ qfunc phase_lad(phi_b: qbit[]) { - repeat (index: len(phi_b)) { - PHASE(phi_b[index]); + repeat (index: phi_b.len) { + PHASE(phi_b[index]); } } qfunc my_qft_step(qbv: qbit[]) { H(qbv[0]); - repeat (index: len(qbv) - 1) { + repeat (index: qbv.len - 1) { CPHASE(qbv[0], qbv[(index) + 1]); } } qfunc qft_ns(qbv: qbit[]) { - repeat (index: len(qbv)) { - my_qft_step(qbv[index:len(qbv)]); + repeat (index: qbv.len) { + my_qft_step(qbv[index:qbv.len]); } } qfunc ctrl_x(ctrl: qnum, aux: qbit) { - quantum_if (ctrl == ref) { + control (ctrl == ref) { X(aux); } } @@ -62,21 +62,21 @@ qfunc cmod_mult(b: qbit[], x: qbit[], ctrl: qbit, aux: qbit) { within { qft(b); } apply { - repeat (index: len(x)) { + repeat (index: x.len) { ccmod_add(b, x[index], ctrl, aux); } } } qfunc multi_swap(x: qbit[], y: qbit[]) { - repeat (index: min(len(x), len(y))) { + repeat (index: min(x.len, y.len)) { SWAP(x[index], y[index]); } } qfunc cmod_mult_pair(x: qbit[], ctrl: qbit, aux: qbit) { b: qbit[]; - allocate(b); + allocate(b); cmod_mult(b, x, ctrl, aux); control (ctrl) { multi_swap(x, b); @@ -88,7 +88,7 @@ qfunc cmod_mult_pair(x: qbit[], ctrl: qbit, aux: qbit) { } qfunc mod_exp_func(x: qbit[], m: qbit[], aux: qbit) { - repeat (index: len(m)) { + repeat (index: m.len) { cmod_mult_pair(x, m[index], aux); } } diff --git a/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.ipynb b/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.ipynb index c2bc1650..6e1c8465 100644 --- a/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.ipynb +++ b/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.ipynb @@ -118,6 +118,7 @@ " allocate,\n", " allocate_num,\n", " bind,\n", + " control,\n", " create_model,\n", " execute,\n", " inplace_prepare_state,\n", @@ -125,7 +126,6 @@ " linear_pauli_rotations,\n", " qfunc,\n", " qpe,\n", - " quantum_if,\n", " set_constraints,\n", " show,\n", " synthesize,\n", @@ -320,7 +320,7 @@ "\n", "The `within_apply` operator takes two function arguments - compute and action, and invokes the sequence compute(), action(), and invert(compute()). Quantum objects that are allocated and prepared by compute are subsequently uncomputed and released.\n", "\n", - "The `quantum_if` operator is a generalized form of the control operator. The control condition is a logical expression over a quantum variable. Currently, expressions are restricted to the form ` == `, where both `` and `` are integer types." + "The `control` condition is a logical expression over a quantum variable. Currently, expressions are restricted to the form ` == `, where both `` and `` are integer types." ] }, { @@ -345,8 +345,7 @@ "\n", "@qfunc\n", "def zero_oracle(x: QNum, ind: QBit):\n", - "\n", - " within_apply(lambda: prepare_minus(ind), lambda: quantum_if(x == 0, lambda: X(ind)))" + " within_apply(lambda: prepare_minus(ind), lambda: control(x == 0, lambda: X(ind)))" ] }, { diff --git a/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.qmod b/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.qmod index bfb12593..a7989c89 100644 --- a/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.qmod +++ b/algorithms/amplitude_estimation/qmc_user_defined/qmc_user_defined.qmod @@ -33,14 +33,14 @@ qfunc zero_oracle(x: qnum, ind: qbit) { within { prepare_minus(ind); } apply { - quantum_if (x == 0) { + control (x == 0) { X(ind); } } } qfunc my_grover_operator(state: qbit[]) { - io: qbit[len(state) - 1]; + io: qbit[state.len - 1]; ind: qbit; state -> {ind, io}; good_state_oracle(ind); diff --git a/algorithms/amplitude_estimation/quantum_counting/quantum_counting.ipynb b/algorithms/amplitude_estimation/quantum_counting/quantum_counting.ipynb index 594a08e4..12f7ab2b 100644 --- a/algorithms/amplitude_estimation/quantum_counting/quantum_counting.ipynb +++ b/algorithms/amplitude_estimation/quantum_counting/quantum_counting.ipynb @@ -179,7 +179,7 @@ "\n", " apply_to_all(X, x)\n", " bind(x, [msbs, lsb])\n", - " control(lambda: Z(lsb), msbs)\n", + " control(msbs, lambda: Z(lsb))\n", " bind([msbs, lsb], x)\n", " apply_to_all(X, x)\n", "\n", @@ -587,12 +587,12 @@ }, "outputs": [], "source": [ - "from classiq import QParam, power\n", + "from classiq import CInt, power\n", "\n", "\n", "@qfunc\n", "def my_iqae_algorithm(\n", - " k: QParam[int],\n", + " k: CInt,\n", " oracle_operand: QCallable[QArray[QBit]],\n", " sp_operand: QCallable[QArray[QBit]],\n", " x: QArray[QBit],\n", @@ -639,7 +639,7 @@ "\n", "@qfunc\n", "def main(\n", - " k: QParam[int],\n", + " k: CInt,\n", " ind_reg: Output[QBit],\n", ") -> None:\n", " full_reg = QArray(\"full_reg\")\n", diff --git a/algorithms/amplitude_estimation/quantum_counting/quantum_counting_iqae.qmod b/algorithms/amplitude_estimation/quantum_counting/quantum_counting_iqae.qmod index e49f38b5..4ddd5911 100644 --- a/algorithms/amplitude_estimation/quantum_counting/quantum_counting_iqae.qmod +++ b/algorithms/amplitude_estimation/quantum_counting/quantum_counting_iqae.qmod @@ -14,7 +14,7 @@ qfunc iqae_state_preparation(a: qnum, b: qnum, res: qbit) { qfunc reflection_about_zero(x: qbit[]) { lsb: qbit; - msbs: qbit[len(x) - 1]; + msbs: qbit[x.len - 1]; apply_to_all(x); x -> {msbs, lsb}; control (msbs) { @@ -51,9 +51,9 @@ qfunc main(output ind_reg: qbit) { full_reg: qbit[]; allocate<5>(full_reg); my_iqae_algorithm(full_reg); state_reg: qbit[4]; full_reg -> {state_reg, ind_reg}; diff --git a/algorithms/amplitude_estimation/quantum_counting/quantum_counting_qpe.qmod b/algorithms/amplitude_estimation/quantum_counting/quantum_counting_qpe.qmod index 373d1418..79df473e 100644 --- a/algorithms/amplitude_estimation/quantum_counting/quantum_counting_qpe.qmod +++ b/algorithms/amplitude_estimation/quantum_counting/quantum_counting_qpe.qmod @@ -15,7 +15,7 @@ qfunc arith_oracle(a: qnum, b: qnum) { qfunc reflection_about_zero(x: qbit[]) { lsb: qbit; - msbs: qbit[len(x) - 1]; + msbs: qbit[x.len - 1]; apply_to_all(x); x -> {msbs, lsb}; control (msbs) { @@ -48,7 +48,7 @@ qfunc main(output phase_reg: qnum) { hadamard_transform(state_reg); qpe(state_reg); diff --git a/algorithms/bernstein_vazirani/bernstein_vazirani.ipynb b/algorithms/bernstein_vazirani/bernstein_vazirani.ipynb index 88f8e363..ca109e07 100644 --- a/algorithms/bernstein_vazirani/bernstein_vazirani.ipynb +++ b/algorithms/bernstein_vazirani/bernstein_vazirani.ipynb @@ -28,7 +28,7 @@ "\n", "Comments:\n", "* This problem is a special case of the [hidden-shift problem](https://github.com/Classiq/classiq-library/blob/main/algorithms/algebraic/hidden_shift/hidden_shift.ipynb), where the goal is to find a secret string satisfing $f(x)=f(x\\oplus a)$, with $\\oplus$ indicating bitwise addition.\n", - "* The problem can be considered as a restricted version of the [Duetsch-Jozsa algorithm](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_josza/deutsch_jozsa.ipynb). In particular, the functional quantum circuit is identical for both problems.\n", + "* The problem can be considered as a restricted version of the [Duetsch-Jozsa algorithm](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb). In particular, the functional quantum circuit is identical for both problems.\n", "\n", "***" ] @@ -94,12 +94,12 @@ "metadata": {}, "outputs": [], "source": [ - "from classiq import CX, IDENTITY, QArray, QBit, QParam, allocate, if_, qfunc, repeat\n", + "from classiq import CX, IDENTITY, CInt, QArray, QBit, allocate, if_, qfunc, repeat\n", "from classiq.qmod.symbolic import floor\n", "\n", "\n", "@qfunc\n", - "def bv_predicate(a: QParam[int], x: QArray, res: QBit):\n", + "def bv_predicate(a: CInt, x: QArray, res: QBit):\n", "\n", " repeat(\n", " x.len,\n", @@ -136,7 +136,7 @@ "source": [ "### Implementing the BV Quantum Function\n", "\n", - "The quantum part of the BV algorithm is essentially identical to the Deutch-Jozsa one, see `deutsch_jozsa` function in [Deutsch-Jozsa notebook](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_josza/deutsch_jozsa.ipynb). However, in contrast to the latter, the predicate function implementation is fixed, depending solely on the secret string $a$. Hereafter we refer to the secret string as a secret integer, defined as an integer argument for the `bv_function`:" + "The quantum part of the BV algorithm is essentially identical to the Deutch-Jozsa one, see `deutsch_jozsa` function in [Deutsch-Jozsa notebook](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb). However, in contrast to the latter, the predicate function implementation is fixed, depending solely on the secret string $a$. Hereafter we refer to the secret string as a secret integer, defined as an integer argument for the `bv_function`:" ] }, { @@ -150,7 +150,7 @@ "\n", "\n", "@qfunc\n", - "def bv_function(a: QParam[int], x: QArray):\n", + "def bv_function(a: CInt, x: QArray):\n", "\n", " aux = QBit(\"aux\")\n", " hadamard_transform(x)\n", diff --git a/algorithms/bernstein_vazirani/bernstein_vazirani_example.qmod b/algorithms/bernstein_vazirani/bernstein_vazirani_example.qmod index c499ea55..bbe61636 100644 --- a/algorithms/bernstein_vazirani/bernstein_vazirani_example.qmod +++ b/algorithms/bernstein_vazirani/bernstein_vazirani_example.qmod @@ -1,5 +1,5 @@ qfunc bv_predicate(x: qbit[], res: qbit) { - repeat (i: len(x)) { + repeat (i: x.len) { if ((floor(a / (2 ** i)) % 2) == 1) { CX(x[i], res); } else { diff --git a/algorithms/grover/3_sat_grover/3_sat_grover.ipynb b/algorithms/grover/3_sat_grover/3_sat_grover.ipynb index 97f863a0..454e6c8c 100644 --- a/algorithms/grover/3_sat_grover/3_sat_grover.ipynb +++ b/algorithms/grover/3_sat_grover/3_sat_grover.ipynb @@ -353,12 +353,14 @@ "from classiq import execute, set_quantum_program_execution_preferences\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", "backend_preferences = ExecutionPreferences(\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " )\n", ")\n", "\n", "qprog = set_quantum_program_execution_preferences(qprog, backend_preferences)\n", diff --git a/algorithms/grover/3_sat_grover_large/3_sat_grover_large.ipynb b/algorithms/grover/3_sat_grover_large/3_sat_grover_large.ipynb index 74408610..a6b4d130 100644 --- a/algorithms/grover/3_sat_grover_large/3_sat_grover_large.ipynb +++ b/algorithms/grover/3_sat_grover_large/3_sat_grover_large.ipynb @@ -265,7 +265,7 @@ "source": [ "## Executing the circuit\n", "\n", - "Lastly, we can execute the resulting circuit with Classiq's execute interface, using the `execute` function. We select the number of iterations we wish to run (in this case - 1), and the execution backend (in this case - the IBM Aer simulator):" + "Lastly, we can execute the resulting circuit with Classiq's execute interface, using the `execute` function. We select the number of iterations we wish to run (in this case - 1), and the execution backend (in this case - Classiq's default simulator):" ] }, { @@ -289,12 +289,14 @@ "from classiq import execute, set_quantum_program_execution_preferences\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", "backend_preferences = ExecutionPreferences(\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " )\n", ")\n", "\n", "qprog = set_quantum_program_execution_preferences(qprog, backend_preferences)\n", diff --git a/algorithms/grover/grover_max_cut/grover_max_cut.ipynb b/algorithms/grover/grover_max_cut/grover_max_cut.ipynb index 9461a76b..973c81d6 100644 --- a/algorithms/grover/grover_max_cut/grover_max_cut.ipynb +++ b/algorithms/grover/grover_max_cut/grover_max_cut.ipynb @@ -430,12 +430,14 @@ "from classiq import execute, set_quantum_program_execution_preferences\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", "backend_preferences = ExecutionPreferences(\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " )\n", ")\n", "\n", "qprog = set_quantum_program_execution_preferences(qprog, backend_preferences)\n", diff --git a/algorithms/hhl/hhl/hhl.ipynb b/algorithms/hhl/hhl/hhl.ipynb index e888e2a5..f9da51eb 100644 --- a/algorithms/hhl/hhl/hhl.ipynb +++ b/algorithms/hhl/hhl/hhl.ipynb @@ -265,12 +265,12 @@ "outputs": [], "source": [ "from classiq import (\n", + " CInt,\n", " Output,\n", " QArray,\n", " QBit,\n", " QCallable,\n", " QNum,\n", - " QParam,\n", " allocate,\n", " allocate_num,\n", " qfunc,\n", @@ -287,8 +287,8 @@ "\n", "@qfunc\n", "def my_matrix_inversion_flexible(\n", - " unitary_with_power: QCallable[QParam[int], QArray[QBit]],\n", - " precision: QParam[int],\n", + " unitary_with_power: QCallable[CInt, QArray[QBit]],\n", + " precision: CInt,\n", " state: QArray[QBit],\n", " indicator: Output[QBit],\n", ") -> None:\n", @@ -401,19 +401,17 @@ }, "outputs": [], "source": [ - "from typing import List\n", - "\n", - "from classiq import suzuki_trotter\n", + "from classiq import CArray, CReal, suzuki_trotter\n", "from classiq.qmod.symbolic import ceiling, log\n", "\n", "\n", "@qfunc\n", "def suzuki_trotter1_with_power_logic(\n", - " hamiltonian: QParam[List[PauliTerm]],\n", - " pw: QParam[int],\n", - " r0: QParam[int],\n", - " reps_scaling_factor: QParam[float],\n", - " evolution_coefficient: QParam[float],\n", + " hamiltonian: CArray[PauliTerm],\n", + " pw: CInt,\n", + " r0: CInt,\n", + " reps_scaling_factor: CReal,\n", + " evolution_coefficient: CReal,\n", " target: QArray[QBit],\n", ") -> None:\n", " suzuki_trotter(\n", @@ -624,11 +622,15 @@ }, "outputs": [], "source": [ - "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n", + "from classiq.execution import (\n", + " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", + " ExecutionPreferences,\n", + ")\n", "from classiq.synthesis import set_execution_preferences\n", "\n", "backend_preferences = ClassiqBackendPreferences(\n", - " backend_name=\"aer_simulator_statevector\"\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR\n", ")\n", "qmod_hhl = create_model(main)\n", "\n", @@ -856,7 +858,7 @@ "\n", "phase_pos = [\n", " total_q - k - 1 for k in range(total_q) if k not in sol_pos + [target_pos]\n", - "] # Finds the position of the \u201cphase\u201d register and flips for endianness, as you will use the indices to read directly from the string" + "] # Finds the position of the “phase” register and flips for endianness, as you will use the indices to read directly from the string" ] }, { @@ -889,7 +891,7 @@ " and parsed_state[\"res\"] == solution\n", " and [parsed_state.bitstring[k] for k in phase_pos]\n", " == [\"0\"]\n", - " * QPE_SIZE # this takes the entries where the \u201cphase\u201d register is at state zero\n", + " * QPE_SIZE # this takes the entries where the “phase” register is at state zero\n", "]" ] }, diff --git a/algorithms/hhl/hhl/hhl.qmod b/algorithms/hhl/hhl/hhl.qmod index bfeb89ee..abf2ed2e 100644 --- a/algorithms/hhl/hhl/hhl.qmod +++ b/algorithms/hhl/hhl/hhl.qmod @@ -4,7 +4,7 @@ qfunc suzuki_trotter1_with_power_logic(indicator); - indicator *= (1 / (2 ** len(phase))) / phase; + indicator *= (1 / (2 ** phase.len)) / phase; } qfunc my_matrix_inversion_flexible(arg1: qbit[]), precision: int>(state: qbit[], output indicator: qbit) { diff --git a/algorithms/qml/qgan/qgan_bars_and_strips.ipynb b/algorithms/qml/qgan/qgan_bars_and_strips.ipynb index e65bd027..44d58c42 100644 --- a/algorithms/qml/qgan/qgan_bars_and_strips.ipynb +++ b/algorithms/qml/qgan/qgan_bars_and_strips.ipynb @@ -4,10 +4,7 @@ "cell_type": "markdown", "id": "9cd05212-388f-4702-a1bd-d4db19afc8fa", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "# Quantum Generative Adversarial Networks (QGANs)\n", @@ -23,10 +20,7 @@ "cell_type": "markdown", "id": "cbc47d04-891a-4ec2-ad39-5b146622fc75", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "## 1 Data Preparation\n", @@ -43,10 +37,7 @@ "end_time": "2024-02-21T14:01:58.670187Z", "start_time": "2024-02-21T14:01:58.613757Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -79,10 +70,7 @@ "end_time": "2024-02-21T14:01:58.685166Z", "start_time": "2024-02-21T14:01:58.676420Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -94,10 +82,7 @@ "cell_type": "markdown", "id": "a8da3493f26da0", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 1.1 Visualizing the generated data \n", @@ -113,10 +98,7 @@ "end_time": "2024-02-28T12:04:38.504739Z", "start_time": "2024-02-28T12:04:38.351180Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -160,10 +142,7 @@ "end_time": "2024-02-28T12:04:38.504739Z", "start_time": "2024-02-28T12:04:38.351180Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -187,10 +166,7 @@ "cell_type": "markdown", "id": "d106636b-b885-4404-862f-f34fdb59756a", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "We create a PyTorch DataLoader to feed the dataset to the GAN model during training." @@ -205,10 +181,7 @@ "end_time": "2024-02-21T14:01:58.844465Z", "start_time": "2024-02-21T14:01:58.842762Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -224,10 +197,7 @@ "cell_type": "markdown", "id": "c702902d-0242-4cbf-9bfa-e12e49c7ae38", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "## 2 Classical network " @@ -237,10 +207,7 @@ "cell_type": "markdown", "id": "942b1203-cf34-4a4b-8a45-51dcbd11c847", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 2.1 Defining a classical GAN\n", @@ -284,10 +251,7 @@ "end_time": "2024-02-21T14:01:58.849345Z", "start_time": "2024-02-21T14:01:58.847144Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -332,10 +296,7 @@ "cell_type": "markdown", "id": "53cf99bc973320d0", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 2.2 Training a classical GAN\n", @@ -352,10 +313,7 @@ "end_time": "2024-02-21T14:01:58.854405Z", "start_time": "2024-02-21T14:01:58.852029Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -477,10 +435,7 @@ "end_time": "2024-02-21T14:01:59.041937Z", "start_time": "2024-02-21T14:01:58.854469Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -527,10 +482,7 @@ "cell_type": "markdown", "id": "5d30d237c39c3d91", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 2.3 Performance evaluation " @@ -545,10 +497,7 @@ "end_time": "2024-02-21T14:01:59.046590Z", "start_time": "2024-02-21T14:01:59.043009Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -601,10 +550,7 @@ "end_time": "2024-02-21T14:01:59.210255Z", "start_time": "2024-02-21T14:01:59.048795Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -640,10 +586,7 @@ "cell_type": "markdown", "id": "66344754c5a37cb7", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "\n", @@ -690,15 +633,15 @@ "source": [ "from typing import List\n", "\n", - "from classiq import IDENTITY, RX, RY, RZ, RZZ, QArray, QParam, if_, qfunc, repeat\n", + "from classiq import IDENTITY, RX, RY, RZ, RZZ, CArray, CReal, QArray, if_, qfunc, repeat\n", "from classiq.applications.qnn.types import SavedResult\n", "from classiq.qmod.symbolic import floor, pi\n", "\n", "\n", "@qfunc\n", - "def datum_angle_encoding(data_in: QParam[List[float]], qbv: QArray) -> None:\n", + "def datum_angle_encoding(data_in: CArray[CReal], qbv: QArray) -> None:\n", "\n", - " def even_case(exe_params: QParam[List[float]], qbv: QArray) -> None:\n", + " def even_case(exe_params: CArray[CReal], qbv: QArray) -> None:\n", " repeat(\n", " count=exe_params.len,\n", " iteration=lambda index: RX(pi * data_in[index], qbv[index]),\n", @@ -708,7 +651,7 @@ " iteration=lambda index: RZ(pi * data_in[index], qbv[index]),\n", " )\n", "\n", - " def odd_case(data_in: QParam[List[float]], qbv: QArray) -> None:\n", + " def odd_case(data_in: CArray[CReal], qbv: QArray) -> None:\n", "\n", " even_case(data_in, qbv)\n", " RX(pi * data_in[data_in.len - 1], target=qbv[data_in.len])\n", @@ -721,7 +664,7 @@ "\n", "\n", "@qfunc\n", - "def my_ansatz(weights: QParam[List[float]], qbv: QArray) -> None:\n", + "def my_ansatz(weights: CArray[CReal], qbv: QArray) -> None:\n", "\n", " repeat(\n", " count=qbv.len,\n", @@ -754,10 +697,7 @@ "cell_type": "markdown", "id": "3411251e74a31939", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "Finally, we define the quantum model with its hyperparameters as our `main` quantum function, and synthesize it into a quantum program." @@ -772,10 +712,7 @@ "end_time": "2024-02-21T14:02:05.014020Z", "start_time": "2024-02-21T14:01:59.219051Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -790,10 +727,10 @@ "import numpy as np\n", "\n", "from classiq import (\n", - " Array,\n", + " CArray,\n", + " CReal,\n", " Output,\n", " QArray,\n", - " QParam,\n", " allocate,\n", " create_model,\n", " qfunc,\n", @@ -814,8 +751,8 @@ "\n", "@qfunc\n", "def main(\n", - " input: QParam[Array[float, QLAYER_SIZE]],\n", - " weight: QParam[Array[float, num_weights]],\n", + " input: CArray[CReal, QLAYER_SIZE],\n", + " weight: CArray[CReal, num_weights],\n", " result: Output[QArray[num_qubits]],\n", ") -> None:\n", "\n", @@ -838,10 +775,7 @@ "cell_type": "markdown", "id": "403a05ded0c7cb89", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "**The resulting circuit is**:" @@ -855,10 +789,7 @@ "end_time": "2024-02-21T14:02:05.016564Z", "start_time": "2024-02-21T14:02:05.011367Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "
\n", @@ -875,10 +806,7 @@ "end_time": "2024-02-21T14:02:05.027039Z", "start_time": "2024-02-21T14:02:05.015883Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "
\n", @@ -895,10 +823,7 @@ "end_time": "2024-02-21T14:02:05.034783Z", "start_time": "2024-02-21T14:02:05.021506Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "
\n", @@ -919,10 +844,7 @@ "cell_type": "markdown", "id": "7a9dd3d2c7fcce2", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "We define the network building blocks: the generator and discriminator in a hybrid network configuration with a quantum layer," @@ -937,10 +859,7 @@ "end_time": "2024-02-21T14:02:07.266266Z", "start_time": "2024-02-21T14:02:05.058392Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -1016,10 +935,7 @@ "end_time": "2024-02-21T14:02:07.266266Z", "start_time": "2024-02-21T14:02:05.058392Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -1030,10 +946,7 @@ "cell_type": "markdown", "id": "a8df1e990a6213e6", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 3.3 Training the QGAN" @@ -1066,10 +979,7 @@ "cell_type": "markdown", "id": "88cb4abd27602131", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "The following cell generates an archive of the training process in the `q_logs` directory. We will also use Tensorboard to monitor the training in real time. It is possible to use an online version which is more convenient, but for the purpose of this notebook we will use the local version. Example of vizualization output that can be obtained from `tensorboard` is shown in the next figure." @@ -1084,10 +994,7 @@ "end_time": "2024-02-21T14:02:07.307279Z", "start_time": "2024-02-21T14:02:07.278688Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -1111,10 +1018,7 @@ "end_time": "2024-02-21T14:02:07.308905Z", "start_time": "2024-02-21T14:02:07.288999Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "
\n", @@ -1142,10 +1046,7 @@ "end_time": "2024-02-21T14:02:07.309344Z", "start_time": "2024-02-21T14:02:07.292707Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [], "source": [ @@ -1177,10 +1078,7 @@ "end_time": "2024-02-21T14:02:07.309344Z", "start_time": "2024-02-21T14:02:07.292707Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -1215,10 +1113,7 @@ "cell_type": "markdown", "id": "423636ec0b58e28", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### 3.3 Performance evaluation " @@ -1241,10 +1136,7 @@ "end_time": "2024-02-21T14:02:09.860719Z", "start_time": "2024-02-21T14:02:07.297626Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -1276,10 +1168,7 @@ "end_time": "2024-02-21T14:02:12.505574Z", "start_time": "2024-02-21T14:02:09.861535Z" }, - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "outputs": [ { @@ -1309,10 +1198,7 @@ "cell_type": "markdown", "id": "c18f8867230ac7d6", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "***\n", diff --git a/algorithms/qml/quantum_autoencoder/quantum_autoencoder.ipynb b/algorithms/qml/quantum_autoencoder/quantum_autoencoder.ipynb index b3dea805..f1f7bc95 100644 --- a/algorithms/qml/quantum_autoencoder/quantum_autoencoder.ipynb +++ b/algorithms/qml/quantum_autoencoder/quantum_autoencoder.ipynb @@ -89,7 +89,7 @@ "2. An encoder block which is some variational quantum ansatz; input port of size $n$ and output ports of size $m$ and $n-m$.\n", "3. A swap test block between the $n-m$ trash output of the encoder and new $n-m$ zero registers.\n", "\n", - "We train the network such that the test qubit of the swap test is at state |0\u27e9 with probability 1.\n", + "We train the network such that the test qubit of the swap test is at state |0⟩ with probability 1.\n", "
\n", "\n", "
Quantum auto encoder layout: uncoded data of size 5 transforms into two outputs, a coded register of size 3 and trash outputs of size 2 at state $|00\\rangle$\n", @@ -126,17 +126,16 @@ }, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from classiq import (\n", " CX,\n", " RY,\n", - " Array,\n", + " CArray,\n", + " CInt,\n", + " CReal,\n", " Input,\n", " Output,\n", " QArray,\n", " QBit,\n", - " QParam,\n", " allocate,\n", " bind,\n", " create_model,\n", @@ -161,9 +160,7 @@ "outputs": [], "source": [ "@qfunc\n", - "def angle_encoding(\n", - " exe_params: QParam[List[float]], qbv: Output[QArray[QBit, \"len(exe_params)\"]]\n", - ") -> None:\n", + "def angle_encoding(exe_params: CArray[CReal], qbv: Output[QArray[QBit]]) -> None:\n", " allocate(exe_params.len, qbv)\n", " repeat(\n", " count=exe_params.len,\n", @@ -187,9 +184,9 @@ "source": [ "@qfunc\n", "def encoder_ansatz(\n", - " num_qubits: QParam[int],\n", - " num_encoding_qubits: QParam[int],\n", - " exe_params: QParam[List[float]],\n", + " num_qubits: CInt,\n", + " num_encoding_qubits: CInt,\n", + " exe_params: CArray[CReal],\n", " x: Input[QArray[QBit, \"num_qubits\"]],\n", " trash: Output[QArray[QBit, \"num_qubits-num_encoding_qubits\"]],\n", " coded: Output[QArray[QBit, \"num_encoding_qubits\"]],\n", @@ -200,7 +197,7 @@ " and a final layer with RY gate on each of the trash qubits is applied.\n", " \"\"\"\n", "\n", - " def single_layer(rep: QParam[int]) -> None:\n", + " def single_layer(rep: CInt) -> None:\n", " repeat(\n", " count=num_qubits,\n", " iteration=lambda index: RY(exe_params[rep * num_qubits + index], x[index]),\n", @@ -338,8 +335,8 @@ "source": [ "@qfunc\n", "def main(\n", - " w: QParam[Array[float, num_weights_in_encoder]],\n", - " input: QParam[Array[float, NUM_QUBITS]],\n", + " w: CArray[CReal, num_weights_in_encoder],\n", + " input: CArray[CReal, NUM_QUBITS],\n", " trash: Output[QArray[QBit, num_trash_qubits]],\n", " coded: Output[QArray[QBit, NUM_ENCODING_QUBITS]],\n", " test: Output[QBit],\n", @@ -755,9 +752,9 @@ "source": [ "@qfunc\n", "def encoder_ansatz_wrapper(\n", - " num_qubits: QParam[int],\n", - " num_encoding_qubits: QParam[int],\n", - " exe_params: QParam[List[float]],\n", + " num_qubits: CInt,\n", + " num_encoding_qubits: CInt,\n", + " exe_params: CArray[CReal],\n", " qbv: QArray[QBit, \"num_qubits\"],\n", ") -> None:\n", " coded = QArray(\"coded\")\n", @@ -800,8 +797,8 @@ "\n", "@qfunc\n", "def main(\n", - " w: QParam[Array[float, num_weights_in_encoder]],\n", - " input: QParam[Array[float, NUM_QUBITS]],\n", + " w: CArray[CReal, num_weights_in_encoder],\n", + " input: CArray[CReal, NUM_QUBITS],\n", " decoded: Output[QArray[QBit, NUM_QUBITS]],\n", " trash: Output[QArray[QBit, num_trash_qubits]],\n", ") -> None:\n", @@ -1144,8 +1141,8 @@ "source": [ "@qfunc\n", "def main(\n", - " w: QParam[Array[float, num_weights_in_encoder]],\n", - " input: QParam[Array[float, NUM_QUBITS]],\n", + " w: CArray[CReal, num_weights_in_encoder],\n", + " input: CArray[CReal, NUM_QUBITS],\n", " trash: Output[QArray[QBit, num_trash_qubits]],\n", ") -> None:\n", " x = QArray(\"x\")\n", diff --git a/algorithms/qpe/qpe_for_matrix/qpe_for_matrix.ipynb b/algorithms/qpe/qpe_for_matrix/qpe_for_matrix.ipynb index 0d8946c7..b3b3959f 100644 --- a/algorithms/qpe/qpe_for_matrix/qpe_for_matrix.ipynb +++ b/algorithms/qpe/qpe_for_matrix/qpe_for_matrix.ipynb @@ -13,7 +13,7 @@ "\n", "By measuring the accumulated phase, the QPE algorithm calculates the eigenvalues relating to the chosen input vector. To read more about the QPE algorithm and its method for achieving the phase, refer to [[1](#NC)].\n", "\n", - "Generally speaking, when the eigenvectors of the matrix are not known in advance yet the eigenvalues are sought, you can choose a random vector ${|v\\rangle}$ for the algorithm\u2019s initial state. Some eigenvalues will be found as the vector can be described in the matrix's basis, defined by the set of eigenvalues of $M$: {$\\psi_i$}. Generally, any vector can be written as a superposition of any basis set, thus\n", + "Generally speaking, when the eigenvectors of the matrix are not known in advance yet the eigenvalues are sought, you can choose a random vector ${|v\\rangle}$ for the algorithm’s initial state. Some eigenvalues will be found as the vector can be described in the matrix's basis, defined by the set of eigenvalues of $M$: {$\\psi_i$}. Generally, any vector can be written as a superposition of any basis set, thus\n", "\n", "${|v\\rangle} = \\sum_i a_i{|\\psi_i\\rangle}$\n", "\n", @@ -449,12 +449,12 @@ "outputs": [], "source": [ "from classiq import (\n", + " CInt,\n", " H,\n", " Output,\n", " QArray,\n", " QBit,\n", " QCallable,\n", - " QParam,\n", " apply_to_all,\n", " bind,\n", " control,\n", @@ -467,8 +467,8 @@ "\n", "@qfunc\n", "def my_qpe_flexible(\n", - " unitary_with_power: QCallable[QParam[int], QArray[QBit]],\n", - " precision: QParam[int],\n", + " unitary_with_power: QCallable[CInt, QArray[QBit]],\n", + " precision: CInt,\n", " state: QArray[QBit],\n", " phase: Output[QArray[QBit, \"precision\"]],\n", ") -> None:\n", @@ -478,8 +478,8 @@ " repeat(\n", " count=precision,\n", " iteration=lambda index: control(\n", - " operand=lambda: unitary_with_power(2**index, state),\n", " ctrl=phase[index],\n", + " operand=lambda: unitary_with_power(2**index, state),\n", " ),\n", " )\n", "\n", @@ -510,17 +510,17 @@ }, "outputs": [], "source": [ - "from classiq import suzuki_trotter\n", + "from classiq import CArray, CReal, suzuki_trotter\n", "from classiq.qmod.symbolic import ceiling, log\n", "\n", "\n", "@qfunc\n", "def suzuki_trotter1_with_power_logic(\n", - " hamiltonian: QParam[List[PauliTerm]],\n", - " pw: QParam[int],\n", - " r0: QParam[int],\n", - " reps_scaling_factor: QParam[float],\n", - " evolution_coefficient: QParam[float],\n", + " hamiltonian: CArray[PauliTerm],\n", + " pw: CInt,\n", + " r0: CInt,\n", + " reps_scaling_factor: CReal,\n", + " evolution_coefficient: CReal,\n", " target: QArray[QBit],\n", ") -> None:\n", " suzuki_trotter(\n", @@ -561,7 +561,7 @@ "\n", "@qfunc\n", "def unitary_with_power_logic(\n", - " pw: QParam[int], matrix: QParam[List[List[float]]], target: QArray[QBit]\n", + " pw: CInt, matrix: CArray[CArray[CReal]], target: QArray[QBit]\n", ") -> None:\n", " power(pw, lambda: unitary(elements=matrix, target=target))" ] diff --git a/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.ipynb b/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.ipynb index 96cff10a..fafdb104 100644 --- a/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.ipynb +++ b/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.ipynb @@ -57,15 +57,15 @@ }, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from classiq import QArray, QBit, QNum, qfunc\n", "from classiq.qmod import (\n", " IDENTITY,\n", " RZ,\n", + " CArray,\n", + " CInt,\n", + " CReal,\n", " H,\n", " QCallable,\n", - " QParam,\n", " X,\n", " allocate,\n", " apply_to_all,\n", @@ -80,10 +80,10 @@ "\n", "@qfunc\n", "def qsvt_step(\n", - " phase_seq: QParam[List[float]],\n", - " index: QParam[int],\n", - " proj_ctrl_phase_1: QCallable[QParam[float], QArray[QBit], QBit],\n", - " proj_ctrl_phase_2: QCallable[QParam[float], QArray[QBit], QBit],\n", + " phase_seq: CArray[CReal],\n", + " index: CInt,\n", + " proj_ctrl_phase_1: QCallable[CReal, QArray[QBit], QBit],\n", + " proj_ctrl_phase_2: QCallable[CReal, QArray[QBit], QBit],\n", " u: QCallable[QArray[QBit]],\n", " qbv_reg: QArray[QBit],\n", " qbv_aux: QBit,\n", @@ -93,7 +93,7 @@ " proj_ctrl_phase_2(phase_seq[2 * index + 1], qbv_reg, qbv_aux)\n", "\n", " if_(\n", - " condition=\"2 * index + 2 == len(phase_seq)\",\n", + " condition=2 * index + 2 == phase_seq.len,\n", " then=lambda: IDENTITY(qbv_reg),\n", " else_=lambda: invert(lambda: u(qbv_reg)),\n", " )\n", @@ -101,9 +101,9 @@ "\n", "@qfunc\n", "def qsvt(\n", - " phase_seq: QParam[List[float]],\n", - " proj_ctrl_phase_1: QCallable[QParam[float], QArray[QBit], QBit],\n", - " proj_ctrl_phase_2: QCallable[QParam[float], QArray[QBit], QBit],\n", + " phase_seq: CArray[CReal],\n", + " proj_ctrl_phase_1: QCallable[CReal, QArray[QBit], QBit],\n", + " proj_ctrl_phase_2: QCallable[CReal, QArray[QBit], QBit],\n", " u: QCallable[QArray[QBit]],\n", " qbv_reg: QArray[QBit],\n", " qbv_aux: QBit,\n", @@ -111,7 +111,7 @@ " H(qbv_aux)\n", "\n", " repeat(\n", - " count=\"len(phase_seq) / 2\",\n", + " count=phase_seq.len / 2,\n", " iteration=lambda index: qsvt_step(\n", " phase_seq, index, proj_ctrl_phase_1, proj_ctrl_phase_2, u, qbv_reg, qbv_aux\n", " ),\n", @@ -142,12 +142,12 @@ }, "outputs": [], "source": [ - "def initial_state_rot(phase: QParam[float], state: QArray[QBit], aux: QBit):\n", + "def initial_state_rot(phase: CReal, state: QArray[QBit], aux: QBit):\n", " hadamard_transform(state)\n", " apply_to_all(X, state)\n", - " control(operand=lambda: X(aux), ctrl=state)\n", + " control(ctrl=state, operand=lambda: X(aux))\n", " RZ(phase, aux)\n", - " control(operand=lambda: X(aux), ctrl=state)\n", + " control(ctrl=state, operand=lambda: X(aux))\n", " apply_to_all(X, state)\n", " hadamard_transform(state)" ] @@ -175,7 +175,7 @@ "outputs": [], "source": [ "def target_state_rot(\n", - " phase: QParam[float],\n", + " phase: CReal,\n", " arith_oracle: QCallable[QArray[QBit], QBit],\n", " state: QArray[QBit],\n", " aux: QBit,\n", @@ -254,7 +254,7 @@ "\n", "@qfunc\n", "def qsvt_fpaa(\n", - " phase_seq: QParam[List[float]],\n", + " phase_seq: CArray[CReal],\n", " arith_oracle: QCallable[QArray[QBit], QBit],\n", " qbv_reg: QArray[QBit],\n", " qbv_aux: Output[QBit],\n", @@ -454,7 +454,7 @@ "id": "e1de3b81-2152-4ecf-9cd4-97be748561f9", "metadata": {}, "source": [ - "We will use classiq's synthesis engine to translate the model to a quantum circuit, and execute on the `aer_simulator`" + "We will use Classiq's synthesis engine to translate the model to a quantum circuit, and execute on Classiq's simulator" ] }, { @@ -479,7 +479,11 @@ " synthesize,\n", " write_qmod,\n", ")\n", - "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n", + "from classiq.execution import (\n", + " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", + " ExecutionPreferences,\n", + ")\n", "\n", "# convert the functions to a qmod model\n", "constraints = Constraints(max_width=12)\n", @@ -489,7 +493,9 @@ "# we will want to execute this qmod on a state-vector simulator:\n", "execution_preferences = ExecutionPreferences(\n", " num_shots=NUM_SHOTS,\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\"),\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " ),\n", ")\n", "qmod = set_execution_preferences(qmod, execution_preferences)\n", "\n", diff --git a/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.qmod b/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.qmod index 9efb73b6..48533aca 100644 --- a/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.qmod +++ b/algorithms/qsvt/qsvt_fixed_point_amplitude_amplification/qsvt_fixed_point_amplitude_amplification.qmod @@ -6,7 +6,7 @@ qfunc qsvt_step(qbv_reg, qbv_aux); u(qbv_reg); proj_ctrl_phase_2(qbv_reg, qbv_aux); - if (((2 * index) + 2) == len(phase_seq)) { + if (((2 * index) + 2) == phase_seq.len) { IDENTITY(qbv_reg); } else { invert { @@ -17,7 +17,7 @@ qfunc qsvt_step(arg1: qbit[], arg2: qbit), proj_ctrl_phase_2: qfunc (arg1: qbit[], arg2: qbit), u: qfunc (arg0: qbit[])>(qbv_reg: qbit[], qbv_aux: qbit) { H(qbv_aux); - repeat (index: len(phase_seq) / 2) { + repeat (index: phase_seq.len / 2) { qsvt_step(qbv_reg, qbv_aux); } H(qbv_aux); diff --git a/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.ipynb b/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.ipynb index 2c2f728f..d9582e40 100644 --- a/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.ipynb +++ b/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.ipynb @@ -276,25 +276,22 @@ "iopub.status.busy": "2024-03-12T12:54:20.697859Z", "iopub.status.idle": "2024-03-12T12:54:23.759670Z", "shell.execute_reply": "2024-03-12T12:54:23.758841Z" - }, - "jupyter": { - "outputs_hidden": false } }, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from classiq.qmod import (\n", " CX,\n", " IDENTITY,\n", " RZ,\n", + " CArray,\n", + " CInt,\n", + " CReal,\n", " H,\n", " Output,\n", " QArray,\n", " QBit,\n", " QCallable,\n", - " QParam,\n", " X,\n", " allocate,\n", " bind,\n", @@ -309,7 +306,7 @@ "\n", "@qfunc\n", "def projector_controlled_phase(\n", - " phase: QParam[float],\n", + " phase: CReal,\n", " proj_cnot: QCallable[QArray[QBit, REG_SIZE], QBit],\n", " qbv_reg: QArray[QBit, REG_SIZE],\n", " qbv_aux: QBit,\n", @@ -321,9 +318,9 @@ "\n", "@qfunc\n", "def qsvt_step(\n", - " phase_seq: QParam[List[float]],\n", - " num_qubits: QParam[int],\n", - " index: QParam[int],\n", + " phase_seq: CArray[CReal],\n", + " num_qubits: CInt,\n", + " index: CInt,\n", " proj_cnot_1: QCallable[QArray[QBit, \"num_qubits\"], QBit],\n", " proj_cnot_2: QCallable[QArray[QBit, \"num_qubits\"], QBit],\n", " u: QCallable[QArray[QBit, \"num_qubits\"]],\n", @@ -344,7 +341,7 @@ " )\n", "\n", " if_(\n", - " condition=\"2 * index + 2 == len(phase_seq)\",\n", + " condition=2 * index + 2 == phase_seq.len,\n", " then=lambda: IDENTITY(qbv_reg),\n", " else_=lambda: invert(lambda: u(qbv_reg)),\n", " )\n", @@ -354,8 +351,8 @@ "\n", "@qfunc\n", "def qsvt(\n", - " num_qubits: QParam[int],\n", - " phase_seq: QParam[List[float]],\n", + " num_qubits: CInt,\n", + " phase_seq: CArray[CReal],\n", " proj_cnot_1: QCallable[QArray[QBit, \"num_qubits\"], QBit],\n", " proj_cnot_2: QCallable[QArray[QBit, \"num_qubits\"], QBit],\n", " u: QCallable[QArray[QBit, \"num_qubits\"]],\n", @@ -367,7 +364,7 @@ " qbv = QArray(\"qbv\")\n", " bind([qbv_reg, qbv_aux], qbv)\n", " repeat(\n", - " count=\"len(phase_seq) / 2\",\n", + " count=phase_seq.len / 2,\n", " iteration=lambda index: qsvt_step(\n", " phase_seq, num_qubits, index, proj_cnot_1, proj_cnot_2, u, qbv\n", " ),\n", @@ -381,10 +378,7 @@ "cell_type": "markdown", "id": "43b71428-1835-4637-a352-b9658f0ca240", "metadata": { - "collapsed": false, - "jupyter": { - "outputs_hidden": false - } + "collapsed": false }, "source": [ "### Matrix inversion logic\n", @@ -408,8 +402,8 @@ "source": [ "@qfunc\n", "def qsvt_inversion(\n", - " num_qubits: QParam[int],\n", - " phase_seq: QParam[List[float]],\n", + " num_qubits: CInt,\n", + " phase_seq: CArray[CReal],\n", " u: QCallable[QArray[QBit, \"num_qubits\"]],\n", " qbv_reg: QArray[QBit, \"num_qubits\"],\n", " qbv_aux: Output[QBit],\n", @@ -665,7 +659,11 @@ "outputs": [], "source": [ "from classiq import create_model, execute, set_execution_preferences, show, synthesize\n", - "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n", + "from classiq.execution import (\n", + " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", + " ExecutionPreferences,\n", + ")\n", "\n", "# convert the functions to a qmod model\n", "qmod = create_model(main)\n", @@ -674,7 +672,7 @@ "execution_preferences = ExecutionPreferences(\n", " num_shots=1,\n", " backend_preferences=ClassiqBackendPreferences(\n", - " backend_name=\"aer_simulator_statevector\"\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR\n", " ),\n", ")\n", "qmod = set_execution_preferences(qmod, execution_preferences)" diff --git a/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.qmod b/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.qmod index 7433acb1..9c62bc2a 100644 --- a/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.qmod +++ b/algorithms/qsvt/qsvt_matrix_inversion/qsvt_matrix_inversion.qmod @@ -11,7 +11,7 @@ qfunc qsvt_step(qbv_reg, qbv_aux); u(qbv_reg); projector_controlled_phase(qbv_reg, qbv_aux); - if (((2 * index) + 2) == len(phase_seq)) { + if (((2 * index) + 2) == phase_seq.len) { IDENTITY(qbv_reg); } else { invert { @@ -25,7 +25,7 @@ qfunc qsvt qbv; - repeat (index: len(phase_seq) / 2) { + repeat (index: phase_seq.len / 2) { qsvt_step(qbv); } qbv -> {qbv_reg, qbv_aux}; diff --git a/algorithms/simon/simon.ipynb b/algorithms/simon/simon.ipynb index 66590a40..eab70b4c 100644 --- a/algorithms/simon/simon.ipynb +++ b/algorithms/simon/simon.ipynb @@ -241,12 +241,12 @@ "metadata": {}, "outputs": [], "source": [ - "from classiq import Output, QNum, QParam, create_model, hadamard_transform, qfunc\n", + "from classiq import CInt, Output, QNum, create_model, hadamard_transform, qfunc\n", "from classiq.qmod.symbolic import min\n", "\n", "\n", "@qfunc\n", - "def simon_qfunc_simple(s: QParam[int], x: QNum, res: Output[QNum]):\n", + "def simon_qfunc_simple(s: CInt, x: QNum, res: Output[QNum]):\n", " res |= min(x, x ^ s)" ] }, @@ -492,7 +492,7 @@ "\n", "@qfunc\n", "def simon_qfunc_with_bipartite_s(\n", - " partition_index: QParam[int], x: QArray[QBit], res: Output[QArray[QBit]]\n", + " partition_index: CInt, x: QArray[QBit], res: Output[QArray[QBit]]\n", "):\n", "\n", " allocate(x.len, res)\n", diff --git a/algorithms/simon/simon_shallow_example.qmod b/algorithms/simon/simon_shallow_example.qmod index 0babb3ef..5611d0be 100644 --- a/algorithms/simon/simon_shallow_example.qmod +++ b/algorithms/simon/simon_shallow_example.qmod @@ -1,11 +1,11 @@ qfunc simon_qfunc_with_bipartite_s(x: qbit[], output res: qbit[]) { - allocate(res); - repeat (i: len(x) - partition_index) { + allocate(res); + repeat (i: x.len - partition_index) { CX(x[i], res[i]); } repeat (i: partition_index - 1) { - CX(x[(((len(x)) - (partition_index)) + 1) + (i)], res[(((len(x)) - (partition_index)) + 1) + (i)]); - CX(x[(len(x)) - (partition_index)], res[(((len(x)) - (partition_index)) + 1) + (i)]); + CX(x[(((x.len) - (partition_index)) + 1) + (i)], res[(((x.len) - (partition_index)) + 1) + (i)]); + CX(x[(x.len) - (partition_index)], res[(((x.len) - (partition_index)) + 1) + (i)]); } } diff --git a/algorithms/swap_test/swap_test.ipynb b/algorithms/swap_test/swap_test.ipynb index 27fd9f0f..bcac1dde 100644 --- a/algorithms/swap_test/swap_test.ipynb +++ b/algorithms/swap_test/swap_test.ipynb @@ -119,7 +119,7 @@ "metadata": {}, "source": [ "## swap test - qmod implementations\n", - "The swap test is defined as a library function in the qmod language (definition can be found on our [public github](https://github.com/Classiq/classiq-library/blob/main/functions/open_library_definitions/swap_test.qmod)).\n", + "The swap test is defined as a library function in the qmod language (definition can be found on our [public github](https://github.com/Classiq/classiq-library/blob/main/functions/open_library_definitions/swap_test.qmod ) ).\n", "Users can easily add their own functions" ] }, @@ -294,7 +294,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/applications/benchmarking/quantum_volume/quantum_volume.ipynb b/applications/benchmarking/quantum_volume/quantum_volume.ipynb index 4565fe2a..86dc2b1d 100644 --- a/applications/benchmarking/quantum_volume/quantum_volume.ipynb +++ b/applications/benchmarking/quantum_volume/quantum_volume.ipynb @@ -17,7 +17,7 @@ "5. For a given output, to get the quantum volume, repeat Items 1-4 for an increasing number of qubits until the inequality described in Item 4 does not hold. To ensure it, the circuits are created many times and the average and standard deviation are taken into account.\n", "6. The quantum volume is 2 to the power of the number of qubits, such that they pass inequality (1) as per the procedure described in Items 1-5.\n", "\n", - "The heavy output probability is a good measurement of the quality of the circuit, as noise reduces the probabilities of uniform distribution. While this is so, consider that there are many components to the results of the procedure\u2014not only the hardware noises, but also the connectivity map, the quality of the transpilation, and even the quantum software that translates the circuit into basis gates for the hardware, thus contributing to the circuit depth.\n", + "The heavy output probability is a good measurement of the quality of the circuit, as noise reduces the probabilities of uniform distribution. While this is so, consider that there are many components to the results of the procedure—not only the hardware noises, but also the connectivity map, the quality of the transpilation, and even the quantum software that translates the circuit into basis gates for the hardware, thus contributing to the circuit depth.\n", "\n", "This demonstration shows the code for implementing the steps to calculate the quantum volume using the Classiq platform and an example of such calculations for several quantum simulators and hardware backends." ] @@ -29,7 +29,7 @@ "source": [ "## Step 1: Create a Haar Random Unitary Matrix\n", "\n", - "Create a function, generating a (n,n) sized Haar random unitary matrix [2]. This matrix contains a random complex number that is distributed evenly in the $2^n$ space of quantum states. The Haar distribution indicates how to weight the elements of $\ud835\udc48(\ud835\udc41)$ such that uniform distribution occurs in the parameter space." + "Create a function, generating a (n,n) sized Haar random unitary matrix [2]. This matrix contains a random complex number that is distributed evenly in the $2^n$ space of quantum states. The Haar distribution indicates how to weight the elements of $𝑈(𝑁)$ such that uniform distribution occurs in the parameter space." ] }, { @@ -91,13 +91,13 @@ "source": [ "import math\n", "import random\n", - "from typing import List\n", "\n", "from classiq.qmod import (\n", + " CArray,\n", + " CReal,\n", " Output,\n", " QArray,\n", " QBit,\n", - " QParam,\n", " allocate,\n", " bind,\n", " create_model,\n", @@ -107,7 +107,7 @@ "\n", "\n", "@qfunc\n", - "def apply_2qbit_unitary(unitary_params: QParam[List[List[float]]], x: QBit, y: QBit):\n", + "def apply_2qbit_unitary(unitary_params: CArray[CArray[CReal]], x: QBit, y: QBit):\n", " joined = QArray[QBit](\"joined\")\n", " bind([x, y], joined)\n", " unitary(unitary_params, joined)\n", @@ -175,7 +175,7 @@ "from classiq.execution import (\n", " AzureBackendPreferences,\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", @@ -337,7 +337,7 @@ "id": "fe220794-001e-4e8f-8a64-970b42148853", "metadata": {}, "source": [ - "### Running with the IBM Simulator" + "### Running with Classiq's Simulator" ] }, { @@ -381,7 +381,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -396,14 +396,14 @@ "output_type": "stream", "text": [ "\r", - " 10%|\u2588 | 1/10 [00:04<00:38, 4.23s/it]" + " 10%|█ | 1/10 [00:04<00:38, 4.23s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -418,14 +418,14 @@ "output_type": "stream", "text": [ "\r", - " 20%|\u2588\u2588 | 2/10 [00:08<00:31, 3.96s/it]" + " 20%|██ | 2/10 [00:08<00:31, 3.96s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -440,14 +440,14 @@ "output_type": "stream", "text": [ "\r", - " 30%|\u2588\u2588\u2588 | 3/10 [00:11<00:26, 3.84s/it]" + " 30%|███ | 3/10 [00:11<00:26, 3.84s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -462,14 +462,14 @@ "output_type": "stream", "text": [ "\r", - " 40%|\u2588\u2588\u2588\u2588 | 4/10 [00:15<00:22, 3.78s/it]" + " 40%|████ | 4/10 [00:15<00:22, 3.78s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -484,14 +484,14 @@ "output_type": "stream", "text": [ "\r", - " 50%|\u2588\u2588\u2588\u2588\u2588 | 5/10 [00:19<00:19, 3.81s/it]" + " 50%|█████ | 5/10 [00:19<00:19, 3.81s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -506,14 +506,14 @@ "output_type": "stream", "text": [ "\r", - " 60%|\u2588\u2588\u2588\u2588\u2588\u2588 | 6/10 [00:22<00:15, 3.78s/it]" + " 60%|██████ | 6/10 [00:22<00:15, 3.78s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -528,14 +528,14 @@ "output_type": "stream", "text": [ "\r", - " 70%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7/10 [00:26<00:11, 3.77s/it]" + " 70%|███████ | 7/10 [00:26<00:11, 3.77s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -550,14 +550,14 @@ "output_type": "stream", "text": [ "\r", - " 80%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 8/10 [00:30<00:07, 3.77s/it]" + " 80%|████████ | 8/10 [00:30<00:07, 3.77s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -572,14 +572,14 @@ "output_type": "stream", "text": [ "\r", - " 90%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 9/10 [00:34<00:03, 3.84s/it]" + " 90%|█████████ | 9/10 [00:34<00:03, 3.84s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -594,14 +594,14 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:38<00:00, 3.87s/it]" + "100%|██████████| 10/10 [00:38<00:00, 3.87s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -609,7 +609,7 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:38<00:00, 3.84s/it]" + "100%|██████████| 10/10 [00:38<00:00, 3.84s/it]" ] }, { @@ -618,7 +618,7 @@ "text": [ "\n", "\r", - " 25%|\u2588\u2588\u258c | 1/4 [00:38<01:55, 38.46s/it]" + " 25%|██▌ | 1/4 [00:38<01:55, 38.46s/it]" ] }, { @@ -647,7 +647,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -662,14 +662,14 @@ "output_type": "stream", "text": [ "\r", - " 10%|\u2588 | 1/10 [00:03<00:34, 3.86s/it]" + " 10%|█ | 1/10 [00:03<00:34, 3.86s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -684,14 +684,14 @@ "output_type": "stream", "text": [ "\r", - " 20%|\u2588\u2588 | 2/10 [00:07<00:31, 3.92s/it]" + " 20%|██ | 2/10 [00:07<00:31, 3.92s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -706,14 +706,14 @@ "output_type": "stream", "text": [ "\r", - " 30%|\u2588\u2588\u2588 | 3/10 [00:12<00:30, 4.39s/it]" + " 30%|███ | 3/10 [00:12<00:30, 4.39s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -728,14 +728,14 @@ "output_type": "stream", "text": [ "\r", - " 40%|\u2588\u2588\u2588\u2588 | 4/10 [00:16<00:24, 4.14s/it]" + " 40%|████ | 4/10 [00:16<00:24, 4.14s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -750,14 +750,14 @@ "output_type": "stream", "text": [ "\r", - " 50%|\u2588\u2588\u2588\u2588\u2588 | 5/10 [00:21<00:21, 4.38s/it]" + " 50%|█████ | 5/10 [00:21<00:21, 4.38s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -772,14 +772,14 @@ "output_type": "stream", "text": [ "\r", - " 60%|\u2588\u2588\u2588\u2588\u2588\u2588 | 6/10 [00:26<00:18, 4.53s/it]" + " 60%|██████ | 6/10 [00:26<00:18, 4.53s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -794,14 +794,14 @@ "output_type": "stream", "text": [ "\r", - " 70%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7/10 [00:30<00:12, 4.32s/it]" + " 70%|███████ | 7/10 [00:30<00:12, 4.32s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -816,14 +816,14 @@ "output_type": "stream", "text": [ "\r", - " 80%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 8/10 [00:33<00:08, 4.15s/it]" + " 80%|████████ | 8/10 [00:33<00:08, 4.15s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -838,14 +838,14 @@ "output_type": "stream", "text": [ "\r", - " 90%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 9/10 [00:37<00:04, 4.05s/it]" + " 90%|█████████ | 9/10 [00:37<00:04, 4.05s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -860,14 +860,14 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:41<00:00, 4.01s/it]" + "100%|██████████| 10/10 [00:41<00:00, 4.01s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -875,7 +875,7 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:41<00:00, 4.16s/it]" + "100%|██████████| 10/10 [00:41<00:00, 4.16s/it]" ] }, { @@ -884,7 +884,7 @@ "text": [ "\n", "\r", - " 50%|\u2588\u2588\u2588\u2588\u2588 | 2/4 [01:20<01:20, 40.31s/it]" + " 50%|█████ | 2/4 [01:20<01:20, 40.31s/it]" ] }, { @@ -913,7 +913,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -928,14 +928,14 @@ "output_type": "stream", "text": [ "\r", - " 10%|\u2588 | 1/10 [00:05<00:45, 5.09s/it]" + " 10%|█ | 1/10 [00:05<00:45, 5.09s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -950,14 +950,14 @@ "output_type": "stream", "text": [ "\r", - " 20%|\u2588\u2588 | 2/10 [00:10<00:44, 5.57s/it]" + " 20%|██ | 2/10 [00:10<00:44, 5.57s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -972,14 +972,14 @@ "output_type": "stream", "text": [ "\r", - " 30%|\u2588\u2588\u2588 | 3/10 [00:15<00:36, 5.27s/it]" + " 30%|███ | 3/10 [00:15<00:36, 5.27s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -994,14 +994,14 @@ "output_type": "stream", "text": [ "\r", - " 40%|\u2588\u2588\u2588\u2588 | 4/10 [00:19<00:28, 4.69s/it]" + " 40%|████ | 4/10 [00:19<00:28, 4.69s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1016,14 +1016,14 @@ "output_type": "stream", "text": [ "\r", - " 50%|\u2588\u2588\u2588\u2588\u2588 | 5/10 [00:25<00:25, 5.12s/it]" + " 50%|█████ | 5/10 [00:25<00:25, 5.12s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1038,14 +1038,14 @@ "output_type": "stream", "text": [ "\r", - " 60%|\u2588\u2588\u2588\u2588\u2588\u2588 | 6/10 [00:29<00:18, 4.68s/it]" + " 60%|██████ | 6/10 [00:29<00:18, 4.68s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1060,14 +1060,14 @@ "output_type": "stream", "text": [ "\r", - " 70%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7/10 [00:33<00:13, 4.47s/it]" + " 70%|███████ | 7/10 [00:33<00:13, 4.47s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1082,14 +1082,14 @@ "output_type": "stream", "text": [ "\r", - " 80%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 8/10 [00:38<00:09, 4.62s/it]" + " 80%|████████ | 8/10 [00:38<00:09, 4.62s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1104,14 +1104,14 @@ "output_type": "stream", "text": [ "\r", - " 90%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 9/10 [00:43<00:04, 4.68s/it]" + " 90%|█████████ | 9/10 [00:43<00:04, 4.68s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1126,14 +1126,14 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:48<00:00, 4.72s/it]" + "100%|██████████| 10/10 [00:48<00:00, 4.72s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1141,7 +1141,7 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:48<00:00, 4.80s/it]" + "100%|██████████| 10/10 [00:48<00:00, 4.80s/it]" ] }, { @@ -1150,7 +1150,7 @@ "text": [ "\n", "\r", - " 75%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258c | 3/4 [02:08<00:43, 43.84s/it]" + " 75%|███████▌ | 3/4 [02:08<00:43, 43.84s/it]" ] }, { @@ -1179,7 +1179,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1194,14 +1194,14 @@ "output_type": "stream", "text": [ "\r", - " 10%|\u2588 | 1/10 [00:05<00:53, 5.94s/it]" + " 10%|█ | 1/10 [00:05<00:53, 5.94s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1216,14 +1216,14 @@ "output_type": "stream", "text": [ "\r", - " 20%|\u2588\u2588 | 2/10 [00:11<00:47, 5.95s/it]" + " 20%|██ | 2/10 [00:11<00:47, 5.95s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1238,14 +1238,14 @@ "output_type": "stream", "text": [ "\r", - " 30%|\u2588\u2588\u2588 | 3/10 [00:17<00:41, 5.97s/it]" + " 30%|███ | 3/10 [00:17<00:41, 5.97s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1260,14 +1260,14 @@ "output_type": "stream", "text": [ "\r", - " 40%|\u2588\u2588\u2588\u2588 | 4/10 [00:22<00:33, 5.57s/it]" + " 40%|████ | 4/10 [00:22<00:33, 5.57s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1282,14 +1282,14 @@ "output_type": "stream", "text": [ "\r", - " 50%|\u2588\u2588\u2588\u2588\u2588 | 5/10 [00:28<00:28, 5.72s/it]" + " 50%|█████ | 5/10 [00:28<00:28, 5.72s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1304,14 +1304,14 @@ "output_type": "stream", "text": [ "\r", - " 60%|\u2588\u2588\u2588\u2588\u2588\u2588 | 6/10 [00:34<00:23, 5.78s/it]" + " 60%|██████ | 6/10 [00:34<00:23, 5.78s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1326,14 +1326,14 @@ "output_type": "stream", "text": [ "\r", - " 70%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 7/10 [00:39<00:16, 5.47s/it]" + " 70%|███████ | 7/10 [00:39<00:16, 5.47s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1348,14 +1348,14 @@ "output_type": "stream", "text": [ "\r", - " 80%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 8/10 [00:46<00:11, 5.92s/it]" + " 80%|████████ | 8/10 [00:46<00:11, 5.92s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1370,14 +1370,14 @@ "output_type": "stream", "text": [ "\r", - " 90%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 | 9/10 [00:51<00:05, 5.63s/it]" + " 90%|█████████ | 9/10 [00:51<00:05, 5.63s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1392,14 +1392,14 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:57<00:00, 5.91s/it]" + "100%|██████████| 10/10 [00:57<00:00, 5.91s/it]" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "\u001b[A" + "\u001B[A" ] }, { @@ -1407,7 +1407,7 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 10/10 [00:57<00:00, 5.80s/it]" + "100%|██████████| 10/10 [00:57<00:00, 5.80s/it]" ] }, { @@ -1416,7 +1416,7 @@ "text": [ "\n", "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 4/4 [03:06<00:00, 49.42s/it]" + "100%|██████████| 4/4 [03:06<00:00, 49.42s/it]" ] }, { @@ -1424,7 +1424,7 @@ "output_type": "stream", "text": [ "\r", - "100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 4/4 [03:06<00:00, 46.52s/it]" + "100%|██████████| 4/4 [03:06<00:00, 46.52s/it]" ] }, { @@ -1446,7 +1446,9 @@ "source": [ "num_trials = 10 # number of times to run the QV circuit for each number of qubits. Best: 200 or more\n", "num_shots = 100 # number of runs for each execution. Best: 1000 or more\n", - "preferences = ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + "preferences = ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + ")\n", "min_qubits = 3\n", "max_qubits = 6\n", "\n", diff --git a/applications/benchmarking/randomized_benchmarking/randomized_benchmarking.ipynb b/applications/benchmarking/randomized_benchmarking/randomized_benchmarking.ipynb index 7d70f0f4..07a1bbc8 100644 --- a/applications/benchmarking/randomized_benchmarking/randomized_benchmarking.ipynb +++ b/applications/benchmarking/randomized_benchmarking/randomized_benchmarking.ipynb @@ -124,7 +124,7 @@ }, "source": [ "## 3) Execution\n", - "When you have the programs you are ready to run. Classiq allows running multiple programs on multiple backends in a single command. You specify the hardware (see details in the [executor user guide](https://docs.classiq.io/latest/user-guide/executor/index.html)). This example runs on IBM Quantum simulators but may be replaced by any hardware with the proper access credentials. For IBM Quantum hardware access, for example, replace `ibmq_access_t` with an API token from [IBMQ's website](https://quantum-computing.ibm.com/) and specify the hardware name in the `backend_name` field of the `BackendPreferences` objects." + "When you have the programs you are ready to run. Classiq allows running multiple programs on multiple backends in a single command. You specify the hardware (see details in the [executor user guide](https://docs.classiq.io/latest/user-guide/platform/executor/index.html ) ). This example runs on IBM Quantum simulators but may be replaced by any hardware with the proper access credentials. For IBM Quantum hardware access, for example, replace `ibmq_access_t` with an API token from [IBMQ's website](https://quantum-computing.ibm.com/) and specify the hardware name in the `backend_name` field of the `BackendPreferences` objects." ] }, { @@ -151,13 +151,16 @@ "from classiq import execute_async, set_quantum_program_execution_preferences\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", "ibmq_access_t = None\n", "\n", - "backend_names = (\"aer_simulator_statevector\", \"aer_simulator\")\n", + "backend_names = (\n", + " ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR,\n", + " ClassiqSimulatorBackendNames.SIMULATOR,\n", + ")\n", "backend_prefs = ClassiqBackendPreferences.batch_preferences(\n", " backend_names=backend_names,\n", ")\n", diff --git a/applications/chemistry/molecular_energy_curve/molecular_energy_curve.qmod b/applications/chemistry/molecular_energy_curve/molecular_energy_curve.qmod index 7bbc5307..de726d7c 100644 --- a/applications/chemistry/molecular_energy_curve/molecular_energy_curve.qmod +++ b/applications/chemistry/molecular_energy_curve/molecular_energy_curve.qmod @@ -1,5 +1,5 @@ qfunc main(output qbv: qbit[]) { - allocate(qbv); + })[0].pauli.len>(qbv); molecule_hartree_fock(output qbv: qbit[]) { - allocate(output qbv: qbit[]) { }, freeze_core = True, remove_orbitals = [] - })[0].pauli)>(qbv); + })[0].pauli.len>(qbv); molecule_hartree_fock(output target: qbit[7]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/chemistry/qpe_for_molecules/qpe_for_molecules.ipynb b/applications/chemistry/qpe_for_molecules/qpe_for_molecules.ipynb index afb6340e..8d5ea033 100644 --- a/applications/chemistry/qpe_for_molecules/qpe_for_molecules.ipynb +++ b/applications/chemistry/qpe_for_molecules/qpe_for_molecules.ipynb @@ -56,7 +56,7 @@ "\n", "e. Executing the circuit to find the related phases and analyzing the results to find the ground state.\n", "\n", - "f. Comparing the QPE results with exact solution for the molecule\u2019s ground state." + "f. Comparing the QPE results with exact solution for the molecule’s ground state." ] }, { @@ -480,12 +480,12 @@ "source": [ "from classiq import molecule_problem_to_qmod\n", "from classiq.qmod import (\n", + " CInt,\n", " Output,\n", " QArray,\n", " QBit,\n", " QCallable,\n", " QNum,\n", - " QParam,\n", " allocate,\n", " allocate_num,\n", " control,\n", @@ -512,7 +512,7 @@ "# power unitary directly\n", "@qfunc\n", "def my_flexible_qpe(\n", - " unitary_with_power: QCallable[QParam[int]],\n", + " unitary_with_power: QCallable[CInt],\n", " phase: QArray[QBit],\n", ") -> None:\n", " apply_to_all(H, phase)\n", @@ -520,8 +520,8 @@ " repeat(\n", " count=phase.len,\n", " iteration=lambda index: control(\n", - " operand=lambda: unitary_with_power(2**index),\n", " ctrl=phase[index],\n", + " operand=lambda: unitary_with_power(2**index),\n", " ),\n", " )\n", " invert(lambda: qft(phase))\n", diff --git a/applications/chemistry/qpe_for_molecules/qpe_for_molecules.qmod b/applications/chemistry/qpe_for_molecules/qpe_for_molecules.qmod index 500cb07f..1ae3e03c 100644 --- a/applications/chemistry/qpe_for_molecules/qpe_for_molecules.qmod +++ b/applications/chemistry/qpe_for_molecules/qpe_for_molecules.qmod @@ -1,6 +1,6 @@ qfunc my_flexible_qpe()>(phase: qbit[]) { apply_to_all(phase); - repeat (index: len(phase)) { + repeat (index: phase.len) { control (phase[index]) { unitary_with_power<2 ** index>(); } diff --git a/applications/chemistry/second_quantized_hamiltonian/second_quantized_hamiltonian.qmod b/applications/chemistry/second_quantized_hamiltonian/second_quantized_hamiltonian.qmod index 6034b7ad..2bf46863 100644 --- a/applications/chemistry/second_quantized_hamiltonian/second_quantized_hamiltonian.qmod +++ b/applications/chemistry/second_quantized_hamiltonian/second_quantized_hamiltonian.qmod @@ -1,5 +1,5 @@ qfunc main(output qbv: qbit[]) { - allocate(output qbv: qbit[]) { } ], num_particles = [1, 1] - })[0].pauli)>(qbv); + })[0].pauli.len>(qbv); full_hea<4, [0, 1, 0], t, [[0, 1], [1, 2], [2, 3]], 3, [lambda(q) { X(q); }, lambda(q) { diff --git a/applications/cybersecurity/link_monitoring/link_monitoring.qmod b/applications/cybersecurity/link_monitoring/link_monitoring.qmod index c96cf6bc..71648cce 100644 --- a/applications/cybersecurity/link_monitoring/link_monitoring.qmod +++ b/applications/cybersecurity/link_monitoring/link_monitoring.qmod @@ -359,8 +359,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[12]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/cybersecurity/patching_management/patch_min_vertex_cover.qmod b/applications/cybersecurity/patching_management/patch_min_vertex_cover.qmod index 5ff598d4..56edad7c 100644 --- a/applications/cybersecurity/patching_management/patch_min_vertex_cover.qmod +++ b/applications/cybersecurity/patching_management/patch_min_vertex_cover.qmod @@ -353,8 +353,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[8]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.ipynb b/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.ipynb index 91209e8c..cecc8fdc 100644 --- a/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.ipynb +++ b/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.ipynb @@ -414,14 +414,14 @@ }, "outputs": [], "source": [ - "from classiq import X, bind, invert, quantum_if\n", + "from classiq import X, bind, control, invert\n", "\n", "\n", "@qfunc\n", "def zero_predicate(x: QNum, y: QNum, res: QBit):\n", " joined = QNum(\"joined\", x.size + y.size, False, 0)\n", " bind([x, y], joined)\n", - " quantum_if(joined == 0, lambda: X(res))\n", + " control(joined == 0, lambda: X(res))\n", " bind(joined, [x, y])\n", "\n", "\n", @@ -685,12 +685,14 @@ "from classiq import execute, set_quantum_program_execution_preferences\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", - " ExecutionDetails,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", ")\n", "\n", "backend_preferences = ExecutionPreferences(\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\"),\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " ),\n", " num_shots=500,\n", ")\n", "\n", @@ -826,7 +828,7 @@ "\n", "[3]: [Grover's algorithm (Wikipedia)](https://en.wikipedia.org/wiki/Grover%27s_algorithm)\n", "\n", - "[4]: [Yoder, Theodore J. et al. \u201cFixed-point quantum search with an optimal number of queries.\u201d Physical review letters 113 21 (2014): 210501](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.113.210501)\n", + "[4]: [Yoder, Theodore J. et al. “Fixed-point quantum search with an optimal number of queries.” Physical review letters 113 21 (2014): 210501](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.113.210501)\n", "\n", "[5]: [Montanaro, Ashley. (2015). Quantum walk speedup of backtracking algorithms. Theory of Computing. 14. 10.4086/toc.2018.v014a015](https://theoryofcomputing.org/articles/v014a015/)\n" ] diff --git a/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.qmod b/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.qmod index 3057e05b..41d4b803 100644 --- a/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.qmod +++ b/applications/cybersecurity/whitebox_fuzzing/whitebox_fuzzing.qmod @@ -23,9 +23,9 @@ qfunc my_oracle() { } qfunc zero_predicate(x: qnum, y: qnum, res: qbit) { - joined: qnum; + joined: qnum; {x, y} -> joined; - quantum_if (joined == 0) { + control (joined == 0) { X(res); } joined -> {x, y}; diff --git a/applications/finance/option_pricing/option_pricing.qmod b/applications/finance/option_pricing/option_pricing.qmod index 763020be..5f5d4504 100644 --- a/applications/finance/option_pricing/option_pricing.qmod +++ b/applications/finance/option_pricing/option_pricing.qmod @@ -1,8 +1,8 @@ qfunc qmci(phase: qnum, packed_vars: qbit[]) { amplitude_estimation(phase, packed_vars); } diff --git a/applications/finance/portfolio_optimization/portfolio_optimization.qmod b/applications/finance/portfolio_optimization/portfolio_optimization.qmod index a9ead2a3..6eeb0a9e 100644 --- a/applications/finance/portfolio_optimization/portfolio_optimization.qmod +++ b/applications/finance/portfolio_optimization/portfolio_optimization.qmod @@ -646,8 +646,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[9]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/logistics/facility_location/facility_location.qmod b/applications/logistics/facility_location/facility_location.qmod index 4cd20f27..859ce521 100644 --- a/applications/logistics/facility_location/facility_location.qmod +++ b/applications/logistics/facility_location/facility_location.qmod @@ -12259,8 +12259,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[12]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/logistics/task_scheduling_problem/task_scheduling_problem.qmod b/applications/logistics/task_scheduling_problem/task_scheduling_problem.qmod index 305be2d3..4d78f789 100644 --- a/applications/logistics/task_scheduling_problem/task_scheduling_problem.qmod +++ b/applications/logistics/task_scheduling_problem/task_scheduling_problem.qmod @@ -156,8 +156,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[6]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/logistics/task_scheduling_problem/task_scheduling_problem_large.qmod b/applications/logistics/task_scheduling_problem/task_scheduling_problem_large.qmod index 54841ea7..5ea73b9f 100644 --- a/applications/logistics/task_scheduling_problem/task_scheduling_problem_large.qmod +++ b/applications/logistics/task_scheduling_problem/task_scheduling_problem_large.qmod @@ -2989,8 +2989,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[24]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/logistics/traveling_salesman_problem/traveling_saleman_problem.qmod b/applications/logistics/traveling_salesman_problem/traveling_saleman_problem.qmod index f33f0854..acd5f27e 100644 --- a/applications/logistics/traveling_salesman_problem/traveling_saleman_problem.qmod +++ b/applications/logistics/traveling_salesman_problem/traveling_saleman_problem.qmod @@ -2123,8 +2123,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[16]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/electric_grid_optimization/electric_grid_optimization.qmod b/applications/optimization/electric_grid_optimization/electric_grid_optimization.qmod index 330c1f8a..99733dd9 100644 --- a/applications/optimization/electric_grid_optimization/electric_grid_optimization.qmod +++ b/applications/optimization/electric_grid_optimization/electric_grid_optimization.qmod @@ -1750,8 +1750,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[18]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/integer_linear_programming/integer_linear_programming.qmod b/applications/optimization/integer_linear_programming/integer_linear_programming.qmod index 4dfe1b30..d2375fde 100644 --- a/applications/optimization/integer_linear_programming/integer_linear_programming.qmod +++ b/applications/optimization/integer_linear_programming/integer_linear_programming.qmod @@ -1058,8 +1058,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[11]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/knapsack_binary/knapsack_binary.qmod b/applications/optimization/knapsack_binary/knapsack_binary.qmod index c450113c..5398f8c2 100644 --- a/applications/optimization/knapsack_binary/knapsack_binary.qmod +++ b/applications/optimization/knapsack_binary/knapsack_binary.qmod @@ -244,8 +244,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[6]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/knapsack_integer/knapsack_integer.qmod b/applications/optimization/knapsack_integer/knapsack_integer.qmod index 59d0a5ab..c01629a8 100644 --- a/applications/optimization/knapsack_integer/knapsack_integer.qmod +++ b/applications/optimization/knapsack_integer/knapsack_integer.qmod @@ -483,8 +483,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[8]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/max_clique/max_clique.qmod b/applications/optimization/max_clique/max_clique.qmod index 3890e859..e6a1e63f 100644 --- a/applications/optimization/max_clique/max_clique.qmod +++ b/applications/optimization/max_clique/max_clique.qmod @@ -734,8 +734,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[7]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/max_cut/max_cut.qmod b/applications/optimization/max_cut/max_cut.qmod index 89c5a88b..46d44f82 100644 --- a/applications/optimization/max_cut/max_cut.qmod +++ b/applications/optimization/max_cut/max_cut.qmod @@ -72,8 +72,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[5]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/max_independent_set/max_independent_set.qmod b/applications/optimization/max_independent_set/max_independent_set.qmod index 7a009d53..f6090016 100644 --- a/applications/optimization/max_independent_set/max_independent_set.qmod +++ b/applications/optimization/max_independent_set/max_independent_set.qmod @@ -288,8 +288,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[8]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/max_induced_k_color_subgraph/max_induced_k_color_subgraph.qmod b/applications/optimization/max_induced_k_color_subgraph/max_induced_k_color_subgraph.qmod index ce72d6a6..96617c8f 100644 --- a/applications/optimization/max_induced_k_color_subgraph/max_induced_k_color_subgraph.qmod +++ b/applications/optimization/max_induced_k_color_subgraph/max_induced_k_color_subgraph.qmod @@ -6700,8 +6700,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[12]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/max_k_vertex_cover/max_k_vertex_cover.qmod b/applications/optimization/max_k_vertex_cover/max_k_vertex_cover.qmod index 783210a1..3fb71683 100644 --- a/applications/optimization/max_k_vertex_cover/max_k_vertex_cover.qmod +++ b/applications/optimization/max_k_vertex_cover/max_k_vertex_cover.qmod @@ -842,8 +842,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[10]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/min_graph_coloring/min_graph_coloring.qmod b/applications/optimization/min_graph_coloring/min_graph_coloring.qmod index ab87effe..b24a700a 100644 --- a/applications/optimization/min_graph_coloring/min_graph_coloring.qmod +++ b/applications/optimization/min_graph_coloring/min_graph_coloring.qmod @@ -7882,8 +7882,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[15]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/minimum_dominating_set/minimum_dominating_set.qmod b/applications/optimization/minimum_dominating_set/minimum_dominating_set.qmod index d8a12881..f3876998 100644 --- a/applications/optimization/minimum_dominating_set/minimum_dominating_set.qmod +++ b/applications/optimization/minimum_dominating_set/minimum_dominating_set.qmod @@ -2702,8 +2702,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[20]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/set_cover/set_cover.qmod b/applications/optimization/set_cover/set_cover.qmod index 3ab53cdb..a04b764f 100644 --- a/applications/optimization/set_cover/set_cover.qmod +++ b/applications/optimization/set_cover/set_cover.qmod @@ -2410,8 +2410,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[23]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/optimization/set_partition/set_partition.qmod b/applications/optimization/set_partition/set_partition.qmod index 895fe0a9..c86e1c9c 100644 --- a/applications/optimization/set_partition/set_partition.qmod +++ b/applications/optimization/set_partition/set_partition.qmod @@ -692,8 +692,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[10]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/applications/physical_systems/ising_model/ising_model.qmod b/applications/physical_systems/ising_model/ising_model.qmod index da724b4b..71eb3cc8 100644 --- a/applications/physical_systems/ising_model/ising_model.qmod +++ b/applications/physical_systems/ising_model/ising_model.qmod @@ -134,8 +134,8 @@ hamiltonian: PauliTerm[] = [ ]; qfunc main(output target: qbit[6]) { - allocate(target); - qaoa_penalty(target); + allocate(target); + qaoa_penalty(target); } cscope ``` diff --git a/built_in_apps/chemistry/chemistry.ipynb b/built_in_apps/chemistry/chemistry.ipynb index fb005939..63db40f1 100644 --- a/built_in_apps/chemistry/chemistry.ipynb +++ b/built_in_apps/chemistry/chemistry.ipynb @@ -11,7 +11,7 @@ "source": [ "# VQE Method for Molecule Energy Solver\n", "\n", - "This notebook demonstrates how to use the `construct_chemistry_model` function, which constructs a VQE model for Molecule eigensolver. For more comprehensive explanation on the algorithm see [Molecule Eigensolver notebook](https://docs.classiq.io/latest/tutorials/applications/chemistry/molecule-eigensolver/molecule-eigensolver/).\n" + "This notebook demonstrates how to use the `construct_chemistry_model` function, which constructs a VQE model for Molecule eigensolver. For more comprehensive explanation on the algorithm see [Molecule Eigensolver notebook](https://github.com/Classiq/classiq-library/blob/main/applications/chemistry/molecule_eigensolver/molecule_eigensolver.ipynb).\n" ] }, { @@ -42,6 +42,7 @@ ")\n", "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", " OptimizerType,\n", ")\n", @@ -59,7 +60,7 @@ "source": [ "## 1. Defining a Molecule and a Molecule Problem\n", "\n", - "First, declare the class Molecule and insert a list of atoms and their spacial positions (distances are in \u00c5 ($10^{-10} m$)). Below we treat the $H_2$ example." + "First, declare the class Molecule and insert a list of atoms and their spacial positions (distances are in Å ($10^{-10} m$)). Below we treat the $H_2$ example." ] }, { @@ -175,7 +176,9 @@ " ),\n", ")\n", "\n", - "backend_preferences = ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + "backend_preferences = ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + ")\n", "\n", "chemistry_model = set_execution_preferences(\n", " chemistry_model,\n", diff --git a/built_in_apps/chemistry/chemistry.qmod b/built_in_apps/chemistry/chemistry.qmod index 414b4164..b56889e2 100644 --- a/built_in_apps/chemistry/chemistry.qmod +++ b/built_in_apps/chemistry/chemistry.qmod @@ -1,5 +1,5 @@ qfunc main(output qbv: qbit[]) { - allocate(qbv); + })[0].pauli.len>(qbv); molecule_hartree_fock(phase: qnum, packed_vars: qbit[]) { amplitude_estimation(phase, packed_vars); } diff --git a/functions/function_declarations/core_lib_decls.qmod b/functions/function_declarations/core_lib_decls.qmod index 54805f30..67c4d8a7 100644 --- a/functions/function_declarations/core_lib_decls.qmod +++ b/functions/function_declarations/core_lib_decls.qmod @@ -1,12 +1,12 @@ // Core library functions -qfunc molecule_ucc(qbv: qbit[len(molecule_problem_to_hamiltonian(molecule_problem)[0].pauli)]); -qfunc molecule_hva(qbv: qbit[len(molecule_problem_to_hamiltonian(molecule_problem)[0].pauli)]); -qfunc molecule_hartree_fock(qbv: qbit[len(molecule_problem_to_hamiltonian(molecule_problem)[0].pauli)]); -qfunc fock_hamiltonian_ucc(qbv: qbit[len(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli)]); -qfunc fock_hamiltonian_hva(qbv: qbit[len(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli)]); -qfunc fock_hamiltonian_hartree_fock(qbv: qbit[len(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli)]); +qfunc molecule_ucc(qbv: qbit[molecule_problem_to_hamiltonian(molecule_problem)[0].pauli.len]); +qfunc molecule_hva(qbv: qbit[molecule_problem_to_hamiltonian(molecule_problem)[0].pauli.len]); +qfunc molecule_hartree_fock(qbv: qbit[molecule_problem_to_hamiltonian(molecule_problem)[0].pauli.len]); +qfunc fock_hamiltonian_ucc(qbv: qbit[fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli.len]); +qfunc fock_hamiltonian_hva(qbv: qbit[fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli.len]); +qfunc fock_hamiltonian_hartree_fock(qbv: qbit[fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0].pauli.len]); qfunc log_normal_finance(func_port: qbit[finance_model.num_qubits], obj_port: qbit); -qfunc gaussian_finance(func_port: qbit[((finance_model.num_qubits + len(finance_model.rhos)) + floor(log(sum(finance_model.loss), 2))) + 1], obj_port: qbit); +qfunc gaussian_finance(func_port: qbit[((finance_model.num_qubits + finance_model.rhos.len) + floor(log(sum(finance_model.loss), 2))) + 1], obj_port: qbit); qfunc pauli_feature_map(qbv: qbit[feature_map.feature_dimension]); qfunc bloch_sphere_feature_map(qbv: qbit[ceiling(feature_dimension / 2)]); qfunc H(target: qbit); @@ -36,10 +36,10 @@ qfunc CRZ(control: qbit, target: qbit); qfunc CPHASE(control: qbit, target: qbit); qfunc SWAP(qbit0: qbit, qbit1: qbit); qfunc IDENTITY(target: qbit[]); -qfunc prepare_state(output out: qbit[log(len(probabilities), 2)]); -qfunc prepare_amplitudes(output out: qbit[log(len(amplitudes), 2)]); -qfunc unitary(target: qbit[log(len(elements[0]), 2)]); -qfunc add(left: qbit[], right: qbit[], output result: qbit[Max(len(left), len(right)) + 1]); +qfunc prepare_state(output out: qbit[log(probabilities.len, 2)]); +qfunc prepare_amplitudes(output out: qbit[log(amplitudes.len, 2)]); +qfunc unitary(target: qbit[log(elements[0].len, 2)]); +qfunc add(left: qbit[], right: qbit[], output result: qbit[Max(left.len, right.len) + 1]); qfunc modular_add(left: qbit[], right: qbit[]); qfunc integer_xor(left: qbit[], right: qbit[]); qfunc U(target: qbit); @@ -47,9 +47,9 @@ qfunc CCX(control: qbit[2], target: qbit); qfunc allocate(output out: qbit[num_qubits]); qfunc free(input in: qbit[]); qfunc randomized_benchmarking(target: qbit[]); -qfunc inplace_prepare_state(target: qbit[log(len(probabilities), 2)]); -qfunc inplace_prepare_amplitudes(target: qbit[log(len(amplitudes), 2)]); -qfunc single_pauli_exponent(qbv: qbit[len(pauli_string)]); -qfunc suzuki_trotter(qbv: qbit[len(pauli_operator[0].pauli)]); -qfunc qdrift(qbv: qbit[len(pauli_operator[0].pauli)]); -qfunc exponentiation_with_depth_constraint(qbv: qbit[len(pauli_operator[0].pauli)]); +qfunc inplace_prepare_state(target: qbit[log(probabilities.len, 2)]); +qfunc inplace_prepare_amplitudes(target: qbit[log(amplitudes.len, 2)]); +qfunc single_pauli_exponent(qbv: qbit[pauli_string.len]); +qfunc suzuki_trotter(qbv: qbit[pauli_operator[0].pauli.len]); +qfunc qdrift(qbv: qbit[pauli_operator[0].pauli.len]); +qfunc exponentiation_with_depth_constraint(qbv: qbit[pauli_operator[0].pauli.len]); diff --git a/functions/function_declarations/open_lib_decls.qmod b/functions/function_declarations/open_lib_decls.qmod index 9cb70768..97a6edf5 100644 --- a/functions/function_declarations/open_lib_decls.qmod +++ b/functions/function_declarations/open_lib_decls.qmod @@ -13,6 +13,15 @@ qfunc grover_operator(packed_vars: qbit[]); qfunc hadamard_transform(target: qbit[]); qfunc apply_to_all(target: qbit[]); +qfunc qft_no_swap(qbv: qbit[]); +qfunc _check_msb(x: qbit[], aux: qbit); +qfunc _ctrl_x(ctrl: qbit, aux: qbit); +qfunc qft_space_add_const(phi_b: qbit[]); +qfunc cc_modular_add(phi_b: qbit[], c1: qbit, c2: qbit, aux: qbit); +qfunc c_modular_multiply(b: qbit[], x: qbit[], ctrl: qbit, aux: qbit); +qfunc multiswap(x: qbit[], y: qbit[]); +qfunc inplace_c_modular_multiply(x: qbit[], ctrl: qbit, aux: qbit); +qfunc modular_exp(x: qbit[], power: qbit[]); qfunc allocate_num(output out: qnum); qfunc qaoa_mixer_layer(target: qbit[]); qfunc qaoa_cost_layer(target: qbit[]); diff --git a/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.ipynb b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.ipynb new file mode 100644 index 00000000..48a09797 --- /dev/null +++ b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "82b4c2f7-3bb7-45ed-ad51-22640ef86236", + "metadata": {}, + "source": [ + "# Amplitude Loading\n", + "\n", + "The amplitude loading function performs the following operation:\n", + "\n", + "$|d\\rangle |0\\rangle \\rightarrow \\sqrt{1-f^2(d)}|d\\rangle |0\\rangle +\n", + "f(d)|d\\rangle |1\\rangle$\n", + "\n", + "for any input, $|d\\rangle$, and function $f(d)$.\n", + "\n", + "The function $f(d)$ is expected to be real and include only a single variable.\n", + "Its domain is [0, 1] and its range is contained in [-1, 1].\n", + "For multi-argument or complex functions, an exception is raised.\n", + "If, for some input, the function value exceeds the [-1, 1] range,\n", + "the value is trimmed accordingly.\n", + "\n", + "The function is implemented using repeated multiple controlled RY rotations\n", + "where $|d\\rangle$ is the control register and $|0\\rangle$ is the target qubit.\n", + "\n", + "Poles of the expression are automatically ignored (set to 0). For example, for the `1/x` function,\n", + "the zero input state is ignored, as it is undefined.\n", + "\n", + "The function is invoked using the `*=` expression, where the left side is the indicator qubit, and the right side is an expression of the input quantum state." + ] + }, + { + "cell_type": "markdown", + "id": "ff1f8538-2ac0-40f0-9d72-832bad60646d", + "metadata": {}, + "source": [ + "# Example\n", + "\n", + "The following code loads the function $x^2$ into the amplitude of a quantum state, using $|x\\rangle$ of size 4 and a single indicator qubit." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "110fe261-2023-4739-b7d0-7ee569ba7f6b", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " allocate_num,\n", + " create_model,\n", + " qfunc,\n", + ")\n", + "\n", + "VAR_SIZE = 4\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QNum], ind: Output[QNum]) -> None:\n", + " allocate_num(VAR_SIZE, False, VAR_SIZE, x)\n", + " allocate(1, ind)\n", + "\n", + " ind *= x**2\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "aaffdc84-c24d-4329-9499-7656aed196f7", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"amplitude_loading_example\")\n", + "qprog = synthesize(qmod)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.json b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.json new file mode 100644 index 00000000..bfc7bab5 --- /dev/null +++ b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Amplitude Loading", + "description": "Amplitude Loading", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.qmod b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.qmod new file mode 100644 index 00000000..14436982 --- /dev/null +++ b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output x: qnum, output ind: qnum) { + allocate_num<4, False, 4>(x); + allocate<1>(ind); + ind *= x ** 2; +} diff --git a/functions/function_usage_examples/qft/qft_usage_example.synthesis_options.json b/functions/function_usage_examples/amplitude_loading/amplitude_loading_example.synthesis_options.json similarity index 100% rename from functions/function_usage_examples/qft/qft_usage_example.synthesis_options.json rename to functions/function_usage_examples/amplitude_loading/amplitude_loading_example.synthesis_options.json diff --git a/functions/function_usage_examples/arithmetic/addition.json b/functions/function_usage_examples/arithmetic/addition.json deleted file mode 100644 index 08784ec5..00000000 --- a/functions/function_usage_examples/arithmetic/addition.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Addition", - "description": "Addition", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/addition.qmod b/functions/function_usage_examples/arithmetic/addition.qmod deleted file mode 100644 index 2c830ae4..00000000 --- a/functions/function_usage_examples/arithmetic/addition.qmod +++ /dev/null @@ -1,17 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Adder", - "function_params": { - "left_arg": 3.5, - "right_arg": { "size": 3 }, - "inplace_arg": null - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/addition_two_regs.json b/functions/function_usage_examples/arithmetic/addition_two_regs.json deleted file mode 100644 index b4e790da..00000000 --- a/functions/function_usage_examples/arithmetic/addition_two_regs.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Two-Register Addition", - "description": "Two-Register Addition", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/addition_two_regs.qmod b/functions/function_usage_examples/arithmetic/addition_two_regs.qmod deleted file mode 100644 index 823d1eaf..00000000 --- a/functions/function_usage_examples/arithmetic/addition_two_regs.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Adder", - "function_params": { - "left_arg": {"size": 3}, - "right_arg": {"size": 3} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression.json b/functions/function_usage_examples/arithmetic/arithmetic_expression.json deleted file mode 100644 index 1896928d..00000000 --- a/functions/function_usage_examples/arithmetic/arithmetic_expression.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Arithmetic Expression Example", - "description": "Arithmetic Expression Example", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression.qmod b/functions/function_usage_examples/arithmetic/arithmetic_expression.qmod deleted file mode 100644 index 41723843..00000000 --- a/functions/function_usage_examples/arithmetic/arithmetic_expression.qmod +++ /dev/null @@ -1,28 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Arithmetic", - "function_params": { - "expression": "a ^ 3 + b + (2 - c % 4) - max(a, b, -c)", - "definitions": { - "a": { - "size": 2 - }, - "b": { - "size": 1 - }, - "c": { - "size": 3 - } - }, - "uncomputation_method": "optimized", - "qubit_count": 25 - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.ipynb b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.ipynb new file mode 100644 index 00000000..de8a0317 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "34cae875-0dd8-46e8-af7e-b346a7067711", + "metadata": {}, + "source": [ + "# Arithmetic Expressions\n", + "\n", + "Use the `Arithmetic` function to write complex mathematical expression in free format.\n", + "The notation follows the Python language for math notation.\n", + "\n", + "The function first parses the expression and builds an abstract syntax tree (AST). Then, the Classiq engine finds a\n", + "computation strategy for a specified number of qubits, and compiles the desired quantum program.\n", + "\n", + "As opposed to classical computers, when quantum computers evaluate arithmetic\n", + "expression, the calculations are reversible and are applied on all quantum states in parallel.\n", + "To do so, quantum computers store all intermediate computation results in a quantum variables.\n", + "Qubits that are not freed cannot be used later on in the quantum program.\n", + "\n", + "Analogously to the classical world, there is a form of quantum \"garbage collection\",\n", + "usually referred to as uncomputation, which returns the garbage qubits to their original state.\n", + "The computation strategy determines the order in which qubits are released and reused.\n", + "By employing different strategies, you can produce a variety of quantum programs with the same functionality.\n", + "In general, longer quantum programs require less qubits than shorter ones.\n", + "\n", + "Supported operators:\n", + "\n", + "- Add: `+`\n", + "- Subtract: `-` (two arguments)\n", + "- Negate: `-` (a single argument)\n", + "- Multiply: `*`\n", + "- Bitwise Or: `|`\n", + "- Bitwise And: `&`\n", + "- Bitwise Xor: `^`\n", + "- Invert: `~`\n", + "- Equal: `==`\n", + "- Not Equal: `!=`\n", + "- Greater Than: `>`\n", + "- Greater Or Equal: `>=`\n", + "- Less Than: `<`\n", + "- Less Or Equal: `<=`\n", + "- Modulo: `%` limited for power of 2\n", + "- Logical And: `and`\n", + "- Logical Or: `or`\n", + "- Max: `max` (n>=2 arguments)\n", + "- Min: `min` (n>=2 arguments)\n", + "- Power `**` (register base, positive int power)" + ] + }, + { + "cell_type": "markdown", + "id": "721738fb-4975-4a39-9b50-1531535b2c75", + "metadata": {}, + "source": [ + "## Example\n", + "\n", + "This example generates a quantum program that calculates the expression `(a + b + c & 15) % 8 ^ 3 & a ^ 10 == 4`.\n", + "Each of the variables `a`,`b`, and `c` is defined as a quantum varialbe with a different size." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "0bddc7b7-afe0-4fcc-a4f6-d5636c9df559", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], c: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(2, a)\n", + " prepare_int(1, b)\n", + " prepare_int(5, c)\n", + "\n", + " res |= (a + b + c & 15) % 8 ^ 3 & a ^ 10 == 4\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "531a28d1-e5c3-467e-9abf-0692d2d5c5cd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 2.0, 'b': 1.0, 'c': 5.0, 'res': 0.0}: 1000]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"arithmetic_expression_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.json b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.json new file mode 100644 index 00000000..aad04ee8 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Arithmetic Expression", + "description": "Arithmetic Expression", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.qmod b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.qmod new file mode 100644 index 00000000..ebc41669 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.qmod @@ -0,0 +1,6 @@ +qfunc main(output a: qnum, output b: qnum, output c: qnum, output res: qnum) { + prepare_int<2>(a); + prepare_int<1>(b); + prepare_int<5>(c); + res = ((((((a + b) + c) & 15) % 8) ^ (3 & (a >> 2))) ^ 10) == 4; +} diff --git a/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/arithmetic_expression/arithmetic_expression_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and.json b/functions/function_usage_examples/arithmetic/bitwise_and.json deleted file mode 100644 index 4de1a2fe..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_and.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise And", - "description": "Bitwise And", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and.qmod b/functions/function_usage_examples/arithmetic/bitwise_and.qmod deleted file mode 100644 index 2cfe8e82..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_and.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseAnd", - "function_params": { - "left_arg": 3, - "right_arg": { "size": 3 } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.json b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.json new file mode 100644 index 00000000..7e69d3d6 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Bitwise And", + "description": "Quantum Variables Bitwise And", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.qmod new file mode 100644 index 00000000..2ec27de6 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + prepare_int<4>(a); + prepare_int<5>(b); + res = a & b; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_example.ipynb b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_example.ipynb new file mode 100644 index 00000000..65ccb523 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_example.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "deb4a99c-3de0-441d-9fcd-d9f373c1e06d", + "metadata": {}, + "source": [ + "# Bitwise And\n", + "\n", + "The Bitwise And (denoted as '&') is implemented by applying this truth table between each pair of qubits in register A and B (or qubit and bit).\n", + "\n", + "
\n", + "\n", + "| a | b | a & b |\n", + "| :-: | :-: | :---: |\n", + "| 0 | 0 | 0 |\n", + "| 0 | 1 | 0 |\n", + "| 1 | 0 | 0 |\n", + "| 1 | 1 | 1 |\n", + "\n", + "
\n", + "\n", + "Note that integer and fixed-point numbers are represented in a two-complement method during function evaluation.\n", + "The binary number is extended in the case of a register size mismatch.\n", + "\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when operating with a five-qubit register.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "Examples:\n", + "\n", + "5 & 3 = 1 since 101 & 011 = 001\n", + "\n", + "5 & -3 = 5 since 0101 & 1101 = 0101\n", + "\n", + "-5 & -3 = -7 since 1011 & 1101 = 1001" + ] + }, + { + "cell_type": "markdown", + "id": "c39533b4-a023-4d35-bbb8-9f2fb49be987", + "metadata": {}, + "source": [ + "# Examples\n", + "\n", + "#### Example 1: Two Quantum Variables\n", + "\n", + "This example generates a quantum program that performs a bitwise 'and' between two variables, both are unsigned integer" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "32c35c64-07d7-4244-a2b1-436c983289aa", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " prepare_int(5, b)\n", + " res |= a & b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "0eb01ba2-361a-4407-9373-960c6b28c531", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 4.0, 'b': 5.0, 'res': 4.0}: 1000]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_and_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + }, + { + "cell_type": "markdown", + "id": "f3e6b1f8-b444-4ec5-af53-16a6e3c46c52", + "metadata": {}, + "source": [ + "#### Example 2: Integer and Quantum Variable\n", + "\n", + "This example generates a quantum program that performs a bitwise 'and' between a quantum variable and an integer.\n", + "The left arg is an integer equal to 3\n", + "and the right arg is an unsigned quantum variable with three qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "3c8565b2-eaf1-4315-b748-e128c9f613b8", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(5, a)\n", + " res |= 3 & a\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "c9ac0055-0f2a-4a6e-9390-632fd241f28d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 5.0, 'res': 1.0}: 1000]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_and_integer_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.json b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.json new file mode 100644 index 00000000..543c80cd --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Integer Bitwise And", + "description": "Quantum Variable and Integer Bitwise And", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.qmod new file mode 100644 index 00000000..949476fb --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output a: qnum, output res: qnum) { + prepare_int<5>(a); + res = 3 & a; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_and/bitwise_and_integer_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.json b/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.json deleted file mode 100644 index 9fe69a53..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise And - Two Registers", - "description": "Bitwise And - Two Registers", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.qmod b/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.qmod deleted file mode 100644 index 32eb5b57..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_and_two_regs.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseAnd", - "function_params": { - "left_arg": {"size": 5, "is_signed":true}, - "right_arg": {"size": 3} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_invert.qmod b/functions/function_usage_examples/arithmetic/bitwise_invert.qmod deleted file mode 100644 index da99a44a..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_invert.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseInvert", - "function_params": { - "arg": {"size": 7, "fraction_places": 3, "is_signed": true}, - "inplace": true - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.ipynb b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.ipynb new file mode 100644 index 00000000..9cae4cd8 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.ipynb @@ -0,0 +1,88 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "eb92b0dd-3c28-4ff5-b636-9c204c446005", + "metadata": {}, + "source": [ + "# Bitwise Invert\n", + "\n", + "The bitwise inversion operation receives a quantum register representing some number $x$,\n", + "and inverts its binary representation, namely, replaces $1$s by $0$s and vice versa." + ] + }, + { + "cell_type": "markdown", + "id": "5eba81d0-4776-43cc-b503-3b2bba07c24f", + "metadata": {}, + "source": [ + "# Example" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "4fd85f09-fb85-4f00-8938-be3854c6c49c", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QNum], y: Output[QNum]) -> None:\n", + " prepare_int(6, x)\n", + "\n", + " y |= ~x\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "002c8028-c157-468a-8c2e-cefa10c4c0d4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{('011', '100'): 1000}\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_invert_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.counts_of_multiple_outputs([\"x\", \"y\"]))" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_invert.json b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.json similarity index 67% rename from functions/function_usage_examples/arithmetic/bitwise_invert.json rename to functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.json index f4501623..f20f3d2c 100644 --- a/functions/function_usage_examples/arithmetic/bitwise_invert.json +++ b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.json @@ -1,7 +1,6 @@ { "friendly_name": "Bitwise Invert", "description": "Bitwise Invert", - "problem_domain_tags": [], "qmod_type": ["function"], - "level": ["demos"] + "level": ["demos", "basic"] } diff --git a/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.qmod new file mode 100644 index 00000000..686115c7 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output x: qnum, output y: qnum) { + prepare_int<6>(x); + y = ~x; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_invert/bitwise_invert_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or.json b/functions/function_usage_examples/arithmetic/bitwise_or.json deleted file mode 100644 index f72aa3bf..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_or.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise Or", - "description": "Bitwise Or", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or.qmod b/functions/function_usage_examples/arithmetic/bitwise_or.qmod deleted file mode 100644 index f5e55049..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_or.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseOr", - "function_params": { - "left_arg": 3, - "right_arg": { "size": 3 } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.json b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.json new file mode 100644 index 00000000..1b203b95 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Bitwise Or", + "description": "Quantum Variables Bitwise Or", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.qmod new file mode 100644 index 00000000..50f4596f --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.qmod @@ -0,0 +1,7 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + allocate_num<5, True, 0>(a); + allocate_num<3, False, 0>(b); + inplace_prepare_int<4>(a); + inplace_prepare_int<5>(b); + res = a | b; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_example.ipynb b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_example.ipynb new file mode 100644 index 00000000..0ab52ea6 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_example.ipynb @@ -0,0 +1,188 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "deb4a99c-3de0-441d-9fcd-d9f373c1e06d", + "metadata": {}, + "source": [ + "# Bitwise Or\n", + "\n", + "The Bitwise Or (denoted as '|') is implemented by applying the following truth table between each pair of qubits (or qubit and bit) in variables A and B.\n", + "\n", + "
\n", + "\n", + "| a | b | a or b |\n", + "| :-: | :-: | :----: |\n", + "| 0 | 0 | 0 |\n", + "| 0 | 1 | 1 |\n", + "| 1 | 0 | 1 |\n", + "| 1 | 1 | 1 |\n", + "\n", + "
\n", + "\n", + "Note that integer and fixed-point numbers are represented in a two-complement method during function evaluation.\n", + "The binary number is extended in the case of a variable size mismatch.\n", + "\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when operating with a five-qubit variable.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "Examples:\n", + "\n", + "5 | 3 = 7 since 101 | 011 = 111\n", + "\n", + "5 | -3 = -3 since 0101 | 1101 = 1101\n", + "\n", + "-5 | -3 = -1 since 1011 | 1101 = 1111" + ] + }, + { + "cell_type": "markdown", + "id": "c39533b4-a023-4d35-bbb8-9f2fb49be987", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Two Quantum Variables\n", + "\n", + "This example generates a quantum program that performs bitwise 'or' between two variables.\n", + "The left arg is a signed with five qubits and the right arg is unsigned with three qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "32c35c64-07d7-4244-a2b1-436c983289aa", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate_num,\n", + " create_model,\n", + " inplace_prepare_int,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate_num(5, True, 0, a)\n", + " allocate_num(3, False, 0, b)\n", + " inplace_prepare_int(4, a)\n", + " inplace_prepare_int(5, b)\n", + " res |= a | b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "0eb01ba2-361a-4407-9373-960c6b28c531", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'a': 4.0, 'b': 5.0, 'res': 5.0}: 1000]\n", + "{('00100', '101', '10100'): 1000}\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_or_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.parsed_counts)\n", + "print(result.counts_of_multiple_outputs([\"a\", \"b\", \"res\"]))" + ] + }, + { + "cell_type": "markdown", + "id": "f3e6b1f8-b444-4ec5-af53-16a6e3c46c52", + "metadata": {}, + "source": [ + "#### Example 2: Integer and Quantum Variable\n", + "\n", + "This example generates a quantum program that performs a bitwise 'or' between a quantum variable and an integer.\n", + "The left arg is an integer equal to three\n", + "and the right arg is an unsigned quantum variable with three qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "3c8565b2-eaf1-4315-b748-e128c9f613b8", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " res |= 3 | a\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "c9ac0055-0f2a-4a6e-9390-632fd241f28d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 4.0, 'res': 7.0}: 1000]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_or_integer_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.json b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.json new file mode 100644 index 00000000..66347dc6 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Integer Bitwise Or", + "description": "Quantum Variable and Integer Bitwise Or", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.qmod new file mode 100644 index 00000000..a44210b6 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output a: qnum, output res: qnum) { + prepare_int<4>(a); + res = 3 | a; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_or/bitwise_or_integer_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.json b/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.json deleted file mode 100644 index 2dbde57c..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise Or - Two Registers", - "description": "Bitwise Or - Two Registers", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.qmod b/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.qmod deleted file mode 100644 index 7c804ddf..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_or_two_regs.qmod +++ /dev/null @@ -1,21 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseOr", - "function_params": { - "left_arg": { - "size": 5, - "is_signed": true - }, - "right_arg": { - "size": 3 - } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor.json b/functions/function_usage_examples/arithmetic/bitwise_xor.json deleted file mode 100644 index cfbeafbf..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_xor.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise Xor", - "description": "Bitwise Xor", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor.qmod b/functions/function_usage_examples/arithmetic/bitwise_xor.qmod deleted file mode 100644 index 042a2cfc..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_xor.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseXor", - "function_params": { - "left_arg": 3, - "right_arg": { "size": 3 } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.json b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.json new file mode 100644 index 00000000..a5f6924f --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Bitwise Xor", + "description": "Quantum Variables Bitwise Xor", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.qmod new file mode 100644 index 00000000..ea59cac4 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.qmod @@ -0,0 +1,7 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + allocate_num<5, True, 0>(a); + allocate_num<3, False, 0>(b); + inplace_prepare_int<4>(a); + inplace_prepare_int<5>(b); + res = a ^ b; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_example.ipynb b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_example.ipynb new file mode 100644 index 00000000..c8aec20f --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_example.ipynb @@ -0,0 +1,188 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "deb4a99c-3de0-441d-9fcd-d9f373c1e06d", + "metadata": {}, + "source": [ + "# Bitwise Xor\n", + "\n", + "The Bitwise Xor (denoted as '^') is implemented by applying this truth table between each pair of qubits (or qubit and bit) in variables A and B.\n", + "\n", + "
\n", + "\n", + "| a | b | a ^ b |\n", + "| :-: | :-: | :---: |\n", + "| 0 | 0 | 0 |\n", + "| 0 | 1 | 1 |\n", + "| 1 | 0 | 1 |\n", + "| 1 | 1 | 0 |\n", + "\n", + "
\n", + "\n", + "Note that integer and fixed-point numbers are represented in a two-complement method during function evaluation.\n", + "The binary number is extended in the case of a variable size mismatch.\n", + "\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when operating with a five-qubit variable.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "Examples:\n", + "\n", + "5 ^ 3 = 6 since 101 ^ 011 = 110\n", + "\n", + "5 ^ -3 = -8 since 0101 ^ 1101 = 1000\n", + "\n", + "-5 ^ -3 = 6 since 1011 ^ 1101 = 0110" + ] + }, + { + "cell_type": "markdown", + "id": "c39533b4-a023-4d35-bbb8-9f2fb49be987", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Two Quantum Variables\n", + "\n", + "This example generates a quantum program that performs bitwise 'xor' between two variables.\n", + "The left arg is a signed with five qubits and the right arg is unsigned with three qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "32c35c64-07d7-4244-a2b1-436c983289aa", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate_num,\n", + " create_model,\n", + " inplace_prepare_int,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate_num(5, True, 0, a)\n", + " allocate_num(3, False, 0, b)\n", + " inplace_prepare_int(4, a)\n", + " inplace_prepare_int(5, b)\n", + " res |= a ^ b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0eb01ba2-361a-4407-9373-960c6b28c531", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'a': 4.0, 'b': 5.0, 'res': 1.0}: 1000]\n", + "{('00100', '101', '10000'): 1000}\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_xor_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.parsed_counts)\n", + "print(result.counts_of_multiple_outputs([\"a\", \"b\", \"res\"]))" + ] + }, + { + "cell_type": "markdown", + "id": "f3e6b1f8-b444-4ec5-af53-16a6e3c46c52", + "metadata": {}, + "source": [ + "#### Example 2: Integer and Quantum Variable\n", + "\n", + "This example generates a quantum program that performs a bitwise 'xor' between a quantum variable and an integer.\n", + "The left arg is an integer equal to three\n", + "and the right arg is an unsigned quantum variable with three qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3c8565b2-eaf1-4315-b748-e128c9f613b8", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " res |= 3 ^ a\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c9ac0055-0f2a-4a6e-9390-632fd241f28d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 4.0, 'res': 7.0}: 1000]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"bitwise_xor_integer_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.json b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.json new file mode 100644 index 00000000..b04e95ab --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Integer Bitwise Xor", + "description": "Quantum Variable and Integer Bitwise Xor", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.qmod b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.qmod new file mode 100644 index 00000000..1d529a33 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output a: qnum, output res: qnum) { + prepare_int<4>(a); + res = 3 ^ a; +} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/bitwise_xor/bitwise_xor_integer_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.json b/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.json deleted file mode 100644 index 052701e4..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bitwise Xor - Two Registers", - "description": "Bitwise Xor - Two Registers", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.qmod b/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.qmod deleted file mode 100644 index 71fade75..00000000 --- a/functions/function_usage_examples/arithmetic/bitwise_xor_two_regs.qmod +++ /dev/null @@ -1,21 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BitwiseXor", - "function_params": { - "left_arg": { - "size": 5, - "is_signed": true - }, - "right_arg": { - "size": 3 - } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.json b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.json new file mode 100644 index 00000000..c42ddafb --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Comparator", + "description": "Quantum Variables Comparator", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.qmod b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.qmod new file mode 100644 index 00000000..e04979a9 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + allocate_num<5, True, 0>(a); + allocate_num<3, False, 0>(b); + res = a == b; +} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_example.ipynb b/functions/function_usage_examples/arithmetic/comparator/comparator_example.ipynb new file mode 100644 index 00000000..7cbb0823 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_example.ipynb @@ -0,0 +1,178 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "c6409153-313e-4911-b999-fce3fa5b3e0d", + "metadata": {}, + "source": [ + "# Comparators\n", + "\n", + "The following comparators are supported:\n", + "\n", + "- Equal (denoted as '==')\n", + "- NotEqual (denoted as '!=')\n", + "- GreaterThan (denoted as '>')\n", + "- GreaterEqual (denoted as '>=')\n", + "- LessThan (denoted as '<')\n", + "- LessEqual (denoted as '<=')\n", + "\n", + "Note that integer and fixed-point numbers are represented in a 2-complement method during function evaluation.\n", + "The binary number is extended in the case of a register size miss-match.\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when operating with a 5-qubit register.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "Examples:\n", + "\n", + "(5 <= 3) = 0\n", + "\n", + "(5 == 5) = 1\n", + "\n", + "($(011)_2$ == $(11)_2$) = 1\n", + "\n", + "(signed $(101)_2$ < unsigned $(101)_2$) = 1" + ] + }, + { + "cell_type": "markdown", + "id": "52f4a3fd-ed76-4cb8-9145-584e82163533", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Comparing Two Quantum Variables\n", + "\n", + "This example generates a quantum program that performs 'equal' between two variables.\n", + "The left arg is a signed variable with 5 qubits and the right arg is an unsigned varialbe with 3 qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c57c4fc6-98ab-4d49-9029-7b48411b25d3", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, allocate_num, create_model, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate_num(5, True, 0, a)\n", + " allocate_num(3, False, 0, b)\n", + "\n", + " res |= a == b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4c8aebb5-1e29-4062-a95d-6068057ecc8a", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"comparator_2vars_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "0ad9c0c6-857d-4e15-8735-c4008bafe537", + "metadata": {}, + "source": [ + "#### Example 2: Comparing Integer and Quantum Variable\n", + "\n", + "This example generates a quantum program that performs 'less equal' between a quantum register and an integer. \n", + "The left arg is an unsigned quantum variable with 3 qubits, and the right arg is an integer equal to 2." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "9ea8e6c8-6fc7-418a-91b1-811dbd4fd996", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate(3, a)\n", + " hadamard_transform(a)\n", + " res |= a <= 2\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "0f389b0c-2388-4dd0-b79c-4f82c36b5d89", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 7.0, 'res': 0.0}: 141,\n", + " {'a': 5.0, 'res': 0.0}: 135,\n", + " {'a': 0.0, 'res': 1.0}: 131,\n", + " {'a': 2.0, 'res': 1.0}: 126,\n", + " {'a': 4.0, 'res': 0.0}: 125,\n", + " {'a': 3.0, 'res': 0.0}: 118,\n", + " {'a': 1.0, 'res': 1.0}: 112,\n", + " {'a': 6.0, 'res': 0.0}: 112]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"comparator_integer_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.json b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.json new file mode 100644 index 00000000..3efa55cc --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Integer Comparator", + "description": "Quantum Variable and Integer Comparator", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.qmod b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.qmod new file mode 100644 index 00000000..39bb8a37 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output res: qnum) { + allocate<3>(a); + hadamard_transform(a); + res = a <= 2; +} diff --git a/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/comparator/comparator_integer_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/comparators_ex1.json b/functions/function_usage_examples/arithmetic/comparators_ex1.json deleted file mode 100644 index 08bc06ed..00000000 --- a/functions/function_usage_examples/arithmetic/comparators_ex1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Comparator - Two Registers", - "description": "Comparator - Two Registers", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/comparators_ex1.qmod b/functions/function_usage_examples/arithmetic/comparators_ex1.qmod deleted file mode 100644 index cb48471d..00000000 --- a/functions/function_usage_examples/arithmetic/comparators_ex1.qmod +++ /dev/null @@ -1,21 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Equal", - "function_params": { - "left_arg": { - "size": 5, - "is_signed": true - }, - "right_arg": { - "size": 3 - } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/comparators_ex2.json b/functions/function_usage_examples/arithmetic/comparators_ex2.json deleted file mode 100644 index d5fa775a..00000000 --- a/functions/function_usage_examples/arithmetic/comparators_ex2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Comparator - Integer and Register", - "description": "Comparator - Integer and Register", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/comparators_ex2.qmod b/functions/function_usage_examples/arithmetic/comparators_ex2.qmod deleted file mode 100644 index 064c8b39..00000000 --- a/functions/function_usage_examples/arithmetic/comparators_ex2.qmod +++ /dev/null @@ -1,18 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Equal", - "function_params": { - "left_arg": 3, - "right_arg": { - "size": 3 - } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/extremum/extremum_example.ipynb b/functions/function_usage_examples/arithmetic/extremum/extremum_example.ipynb new file mode 100644 index 00000000..990260f1 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/extremum_example.ipynb @@ -0,0 +1,193 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fbe539e6-1e8a-49e9-b2b9-5e5c528364b8", + "metadata": {}, + "source": [ + "# Minimum and Maximum\n", + "\n", + "The minimum and maximum operators determine the smallest and largest input, respectively.\n", + "Both functions receive two inputs. Each may be a fixed point number or a quantum register." + ] + }, + { + "cell_type": "markdown", + "id": "286e60ea-b549-464d-a01b-85dd13b92577", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Two Quantum Variables Minimum\n", + "\n", + "This code example generates a quantum program that returns a minimum of two arguments.\n", + "Both the left and right arguments are defined as quantum variables of size three." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "a7ceea4e-69b2-4f34-bfac-de55d23b9899", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " create_model,\n", + " hadamard_transform,\n", + " prepare_int,\n", + " qfunc,\n", + ")\n", + "from classiq.qmod.symbolic import min\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " allocate(3, b)\n", + " hadamard_transform(b)\n", + "\n", + " res |= min(a, b)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8ab2c7cd-fc78-47b7-ac0f-a48868fb9ebe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 4.0, 'b': 6.0, 'res': 4.0}: 146,\n", + " {'a': 4.0, 'b': 0.0, 'res': 0.0}: 142,\n", + " {'a': 4.0, 'b': 3.0, 'res': 3.0}: 137,\n", + " {'a': 4.0, 'b': 1.0, 'res': 1.0}: 132,\n", + " {'a': 4.0, 'b': 7.0, 'res': 4.0}: 116,\n", + " {'a': 4.0, 'b': 4.0, 'res': 4.0}: 113,\n", + " {'a': 4.0, 'b': 5.0, 'res': 4.0}: 108,\n", + " {'a': 4.0, 'b': 2.0, 'res': 2.0}: 106]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"minimum_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + }, + { + "cell_type": "markdown", + "id": "4821f55d-ebfa-46fe-ba4a-353a7f853112", + "metadata": {}, + "source": [ + "#### Example 2: Float and Quantum Variable Maximum\n", + "\n", + "This code example returns a quantum program with a maximum of two arguments.\n", + "Here, the left arg is a fixed-point number $(11.1)_2$ (3.5),\n", + "and the right arg is a quantum variable of size three." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7efdb898-a317-43d9-8915-5f4719a93217", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + ")\n", + "from classiq.qmod.symbolic import max\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate(3, a)\n", + " hadamard_transform(a)\n", + "\n", + " res |= max(3.5, a)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "79376eb8-baaa-4bc8-b8df-15915e20d577", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 3.0, 'res': 3.5}: 144,\n", + " {'a': 5.0, 'res': 5.0}: 141,\n", + " {'a': 2.0, 'res': 3.5}: 134,\n", + " {'a': 4.0, 'res': 4.0}: 127,\n", + " {'a': 7.0, 'res': 7.0}: 121,\n", + " {'a': 6.0, 'res': 6.0}: 118,\n", + " {'a': 1.0, 'res': 3.5}: 116,\n", + " {'a': 0.0, 'res': 3.5}: 99]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"maximum_float_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.json b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.json new file mode 100644 index 00000000..c5941944 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Float Maximum", + "description": "Quantum Variable and Float Maximum", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.qmod b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.qmod new file mode 100644 index 00000000..bf87f19e --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output res: qnum) { + allocate<3>(a); + hadamard_transform(a); + res = max(3.5, a); +} diff --git a/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/maximum_float_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.qmod b/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.qmod new file mode 100644 index 00000000..bf87f19e --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output res: qnum) { + allocate<3>(a); + hadamard_transform(a); + res = max(3.5, a); +} diff --git a/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/maximum_integer_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.json b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.json new file mode 100644 index 00000000..1cbb6695 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Mininum", + "description": "Quantum Variables Mininum", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.qmod b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.qmod new file mode 100644 index 00000000..4a30635e --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.qmod @@ -0,0 +1,6 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + prepare_int<4>(a); + allocate<3>(b); + hadamard_transform(b); + res = min(a, b); +} diff --git a/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/extremum/minimum_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.json b/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.json deleted file mode 100644 index 72d714f1..00000000 --- a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Two Register Minimum", - "description": "Two Register Minimum", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.qmod b/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.qmod deleted file mode 100644 index c061388d..00000000 --- a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex1.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Min", - "function_params": { - "left_arg": {"size": 3, "name": "left"}, - "right_arg": {"size": 3, "name": "right"} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.json b/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.json deleted file mode 100644 index 561b2419..00000000 --- a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Float and Register Minimum", - "description": "Float and Register Minimum", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.qmod b/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.qmod deleted file mode 100644 index f29d1b8c..00000000 --- a/functions/function_usage_examples/arithmetic/minimum_and_maximum_ex2.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Min", - "function_params": { - "left_arg": 3.5, - "right_arg": {"size": 3, "name": "arg"} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/modulo/modulo_example.ipynb b/functions/function_usage_examples/arithmetic/modulo/modulo_example.ipynb new file mode 100644 index 00000000..4996a8b0 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/modulo/modulo_example.ipynb @@ -0,0 +1,123 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "f6834a62-d124-48f6-bd87-d313b7eb5054", + "metadata": {}, + "source": [ + "# Modulo\n", + "\n", + "The modulo operation (denoted as '%') returns the remainder (called \"modulus\") of a division.\n", + "Given two numbers $a$ and $n$, the result of ($a \\% n$) is the remainder of the division of a by n.\n", + "The modulo operation is supported only for $n = 2^m$ for an integer $m$, its result is the $m$ least significant bits.\n", + "\n", + "For example, the binary representation of the number $53$ is $0b110101$.\n", + "The expression ($53 \\% 8$) equals $0b101 = 5$, because $8 = 2^3$, which means only accounting for the $3$ least\n", + "significant bits of $53$.\n", + "\n", + "#### Implementation in Expressions\n", + "\n", + "If an expression is defined using a modulo operation, the output size is set recursively to all of its subexpressions.\n", + "But if for some sub-expressions, another modulo operation is used,\n", + "the sub-expression's output_size is determined by the minimal value between\n", + "the output_size of the sub-expression and the expression.\n", + "\n", + "See this example: $(((a + b) \\% 4) + (c + d)) \\% 8$.\n", + "The result of expression $a + b$ is saved on a two-qubit register,\n", + "and the results of expressions $c + d$ and $((a + b) \\% 4) + (c + d)$ are saved\n", + "using three qubits each." + ] + }, + { + "cell_type": "markdown", + "id": "b54ad820-bdd9-4fbe-bbe7-a7d6a3db046b", + "metadata": {}, + "source": [ + "# Example\n", + "\n", + "This example generates a quantum program that adds two five-qubit arguments: a on qubits 0-4, and b on qubits 5-9.\n", + "The adder result should have been calculated on a 6-qubit register.\n", + "However, the modulo operation decides that the output register of the adder only contains its two least significant\n", + "qubits. Thus, the adder result is written to a two-qubit register, on qubits 10-11." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2663dafc-22a7-43b3-838e-33829cbf04e5", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " create_model,\n", + " inplace_prepare_int,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate(5, a)\n", + " allocate(5, b)\n", + "\n", + " inplace_prepare_int(4, a)\n", + " inplace_prepare_int(7, b)\n", + "\n", + " res |= (a + b) % 4\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "574fb1b6-5ef9-4e87-b6b8-c2f9a858c7ba", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'a': 4.0, 'b': 7.0, 'res': 3.0}: 1000]\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"modulo_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.parsed_counts)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/modulo_ex1.json b/functions/function_usage_examples/arithmetic/modulo/modulo_example.json similarity index 64% rename from functions/function_usage_examples/arithmetic/modulo_ex1.json rename to functions/function_usage_examples/arithmetic/modulo/modulo_example.json index b5d0898c..12164585 100644 --- a/functions/function_usage_examples/arithmetic/modulo_ex1.json +++ b/functions/function_usage_examples/arithmetic/modulo/modulo_example.json @@ -1,7 +1,6 @@ { "friendly_name": "Modulo", "description": "Modulo", - "problem_domain_tags": [], "qmod_type": ["function"], - "level": ["demos"] + "level": ["demos", "basic"] } diff --git a/functions/function_usage_examples/arithmetic/modulo/modulo_example.qmod b/functions/function_usage_examples/arithmetic/modulo/modulo_example.qmod new file mode 100644 index 00000000..3ab6e622 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/modulo/modulo_example.qmod @@ -0,0 +1,7 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + allocate<5>(a); + allocate<5>(b); + inplace_prepare_int<4>(a); + inplace_prepare_int<7>(b); + res = (a + b) % 4; +} diff --git a/functions/function_usage_examples/arithmetic/modulo/modulo_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/modulo/modulo_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/modulo/modulo_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/modulo_ex1.qmod b/functions/function_usage_examples/arithmetic/modulo_ex1.qmod deleted file mode 100644 index a3a7e3bd..00000000 --- a/functions/function_usage_examples/arithmetic/modulo_ex1.qmod +++ /dev/null @@ -1,17 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Modulo", - "function_params": { - "left_arg": {"size": 7}, - "right_arg": 8, - "inplace_arg": "left" - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/modulo_ex2.json b/functions/function_usage_examples/arithmetic/modulo_ex2.json deleted file mode 100644 index 77970bc9..00000000 --- a/functions/function_usage_examples/arithmetic/modulo_ex2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Modulo after and Adder Function", - "description": "Modulo after and Adder Function", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/modulo_ex2.qmod b/functions/function_usage_examples/arithmetic/modulo_ex2.qmod deleted file mode 100644 index 4cc41b0f..00000000 --- a/functions/function_usage_examples/arithmetic/modulo_ex2.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Arithmetic", - "function_params": { - "expression": "(a + b) % 4 == 3", - "definitions": {"a": {"size": 5}, "b": {"size": 5}} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication.ipynb b/functions/function_usage_examples/arithmetic/multiplication/multiplication.ipynb new file mode 100644 index 00000000..7d377d28 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication.ipynb @@ -0,0 +1,191 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a26d486b-c5ac-4b64-a7fb-5500c339dd3b", + "metadata": {}, + "source": [ + "# Multiplication\n", + "\n", + "The multiplication operation, denoted '$*$', is a series of additions (\"long multiplication\").\n", + "The multiplier has different implementations, depending on the type of adder in use.\n", + "\n", + "Note that integer and fixed-point numbers are represented in a two-complement method during function evaluation.\n", + "The binary number is extended in the case of a register size mismatch.\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when working with a five-qubit register.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "## Examples\n", + "\n", + "The calculation of -5 \\* 3 = -15.\n", + "\n", + "The left arg -5 is represented as 1011 and 3 as 11. The number of digits needed to store the answer is 4+2-1 = 5.\n", + "The multiplication is done in the 'regular' manner where each number is extended to five bits and only five digits are kept in the intermediary\n", + "results.\n", + "\n", + "$$\n", + "\\begin{equation*}\\begin{array}{c}\n", + "\\phantom{\\times}11011\\\\\n", + "\\underline{\\times\\phantom{000}11}\\\\\n", + "\\phantom{\\times}11011\\\\\n", + "\\underline{\\phantom\\times1011\\phantom9}\\\\\n", + "\\phantom\\times10001\n", + "\\end{array}\\end{equation*}\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "c24bee78-f00a-4feb-80f6-a8a4f56c3506", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Two Quantum Variables Multiplication\n", + "\n", + "This code example generates a quantum program that multiplies two arguments.\n", + "Both of them are defined as quantum variables of size 3." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "42c07535-40db-48ee-9c1e-7bd1d2995a5d", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " prepare_int(5, b)\n", + " res |= a * b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4db98245-941f-42d7-bd79-b4f6b58d23dd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 4.0, 'b': 5.0, 'res': 20.0}: 1000]" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"multiplication_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + }, + { + "cell_type": "markdown", + "id": "56e1ff0a-822d-4512-ae1f-2aa6e2e0b285", + "metadata": {}, + "source": [ + "#### Example 2: Float and Quantum Variable Multiplication\n", + "\n", + "This code example generates a quantum program that multiplies two arguments.\n", + "Here, the left argument is a fixed-point number $(11.1)_2$ (3.5), \n", + "and the right argument is a quantum variable of size 2." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6eb691d5-8e89-44e1-9c83-a9be9d771edb", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " allocate(2, a)\n", + "\n", + " hadamard_transform(a)\n", + " res |= 3.5 * a\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7c469852-14c7-43f8-8067-91820aa98ff7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': 0.0, 'res': 0.0}: 265,\n", + " {'a': 1.0, 'res': 3.5}: 258,\n", + " {'a': 2.0, 'res': 7.0}: 248,\n", + " {'a': 3.0, 'res': 10.5}: 229]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"multiplication_float_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.json b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.json new file mode 100644 index 00000000..8696ffcc --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Multiplication", + "description": "Quantum Variables Multiplication", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.qmod b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.qmod new file mode 100644 index 00000000..2ca86570 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + prepare_int<4>(a); + prepare_int<5>(b); + res = a * b; +} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.json b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.json new file mode 100644 index 00000000..09917b36 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Float Multiplication", + "description": "Quantum Variable and Float Multiplication", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.qmod b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.qmod new file mode 100644 index 00000000..928f0f80 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output res: qnum) { + allocate<2>(a); + hadamard_transform(a); + res = 3.5 * a; +} diff --git a/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/multiplication/multiplication_float_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/multiplication_ex1.json b/functions/function_usage_examples/arithmetic/multiplication_ex1.json deleted file mode 100644 index 0aab9947..00000000 --- a/functions/function_usage_examples/arithmetic/multiplication_ex1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Two Register Multiplication", - "description": "Two Register Multiplication", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/multiplication_ex1.qmod b/functions/function_usage_examples/arithmetic/multiplication_ex1.qmod deleted file mode 100644 index ff1ccbed..00000000 --- a/functions/function_usage_examples/arithmetic/multiplication_ex1.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Multiplier", - "function_params": { - "left_arg": {"size": 3}, - "right_arg": {"size": 3} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/multiplication_ex2.json b/functions/function_usage_examples/arithmetic/multiplication_ex2.json deleted file mode 100644 index 3023c88a..00000000 --- a/functions/function_usage_examples/arithmetic/multiplication_ex2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Float and Register Multiplication", - "description": "Float and Register Multiplication", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/multiplication_ex2.qmod b/functions/function_usage_examples/arithmetic/multiplication_ex2.qmod deleted file mode 100644 index f316ed50..00000000 --- a/functions/function_usage_examples/arithmetic/multiplication_ex2.qmod +++ /dev/null @@ -1,18 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Multiplier", - "function_params": { - "left_arg": 3.5, - "right_arg": { - "size": 3 - } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/negation.json b/functions/function_usage_examples/arithmetic/negation.json deleted file mode 100644 index a460d154..00000000 --- a/functions/function_usage_examples/arithmetic/negation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Negation", - "description": "Negation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/negation.qmod b/functions/function_usage_examples/arithmetic/negation.qmod deleted file mode 100644 index 754f2718..00000000 --- a/functions/function_usage_examples/arithmetic/negation.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Negation", - "function_params": { - "arg": {"size": 7, "fraction_places": 3, "is_signed": true}, - "inplace": true - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/negation/negation_example.ipynb b/functions/function_usage_examples/arithmetic/negation/negation_example.ipynb new file mode 100644 index 00000000..71a7fc39 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/negation/negation_example.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b16227a7-d8ca-462f-9926-9649342ba0d2", + "metadata": {}, + "source": [ + "# Negation\n", + "\n", + "The negation operation receives a quantum register representing some number $x$\n", + "and returns a quantum register containing $-x$. Integer and fixed point numbers are both supported." + ] + }, + { + "cell_type": "markdown", + "id": "c3e4ae57-2b9a-4318-bd50-6f9651b5109e", + "metadata": {}, + "source": [ + "## Example\n", + "\n", + "The following example will show negation of a signed quantum variable." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "1ef4da37-e2c0-43e7-b525-7a2f001788a6", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate_num,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum]) -> None:\n", + " allocate_num(3, True, 0, a)\n", + " hadamard_transform(a)\n", + " b |= -a\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0cc7105a-ec20-48f6-80d3-9d6a969581ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'a': -1.0, 'b': 1.0}: 133,\n", + " {'a': 1.0, 'b': -1.0}: 133,\n", + " {'a': -4.0, 'b': 4.0}: 133,\n", + " {'a': 0.0, 'b': 0.0}: 127,\n", + " {'a': 2.0, 'b': -2.0}: 127,\n", + " {'a': -3.0, 'b': 3.0}: 124,\n", + " {'a': -2.0, 'b': 2.0}: 120,\n", + " {'a': 3.0, 'b': -3.0}: 103]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"negation_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "result.parsed_counts" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/negation/negation_example.json b/functions/function_usage_examples/arithmetic/negation/negation_example.json new file mode 100644 index 00000000..34b7722a --- /dev/null +++ b/functions/function_usage_examples/arithmetic/negation/negation_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable Negation", + "description": "Quantum Variable Negation", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/negation/negation_example.qmod b/functions/function_usage_examples/arithmetic/negation/negation_example.qmod new file mode 100644 index 00000000..2f656648 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/negation/negation_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output b: qnum) { + allocate_num<3, True, 0>(a); + hadamard_transform(a); + b = -a; +} diff --git a/functions/function_usage_examples/arithmetic/negation/negation_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/negation/negation_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/negation/negation_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.json b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.json new file mode 100644 index 00000000..6ca93dac --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variables Subtraction", + "description": "Quantum Variables Subtraction", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.qmod b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.qmod new file mode 100644 index 00000000..931409e2 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output a: qnum, output b: qnum, output res: qnum) { + prepare_int<4>(a); + prepare_int<5>(b); + res = a - b; +} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_2vars_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_example.ipynb b/functions/function_usage_examples/arithmetic/subtraction/subtraction_example.ipynb new file mode 100644 index 00000000..f3da5c5d --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_example.ipynb @@ -0,0 +1,164 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "31a63d07-866d-4883-83fc-0fa453dc9775", + "metadata": {}, + "source": [ + "# Subtraction\n", + "\n", + "Subtraction (denoted as '-') is implemented by negation and addition in 2-complement representation.\n", + "\n", + "$$\n", + "a - b \\longleftrightarrow a + (-b) \\longleftrightarrow a + \\sim{b} + lsb\\_value\n", + "$$\n", + "\n", + "Where '~' is bitwise not and $lsb\\_value$ is the least significant bit value.\n", + "\n", + "Note that integer and fixed-point numbers are represented in a 2-complement method during function evaluation.\n", + "The binary number is extended in the case of a register size miss-match.\n", + "For example, the positive signed number $(110)_2=6$ is expressed as $(00110)_2$ when operating with a 5-qubit register.\n", + "Similarly, the negative signed number $(110)_2=-2$ is expressed as $(11110)_2$.\n", + "\n", + "Examples:\n", + "\n", + "5 + 3 = 8 , 0101 + 0011 = 1000\n", + "\n", + "5 - 3 = 5 + (-3) = 2, 0101 + 1101 = 0010\n", + "\n", + "-5 + -3 = -8, 1011 + 1101 = 1000" + ] + }, + { + "cell_type": "markdown", + "id": "25b2abef-2324-4dd4-bebc-7e60b44e7caa", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "#### Example 1: Subtraction of Two Quantum Variables\n", + "\n", + "This example generates a quantum program that subtracts one quantum variables from the other, both of size 3 qubits." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "85eb57a6-0488-49a5-8675-5cb4c94689bb", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], b: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " prepare_int(5, b)\n", + " res |= a - b\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "bc11dc7d-eb99-4042-ba3b-c0aebaee66b6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'a': 4.0, 'b': 5.0, 'res': -1.0}: 1000]\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"subtraction_2vars_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.parsed_counts)" + ] + }, + { + "cell_type": "markdown", + "id": "d26be91f-435f-4f0d-8214-1b5b06196dbd", + "metadata": {}, + "source": [ + "#### Example 2: Subtraction of a Float from a Register\n", + "\n", + "This example generates a quantum program which subtracts two argument. The left_arg is defined to be a fix point number $(11.1)_2$ (3.5).\n", + "The right_arg is defined to be a quantum register of size of three." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "fe79e229-397b-4ee9-8396-0831e809008a", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, QNum, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(a: Output[QNum], res: Output[QNum]) -> None:\n", + " prepare_int(4, a)\n", + " res |= a - 3.5\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "f8704a73-2dd0-4343-bf5a-cde4e14dffdc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[{'a': 4.0, 'res': 0.5}: 1000]\n" + ] + } + ], + "source": [ + "from classiq import execute, synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"subtraction_float_example\")\n", + "qprog = synthesize(qmod)\n", + "\n", + "result = execute(qprog).result()[0].value\n", + "print(result.parsed_counts)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.json b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.json new file mode 100644 index 00000000..f43a13f5 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Variable and Float Subtraction", + "description": "Quantum Variable and Float Subtraction", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.qmod b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.qmod new file mode 100644 index 00000000..ebc6722e --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output a: qnum, output res: qnum) { + prepare_int<4>(a); + res = a - 3.5; +} diff --git a/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.synthesis_options.json b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/arithmetic/subtraction/subtraction_float_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/arithmetic/subtraction_ex1.json b/functions/function_usage_examples/arithmetic/subtraction_ex1.json deleted file mode 100644 index 4f7c59a9..00000000 --- a/functions/function_usage_examples/arithmetic/subtraction_ex1.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Subtraction - Two Register", - "description": "Subtraction - Two Register", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/subtraction_ex1.qmod b/functions/function_usage_examples/arithmetic/subtraction_ex1.qmod deleted file mode 100644 index ded55d4f..00000000 --- a/functions/function_usage_examples/arithmetic/subtraction_ex1.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Subtractor", - "function_params": { - "left_arg": {"size": 3}, - "right_arg": {"size": 3} - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/arithmetic/subtraction_ex2.json b/functions/function_usage_examples/arithmetic/subtraction_ex2.json deleted file mode 100644 index 957d9cb9..00000000 --- a/functions/function_usage_examples/arithmetic/subtraction_ex2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Subtraction - Float and Register", - "description": "Subtraction - Float and Register", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/arithmetic/subtraction_ex2.qmod b/functions/function_usage_examples/arithmetic/subtraction_ex2.qmod deleted file mode 100644 index b6452bf3..00000000 --- a/functions/function_usage_examples/arithmetic/subtraction_ex2.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "Subtractor", - "function_params": { - "left_arg": 3.5, - "right_arg": { "size": 3 } - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/grover_operator/grover_operator_example.ipynb b/functions/function_usage_examples/grover_operator/grover_operator_example.ipynb new file mode 100644 index 00000000..ceec273e --- /dev/null +++ b/functions/function_usage_examples/grover_operator/grover_operator_example.ipynb @@ -0,0 +1,252 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a19f89e9-21fc-4399-898b-b79f77de8c3a", + "metadata": {}, + "source": [ + "# Grover Operator\n", + "\n", + "The Grover operator is a unitary used in amplitude estimation and amplitude\n", + "amplification algorithms [[1]](#1). The Grover operator is given by\n", + "\n", + "$$\n", + "Q = Q(A,\\chi) = -AS_0A^{-1}S_\\chi\n", + "$$\n", + "\n", + "where $A$ is a state preparation operator,\n", + "\n", + "$$\n", + "A|0 \\rangle= |\\psi \\rangle\n", + "$$\n", + "\n", + "$S_\\chi$ marks good states and is called an oracle,\n", + "$$\n", + "S_\\chi\\lvert x \\rangle = \n", + "\\begin{cases} \n", + "-\\lvert x \\rangle & \\text{if } \\chi(x) = 1 \\\\\n", + " \\phantom{-} \\lvert x \\rangle & \\text{if } \\chi(x) = 0 \n", + "\\end{cases}\n", + "$$\n", + "and $S_0$ is a reflection about the zero state. \n", + "\n", + "$$\n", + "S_0 = I - 2|0\\rangle\\langle0|\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "e2e4a2a3-c2f9-4d10-8656-dfd92048ed93", + "metadata": {}, + "source": [ + "Function: `grover_operator`\n", + "\n", + "Arguments:\n", + "\n", + "- `oracle: QCallable[QArray[QBit]]` - Oracle representing $S_{\\chi}$, accepting quantum state to apply on.\n", + "- `space_transform: QCallable[QArray[QBit]]` - State preparation operator $A$, accepting quantum state to apply on.\n", + "- `packed_vars: QArray[QBit]` - Packed form of the variable to apply the grover operator on." + ] + }, + { + "cell_type": "markdown", + "id": "4d7c22bd-f0d5-460e-8611-0930996c5a36", + "metadata": {}, + "source": [ + "### Example\n", + "\n", + "The following example implements a grover search algorithm using the grover operator for a specific oracle, with a uniform superposition over the search space.\n", + "The circuit starts with a uniform superposition on the search space, followed by 2 applications of the grover operator." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "10f00ffb-e800-4d38-8558-186320e92d99", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Constraints,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QCallable,\n", + " QNum,\n", + " allocate,\n", + " bind,\n", + " create_model,\n", + " grover_operator,\n", + " hadamard_transform,\n", + " phase_oracle,\n", + " power,\n", + " qfunc,\n", + ")\n", + "from classiq.qmod.symbolic import logical_and\n", + "\n", + "VAR_SIZE = 2\n", + "\n", + "\n", + "@qfunc\n", + "def my_predicate(x: QNum, y: QNum, res: QBit) -> None:\n", + " res ^= logical_and((x + y < 9), ((x * y) % 4 == 1))\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QNum[VAR_SIZE, False, 0]], y: Output[QNum[VAR_SIZE, False, 0]]):\n", + " packed_vars = QArray(\"packed_vars\")\n", + " allocate(2 * VAR_SIZE, packed_vars)\n", + "\n", + " hadamard_transform(packed_vars)\n", + "\n", + " power(\n", + " 2,\n", + " lambda: grover_operator(\n", + " lambda vars: phase_oracle(\n", + " predicate=lambda _vars, _res: my_predicate(\n", + " _vars[0:VAR_SIZE], _vars[VAR_SIZE : _vars.len], _res\n", + " ),\n", + " target=vars,\n", + " ),\n", + " lambda vars: hadamard_transform(vars),\n", + " packed_vars,\n", + " ),\n", + " )\n", + " bind(packed_vars, [x, y])\n", + "\n", + "\n", + "constraints = Constraints(max_width=15)\n", + "qmod_grover = create_model(main, constraints=constraints)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "1be60ce8-8039-46ed-9823-e531efdc47c3", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod_grover, \"grover_operator_example\")\n", + "qprog = synthesize(qmod_grover)" + ] + }, + { + "cell_type": "markdown", + "id": "f7ccbdd9-101b-4014-87f0-4292966d6203", + "metadata": {}, + "source": [ + "And the next is a verification of the amplification of the solutions to the oracle:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "2ab73502-297e-4f4f-a1c7-39e1b269c823", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'x': 1.0, 'y': 1.0}: 478,\n", + " {'x': 3.0, 'y': 3.0}: 475,\n", + " {'x': 2.0, 'y': 2.0}: 7,\n", + " {'x': 3.0, 'y': 0.0}: 6,\n", + " {'x': 2.0, 'y': 0.0}: 6,\n", + " {'x': 0.0, 'y': 2.0}: 5,\n", + " {'x': 0.0, 'y': 1.0}: 5,\n", + " {'x': 1.0, 'y': 0.0}: 4,\n", + " {'x': 0.0, 'y': 3.0}: 4,\n", + " {'x': 3.0, 'y': 1.0}: 4,\n", + " {'x': 1.0, 'y': 2.0}: 2,\n", + " {'x': 3.0, 'y': 2.0}: 1,\n", + " {'x': 0.0, 'y': 0.0}: 1,\n", + " {'x': 2.0, 'y': 3.0}: 1,\n", + " {'x': 1.0, 'y': 3.0}: 1]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from classiq import execute\n", + "\n", + "res = execute(qprog).result()[0].value\n", + "res.parsed_counts" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a63180c7-f2b3-444e-a518-e9bb3f3f1298", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 0 False\n", + "0 1 False\n", + "0 2 False\n", + "0 3 False\n", + "1 0 False\n", + "1 1 True\n", + "1 2 False\n", + "1 3 False\n", + "2 0 False\n", + "2 1 False\n", + "2 2 False\n", + "2 3 False\n", + "3 0 False\n", + "3 1 False\n", + "3 2 False\n", + "3 3 True\n" + ] + } + ], + "source": [ + "from itertools import product\n", + "\n", + "for x, y in product(range(2**VAR_SIZE), range(2**VAR_SIZE)):\n", + " print(x, y, (x + y < 9) and ((x * y) % 4 == 1))" + ] + }, + { + "cell_type": "markdown", + "id": "00f8feca-6f2a-444e-973e-20be5dc9bed0", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1] G. Brassard, P. Hoyer, M. Mosca, and A. Tapp, “Quantum\n", + "Amplitude Amplification and Estimation,” arXiv:quant-ph/0005055, vol. 305, pp.\n", + "53–74, 2002, doi: 10.1090/conm/305/05215." + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/grover_operator/grover_operator_example.json b/functions/function_usage_examples/grover_operator/grover_operator_example.json new file mode 100644 index 00000000..2e60532e --- /dev/null +++ b/functions/function_usage_examples/grover_operator/grover_operator_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Grover Operator", + "description": "Grover Operator", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/grover_operator/grover_operator_example.qmod b/functions/function_usage_examples/grover_operator/grover_operator_example.qmod new file mode 100644 index 00000000..60daaedf --- /dev/null +++ b/functions/function_usage_examples/grover_operator/grover_operator_example.qmod @@ -0,0 +1,19 @@ +qfunc my_predicate(x: qnum, y: qnum, res: qbit) { + res ^= ((x + y) < 9) and (((x * y) % 4) == 1); +} + +qfunc main(output x: qnum<2, False, 0>, output y: qnum<2, False, 0>) { + packed_vars: qbit[]; + allocate<4>(packed_vars); + hadamard_transform(packed_vars); + power (2) { + grover_operator(arg0); + }, lambda(arg0) { + hadamard_transform(arg0); + }>(packed_vars); + } + packed_vars -> {x, y}; +} diff --git a/functions/function_usage_examples/grover_operator/grover_operator_example.synthesis_options.json b/functions/function_usage_examples/grover_operator/grover_operator_example.synthesis_options.json new file mode 100644 index 00000000..50421076 --- /dev/null +++ b/functions/function_usage_examples/grover_operator/grover_operator_example.synthesis_options.json @@ -0,0 +1,5 @@ +{ + "constraints": { + "max_width": 15 + } +} diff --git a/functions/function_usage_examples/hadamard_transform/hadamard_transform.ipynb b/functions/function_usage_examples/hadamard_transform/hadamard_transform.ipynb new file mode 100644 index 00000000..f6e8ca2e --- /dev/null +++ b/functions/function_usage_examples/hadamard_transform/hadamard_transform.ipynb @@ -0,0 +1,100 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "08fdfed7-8f70-4479-909a-6123464a5272", + "metadata": {}, + "source": [ + "# Hadamard Transform\n", + "\n", + "The Hadamard transform function applies an H gate on each qubit of the register inputted to the function.\n", + "\n", + "Function: `hadamard_transform`\n", + "\n", + "Arguments:\n", + "\n", + "- `target`: `QArray[QBit]`\n", + "\n", + "The `target` quantum argument is the quantum state on which we apply the Hadamard Transform.\n" + ] + }, + { + "cell_type": "markdown", + "id": "4aaa84d1-36c5-4eb3-a713-593d9cc509b3", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "d67855d0-5461-4d8e-9f7d-1bc47ca80928", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + "\n", + " allocate(3, x)\n", + " hadamard_transform(x)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4e9bb384-4af0-4ab4-9e2e-2b8ba243ad5e", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"hadamard_transform_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "47483246-abce-4f8e-aa85-9265dca3f21a", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.json b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.json new file mode 100644 index 00000000..da48e40c --- /dev/null +++ b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Hadamard Transform", + "description": "Hadamard Transform", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.qmod b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.qmod new file mode 100644 index 00000000..f5fd0a30 --- /dev/null +++ b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output x: qbit[]) { + allocate<3>(x); + hadamard_transform(x); +} diff --git a/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.synthesis_options.json b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/hadamard_transform/hadamard_transform_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation.ipynb b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation.ipynb new file mode 100644 index 00000000..5f878db6 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "3509e851-c4c3-4feb-8999-340b26b68600", + "metadata": {}, + "source": [ + "# Exponentiation\n", + "\n", + "The exponentiation function produces a quantum gate that approximates the exponentiation, $\\exp(-iHt)$, of any input Hermitian operator, $H$. The Classiq engine automatically generates an efficient higher-order Trotter-Suzuki quantum program [ [1] ](#Trotter-Suzuki) that minimizes the functional error and satisfies a given local constraint on the depth. The functional error is measured by the operator norm [ [2] ](#operator-norm) and evaluated according to Ref. [[3]](#error-bound)\n", + "\n", + "The Hamiltonian is given as any $n$-qubit operator in its Pauli basis [[4]](#pauli-basis):\n", + "$$\n", + "H=\\sum_i c_i\\left[\\sigma_{j_{1,i}}\\otimes\\sigma_{j_{2,i}}\\otimes\\cdots\\otimes\\sigma_{j_{n,i}}\\right],\n", + "$$\n", + "where $\\sigma_{0,1,2,3}=I,X,Y,Z$ are the single-qubit Pauli operators, and $j\\in\\{0,1,2,3\\}$, and $c_i$ are complex coefficients.\n", + "For example, the operator $H=0.1\\cdot I\\otimes Z+0.2\\cdot X\\otimes Y$ is input as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a6d52a3e-3f5a-43d4-af4e-c1e9f9be559d", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Pauli, PauliTerm\n", + "\n", + "pauli_list = [\n", + " PauliTerm(pauli=[Pauli.I, Pauli.Z], coefficient=0.1),\n", + " PauliTerm(pauli=[Pauli.X, Pauli.Y], coefficient=0.2),\n", + "]" + ] + }, + { + "cell_type": "markdown", + "id": "9c9febbd-4593-42b9-b443-a4fde60e088c", + "metadata": {}, + "source": [ + "Function: `exponentiation_with_depth_constraint`\n", + "\n", + "Arguments:\n", + "\n", + "* `pauli_operator`: `CArray[PauliTerm]` - the Hamiltonian to exponentiate as described above,\n", + "* `evolution_coefficient`: `CReal` - a global evolution coefficient (the parameter $t$ above),\n", + "* `max_depth`: `CInt` - a maximal depth for the implementation,\n", + "* `qbv`: `QArray[QBit]` - the quantum state on which we apply the evolution." + ] + }, + { + "cell_type": "markdown", + "id": "eb6eafb6-66b3-400d-a044-906446ab551f", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d10f9e15-bca1-4cf4-9578-e054ebc2d760", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " Pauli,\n", + " PauliTerm,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " exponentiation_with_depth_constraint,\n", + " qfunc,\n", + " synthesize,\n", + " write_qmod,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(qba: Output[QArray[QBit]]):\n", + "\n", + " allocate(4, qba)\n", + " exponentiation_with_depth_constraint(\n", + " [\n", + " PauliTerm(pauli=[Pauli.X, Pauli.X, Pauli.I, Pauli.I], coefficient=0.1),\n", + " PauliTerm(pauli=[Pauli.Y, Pauli.Y, Pauli.I, Pauli.I], coefficient=0.2),\n", + " PauliTerm(pauli=[Pauli.Z, Pauli.Z, Pauli.Y, Pauli.X], coefficient=0.4),\n", + " PauliTerm(pauli=[Pauli.I, Pauli.I, Pauli.I, Pauli.X], coefficient=0.4),\n", + " ],\n", + " evolution_coefficient=0.05,\n", + " max_depth=50,\n", + " qbv=qba,\n", + " )\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"exponentiation_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "81411696-003b-4ecb-977b-a5752c7ca1e8", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "\n", + "[1] N. Hatano and M. Suzuki, Finding Exponential Product Formulas of Higher Orders, [https://arxiv.org/abs/math-ph/0506007](https://arxiv.org/abs/math-ph/0506007) (2005).\n", + "\n", + "\n", + "\n", + "[2] [https://en.wikipedia.org/wiki/Operator_norm](https://en.wikipedia.org/wiki/Operator_norm)\n", + "\n", + "[3] A. M. Childs et al, Toward the first quantum simulation with quantum speedup, [https://arxiv.org/abs/1711.10980](https://arxiv.org/abs/1711.10980) (2017).\n", + "\n", + "[4] [https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices#Multi-qubit_Pauli_matrices_(Hermitian)](https://en.wikipedia.org/wiki/Generalizations_of_Pauli_matrices#Multi-qubit_Pauli_matrices_(Hermitian))\n", + "" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.json b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.json new file mode 100644 index 00000000..8b96b7c3 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Exponentiation", + "description": "Exponentiation Example", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.qmod b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.qmod new file mode 100644 index 00000000..049e06b3 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.qmod @@ -0,0 +1,41 @@ +qfunc main(output qba: qbit[]) { + allocate<4>(qba); + exponentiation_with_depth_constraint<[ + PauliTerm { + pauli = [ + Pauli::X, + Pauli::X, + Pauli::I, + Pauli::I + ], + coefficient = 0.1 + }, + PauliTerm { + pauli = [ + Pauli::Y, + Pauli::Y, + Pauli::I, + Pauli::I + ], + coefficient = 0.2 + }, + PauliTerm { + pauli = [ + Pauli::Z, + Pauli::Z, + Pauli::Y, + Pauli::X + ], + coefficient = 0.4 + }, + PauliTerm { + pauli = [ + Pauli::I, + Pauli::I, + Pauli::I, + Pauli::X + ], + coefficient = 0.4 + } + ], 0.05, 50>(qba); +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.synthesis_options.json b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/exponentiation/exponentiation_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift.ipynb b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift.ipynb new file mode 100644 index 00000000..3a1be5f9 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift.ipynb @@ -0,0 +1,105 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "acaa6448-587f-414b-8a39-8c684a65cb20", + "metadata": {}, + "source": [ + "# qDrift\n", + "\n", + "The `qdrift` function implements the qDrift Trotter evolution of Ref.[ [1] ](#qDrift).\n", + "\n", + "\n", + "Function: `qdrift`\n", + "\n", + "Arguments:\n", + "\n", + "* `pauli_operator`: `CArray[PauliTerm]`,\n", + "* `evolution_coefficient`: `CReal`,\n", + "* `num_qdrift`: `CInt`,\n", + "* `qbv`: `QArray[QBit]`," + ] + }, + { + "cell_type": "markdown", + "id": "df684532-0095-41fd-8913-b7e59d049a3b", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "dc97bd53-669a-481f-a42d-09a486046b2d", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " Pauli,\n", + " PauliTerm,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " qdrift,\n", + " qfunc,\n", + " synthesize,\n", + " write_qmod,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(qba: Output[QArray[QBit]]):\n", + "\n", + " allocate(2, qba)\n", + " qdrift(\n", + " [\n", + " PauliTerm(pauli=[Pauli.X, Pauli.Y], coefficient=1.0),\n", + " PauliTerm(pauli=[Pauli.Z, Pauli.I], coefficient=0.5),\n", + " ],\n", + " evolution_coefficient=2.0,\n", + " num_qdrift=5,\n", + " qbv=qba,\n", + " )\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"qdrift_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "7e1bc3d2-fb05-4125-8bce-832d27a3a3c6", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1] E. Campbell, Random Compiler for Fast Hamiltonian Simulation, (2019). [https://arxiv.org/abs/1811.08017](https://arxiv.org/abs/1811.08017)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.json b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.json new file mode 100644 index 00000000..3b190d01 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "qDRIFT", + "description": "qDRIFT Example", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.qmod b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.qmod new file mode 100644 index 00000000..63948f54 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.qmod @@ -0,0 +1,13 @@ +qfunc main(output qba: qbit[]) { + allocate<2>(qba); + qdrift<[ + PauliTerm { + pauli = [Pauli::X, Pauli::Y], + coefficient = 1.0 + }, + PauliTerm { + pauli = [Pauli::Z, Pauli::I], + coefficient = 0.5 + } + ], 2.0, 5>(qba); +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.synthesis_options.json b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/qdrift/qdrift_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter.ipynb b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter.ipynb new file mode 100644 index 00000000..0e97b3af --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter.ipynb @@ -0,0 +1,106 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "080e62a2-0cef-41ad-b745-b4a00331703b", + "metadata": {}, + "source": [ + "# Suzuki Trotter\n", + "\n", + "The `suzuki_trotter` function produces the Suzuki-Trotter product for a given order and repetitions.\n", + "\n", + "Function: `suzuki_trotter`\n", + "\n", + "Arguments:\n", + "\n", + "- `pauli_operator`: `CArray[PauliTerm]`\n", + "- `evolution_coefficient`: `CReal`\n", + "- `order`: `CInt`,\n", + "- `repetitions`: `CInt`,\n", + "- `qbv`: `QArray[QBit]`" + ] + }, + { + "cell_type": "markdown", + "id": "e7166188-af15-48c9-96fd-cf4b737e24e5", + "metadata": {}, + "source": [ + "## Example" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "61acbf62-6bd5-4649-a151-6b434915d6ee", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " Pauli,\n", + " PauliTerm,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " qfunc,\n", + " suzuki_trotter,\n", + " synthesize,\n", + " write_qmod,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(qba: Output[QArray[QBit]]):\n", + "\n", + " allocate(3, qba)\n", + " suzuki_trotter(\n", + " [\n", + " PauliTerm(pauli=[Pauli.X, Pauli.X, Pauli.Z], coefficient=\"a\"),\n", + " PauliTerm(pauli=[Pauli.Y, Pauli.X, Pauli.Z], coefficient=0.5),\n", + " ],\n", + " evolution_coefficient=\"x\",\n", + " order=1,\n", + " repetitions=1,\n", + " qbv=qba,\n", + " )\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"suzuki_trotter_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "be631c78-7c6a-4cdf-a968-1a2e6cdefde6", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1] N. Hatano and M. Suzuki, Finding Exponential Product Formulas of Higher Orders, (2005). [https://arxiv.org/abs/math-ph/0506007](https://arxiv.org/abs/math-ph/0506007)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.json b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.json new file mode 100644 index 00000000..8799b411 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Suzuki Trotter", + "description": "Suzuki Trotter Example", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.qmod b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.qmod new file mode 100644 index 00000000..64906a43 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.qmod @@ -0,0 +1,21 @@ +qfunc main(output qba: qbit[]) { + allocate<3>(qba); + suzuki_trotter<[ + PauliTerm { + pauli = [ + Pauli::X, + Pauli::X, + Pauli::Z + ], + coefficient = a + }, + PauliTerm { + pauli = [ + Pauli::Y, + Pauli::X, + Pauli::Z + ], + coefficient = 0.5 + } + ], x, 1, 1>(qba); +} diff --git a/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.synthesis_options.json b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/hamiltonian_evolution/suzuki_trotter/suzuki_trotter_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.ipynb b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.ipynb new file mode 100644 index 00000000..9a1eb9a9 --- /dev/null +++ b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fdc3501d-d0a6-4a6f-a8af-cada198ed978", + "metadata": {}, + "source": [ + "# Linear Pauli Rotations\n", + "\n", + "This function performs a rotation on a series of $m$ target qubits,\n", + "where the rotation angle is a linear function of an $n$-qubit\n", + "control register, as follows:\n", + "\n", + "$$\n", + "\\left|x\\right\\rangle _{n}\\left|q\\right\\rangle\n", + "_{m}\\rightarrow\\left|x\\right\\rangle\n", + "_{n}\\prod_{k=1}^{m}\\left(\\cos\\left(\\frac{a_{k}}{2}x+\\frac{b_{k}}{2}\\right)-\n", + "i\\sin\\left(\\frac{a_{k}}{2}x+\\frac{b_{k}}{2}\\right)P_{k}\\right)\\left|q_{k}\\right\\rangle\n", + "$$\n", + "\n", + "where $\\left|x\\right\\rangle$ is the control register,\n", + "$\\left|q\\right\\rangle$ is the target register, each $P_{k}$ is one of\n", + "the three Pauli matrices $X$, $Y$, or $Z$, and $a_{k}$, $b_{k}$ are\n", + "the user given slopes and offsets, respectively.\n", + "\n", + "For example, the operation of a linear $Y$ rotation on a zero-input\n", + "qubit is\n", + "\n", + "$$\n", + "\\left|x\\right\\rangle _{n}\\left|0\\right\\rangle\n", + "\\rightarrow\\left|x\\right\\rangle _{n}\\left(\n", + "\\cos\\left(\\frac{a}{2}x+\\frac{b}{2}\\right)\\left|0\\right\\rangle\n", + "+\\sin\\left(\\frac{a}{2}x+\\frac{b}{2}\\right)\\left|1\\right\\rangle \\right)\n", + "$$\n", + "\n", + "Such a rotation can be realized as a series of controlled rotations\n", + "as follows:\n", + "\n", + "$$\n", + "\\left[R_{y}\\left(2^{n-1}a\\right)\\right]^{x_{n-1}}\\cdots\n", + "\\left[R_{y}\\left(2^{1}a\\right)\\right]^{x_{1}}\n", + "\\left[R_{y}\\left(2^{0}a\\right)\\right]^{x_{0}}R_{y}\\left(b\\right)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "819091bc-5d90-476d-b855-ce0b5213a8c7", + "metadata": {}, + "source": [ + "Function: `linear_pauli_rotations`\n", + "\n", + "Arguments:\n", + "\n", + "- `bases: QParam[List[int]]` - List of Pauli Enums.\n", + "- `slopes: QParam[List[float]]` - Rotation slopes for each of the given Pauli bases.\n", + "- `offsets: QParam[List[float]]` - Rotation offsets for each of the given Pauli bases.\n", + "- `x: QArray[QBit]` - Quantum state to apply the rotation based on its value.\n", + "- `q: QArray[QBit]` - List of indicator qubits for each of the given Pauli bases.\n", + "\n", + "Notice that `bases`, `slopes`, `offset` and `q` should be of the same size." + ] + }, + { + "cell_type": "markdown", + "id": "20f84a5c-2973-4610-a87c-6c30c77c00bc", + "metadata": {}, + "source": [ + "## Example: Three Y Rotations Controlled by a 6-qubit State\n", + "\n", + "This example generates a quantum program with a $6$-qubit control\n", + "state and $3$ target qubits, acted upon by Y rotations with different slopes and offsets." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "4a73e45a-d2b7-491a-b334-73f56e23ef8f", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " Pauli,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " linear_pauli_rotations,\n", + " qfunc,\n", + ")\n", + "\n", + "NUM_STATE_QUBITS = 6\n", + "BASES = [Pauli.Y.value] * 3\n", + "OFFSETS = [0.1, 0.3, 0.33]\n", + "SLOPES = [2.1, 1, 7.0]\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]], ind: Output[QArray[QBit]]):\n", + " allocate(NUM_STATE_QUBITS, x)\n", + " allocate(len(BASES), ind)\n", + " linear_pauli_rotations(BASES, SLOPES, OFFSETS, x, ind)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "8aae1cc5-2ff5-47d4-abde-340b0f355ff0", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"linear_pauli_rotations_example\")\n", + "qprog = synthesize(qmod)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.json b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.json new file mode 100644 index 00000000..1d3339e5 --- /dev/null +++ b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Linear Pauli Rotations", + "description": "Linear Pauli Rotations", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.qmod b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.qmod new file mode 100644 index 00000000..d4bcb409 --- /dev/null +++ b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.qmod @@ -0,0 +1,5 @@ +qfunc main(output x: qbit[], output ind: qbit[]) { + allocate<6>(x); + allocate<3>(ind); + linear_pauli_rotations<[2, 2, 2], [2.1, 1, 7.0], [0.1, 0.3, 0.33]>(x, ind); +} diff --git a/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.synthesis_options.json b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/linear_pauli_rotations/linear_pauli_rotations_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/mcx/mcx_example.ipynb b/functions/function_usage_examples/mcx/mcx_example.ipynb new file mode 100644 index 00000000..87ed8fc2 --- /dev/null +++ b/functions/function_usage_examples/mcx/mcx_example.ipynb @@ -0,0 +1,134 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6ad831b3-2025-4789-a8bc-b27dcd531fa5", + "metadata": {}, + "source": [ + "# Multi-Control-X\n", + "\n", + "The multi-control-X applies X gate to one target qubit bit only if the logical AND of all control qubits is satisfied.\n", + "The multi-control-X function incorporates numerous implementations for the multi-control-X gate,\n", + "each with a different depth and number of auxiliary qubits.\n", + "These implementations generically outperform the Gray-code, V-chain and recursive implementations of Ref. [[1]](#1),\n", + "as well as the relative-phase Toffoli implementation of Ref. [[2]](#2).\n", + "Given a sufficient number of auxiliary qubits, some implementations allow for logarithmic depth and linear CX-count.\n", + "The synthesis process selects the appropriate implementation depending on the defined constraints." + ] + }, + { + "cell_type": "markdown", + "id": "5c849116-e74a-4249-9c54-8f163e3d7a55", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Operator: `control`\n", + "\n", + "Arguments:\n", + "\n", + "- `ctrl: Union[QBit, QArray[QBit]]`\n", + "- `operand: QCallable`\n", + " \n", + "\n", + "Operator `control` takes a qubit array of length one or more as `ctrl`, and applies the `operand` if all qubits are in the `1` state \n" + ] + }, + { + "cell_type": "markdown", + "id": "b3ce5912-c51f-4605-ae2d-02edb109565d", + "metadata": {}, + "source": [ + "## Example\n", + "\n", + "The following example shows how to use the `control` operator to implement a Multi-Control-X where a 7-qubit quantum variable serves as the control" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "9629ac10-0774-4140-a207-f210d3cfe4b3", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " X,\n", + " allocate,\n", + " control,\n", + " create_model,\n", + " prepare_bell_state,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(cntrl: Output[QArray[QBit]], target: Output[QBit]) -> None:\n", + " allocate(7, cntrl)\n", + " allocate(1, target)\n", + " control(ctrl=cntrl, operand=lambda: X(target))" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "58821271-3a15-4001-bbfc-740eaa604791", + "metadata": {}, + "outputs": [], + "source": [ + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "397278e2-68d5-4677-9f14-b5c3e13a7224", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"mcx_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "d0df544d-9cba-44ec-9bdd-df8b9f0aaaa4", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1] A. Barenco et al, Elementary gates for quantum computation,\n", + "Phys. Rev. A 52 (1995). https://journals.aps.org/pra/abstract/10.1103/PhysRevA.52.3457\n", + "\n", + "[2] D. Maslov, Advantages of using relative-phase Toffoli gates\n", + "with an application to multiple control Toffoli optimization,\n", + "Phys. Rev. A 93 (2016). https://journals.aps.org/pra/abstract/10.1103/PhysRevA.93.022311" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dev_py3.11", + "language": "python", + "name": "dev_py3.11" + }, + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/mcx/mcx_example.json b/functions/function_usage_examples/mcx/mcx_example.json new file mode 100644 index 00000000..41bc23be --- /dev/null +++ b/functions/function_usage_examples/mcx/mcx_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Multi-Control-X", + "description": "Multi-Control-X using the control operator", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/mcx/mcx_example.qmod b/functions/function_usage_examples/mcx/mcx_example.qmod new file mode 100644 index 00000000..67e5b9aa --- /dev/null +++ b/functions/function_usage_examples/mcx/mcx_example.qmod @@ -0,0 +1,7 @@ +qfunc main(output cntrl: qbit[], output target: qbit) { + allocate<7>(cntrl); + allocate<1>(target); + control (cntrl) { + X(target); + } +} diff --git a/functions/function_usage_examples/mcx/mcx_example.synthesis_options.json b/functions/function_usage_examples/mcx/mcx_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/mcx/mcx_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/qft/qft.ipynb b/functions/function_usage_examples/qft/qft.ipynb index ade18c79..f7aa1c0c 100644 --- a/functions/function_usage_examples/qft/qft.ipynb +++ b/functions/function_usage_examples/qft/qft.ipynb @@ -83,7 +83,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/functions/function_usage_examples/qft/qft_usage_example.json b/functions/function_usage_examples/qft/qft_example.json similarity index 100% rename from functions/function_usage_examples/qft/qft_usage_example.json rename to functions/function_usage_examples/qft/qft_example.json diff --git a/functions/function_usage_examples/qft/qft_usage_example.qmod b/functions/function_usage_examples/qft/qft_example.qmod similarity index 100% rename from functions/function_usage_examples/qft/qft_usage_example.qmod rename to functions/function_usage_examples/qft/qft_example.qmod diff --git a/functions/function_usage_examples/qft/qft_example.synthesis_options.json b/functions/function_usage_examples/qft/qft_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/qft/qft_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/qpe/qpe.json b/functions/function_usage_examples/qpe/qpe.json deleted file mode 100644 index 4491a5fe..00000000 --- a/functions/function_usage_examples/qpe/qpe.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Quantum Phase Estimation Function", - "description": "Quantum Phase Estimation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/qpe/qpe.qmod b/functions/function_usage_examples/qpe/qpe.qmod deleted file mode 100644 index 3b965326..00000000 --- a/functions/function_usage_examples/qpe/qpe.qmod +++ /dev/null @@ -1,36 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "XGate", - "function_params": {}, - "outputs": { - "TARGET": "x_qpe" - } - }, - { - "function": "PhaseEstimation", - "function_params": { - "size": 2, - "unitary": "Exponentiation", - "unitary_params": { - "pauli_operator": { - "pauli_list": [ - ["ZI", -0.125], - ["IZ", -0.25], - ["II", 0.375] - ] - }, - "evolution_coefficient": -6.283185307179586 - } - }, - "inputs": { - "IN[0]": "x_qpe" - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/qpe/qpe_custom_function.json b/functions/function_usage_examples/qpe/qpe_custom_function.json deleted file mode 100644 index 04997f8b..00000000 --- a/functions/function_usage_examples/qpe/qpe_custom_function.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Quantum Phase Estimation: Custom Function", - "description": "Quantum Phase Estimation With A Custom Function", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/qpe/qpe_custom_function.qmod b/functions/function_usage_examples/qpe/qpe_custom_function.qmod deleted file mode 100644 index 38e6f8b1..00000000 --- a/functions/function_usage_examples/qpe/qpe_custom_function.qmod +++ /dev/null @@ -1,32 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "PhaseEstimation", - "function_params": { - "unitary": "my_custom_function", - "unitary_params": { - "input_decls": {"custom_input": {"size": 1}}, - "output_decls": {"custom_output": {"size": 1}} - }, - "size": 2 - } - } - ] - }, - { - "name": "my_custom_function", - "implementations": [ - { - "serialized_circuit": "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[1];\nh q[0];" - } - ], - "register_mapping": { - "output_registers": [{"name": "custom_output", "qubits": [0]}], - "input_registers": [{"name": "custom_input", "qubits": [0]}] - } - } - ] -} diff --git a/functions/function_usage_examples/qpe/qpe_example.ipynb b/functions/function_usage_examples/qpe/qpe_example.ipynb new file mode 100644 index 00000000..bb5e0c50 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_example.ipynb @@ -0,0 +1,299 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1bd7cdd6-f48d-4100-ba04-18da2eca556b", + "metadata": {}, + "source": [ + "# Quantum Phase Estimation\n", + "\n", + "The quantum phase estimation (QPE) function estimates the phase of an eigenvector of a unitary function.\n", + "More precisely, given a unitary function $F$ and an input containing a quantum variable with a state $|\\psi\\rangle$ such that $F(|\\psi\\rangle)=e^{2\\pi i\\nu}|\\psi\\rangle$,\n", + "the phase estimation function outputs an estimation of $\\nu$ as a fixed-point binary number.\n", + "\n", + "Phase estimation is frequently used as a subroutine in other quantum algorithms such as Shor's algorithm and quantum algorithms for solving linear systems of equations (HHL algorithm).\n", + "Theoretical details are in Ref. [[1]](#1)." + ] + }, + { + "cell_type": "markdown", + "id": "eeb1258a-e060-46ec-adf3-6db85caaa41c", + "metadata": {}, + "source": [ + "Function: `qpe`\n", + "\n", + "Arguments:\n", + "\n", + "- `unitary: QCallable` - The unitary operation for which the qpe estimation the eigenvalues\n", + "- `phase: QNum` - The output of the qpe, holding the phase as a number in the range $[0, 1)$\n", + "\n", + "Function: `qpe_flexible`\n", + "\n", + "The function is suitalbe when wants to specialize the way the power of a unitary is defined, other than using the naive power. For example it can used with exponentiaing hamiltonians or for shor's algorithm.\n", + "\n", + "Arguments:\n", + "\n", + "- `unitary_with_power: QCallable[QParam[int]]` - Power of a unitary. Accepts as argument the power of the unitary to apply.\n", + "- `phase: QNum`" + ] + }, + { + "cell_type": "markdown", + "id": "8814160e-d3ea-437c-be04-101572c0ebb1", + "metadata": {}, + "source": [ + "## Examples\n", + "\n", + "### Example 1: QPE of a function\n", + "\n", + "This example shows how to perform a simple phase estimation:\n", + "\n", + "1. Initialize the state $|3\\rangle$ over two qubits.\n", + "2. Apply a phase estimation on the the controlled-RZ gate, represeneted by the unitary matrix:\n", + "\n", + "$$\n", + "\\begin{pmatrix}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & e^{-i\\frac{\\lambda}{2}} & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 0 & 0 & e^{i\\frac{\\lambda}{2}}\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "The expected phase variable should encode $\\frac{\\lambda}{4\\pi}$, the phase of the eigenvalue of the $|3\\rangle$ state.\n", + "Choosing $\\lambda = \\pi$, the expected result is $\\frac{1}{4}$, represented in binary by `01`." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "bed3f9b5-5b1b-4602-aea5-711dd1a9c43b", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " CRZ,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " allocate_num,\n", + " create_model,\n", + " inplace_prepare_int,\n", + " qfunc,\n", + " qpe,\n", + ")\n", + "from classiq.qmod.symbolic import pi\n", + "\n", + "QPE_RESOLUTION = 2\n", + "\n", + "\n", + "@qfunc\n", + "def main(state: Output[QArray[QBit]], phase: Output[QNum]):\n", + " allocate(2, state)\n", + " allocate_num(QPE_RESOLUTION, 0, QPE_RESOLUTION, phase)\n", + "\n", + " inplace_prepare_int(3, state)\n", + " qpe(unitary=lambda: CRZ(pi, state[0], state[1]), phase=phase)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "2974e928-0a4f-495d-9bc5-f7d908b7e84f", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"qpe_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "94c28c4f-9065-45c9-8020-a682c8fae00c", + "metadata": {}, + "source": [ + "Show the actual results:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "359b2840-0149-4c74-9748-b4fbb2728367", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results: [{'state': 3.0, 'phase': 0.25}: 1000]\n" + ] + } + ], + "source": [ + "from classiq import execute\n", + "\n", + "res = execute(qprog).result()[0].value\n", + "print(\"Results:\", res.parsed_counts)" + ] + }, + { + "cell_type": "markdown", + "id": "050e47b8-65e0-4acc-8ed2-f1365dc734a7", + "metadata": {}, + "source": [ + "### Example 2: Flexible QPE\n", + "\n", + "The following examples will specifiy directly how to take powers in the QPE. The unitary function is `suzuki_trotter`, where the number of repetitions will be 1. In the case of diagonal hamiltonian it be exact exponentiation of the hamiltoian.\n", + "\n", + "Take the following matrix:\n", + "$$\n", + "\\begin{pmatrix}\n", + "0 & 0 & 0 & 0 \\\\\n", + "0 & \\tfrac{1}{4} & 0 & 0 \\\\\n", + "0 & 0 & \\tfrac{1}{2} & 0 \\\\\n", + "0 & 0 & 0 & \\tfrac{3}{4} \\\\\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "Represented by the hamiltonian:\n", + "\n", + "$H = -\\frac{1}{8}Z_0I_1 - \\frac{1}{4}I_0Z_1 + \\frac{3}{8}I_0I_1$" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "2202730d-c9ca-475e-8e15-b66c96c11f9c", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " Pauli,\n", + " PauliTerm,\n", + " QArray,\n", + " QBit,\n", + " QNum,\n", + " allocate,\n", + " allocate_num,\n", + " create_model,\n", + " hadamard_transform,\n", + " qfunc,\n", + " qpe_flexible,\n", + " suzuki_trotter,\n", + ")\n", + "from classiq.qmod.symbolic import pi\n", + "\n", + "QPE_RESOLUTION = 2\n", + "\n", + "HAMILTONIAN = [\n", + " PauliTerm(pauli=[Pauli.I, Pauli.Z], coefficient=-0.125),\n", + " PauliTerm(pauli=[Pauli.Z, Pauli.I], coefficient=-0.25),\n", + " PauliTerm(pauli=[Pauli.I, Pauli.I], coefficient=0.375),\n", + "]\n", + "\n", + "\n", + "@qfunc\n", + "def main(state: Output[QArray[QBit]], phase: Output[QNum]):\n", + " allocate(2, state)\n", + " allocate_num(QPE_RESOLUTION, 0, QPE_RESOLUTION, phase)\n", + "\n", + " hadamard_transform(state)\n", + " qpe_flexible(\n", + " lambda power: suzuki_trotter(\n", + " HAMILTONIAN,\n", + " evolution_coefficient=-2 * pi * (power),\n", + " order=1,\n", + " repetitions=1,\n", + " qbv=state,\n", + " ),\n", + " phase,\n", + " )\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "811cf6c4-9bb1-433b-9291-69148013b2d3", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"qpe_flexible_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "0b0a0eee-d1ac-489e-927c-7731bc9ef4a2", + "metadata": {}, + "source": [ + "Show the actual results:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e97a50fd-6080-47f5-b522-f4ce6bfeb503", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Results: [{'state': 3.0, 'phase': 0.75}: 257, {'state': 2.0, 'phase': 0.5}: 256, {'state': 1.0, 'phase': 0.25}: 250, {'state': 0.0, 'phase': 0.0}: 237]\n" + ] + } + ], + "source": [ + "from classiq import execute\n", + "\n", + "res = execute(qprog).result()[0].value\n", + "print(\"Results:\", res.parsed_counts)" + ] + }, + { + "cell_type": "markdown", + "id": "611fa4cb-eb30-41d0-8fbd-a6f1475ebc64", + "metadata": {}, + "source": [ + "## References\n", + "\n", + "[1] A. Yu. Kitaev Barenco et al, Quantum Measurements and the Abelian Stabilizer Problem,\n", + "(1995). https://doi.org/10.48550/arXiv.quant-ph/9511026" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/qpe/qpe_example.json b/functions/function_usage_examples/qpe/qpe_example.json new file mode 100644 index 00000000..790938ec --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Quantum Phase Estimation (QPE)", + "description": "Quantum Phase Estimation (QPE)", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/qpe/qpe_example.qmod b/functions/function_usage_examples/qpe/qpe_example.qmod new file mode 100644 index 00000000..37b51848 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_example.qmod @@ -0,0 +1,8 @@ +qfunc main(output state: qbit[], output phase: qnum) { + allocate<2>(state); + allocate_num<2, 0, 2>(phase); + inplace_prepare_int<3>(state); + qpe(state[0], state[1]); + }>(phase); +} diff --git a/functions/function_usage_examples/qpe/qpe_example.synthesis_options.json b/functions/function_usage_examples/qpe/qpe_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/qpe/qpe_flexible_example.json b/functions/function_usage_examples/qpe/qpe_flexible_example.json new file mode 100644 index 00000000..990da6c1 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_flexible_example.json @@ -0,0 +1,6 @@ +{ + "friendly_name": "Flexible Quantum Phase Estimation (QPE)", + "description": "Flexible Quantum Phase Estimation (QPE)", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/qpe/qpe_flexible_example.qmod b/functions/function_usage_examples/qpe/qpe_flexible_example.qmod new file mode 100644 index 00000000..953fc4e7 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_flexible_example.qmod @@ -0,0 +1,21 @@ +qfunc main(output state: qbit[], output phase: qnum) { + allocate<2>(state); + allocate_num<2, 0, 2>(phase); + hadamard_transform(state); + qpe_flexible() { + suzuki_trotter<[ + PauliTerm { + pauli = [Pauli::I, Pauli::Z], + coefficient = -0.125 + }, + PauliTerm { + pauli = [Pauli::Z, Pauli::I], + coefficient = -0.25 + }, + PauliTerm { + pauli = [Pauli::I, Pauli::I], + coefficient = 0.375 + } + ], ((-2) * pi) * power, 1, 1>(state); + }>(phase); +} diff --git a/functions/function_usage_examples/qpe/qpe_flexible_example.synthesis_options.json b/functions/function_usage_examples/qpe/qpe_flexible_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/qpe/qpe_flexible_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/CRX_example.json b/functions/function_usage_examples/standard_gates/CRX_example.json new file mode 100644 index 00000000..f230f881 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CRX_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "CRX Gate", + "description": "CRX Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/CRX_example.qmod b/functions/function_usage_examples/standard_gates/CRX_example.qmod new file mode 100644 index 00000000..369ca959 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CRX_example.qmod @@ -0,0 +1,7 @@ +qfunc main() { + q_t: qbit; + allocate<1>(q_t); + q_c: qbit; + allocate<1>(q_c); + CRX<1>(q_c, q_t); +} diff --git a/functions/function_usage_examples/standard_gates/CRX_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/CRX_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CRX_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/CX_example.json b/functions/function_usage_examples/standard_gates/CX_example.json new file mode 100644 index 00000000..29d98cf2 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CX_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "CX Gate", + "description": "CX Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/CX_example.qmod b/functions/function_usage_examples/standard_gates/CX_example.qmod new file mode 100644 index 00000000..76b5e247 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CX_example.qmod @@ -0,0 +1,7 @@ +qfunc main() { + q_t: qbit; + allocate<1>(q_t); + q_c: qbit; + allocate<1>(q_c); + CX(q_c, q_t); +} diff --git a/functions/function_usage_examples/standard_gates/CX_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/CX_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/CX_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/PHASE_example.json b/functions/function_usage_examples/standard_gates/PHASE_example.json new file mode 100644 index 00000000..b0814c42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/PHASE_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Phase Gate", + "description": "Phase Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/PHASE_example.qmod b/functions/function_usage_examples/standard_gates/PHASE_example.qmod new file mode 100644 index 00000000..83221229 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/PHASE_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit; + allocate<1>(q); + PHASE<1>(q); +} diff --git a/functions/function_usage_examples/standard_gates/PHASE_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/PHASE_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/PHASE_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/RZZ_example.json b/functions/function_usage_examples/standard_gates/RZZ_example.json new file mode 100644 index 00000000..ee83d3a2 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZZ_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "RZZ Gate", + "description": "RZZ Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/RZZ_example.qmod b/functions/function_usage_examples/standard_gates/RZZ_example.qmod new file mode 100644 index 00000000..fc939b49 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZZ_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit[]; + allocate<2>(q); + RZZ<1>(q); +} diff --git a/functions/function_usage_examples/standard_gates/RZZ_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/RZZ_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZZ_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/RZ_example.json b/functions/function_usage_examples/standard_gates/RZ_example.json new file mode 100644 index 00000000..10b2ed86 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZ_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "RZ Gate", + "description": "RZ Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/RZ_example.qmod b/functions/function_usage_examples/standard_gates/RZ_example.qmod new file mode 100644 index 00000000..5e63bcdd --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZ_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit; + allocate<1>(q); + RZ<1.9>(q); +} diff --git a/functions/function_usage_examples/standard_gates/RZ_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/RZ_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/RZ_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/R_example.json b/functions/function_usage_examples/standard_gates/R_example.json new file mode 100644 index 00000000..45215ae6 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/R_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "R Gate", + "description": "R Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/R_example.qmod b/functions/function_usage_examples/standard_gates/R_example.qmod new file mode 100644 index 00000000..00672c4a --- /dev/null +++ b/functions/function_usage_examples/standard_gates/R_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit; + allocate<1>(q); + R<1, 2>(q); +} diff --git a/functions/function_usage_examples/standard_gates/R_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/R_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/R_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/SWAP_example.json b/functions/function_usage_examples/standard_gates/SWAP_example.json new file mode 100644 index 00000000..1f077601 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/SWAP_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "SWAP Gate", + "description": "SWAP Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/SWAP_example.qmod b/functions/function_usage_examples/standard_gates/SWAP_example.qmod new file mode 100644 index 00000000..db16df14 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/SWAP_example.qmod @@ -0,0 +1,7 @@ +qfunc main() { + q1: qbit; + allocate<1>(q1); + q2: qbit; + allocate<1>(q2); + SWAP(q1, q2); +} diff --git a/functions/function_usage_examples/standard_gates/SWAP_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/SWAP_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/SWAP_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/U_example.json b/functions/function_usage_examples/standard_gates/U_example.json new file mode 100644 index 00000000..7d4210f9 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/U_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "U Gate", + "description": "U Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/U_example.qmod b/functions/function_usage_examples/standard_gates/U_example.qmod new file mode 100644 index 00000000..63832ef0 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/U_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit; + allocate<1>(q); + U<1, 2, 1.5, 1.1>(q); +} diff --git a/functions/function_usage_examples/standard_gates/U_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/U_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/U_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/X_example.json b/functions/function_usage_examples/standard_gates/X_example.json new file mode 100644 index 00000000..f4fcce54 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/X_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "X Gate", + "description": "X Gate", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/standard_gates/X_example.qmod b/functions/function_usage_examples/standard_gates/X_example.qmod new file mode 100644 index 00000000..89f9ab98 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/X_example.qmod @@ -0,0 +1,5 @@ +qfunc main() { + q: qbit; + allocate<1>(q); + X(q); +} diff --git a/functions/function_usage_examples/standard_gates/X_example.synthesis_options.json b/functions/function_usage_examples/standard_gates/X_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/standard_gates/X_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/standard_gates/standard_gates_example.ipynb b/functions/function_usage_examples/standard_gates/standard_gates_example.ipynb new file mode 100644 index 00000000..a975c47c --- /dev/null +++ b/functions/function_usage_examples/standard_gates/standard_gates_example.ipynb @@ -0,0 +1,520 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "528f1eb6-271f-48be-b0fb-5820ca21c5d6", + "metadata": {}, + "source": [ + "# Standard Gates\n", + "\n", + "The Classiq platform provides many standard gates.\n", + "Some key standard gates are shown here in detail.
\n", + "All gates are covered in the [reference manual](https://docs.classiq.io/latest/reference-manual/python-sdk/#classiq.interface.generator.standard_gates)." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "60fe7e57-d4e7-4c03-9104-ed3cec1177ab", + "metadata": {}, + "outputs": [], + "source": [ + "# Generic imports\n", + "from classiq import QArray, QBit, allocate, create_model, qfunc, synthesize, write_qmod" + ] + }, + { + "cell_type": "markdown", + "id": "f3298ff3-c891-475b-acef-e581b5252f70", + "metadata": {}, + "source": [ + "## Single Qubit Gates\n", + "\n", + "An example is given for $X$ gate. The gates $I$, $X$, $Y$, $Z$, $H$, $T$ are used in the same way." + ] + }, + { + "cell_type": "markdown", + "id": "e201bfba-7656-47a5-9f3d-5d479383b917", + "metadata": {}, + "source": [ + "### For example: X\n", + "Function: `X`\n", + "\n", + "Arguments:\n", + "\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "26931e36-bb1a-4003-9d8e-c6533bfacc9a", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import X\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QBit(\"q\")\n", + " allocate(1, q)\n", + "\n", + " X(q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"X_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "7b246605-e907-485f-8e03-3835180564ca", + "metadata": {}, + "source": [ + "## Single Qubit Rotation Gates\n", + "\n", + "An example is given for $RZ$ gate. The gates $RX$, $RY$, $RZ$ are used in the same way except for parameter name.\n", + "\n", + "#### Parameter names for different rotation gates\n", + "\n", + "- `RX`: `theta`\n", + "- `RY`: `theta`\n", + "- `RZ`: `phi`" + ] + }, + { + "cell_type": "markdown", + "id": "fcad9460-e221-4d53-85e6-dac9f9397897", + "metadata": {}, + "source": [ + "### For example: RZ\n", + "\n", + "$$\n", + "\\begin{split}RZ(\\theta) = \\begin{pmatrix}\n", + "{e^{-i\\frac{\\theta}{2}}} & 0 \\\\\n", + "0 & {e^{i\\frac{\\theta}{2}}} \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "Function: `RZ`\n", + "\n", + "Arguments:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "c93cd414-9cac-4221-90b1-0b7b5e375ca4", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import RZ\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QBit(\"q\")\n", + " allocate(1, q)\n", + "\n", + " theta = 1.9\n", + " RZ(theta, q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"RZ_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "db881855-1856-44bb-a9b6-14d5c0a300d8", + "metadata": {}, + "source": [ + "### R Gate\n", + "\n", + "Rotation by $\\theta$ around the $cos(\\phi)X + sin(\\phi)Y$ axis.\n", + "\n", + "$$\n", + "\\begin{split}R(\\theta, \\phi) = \\begin{pmatrix}\n", + "cos(\\frac{\\theta}{2}) & -ie^{-i\\phi}sin(\\frac{\\theta}{2}) \\\\\n", + "-ie^{i\\phi}sin(\\frac{\\theta}{2}) & cos(\\frac{\\theta}{2}) \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "Parameters:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `phi`: `QParam[float]`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "e091727f-901d-4ff0-8e8b-420825aedfc5", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import R\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QBit(\"q\")\n", + " allocate(1, q)\n", + "\n", + " theta = 1\n", + " phi = 2\n", + " R(theta, phi, q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"R_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "06c0c63b-ea3c-43b1-adcf-4a84117f5929", + "metadata": {}, + "source": [ + "### Phase Gate\n", + "\n", + "Rotation about the Z axis by $\\lambda$ with global phase of $\\frac{\\lambda}{2}$.\n", + "\n", + "$$\n", + "\\begin{split}X = \\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\lambda} \\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "Parameters:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "6e7396cd-28a0-4dec-83ea-2a06817b2749", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import PHASE\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QBit(\"q\")\n", + " allocate(1, q)\n", + "\n", + " theta = 1\n", + " PHASE(theta, q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"PHASE_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "355c2ca8-5c60-4d28-a825-e3fdca3ec60a", + "metadata": {}, + "source": [ + "## Double Qubits Rotation Gates\n", + "\n", + "An example is given for $RZZ$ gate. The gates $RXX$, $RYY$, $RZZ$ are used in the same way.\n", + "\n", + "### RZZ Gate\n", + "\n", + "Rotation about ZZ.\n", + "\n", + "$$\n", + "\\begin{split}RZZ(\\theta) = \\begin{pmatrix}\n", + "{e^{-i\\frac{\\theta}{2}}} & 0 & 0 & 0 \\\\\n", + "0 & {e^{i\\frac{\\theta}{2}}} & 0 & 0 \\\\\n", + "0 & 0 & {e^{i\\frac{\\theta}{2}}} & 0 \\\\\n", + "0 & 0 & 0 & {e^{-i\\frac{\\theta}{2}}} \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "\n", + "Parameters:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `target`: `QArray[QBit]`" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "8e1afacc-ea99-4bbe-8cdc-a9aee51d58ca", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import RZZ\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QArray(\"q\")\n", + " allocate(2, q)\n", + "\n", + " theta = 1\n", + " RZZ(theta, q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"RZZ_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "75bea4e9-7195-4a9c-a5bc-5fd43193220a", + "metadata": {}, + "source": [ + "## Controlled Gates\n", + "\n", + "An example is given for $CX$ gate. The gates $CX$, $CY$, $CZ$, $CH$, $CSX$, $CCX$ are used in a similar way.\n", + "\n", + "In $CCX$ Gate the `ctrl_state` parameter receives a value suitable for 2 control qubits. for example: `\"01\"`.\n", + "\n", + "### CX Gate\n", + "\n", + "The Controlled $X$ gate.\n", + "\n", + "Applies $X$ Gate on the target qubit, based on the state of the control qubit\n", + "(by default if the controlled state is $|1\\rangle$).\n", + "\n", + "$$\n", + "\\begin{split}CX = \\begin{pmatrix}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "\n", + "Parameters:\n", + "\n", + "- `control`: `QBit`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "db26e697-0c46-42ac-977e-4f1e5525486e", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import CX\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q_target = QBit(\"q_t\")\n", + " allocate(1, q_target)\n", + "\n", + " q_control = QBit(\"q_c\")\n", + " allocate(1, q_control)\n", + "\n", + " CX(q_control, q_target)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"CX_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "d6509986-4f44-4481-b88e-e05b6f19b048", + "metadata": {}, + "source": [ + "## Controlled Rotations\n", + "\n", + "An example is given for $CRX$ gate. The gates $CRX$, $CRY$, $CRZ$, CPhase are used in the same way.\n", + "\n", + "### CRX Gate\n", + "\n", + "Controlled rotation around the X axis.\n", + "\n", + "$$\n", + "\\begin{split}CRX(\\theta) = \\begin{pmatrix}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & \\cos(\\frac{\\theta}{2}) & -i\\sin(\\frac{\\theta}{2}) \\\\\n", + "0 & 0 & -i\\sin(\\frac{\\theta}{2}) & \\cos(\\frac{\\theta}{2}) \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "Parameters:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `control`: `QBit`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "a362c33c-06d3-476e-9e4f-adbec2763977", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import CRX\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q_target = QBit(\"q_t\")\n", + " allocate(1, q_target)\n", + "\n", + " q_control = QBit(\"q_c\")\n", + " allocate(1, q_control)\n", + "\n", + " theta = 1\n", + " CRX(theta, q_control, q_target)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"CRX_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "bed9783a-1469-423e-8ed5-e51de881e036", + "metadata": {}, + "source": [ + "## Swap Gate\n", + "\n", + "Swaps between two qubit states.\n", + "\n", + "$$\n", + "\\begin{split}SWAP = \\begin{pmatrix}\n", + "1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 \\\\\n", + "0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 \\\\\n", + "\\end{pmatrix}\\end{split}\n", + "$$\n", + "\n", + "Parameters:\n", + "\n", + "- `qbit0`: `QBit`\n", + "- `qbit1`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "10bf72bc-603d-4a63-9463-82fe91936e89", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import SWAP\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q1 = QBit(\"q1\")\n", + " allocate(1, q1)\n", + "\n", + " q2 = QBit(\"q2\")\n", + " allocate(1, q2)\n", + "\n", + " SWAP(q1, q2)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"SWAP_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "82d75454-20cb-4ad8-a025-600501867a84", + "metadata": {}, + "source": [ + "## U Gate\n", + "\n", + "The single-qubit gate applies phase and rotation with three Euler angles.\n", + "\n", + "Matrix representation:\n", + "\n", + "$$\n", + "U(\\gamma,\\phi,\\theta,\\lambda) = e^{i\\gamma}\\begin{pmatrix}\n", + "\\cos(\\frac{\\theta}{2}) & -e^{i\\lambda}\\sin(\\frac{\\theta}{2}) \\\\\n", + "e^{i\\phi}\\sin(\\frac{\\theta}{2}) & e^{i(\\phi+\\lambda)}\\cos(\\frac{\\theta}{2}) \\\\\n", + "\\end{pmatrix}\n", + "$$\n", + "\n", + "Parameters:\n", + "\n", + "- `theta`: `QParam[float]`\n", + "- `phi`: `QParam[float]`\n", + "- `lam`: `QParam[float]`\n", + "- `gam`: `QParam[float]`\n", + "- `target`: `QBit`" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "654f9ae6-5bc0-43cd-bbc3-475ae8aa96ca", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import U\n", + "\n", + "\n", + "@qfunc\n", + "def main():\n", + " q = QBit(\"q\")\n", + " allocate(1, q)\n", + "\n", + " theta = 1\n", + " phi = 2\n", + " lam = 1.5\n", + " gam = 1.1\n", + " U(theta, phi, lam, gam, q)\n", + "\n", + "\n", + "qmod = create_model(main)\n", + "write_qmod(qmod, \"U_example\")\n", + "qprog = synthesize(qmod)" + ] + } + ], + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/state_preparation/bell_state_preparation.json b/functions/function_usage_examples/state_preparation/bell_state_preparation.json deleted file mode 100644 index 0f529591..00000000 --- a/functions/function_usage_examples/state_preparation/bell_state_preparation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Bell State Preparation", - "description": "Bell State Preparation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/state_preparation/bell_state_preparation.qmod b/functions/function_usage_examples/state_preparation/bell_state_preparation.qmod deleted file mode 100644 index 0e0d3b50..00000000 --- a/functions/function_usage_examples/state_preparation/bell_state_preparation.qmod +++ /dev/null @@ -1,15 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "BellStatePreparation", - "function_params": { - "name": "phi-" - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/state_preparation/computational_state_preparation.json b/functions/function_usage_examples/state_preparation/computational_state_preparation.json deleted file mode 100644 index 800faaa3..00000000 --- a/functions/function_usage_examples/state_preparation/computational_state_preparation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Computational State Preparation", - "description": "Computational State Preparation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/state_preparation/computational_state_preparation.qmod b/functions/function_usage_examples/state_preparation/computational_state_preparation.qmod deleted file mode 100644 index 172bc5ba..00000000 --- a/functions/function_usage_examples/state_preparation/computational_state_preparation.qmod +++ /dev/null @@ -1,15 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "ComputationalBasisStatePreparation", - "function_params": { - "computational_state": "10011101" - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/state_preparation/exponential_state_preparation.json b/functions/function_usage_examples/state_preparation/exponential_state_preparation.json deleted file mode 100644 index 4ab5a2f7..00000000 --- a/functions/function_usage_examples/state_preparation/exponential_state_preparation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Exponential State Preparation", - "description": "Exponential State Preparation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/state_preparation/exponential_state_preparation.qmod b/functions/function_usage_examples/state_preparation/exponential_state_preparation.qmod deleted file mode 100644 index 58dd968a..00000000 --- a/functions/function_usage_examples/state_preparation/exponential_state_preparation.qmod +++ /dev/null @@ -1,16 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "ExponentialStatePreparation", - "function_params": { - "num_qubits": 5, - "rate": 0.1 - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.json b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.json new file mode 100644 index 00000000..6ce6d03b --- /dev/null +++ b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Inplace Prepare Int", + "description": "Computation Basis State Preparation (Inplace)", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.qmod b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.qmod new file mode 100644 index 00000000..77c26efa --- /dev/null +++ b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output x: qbit[]) { + allocate<5>(x); + inplace_prepare_int<3>(x); +} diff --git a/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/inplace_prepare_int_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.json b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.json new file mode 100644 index 00000000..a23be424 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Prepare Amplitudes", + "description": "State Preparation: Loading Amplitudes", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.qmod b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.qmod new file mode 100644 index 00000000..50b3954d --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.qmod @@ -0,0 +1,12 @@ +qfunc main(output x: qbit[]) { + prepare_amplitudes<[ + (-0.540061724867322), + (-0.38575837490523), + (-0.231455024943138), + (-0.077151674981046), + 0.077151674981046, + 0.231455024943138, + 0.38575837490523, + 0.540061724867322 + ], 0>(x); +} diff --git a/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_amplitudes_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.ipynb b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.ipynb index 298d5c15..8ec7f3e3 100644 --- a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.ipynb +++ b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.ipynb @@ -35,7 +35,7 @@ "\n", "Arguments:\n", "\n", - "- `state_num: QParam[int]`\n", + "- `state_num: CInt`\n", "- `q: Output[QArray[QBit]]`" ] }, @@ -56,17 +56,17 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 25, "id": "e5c0df9f-8cc8-4fef-b9e4-44e26a40af34", "metadata": {}, "outputs": [], "source": [ - "from classiq import Output, QArray, QBit, prepare_bell_state, create_model, qfunc\n", + "from classiq import Output, QArray, QBit, create_model, prepare_bell_state, qfunc\n", "\n", "\n", "@qfunc\n", "def main(x: Output[QArray[QBit]]):\n", - " prepare_bell_state(2,x)\n", + " prepare_bell_state(2, x)\n", "\n", "\n", "qmod = create_model(main)" @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 26, "id": "ca1341a7-5465-4ff2-b037-7c6bf1f5a06e", "metadata": {}, "outputs": [], @@ -88,9 +88,9 @@ ], "metadata": { "kernelspec": { - "display_name": "prod_py3.11", + "display_name": "dev_py3.11", "language": "python", - "name": "prod_py3.11" + "name": "dev_py3.11" }, "language_info": { "codemirror_mode": { diff --git a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.json b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.json index d529b940..8bb2b19c 100644 --- a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.json +++ b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.json @@ -1,6 +1,6 @@ { - "friendly_name": "Prepare Bell State", - "description": "Prepare Bell State example", - "qmod_type": ["function"], - "level": ["demos", "basic"] - } \ No newline at end of file + "friendly_name": "Prepare Bell State", + "description": "Prepare Bell State example", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.qmod b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.qmod index a1d34165..5c99f274 100644 --- a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.qmod +++ b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.qmod @@ -1,4 +1,3 @@ qfunc main(output x: qbit[]) { prepare_bell_state<2>(x); } - diff --git a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.synthesis_options.json index 9e26dfee..0967ef42 100644 --- a/functions/function_usage_examples/state_preparation/prepare_bell_state_example.synthesis_options.json +++ b/functions/function_usage_examples/state_preparation/prepare_bell_state_example.synthesis_options.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.ipynb b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.ipynb new file mode 100644 index 00000000..054adce2 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b9238b75-f1ea-4e1f-bbea-757346913a15", + "metadata": {}, + "source": [ + "# Exponential State Preparation\n", + "\n", + "The `prepare_exponential_state` function\n", + "creates a state with exponentially decreasing amplitudes. Namely,\n", + "the probability for a state representing an integer $n$ is\n", + "\n", + "$$\n", + "P\\left(n\\right) = \\frac{1}{Z} e^{-\\lambda n}\n", + "$$\n", + "\n", + "where $\\lambda$ is the rate, and $Z$ is a normalization factor.\n", + "If $q$ in the number of qubits, then\n", + "\n", + "$$\n", + "Z = \\sum_{n=0} ^{n = 2^q - 1} e^{-\\lambda n} = \\frac{1 - e^{-\\lambda 2^q}}{1 - e^{-\\lambda}}\n", + "$$\n", + "\n", + "Function: `prepare_exponential_state`\n", + "\n", + "Arguments:\n", + "\n", + "- `rate: CReal`\n", + "- `q: QArray[QBit]`\n", + "\n", + "Notice that the function acts inplace on the qubits." + ] + }, + { + "cell_type": "markdown", + "id": "eb5136ac-470c-445b-9de6-e9ac856249b9", + "metadata": {}, + "source": [ + "## Example\n", + "\n", + "Prepare a state with probabilities:\n", + "$$\n", + "P\\left(n\\right) = \\frac{1}{Z} e^{-0.1 n}\n", + "$$\n", + "where $n$ is in the range $[0, 31]$." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5752cf71-1d39-4b37-88de-0acf42ade6be", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " prepare_exponential_state,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + " allocate(5, x)\n", + " prepare_exponential_state(0.1, x)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "cf36a83d-8054-47db-aa31-ab4fec59c5af", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"prepare_exponential_state_example\")\n", + "qprog = synthesize(qmod)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.json b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.json new file mode 100644 index 00000000..60c90900 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Prepare Exponential State", + "description": "Prepare Exponential State", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.qmod b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.qmod new file mode 100644 index 00000000..7b7f2210 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.qmod @@ -0,0 +1,4 @@ +qfunc main(output x: qbit[]) { + allocate<5>(x); + prepare_exponential_state<0.1>(x); +} diff --git a/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_exponential_state_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.ipynb b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.ipynb index a367537d..7287c130 100644 --- a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.ipynb +++ b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.ipynb @@ -5,7 +5,7 @@ "id": "1412827c-808e-4e57-9079-4125d38457c2", "metadata": {}, "source": [ - "# Prepare GHZ State " + "# GHZ State Preparation" ] }, { @@ -14,7 +14,7 @@ "metadata": {}, "source": [ "Use the `prepare_ghz_state` function to create a Greenberger-Horne-Zeilinger (GHZ) state.\n", - "i.e., a balanced superposition of all ones and all zeros, on an arbitrary number of qubits (three by default)." + "i.e., a balanced superposition of all ones and all zeros, on an arbitrary number of qubits." ] }, { @@ -34,7 +34,7 @@ "\n", "Arguments:\n", "\n", - "- `size: QParam[int]`\n", + "- `size: CInt`\n", "- `q: Output[QArray[QBit]]`" ] }, @@ -54,12 +54,12 @@ "metadata": {}, "outputs": [], "source": [ - "from classiq import Output, QArray, QBit, prepare_ghz_state, create_model, qfunc\n", + "from classiq import Output, QArray, QBit, create_model, prepare_ghz_state, qfunc\n", "\n", "\n", "@qfunc\n", "def main(x: Output[QArray[QBit]]):\n", - " prepare_ghz_state(5,x)\n", + " prepare_ghz_state(5, x)\n", "\n", "\n", "qmod = create_model(main)" @@ -67,7 +67,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "id": "ffe08c9b-ca87-49d9-bac6-b0a59157e798", "metadata": {}, "outputs": [], @@ -77,40 +77,13 @@ "write_qmod(qmod, \"prepare_ghz_state_example\")\n", "qprog = synthesize(qmod)" ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5f3fe6c2-ab49-4016-95ba-ec85e65d635a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Opening: https://platform.classiq.io/circuit/5c374d06-ab75-43f8-b4a3-0553a37a3024?version=0.38.0\n" - ] - } - ], - "source": [ - "from classiq import show\n", - "show(qprog)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "406f3d72-b589-483e-8796-00d78a0992e7", - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "prod_py3.11", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "prod_py3.11" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.json b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.json index 2c24f42e..efc6892f 100644 --- a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.json +++ b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.json @@ -1,6 +1,6 @@ { - "friendly_name": "Prepare GHZ State", - "description": "Prepare Greenberger-Horne-Zeilinger (GHZ) State", - "qmod_type": ["function"], - "level": ["demos", "basic"] - } \ No newline at end of file + "friendly_name": "Prepare GHZ State", + "description": "Prepare Greenberger-Horne-Zeilinger (GHZ) State", + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.qmod b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.qmod index 56c3ead1..e62aa9fc 100644 --- a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.qmod +++ b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.qmod @@ -1,4 +1,3 @@ qfunc main(output x: qbit[]) { prepare_ghz_state<5>(x); } - diff --git a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.synthesis_options.json index 9e26dfee..0967ef42 100644 --- a/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.synthesis_options.json +++ b/functions/function_usage_examples/state_preparation/prepare_ghz_state_example.synthesis_options.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_int_example.ipynb b/functions/function_usage_examples/state_preparation/prepare_int_example.ipynb new file mode 100644 index 00000000..9e2f1b1a --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_int_example.ipynb @@ -0,0 +1,159 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a49979a2-39e8-4dde-a89e-c1cc6647e416", + "metadata": {}, + "source": [ + "# Computation Basis State Preparation\n", + "\n", + "The `prepare_int` and `inplace_prepare_int` functions create a single state computational basis state, indexed by the given integer argument.\n", + "\n", + "The `prepare_int` will allocate a `QArray` with the minimal required size for representing the given integer argument.\n", + "`inplace_prepare_int` on the other hand will prepare the state on a given `QArray`. It is more suitable were on wants to prepare a state with a given size." + ] + }, + { + "cell_type": "markdown", + "id": "b1f345b1-a938-49e7-8a53-8984877c32fd", + "metadata": {}, + "source": [ + "Function: `prepare_int`\n", + " \n", + "Arguments:\n", + "\n", + "- `value: CInt` - The index of the state to prepare in the computational basis.\n", + "- `target: Output[QArray[QBit]]`" + ] + }, + { + "cell_type": "markdown", + "id": "34b0c6a8-980d-45bc-8de6-e8c2eb748abf", + "metadata": {}, + "source": [ + "Function: `inplace_prepare_int`\n", + "\n", + "Arguments:\n", + "\n", + "- `value: CInt` - The index of the state to prepare in the computational basis.\n", + "- `target: QArray[QBit]` - The quantum array to prepare the state at. Should be of size at least $\\lceil \\log_2{value}\\rceil$." + ] + }, + { + "cell_type": "markdown", + "id": "08bbf4a2-8c66-4d47-af65-3c74fe02020d", + "metadata": {}, + "source": [ + "## Example 1\n", + "\n", + "Prepare the $|3\\rangle$ state (will result in a 2 qubits state space):" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c5a5a8ec-c036-4554-a64b-4f27a1154714", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, create_model, prepare_int, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + " prepare_int(3, x)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f7652296-b021-4bb0-bff2-2e833df1c629", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"prepare_int_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "6feda775-c958-4b84-ba74-38aa035643b3", + "metadata": {}, + "source": [ + "## Example 2\n", + "\n", + "Prepare the $|3\\rangle$ state, in a state space of 5 qubits:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ee6eea2f-11e5-45c0-9ef0-296fca5e3f89", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " inplace_prepare_int,\n", + " qfunc,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + " allocate(5, x)\n", + " inplace_prepare_int(3, x)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9e647b43-85d1-43e7-8613-cdfec105172f", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"inplace_prepare_int_example\")\n", + "qprog = synthesize(qmod)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/state_preparation/prepare_int_example.json b/functions/function_usage_examples/state_preparation/prepare_int_example.json new file mode 100644 index 00000000..e9344097 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_int_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Prepare Int", + "description": "Computation Basis State Preparation", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_int_example.qmod b/functions/function_usage_examples/state_preparation/prepare_int_example.qmod new file mode 100644 index 00000000..1641cd21 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_int_example.qmod @@ -0,0 +1,3 @@ +qfunc main(output x: qbit[]) { + prepare_int<3>(x); +} diff --git a/functions/function_usage_examples/state_preparation/prepare_int_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_int_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_int_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/state_preparation/prepare_state_example.ipynb b/functions/function_usage_examples/state_preparation/prepare_state_example.ipynb new file mode 100644 index 00000000..d3206fa0 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_state_example.ipynb @@ -0,0 +1,309 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "02c86170-6b8b-46d2-ac09-a75516d48cfa", + "metadata": {}, + "source": [ + "# State Preparation\n", + "\n", + "Most quantum applications start with preparing a state in a quantum register.\n", + "For example, in finance the state may represent the price distribution of some assets.\n", + "In chemistry, it may be an initial guess for the ground state of a molecule, and in\n", + "a quantum machine learning, a feature vector to analyze.\n", + "\n", + "The state preparation functions creates a quantum program that\n", + "outputs either a probability distribution $p_{i}$ or a real amplitudes\n", + "vector $a_{i}$ in the computational basis, with $i$ denoting the corresponding\n", + "basis state. The amplitudes take the form of list of float numbers.\n", + "The probabilities are a list of positive numbers. This is the resulting wave function for probability:\n", + "\n", + "$$\n", + "\\left|\\psi\\right\\rangle = \\sum_{i}\\sqrt{p_{i}}\n", + "\\left|i\\right\\rangle,\n", + "$$\n", + "\n", + "and this is for amplitude:\n", + "\n", + "$$\n", + "\\left|\\psi\\right\\rangle = \\sum_{i}a_{i}\n", + "\\left|i\\right\\rangle.\n", + "$$\n", + "\n", + "In general, state preparation is hard. Only a very small portion\n", + "of the Hilbert space can be prepared efficiently (in $O(poly(n))$\n", + "steps) on a quantum program. Therefore, in practice, an approximation\n", + "is often used to lower the complexity. The approximation is specified\n", + "by an error bound, using the [$L_2$ norm](https://en.wikipedia.org/wiki/Lp_space).\n", + "\n", + "The higher the specified error tolerance, the smaller the output\n", + "quantum program. For exact state preparation, specify an error bound of $0$.\n", + "\n", + "The state preparation algorithm can be tuned depending on whether the\n", + "probability distribution is sparse or dense. The synthesis engine will\n", + "automatically select the parameterization based on the given constraints and\n", + "optimization level." + ] + }, + { + "cell_type": "markdown", + "id": "f8b513d5-4d53-488c-9d8f-b3e98233c2f1", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Function: `prepare_state`\n", + "\n", + "Parameters:\n", + "\n", + "- `probabilities: CArray[CReal]` - Probabilities to load. Should be non-negative and sum to 1.\n", + "- `bound: CReal` - Approximation Error Bound, in the $L_2$ metric (with respect to the given probabilies vector).\n", + "- `out: Output[QArray[QBit]]`\n", + "\n", + "\n", + "\n", + "Function: `inplace_prepare_state`\n", + "\n", + "Parameters:\n", + "\n", + "- `probabilities: CArray[CReal]`\n", + "- `bound: CReal`\n", + "- `out: QArray[QBit]` - Should of size exactly $\\log_2$(``probabilities.len`)\n", + "\n", + "The `inplace_prepare_state` works the same, but for a given allocated `QArray`." + ] + }, + { + "cell_type": "markdown", + "id": "07470a72-7f9d-42a7-b98e-4acf18edf63a", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Function: `prepare_amplitudes`\n", + "\n", + "Parameters:\n", + "\n", + "- `amplitudes: CArray[CReal]` - Amplitudes of the loaded state. Each should be real and the vector norm should be equal to 1.\n", + "- `bound: CReal` - Approximation Error Bound, in the $L_2$ metric (with respect to the given amplitudes vector).\n", + "- `out: Output[QArray[QBit]]`\n", + "\n", + "\n", + "\n", + "Function: `inplace_prepare_amplitudes`\n", + "\n", + "Parameters:\n", + "\n", + "- `amplitudes: CArray[CReal]` - Amplitudes of the loaded state. Each should be real and the vector norm should be equal to 1.\n", + "- `bound: CReal` - Approximation Error Bound, in the $L_2$ metric (with respect to the given amplitudes vector).\n", + "- `out: QArray[QBit]` - Should of size exactly $\\log_2$(`amplitudes.len`)\n", + "\n", + "The `inplace_prepare_amplitudes` works the same, but for a given allocated `QArray`." + ] + }, + { + "cell_type": "markdown", + "id": "647e9afc-c2a2-4a12-9e60-566fdc4745d1", + "metadata": {}, + "source": [ + "## Example 1: Loading Point Mass (PMF) Function\n", + "\n", + "This example generates a quantum program whose output state probabilities are an approximation to the PMF given.\n", + "That is, the probability of measuring the state $|000⟩$ is $0.05$, $|001⟩$ is $0.11$,...\n", + ", and the probability to measure $|111⟩$ is $0.06$." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "802bc17c-14d0-40b8-a3b4-57a3d7ea6bbc", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import Output, QArray, QBit, allocate, create_model, prepare_state, qfunc\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + " probabilities = [0.05, 0.11, 0.13, 0.23, 0.27, 0.12, 0.03, 0.06]\n", + " prepare_state(probabilities=probabilities, bound=0.01, out=x)\n", + "\n", + "\n", + "qmod = create_model(main)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "125709cb-039d-4e4e-9432-642e0a16d15f", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"prepare_state_example\")\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "09ad3fc6-b48d-4d0c-8eb7-df7d880ff786", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Print the resulting probabilities:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a881d37d-d79e-4ee2-94d4-a6fdf8008516", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Resulting probabilities: [0.066 0.133 0.122 0.226 0.262 0.103 0.025 0.063]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "from classiq import execute\n", + "\n", + "res = execute(qprog).result()[0].value\n", + "\n", + "probs = np.zeros(8)\n", + "for sample in res.parsed_counts:\n", + " probs[int(sample.state[\"x\"])] = sample.shots / res.num_shots\n", + "print(\"Resulting probabilities:\", probs)" + ] + }, + { + "cell_type": "markdown", + "id": "a512d075-7ae6-44be-94eb-a051fb4fd96b", + "metadata": {}, + "source": [ + "## Example 2 - Preparating Amplitudes\n", + "\n", + "This example loads a normalized linear space between -1 to 1. The load\n", + "state has an accuracy of 99 present under the L2 norm." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ddf1d24d-1fba-41de-b8d3-d44c2de94104", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import (\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " allocate,\n", + " create_model,\n", + " prepare_amplitudes,\n", + " qfunc,\n", + ")\n", + "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n", + "\n", + "\n", + "@qfunc\n", + "def main(x: Output[QArray[QBit]]):\n", + " amps = np.linspace(-1, 1, 8)\n", + " amps = amps / np.linalg.norm(amps)\n", + " prepare_amplitudes(amplitudes=amps.tolist(), bound=0, out=x)\n", + "\n", + "\n", + "backend_preferences = ClassiqBackendPreferences(\n", + " backend_name=\"aer_simulator_statevector\"\n", + ")\n", + "execution_preferences = ExecutionPreferences(\n", + " num_shots=1, backend_preferences=backend_preferences\n", + ")\n", + "qmod = create_model(main, execution_preferences=execution_preferences)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "d612bf06-8192-4b86-b5dd-2f09964d025a", + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import synthesize, write_qmod\n", + "\n", + "write_qmod(qmod, \"prepare_amplitudes_example\", decimal_precision=15)\n", + "qprog = synthesize(qmod)" + ] + }, + { + "cell_type": "markdown", + "id": "3d18791b-4b25-4ef9-9030-7a08bf4957ed", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "Print the resulting amplitudes:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "d34eb750-f660-4231-96c8-16db5351119b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Resulting amplitudes: [ 0.54006172 0.38575837 0.23145502 0.07715167 -0.07715167 -0.23145502\n", + " -0.38575837 -0.54006172]\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "\n", + "from classiq import execute\n", + "\n", + "res = execute(qprog).result()[0].value\n", + "\n", + "amps = np.zeros(8, dtype=complex)\n", + "for sample in res.parsed_state_vector:\n", + " amps[int(sample.state[\"x\"])] = sample.amplitude\n", + "\n", + "# remove global phase\n", + "global_phase = np.angle(amps[0])\n", + "amps = np.real(amps / np.exp(1j * global_phase))\n", + "\n", + "print(\"Resulting amplitudes:\", amps)" + ] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/functions/function_usage_examples/state_preparation/prepare_state_example.json b/functions/function_usage_examples/state_preparation/prepare_state_example.json new file mode 100644 index 00000000..d1d687b7 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_state_example.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Prepare State", + "description": "State Preparation: Loading Probability Mass Function (PMF)", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["demos", "basic"] +} diff --git a/functions/function_usage_examples/state_preparation/prepare_state_example.qmod b/functions/function_usage_examples/state_preparation/prepare_state_example.qmod new file mode 100644 index 00000000..92c224dc --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_state_example.qmod @@ -0,0 +1,12 @@ +qfunc main(output x: qbit[]) { + prepare_state<[ + 0.05, + 0.11, + 0.13, + 0.23, + 0.27, + 0.12, + 0.03, + 0.06 + ], 0.01>(x); +} diff --git a/functions/function_usage_examples/state_preparation/prepare_state_example.synthesis_options.json b/functions/function_usage_examples/state_preparation/prepare_state_example.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/functions/function_usage_examples/state_preparation/prepare_state_example.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.json b/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.json deleted file mode 100644 index c7762b2f..00000000 --- a/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "Uniform Distribution State Preparation", - "description": "Uniform Distribution State Preparation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.qmod b/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.qmod deleted file mode 100644 index ae38bff1..00000000 --- a/functions/function_usage_examples/state_preparation/uniform_distribution_state_preparation.qmod +++ /dev/null @@ -1,15 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "UniformDistributionStatePreparation", - "function_params": { - "num_qubits": 5 - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/state_preparation/w_state_preparation.json b/functions/function_usage_examples/state_preparation/w_state_preparation.json deleted file mode 100644 index 66615a4d..00000000 --- a/functions/function_usage_examples/state_preparation/w_state_preparation.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "friendly_name": "W State Preparation", - "description": "W State Preparation", - "problem_domain_tags": [], - "qmod_type": ["function"], - "level": ["demos"] -} diff --git a/functions/function_usage_examples/state_preparation/w_state_preparation.qmod b/functions/function_usage_examples/state_preparation/w_state_preparation.qmod deleted file mode 100644 index 27a2a330..00000000 --- a/functions/function_usage_examples/state_preparation/w_state_preparation.qmod +++ /dev/null @@ -1,15 +0,0 @@ -{ - "functions": [ - { - "name": "main", - "body": [ - { - "function": "WStatePreparation", - "function_params": { - "num_qubits": 5 - } - } - ] - } - ] -} diff --git a/functions/function_usage_examples/unitary/unitary_example.ipynb b/functions/function_usage_examples/unitary/unitary_example.ipynb index 9ca78d8e..568ccb0b 100644 --- a/functions/function_usage_examples/unitary/unitary_example.ipynb +++ b/functions/function_usage_examples/unitary/unitary_example.ipynb @@ -17,7 +17,7 @@ "\n", "Arguments:\n", "\n", - "- `elements: QParam[List[List[float]]]` - A 2d array of complex numbers representing the unitary matrix. \n", + "- `elements: CArray[CArray[CReal]]` - A 2d array of complex numbers representing the unitary matrix. \n", "- `target: QArray[QBit]` - The quantum state to apply the unitary on. Should be of corresponding size." ] }, @@ -38,27 +38,16 @@ "metadata": {}, "outputs": [], "source": [ - "from classiq import (\n", - " Output,\n", - " QArray,\n", - " QBit,\n", - " allocate,\n", - " create_model,\n", - " unitary,\n", - " qfunc,\n", - ")\n", + "from classiq import Output, QArray, QBit, allocate, create_model, qfunc, unitary\n", "\n", + "UNITARY = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1j, 0], [0, 0, 0, 1j]]\n", "\n", - "UNITARY = [[1, 0, 0, 0],\n", - " [0, 1, 0, 0],\n", - " [0, 0, -1j, 0],\n", - " [0, 0, 0, 1j]]\n", "\n", "@qfunc\n", "def main(x: Output[QArray[QBit]]):\n", " allocate(2, x)\n", " unitary(UNITARY, x)\n", - " \n", + "\n", "\n", "qmod = create_model(main)" ] diff --git a/functions/function_usage_examples/unitary/unitary_example.qmod b/functions/function_usage_examples/unitary/unitary_example.qmod index de57e984..c1b16db8 100644 --- a/functions/function_usage_examples/unitary/unitary_example.qmod +++ b/functions/function_usage_examples/unitary/unitary_example.qmod @@ -7,4 +7,3 @@ qfunc main(output x: qbit[]) { [0, 0, 0, 1j] ]>(x); } - diff --git a/functions/function_usage_examples/unitary/unitary_example.synthesis_options.json b/functions/function_usage_examples/unitary/unitary_example.synthesis_options.json index 9e26dfee..0967ef42 100644 --- a/functions/function_usage_examples/unitary/unitary_example.synthesis_options.json +++ b/functions/function_usage_examples/unitary/unitary_example.synthesis_options.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/functions/open_library_definitions/_check_msb.qmod b/functions/open_library_definitions/_check_msb.qmod new file mode 100644 index 00000000..19c0f69e --- /dev/null +++ b/functions/open_library_definitions/_check_msb.qmod @@ -0,0 +1,9 @@ +qfunc _check_msb(x: qbit[], aux: qbit) { + within { + invert { + qft_no_swap(x); + } + } apply { + _ctrl_x(x[0], aux); + } +} diff --git a/functions/open_library_definitions/_ctrl_x.qmod b/functions/open_library_definitions/_ctrl_x.qmod new file mode 100644 index 00000000..3c61e49b --- /dev/null +++ b/functions/open_library_definitions/_ctrl_x.qmod @@ -0,0 +1,5 @@ +qfunc _ctrl_x(ctrl: qnum, aux: qbit) { + control (ctrl == ref) { + X(aux); + } +} diff --git a/functions/open_library_definitions/apply_to_all.qmod b/functions/open_library_definitions/apply_to_all.qmod index dc5be56d..4a2c7481 100644 --- a/functions/open_library_definitions/apply_to_all.qmod +++ b/functions/open_library_definitions/apply_to_all.qmod @@ -1,5 +1,5 @@ qfunc apply_to_all(target: qbit[]) { - repeat (index: len(target)) { + repeat (index: target.len) { gate_operand(target[index]); } } diff --git a/functions/open_library_definitions/c_modular_multiply.qmod b/functions/open_library_definitions/c_modular_multiply.qmod new file mode 100644 index 00000000..5d58c6e6 --- /dev/null +++ b/functions/open_library_definitions/c_modular_multiply.qmod @@ -0,0 +1,9 @@ +qfunc c_modular_multiply(b: qbit[], x: qbit[], ctrl: qbit, aux: qbit) { + within { + qft(b); + } apply { + repeat (index: x.len) { + cc_modular_add(b, x[index], ctrl, aux); + } + } +} diff --git a/functions/open_library_definitions/cc_modular_add.qmod b/functions/open_library_definitions/cc_modular_add.qmod new file mode 100644 index 00000000..1fedd8dd --- /dev/null +++ b/functions/open_library_definitions/cc_modular_add.qmod @@ -0,0 +1,24 @@ +qfunc cc_modular_add(phi_b: qbit[], c1: qbit, c2: qbit, aux: qbit) { + ctrl: qbit[]; + {c1, c2} -> ctrl; + control (ctrl) { + qft_space_add_const(phi_b); + } + invert { + qft_space_add_const(phi_b); + } + _check_msb<1>(phi_b, aux); + control (aux) { + qft_space_add_const(phi_b); + } + within { + invert { + control (ctrl) { + qft_space_add_const(phi_b); + } + } + } apply { + _check_msb<0>(phi_b, aux); + } + ctrl -> {c1, c2}; +} diff --git a/functions/open_library_definitions/full_hea.qmod b/functions/open_library_definitions/full_hea.qmod index d8daea71..c8eab702 100644 --- a/functions/open_library_definitions/full_hea.qmod +++ b/functions/open_library_definitions/full_hea.qmod @@ -1,18 +1,18 @@ qfunc full_hea(q: qbit), operands_2qubit: qfunc[] (q1: qbit, q2: qbit)>(x: qbit[num_qubits]) { repeat (r: reps) { - repeat (i1: len(operands_1qubit)) { + repeat (i1: operands_1qubit.len) { repeat (index: num_qubits) { if (is_parametrized[i1] == 1) { - operands_1qubit[i1](x[index]); + operands_1qubit[i1](x[index]); } else { operands_1qubit[i1]<0>(x[index]); } } } - repeat (i2: len(operands_2qubit)) { - repeat (index: len(connectivity_map)) { - if (is_parametrized[len(operands_1qubit) + i2] == 1) { - operands_2qubit[i2](x[connectivity_map[index][0]], x[connectivity_map[index][1]]); + repeat (i2: operands_2qubit.len) { + repeat (index: connectivity_map.len) { + if (is_parametrized[operands_1qubit.len + i2] == 1) { + operands_2qubit[i2](x[connectivity_map[index][0]], x[connectivity_map[index][1]]); } else { operands_2qubit[i2]<0>(x[connectivity_map[index][0]], x[connectivity_map[index][1]]); } diff --git a/functions/open_library_definitions/inplace_c_modular_multiply.qmod b/functions/open_library_definitions/inplace_c_modular_multiply.qmod new file mode 100644 index 00000000..1a6a3dbe --- /dev/null +++ b/functions/open_library_definitions/inplace_c_modular_multiply.qmod @@ -0,0 +1,12 @@ +qfunc inplace_c_modular_multiply(x: qbit[], ctrl: qbit, aux: qbit) { + b: qbit[]; + allocate(b); + c_modular_multiply(b, x, ctrl, aux); + control (ctrl) { + multiswap(x, b); + } + invert { + c_modular_multiply(b, x, ctrl, aux); + } + free(b); +} diff --git a/functions/open_library_definitions/inplace_prepare_int.qmod b/functions/open_library_definitions/inplace_prepare_int.qmod index 9b1582dd..03fc7c04 100644 --- a/functions/open_library_definitions/inplace_prepare_int.qmod +++ b/functions/open_library_definitions/inplace_prepare_int.qmod @@ -1,9 +1,9 @@ qfunc inplace_prepare_int(target: qbit[]) { - repeat (index: len(target)) { + repeat (index: target.len) { if ((floor(value / (2 ** index)) % 2) == 1) { X(target[index]); } else { IDENTITY(target[index]); - }; + } } } diff --git a/functions/open_library_definitions/linear_pauli_rotations.qmod b/functions/open_library_definitions/linear_pauli_rotations.qmod index 9f388537..b17e146c 100644 --- a/functions/open_library_definitions/linear_pauli_rotations.qmod +++ b/functions/open_library_definitions/linear_pauli_rotations.qmod @@ -1,5 +1,5 @@ qfunc linear_pauli_rotations(x: qbit[], q: qbit[]) { - repeat (index: len(q)) { + repeat (index: q.len) { single_pauli(target) { switch(x: qbit[], power: qbit[]) { + aux: qbit; + allocate<1>(aux); + repeat (index: power.len) { + inplace_c_modular_multiply(x, power[index], aux); + } + free(aux); +} diff --git a/functions/open_library_definitions/multiswap.qmod b/functions/open_library_definitions/multiswap.qmod new file mode 100644 index 00000000..40cae55d --- /dev/null +++ b/functions/open_library_definitions/multiswap.qmod @@ -0,0 +1,5 @@ +qfunc multiswap(x: qbit[], y: qbit[]) { + repeat (index: min(x.len, y.len)) { + SWAP(x[index], y[index]); + } +} diff --git a/functions/open_library_definitions/prepare_exponential_state.qmod b/functions/open_library_definitions/prepare_exponential_state.qmod index 50bc34a0..621314b0 100644 --- a/functions/open_library_definitions/prepare_exponential_state.qmod +++ b/functions/open_library_definitions/prepare_exponential_state.qmod @@ -1,5 +1,5 @@ qfunc prepare_exponential_state(q: qbit[]) { - repeat (i: len(q)) { + repeat (i: q.len) { RY<2.0 * atan(exp(((-rate) * (2.0 ** i)) / 2.0))>(q[i]); } } diff --git a/functions/open_library_definitions/prepare_ghz_state.qmod b/functions/open_library_definitions/prepare_ghz_state.qmod index 8e9afa6f..5ef87ffb 100644 --- a/functions/open_library_definitions/prepare_ghz_state.qmod +++ b/functions/open_library_definitions/prepare_ghz_state.qmod @@ -6,8 +6,8 @@ qfunc prepare_ghz_state(output q: qbit[]) { if (size <= (control_index + (2 ** step))) { IDENTITY(q[0]); } else { - CX(q[control_index], q[(control_index) + (2 ** (step))]); - }; + CX(q[control_index], q[control_index + (2 ** step)]); + } } } } diff --git a/functions/open_library_definitions/qaoa_init.qmod b/functions/open_library_definitions/qaoa_init.qmod index 0107e8cb..3c940eac 100644 --- a/functions/open_library_definitions/qaoa_init.qmod +++ b/functions/open_library_definitions/qaoa_init.qmod @@ -1,5 +1,5 @@ qfunc qaoa_init(target: qbit[]) { - repeat (index: len(target)) { + repeat (index: target.len) { H(target[index]); } } diff --git a/functions/open_library_definitions/qaoa_mixer_layer.qmod b/functions/open_library_definitions/qaoa_mixer_layer.qmod index 13f7e223..837d3a0c 100644 --- a/functions/open_library_definitions/qaoa_mixer_layer.qmod +++ b/functions/open_library_definitions/qaoa_mixer_layer.qmod @@ -1,5 +1,5 @@ qfunc qaoa_mixer_layer(target: qbit[]) { - repeat (index: len(target)) { + repeat (index: target.len) { RX(target[index]); } } diff --git a/functions/open_library_definitions/qaoa_penalty.qmod b/functions/open_library_definitions/qaoa_penalty.qmod index 91543c8b..7997dd35 100644 --- a/functions/open_library_definitions/qaoa_penalty.qmod +++ b/functions/open_library_definitions/qaoa_penalty.qmod @@ -1,6 +1,6 @@ qfunc qaoa_penalty(target: qbit[num_qubits]) { qaoa_init(target); - repeat (index: len(params_list) / 2) { + repeat (index: params_list.len / 2) { qaoa_layer(target); } } diff --git a/functions/open_library_definitions/qft.qmod b/functions/open_library_definitions/qft.qmod index e6aed280..dfb93787 100644 --- a/functions/open_library_definitions/qft.qmod +++ b/functions/open_library_definitions/qft.qmod @@ -1,8 +1,8 @@ qfunc qft(target: qbit[]) { - repeat (index: len(target) / 2) { - SWAP(target[index], target[len(target)-1-index]); + repeat (index: target.len / 2) { + SWAP(target[index], target[(target.len - 1) - index]); } - repeat (index: len(target)) { - qft_step(target[index:len(target)]); + repeat (index: target.len) { + qft_step(target[index:target.len]); } } diff --git a/functions/open_library_definitions/qft_no_swap.qmod b/functions/open_library_definitions/qft_no_swap.qmod new file mode 100644 index 00000000..1e2b4cdc --- /dev/null +++ b/functions/open_library_definitions/qft_no_swap.qmod @@ -0,0 +1,5 @@ +qfunc qft_no_swap(qbv: qbit[]) { + repeat (index: qbv.len) { + qft_step(qbv[index:qbv.len]); + } +} diff --git a/functions/open_library_definitions/qft_space_add_const.qmod b/functions/open_library_definitions/qft_space_add_const.qmod new file mode 100644 index 00000000..33ff18e1 --- /dev/null +++ b/functions/open_library_definitions/qft_space_add_const.qmod @@ -0,0 +1,5 @@ +qfunc qft_space_add_const(phi_b: qbit[]) { + repeat (index: phi_b.len) { + PHASE(phi_b[index]); + } +} diff --git a/functions/open_library_definitions/qft_step.qmod b/functions/open_library_definitions/qft_step.qmod index 7014a209..580656ec 100644 --- a/functions/open_library_definitions/qft_step.qmod +++ b/functions/open_library_definitions/qft_step.qmod @@ -1,6 +1,6 @@ qfunc qft_step(target: qbit[]) { H(target[0]); - repeat (index: len(target) - 1) { - CPHASE(target[index+1], target[0]); + repeat (index: target.len - 1) { + CPHASE(target[index + 1], target[0]); } } diff --git a/functions/open_library_definitions/qpe_flexible.qmod b/functions/open_library_definitions/qpe_flexible.qmod index 39799eac..d39c736f 100644 --- a/functions/open_library_definitions/qpe_flexible.qmod +++ b/functions/open_library_definitions/qpe_flexible.qmod @@ -2,7 +2,7 @@ qfunc qpe_flexible()>(phase: qnum) { phase_array: qbit[]; phase -> phase_array; apply_to_all(phase_array); - repeat (index: len(phase_array)) { + repeat (index: phase_array.len) { control (phase_array[index]) { unitary_with_power<2 ** index>(); } diff --git a/functions/open_library_definitions/reflect_about_zero.qmod b/functions/open_library_definitions/reflect_about_zero.qmod index fa348b24..45f51ba6 100644 --- a/functions/open_library_definitions/reflect_about_zero.qmod +++ b/functions/open_library_definitions/reflect_about_zero.qmod @@ -1,12 +1,12 @@ qfunc reflect_about_zero(packed_vars: qbit[]) { - msbs: qnum; + msbs: qnum; lsb: qbit; packed_vars -> {msbs, lsb}; within { X(lsb); H(lsb); } apply { - quantum_if (msbs == 0) { + control (msbs == 0) { X(lsb); } } diff --git a/functions/open_library_definitions/single_pauli.qmod b/functions/open_library_definitions/single_pauli.qmod index 3af289e1..d8be02b7 100644 --- a/functions/open_library_definitions/single_pauli.qmod +++ b/functions/open_library_definitions/single_pauli.qmod @@ -1,5 +1,5 @@ qfunc single_pauli(target: qbit)>(x: qbit[], q: qbit) { - repeat (index: len(x)) { + repeat (index: x.len) { control (x[index]) { q1_qfunc<(2 ** index) * slope>(q); } diff --git a/functions/open_library_definitions/swap_test.qmod b/functions/open_library_definitions/swap_test.qmod index dc63de40..9dccc238 100644 --- a/functions/open_library_definitions/swap_test.qmod +++ b/functions/open_library_definitions/swap_test.qmod @@ -2,7 +2,7 @@ qfunc swap_test(state1: qbit[], state2: qbit[], output test: qbit) { allocate<1>(test); H(test); control (test) { - repeat (i: len(state1)) { + repeat (i: state1.len) { SWAP(state1[i], state2[i]); } } diff --git a/tutorials/classiq_concepts/repeat/repeat.ipynb b/tutorials/classiq_concepts/repeat/repeat.ipynb new file mode 100644 index 00000000..1e9d0756 --- /dev/null +++ b/tutorials/classiq_concepts/repeat/repeat.ipynb @@ -0,0 +1,155 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Repeat" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `repeat` concept of the QMOD language is just like a classical for loop but for quantum objects. That is, when one wants to repeat a quantum operation several times, e.g. to do a bit-wise operation, they can just use the `repeat` concept of QMOD. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With the Classiq Python SDK package `repeat` is accessed as a function that has 2 arguments:\n", + "\n", + "1. `count`: `int` or `CInt` - how many times to repeat the operation;\n", + "2. `iteration`: `QCallable` - what operation to repeat;\n", + "\n", + "The argmuent that is passed as the `iteration` is a function by itself. Therefore it leverages the concept of lambda functions in Python (read more [here](https://www.geeksforgeeks.org/python-lambda-anonymous-functions-filter-map-reduce/))." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the following example, two quantum states $|\\psi \\rangle$ and $| \\phi \\rangle$ are initialized with 5 qubits each. Then an Hadamard gate is applied on all the qubits of $|\\psi \\rangle$, i.e. $H^{\\otimes 5}|\\psi \\rangle$, and a NOT gate on all the qubits of $|\\phi \\rangle$, i.e. $X^{\\otimes 5}|\\phi \\rangle$.\n", + "Finally, using the `repeat` function, a bit-wise `SWAP` is performed between $|\\phi \\rangle$ and $|\\psi \\rangle$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \"Phase\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: https://platform.classiq.io/circuit/77ea78cb-f1b0-441f-b14f-8fc9927dede0?version=0.39.0\n" + ] + } + ], + "source": [ + "from classiq import (\n", + " SWAP,\n", + " H,\n", + " Output,\n", + " QArray,\n", + " QBit,\n", + " X,\n", + " allocate,\n", + " apply_to_all,\n", + " create_model,\n", + " qfunc,\n", + " repeat,\n", + " show,\n", + " synthesize,\n", + ")\n", + "\n", + "\n", + "@qfunc\n", + "def main(psi: Output[QArray[QBit]], phi: Output[QArray[QBit]]):\n", + "\n", + " allocate(num_qubits=5, out=psi)\n", + " allocate(num_qubits=5, out=phi)\n", + "\n", + " apply_to_all(H, psi)\n", + " apply_to_all(X, phi)\n", + "\n", + " repeat(count=psi.len, iteration=lambda i: SWAP(phi[i], psi[i]))\n", + "\n", + "\n", + "qprog = synthesize(create_model(main))\n", + "show(qprog)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The native QMOD version of the above code:\n", + "\n", + "```\n", + "// Repeat Example\n", + "\n", + "qfunc main(output psi: qbit[], output phi: qbit[]) {\n", + " allocate<5>(psi);\n", + " allocate<5>(phi);\n", + " \n", + " apply_to_all(psi);\n", + " apply_to_all(phi);\n", + " \n", + " repeat(i:psi.len) {\n", + " SWAP(phi[i], psi[i]);\n", + " }\n", + "}\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from classiq import write_qmod\n", + "\n", + "write_qmod(create_model(main), \"repeat\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.11.7 ('classiq_devolpment')", + "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.7" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "e992e515f6583afc67b46eeabcda0f30363069fab8b382c7517b274ba7a59477" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tutorials/classiq_concepts/repeat/repeat.json b/tutorials/classiq_concepts/repeat/repeat.json new file mode 100644 index 00000000..2cbe9080 --- /dev/null +++ b/tutorials/classiq_concepts/repeat/repeat.json @@ -0,0 +1,7 @@ +{ + "friendly_name": "Repeat Concept", + "description": "Demonstration of the Repeat Concept of QMOD", + "problem_domain_tags": [], + "qmod_type": ["function"], + "level": ["basic", "demos"] +} diff --git a/tutorials/classiq_concepts/repeat/repeat.qmod b/tutorials/classiq_concepts/repeat/repeat.qmod new file mode 100644 index 00000000..f37610a4 --- /dev/null +++ b/tutorials/classiq_concepts/repeat/repeat.qmod @@ -0,0 +1,9 @@ +qfunc main(output psi: qbit[], output phi: qbit[]) { + allocate<5>(psi); + allocate<5>(phi); + apply_to_all(psi); + apply_to_all(phi); + repeat (i: psi.len) { + SWAP(phi[i], psi[i]); + } +} diff --git a/tutorials/classiq_concepts/repeat/repeat.synthesis_options.json b/tutorials/classiq_concepts/repeat/repeat.synthesis_options.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/tutorials/classiq_concepts/repeat/repeat.synthesis_options.json @@ -0,0 +1 @@ +{} diff --git a/tutorials/exponentiation/exponentiation.ipynb b/tutorials/exponentiation/exponentiation.ipynb index cb5cc0c6..252b2b03 100644 --- a/tutorials/exponentiation/exponentiation.ipynb +++ b/tutorials/exponentiation/exponentiation.ipynb @@ -177,7 +177,7 @@ } }, "source": [ - "These impressive results can be compared to the naive exponentiation modules often found in the literature, see comprehensive comparison in the [Hamiltonian Evolution](https://docs.classiq.io/latest/tutorials/tutorials/technology-demonstrations/hamiltonian-evolution/hamiltonian-evolution/) notebook under [Technology Demonstrations](\"https://docs.classiq.io/latest/tutorials/tutorials/technology-demonstrations/) section." + "These impressive results can be compared to the naive exponentiation modules often found in the literature, see comprehensive comparison in the [Hamiltonian Evolution](https://github.com/Classiq/classiq-library/blob/main/tutorials/technology_demonstrations/hamiltonian_evolution/hamiltonian_evolution.ipynb) notebook under [Technology Demonstrations](\"https://docs.classiq.io/latest/tutorials/tutorials/technology-demonstrations/) section." ] }, { @@ -297,7 +297,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.11.7" } }, "nbformat": 4, diff --git a/tutorials/getting_started/Part1_Arithmetic.ipynb b/tutorials/getting_started/part1_arithmetic.ipynb similarity index 98% rename from tutorials/getting_started/Part1_Arithmetic.ipynb rename to tutorials/getting_started/part1_arithmetic.ipynb index 9d0a2021..f7f0a80a 100644 --- a/tutorials/getting_started/Part1_Arithmetic.ipynb +++ b/tutorials/getting_started/part1_arithmetic.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -32,28 +32,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/0fa2ec7a-6fe1-4b30-ab44-3113b6fc9369?version=0.0.0\n" + ] + } + ], "source": [ "# QFunc declares a quantum function\n", "@qfunc\n", "# The main quantum function that will produce 3 outputs.\n", "def main(res: Output[QNum], a: Output[QNum], b: Output[QNum]):\n", " # Encode the integer value 3 in variable a\n", - " prepare_int(3,a)\n", + " prepare_int(3, a)\n", "\n", " # Encode the super position of 0 and 3 into variable b\n", - " prepare_state([0.5,0,0,0.5],out=b, bound=0.01)\n", + " prepare_state([0.5, 0, 0, 0.5], out=b, bound=0.01)\n", "\n", " # Add a and b togehter, and save the result in res\n", " res |= a + b\n", "\n", + "\n", "# Create a quantum circuit from the model above\n", "qprog = synthesize(create_model(main))\n", "\n", "# Open the circuit in the IDE, where it can be analyzed and executed\n", - "show(qprog)\n" + "show(qprog)" ] }, { @@ -100,21 +109,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/d1f5096b-e6b1-43f6-a8b2-b67f7204a3d9?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def main(\n", " # Uncomment the variables below\n", - " # a: Output[QNum], \n", - " # b: Output[QNum], \n", - " # c: Output[QNum], \n", + " # a: Output[QNum],\n", + " # b: Output[QNum],\n", + " # c: Output[QNum],\n", " # res:Output[QNum]\n", - " ):\n", + "):\n", " # Your code here\n", " pass\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -123,23 +141,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### The full solution for your reference" + "### The full solution for your reference\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/45794f6f-121e-4697-a9ab-1060b4ead007?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", - "def main(a: Output[QNum], b: Output[QNum], c: Output[QNum], res:Output[QNum]):\n", - " prepare_state([1/3, 0, 1/3, 1/3], out=a, bound=0.01)\n", - " prepare_state([1/4, 0, 0, 3/4], out=b, bound=0.01)\n", - " prepare_state([1/2, 1/2], out=c, bound=0.01)\n", + "def main(a: Output[QNum], b: Output[QNum], c: Output[QNum], res: Output[QNum]):\n", + " prepare_state([1 / 3, 0, 1 / 3, 1 / 3], out=a, bound=0.1)\n", + " prepare_state([1 / 4, 0, 0, 3 / 4], out=b, bound=0.1)\n", + " prepare_state([1 / 2, 1 / 2], out=c, bound=0.1)\n", "\n", " res |= (a * b) + c\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -147,7 +174,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -161,9 +188,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tutorials/getting_started/Part2_State_preparation.ipynb b/tutorials/getting_started/part2_state_preparation.ipynb similarity index 65% rename from tutorials/getting_started/Part2_State_preparation.ipynb rename to tutorials/getting_started/part2_state_preparation.ipynb index 758b6ba6..2d47f06c 100644 --- a/tutorials/getting_started/Part2_State_preparation.ipynb +++ b/tutorials/getting_started/part2_state_preparation.ipynb @@ -11,18 +11,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from classiq import *\n", "\n", "amplitudes = [\n", - " 0.2450344728207077, -0.1700813505441722, 0.16769736623372838, \n", - " -0.0239052232765222, 0.34393605643711794, -0.2966929669473228, \n", - " -0.2839167245810649, 0.3305828537849893, -0.32376029368963405, \n", - " 0.25704647614347453, 0.1531631416826692, -0.07516264976664182, \n", - " -0.314744872342388, -0.24992215398592088, 0.3526620654512262, -0.015039183255468514\n", + " 0.2450344728207077,\n", + " -0.1700813505441722,\n", + " 0.16769736623372838,\n", + " -0.0239052232765222,\n", + " 0.34393605643711794,\n", + " -0.2966929669473228,\n", + " -0.2839167245810649,\n", + " 0.3305828537849893,\n", + " -0.32376029368963405,\n", + " 0.25704647614347453,\n", + " 0.1531631416826692,\n", + " -0.07516264976664182,\n", + " -0.314744872342388,\n", + " -0.24992215398592088,\n", + " 0.3526620654512262,\n", + " -0.015039183255468514,\n", "]" ] }, @@ -37,20 +48,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/42ddc9d3-a4c0-4e9c-8819-433ea765a57e?version=0.0.0\n" + ] + } + ], "source": [ "bound = 0.3\n", "\n", + "\n", "@qfunc\n", "def main(\n", - " # Uncomment the variables below\n", " # target: Output[QArray]\n", - " ):\n", + "):\n", " # Your code here\n", " pass\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -73,12 +93,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/5c01c8fa-787d-469c-aa05-eafdc2e14b63?version=0.0.0\n" + ] + } + ], "source": [ "bound = 0.3\n", "\n", + "\n", "@qfunc\n", "def main(target: Output[QArray]):\n", " prepare_amplitudes(amplitudes=amplitudes, out=target, bound=bound)\n", @@ -91,7 +120,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -105,9 +134,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tutorials/getting_started/Part3_Deutsch_Jozsa.ipynb b/tutorials/getting_started/part3_deutsch_jozsa.ipynb similarity index 95% rename from tutorials/getting_started/Part3_Deutsch_Jozsa.ipynb rename to tutorials/getting_started/part3_deutsch_jozsa.ipynb index 78a9beb1..60454392 100644 --- a/tutorials/getting_started/Part3_Deutsch_Jozsa.ipynb +++ b/tutorials/getting_started/part3_deutsch_jozsa.ipynb @@ -37,7 +37,7 @@ "3. create an oracle with the `phase_oracle()` function, this is the function signature: (if you are stuck more details are below) \n", "\n", " def simple_oracle(\n", - " predicate: QCallable[QArray[QBit, Literal[\"len(target)\"]], QBit],\n", + " predicate: QCallable[QArray[QBit], QBit],\n", " target: QArray[QBit],\n", " )\n", " \n", @@ -62,24 +62,35 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/a2aa9294-450a-49b3-99a7-f099b2140682?version=0.0.0\n" + ] + } + ], "source": [ "from classiq import *\n", "\n", + "\n", "@qfunc\n", "def my_black_box_prediate(aux: QBit, target: QNum):\n", " aux ^= target > 30\n", "\n", + "\n", "@qfunc\n", "def main(target: Output[QNum]):\n", - " allocate(3,target) #Allocate 3 qubits to the target register\n", + " allocate(3, target) # Allocate 3 qubits to the target register\n", "\n", " pass\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", - "show(qprog)\n" + "show(qprog)" ] }, { @@ -105,16 +116,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/a414d7b8-4fec-41d0-b633-26f90e1ff45e?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def main(target: Output[QNum]):\n", - " allocate(3,target) #Allocate 3 qubits to the target register\n", + " allocate(3, target) # Allocate 3 qubits to the target register\n", "\n", " pass\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -164,28 +184,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/ce829573-13ec-49c4-9f64-27365fcfd378?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def my_black_box_prediate(aux: QBit, target: QNum):\n", " aux ^= target > 40\n", "\n", + "\n", "@qfunc\n", "def main(target: Output[QNum]):\n", - " allocate(3,target) #Allocate 3 qubits to the target register\n", - " \n", - " aux = QBit('aux')\n", + " allocate(3, target) # Allocate 3 qubits to the target register\n", + "\n", + " aux = QBit(\"aux\")\n", " allocate(1, aux)\n", "\n", " within_apply(\n", " compute=lambda: hadamard_transform(target=target),\n", - " action=lambda: phase_oracle(predicate=lambda target, aux: my_black_box_prediate(aux=aux, target=target), target=target)\n", + " action=lambda: phase_oracle(\n", + " predicate=lambda target, aux: my_black_box_prediate(aux=aux, target=target),\n", + " target=target,\n", + " ),\n", " )\n", - " \n", + "\n", " free(aux)\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -193,7 +226,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -207,9 +240,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tutorials/getting_started/Part4_GHZ_state.ipynb b/tutorials/getting_started/part4_ghz_state.ipynb similarity index 95% rename from tutorials/getting_started/Part4_GHZ_state.ipynb rename to tutorials/getting_started/part4_ghz_state.ipynb index 3a6d010c..4634dad9 100644 --- a/tutorials/getting_started/Part4_GHZ_state.ipynb +++ b/tutorials/getting_started/part4_ghz_state.ipynb @@ -24,18 +24,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/26ec3b24-258b-46f6-931b-d65522de9456?version=0.0.0\n" + ] + } + ], "source": [ "from classiq import *\n", "\n", + "\n", "@qfunc\n", "def main(reg: Output[QArray]):\n", - " allocate(6,reg)\n", - " #your code here\n", + " allocate(6, reg)\n", + " # your code here\n", " pass\n", "\n", + "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" ] @@ -49,17 +59,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/9575fb71-7c60-44d4-92bb-fa1ec1a37f87?version=0.0.0\n" + ] + } + ], "source": [ "from classiq import *\n", "\n", + "\n", "@qfunc\n", "def main(reg: Output[QArray]):\n", - " allocate(6,reg)\n", + " allocate(6, reg)\n", " H(reg[0])\n", - " repeat(count=reg.len - 1, iteration= lambda index: CX(control=reg[index], target=reg[index+1]))\n", + " repeat(\n", + " count=reg.len - 1,\n", + " iteration=lambda index: CX(control=reg[index], target=reg[index + 1]),\n", + " )\n", + "\n", "\n", "qprog = synthesize(create_model(main))\n", "show(qprog)" @@ -68,7 +91,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -82,9 +105,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tutorials/getting_started/Part5_Grover.ipynb b/tutorials/getting_started/part5_grover.ipynb similarity index 98% rename from tutorials/getting_started/Part5_Grover.ipynb rename to tutorials/getting_started/part5_grover.ipynb index 188283fa..13ea320b 100644 --- a/tutorials/getting_started/Part5_Grover.ipynb +++ b/tutorials/getting_started/part5_grover.ipynb @@ -13,9 +13,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/7d00de41-1f93-43be-bac7-373d8ed4faa6?version=0.0.0\n" + ] + } + ], "source": [ "from classiq import *\n", "\n", @@ -24,11 +32,10 @@ " (\"a\", RegisterUserInput(size=4)),\n", " (\"b\", RegisterUserInput(size=4)),\n", " ],\n", - " expression=\"2 * a == b\"\n", + " expression=\"2 * a == b\",\n", ")\n", "qprog = synthesize(grover_model)\n", - "show(qprog)\n", - " " + "show(qprog)" ] }, { @@ -75,12 +82,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from classiq import *\n", "\n", + "\n", "@qfunc\n", "def my_hadamard_transform(reg: QArray[QBit]):\n", " # Your code\n", @@ -123,16 +131,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "@qfunc\n", - "def my_predicate(res: QNum, a: QNum, b: QNum) -> None:\n", - " res ^= 2 * a == b * a\n", + "def my_predicate(res: QNum, a: QNum, b: QNum) -> None:\n", + " res ^= 2 * a == b * a\n", + "\n", "\n", "@qfunc\n", - "def my_oracle(a: QNum, b:QNum):\n", + "def my_oracle(a: QNum, b: QNum):\n", " # Your code here\n", " pass" ] @@ -179,7 +188,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -204,19 +213,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/96f35f70-4cb8-4fed-b373-2c2140b85c5a?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def main(\n", - " # Uncomment the variables below\n", - " # a: Output[QNum], \n", + " # a: Output[QNum],\n", " # b: Output[QNum]\n", - " ) -> None:\n", - " #Your code here\n", + ") -> None:\n", + " # #Your code here\n", " pass\n", "\n", + "\n", "model = create_model(main)\n", "qprog = synthesize(model)\n", "show(qprog)" @@ -258,11 +275,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ - "#Your code here" + "# Your code here" ] }, { @@ -292,11 +309,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ - "#Your code here" + "# Your code here" ] }, { @@ -317,18 +334,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/c2e97173-d12f-412e-8872-aece06e0a031?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def main(\n", - " # a: Output[QInt], \n", + " # a: Output[QInt],\n", " # b: Output[QInt]\n", - " ):\n", - " #Your code here\n", + "):\n", + " # Your code here\n", " pass\n", "\n", + "\n", "model = create_model(main)\n", "qprog = synthesize(model)\n", "show(qprog)" @@ -347,7 +373,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -420,23 +446,33 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Opening: http://localhost:4200/circuit/09b6fe49-2406-4c2a-a2b8-b75ff418e65c?version=0.0.0\n" + ] + } + ], "source": [ "@qfunc\n", "def my_hadamard_transform(reg: QArray[QBit]):\n", "\n", " repeat(count=reg.len, iteration=lambda index: H(reg[index]))\n", "\n", + "\n", "@qfunc\n", - "def my_predicate(res: QNum, a: QNum, b: QNum) -> None:\n", - " res ^= 2 * a == b\n", + "def my_predicate(res: QNum, a: QNum, b: QNum) -> None:\n", + " res ^= 2 * a == b\n", + "\n", "\n", "@qfunc\n", - "def my_oracle(a: QNum, b:QNum):\n", + "def my_oracle(a: QNum, b: QNum):\n", "\n", - " aux = QBit('aux')\n", + " aux = QBit(\"aux\")\n", " allocate(1, aux)\n", " X(aux)\n", " H(aux)\n", @@ -445,21 +481,23 @@ " H(aux)\n", " free(aux)\n", "\n", + "\n", "@qfunc\n", "def my_difuser(a: QNum, b: QNum):\n", "\n", - " reg = QArray('reg')\n", - " msbs = QArray('msbs')\n", - " lsb = QBit('lsb')\n", + " reg = QArray(\"reg\")\n", + " msbs = QArray(\"msbs\")\n", + " lsb = QBit(\"lsb\")\n", " bind([a, b], reg)\n", " my_hadamard_transform(reg)\n", " apply_to_all(gate_operand=X, target=reg)\n", " bind(reg, [msbs, lsb])\n", - " control(ctrl=msbs, operand=lambda:Z(lsb))\n", + " control(ctrl=msbs, operand=lambda: Z(lsb))\n", " bind([msbs, lsb], reg)\n", " invert(operand=lambda: my_hadamard_transform(reg))\n", " bind(reg, [a, b])\n", "\n", + "\n", "@qfunc\n", "def main(a: Output[QNum], b: Output[QNum]) -> None:\n", "\n", @@ -467,20 +505,19 @@ " allocate(4, b)\n", " my_hadamard_transform(a)\n", " my_hadamard_transform(b)\n", - " my_oracle(a,b)\n", + " my_oracle(a, b)\n", " my_difuser(a, b)\n", "\n", "\n", "model = create_model(main)\n", "qprog = synthesize(model)\n", - "show(qprog)\n", - "\n" + "show(qprog)" ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -494,9 +531,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/tutorials/hardware_aware_mcx/hardware_aware_mcx.ipynb b/tutorials/hardware_aware_mcx/hardware_aware_mcx.ipynb index 3738ba34..5cb7b3e9 100644 --- a/tutorials/hardware_aware_mcx/hardware_aware_mcx.ipynb +++ b/tutorials/hardware_aware_mcx/hardware_aware_mcx.ipynb @@ -69,7 +69,7 @@ "\n", "@qfunc\n", "def my_mcx(cntrl: QArray[QBit], target: QBit) -> None:\n", - " control(lambda: X(target), cntrl)\n", + " control(cntrl, lambda: X(target))\n", "\n", "\n", "# define the MCX parameters within the quantum 'main' function\n", diff --git a/tutorials/high_level_modeling_flexible_qpe/high_level_modeling_flexible_qpe.ipynb b/tutorials/high_level_modeling_flexible_qpe/high_level_modeling_flexible_qpe.ipynb index 311ef9ae..3cbddcc3 100644 --- a/tutorials/high_level_modeling_flexible_qpe/high_level_modeling_flexible_qpe.ipynb +++ b/tutorials/high_level_modeling_flexible_qpe/high_level_modeling_flexible_qpe.ipynb @@ -41,7 +41,7 @@ }, "outputs": [], "source": [ - "from classiq import QArray, QBit, QCallable, QParam, qfunc" + "from classiq import CArray, CInt, CReal, QArray, QBit, QCallable, qfunc" ] }, { @@ -84,7 +84,7 @@ "\n", "@qfunc\n", "def my_qpe_flexible(\n", - " unitary: QCallable[QParam[int], QArray[QBit]],\n", + " unitary: QCallable[CInt, QArray[QBit]],\n", " state: QArray[QBit],\n", " phase: QArray[QBit],\n", ") -> None:\n", @@ -93,8 +93,8 @@ " repeat(\n", " count=phase.len,\n", " iteration=lambda index: control(\n", - " operand=lambda: unitary(2**index, state),\n", " ctrl=phase[index],\n", + " operand=lambda: unitary(2**index, state),\n", " ),\n", " )\n", "\n", @@ -193,9 +193,9 @@ "\n", "def suzuki_trotter_with_power_logic(\n", " hamiltonian,\n", - " pw: QParam[int],\n", - " evolution_coefficient: QParam[float],\n", - " order: QParam[int],\n", + " pw: CInt,\n", + " evolution_coefficient: CReal,\n", + " order: CInt,\n", " target: QArray[QBit],\n", " p_0: int,\n", " gamma: float,\n", @@ -583,7 +583,7 @@ "\n", "@qfunc\n", "def unitary_with_power_logic(\n", - " pw: QParam[int], matrix: QParam[List[List[float]]], target: QArray[QBit]\n", + " pw: CInt, matrix: CArray[CArray[CReal]], target: QArray[QBit]\n", ") -> None:\n", " power(pw, lambda: unitary(elements=matrix, target=target))" ] diff --git a/tutorials/mcx/mcx.ipynb b/tutorials/mcx/mcx.ipynb index 4ed37c75..a1da3fed 100644 --- a/tutorials/mcx/mcx.ipynb +++ b/tutorials/mcx/mcx.ipynb @@ -23,7 +23,7 @@ "source": [ "## QUANTUM RESOURCES ARE VALUABLE, YET LIMITED\n", "\n", - "Quantum computers offer tantalizing promises to those who can harness their power. And though today\u2019s computers are not quite able to solve real-world problems, those who are able to optimize for the hardware available will be able to reap rewards sooner than those who wait. The MCX gate is an important quantum gate used in a variety of circuits, such as the Grover Operator, logical AND operator, various state preparation algorithms, and arithmetic comparators. The ability to adapt implementations of MCX gates to meet the hardware constraints - limited qubit count, fidelities, gate count, and so on - is not trivial." + "Quantum computers offer tantalizing promises to those who can harness their power. And though today’s computers are not quite able to solve real-world problems, those who are able to optimize for the hardware available will be able to reap rewards sooner than those who wait. The MCX gate is an important quantum gate used in a variety of circuits, such as the Grover Operator, logical AND operator, various state preparation algorithms, and arithmetic comparators. The ability to adapt implementations of MCX gates to meet the hardware constraints - limited qubit count, fidelities, gate count, and so on - is not trivial." ] }, { @@ -90,7 +90,7 @@ "source": [ "@qfunc\n", "def my_mcx(cntrl: QArray[QBit], target: QBit) -> None:\n", - " control(lambda: X(target), cntrl)" + " control(cntrl, lambda: X(target))" ] }, { diff --git a/tutorials/optimization/learning_optimization.ipynb b/tutorials/optimization/learning_optimization.ipynb index 7550c7f9..5e7e0fad 100644 --- a/tutorials/optimization/learning_optimization.ipynb +++ b/tutorials/optimization/learning_optimization.ipynb @@ -197,7 +197,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "I.e., the constraint is $3x_1 + 2x_2 \\ge 2$. There are several ways to define constraints in Pyomo. Here, add a field to the application object called `constraint`, which is equal to some Pyomo constraint object. Read [link](https://docs.classiq.io/latest/user-guide/combinatorial-optimization/problem-formulation/) for more ways of defining constraints.\n", + "I.e., the constraint is $3x_1 + 2x_2 \\ge 2$. There are several ways to define constraints in Pyomo. Here, add a field to the application object called `constraint`, which is equal to some Pyomo constraint object. Read [link](https://docs.classiq.io/latest/user-guide/built-in-algorithms/combinatorial-optimization/problem-formulation/) for more ways of defining constraints.\n", "\n", "Examine the application object using the Pyomo method 'pprint':\n" ] @@ -699,7 +699,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.11.7" }, "vscode": { "interpreter": { diff --git a/tutorials/phase_kickback/phase_kickback.ipynb b/tutorials/phase_kickback/phase_kickback.ipynb index cf253248..265e0bbc 100644 --- a/tutorials/phase_kickback/phase_kickback.ipynb +++ b/tutorials/phase_kickback/phase_kickback.ipynb @@ -11,7 +11,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Phase kickback [[1](#childs),[2](#LinLin),[3](#Wolf)] is an important and highly used primitive in quantum computing, and it deals with kicking the result of a function to the phase of a quantum state so it can be smartly manipulated with constructive and destructive interferences in order to achieve the desired result. Every quantum algortihm can be decomposed into 3 steps: 1)Encoding the data; 2) Manipulating the data; and 3) Extracting the result. The phase kickback primitive is a key step in the manipulaiton of the data that enables the extraction of the result. See the [Deutch-Josza](https://nightly.docs.classiq.io/latest/tutorials/algorithms/deutsch-josza/deutsch-jozsa/) and [Simon's](https://nightly.docs.classiq.io/latest/tutorials/algorithms/simon/simon/) algortihms for concrete examples of the applications of it.\n", + "Phase kickback [[1](#childs),[2](#LinLin),[3](#Wolf)] is an important and highly used primitive in quantum computing, and it deals with kicking the result of a function to the phase of a quantum state so it can be smartly manipulated with constructive and destructive interferences in order to achieve the desired result. Every quantum algortihm can be decomposed into 3 steps: 1)Encoding the data; 2) Manipulating the data; and 3) Extracting the result. The phase kickback primitive is a key step in the manipulaiton of the data that enables the extraction of the result. See the [Deutch-Jozsa](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb) and [Simon's](https://github.com/Classiq/classiq-library/blob/main/algorithms/simon/simon.ipynb) algortihms for concrete examples of the applications of it.\n", "\n", "The standard way [[4](#NielsenChuang)] of applying a classical function $f:\\{0,1\\}^n \\rightarrow \\{0,1\\}$ on quantum states is with the oracle model: \n", "$\\begin{equation}\n", @@ -55,12 +55,12 @@ "metadata": {}, "source": [ "**Classiq Concepts**\n", - "* [Within-Apply](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/)\n", - "* [In-Place XOR](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/)\n", + "* [Within-Apply](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/ )\n", + "* [In-Place XOR](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/ )\n", "\n", "**Related Algorithms**\n", - "* [Deutch-Josza Algorithm](https://docs.classiq.io/latest/tutorials/algorithms/deutsch-josza/deutsch-jozsa/)\n", - "* [Simon's Algorithm](https://docs.classiq.io/latest/tutorials/algorithms/simon/simon/)" + "* [Deutch-Jozsa Algorithm](https://github.com/Classiq/classiq-library/blob/main/algorithms/deutsch_jozsa/deutsch_jozsa.ipynb)\n", + "* [Simon's Algorithm](https://github.com/Classiq/classiq-library/blob/main/algorithms/simon/simon.ipynb)" ] }, { @@ -169,7 +169,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now we want to combine the two building blocks for preforming the phase kickback. Notice that the we not intrested in the $\\ket{-}$ state and its only purpose is for the implementation of $\\ket{x}\\rightarrow (-1)^{f(x)}\\ket{x}$. For such cases (that are common in quantum computing) the QMOD language offers the `Within-Apply` ([read more](https://nightly.docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/)) statment. Everything we want only for the use of another specific function we apply in the `Within`, and we use it for the specific thing we are intrested at in the `Apply`" + "Now we want to combine the two building blocks for preforming the phase kickback. Notice that the we not intrested in the $\\ket{-}$ state and its only purpose is for the implementation of $\\ket{x}\\rightarrow (-1)^{f(x)}\\ket{x}$. For such cases (that are common in quantum computing) the QMOD language offers the `Within-Apply` ([read more](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/ ) ) statment. Everything we want only for the use of another specific function we apply in the `Within`, and we use it for the specific thing we are intrested at in the `Apply`" ] }, { diff --git a/tutorials/prepare_state/prepare_state.ipynb b/tutorials/prepare_state/prepare_state.ipynb index b809d39c..9e9b87e6 100644 --- a/tutorials/prepare_state/prepare_state.ipynb +++ b/tutorials/prepare_state/prepare_state.ipynb @@ -232,12 +232,15 @@ "source": [ "from classiq.execution import (\n", " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", " ExecutionPreferences,\n", " set_quantum_program_execution_preferences,\n", ")\n", "\n", "preferences = ExecutionPreferences(\n", - " backend_preferences=ClassiqBackendPreferences(backend_name=\"aer_simulator\")\n", + " backend_preferences=ClassiqBackendPreferences(\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR\n", + " )\n", ")\n", "qprog = set_quantum_program_execution_preferences(qprog, preferences)" ] @@ -248,7 +251,7 @@ "metadata": {}, "source": [ "## 7/8 Let's run your quantum program on a quantum simulator!\n", - "**On the IDE:** Press 'Run' button to execute your quantum program on the aer_simulator which we chose in the previous step\n", + "**On the IDE:** Press 'Run' button to execute your quantum program on the simulator which we chose in the previous step\n", "\n", "*Bellow is the simple SDK execute code:*" ] diff --git a/tutorials/prepare_state/prepare_state.json b/tutorials/prepare_state/prepare_state.json index 4da1d781..64be3ce1 100644 --- a/tutorials/prepare_state/prepare_state.json +++ b/tutorials/prepare_state/prepare_state.json @@ -1,5 +1,5 @@ { - "friendly_name": "Walkthrough: prepare_state", + "friendly_name": "Prepare State", "description": "Walkthrough: prepare_state function usage", "problem_domain_tags": [], "qmod_type": ["function"], diff --git a/tutorials/technology_demonstrations/hamiltonian_evolution/hamiltonian_evolution.ipynb b/tutorials/technology_demonstrations/hamiltonian_evolution/hamiltonian_evolution.ipynb index 183d69cd..7f72c39e 100644 --- a/tutorials/technology_demonstrations/hamiltonian_evolution/hamiltonian_evolution.ipynb +++ b/tutorials/technology_demonstrations/hamiltonian_evolution/hamiltonian_evolution.ipynb @@ -263,6 +263,7 @@ " ctrl = QBit(\"ctrl\")\n", " allocate(1, ctrl)\n", " control(\n", + " ctrl=ctrl,\n", " operand=lambda: suzuki_trotter(\n", " pauli_operator=hamiltonian,\n", " evolution_coefficient=1,\n", @@ -270,7 +271,6 @@ " repetitions=REPETITIONS_for_ST[k],\n", " qbv=qbv,\n", " ),\n", - " ctrl=ctrl,\n", " )\n", "\n", " qmod = create_model(main)\n", diff --git a/tutorials/technology_demonstrations/hhl/hhl.ipynb b/tutorials/technology_demonstrations/hhl/hhl.ipynb index b834abe3..fa95ceec 100644 --- a/tutorials/technology_demonstrations/hhl/hhl.ipynb +++ b/tutorials/technology_demonstrations/hhl/hhl.ipynb @@ -115,9 +115,10 @@ }, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from classiq import (\n", + " CArray,\n", + " CInt,\n", + " CReal,\n", " CustomHardwareSettings,\n", " Output,\n", " Preferences,\n", @@ -125,7 +126,6 @@ " QBit,\n", " QCallable,\n", " QNum,\n", - " QParam,\n", " QuantumProgram,\n", " allocate,\n", " allocate_num,\n", @@ -140,7 +140,11 @@ " unitary,\n", " within_apply,\n", ")\n", - "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n", + "from classiq.execution import (\n", + " ClassiqBackendPreferences,\n", + " ClassiqSimulatorBackendNames,\n", + " ExecutionPreferences,\n", + ")\n", "from classiq.qmod.symbolic import floor, log\n", "from classiq.synthesis import set_execution_preferences\n", "\n", @@ -153,8 +157,8 @@ "\n", "@qfunc\n", "def my_hhl(\n", - " precision: QParam[int],\n", - " b: QParam[List[float]],\n", + " precision: CInt,\n", + " b: CArray[CReal],\n", " unitary: QCallable[QArray[QBit]],\n", " res: Output[QArray[QBit]],\n", " phase: Output[QNum],\n", @@ -196,7 +200,7 @@ " transpilation_option=transpilation_options[\"classiq\"],\n", " )\n", " backend_preferences = ClassiqBackendPreferences(\n", - " backend_name=\"aer_simulator_statevector\"\n", + " backend_name=ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR\n", " )\n", "\n", " qmod_hhl = set_preferences(qmod_hhl, preferences)\n", @@ -226,7 +230,7 @@ " sol_pos = list(res_hhl.physical_qubits_map[\"res\"]) # position of solution\n", " phase_pos = list(\n", " res_hhl.physical_qubits_map[\"phase\"]\n", - " ) # position of the \u201cphase\u201d register, and flips for endianness as we will use the indices to read directly from the string\n", + " ) # position of the “phase” register, and flips for endianness as we will use the indices to read directly from the string\n", " qsol = [\n", " np.round(parsed_state.amplitude / (1 / 2**precision), 5)\n", " for solution in range(2**num_qubits)\n", @@ -234,7 +238,7 @@ " if parsed_state[\"indicator\"] == 1.0\n", " and parsed_state[\"res\"] == solution\n", " and parsed_state[\"phase\"]\n", - " == 0.0 # this takes the entries where the \u201cphase\u201d register is at state zero\n", + " == 0.0 # this takes the entries where the “phase” register is at state zero\n", " ]\n", " fidelity = (\n", " np.abs(\n", diff --git a/tutorials/technology_demonstrations/qpe/qpe_for_grover_operator/qpe_for_grover_operator.ipynb b/tutorials/technology_demonstrations/qpe/qpe_for_grover_operator/qpe_for_grover_operator.ipynb index 4db7a110..8d4389ad 100644 --- a/tutorials/technology_demonstrations/qpe/qpe_for_grover_operator/qpe_for_grover_operator.ipynb +++ b/tutorials/technology_demonstrations/qpe/qpe_for_grover_operator/qpe_for_grover_operator.ipynb @@ -40,26 +40,25 @@ }, "outputs": [], "source": [ - "from typing import List\n", - "\n", "from classiq import (\n", + " CArray,\n", + " CInt,\n", " H,\n", " Output,\n", " QArray,\n", " QBit,\n", " QNum,\n", - " QParam,\n", " U,\n", " X,\n", " Z,\n", " allocate,\n", " allocate_num,\n", + " control,\n", " create_model,\n", " hadamard_transform,\n", " invert,\n", " qfunc,\n", " qpe,\n", - " quantum_if,\n", " repeat,\n", " synthesize,\n", " within_apply,\n", @@ -139,10 +138,10 @@ "\n", "\n", "@qfunc\n", - "def my_state_preparation(states: QParam[List[int]], x: QNum, ind: QBit):\n", + "def my_state_preparation(states: CArray[CInt], x: QNum, ind: QBit):\n", "\n", " hadamard_transform(x)\n", - " repeat(states.len, lambda i: quantum_if(x == states[i], lambda: X(ind)))" + " repeat(states.len, lambda i: control(x == states[i], lambda: X(ind)))" ] }, { @@ -169,7 +168,7 @@ " within_apply(\n", " lambda: invert(lambda: my_state_preparation(ints_to_flip, x, ind)),\n", " lambda: within_apply(\n", - " lambda: (X(ind), H(ind)), lambda: quantum_if(x == 0, lambda: X(ind))\n", + " lambda: (X(ind), H(ind)), lambda: control(x == 0, lambda: X(ind))\n", " ), # zero oracle 1-|0><0|\n", " )\n", " U(0, 0, 0, np.pi, ind)" diff --git a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_1.ipynb b/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_1.ipynb deleted file mode 100644 index 608ce9bb..00000000 --- a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_1.ipynb +++ /dev/null @@ -1,619 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The Qmod Workshop - Introduction\n", - "\n", - "The Classiq platform features a high-level quantum modeling language called Qmod. Qmod is compiled into concrete gate-level implementation using a powerful synthesis engine that optimizes and adapts the implementation to different target hardware/simulation environments.\n", - "\n", - "In this workshop, we will learn how to write quantum models using Qmod. We will be using the Python embedding of Qmod, available as part of the Classiq Python SDK. We will learn basic concepts in the Qmod language, such as functions, operators, quantum variables, and quantum types. We will develop useful building blocks and small algorithms.\n", - "\n", - "The [QMOD language reference](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/) covers these concepts more systematically and includes more examples.\n", - "\n", - "This workshop consists of step-by-step exercises. It is structured as follows:\n", - "\n", - "- Part 1: Language Fundamentals - Exercises 1-5\n", - "- Part 2: Higher-Level Concepts - Exercises 6-10\n", - "- Part 3: Execution Flows - Exercises 11, 12\n", - "\n", - "The introduction and Part 1 are included in this notebook. Part 2 and 3 are each in its own separate notebook. For each exercise you will find the solution to the exercises at the bottom of the same notebook.\n", - "\n", - "### Preparations\n", - "\n", - "Make sure you have a Python version of 3.8 through 3.11 installed. Unfortunately, Classiq is not yet supported with Python 3.12.\n", - "\n", - "Install Classiq’s Python SDK by following the instructions on this page: [Getting Started - Classiq](https://docs.classiq.io/latest/getting-started/).\n", - "\n", - "### Python Qmod Exercises - General Instructions\n", - "\n", - "In order to synthesize and execute your Qmod code, you should:\n", - "1. Make sure you define a `main` function that calls functions you create.\n", - "2. Use `create_model` by running `qmod = create_model(main)` to construct a representation of your model.\n", - "3. You can synthesize the model (using `qprog = synthesize(qmod)`) to obtain an implementation - a quantum program.\n", - "4. You can then visualize the quantum program (`show(qprog)`) or execute it (using `execute(qprog)`. See: [Execution - Classiq](https://docs.classiq.io/latest/user-guide/platform/executor/#full-example)). You can also execute it with the IDE after visualizing the circuit.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 0: From Model to Execution\n", - "\n", - "The following model defines a function that applies X and H gates on a single qubit, and subsequently calls it:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "\n", - "# Define a quantum function using the @qfunc decorator\n", - "@qfunc\n", - "def foo(q: QBit) -> None:\n", - " X(target=q)\n", - " H(target=q)\n", - "\n", - "\n", - "# Define a main function\n", - "@qfunc\n", - "def main(res: Output[QBit]) -> None:\n", - " allocate(1, res)\n", - " foo(q=res)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Create a model from it, and synthesize, visualize, and execute it.\n", - "\n", - "Use the General Instructions above to do so.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In Qmod `QBit` is the simplest quantum type, and in this example, `q` is a quantum variable of type `QBit`. Quantum variables abstract away the mapping of quantum objects to qubits in the actual circuit.\n", - "\n", - "See also [Quantum Variables](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-variables/).\n", - "\n", - "We will discuss other quantum types during the workshop.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The Qmod Workshop - Part 1: Language Fundamentals\n", - "\n", - "Follow exercises 1 through 5 for the first session of the workshop." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Exercise 1 - Bell Pair\n", - "\n", - "Create a function that takes two single-qubit (`QBit`) quantum arguments and prepares the bell state on them ([Bell state](https://en.wikipedia.org/wiki/Bell_state)) by applying `H` on one variable and then using it as the control of a `CX` function with the second variable as the target.\n", - "Create a main function that uses this function and has two single-qubit outputs, initialize them to the |0> state (using the `allocate` function), and apply your function to them.\n", - "\n", - "See also [Functions](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/functions#syntax)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use qubit array subscript (the syntax - _variable_ **[** _index-expression_ **]**) to change the function from subsection 1 to receive a single quantum variable, a qubit array (`QArray`) of size 2.\n", - "Change your main function to declare a single output (also an array of size 2).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Exercise 2 - Repeat\n", - "\n", - "Use the built-in `repeat` operator to create your own Hadamard transform function (call it `my_hadamard_transform`). The Hadamard transform function is a function that takes as argument a qubit array of an unspecified size and applies `H` to each of its qubit.\n", - "\n", - "See also [Classical repeat](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/classical-control-flow/#classical-repeat).\n", - "\n", - "Set your main function to have a quantum array output of unspecified size, allocate 10 qubits, and then apply your Hadamard transform function.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Note: Quantum Variable Capture\n", - "The `repeat` operator invokes a statement block multiple times. The statement block is specified using a Python callable, typically a lambda expression. Inside the block you can refer to variables declared in the outer function scope.\n", - "This concept is called `quantum variable capture`, equivalent to [capture](https://en.wikipedia.org/wiki/Closure_(computer_programming)) in classical languages.\n", - "\n", - "See also [Capturing context variables and parameters](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/operators/#capturing-context-variables-and-parameters)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3 - Power\n", - "Raising a quantum operation to a power appears in many known algorithms, for examples, in Grover search and Quantum Phase Estimation.\n", - "For most operations, it simply means repeating the same circuit multiple times.\n", - "\n", - "Sometimes, however, power can be simplified, thus saving computational resources.\n", - "The most trivial example is a quantum operation expressed as a single explicit unitary matrix (i.e., all n*n matrix terms are given) - raising the operation can be done by raising the matrix to that power via classical programming.\n", - "\n", - "See also [Power operator](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n", - "\n", - "Use the following code to generate a 2-qubit (real) unitary matrix:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from typing import List\n", - "\n", - "import numpy as np\n", - "\n", - "from classiq import *\n", - "\n", - "rng = np.random.default_rng(seed=0)\n", - "random_matrix = rng.random((4, 4))\n", - "qr_unitary, _ = np.linalg.qr(random_matrix)\n", - "\n", - "unitary_matrix = QConstant(\"unitary_matrix\", List[List[float]], qr_unitary.tolist())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to reuse some classical value we can define a `QConstant` to store that value.\n", - "\n", - "1. Create a model that applies `unitary_matrix` on a 2 qubit variable.\n", - "2. Create another model that applies `unitary_matrix` raised to power 3 on a 2 qubit variable.\n", - "3. Compare the gate count via the Classiq’s IDE in both cases.\n", - "\n", - "Note - the signature of function `unitary` is:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def unitary(\n", - " elements: QParam[List[List[float]]],\n", - " target: QArray[QBit, Literal[\"log(len(elements[0]), 2)\"]],\n", - ") -> None:\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Exercise 4 - User-defined Operators\n", - "Create a function that applies a given single-qubit operation to all qubits in its quantum argument (Call your function `my_apply_to_all`). Such a function is also called an operator, i.e. a function that one of its arguments is another function (its operand).\n", - "\n", - "See also [Operators](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/operators/).\n", - "\n", - "Follow these guidelines:\n", - "1. Your function should declare a quantum argument of type qubit array. It should also declare an argument of a function type with a single qubit argument.\n", - "2. The body should apply the operand to all qubits in the argument.\n", - "\n", - "When you're done, re-implement `my_hadamard_transform` from exercise 2 using this function instead of `repeat`.\n", - "Use the same main function from exercise 2." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Exercise 5 - Quantum Conditionals\n", - "\n", - "### Exercise 5a - Control Operator\n", - "Use the built-in `control` operator to create a function that receives two single qubit variables and uses one of the variables to control an RY gate with a `pi/2` angle acting on the other variable (without using the `CRY` function).\n", - "\n", - "See also [Quantum operators](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-operators/#syntax).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5b - Quantum If\n", - "The `control` operator is the conditional application of some operation, with the condition being that all control qubits are in the state |1>. This notion is generalized in QMOD to other control states, where the condition is specified as a comparison between a quantum numeric variable and a numeric value, similar to a classical `if` statement. Quantum numeric variables are declared with class `QNum`.\n", - "\n", - "See also [Numeric types](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", - "\n", - "In QMOD this generalization is available as a native statement - quantum-if.\n", - "\n", - "See also [Quantum if](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/quantum-if/).\n", - "\n", - "1. Declare a `QNum` output argument using `Output[QNum]` and name it `x`.\n", - "2. Use the `prepare_int` function to initialize it to `9`. Note that you don't need to specify the `QNum` attributes - size, sign, and fraction digits, as they are inferred at the point of initialization.\n", - "3. Execute the circuit and observe the results.\n", - "4. Declare another output argument of type `QBit` and perform a `quantum_if` such that under the condition that `x` is 9, the qubit is flipped. Execute the circuit and observe the results. Repeat for a different condition." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Solutions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for Exercise 1 part 1:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def bell(q0: QBit, q1: QBit) -> None:\n", - " H(q0)\n", - " CX(q0, q1)\n", - "\n", - "\n", - "@qfunc\n", - "def main(qubit0: Output[QBit], qubit1: Output[QBit]) -> None:\n", - " allocate(1, qubit0)\n", - " allocate(1, qubit1)\n", - " bell(qubit0, qubit1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for Exercise 1 part 2:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def bell(q: QArray[QBit, 2]) -> None:\n", - " H(q[0])\n", - " CX(q[0], q[1])\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit, 2]]) -> None:\n", - " allocate(2, q)\n", - " bell(q)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for Exercise 2:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def my_hadamard_transform(q: QArray[QBit]) -> None:\n", - " repeat(q.len(), lambda i: H(q[i]))\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(10, q)\n", - " my_hadamard_transform(q)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 3:\n", - "\n", - "\n", - "from typing import List\n", - "\n", - "import numpy as np\n", - "\n", - "from classiq import *\n", - "\n", - "rng = np.random.default_rng(seed=0)\n", - "random_matrix = rng.random((4, 4))\n", - "qr_unitary, _ = np.linalg.qr(random_matrix)\n", - "\n", - "unitary_matrix = QConstant(\"unitary_matrix\", List[List[float]], qr_unitary.tolist())\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(2, q)\n", - " power(3, lambda: unitary(unitary_matrix, q))\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for exercise 4:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def my_apply_to_all(operand: QCallable[QBit], q: QArray[QBit]) -> None:\n", - " repeat(q.len(), lambda i: operand(q[i]))\n", - "\n", - "\n", - "@qfunc\n", - "def my_hadamard_transform(q: QArray[QBit]) -> None:\n", - " my_apply_to_all(lambda t: H(t), q)\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(10, q)\n", - " my_hadamard_transform(q)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for exercise 5a:\n", - "\n", - "\n", - "from classiq import *\n", - "from classiq.qmod.symbolic import pi\n", - "\n", - "\n", - "@qfunc\n", - "def my_controlled_ry(control_bit: QBit, target: QBit) -> None:\n", - " control(lambda: RY(pi / 2, target), control_bit)\n", - "\n", - "\n", - "@qfunc\n", - "def main(control_bit: Output[QBit], target: Output[QBit]) -> None:\n", - " allocate(1, control_bit)\n", - " allocate(1, target)\n", - " my_controlled_ry(control_bit, target)\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution for exercise 5b:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(x: Output[QNum], target: Output[QBit]) -> None:\n", - " prepare_int(9, x)\n", - " allocate(1, target)\n", - " quantum_if(x == 9, lambda: X(target))\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_2.ipynb b/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_2.ipynb deleted file mode 100644 index 5eaf8515..00000000 --- a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_2.ipynb +++ /dev/null @@ -1,735 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The Qmod Workshop - Part 2: Higher-Level Concepts\n", - "\n", - "This is the second part of the Qmod workshop, covering exercises 6 through 10. Make sure to go through Part 1 before continuing with this notebook." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6 - Exponentiation and Pauli Operators\n", - "\n", - "The Qmod language supports different classical types: scalars, arrays, and structs. Structs are objects with member variables, or fields.\n", - "\n", - "See also [Classical Types](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/classical-types/#structs).\n", - "\n", - "The builtin struct type `PauliTerm` is defined as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@struct\n", - "class PauliTerm:\n", - " pauli: List[Pauli]\n", - " coefficient: float" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that `Pauli` is an enum for all the Pauli matrices (I, X, Y, Z).\n", - "\n", - "Pauli based hamiltonian can be represented as a list of `PauliTerm`s. A Pauli operator defined this way is the argument to a hamiltonian evolution functions.\n", - "\n", - "In this exercise we will use the Suzuki-Trotter function to find the evolution of `H=0.5XZXX + 0.25YIZI + 0.3 XIZY` (captured as a literal value for the pauli-operator), with the evolution coefficient being 3, the order being 2, and use 4 repetitions.\n", - "\n", - "The declaration of the `suzuki_trotter` function is:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@qfunc(external=True)\n", - "def suzuki_trotter(\n", - " pauli_operator: QParam[List[PauliTerm]],\n", - " evolution_coefficient: QParam[float],\n", - " order: QParam[int],\n", - " repetitions: QParam[int],\n", - " qbv: QArray[QBit],\n", - ") -> None:\n", - " pass" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Fill in the missing parts of the following code in order to complete this exercise:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(4, q)\n", - " suzuki_trotter(\n", - " ...,\n", - " evolution_coefficient=3,\n", - " repetitions=4,\n", - " order=2,\n", - " qbv=q,\n", - " )\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 7 - Basic Arithmetics\n", - "\n", - "#### Exercise 7a\n", - "In this exercise we will use quantum numeric variables and calculate expressions over them.\n", - "\n", - "See details on the syntax of numeric types under [Quantum types](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/quantum-types/#syntax).\n", - "See more on quantum expressions under [Numeric assignment](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/)\n", - "\n", - "Create the following quantum programs:\n", - "1. Initialize variables `x=2`, `y=7` and computes `res = x + y`.\n", - "2. Initialize variables `x=2`, `y=7` and computes `res = x * y`.\n", - "3. Initialize variables `x=2`, `y=7`, `z=1` and computes `res = x * y - z`.\n", - "\n", - "Guidance:\n", - "* Use the operator `|=` to perform out-of-place assignment of arithmetic expression.\n", - "* To initialize the variables, use the function `prepare_int`.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Exercise 7b\n", - "Declare `x` to be a 2-qubit variable and `y` to be 3-qubit variable.\n", - "\n", - "We will perform an addition of two superposition states: `x` is an equal superposition of `0` and `2`, and `y` is an equal superposition of `1`, `2`, `3`, and `6`.\n", - "\n", - "1. Use `prepare_state` to initialize `x` and `y`. Note that `prepare_state` works with probabilities, not amplitudes.\n", - " The declaration of the `prepare_state` function is:\n", - " ```\n", - " @qfunc(external=True)\n", - " def prepare_state(\n", - " probabilities: QParam[List[float]],\n", - " bound: QParam[float],\n", - " out: Output[QArray[QBit, Literal[\"log(len(probabilities), 2)\"]]],\n", - " ) -> None:\n", - " pass\n", - " ```\n", - " (Set the bound to 0 in your code)\n", - "2. Compute `res = x + y`. Execute the resulting circuit. What did you get?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 8 - Within-Apply\n", - "\n", - "The within-apply statement applies the pattern `U_dagger V U` that appears frequently in quantum computing.\n", - "It allows you to compute some function `V` within the context of another function `U`, and afterward uncompute `U` in order to release auxiliary qubits storing intermediate results.\n", - "\n", - "See also [Within Apply](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/within-apply/).\n", - "\n", - "#### Exercise 8a\n", - "\n", - "In this exercise, we will use within-apply to compute an arithmetic expression in steps.\n", - "\n", - "Use the `within_apply` operation to calculate `res = x + y + z` from a two-variable addition building block with the following steps:\n", - "1. Add `x` and `y`\n", - "2. Add the result to `z`\n", - "3. Uncompute the result of the first operation\n", - "\n", - "For simplicity, initialize the registers to simple integers: `x=3`, `y=5`, `z=2`.\n", - "\n", - "Hints:\n", - "\n", - "* Use a temporary variable.\n", - "* Wrap the arithmetic operation in a function.\n", - "\n", - "Execute the circuit and make sure you obtain the expected result." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Exercise 8b\n", - "\n", - "Why should we use `within-apply` and not just write three concatenated functions?\n", - "To understand the motivation, we will create another arithmetic circuit.\n", - "This time, however, we will also set Classiq’s synthesis engine to optimize on the circuit’s number of qubits, i.e., its width.\n", - "\n", - "Setting constraints can be done via the `set_constraints` operation - see [here](https://docs.classiq.io/latest/user-guide/platform/synthesis/constraints/).\n", - "\n", - "Perform the operation `res = w + x + y + z`, where w is initialized to 4 and the rest as before:\n", - "\n", - "1. Add `x` and `y` (as part of the `within_apply` operation)\n", - "2. Add the result to `z` (as part of the within_apply operation)\n", - "3. Uncompute the result of the first operation (as part of the `within_apply` operation)\n", - "4. Add the result of the second operation to `w`. There’s no need to perform another uncomputation, as this brings our calculation to an end.\n", - "\n", - "Create the model, optimize on the circuit’s width, and run the circuit. Can you identify where qubits have been released and reused?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Bonus: Use a Single Arithmetic Expression\n", - "\n", - "What happens when we don't manually decompose this expression?\n", - "\n", - "Use Classiq’s arithmetic engine to calculate `res |= x + y + z + w` and optimize for width.\n", - "Look at the resulting quantum program - can you identify the computation and uncomputation blocks? What else did you notice?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 9 - In-place Arithmetics\n", - "\n", - "For the following exercise we will use numeric quantum variables that represent fixed-point reals.\n", - "\n", - "Arithmetic expressions can be calculated in-place into a target variable, without allocating new qubits to store the result. This is done using the in-place-xor operator.\n", - "\n", - "See also [Numeric assignment](https://docs.classiq.io/latest/user-guide/platform/qmod/language-reference/statements/numeric-assignment/#semantics).\n", - "\n", - "In-place assignment is often used to nest arithmetic expressions under quantum operators. Note that out-of-place assignment requires its left-value variable to be un-initialized, and therefore cannot be used under an operator if the variable is declared outside its scope. Applying operators to arithmetic expressions is required in many algorithms. One example is the piecewise evaluation of mathematical functions - calculating different expressions over `x` depending on the subdomain where `x` falls.\n", - "\n", - "For this exercise, replace the missing parts in the code snippet below to evaluate the result of:\n", - "\n", - "$$\n", - "f(x) = \\begin{cases}\n", - " 2x + 1 & \\text{ if } 0 \\leq x < 0.5 \\\\\n", - " x + 0.5 & \\text{ if } 0.5 \\leq x < 1\n", - " \\end{cases}\n", - "$$\n", - "\n", - "Notes:\n", - "- We cannot use `x` directly as the control variable in a `constrol` operator, because it also occurs in the nested scope. to determine if `x` is in the lower or higher half of the domain we duplicate the most significant bit onto a separate variable called `label`.\n", - "- In Python assignment operators cannot be used in lambda expressions, so the computation of the function needs to be factored out to a named Python function (but not necessarily a Qmod function).\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def dup_msb(qba: QArray[QBit], msb: QBit) -> None:\n", - " CX(qba[qba.len() - 1], msb)\n", - "\n", - "\n", - "@qfunc\n", - "def main(x: Output[QNum[3, False, 3]], res: Output[QNum[5, False, 3]]) -> None:\n", - " allocate(5, res)\n", - " allocate(3, x)\n", - " hadamard_transform(x)\n", - "\n", - " label = QNum(\"label\")\n", - " allocate(1, label)\n", - "\n", - " dup_msb(x, label)\n", - " control(..., label) # 0.5 <= x < 1.0\n", - " X(label)\n", - " control(..., label) # 0.0 <= x < 0.5\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 10 - State-preparation Algorithm using Quantum-if\n", - "\n", - "#### Binding\n", - "The `bind` operation allows to convert smoothly between different quantum types and split or slice bits when necessary. Here’s an example:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QArray[QBit]]) -> None:\n", - " x: QArray[QBit] = QArray(\"x\")\n", - " allocate(3, x)\n", - " ...\n", - " lsb = QBit(\"lsb\")\n", - " msb = QNum(\"msb\", 2, False, 0)\n", - " bind(x, [lsb, msb])\n", - " ...\n", - " bind([lsb, msb], res)\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first `bind` operation splits the 3-qubit register `x` into the 2-qubit and single-qubit registers `lsb` and `msb`, respectively.\n", - "\n", - "After the `bind` operation:\n", - "1. The registers `lsb` and `msb` can be operated on as separated registers.\n", - "2. The register`x` is consumed and can no longer be used.\n", - "\n", - "The second `bind` operation concatenates the registers to the output register `res`.\n", - "\n", - "For this exercise, fill in the missing code parts in the above snippet and use the `quantum_if` statement to manually generate the following lovely 3-qubit probability distribution: `[1/8, 1/8, 1/8, -sqrt(3)/16, 1/8 + sqrt(3)/16, 1/8, 1/8, 1/8, 1/8]`.\n", - "\n", - "The following series of gates generate it:\n", - "\n", - "Perform the Hadamard transform on all three qubits.\n", - "\n", - "Apply a rotation on the LSB (least-significant bit) conditioned by the MSB being |0> and the second to last MSB being |1>. How would you write this condition using a QNum?\n", - "\n", - "The following series of gates generate it:\n", - "1. Perform the Hadamard transform on all three qubits.\n", - "2. Apply a `pi/3` rotation on the LSB (least-significant bit) conditioned by the MSB being |0> and the second to last MSB being |1>. How would you write this condition using a QNum?\n", - "\n", - "If you want to validate your results without looking at the full solution, compare them to running using Classiq’s built-in `prepare_state` function.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "from classiq.qmod.symbolic import sqrt\n", - "\n", - "\n", - "@qfunc\n", - "def pre_prepared_state(q: QArray[QBit]) -> None:\n", - " prepare_state(\n", - " [\n", - " 1 / 8,\n", - " 1 / 8,\n", - " 1 / 8,\n", - " -sqrt(3) / 16,\n", - " 1 / 8 + sqrt(3) / 16,\n", - " 1 / 8,\n", - " 1 / 8,\n", - " 1 / 8,\n", - " 1 / 8,\n", - " ],\n", - " 0.0,\n", - " q,\n", - " )\n", - "\n", - "\n", - "# Your code here:" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Solutions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 6" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 6:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QArray[QBit]]) -> None:\n", - " allocate(4, q)\n", - " suzuki_trotter(\n", - " [\n", - " PauliTerm([Pauli.X, Pauli.Z, Pauli.X, Pauli.X], 0.5),\n", - " PauliTerm([Pauli.Y, Pauli.I, Pauli.Z, Pauli.I], 0.25),\n", - " PauliTerm([Pauli.X, Pauli.I, Pauli.Z, Pauli.Y], 0.3),\n", - " ],\n", - " evolution_coefficient=3,\n", - " repetitions=4,\n", - " order=2,\n", - " qbv=q,\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 7" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 7a:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QNum]) -> None:\n", - " x = QNum(\"x\")\n", - " y = QNum(\"y\")\n", - " z = QNum(\"z\")\n", - " prepare_int(2, x)\n", - " prepare_int(7, y)\n", - " prepare_int(1, z)\n", - " res |= x + y\n", - " # res |= x * y\n", - " # res |= x * y - z" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 7b:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QNum]) -> None:\n", - " x = QNum(\"x\")\n", - " y = QNum(\"y\")\n", - " prepare_state([0.5, 0, 0.5, 0.0], 0.0, x)\n", - " prepare_state([0, 0.25, 0.25, 0.25, 0.0, 0.0, 0.25, 0.0], 0.0, y)\n", - " res |= x + y\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 8" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 8:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def my_add(x: QNum, y: QNum, res: Output[QNum]) -> None:\n", - " res |= x + y\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QNum]) -> None:\n", - " x = QNum(\"x\")\n", - " y = QNum(\"y\")\n", - " z = QNum(\"z\")\n", - " prepare_int(3, x)\n", - " prepare_int(5, y)\n", - " prepare_int(2, z)\n", - "\n", - " temp = QNum(\"temp\")\n", - " within_apply(\n", - " compute=lambda: my_add(x, y, temp), action=lambda: my_add(temp, z, res)\n", - " )\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to the advanced part of exercise 8:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "@qfunc\n", - "def my_add(x: QNum, y: QNum, res: Output[QNum]) -> None:\n", - " res |= x + y\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QNum]) -> None:\n", - " x = QNum(\"x\")\n", - " y = QNum(\"y\")\n", - " z = QNum(\"z\")\n", - " w = QNum(\"w\")\n", - " prepare_int(3, x)\n", - " prepare_int(5, y)\n", - " prepare_int(2, z)\n", - " prepare_int(4, w)\n", - "\n", - " temp_xy = QNum(\"temp_xy\")\n", - " xyz = QNum(\"xyz\")\n", - " within_apply(\n", - " compute=lambda: my_add(x, y, temp_xy), action=lambda: my_add(temp_xy, z, xyz)\n", - " )\n", - " res |= xyz + w\n", - "\n", - "\n", - "model = create_model(main)\n", - "model = set_constraints(\n", - " model, Constraints(optimization_parameter=OptimizationParameter.WIDTH)\n", - ")\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 9" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 9:\n", - "\n", - "\n", - "from classiq import *\n", - "\n", - "\n", - "def linear_func(a: float, b: float, x: QNum, res: QNum) -> None:\n", - " res ^= a * x + b\n", - "\n", - "\n", - "@qfunc\n", - "def dup_msb(qba: QArray[QBit], msb: QBit) -> None:\n", - " CX(qba[qba.len() - 1], msb)\n", - "\n", - "\n", - "@qfunc\n", - "def main(x: Output[QNum[3, False, 3]], res: Output[QNum[5, False, 3]]) -> None:\n", - " allocate(5, res)\n", - " allocate(3, x)\n", - " hadamard_transform(x)\n", - "\n", - " label = QNum(\"label\")\n", - " allocate(1, label)\n", - "\n", - " dup_msb(x, label)\n", - " control(lambda: linear_func(1.0, 0.5, x, res), label) # 0.5 <= x < 1.0\n", - " X(label)\n", - " control(lambda: linear_func(2.0, 1.0, x, res), label) # 0.0 <= x < 0.5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 10" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 10:\n", - "\n", - "\n", - "from classiq import *\n", - "from classiq.qmod.symbolic import pi\n", - "\n", - "\n", - "@qfunc\n", - "def main(res: Output[QArray[QBit]]) -> None:\n", - " x: QArray[QBit] = QArray(\"x\")\n", - " allocate(3, x)\n", - " hadamard_transform(x)\n", - "\n", - " lsb = QBit(\"lsb\")\n", - " msb = QNum(\"msb\", 2, False, 0)\n", - " bind(x, [lsb, msb])\n", - "\n", - " quantum_if(msb == 1, lambda: RY(pi / 3, lsb))\n", - "\n", - " bind([lsb, msb], res)\n", - "\n", - "\n", - "model = create_model(main)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_3.ipynb b/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_3.ipynb deleted file mode 100644 index ec4fc3f5..00000000 --- a/tutorials/workshops/QMOD_workshop/QMOD_Workshop_Part_3.ipynb +++ /dev/null @@ -1,276 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The Qmod Workshop - Part 3: Execution Flows\n", - "\n", - "This is the third part of the Qmod workshop, covering exercises 11 and 12. Make sure to go through Part 1 and 2 before continuing with this notebook." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 11 - Execution with Parameters\n", - "\n", - "In this exercise, we will modify the manually created state preparation function from the previous exercise to accept a rotation angle as a parameter.\n", - "\n", - "1. Start by modifying the signature of the main function to be as follows:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "@qfunc\n", - "def main(rotation_angle: QParam[float], res: Output[QArray[QBit]]) -> None:\n", - " pass" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "2. Pass the rotation angle as a parameter to the controlled RY instead of using `pi/3` directly.\n", - "3. Define the following quantum constant, which will serve as the list of execution parameters:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "angle_vals = QConstant(\"angle_vals\", List[float], [pi / 3, pi / 2])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "4. Create a cmain function that for each rotation angle, it calls the sample function and saves the result.\n", - "5. Execute the circuit and make sure the results are as expected (statistics from two runs should appear. What happens for `pi/2`?).\n", - "6. **Bonus**: try to add other values to the list and observe the results." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "# Your code here:\n", - "\n", - "\n", - "qmod = create_model(main)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 12 - VQE\n", - "\n", - "The Variational Quantum Eigensolver is an algorithm that finds the minimal eigenvalue of a matrix by executing a parametric circuit (also referred to as an ansatz), estimating the expected value of the matrix for the state the circuit creates (from the distribution received by the execution), and using a classical optimizer to select the next set of parameters for the circuit, until reaching convergence (or exceeding a set amount of maximum iterations).\n", - "\n", - "The estimation of the expectation value is done on Pauli based matrices, so any matrix we want to perform this operation on, need to be decomposed into a sum of Pauli terms.\n", - "\n", - "In this exercise, we will create a simple VQE algorithm that estimates the minimal eigenvalue of a 2x2 matrix.\n", - "Fill in the gaps in the following snippet to find the minimal eigenvalue and it corresponding eigenstate for\n", - "\n", - "`[[1, -1], [-1, 0]] = 1/2*I + 1/2*Z - X`\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from classiq import *\n", - "\n", - "HAMILTONIAN = QConstant(...)\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QBit], angles: QParam[Array[float, 3]]) -> None:\n", - " allocate(1, q)\n", - " U(angles[0], angles[1], angles[2], 0, q)\n", - "\n", - "\n", - "@cfunc\n", - "def cmain() -> None:\n", - " res = vqe(\n", - " hamiltonian=...,\n", - " maximize=...,\n", - " initial_point=[],\n", - " optimizer=Optimizer.COBYLA,\n", - " max_iteration=1000,\n", - " tolerance=0.001,\n", - " step_size=0,\n", - " skip_compute_variance=False,\n", - " alpha_cvar=1.0,\n", - " )\n", - " save({\"result\": res})\n", - "\n", - "\n", - "qmod = create_model(main, classical_execution_function=cmain)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)\n", - "res = execute(qprog)\n", - "vqe_result = res.result()[0].value\n", - "print(vqe_result.energy, vqe_result.optimal_parameters, vqe_result.eigenstate)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note:\n", - "The U gate is a general rotation matrix on a single qubit, so the given model creates an ansatz that spans all of the space for a single qubit, and thus gives us a full search space for this specific problem." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Solutions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 11" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 11:\n", - "\n", - "\n", - "from typing import List\n", - "\n", - "from classiq import *\n", - "from classiq.qmod.symbolic import pi\n", - "\n", - "\n", - "@qfunc\n", - "def main(rotation_angle: QParam[float], res: Output[QArray[QBit]]) -> None:\n", - " x: QArray[QBit] = QArray(\"x\")\n", - " allocate(3, x)\n", - " hadamard_transform(x)\n", - "\n", - " ls_bit = QBit(\"ls_bit\")\n", - " ms_bits = QNum(\"ms_bits\", 2, False, 0)\n", - " bind(x, [ls_bit, ms_bits])\n", - "\n", - " quantum_if(ms_bits == 1, lambda: RY(rotation_angle, ls_bit))\n", - "\n", - " bind([ls_bit, ms_bits], res)\n", - "\n", - "\n", - "angle_vals = QConstant(\"angle_vals\", List[float], [pi / 3, pi / 2])\n", - "\n", - "\n", - "@cfunc\n", - "def cmain() -> None:\n", - " result = sample({\"rotation_angle\": angle_vals[0]})\n", - " save({\"result\": result})\n", - " result = sample({\"rotation_angle\": angle_vals[1]})\n", - " save({\"result\": result})\n", - "\n", - "\n", - "model = create_model(main, classical_execution_function=cmain)\n", - "qprog = synthesize(model)\n", - "show(qprog)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 12" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Solution to exercise 12:\n", - "\n", - "\n", - "from typing import List\n", - "\n", - "from classiq import *\n", - "\n", - "HAMILTONIAN = QConstant(\"HAMILTONIAN\", List[PauliTerm], [...])\n", - "\n", - "\n", - "@qfunc\n", - "def main(q: Output[QBit], angles: QParam[Array[float, 3]]) -> None:\n", - " allocate(1, q)\n", - " U(angles[0], angles[1], angles[2], 0, q)\n", - "\n", - "\n", - "@cfunc\n", - "def cmain() -> None:\n", - " res = vqe(\n", - " HAMILTONIAN,\n", - " False,\n", - " [],\n", - " optimizer=Optimizer.COBYLA,\n", - " max_iteration=1000,\n", - " tolerance=0.001,\n", - " step_size=0,\n", - " skip_compute_variance=False,\n", - " alpha_cvar=1.0,\n", - " )\n", - " save({\"result\": res})\n", - "\n", - "\n", - "qmod = create_model(main, classical_execution_function=cmain)\n", - "qprog = synthesize(qmod)\n", - "show(qprog)\n", - "res = execute(qprog)\n", - "vqe_result = res.result()[0].value\n", - "print(vqe_result.energy, vqe_result.optimal_parameters, vqe_result.eigenstate)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -}