Общий оракул Саймона и строка1001
1. Реализуйте общий оракул Саймона в Qiskit.
2. Проверьте его со скрытой строкой b=1001 в симуляторе и на устройстве. Соответствуют ли результаты ожиданиям? Объясните почему.
Контекст автора: оракул получает два n-кубитных регистра и действует как $|x,0\rangle\mapsto|x,f_b(x)\rangle$. При b=0 функция взаимно однозначна, иначе у каждого выходного значения два входа, различающихся на b.
Автор предлагает сначала скопировать x во второй регистр с помощью CNOT. Если b≠0, выберите младший индекс j с bj=1; при xj=0 замените второй регистр на x⊕b, а при xj=1 сохраните x. Затем можно переставить и инвертировать выходные кубиты, сохраняя столкновения входов.
Алгоритм применяет H ко всем входным кубитам до и после оракула, затем измеряет первый регистр. Его результаты z должны удовлетворять b·z=0 по модулю 2. Исходный полный пример использует импортированный simon_oracle для b=110 в симуляторе и b=11 на устройстве; здесь требуется собственная общая реализация, поэтому её тело заранее не подставляется вместо задания. Рисунок — исходная схема для b=110.
Полная исходная программа для задания:
# importing Qiskit
from qiskit import IBMQ, Aer
from qiskit.providers.ibmq import least_busy
from qiskit import QuantumCircuit, transpile
# import basic plot tools
from qiskit.visualization import plot_histogram
from qiskit_textbook.tools import simon_oracle
b = '110'
n = len(b)
simon_circuit = QuantumCircuit(n*2, n)
# Apply Hadamard gates before querying the oracle
simon_circuit.h(range(n))
# Apply barrier for visual separation
simon_circuit.barrier()
simon_circuit = simon_circuit.compose(simon_oracle(b))
# Apply barrier for visual separation
simon_circuit.barrier()
# Apply Hadamard gates to the input register
simon_circuit.h(range(n))
# Measure qubits
simon_circuit.measure(range(n), range(n))
simon_circuit.draw()
# use local simulator
aer_sim = Aer.get_backend('aer_simulator')
results = aer_sim.run(simon_circuit).result()
counts = results.get_counts()
plot_histogram(counts)
# Calculate the dot product of the results
def bdotz(b, z):
accum = 0
for i in range(len(b)):
accum += int(b[i]) * int(z[i])
return (accum % 2)
for z in counts:
print( '{}.{} = {} (mod 2)'.format(b, z, bdotz(b,z)) )
b = '11'
n = len(b)
simon_circuit_2 = QuantumCircuit(n*2, n)
# Apply Hadamard gates before querying the oracle
simon_circuit_2.h(range(n))
# Query oracle
simon_circuit_2 = simon_circuit_2.compose(simon_oracle(b))
# Apply Hadamard gates to the input register
simon_circuit_2.h(range(n))
# Measure qubits
simon_circuit_2.measure(range(n), range(n))
simon_circuit_2.draw()
# Load our saved IBMQ accounts and get the least busy backend device with less than or equal to 5 qubits
IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q')
backend = least_busy(provider.backends(filters=lambda x: x.configuration().n_qubits >= n and
not x.configuration().simulator and x.status().operational==True))
print("least busy backend: ", backend)
# Execute and monitor the job
from qiskit.tools.monitor import job_monitor
shots = 1024
transpiled_simon_circuit = transpile(simon_circuit_2, backend, optimization_level=3)
job = backend.run(transpiled_simon_circuit)
job_monitor(job, interval=2)
# Get results and plot counts
device_counts = job.result().get_counts()
plot_histogram(device_counts)
# Calculate the dot product of the results
def bdotz(b, z):
accum = 0
for i in range(len(b)):
accum += int(b[i]) * int(z[i])
return (accum % 2)
print('b = ' + b)
for z in device_counts:
print( '{}.{} = {} (mod 2) ({:.1f}%)'.format(b, z, bdotz(b,z), device_counts[z]*100/shots))
Предложить решение
Войти, чтобы отправить материал.