quantum / utils /adapt-aqc /test /recompilers /test_approximate_compiler.py
harishaseebat92
Fix: Add adapt-aqc as regular files, not submodule
6d8ed8c
from unittest import TestCase
from unittest.mock import patch
import numpy as np
from qiskit import QuantumCircuit
import adaptaqc.utils.circuit_operations as co
from adaptaqc.backends.python_default_backends import QASM_SIM, SV_SIM, MPS_SIM
from adaptaqc.compilers.adapt.adapt_compiler import AdaptCompiler
from adaptaqc.compilers.approximate_compiler import ApproximateCompiler
@patch.multiple(ApproximateCompiler, __abstractmethods__=set())
class TestApproximateCompiler(TestCase):
def setUp(self) -> None:
self.qc = QuantumCircuit(1)
def test_when_init_with_mps_backend_then_mps_backend_flag_true(self):
self.assertTrue(ApproximateCompiler(self.qc, MPS_SIM).is_aer_mps_backend)
def test_when_init_with_sv_backend_then_sv_backend_flag_true(self):
self.assertTrue(ApproximateCompiler(self.qc, SV_SIM).is_statevector_backend)
def test_given_global_cost_and_SV_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(QuantumCircuit(1), SV_SIM)
with patch.object(compiler.backend, "evaluate_global_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_global_cost_and_MPS_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(QuantumCircuit(1), MPS_SIM)
with patch.object(compiler.backend, "evaluate_global_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_global_cost_and_QASM_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(QuantumCircuit(1), QASM_SIM)
with patch.object(compiler.backend, "evaluate_global_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_local_cost_and_SV_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(
QuantumCircuit(1), SV_SIM, optimise_local_cost=True
)
with patch.object(compiler.backend, "evaluate_local_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_local_cost_and_MPS_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(
QuantumCircuit(1), MPS_SIM, optimise_local_cost=True
)
with patch.object(compiler.backend, "evaluate_local_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_local_cost_and_QASM_backend_when_evaluate_cost_then_correct_function_called(
self,
):
compiler = ApproximateCompiler(
QuantumCircuit(1), QASM_SIM, optimise_local_cost=True
)
with patch.object(compiler.backend, "evaluate_local_cost") as mock:
compiler.evaluate_cost()
mock.assert_called_once()
def test_given_random_circuit_when_evaluate_local_cost_all_three_methods_return_same_cost(
self,
):
qc = co.create_random_initial_state_circuit(4)
compiler_sv = AdaptCompiler(qc, backend=SV_SIM, optimise_local_cost=True)
compiler_mps = AdaptCompiler(qc, backend=MPS_SIM, optimise_local_cost=True)
compiler_qasm = AdaptCompiler(qc, backend=QASM_SIM, optimise_local_cost=True)
cost_sv = compiler_sv.evaluate_cost()
cost_mps = compiler_mps.evaluate_cost()
cost_qasm = compiler_qasm.evaluate_cost()
# Looser pass threshold for qasm because it includes some form of noise
np.testing.assert_almost_equal(cost_sv, cost_mps, decimal=5)
np.testing.assert_almost_equal(cost_sv, cost_qasm, decimal=2)
np.testing.assert_almost_equal(cost_mps, cost_qasm, decimal=2)
def test_given_random_circuit_when_evaluate_global_cost_all_three_methods_return_same_cost(
self,
):
qc = co.create_random_initial_state_circuit(4)
compiler_sv = AdaptCompiler(qc, backend=SV_SIM)
compiler_mps = AdaptCompiler(qc, backend=MPS_SIM)
compiler_qasm = AdaptCompiler(qc, backend=QASM_SIM)
cost_sv = compiler_sv.evaluate_cost()
cost_mps = compiler_mps.evaluate_cost()
cost_qasm = compiler_qasm.evaluate_cost()
# Looser pass threshold for qasm because it includes some form of noise
np.testing.assert_almost_equal(cost_sv, cost_mps, decimal=5)
np.testing.assert_almost_equal(cost_sv, cost_qasm, decimal=2)
np.testing.assert_almost_equal(cost_mps, cost_qasm, decimal=2)
def test_given_simple_states_when_evaluate_global_and_local_costs_then_correct_value(
self,
):
# Analytically calculable costs:
# |0000> global=0, local=0
# |1010> global=1, local=1/2
# 4-qubit GHZ global=1/2, local=1/2
# |++++> global=15/16, local=1/2
# Using equations 9 and 11 from arXiv:1908.04416
analytic_costs = [0, 0, 1, 1 / 2, 1 / 2, 1 / 2, 15 / 16, 1 / 2]
adapt_costs = []
zero = QuantumCircuit(4)
neel = QuantumCircuit(4)
neel.x([0, 2])
ghz = QuantumCircuit(4)
ghz.h(0)
for i in range(3):
ghz.cx(0, i + 1)
hadamard = QuantumCircuit(4)
hadamard.h([0, 1, 2, 3])
circuits = [zero, neel, ghz, hadamard]
for circuit in circuits:
for optimise_local_cost in [False, True]:
compiler = AdaptCompiler(
circuit, backend=SV_SIM, optimise_local_cost=optimise_local_cost
)
cost = compiler.evaluate_cost()
adapt_costs.append(cost)
np.testing.assert_allclose(adapt_costs, analytic_costs)
def test_given_random_circuit_when_calculate_cost_local_less_or_equal_to_global(
self,
):
qc = co.create_random_initial_state_circuit(4)
compiler_local = AdaptCompiler(qc, backend=SV_SIM, optimise_local_cost=True)
compiler_global = AdaptCompiler(qc, backend=SV_SIM)
cost_local = compiler_local.evaluate_cost()
cost_global = compiler_global.evaluate_cost()
self.assertLessEqual(cost_local, cost_global)
@patch("qiskit.QuantumCircuit.set_matrix_product_state")
def test_set_matrix_product_state_used_when_mps_backend(
self, mock_set_matrix_product_state
):
ApproximateCompiler(QuantumCircuit(1), MPS_SIM)
mock_set_matrix_product_state.assert_called_once()