diff --git a/task4/main.py b/task4/main.py new file mode 100644 index 0000000..e5189fb --- /dev/null +++ b/task4/main.py @@ -0,0 +1,91 @@ +"""Алгоритм Бернштейна–Вазирани в Cirq.""" + +import random + +import cirq + + +def main(): + """Выполняет алгоритм BV.""" + # Количество кубитов + qubit_count = 8 + # Количество выборок из схемы + circuit_sample_count = 3 + + # Выберите кубиты для использования + input_qubits = [cirq.GridQubit(i, 0) for i in range(qubit_count)] + output_qubit = cirq.GridQubit(qubit_count, 0) + + # Выберите коэффициенты для оракула и создайте схему для его запроса + secret_bias_bit = random.randint(0, 1) + secret_factor_bits = [random.randint(0, 1) for _ in range(qubit_count)] + + oracle = make_oracle( + input_qubits, output_qubit, secret_factor_bits, secret_bias_bit + ) + + print( + "Secret function:\nf(x) = x*<{}> + {} (mod 2)".format( + ", ".join(str(e) for e in secret_factor_bits), secret_bias_bit + ) + ) + + # Встраиваем оракул в специальную квантовую схему, запрашивая ее ровно один раз + circuit = make_bernstein_vazirani_circuit(input_qubits, output_qubit, oracle) + print("\nCircuit:") + print(circuit) + + # Выберем из схемы пару раз + simulator = cirq.Simulator() + result = simulator.run(circuit, repetitions=circuit_sample_count) + frequencies = result.histogram(key="result", fold_func=bitstring) + print("\nSampled results:\n{}".format(frequencies)) + + # Проверить, действительно ли мы нашли секретное значение + most_common_bitstring = frequencies.most_common(1)[0][0] + print( + "\nMost common matches secret factors:\n{}".format( + most_common_bitstring == bitstring(secret_factor_bits) + ) + ) + + +def make_oracle(input_qubits, output_qubit, secret_factor_bits, secret_bias_bit): + """Вентили, реализующие функцию f(a) = a*factors + bias (mod 2).""" + if secret_bias_bit: + yield cirq.X(output_qubit) + + for qubit, bit in zip(input_qubits, secret_factor_bits): + if bit: + yield cirq.CNOT(qubit, output_qubit) + + +def make_bernstein_vazirani_circuit(input_qubits, output_qubit, oracle): + """Находит множители в f (a) = a * factors + bias (mod 2) с помощью одного запроса.""" + c = cirq.Circuit() + + # Инициализировать кубиты + c.append( + [ + cirq.X(output_qubit), + cirq.H(output_qubit), + cirq.H.on_each(*input_qubits), + ] + ) + + # Запрос оракула + c.append(oracle) + + # Измерение по оси X + c.append([cirq.H.on_each(*input_qubits), cirq.measure(*input_qubits, key="result")]) + + return c + + +def bitstring(bits): + """Создает битовую строку из итерации битов.""" + return "".join(str(int(b)) for b in bits) + + +if __name__ == "__main__": + main()