def test_two_qubit_weyl_decomposition_bgate(self): """Verify Weyl KAK decomposition for U~B""" for k1l, k1r, k2l, k2r in K1K2S: k1 = np.kron(k1l.data, k1r.data) k2 = np.kron(k2l.data, k2r.data) a = Ud(np.pi / 4, np.pi / 8, 0) self.check_two_qubit_weyl_decomposition(k1 @ a @ k2)
def check_two_qubit_weyl_decomposition(self, target_unitary, tolerance=1.e-7): """Check TwoQubitWeylDecomposition() works for a given operator""" with self.subTest(unitary=target_unitary): decomp = TwoQubitWeylDecomposition(target_unitary) op = Operator(np.eye(4)) for u, qs in ( (decomp.K2r, [0]), (decomp.K2l, [1]), (Ud(decomp.a, decomp.b, decomp.c), [0, 1]), (decomp.K1r, [0]), (decomp.K1l, [1]), ): op = op.compose(u, qs) decomp_unitary = op.data target_unitary *= la.det(target_unitary)**(-0.25) decomp_unitary *= la.det(decomp_unitary)**(-0.25) maxdists = [ np.max(np.abs(target_unitary + phase * decomp_unitary)) for phase in [1, 1j, -1, -1j] ] maxdist = np.min(maxdists) self.assertTrue( np.abs(maxdist) < tolerance, "Worst distance {}".format(maxdist))
def test_exact_supercontrolled_decompose_random(self, seeds): """Exact decomposition for random supercontrolled basis and random target""" k1 = np.kron(random_unitary(2, seed=seeds[0]).data, random_unitary(2, seed=seeds[1]).data) k2 = np.kron(random_unitary(2, seed=seeds[2]).data, random_unitary(2, seed=seeds[3]).data) basis_unitary = k1 @ Ud(np.pi / 4, 0, 0) @ k2 decomposer = TwoQubitBasisDecomposer(UnitaryGate(basis_unitary)) self.check_exact_decomposition(random_unitary(4, seed=seeds[4]).data, decomposer)
def check_two_qubit_weyl_decomposition(self, target_unitary, tolerance=1.e-7): """Check TwoQubitWeylDecomposition() works for a given operator""" with self.subTest(unitary=target_unitary): decomp = TwoQubitWeylDecomposition(target_unitary) q = QuantumRegister(2) decomp_circuit = QuantumCircuit(q) decomp_circuit.append(UnitaryGate(decomp.K2r), [q[0]]) decomp_circuit.append(UnitaryGate(decomp.K2l), [q[1]]) decomp_circuit.append( UnitaryGate(Ud(decomp.a, decomp.b, decomp.c)), [q[0], q[1]]) decomp_circuit.append(UnitaryGate(decomp.K1r), [q[0]]) decomp_circuit.append(UnitaryGate(decomp.K1l), [q[1]]) result = execute(decomp_circuit, UnitarySimulatorPy()).result() decomp_unitary = result.get_unitary() target_unitary *= la.det(target_unitary)**(-0.25) decomp_unitary *= la.det(decomp_unitary)**(-0.25) maxdists = [ np.max(np.abs(target_unitary + phase * decomp_unitary)) for phase in [1, 1j, -1, -1j] ] maxdist = np.min(maxdists) self.assertTrue( np.abs(maxdist) < tolerance, "Worst distance {}".format(maxdist))
def test_exact_supercontrolled_decompose_random(self, seed): """Exact decomposition for random supercontrolled basis and random target (seed={seed})""" # pylint: disable=invalid-name k1 = np.kron(random_unitary(2, seed=seed).data, random_unitary(2, seed=seed + 1).data) k2 = np.kron(random_unitary(2, seed=seed + 2).data, random_unitary(2, seed=seed + 3).data) basis_unitary = k1 @ Ud(np.pi / 4, 0, 0) @ k2 decomposer = TwoQubitBasisDecomposer(UnitaryGate(basis_unitary)) self.check_exact_decomposition(random_unitary(4, seed=seed + 4).data, decomposer)
def test_exact_supercontrolled_decompose_random(self, nsamples=10): """Verify exact decomposition for random supercontrolled basis and random target""" for _ in range(nsamples): k1 = np.kron(random_unitary(2).data, random_unitary(2).data) k2 = np.kron(random_unitary(2).data, random_unitary(2).data) basis_unitary = k1 @ Ud(np.pi / 4, 0, 0) @ k2 decomposer = TwoQubitBasisDecomposer(UnitaryGate(basis_unitary)) self.check_exact_decomposition(random_unitary(4).data, decomposer)
def test_two_qubit_weyl_decomposition_aama(self, smallest=1e-18, factor=9.8, steps=11): """Verify Weyl KAK decomposition for U~Ud(a,a,-a)""" for aaa in ([smallest * factor ** i for i in range(steps)] + [np.pi / 4 - smallest * factor ** i for i in range(steps)] + [np.pi / 8, 0.113 * np.pi, 0.1972 * np.pi]): for k1l, k1r, k2l, k2r in K1K2S: k1 = np.kron(k1l.data, k1r.data) k2 = np.kron(k2l.data, k2r.data) a = Ud(aaa, aaa, -aaa) self.check_two_qubit_weyl_decomposition(k1 @ a @ k2)
def check_two_qubit_weyl_decomposition(self, target_unitary, tolerance=1.e-7): """Check TwoQubitWeylDecomposition() works for a given operator""" # pylint: disable=invalid-name decomp = TwoQubitWeylDecomposition(target_unitary) op = np.exp(1j * decomp.global_phase) * Operator(np.eye(4)) for u, qs in ( (decomp.K2r, [0]), (decomp.K2l, [1]), (Ud(decomp.a, decomp.b, decomp.c), [0, 1]), (decomp.K1r, [0]), (decomp.K1l, [1]), ): op = op.compose(u, qs) decomp_unitary = op.data maxdist = np.max(np.abs(target_unitary - decomp_unitary)) self.assertTrue( np.abs(maxdist) < tolerance, "Unitary {}: Worst distance {}".format(target_unitary, maxdist))
def test_exact_nonsupercontrolled_decompose(self): """Check that the nonsupercontrolled basis throws a warning""" with self.assertWarns(UserWarning, msg="Supposed to warn when basis non-supercontrolled"): TwoQubitBasisDecomposer(UnitaryGate(Ud(np.pi / 4, 0.2, 0.1)))