Skip to content
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
// Quantum Counting via Quantum Phase Estimation (QPE)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments from above apply here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


// 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<PHASE_QUBITS, UNSIGNED, PHASE_QUBITS>) {
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
}
12 changes: 8 additions & 4 deletions tutorials/basic_tutorials/add_bell_states/add_bell_states.qmod
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Capitalize states

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// 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;
}
Original file line number Diff line number Diff line change
@@ -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
}