def test_invalid_arguments(): with pytest.raises(ValueError, match='At least one metric must be specified'): NoiseProperties() with pytest.raises( ValueError, match='xeb, pauli error, p00, and p11 must be between 0 and 1'): NoiseProperties(p00=1.2) with pytest.raises( ValueError, match='xeb, pauli error, p00, and p11 must be between 0 and 1'): NoiseProperties(pauli_error=-0.2) with pytest.raises( ValueError, match= 'Only one of xeb fidelity, pauli error, or decay constant should be defined', ): NoiseProperties(pauli_error=0.2, xeb_fidelity=0.5) with pytest.raises(ValueError, match='A NoiseProperties object must be specified'): NoiseModelFromNoiseProperties(None)
def test_wait_gates(): q0 = cirq.LineQubit(0) props = TestNoiseProperties(**default_props([q0], [])) model = NoiseModelFromNoiseProperties(props) op = cirq.wait(q0, nanos=100) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 2 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # No depolarizing noise because WaitGate has none. assert len(noisy_circuit.moments[1].operations) == 1 thermal_op = noisy_circuit.moments[1].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( thermal_choi, [ [1, 0, 0, 9.990005e-01], [0, 9.99500167e-04, 0, 0], [0, 0, 0, 0], [9.990005e-01, 0, 0, 9.990005e-01], ], )
def test_measure_gates(): q00, q01, q10, q11 = cirq.GridQubit.rect(2, 2) qubits = [q00, q01, q10, q11] props = TestNoiseProperties(**default_props( qubits, [ (q00, q01), (q01, q00), (q10, q11), (q11, q10), (q00, q10), (q10, q00), (q01, q11), (q11, q01), ], )) model = NoiseModelFromNoiseProperties(props) op = cirq.measure(*qubits, key='m') circuit = cirq.Circuit(cirq.measure(*qubits, key='m')) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 2 # Amplitude damping before measurement assert len(noisy_circuit.moments[0].operations) == 4 for q in qubits: op = noisy_circuit.moments[0].operation_at(q) assert isinstance(op.gate, cirq.GeneralizedAmplitudeDampingChannel), q assert np.isclose(op.gate.p, 0.90909090), q assert np.isclose(op.gate.gamma, 0.011), q # Original measurement is after the noise. assert len(noisy_circuit.moments[1].operations) == 1 # Measurements are untagged during reconstruction. assert noisy_circuit.moments[1] == circuit.moments[0]
def test_two_qubit_gates(op): q0, q1 = cirq.LineQubit.range(2) props = TestNoiseProperties( **default_props([q0, q1], [(q0, q1), (q1, q0)])) model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 3 assert len(noisy_circuit.moments[0].operations) == 1 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # Depolarizing noise assert len(noisy_circuit.moments[1].operations) == 1 depol_op = noisy_circuit.moments[1].operations[0] assert isinstance(depol_op.gate, cirq.DepolarizingChannel) assert np.isclose(depol_op.gate.p, 0.00952008) # Thermal noise assert len(noisy_circuit.moments[2].operations) == 2 thermal_op_0 = noisy_circuit.moments[2].operation_at(q0) thermal_op_1 = noisy_circuit.moments[2].operation_at(q1) assert isinstance(thermal_op_0.gate, cirq.KrausChannel) assert isinstance(thermal_op_1.gate, cirq.KrausChannel) thermal_choi_0 = cirq.kraus_to_choi(cirq.kraus(thermal_op_0)) thermal_choi_1 = cirq.kraus_to_choi(cirq.kraus(thermal_op_1)) expected_thermal_choi = np.array([ [1, 0, 0, 9.99680051e-01], [0, 3.19948805e-04, 0, 0], [0, 0, 0, 0], [9.99680051e-01, 0, 0, 9.99680051e-01], ]) assert np.allclose(thermal_choi_0, expected_thermal_choi) assert np.allclose(thermal_choi_1, expected_thermal_choi)
def test_single_qubit_gates(op): q0 = cirq.LineQubit(0) props = TestNoiseProperties(**default_props([q0], [])) model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 3 assert len(noisy_circuit.moments[0].operations) == 1 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # Depolarizing noise assert len(noisy_circuit.moments[1].operations) == 1 depol_op = noisy_circuit.moments[1].operations[0] assert isinstance(depol_op.gate, cirq.DepolarizingChannel) assert np.isclose(depol_op.gate.p, 0.00081252) # Thermal noise assert len(noisy_circuit.moments[2].operations) == 1 thermal_op = noisy_circuit.moments[2].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( thermal_choi, [ [1, 0, 0, 9.99750031e-01], [0, 2.49968753e-04, 0, 0], [0, 0, 0, 0], [9.99750031e-01, 0, 0, 9.99750031e-01], ], )
def test_ampl_damping_error(): t1_ns = 200.0 # Create qubits and circuit qubits = [cirq.LineQubit(0), cirq.LineQubit(1)] circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.FSimGate(5 * np.pi / 2, np.pi).on_each(qubits)]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) # Create noise model from NoiseProperties object with specified noise prop = NoiseProperties(t1_ns=t1_ns) noise_model = NoiseModelFromNoiseProperties(prop) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(circuit, qubits)) # Insert expected channels to circuit expected_circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-25.0 / t1_ns)).on_each(qubits)]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-25.0 / t1_ns)).on_each(qubits)]), cirq.Moment([cirq.FSimGate(np.pi / 2, np.pi).on_each(qubits)]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-12.0 / t1_ns)).on_each(qubits)]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), cirq.Moment([ cirq.amplitude_damp(1 - np.exp(-4000.0 / t1_ns)).on_each(qubits) ]), ) assert_equivalent_op_tree(expected_circuit, noisy_circuit)
def test_depolarization_error(): # Account for floating point errors # Needs Cirq issue 3965 to be resolved pauli_error = 0.09999999999999998 # Create qubits and circuit qubits = [cirq.LineQubit(0), cirq.LineQubit(1)] circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) # Create noise model from NoiseProperties object with specified noise prop = NoiseProperties(pauli_error=pauli_error) noise_model = NoiseModelFromNoiseProperties(prop) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(circuit, qubits)) # Insert expected channels to circuit expected_circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.depolarize(pauli_error / 3).on_each(qubits)]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.depolarize(pauli_error / 3).on_each(qubits)]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([cirq.depolarize(pauli_error / 3).on_each(qubits)]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), cirq.Moment([cirq.depolarize(pauli_error / 3).on_each(qubits)]), ) assert_equivalent_op_tree(expected_circuit, noisy_circuit)
def test_sample_model(): q0, q1 = cirq.LineQubit.range(2) props = SampleNoiseProperties([q0, q1], [(q0, q1), (q1, q0)]) model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(cirq.X(q0), cirq.CNOT(q0, q1), cirq.Z(q1), cirq.measure(q0, q1, key='meas')) noisy_circuit = circuit.with_noise(model) expected_circuit = cirq.Circuit( cirq.Moment(cirq.X(q0).with_tags(PHYSICAL_GATE_TAG)), cirq.Moment(cirq.H(q0)), cirq.Moment(cirq.CNOT(q0, q1).with_tags(PHYSICAL_GATE_TAG)), cirq.Moment(cirq.ISWAP(q0, q1)), cirq.Moment(cirq.Z(q1).with_tags(PHYSICAL_GATE_TAG)), cirq.Moment(cirq.H(q1)), cirq.Moment(cirq.measure(q0, q1, key='meas')), cirq.Moment(cirq.H(q0), cirq.H(q1)), ) assert noisy_circuit == expected_circuit
def test_readout_error(): p00 = 0.05 p11 = 0.1 p = p11 / (p00 + p11) gamma = p11 / p # Create qubits and circuit qubits = [cirq.LineQubit(0), cirq.LineQubit(1)] circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) # Create noise model from NoiseProperties object with specified noise prop = NoiseProperties(p00=p00, p11=p11) noise_model = NoiseModelFromNoiseProperties(prop) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(circuit, qubits)) # Insert expected channels to circuit expected_circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([ cirq.GeneralizedAmplitudeDampingChannel( p=p, gamma=gamma).on_each(qubits) ]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) assert_equivalent_op_tree(expected_circuit, noisy_circuit) # Create Noise Model with just p00 prop_p00 = NoiseProperties(p00=p00) noise_model_p00 = NoiseModelFromNoiseProperties(prop_p00) noisy_circuit_p00 = cirq.Circuit( noise_model_p00.noisy_moments(circuit, qubits)) # Insert expected channels to circuit expected_circuit_p00 = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([ cirq.GeneralizedAmplitudeDampingChannel(p=0.0, gamma=p00).on_each(qubits) ]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) assert_equivalent_op_tree(expected_circuit_p00, noisy_circuit_p00) # Create Noise Model with just p11 prop_p11 = NoiseProperties(p11=p11) noise_model_p11 = NoiseModelFromNoiseProperties(prop_p11) noisy_circuit_p11 = cirq.Circuit( noise_model_p11.noisy_moments(circuit, qubits)) # Insert expected channels to circuit expected_circuit_p11 = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.H(qubits[1])]), cirq.Moment([ cirq.GeneralizedAmplitudeDampingChannel(p=1.0, gamma=p11).on_each(qubits) ]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) assert_equivalent_op_tree(expected_circuit_p11, noisy_circuit_p11)
def test_combined_error(): # Helper function to calculate pauli error from depolarization def pauli_error_from_depolarization(pauli_error, t1_ns, duration): t2 = 2 * t1_ns pauli_error_from_t1 = (1 - np.exp(-duration / t2)) / 2 + ( 1 - np.exp(-duration / t1_ns)) / 4 if pauli_error >= pauli_error_from_t1: return pauli_error - pauli_error_from_t1 return pauli_error t1_ns = 2000.0 p11 = 0.01 # Account for floating point errors # Needs Cirq issue 3965 to be resolved pauli_error = 0.019999999999999962 # Create qubits and circuit qubits = [cirq.LineQubit(0), cirq.LineQubit(1)] circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.measure(qubits[0], key='q0')]), cirq.Moment([cirq.ISwapPowGate().on_each(qubits)]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), ) # Create noise model from NoiseProperties object with specified noise prop = NoiseProperties(t1_ns=t1_ns, p11=p11, pauli_error=pauli_error) noise_model = NoiseModelFromNoiseProperties(prop) with pytest.warns( RuntimeWarning, match='Pauli error from T1 decay is greater than total Pauli error' ): noisy_circuit = cirq.Circuit(noise_model.noisy_moments( circuit, qubits)) # Insert expected channels to circuit expected_circuit = cirq.Circuit( cirq.Moment([cirq.X(qubits[0])]), cirq.Moment([ cirq.depolarize( pauli_error_from_depolarization(pauli_error, t1_ns, 25.0) / 3).on_each(qubits) ]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-25.0 / t1_ns)).on_each(qubits)]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([ cirq.depolarize( pauli_error_from_depolarization(pauli_error, t1_ns, 25.0) / 3).on_each(qubits) ]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-25.0 / t1_ns)).on_each(qubits)]), cirq.Moment([ cirq.GeneralizedAmplitudeDampingChannel(p=1.0, gamma=p11).on(qubits[0]) ]), cirq.Moment([cirq.measure(qubits[0], key='q0')]), cirq.Moment([ cirq.depolarize( pauli_error_from_depolarization(pauli_error, t1_ns, 4000.0) / 3).on_each(qubits) ]), cirq.Moment([ cirq.amplitude_damp(1 - np.exp(-4000.0 / t1_ns)).on_each(qubits) ]), cirq.Moment([cirq.ISwapPowGate().on_each(qubits)]), cirq.Moment([ cirq.depolarize( pauli_error_from_depolarization(pauli_error, t1_ns, 32.0) / 3).on_each(qubits) ]), cirq.Moment( [cirq.amplitude_damp(1 - np.exp(-32.0 / t1_ns)).on_each(qubits)]), cirq.Moment([ cirq.GeneralizedAmplitudeDampingChannel(p=1.0, gamma=p11).on_each(qubits) ]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1') ]), cirq.Moment([ cirq.depolarize( pauli_error_from_depolarization(pauli_error, t1_ns, 4000.0) / 3).on_each(qubits) ]), cirq.Moment([ cirq.amplitude_damp(1 - np.exp(-4000.0 / t1_ns)).on_each(qubits) ]), ) assert_equivalent_op_tree(expected_circuit, noisy_circuit)
def test_deprecated_virtual_predicate(): q0, q1 = cirq.LineQubit.range(2) props = SampleNoiseProperties([q0, q1], [(q0, q1), (q1, q0)]) model = NoiseModelFromNoiseProperties(props) with cirq.testing.assert_deprecated("Use is_virtual", deadline="v0.16"): _ = model.virtual_predicate(cirq.X(q0))
def compare_generated_noise_to_metrics( calibration: cirq_google.Calibration, validate: bool = True, tolerance: float = 0.01 ): """Compares the metrics from a Calibration object to those measured from a Noise Model created with cirq.devices.noise_properties_from_calibration. Args: calibration: Calibration object to be turned into a Noise Model validate: check calibration metrics are in agreement (arg for noise_properties_from_calibration) tolerance: tolerance for calibration metrics (argument for noise_properties_from_calibration) Returns: df: Pandas dataframe comparing input and measured values for each calibration metric """ # Create Noise Model from Calibration object noise_prop = noise_properties_from_calibration(calibration, validate, tolerance) noise_model = NoiseModelFromNoiseProperties(noise_prop) p00 = noise_prop.p00 p11 = noise_prop.p11 xeb_fidelity = noise_prop.xeb pauli_error = noise_prop.pauli_error t1_ns = noise_prop.t1_ns average_error = noise_prop.average_error() qubits = [cirq.LineQubit(0), cirq.LineQubit(1)] # Create simulator for experiments with noise model simulator = cirq.sim.DensityMatrixSimulator(noise=noise_model) # Experiments to measure metrics estimate_readout = cirq.experiments.estimate_single_qubit_readout_errors( simulator, qubits=[qubits[0]], repetitions=1000 ) xeb_result = cirq.experiments.cross_entropy_benchmarking( simulator, qubits, num_circuits=50, repetitions=1000 ) measured_xeb = np.mean([datum.xeb_fidelity for datum in xeb_result.data]) decay_constant = xeb_result.depolarizing_model().cycle_depolarization output = [] if p00 is not None: output.append(['p00', p00, estimate_readout.zero_state_errors[cirq.LineQubit(0)]]) if p11 is not None: output.append(['p11', p11, estimate_readout.one_state_errors[cirq.LineQubit(0)]]) if xeb_fidelity is not None: output.append(['XEB Fidelity', xeb_fidelity, measured_xeb]) if t1_ns is not None: t1_results = cirq.experiments.t1_decay( simulator, qubit=qubits[0], num_points=100, repetitions=100, min_delay=cirq.Duration(nanos=10), max_delay=cirq.Duration(micros=1), ) output.append(['T1', t1_ns, t1_results.constant]) if pauli_error is not None: N = 2 # Dimension of Hilbert Space measured_pauli_error = (1 - decay_constant) * (1 - 1 / N / N) output.append(['Pauli Error', pauli_error, measured_pauli_error]) if average_error is not None: N = 2 # Dimension of Hilbert Space measured_average_error = (1 - decay_constant) * (1 - 1 / N) output.append(['Average Error', average_error, measured_average_error]) columns = ["Metric", "Initial value", "Measured value"] df = pd.DataFrame(output, columns=columns) return df