8000 Implement quantum search algorithm by Danii06 · Pull Request #81 · nunezco2/quAPL · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Implement quantum search algorithm #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions APLSource/lib/_QFT_.aplf
8000
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
_QFT_ ← {
_QFT_ ← {
⍝ Quantum Fourier Transform
⍝ Takes a vector state of an n-qubit system
⍝ Returns the n-qubit quantum fourier transform for the vector state
Expand All @@ -10,38 +10,41 @@ _QFT_ ← {
H ← #.quapl.gates.H
SWAP ← #.quapl.gates.SWAP
Rz ← #.quapl.gates.Rz

⍝ Rotation in z multiplied by phase factor to match literature
Rz2 ← {(*0J1×⍵÷2) × Rz ⍵}
Rz2 ← {(*0J1×⍵÷2)×Rz ⍵}

⍝ Rotation in z by 2 Pi / 2 ^ ⍵
Rzn ← {Rz2 ○2÷2*⍵}
Rzn ← {Rz2○2÷2*⍵}

⍝ Controlled form of above rotation
CRzn ← 1 #.quapl.gates.gCTR Rzn

n_qubits ← 2⍟1⌷⍴⍵

⍝ Create part of circuit that affects qubit ⍵
⍝ Create part of circuit that affects qubit number
⍝ Applies the Hadamard gate then rotates qubit about z
⍝ Indices on left-hand side are reduced by 1, since qubit numbering starts from 0
lane ← {((⍵-1),((⍵-1)+⍳n_qubits-⍵),¨(⍵-1))((⊂H), CRzn¨ 1+⍳n_qubits-⍵)}

⍝ Returns indices of qubits to apply gates to, and sets of corresponding gates
lane ← {((⍵-1),((⍵-1)+⍳n_qubits-⍵),¨(⍵-1))(⊂¨(⊂H),CRzn¨1+⍳n_qubits-⍵)}

⍝ Match up indices with the corresponding set of gates for staging
match ← {⊂[1]↑⍵}

⍝ Successively apply the gates of a circuit
stage_all ← {stage / (⌽⊃⍺[1]{⍺ (⊂⍵)}¨¨⍺[2]),⊂⍵ }
stage_all ← {stage/(⌽match ⍺),⊂⍵}

⍝ Apply the above circuit to qubits from 1 to n_qubits successively
apply ← { ⊃stage_all / (⌽lane¨⍺),⊂⍵ }

⍝ Result before swapping
intermediate ← (⍳n_qubits) apply
intermediate ← ⊃stage_all/(⌽lane¨(⍳n_qubits)),⊂

⍝ Circuit to swap qubits
⍝ Indices on left-hand side are reduced by 1, since qubit numbering starts from 0
swap_circuit ← (1-⍨(⌊n_qubits÷2)↑(⌽⍳n_qubits),¨⍳n_qubits)({SWAP}¨⍳⌊n_qubits÷2)

⍝ Returns indices of qubits to apply gates to, and sets of corresponding gates
swap_circuit ← (1-⍨(⌊n_qubits÷2)↑(⌽⍳n_qubits),¨⍳n_qubits) (⊂¨{SWAP}¨⍳⌊n_qubits÷2)

⍝ Check if swap circuit is non-empty
(0=⍴1⌷↑swap_circuit): intermediate
(0=⍴1⌷↑swap_circuit):intermediate

swap_circuit stage_all intermediate
}
}
43 changes: 43 additions & 0 deletions APLSource/lib/_QS_.aplf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
_QS_ ← {
⍝ Quantum Search algorithm
⍝ Takes a vector state ⍵ of an n-qubit system, with first ancilla qubit in the |0> state
⍝ Takes a set of bit sequences to find ⍺[1] and a number of iterations ⍺[2]
⍝ Applies the algorithm with ⍺[2] iterations and returns the measured solution
⍝ ⍵: Vector state input with first ancilla |0> qubit
⍝ ⍺[1]: bit sequences to be found
⍝ ⍺[2]: number of iterations

X ← #.quapl.gates.X
H ← #.quapl.gates.H
query ← #.quapl.lib.oracles.query
oracle ← (⊃⍺[1])∘query
stage ← #.quapl.circuit.stage

n_qubits ← 2⍟1⌷⍴⍵

⍝ Hadamard transform the input bits
state ← ⍵
state ← (0 (⊂X)) stage state
state ← (0 (⊂H)) stage state
hcircuit ← (⍳n_qubits-1) ({H}¨¨⍳n_qubits-1)


⍝ Match up indices with the corresponding set of gates for staging
match ← {⊂[1]↑⍵}

⍝ Successively apply the gates of a circuit
stage_all ← {⊃stage/(⌽match ⍺),⊂⍵}

state ← hcircuit stage_all state

⍝ One step of grover iteration
grover ← {
⍝ Oracle, Inversion about mean
tmp ← hcircuit stage_all oracle ⍵
tmp ← (0 (⊂X)) stage (⊂(n_qubits-1)/0) query tmp
hcircuit stage_all tmp
}

(0 (⊂X)) stage (0 (⊂H)) stage (grover⍣(⍺[2]))state
}
41 changes: 41 additions & 0 deletions APLSource/lib/oracles/query.aplf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
query←{
⍝ Query oracle for the quantum search algorithm
⍝ The ancilla bit in the |-> state is assumed to be the first in the register
⍝ Flips the sign of the vector state ⍵ if the matches any of the bit sequences in the set ⍺

X←#.quapl.gates.X
H←#.quapl.gates.H
stage←#.quapl.circuit.stage

n_qubits←2⍟1⌷⍴⍵

⍝ X gate controlled by the non-ancilla bits
CX←(n_qubits-1)#.quapl.gates.gCTR X

⍝ Query for a single bit sequence ⍺
⍝ Flips bits where the sequence is 0
⍝ Applies the X gate controlled by the non-ancilla bits
single_query←{
state←⍵
to_invert←⍸1-⍺

inv_circuit←(to_invert)({X}¨¨to_invert)

⍝ Match up indices with the corresponding set of gates for staging
match←{⊂[1]↑⍵}

⍝ Successively apply the gates of a circuit
stage_all←{⊃stage/(⌽match ⍺),⊂⍵}

state←inv_circuit stage_all state

state←((⊂(⍳n_qubits-1),0),⊂⊂CX)stage state

state←inv_circuit stage_all state

state
}

⊃single_query/⍺,⊂⍵

}
35 changes: 35 additions & 0 deletions Tests/test_ 8000 QS_oracle_value_001.aplf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
test_QS_oracle_value_001 ← {

X ← #.quapl.gates.X
H ← #.quapl.gates.H

⍝ Generate all possible 3 bit sequences
sequences ← 3(↑⍨∘-⍨)¨(2∘⊥⍣¯1)¨1-⍨⍳2*3

⍝ Generate all unique groups of 3 bit sequences of max length 3
groups ← ∪∪¨(sequences(∘.{⍺ ⍵})sequences)
groups ← ,∪∪¨sequences(∘.{(⊂⍺),⍵})groups

⍝ From bit vector to qubit state
⍝ For example, takes 0 1 0 1 to |0101>
state ← {n ← ⊃⍴⍵ ⋄ (⍪(⍳n)-1),(⍪((#.quapl.sng.q0 (#.quapl.sng.q1))[⍵+1]))}

⍝ Generate all possible pure input states up to 4 bits, where the first qubit is in state is |0>
vectors ← #.quapl.circuit.thread_reg¨ state¨ 0,[1]¨sequences


⍝ Applies the X then H to the ancilla bit in the |0> position
vectors ← (⊂0,⊂⊂H)#.quapl.circuit.stage¨((⊂0,⊂⊂X)#.quapl.circuit.stage¨ vectors)

⍝ All possible applications of solutions and input vectors
results ← ,groups (∘.(#.quapl.lib.oracles.query)) vectors

⍝ Check signs of results
results ← {⍵[1]=¯1}¨{⍵/⍨0≠⍵}¨,¨{×⍵}¨results

⍝ Check if result is equivalent to ∊ element of
results_correct ← ,⍉sequences (∘.{(⊂⍺)∊⍵}) groups

'Query oracle should flip the sign of states which match'⊢ results_correct Assert results:
''
}
15 changes: 15 additions & 0 deletions Tests/test_QS_value_001.aplf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
test_QS_value_001 ← {
⍝ Check that search takes one step on two-bit states
solutions ← 2(↑⍨∘-⍨)¨(2∘⊥⍣¯1)¨1-⍨⍳2*2

vector ← #.quapl.circuit.thread_reg #.quapl.circuit.reg 3

results ← (solutions{(⊂⍺) ⍵}¨1) ({(⊃⍺)#.quapl.lib._QS_ ⍵}⍤0 99) vector

⍝ Measure the results
results ← ,{(⊂#.quapl.sng.q1)≡¨{⍵[2 3;2]}⍪↑⊃#.quapl.measurement.measure ⍵}¨ ⍪¨↓[2]results

⍝ Check if the measured results are the correct solutions
'2 bit Quantum Search should need only one iteration to reach the correct solution'⊢ (∧/ results (∊⍤0) solutions) Assert 1:
''
}
Loading
0