Алгоритм Саймона
This commit is contained in:
104
task5/main.py
Normal file
104
task5/main.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
|
||||
import cirq
|
||||
import numpy as np
|
||||
import scipy as sp
|
||||
|
||||
|
||||
def main(qubit_count=3):
|
||||
|
||||
data = [] # we'll store here the results
|
||||
|
||||
# define a secret string:
|
||||
secret_string = np.random.randint(2, size=qubit_count)
|
||||
|
||||
print(f"Secret string = {secret_string}")
|
||||
|
||||
n_samples = 100
|
||||
for _ in range(n_samples):
|
||||
flag = False # check if we have a linearly independent set of measures
|
||||
while not flag:
|
||||
# Choose qubits to use.
|
||||
input_qubits = [cirq.GridQubit(i, 0) for i in range(qubit_count)] # input x
|
||||
output_qubits = [
|
||||
cirq.GridQubit(i + qubit_count, 0) for i in range(qubit_count)
|
||||
] # output f(x)
|
||||
|
||||
# Pick coefficients for the oracle and create a circuit to query it.
|
||||
oracle = make_oracle(input_qubits, output_qubits, secret_string)
|
||||
|
||||
# Embed oracle into special quantum circuit querying it exactly once
|
||||
circuit = make_simon_circuit(input_qubits, output_qubits, oracle)
|
||||
|
||||
# Sample from the circuit a n-1 times (n = qubit_count).
|
||||
simulator = cirq.Simulator()
|
||||
results = [
|
||||
simulator.run(circuit).measurements["result"][0]
|
||||
for _ in range(qubit_count - 1)
|
||||
]
|
||||
|
||||
# Classical Post-Processing:
|
||||
flag = post_processing(data, results)
|
||||
|
||||
freqs = Counter(data)
|
||||
print("Circuit:")
|
||||
print(circuit)
|
||||
print(f"Most common answer was : {freqs.most_common(1)[0]}")
|
||||
|
||||
|
||||
def make_oracle(input_qubits, output_qubits, secret_string):
|
||||
"""Gates implementing the function f(a) = f(b) iff a ⨁ b = s"""
|
||||
# Copy contents to output qubits:
|
||||
for control_qubit, target_qubit in zip(input_qubits, output_qubits):
|
||||
yield cirq.CNOT(control_qubit, target_qubit)
|
||||
|
||||
# Create mapping:
|
||||
if sum(secret_string): # check if the secret string is non-zero
|
||||
# Find significant bit of secret string (first non-zero bit)
|
||||
significant = list(secret_string).index(1)
|
||||
|
||||
# Add secret string to input according to the significant bit:
|
||||
for j in range(len(secret_string)):
|
||||
if secret_string[j] > 0:
|
||||
yield cirq.CNOT(input_qubits[significant], output_qubits[j])
|
||||
|
||||
|
||||
def make_simon_circuit(input_qubits, output_qubits, oracle):
|
||||
"""Solves for the secret period s of a 2-to-1 function such that
|
||||
f(x) = f(y) iff x ⨁ y = s
|
||||
"""
|
||||
|
||||
c = cirq.Circuit()
|
||||
|
||||
# Initialize qubits.
|
||||
c.append([cirq.H.on_each(*input_qubits)])
|
||||
|
||||
# Query oracle.
|
||||
c.append(oracle)
|
||||
|
||||
# Measure in X basis.
|
||||
c.append([cirq.H.on_each(*input_qubits), cirq.measure(*input_qubits, key="result")])
|
||||
|
||||
return c
|
||||
|
||||
|
||||
def post_processing(data, results):
|
||||
"""Solves a system of equations with modulo 2 numbers"""
|
||||
sing_values = sp.linalg.svdvals(results)
|
||||
tolerance = 1e-5
|
||||
if (
|
||||
sum(sing_values < tolerance) == 0
|
||||
): # check if measurements are linearly dependent
|
||||
flag = True
|
||||
null_space = sp.linalg.null_space(results).T[0]
|
||||
solution = np.around(null_space, 3) # chop very small values
|
||||
minval = abs(min(solution[np.nonzero(solution)], key=abs))
|
||||
solution = (solution / minval % 2).astype(int) # renormalize vector mod 2
|
||||
data.append(str(solution))
|
||||
return flag
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user