|
| 1 | +// Quantum Counting Using Iterative Quantum Amplitude Estimation |
| 2 | + |
| 3 | +// Prepares the IQAE input state over the problem variables (a,b) and an indicator qubit. |
| 4 | +// The quantum variables are transformed into uniform superposition, and the indicator is computed as: |
| 5 | +// ind = 1 iff (a + b) <= THRESHOLD. |
| 6 | +// In the IQAE workflow, the indicator qubit defines the “good” subspace; a phase flip (Z) on |
| 7 | +// this qubit implements the marking oracle used inside amplitude amplification iterations. |
| 8 | + |
| 9 | + |
| 10 | +// Defining the QStruct, containing the quantum variables a and b |
1 | 11 | qstruct OracleVars { |
2 | 12 | a: qnum<2>; |
3 | 13 | b: qnum<2>; |
4 | 14 | } |
5 | 15 |
|
6 | | -qperm oracle(const est_reg: qbit[]) { |
7 | | - Z(est_reg[est_reg.len - 1]); |
| 16 | + |
| 17 | +// Configuration constants |
| 18 | +A_BITS: int = 2; |
| 19 | +B_BITS: int = 2; |
| 20 | + |
| 21 | +PROBLEM_QUBITS: int = A_BITS + B_BITS; // 4 qubits: a[2] || b[2] |
| 22 | +THRESHOLD: int = 2; // predicate: (a + b) <= THRESHOLD |
| 23 | + |
| 24 | + |
| 25 | + |
| 26 | +// Phase oracle: flips the phase of a marked states. |
| 27 | +// Here we mark states by applying Z on the indicator qubit (assumed last qubit in est_var). |
| 28 | +qperm oracle(const est_var: qbit[]) { |
| 29 | + Z(est_var[est_var.len - 1]); |
8 | 30 | } |
9 | 31 |
|
| 32 | + |
| 33 | +// Computes the boolean predicate into `res` via XOR assignment. |
| 34 | +// `res` becomes 1 iff (a + b) <= THRESHOLD (assuming it starts at |0⟩). |
10 | 35 | qperm arith_equation(const state: OracleVars, res: qbit) { |
11 | | - res ^= (state.a + state.b) <= 2; |
| 36 | + res ^= (state.a + state.b) <= THRESHOLD; |
12 | 37 | } |
13 | 38 |
|
| 39 | +// State preparation for amplitude amplification: |
14 | 40 | qfunc iqae_state_preparation(vars: OracleVars, ind: qbit) { |
15 | | - hadamard_transform(vars); |
16 | | - arith_equation(vars, ind); |
| 41 | + hadamard_transform(vars); // Uniform superposition over all possible states |
| 42 | + arith_equation(vars, ind); // Compute predicate into indicator |
17 | 43 | } |
18 | 44 |
|
19 | | -qfunc space_transform(est_reg: qbit[]) { |
20 | | - iqae_state_preparation(est_reg[0:est_reg.len - 1], est_reg[est_reg.len - 1]); |
| 45 | +// Constructs the state expected by `amplitude_amplification`: |
| 46 | +// interprets the first PROBLEM_QUBITS as OracleVars and the last qubit as an indicator. |
| 47 | +qfunc space_transform(est_var: qbit[]) { |
| 48 | + // est_var = [problem_vars..., indicator] |
| 49 | + iqae_state_preparation( |
| 50 | + est_var[0:est_var.len - 1], // OracleVars view of the problem qubits |
| 51 | + est_var[est_var.len - 1] // Indicator qubit |
| 52 | + ); |
21 | 53 | } |
22 | 54 |
|
| 55 | + |
23 | 56 | qfunc main(k: int, output indicator: qbit) { |
24 | | - est_reg: qbit[]; |
25 | | - problem_vars: qbit[4]; |
26 | | - allocate(problem_vars); |
27 | | - allocate(indicator); |
| 57 | + est_var: qbit[]; |
| 58 | + problem_vars: qbit[PROBLEM_QUBITS]; |
| 59 | + |
| 60 | + allocate(problem_vars); // Initiating the indicator qubit |
| 61 | + allocate(indicator); // Solution space qubits |
| 62 | + |
| 63 | + // Create a quantum variable for amplitude amplification. |
28 | 64 | within { |
29 | | - {problem_vars, indicator} -> est_reg; |
| 65 | + {problem_vars, indicator} -> est_var; |
30 | 66 | } apply { |
31 | | - amplitude_amplification(k, oracle, space_transform, est_reg); |
| 67 | + // Apply k iterations of amplitude amplification using the oracle and space transform. |
| 68 | + amplitude_amplification(k, oracle, space_transform, est_var); |
32 | 69 | } |
33 | | - drop(problem_vars); |
| 70 | + |
| 71 | + drop(problem_vars); // Indicates that the quantum state should not be measured |
34 | 72 | } |
0 commit comments