def test_final_density_matrix_param_resolver(): s = sympy.Symbol('s') with pytest.raises(ValueError, match='not specified in parameter sweep'): _ = cirq.final_density_matrix(cirq.X**s) np.testing.assert_allclose( cirq.final_density_matrix(cirq.X**s, param_resolver={s: 0.5}), [[0.5 - 0.j, 0. + 0.5j], [0. - 0.5j, 0.5 - 0.j]])
def test_final_density_matrix_seed_with_dephasing(): a = cirq.LineQubit(0) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.X(a)**0.5, cirq.measure(a)], seed=123), [[0.5 + 0.j, 0. + 0.j], [0. + 0.j, 0.5 + 0.j]], atol=1e-4) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.X(a)**0.5, cirq.measure(a)], seed=124), [[0.5 + 0.j, 0. + 0.j], [0. + 0.j, 0.5 + 0.j]], atol=1e-4)
def test_final_density_matrix_seed_with_collapsing(): a = cirq.LineQubit(0) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.X(a)**0.5, cirq.measure(a)], seed=123, ignore_measurement_results=False), [[0, 0], [0, 1]], atol=1e-4) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.X(a)**0.5, cirq.measure(a)], seed=124, ignore_measurement_results=False), [[1, 0], [0, 0]], atol=1e-4)
def test_final_density_matrix_noise(): a = cirq.LineQubit(0) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.H(a), cirq.Z(a), cirq.H(a), cirq.measure(a)]), [[0, 0], [0, 1]], atol=1e-4) np.testing.assert_allclose(cirq.final_density_matrix( [cirq.H(a), cirq.Z(a), cirq.H(a), cirq.measure(a)], noise=cirq.ConstantQubitNoiseModel(cirq.amplitude_damp(1.0))), [[1, 0], [0, 0]], atol=1e-4)
def test_final_density_matrix_different_program_types(): a, b = cirq.LineQubit.range(2) np.testing.assert_allclose(cirq.final_density_matrix(cirq.X), [[0, 0], [0, 1]], atol=1e-8) ops = [cirq.H(a), cirq.CNOT(a, b)] np.testing.assert_allclose( cirq.final_density_matrix(cirq.Circuit(ops)), [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]], atol=1e-8)
def test_ps_initial_state_dmat(): q0, q1 = cirq.LineQubit.range(2) s00 = cirq.KET_ZERO(q0) * cirq.KET_ZERO(q1) sp0 = cirq.KET_PLUS(q0) * cirq.KET_ZERO(q1) np.testing.assert_allclose( cirq.final_density_matrix(cirq.Circuit(cirq.I.on_each(q0, q1))), cirq.final_density_matrix(cirq.Circuit(cirq.I.on_each(q0, q1)), initial_state=s00)) np.testing.assert_allclose( cirq.final_density_matrix(cirq.Circuit(cirq.H(q0), cirq.I(q1))), cirq.final_density_matrix(cirq.Circuit(cirq.I.on_each(q0, q1)), initial_state=sp0))
def test_gate_substitution_noise_model(): def _overrotation(op): if isinstance(op.gate, cirq.XPowGate): return cirq.XPowGate(exponent=op.gate.exponent + 0.1).on(*op.qubits) return op noise = cirq.devices.noise_model.GateSubstitutionNoiseModel(_overrotation) q0 = cirq.LineQubit(0) circuit = cirq.Circuit(cirq.X(q0) ** 0.5, cirq.Y(q0)) circuit2 = cirq.Circuit(cirq.X(q0) ** 0.6, cirq.Y(q0)) rho1 = cirq.final_density_matrix(circuit, noise=noise) rho2 = cirq.final_density_matrix(circuit2) np.testing.assert_allclose(rho1, rho2)
def test_final_density_matrix_initial_state(): np.testing.assert_allclose(cirq.final_density_matrix(cirq.X, initial_state=0), [[0, 0], [0, 1]], atol=1e-8) np.testing.assert_allclose(cirq.final_density_matrix(cirq.X, initial_state=1), [[1, 0], [0, 0]], atol=1e-8) np.testing.assert_allclose(cirq.final_density_matrix( cirq.X, initial_state=[np.sqrt(0.5), 1j * np.sqrt(0.5)]), [[0.5, 0.5j], [-0.5j, 0.5]], atol=1e-8)
def test_same_partial_trace(): qubit_order = cirq.LineQubit.range(2) q0, q1 = qubit_order mps_simulator = ccq.mps_simulator.MPSSimulator() for _ in range(50): for initial_state in range(4): circuit = cirq.testing.random_circuit(qubit_order, 3, 0.9) expected_density_matrix = cirq.final_density_matrix( circuit, qubit_order=qubit_order, initial_state=initial_state) expected_partial_trace = cirq.partial_trace( expected_density_matrix.reshape(2, 2, 2, 2), keep_indices=[0]) final_state = mps_simulator.simulate( circuit, qubit_order=qubit_order, initial_state=initial_state).final_state actual_density_matrix = final_state.partial_trace([q0, q1]) actual_partial_trace = final_state.partial_trace([q0]) np.testing.assert_allclose(actual_density_matrix, expected_density_matrix, atol=1e-4) np.testing.assert_allclose(actual_partial_trace, expected_partial_trace, atol=1e-4)
def test_noisy_gate_conversions_compiled_sampler(gate: cirq.Gate): # Create test circuit that uses superdense coding to quantify arbitrary Pauli error mixtures. n = gate.num_qubits() qs = cirq.LineQubit.range(n) circuit = cirq.Circuit( cirq.H.on_each(qs), [cirq.CNOT(q, q + n) for q in qs], gate(*qs), [cirq.CNOT(q, q + n) for q in qs], cirq.H.on_each(qs), ) expected_rates = cirq.final_density_matrix(circuit).diagonal().real # Convert test circuit to Stim and sample from it. stim_circuit, _ = cirq_circuit_to_stim_data(circuit + cirq.measure( *sorted(circuit.all_qubits())[::-1])) sample_count = 10000 samples = stim_circuit.compile_sampler().sample_bit_packed( sample_count).flat unique, counts = np.unique(samples, return_counts=True) # Compare sample rates to expected rates. for value, count in zip(unique, counts): expected_rate = expected_rates[value] actual_rate = count / sample_count allowed_variation = 5 * (expected_rate * (1 - expected_rate) / sample_count)**0.5 if not 0 <= expected_rate - allowed_variation <= 1: raise ValueError( "Not enough samples to bound results away from extremes.") assert abs(expected_rate - actual_rate) < allowed_variation, ( f"Sample rate {actual_rate} is over 5 standard deviations away from {expected_rate}.\n" f"Gate: {gate}\n" f"Test circuit:\n{circuit}\n" f"Converted circuit:\n{stim_circuit}\n")
def test_tensor_density_matrix_1(): q = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.YPowGate(exponent=0.25).on(q[0])) rho1 = cirq.final_density_matrix(c, qubit_order=q, dtype=np.complex128) rho2 = ccq.tensor_density_matrix(c, q) np.testing.assert_allclose(rho1, rho2, atol=1e-15)
def test_tensor_density_matrix_3(): qubits = cirq.LineQubit.range(10) circuit = cirq.testing.random_circuit(qubits=qubits, n_moments=10, op_density=0.8) rho1 = cirq.final_density_matrix(circuit, dtype=np.complex128) rho2 = ccq.tensor_density_matrix(circuit, qubits) np.testing.assert_allclose(rho1, rho2, atol=1e-8)
def test_tensor_density_matrix_gridqubit(): qubits = cirq.GridQubit.rect(2, 2) circuit = cirq.testing.random_circuit(qubits=qubits, n_moments=10, op_density=0.8) circuit = cirq.drop_empty_moments(circuit) noise_model = cirq.ConstantQubitNoiseModel(cirq.DepolarizingChannel(p=1e-3)) circuit = cirq.Circuit(noise_model.noisy_moments(circuit.moments, qubits)) rho1 = cirq.final_density_matrix(circuit, dtype=np.complex128) rho2 = ccq.tensor_density_matrix(circuit, qubits) np.testing.assert_allclose(rho1, rho2, atol=1e-8)
def test_tensor_density_matrix_2(): q = cirq.LineQubit.range(2) rs = np.random.RandomState(52) for _ in range(10): g = cirq.MatrixGate(cirq.testing.random_unitary(dim=2 ** len(q), random_state=rs)) c = cirq.Circuit(g.on(*q)) rho1 = cirq.final_density_matrix(c, dtype=np.complex128) rho2 = ccq.tensor_density_matrix(c, q) np.testing.assert_allclose(rho1, rho2, atol=1e-8)
def test_tensor_density_matrix_4(): qubits = cirq.LineQubit.range(4) circuit = cirq.testing.random_circuit(qubits=qubits, n_moments=100, op_density=0.8) cirq.DropEmptyMoments().optimize_circuit(circuit) noise_model = cirq.ConstantQubitNoiseModel(cirq.DepolarizingChannel(p=1e-3)) circuit = cirq.Circuit(noise_model.noisy_moments(circuit.moments, qubits)) rho1 = cirq.final_density_matrix(circuit, dtype=np.complex128) rho2 = ccq.tensor_density_matrix(circuit, qubits) np.testing.assert_allclose(rho1, rho2, atol=1e-8)
def test_final_density_matrix_qubit_order(): a, b = cirq.LineQubit.range(2) np.testing.assert_allclose( cirq.final_density_matrix([cirq.X(a), cirq.X(b)**0.5], qubit_order=[a, b]), [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0.5, 0.5j], [0, 0, -0.5j, 0.5]]) np.testing.assert_allclose( cirq.final_density_matrix([cirq.X(a), cirq.X(b)**0.5], qubit_order=[b, a]), [[0, 0, 0, 0], [0, 0.5, 0, 0.5j], [0, 0, 0, 0], [0, -0.5j, 0, 0.5]]) np.testing.assert_allclose( cirq.final_density_matrix([cirq.X(a), cirq.X(b)**0.5], qubit_order=[b, a], noise=cirq.ConstantQubitNoiseModel( cirq.amplitude_damp(1.0))), [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])
def test_tp_projector(): q0, q1 = cirq.LineQubit.range(2) p00 = (cirq.KET_ZERO(q0) * cirq.KET_ZERO(q1)).projector() rho = cirq.final_density_matrix(cirq.Circuit(cirq.I.on_each(q0, q1))) np.testing.assert_allclose(rho, p00) p01 = (cirq.KET_ZERO(q0) * cirq.KET_ONE(q1)).projector() rho = cirq.final_density_matrix(cirq.Circuit([cirq.I.on_each(q0, q1), cirq.X(q1)])) np.testing.assert_allclose(rho, p01) ppp = (cirq.KET_PLUS(q0) * cirq.KET_PLUS(q1)).projector() rho = cirq.final_density_matrix( cirq.Circuit( [ cirq.H.on_each(q0, q1), ] ) ) np.testing.assert_allclose(rho, ppp, atol=1e-7) ppm = (cirq.KET_PLUS(q0) * cirq.KET_MINUS(q1)).projector() rho = cirq.final_density_matrix(cirq.Circuit([cirq.H.on_each(q0, q1), cirq.Z(q1)])) np.testing.assert_allclose(rho, ppm, atol=1e-7) pii = (cirq.KET_IMAG(q0) * cirq.KET_IMAG(q1)).projector() rho = cirq.final_density_matrix(cirq.Circuit(cirq.rx(-np.pi / 2).on_each(q0, q1))) np.testing.assert_allclose(rho, pii, atol=1e-7) pij = (cirq.KET_IMAG(q0) * cirq.KET_MINUS_IMAG(q1)).projector() rho = cirq.final_density_matrix(cirq.Circuit(cirq.rx(-np.pi / 2)(q0), cirq.rx(np.pi / 2)(q1))) np.testing.assert_allclose(rho, pij, atol=1e-7)
def test_same_partial_trace(): qubit_order = cirq.LineQubit.range(2) q0, q1 = qubit_order angles = [0.0, 0.20160913, math.pi / 3.0, math.pi / 2.0, math.pi] gate_cls = [cirq.rx, cirq.ry, cirq.rz] for angle_0 in angles: for gate_0 in gate_cls: for angle_1 in angles: for gate_1 in gate_cls: for use_cnot in [False, True]: op0 = gate_0(angle_0) op1 = gate_1(angle_1) circuit = cirq.Circuit() circuit.append(op0(q0)) if use_cnot: circuit.append(cirq.qft(q0, q1)) circuit.append(op1(q1)) if use_cnot: circuit.append(cirq.qft(q1, q0)) for initial_state in range(4): expected_density_matrix = cirq.final_density_matrix( circuit, qubit_order=qubit_order, initial_state=initial_state) expected_partial_trace = cirq.partial_trace( expected_density_matrix.reshape(2, 2, 2, 2), keep_indices=[0]) mps_simulator = ccq.mps_simulator.MPSSimulator() final_state = mps_simulator.simulate( circuit, qubit_order=qubit_order, initial_state=initial_state).final_state actual_density_matrix = final_state.partial_trace( [q0, q1]) actual_partial_trace = final_state.partial_trace( [q0]) np.testing.assert_allclose(actual_density_matrix, expected_density_matrix, atol=1e-4) np.testing.assert_allclose(actual_partial_trace, expected_partial_trace, atol=1e-4)
def test_tableau_simulator_error_mechanisms(gate: cirq.Gate): # Technically this be a test of the `stim` package itself, but it's so convenient to compare to cirq. # Create test circuit that uses superdense coding to quantify arbitrary Pauli error mixtures. n = gate.num_qubits() qs = cirq.LineQubit.range(n) circuit = cirq.Circuit( cirq.H.on_each(qs), [cirq.CNOT(q, q + n) for q in qs], gate(*qs), [cirq.CNOT(q, q + n) for q in qs], cirq.H.on_each(qs), ) expected_rates = cirq.final_density_matrix(circuit).diagonal().real # Convert test circuit to Stim and sample from it. stim_circuit, _ = cirq_circuit_to_stim_data(circuit + cirq.measure( *sorted(circuit.all_qubits())[::-1])) sample_count = 10000 samples = [] for _ in range(sample_count): sim = stim.TableauSimulator() sim.do(stim_circuit) s = 0 for k, v in enumerate(sim.current_measurement_record()): s |= v << k samples.append(s) unique, counts = np.unique(samples, return_counts=True) # Compare sample rates to expected rates. for value, count in zip(unique, counts): expected_rate = expected_rates[value] actual_rate = count / sample_count allowed_variation = 5 * (expected_rate * (1 - expected_rate) / sample_count)**0.5 if not 0 <= expected_rate - allowed_variation <= 1: raise ValueError( "Not enough samples to bound results away from extremes.") assert abs(expected_rate - actual_rate) < allowed_variation, ( f"Sample rate {actual_rate} is over 5 standard deviations away from {expected_rate}.\n" f"Gate: {gate}\n" f"Test circuit:\n{circuit}\n" f"Converted circuit:\n{stim_circuit}\n")
def test_final_density_matrix_dtype_insensitive_to_initial_state(): assert (cirq.final_density_matrix(cirq.X, ).dtype == np.complex64) assert cirq.final_density_matrix(cirq.X, initial_state=0).dtype == np.complex64 assert (cirq.final_density_matrix( cirq.X, initial_state=[np.sqrt(0.5), np.sqrt(0.5)]).dtype == np.complex64) assert (cirq.final_density_matrix( cirq.X, initial_state=np.array([np.sqrt(0.5), np.sqrt(0.5)])).dtype == np.complex64) for t in [np.int32, np.float32, np.float64, np.complex64]: assert (cirq.final_density_matrix( cirq.X, initial_state=np.array([1, 0], dtype=t)).dtype == np.complex64) assert (cirq.final_density_matrix( cirq.X, initial_state=np.array([1, 0], dtype=t), dtype=np.complex128).dtype == np.complex128)