diff --git a/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_iqae.qmod b/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_iqae.qmod index f85e591ce..9368b9ce6 100644 --- a/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_iqae.qmod +++ b/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_iqae.qmod @@ -1,34 +1,68 @@ +// Quantum Counting Using Iterative Quantum Amplitude Estimation + +// Prepares the IQAE input state over the problem variables (a,b) and an indicator qubit. +// The quantum variables are transformed into uniform superposition, and the indicator is computed as: +// ind = 1 iff (a + b) <= THRESHOLD. +// In the IQAE workflow, the indicator qubit defines the “good” subspace; a phase flip (Z) on +// this qubit implements the marking oracle used inside amplitude amplification iterations. + + +// Defining the qstruct, containing the quantum variables a and b, each with two qubits qstruct OracleVars { a: qnum<2>; b: qnum<2>; } -qperm oracle(const est_reg: qbit[]) { - Z(est_reg[est_reg.len - 1]); + + +THRESHOLD: int = 2; // predicate: (a + b) <= THRESHOLD + + + +// Phase oracle: flips the phase of a marked states. +// Here we mark states by applying Z on the indicator qubit (assumed last qubit in est_var). +qperm oracle(const est_var: qbit[]) { + Z(est_var[est_var.len - 1]); } + +// Computes the boolean predicate into `res` via XOR assignment. +// `res` becomes 1 iff (a + b) <= THRESHOLD (assuming it starts at |0⟩). qperm arith_equation(const state: OracleVars, res: qbit) { - res ^= (state.a + state.b) <= 2; + res ^= (state.a + state.b) <= THRESHOLD; } +// State preparation for amplitude amplification: qfunc iqae_state_preparation(vars: OracleVars, ind: qbit) { - hadamard_transform(vars); - arith_equation(vars, ind); + hadamard_transform(vars); // Uniform superposition over all possible states + arith_equation(vars, ind); // Compute predicate into indicator } -qfunc space_transform(est_reg: qbit[]) { - iqae_state_preparation(est_reg[0:est_reg.len - 1], est_reg[est_reg.len - 1]); +// Constructs the state expected by `amplitude_amplification`: +// interprets the first 4 qubits as OracleVars and the last qubit as an indicator. +qfunc space_transform(est_var: qbit[]) { + // est_var = [problem_vars..., indicator] + iqae_state_preparation( + est_var[0:est_var.len - 1], // OracleVars view of the problem qubits + est_var[est_var.len - 1] // Indicator qubit + ); } + qfunc main(k: int, output indicator: qbit) { - est_reg: qbit[]; - problem_vars: qbit[4]; - allocate(problem_vars); - allocate(indicator); + est_var: qbit[]; + problem_vars: OracleVars; + + allocate(problem_vars); // Initiating the indicator qubit + allocate(indicator); // Solution space qubits + + // Create a quantum variable for amplitude amplification. within { - {problem_vars, indicator} -> est_reg; + {problem_vars, indicator} -> est_var; } apply { - amplitude_amplification(k, oracle, space_transform, est_reg); + // Apply k iterations of amplitude amplification using the oracle and space transform. + amplitude_amplification(k, oracle, space_transform, est_var); } - drop(problem_vars); + + drop(problem_vars); // Indicates that the quantum state should not be measured } diff --git a/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_qpe.qmod b/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_qpe.qmod index e7fcf7b00..8ef70fc31 100644 --- a/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_qpe.qmod +++ b/algorithms/amplitude_amplification_and_estimation/quantum_counting/quantum_counting_qpe.qmod @@ -1,23 +1,56 @@ +// Quantum Counting via Quantum Phase Estimation (QPE) + +// Demonstrates quantum counting, which efficiently estimates the number +// of valid (marked) solutions to a search problem, based on the amplitude estimation algorithm. +// It demonstrates a quadratic improvement with regard +// to a classical algorithm with black box oracle access to the function. +// +// We encode two 2-bit unsigned integers (a, b) and mark states satisfying +// (a + b) <= THRESHOLD. +// The Grover operator induced by this oracle has eigenphases that encode +// the solution ratio; QPE extracts an estimate of that phase. + + + + +// Mark states for which (a + b) <= THRESHOLD +THRESHOLD: int = 2; + +// Number of qubits used by the phase quantum variable in the QPE. +// Larger values provide finer phase resolution. +PHASE_QUBITS: int = 5; + +// Defining the qstruct, containing the quantum variables a and b qstruct OracleVars { a: qnum<2>; b: qnum<2>; } +// Predicate: flips `res` iff the input (a, b) is a marked solution. qperm arith_equation(const state: OracleVars, res: qbit) { res ^= (state.a + state.b) <= 2; } +// Convert the predicate into a phase oracle via phase kickback. qfunc arith_oracle(state: OracleVars) { phase_oracle(arith_equation, state); } -qfunc main(output phase_reg: qnum<5, UNSIGNED, 5>) { - state_reg: OracleVars; - allocate(state_reg); - allocate(phase_reg); - hadamard_transform(state_reg); + + +qfunc main(output phase_var: qnum) { + state_var: OracleVars; + + allocate(state_var); // Initiates the ancilla qstruct + allocate(phase_var); // Initiates the phase quantum variable + + // Prepare a uniform superposition over all (a, b) inputs. + hadamard_transform(state_var); + + // Estimate the eigenphase of the Grover operator induced by the oracle. qpe(lambda() { - grover_operator(arith_oracle, hadamard_transform, state_reg); - }, phase_reg); - drop(state_reg); + grover_operator(arith_oracle, hadamard_transform, state_var); + }, phase_var); + + drop(state_var); // Indicates that the quantum state should not be measured } diff --git a/tutorials/basic_tutorials/add_bell_states/add_bell_states.qmod b/tutorials/basic_tutorials/add_bell_states/add_bell_states.qmod index 5f3da85bc..c5a51feb0 100644 --- a/tutorials/basic_tutorials/add_bell_states/add_bell_states.qmod +++ b/tutorials/basic_tutorials/add_bell_states/add_bell_states.qmod @@ -1,5 +1,9 @@ -qfunc main(output a: qnum, output b: qnum, output sum: qnum){ - prepare_state([1/2, 0, 0, 1/2], 0, a); // a is in an equal superposition of 0 and 3 - prepare_state([0, 1/2, 1/2, 0], 0, b); // b is in an equal superposition of 1 and 2 - sum = a + b; +// Add Bell states + +// Prepares two Bell states A and B and adds them + +qfunc main(output A: qnum, output B: qnum, output sum: qnum){ + prepare_state([1/2, 0, 0, 1/2], 0, A); // a is in an equal superposition of 0 and 3 + prepare_state([0, 1/2, 1/2, 0], 0, B); // b is in an equal superposition of 1 and 2 + sum = A + B; } diff --git a/tutorials/basic_tutorials/quantum_primitives/hadamard_test/hadamard_test.qmod b/tutorials/basic_tutorials/quantum_primitives/hadamard_test/hadamard_test.qmod index d5a92e6ed..1759331eb 100644 --- a/tutorials/basic_tutorials/quantum_primitives/hadamard_test/hadamard_test.qmod +++ b/tutorials/basic_tutorials/quantum_primitives/hadamard_test/hadamard_test.qmod @@ -1,21 +1,35 @@ +// Hadamard Test + +// Implements a minimal version of the Hadamard test, +// where an ancilla qubit controls the application of a Quantum +// Fourier Transform (QFT) on a target register. Measuring the ancilla +// allows extracting information about the real part of an expectation +// value associated with the controlled unitary. + +// Utility function, applying a controlled QFT qfunc controlled_qft(expectation_value: qbit, psi: qbit[]) { control (expectation_value) { qft(psi); } } + +// Performs the Hadamard test utilizing the within-applied function implementing +// U-dagger V U, where U is the Hadamard gate and V is the controlled_qft function. qfunc preparation_and_application(expectation_value: qbit, psi: qbit[]) { within { - H(expectation_value); + H(expectation_value); // Creates a superposition of |0> and |1> states } apply { controlled_qft(expectation_value, psi); } } + qfunc main(output expectation_value: qbit) { - psi: qbit[]; - allocate(1, expectation_value); - allocate(4, psi); + psi: qbit[4]; // Target quantum variable, of size 4 + allocate(expectation_value); // Ancilla qubit used for the Hadamard test + allocate(psi); // Initializes the target state + preparation_and_application(expectation_value, psi); - drop(psi); + drop(psi); // Indicates that the quantum state should not be measured }