def test_kron_factor_special_unitaries(f1, f2): p = cirq.kron(f1, f2) g, g1, g2 = cirq.kron_factor_4x4_to_2x2s(p) assert np.allclose(cirq.kron(g1, g2), p) assert abs(g - 1) < 0.000001 assert cirq.is_special_unitary(g1) assert cirq.is_special_unitary(g2)
def _random_single_partial_cz_effect(): return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.diag([1, 1, 1, cmath.exp(2j * random.random() * np.pi)]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def test_targeted_left_multiply_matches_kron_then_dot(): t = np.array([1, 2, 3, 4, 5, 6, 7, 8]) m = np.array([[2, 3], [5, 7]]) i = np.eye(2) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[0]), np.dot(cirq.kron(m, i, i), t).reshape((2, 2, 2)), atol=1e-8) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[1]), np.dot(cirq.kron(i, m, i), t).reshape((2, 2, 2)), atol=1e-8) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[2]), np.dot(cirq.kron(i, i, m), t).reshape((2, 2, 2)), atol=1e-8)
def _random_double_full_cz_effect(): return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), cirq.unitary(cirq.CZ), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), cirq.unitary(cirq.CZ), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def _random_double_full_cz_effect(): return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), cirq.CZ.matrix(), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), cirq.CZ.matrix(), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def _random_double_partial_cz_effect(): return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.diag([1, 1, 1, cmath.exp(2j * random.random() * np.pi)]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.diag([1, 1, 1, cmath.exp(2j * random.random() * np.pi)]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def test_entangled_state(self): entangled_state = cirq.kron(z[0], z[1]) + cirq.kron(z[1], z[0]) entangled_state /= np.sqrt( np.conj(entangled_state) @ entangled_state.T) entangled_state_tensor = tf.convert_to_tensor(entangled_state) with self.assertRaisesRegex( ValueError, re.compile( "Input wavefunction could not be factored into pure state over " "indices \[1\]")): substates(entangled_state_tensor, keep_indices=[1])
def _random_single_MS_effect(): t = random.random() s = np.sin(t) c = np.cos(t) return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.array([[c, 0, 0, -1j * s], [0, c, -1j * s, 0], [0, -1j * s, c, 0], [-1j * s, 0, 0, c]]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def recompose_kak(g, a, v, b) -> np.ndarray: a1, a0 = a x, y, z = v b1, b0 = b xx = cirq.kron(X, X) yy = cirq.kron(Y, Y) zz = cirq.kron(Z, Z) a = cirq.kron(a1, a0) m = cirq.map_eigenvalues(xx * x + yy * y + zz * z, lambda e: np.exp(1j * e)) b = cirq.kron(b1, b0) return cirq.dot(a, m, b) * g
def _test_inner_product(method): from paulicirq.gates.swap_test_gate import add_swap_test from paulicirq.gates.swap_test_gate import inner_product_from_swap_test_result from paulicirq.gates.overlap_test_gate import add_overlap_test from paulicirq.gates.overlap_test_gate import inner_product_from_overlap_test_result if method == "SWAP": add_test = add_swap_test inner_product_from_test_result = \ inner_product_from_swap_test_result elif method == "overlap": add_test = add_overlap_test inner_product_from_test_result = \ inner_product_from_overlap_test_result else: raise ValueError("Not supported test method.") circuit = cirq.Circuit() state1 = cirq.LineQubit.range(0, 3) state2 = cirq.LineQubit.range(3, 6) simulator = cirq.Simulator() for qubit1, qubit2 in zip(state1, state2): circuit.append([cirq.X(qubit1), cirq.X(qubit2), cirq.H(qubit2)]) measurement = add_test(state1, state2, circuit) print(circuit) result = simulator.run(circuit, repetitions=10000) # print(result) inner_product_simulator = inner_product_from_test_result( result, measurement) zero_state = np.array([1, 0]) initial_state = cirq.kron(zero_state, zero_state, zero_state).flatten() _x = cirq.unitary(cirq.X) _h = cirq.unitary(cirq.H) all_x = cirq.kron(_x, _x, _x) all_h = cirq.kron(_h, _h, _h) _state1 = all_x @ initial_state _state2 = all_h @ all_x @ initial_state inner_product_exact = _state1 @ _state2 return inner_product_simulator, inner_product_exact
def test_kron_spreads_values(): u = np.array([[2, 3], [5, 7]]) assert np.allclose( cirq.kron(np.eye(2), u), np.array([[2, 3, 0, 0], [5, 7, 0, 0], [0, 0, 2, 3], [0, 0, 5, 7]])) assert np.allclose( cirq.kron(u, np.eye(2)), np.array([[2, 0, 3, 0], [0, 2, 0, 3], [5, 0, 7, 0], [0, 5, 0, 7]])) assert np.allclose( cirq.kron(u, u), np.array([[4, 6, 6, 9], [10, 14, 15, 21], [10, 15, 14, 21], [25, 35, 35, 49]]))
def test_targeted_left_multiply_matches_kron_then_dot(): t = np.array([1, 2, 3, 4, 5, 6, 7, 8]) m = np.array([[2, 3], [5, 7]]) i = np.eye(2) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[0]), np.dot(cirq.kron(m, i, i), t).reshape((2, 2, 2)), atol=1e-8, ) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[1]), np.dot(cirq.kron(i, m, i), t).reshape((2, 2, 2)), atol=1e-8, ) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[2]), np.dot(cirq.kron(i, i, m), t).reshape((2, 2, 2)), atol=1e-8, ) np.testing.assert_allclose( cirq.targeted_left_multiply(left_matrix=m, right_target=t.reshape((2, 2, 2)), target_axes=[2]), np.dot(cirq.kron(i, i, m), t).reshape((2, 2, 2)), atol=1e-8, ) common = t.reshape((2, 2, 2)) with pytest.raises(ValueError, match="out is"): cirq.targeted_left_multiply(left_matrix=m, right_target=common, out=common, target_axes=[2]) with pytest.raises(ValueError, match="out is"): cirq.targeted_left_multiply(left_matrix=m, right_target=common, out=m, target_axes=[2])
def test_to_z_basis_ops(): x0 = np.array([1, 1]) / np.sqrt(2) x1 = np.array([1, -1]) / np.sqrt(2) y0 = np.array([1, 1j]) / np.sqrt(2) y1 = np.array([1, -1j]) / np.sqrt(2) z0 = np.array([1, 0]) z1 = np.array([0, 1]) q0, q1, q2, q3, q4, q5 = _make_qubits(6) pauli_string = cirq.PauliString({ q0: cirq.X, q1: cirq.X, q2: cirq.Y, q3: cirq.Y, q4: cirq.Z, q5: cirq.Z }) circuit = cirq.Circuit.from_ops(pauli_string.to_z_basis_ops()) initial_state = cirq.kron(x0, x1, y0, y1, z0, z1) z_basis_state = circuit.final_wavefunction(initial_state) expected_state = np.zeros(2**6) expected_state[0b010101] = 1 cirq.testing.assert_allclose_up_to_global_phase(z_basis_state, expected_state, rtol=1e-7, atol=1e-7)
def test_kron_multiplies_sizes(): assert np.allclose(cirq.kron(1j, np.array([2, 3])), np.array([2j, 3j])) assert np.allclose(cirq.kron(), np.eye(1)) assert np.allclose(cirq.kron(np.eye(1)), np.eye(1)) assert np.allclose(cirq.kron(np.eye(2)), np.eye(2)) assert np.allclose(cirq.kron(np.eye(1), np.eye(1)), np.eye(1)) assert np.allclose(cirq.kron(np.eye(1), np.eye(2)), np.eye(2)) assert np.allclose(cirq.kron(np.eye(2), np.eye(3)), np.eye(6)) assert np.allclose(cirq.kron(np.eye(2), np.eye(3), np.eye(4)), np.eye(24))
def recompose_so4(a: np.ndarray, b: np.ndarray) -> np.ndarray: assert a.shape == (2, 2) assert b.shape == (2, 2) assert cirq.is_special_unitary(a) assert cirq.is_special_unitary(b) magic = np.array([[1, 0, 0, 1j], [0, 1j, 1, 0], [0, 1j, -1, 0], [1, 0, 0, -1j]]) * np.sqrt(0.5) result = np.real(cirq.dot(np.conj(magic.T), cirq.kron(a, b), magic)) assert cirq.is_orthogonal(result) return result
def _random_double_MS_effect(): t1 = random.random() s1 = np.sin(t1) c1 = np.cos(t1) t2 = random.random() s2 = np.sin(t2) c2 = np.cos(t2) return cirq.dot( cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.array([[c1, 0, 0, -1j * s1], [0, c1, -1j * s1, 0], [0, -1j * s1, c1, 0], [-1j * s1, 0, 0, c1]]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)), np.array([[c2, 0, 0, -1j * s2], [0, c2, -1j * s2, 0], [0, -1j * s2, c2, 0], [-1j * s2, 0, 0, c2]]), cirq.kron(cirq.testing.random_unitary(2), cirq.testing.random_unitary(2)))
def test_commutes_on_gates_and_gate_operations(): X, Y, Z = tuple(cirq.unitary(A) for A in (cirq.X, cirq.Y, cirq.Z)) XGate, YGate, ZGate = (cirq.MatrixGate(A) for A in (X, Y, Z)) XXGate, YYGate, ZZGate = (cirq.MatrixGate(cirq.kron(A, A)) for A in (X, Y, Z)) a, b = cirq.LineQubit.range(2) for A in (XGate, YGate, ZGate): assert cirq.commutes(A, A) assert A._commutes_on_qids_(a, A, atol=1e-8) is NotImplemented with pytest.raises(TypeError): cirq.commutes(A(a), A) with pytest.raises(TypeError): cirq.commutes(A, A(a)) assert cirq.commutes(A(a), A(a)) assert cirq.commutes(A, XXGate, default='default') == 'default' for A, B in [ (XGate, YGate), (XGate, ZGate), (ZGate, YGate), (XGate, cirq.Y), (XGate, cirq.Z), (ZGate, cirq.Y), ]: assert not cirq.commutes(A, B) assert cirq.commutes(A(a), B(b)) assert not cirq.commutes(A(a), B(a)) with pytest.raises(TypeError): cirq.commutes(A, B(a)) cirq.testing.assert_commutes_magic_method_consistent_with_unitaries( A, B) for A, B in [(XXGate, YYGate), (XXGate, ZZGate)]: assert cirq.commutes(A, B) with pytest.raises(TypeError): cirq.commutes(A(a, b), B) with pytest.raises(TypeError): cirq.commutes(A, B(a, b)) assert cirq.commutes(A(a, b), B(a, b)) assert cirq.definitely_commutes(A(a, b), B(a, b)) cirq.testing.assert_commutes_magic_method_consistent_with_unitaries( A, B) for A, B in [(XGate, XXGate), (XGate, YYGate)]: with pytest.raises(TypeError): cirq.commutes(A, B(a, b)) assert not cirq.definitely_commutes(A, B(a, b)) with pytest.raises(TypeError): assert cirq.commutes(A(b), B) with pytest.raises(TypeError): assert cirq.commutes(A, B) cirq.testing.assert_commutes_magic_method_consistent_with_unitaries( A, B) with pytest.raises(TypeError): assert cirq.commutes(XGate, cirq.X**sympy.Symbol('e')) with pytest.raises(TypeError): assert cirq.commutes(XGate(a), 'Gate') assert cirq.commutes(XGate(a), 'Gate', default='default') == 'default'
def assert_fswap_consistent(gate): gate = gate.__copy__() n_qubits = gate.num_qubits() for i in range(n_qubits - 1): fswap = cirq.kron(np.eye(1 << i), cirq.unitary(ofc.FSWAP), np.eye(1 << (n_qubits - i - 2))) assert fswap.shape == (1 << n_qubits, ) * 2 generator = gate.qubit_generator_matrix fswapped_generator = np.linalg.multi_dot([fswap, generator, fswap]) gate.fswap(i) assert np.allclose(gate.qubit_generator_matrix, fswapped_generator) for i in (-1, n_qubits): with pytest.raises(ValueError): gate.fswap(i)
# You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import numpy as np import cirq H = np.array([[1, 1], [1, -1]]) * np.sqrt(0.5) HH = cirq.kron(H, H) QFT2 = np.array([[1, 1, 1, 1], [1, 1j, -1, -1j], [1, -1, 1, -1], [1, -1j, -1, 1j]]) * 0.5 def test_single_qubit_init(): m = np.array([[1, 1j], [1j, 1]]) * np.sqrt(0.5) x2 = cirq.SingleQubitMatrixGate(m) assert np.alltrue(x2.matrix() == m) def test_single_qubit_eq(): eq = cirq.testing.EqualsTester() eq.make_equality_group(lambda: cirq.SingleQubitMatrixGate(np.eye(2)))
assert np.allclose(restored, matrix), "Can't factor kronecker product." def assert_kronecker_factorization_not_within_tolerance(matrix, g, f1, f2): restored = g * cirq.linalg.combinators.kron(f1, f2) assert np.any(np.isnan(restored) or not np.allclose(restored, matrix)) def assert_magic_su2_within_tolerance(mat, a, b): M = cirq.linalg.decompositions.MAGIC MT = cirq.linalg.decompositions.MAGIC_CONJ_T recon = cirq.linalg.combinators.dot(MT, cirq.linalg.combinators.kron(a, b), M) assert np.allclose(recon, mat), "Failed to decompose within tolerance." @pytest.mark.parametrize('matrix', [X, cirq.kron(X, X), cirq.kron(X, Y), cirq.kron(X, np.eye(2))]) def test_map_eigenvalues_identity(matrix): identity_mapped = cirq.map_eigenvalues(matrix, lambda e: e) assert np.allclose(matrix, identity_mapped) @pytest.mark.parametrize( 'matrix,exponent,desired', [ [X, 2, np.eye(2)], [X, 3, X], [Z, 2, np.eye(2)], [H, 2, np.eye(2)], [Z, 0.5, np.diag([1, 1j])], [X, 0.5, np.array([[1j, 1], [1, 1j]]) * (1 - 1j) / 2], ],
c = np.exp(1j * np.pi / 4) SQRT_SQRT_X = np.array([[1 + c, 1 - c], [1 - c, 1 + c]]) / 2 SWAP = np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]]) CNOT = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]) CZ = np.diag([1, 1, 1, -1]) @pytest.mark.parametrize('matrix', [ X, cirq.kron(X, X), cirq.kron(X, Y), cirq.kron(X, np.eye(2)) ]) def test_map_eigenvalues_identity(matrix): identity_mapped = cirq.map_eigenvalues(matrix, lambda e: e) assert np.allclose(matrix, identity_mapped) @pytest.mark.parametrize('matrix,exponent,desired', [ [X, 2, np.eye(2)], [X, 3, X], [Z, 2, np.eye(2)], [H, 2, np.eye(2)], [Z, 0.5, np.diag([1, 1j])], [X, 0.5, np.array([[1j, 1], [1, 1j]]) * (1 - 1j) / 2],
def test_kron_factor(f1, f2): p = cirq.kron(f1, f2) g, g1, g2 = cirq.kron_factor_4x4_to_2x2s(p) assert abs(np.linalg.det(g1) - 1) < 0.00001 assert abs(np.linalg.det(g2) - 1) < 0.00001 assert np.allclose(g * cirq.kron(g1, g2), p)
def test_kron_multiplies_sizes(): assert cirq.kron(np.array([1, 2])).shape == (1, 2) assert cirq.kron(np.array([1, 2]), shape_len=1).shape == (2,) assert cirq.kron(np.array([1, 2]), np.array([3, 4, 5]), shape_len=1).shape == (6,) assert cirq.kron(shape_len=0).shape == () assert cirq.kron(shape_len=1).shape == (1,) assert cirq.kron(shape_len=2).shape == (1, 1) assert np.allclose(cirq.kron(1j, np.array([2, 3])), np.array([2j, 3j])) assert np.allclose(cirq.kron(), np.eye(1)) assert np.allclose(cirq.kron(np.eye(1)), np.eye(1)) assert np.allclose(cirq.kron(np.eye(2)), np.eye(2)) assert np.allclose(cirq.kron(np.eye(1), np.eye(1)), np.eye(1)) assert np.allclose(cirq.kron(np.eye(1), np.eye(2)), np.eye(2)) assert np.allclose(cirq.kron(np.eye(2), np.eye(3)), np.eye(6)) assert np.allclose(cirq.kron(np.eye(2), np.eye(3), np.eye(4)), np.eye(24))
not np.allclose(restored, matrix))) def assert_magic_su2_within_tolerance(mat, a, b): M = cirq.linalg.decompositions.MAGIC MT = cirq.linalg.decompositions.MAGIC_CONJ_T recon = cirq.linalg.combinators.dot( MT, cirq.linalg.combinators.kron(a, b), M) assert np.allclose(recon, mat), "Failed to decompose within tolerance." @pytest.mark.parametrize('matrix', [ X, cirq.kron(X, X), cirq.kron(X, Y), cirq.kron(X, np.eye(2)) ]) def test_map_eigenvalues_identity(matrix): identity_mapped = cirq.map_eigenvalues(matrix, lambda e: e) assert np.allclose(matrix, identity_mapped) @pytest.mark.parametrize('matrix,exponent,desired', [ [X, 2, np.eye(2)], [X, 3, X], [Z, 2, np.eye(2)], [H, 2, np.eye(2)], [Z, 0.5, np.diag([1, 1j])], [X, 0.5, np.array([[1j, 1], [1, 1j]]) * (1 - 1j) / 2],
def assert_kronecker_factorization_not_within_tolerance(matrix, g, f1, f2): restored = g * cirq.linalg.combinators.kron(f1, f2) assert (np.any(np.isnan(restored) or not np.allclose(restored, matrix))) def assert_magic_su2_within_tolerance(mat, a, b): M = cirq.linalg.decompositions.MAGIC MT = cirq.linalg.decompositions.MAGIC_CONJ_T recon = cirq.linalg.combinators.dot(MT, cirq.linalg.combinators.kron(a, b), M) assert np.allclose(recon, mat), "Failed to decompose within tolerance." @pytest.mark.parametrize( 'matrix', [X, cirq.kron(X, X), cirq.kron(X, Y), cirq.kron(X, np.eye(2))]) def test_map_eigenvalues_identity(matrix): identity_mapped = cirq.map_eigenvalues(matrix, lambda e: e) assert np.allclose(matrix, identity_mapped) @pytest.mark.parametrize('matrix,exponent,desired', [ [X, 2, np.eye(2)], [X, 3, X], [Z, 2, np.eye(2)], [H, 2, np.eye(2)], [Z, 0.5, np.diag([1, 1j])], [X, 0.5, np.array([[1j, 1], [1, 1j]]) * (1 - 1j) / 2], ])
def kron_to_tensor(state_lists): states = tf.convert_to_tensor( np.concatenate( tuple(cirq.kron(*state_list) for state_list in state_lists))) return states
s, m, match: str): m = np.array(m) s = np.diag(s) with pytest.raises(ValueError, match=match): cirq.diagonalize_real_symmetric_and_sorted_diagonal_matrices(m, s) @pytest.mark.parametrize( 'a,b', [ (np.zeros((0, 0)), np.zeros((0, 0))), (np.eye(2), np.eye(2)), (np.eye(4), np.eye(4)), (np.eye(4), np.zeros((4, 4))), (H, H), (cirq.kron(np.eye(2), H), cirq.kron(H, np.eye(2))), (cirq.kron(np.eye(2), Z), cirq.kron(X, np.eye(2))), ] + [random_bi_diagonalizable_pair(2) for _ in range(10)] + [random_bi_diagonalizable_pair(4) for _ in range(10)] + [ random_bi_diagonalizable_pair(4, d1, d2) for _ in range(10) for d1 in range(4) for d2 in range(4) ] + [random_bi_diagonalizable_pair(k) for k in range(1, 10)], ) def test_bidiagonalize_real_matrix_pair_with_symmetric_products(a, b): a = np.array(a) b = np.array(b) p, q = cirq.bidiagonalize_real_matrix_pair_with_symmetric_products(a, b) assert_bidiagonalized_by(a, p, q) assert_bidiagonalized_by(b, p, q)
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import itertools import numpy as np import pytest import sympy import cirq H = np.array([[1, 1], [1, -1]]) * np.sqrt(0.5) HH = cirq.kron(H, H) QFT2 = np.array([[1, 1, 1, 1], [1, 1j, -1, -1j], [1, -1, 1, -1], [1, -1j, -1, 1j]]) * 0.5 @pytest.mark.parametrize('eigen_gate_type', [ cirq.CZPowGate, cirq.XPowGate, cirq.YPowGate, cirq.ZPowGate, ]) def test_phase_insensitive_eigen_gates_consistent_protocols(eigen_gate_type): cirq.testing.assert_eigengate_implements_consistent_protocols( eigen_gate_type)
def score_input( matrix_to_sycamore_operations: Callable, input: np.ndarray, result: JudgeLogEntry, multiplier: int, n_qubits: int, min_two_qubit, ): # see Shende et al. theoretical_lower_bound = int(1 / 4 * (4**n_qubits - 3 * n_qubits - 1)) generic_lower_bound = min(theoretical_lower_bound, min_two_qubit) # max score settings max_trace_distance_score = multiplier result.max_score += max_trace_distance_score max_two_qubit_gate_count_score = multiplier * 2 result.max_score += max_two_qubit_gate_count_score max_sycamore_score = multiplier result.max_score += max_sycamore_score # prepare qubits if n_qubits < 4: qs = cirq.GridQubit.rect(1, n_qubits, 3, 3) elif int(np.sqrt(n_qubits))**2 == n_qubits: qs = cirq.GridQubit.square(int(np.sqrt(n_qubits)), 3, 3) elif n_qubits % 2 == 0: qs = cirq.GridQubit.rect(2, int(n_qubits / 2), 3, 3) else: qs = cirq.GridQubit.rect(2, int((n_qubits + 1) / 2), 3, 3)[:-1] # an executing method is mandatory skipped = False result.msgs += f"\nexecuting method (0 pts): " try: response, ancillae = matrix_to_sycamore_operations(qs, input) if response == NotImplemented: skipped = True result.msgs += f"✔ [0 pts]" elif response != NotImplemented: response_circuit = cirq.Circuit(response) print(f'Circuit:\n{response_circuit}') total_qubit_count = len(qs) + len(ancillae) assert ( total_qubit_count <= 10 ), f"Number of total qubits (target + ancilla) can't be larger than 10! Response has {total_qubit_count}." response_unitary = response_circuit.unitary( qubit_order=qs + ancillae, qubits_that_should_be_present=qs + ancillae) expected_unitary = cirq.kron(input, np.eye(2**len(ancillae))) result.msgs += f"✔ [0 pts]" failed = False except BaseException as ex: response = ex response_tb = traceback.format_exc() failed = True result.msgs += (f"✘\n {type(response)}: {str(response)[:50]}" f"\n {response_tb[:500]}") ##### # scoring functions for each feature ##### def _score_two_plus_qubit_gates(): # it is mandatory to have 1 and 2 qubit gates max more_than_two_qubit_gates = len([ op for op in response_circuit.all_operations() if cirq.num_qubits(op) > 2 or np.log2(len(cirq.unitary(op))) > 2 ]) assert more_than_two_qubit_gates == 0, ( f"Number of gates that need more than two " f"qubits: {more_than_two_qubit_gates} <-- it " f"should be zero!") return 0, "" def _score_trace_distance(): # extra points for exact equality u = response_unitary @ expected_unitary.conj().T trace_distance = cirq.trace_distance_from_angle_list( np.angle(np.linalg.eigvals(u))) print(f'Response:\n{response_unitary}\nExpected:\n{expected_unitary}') assert ( trace_distance < 1e-4 ), f"trace distance of input.conj().T @ response is {trace_distance} > 1e-4" return max_trace_distance_score, "" def _score_circuit_structure(): # the shorter your circuit/response the more points you get! num_two_qubit_gates = len([ op for op in response_circuit.all_operations() if cirq.num_qubits(op) == 2 ]) res_score = 0 if num_two_qubit_gates == 0: res_score = max_two_qubit_gate_count_score elif num_two_qubit_gates >= generic_lower_bound: res_score = (generic_lower_bound / num_two_qubit_gates * max_two_qubit_gate_count_score) elif num_two_qubit_gates < generic_lower_bound: # bonus for going below the lower bound! res_score = (max_two_qubit_gate_count_score + max_two_qubit_gate_count_score / 2) result.msgs += " [WOW! 50% bonus] " extra_msgs = f"\n - 2-qubit gates in your result: {num_two_qubit_gates}" extra_msgs += f"\n - Lower bound for general case: {generic_lower_bound}" return res_score, extra_msgs def _score_sycamore(): # extra points for compatibility with Sycamore cirq.Circuit(response, device=cirq.google.Sycamore) return max_sycamore_score, "" # running the scoring functions for task, score_func, fail_all_after, max_score in [ ("2+ qubit gates", _score_two_plus_qubit_gates, True, 0), ( f"Close in trace distance", _score_trace_distance, True, max_trace_distance_score, ), ( "Circuit structure", _score_circuit_structure, False, max_two_qubit_gate_count_score, ), ("Valid for Sycamore device", _score_sycamore, False, max_sycamore_score), ]: result.msgs += f"\n{task} ({max_score} pts): " if skipped: result.msgs += "[skipped] " elif failed: result.msgs += f"✘\n" else: try: score, extra_msgs = score_func() result.msgs += f"✔ [{score} pts]" result.msgs += extra_msgs result.actual_score += score except BaseException as ex: if fail_all_after: failed = True result.msgs += (f"✘\n {type(ex)}: {str(ex)[:50]}" f"\n {traceback.format_exc()}")