Esempio n. 1
0
def test_floquet_to_calibration_layer_with_measure_qubits():
    qubits = tuple(cirq.GridQubit(0, index) for index in range(5))
    q_00, q_01, q_02, q_03, _ = qubits
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
            measure_qubits=qubits,
        ),
    )

    assert request.to_calibration_layer() == cirq_google.CalibrationLayer(
        calibration_type='floquet_phased_fsim_characterization',
        program=cirq.Circuit(
            [gate.on(q_00, q_01),
             gate.on(q_02, q_03),
             cirq.measure(*qubits)], ),
        args={
            'est_theta': True,
            'est_zeta': True,
            'est_chi': False,
            'est_gamma': False,
            'est_phi': True,
            'readout_corrections': True,
            'version': 2,
        },
    )
Esempio n. 2
0
def test_floquet_parse_result_bad_metric():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )
    result = cirq_google.CalibrationResult(
        code=cirq_google.api.v2.calibration_pb2.SUCCESS,
        error_message=None,
        token=None,
        valid_until=None,
        metrics=cirq_google.Calibration(
            cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[
                cirq_google.api.v2.metrics_pb2.Metric(
                    name='angles',
                    targets=[
                        '1000gerbils',
                    ],
                    values=[
                        cirq_google.api.v2.metrics_pb2.Value(str_val='100_10'),
                    ],
                )
            ])),
    )
    with pytest.raises(ValueError, match='Unknown metric name 1000gerbils'):
        _ = request.parse_result(result)
Esempio n. 3
0
def test_floquet_to_calibration_layer_readout_thresholds():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
            readout_error_tolerance=0.4,
        ),
    )

    assert request.to_calibration_layer() == cirq_google.CalibrationLayer(
        calibration_type='floquet_phased_fsim_characterization',
        program=cirq.Circuit([gate.on(q_00, q_01),
                              gate.on(q_02, q_03)]),
        args={
            'est_theta': True,
            'est_zeta': True,
            'est_chi': False,
            'est_gamma': False,
            'est_phi': True,
            'readout_corrections': True,
            'readout_error_tolerance': 0.4,
            'correlated_readout_error_tolerance': 7 / 6 * 0.4 - 1 / 6,
            'version': 2,
        },
    )
Esempio n. 4
0
def test_run_characterization_fails_when_invalid_arguments():
    with pytest.raises(ValueError):
        assert workflow.run_calibrations([],
                                         None,
                                         'qproc',
                                         cirq_google.FSIM_GATESET,
                                         max_layers_per_request=0)

    request = FloquetPhasedFSimCalibrationRequest(
        gate=SQRT_ISWAP_GATE,
        pairs=(),
        options=WITHOUT_CHI_FLOQUET_PHASED_FSIM_CHARACTERIZATION,
    )
    engine = mock.MagicMock(spec=cirq_google.Engine)

    with pytest.raises(ValueError):
        assert workflow.run_calibrations([request], engine, None,
                                         cirq_google.FSIM_GATESET)

    with pytest.raises(ValueError):
        assert workflow.run_calibrations([request], engine, 'qproc', None)

    with pytest.raises(ValueError):
        assert workflow.run_calibrations([request], 0, 'qproc',
                                         cirq_google.FSIM_GATESET)
Esempio n. 5
0
def _merge_into_calibrations(
    calibration: FloquetPhasedFSimCalibrationRequest,
    calibrations: List[FloquetPhasedFSimCalibrationRequest],
    pairs_map: Dict[Tuple[Tuple[Qid, Qid], ...], int],
    options: FloquetPhasedFSimCalibrationOptions,
) -> int:
    """Merges a calibration into list of calibrations.

    If calibrations contains an item of which pairs could be expanded to include a new calibration
    pairs, without breaking a moment structure, then those two calibrations will be merged together
    and used as a calibration for both old and newly added calibration.
    If no calibration like that exists, the list will be expanded by calibration item.

    Args:
        calibration: Calibration to be added.
        calibrations: List of calibrations to be mutated.
        pairs_map: Map from pairs parameter of each calibration on the calibrations list to the
            index on that list. This map will be updated if the calibrations list us updated.
        options: Calibrations options to use when creating a new requests.

    Returns:
        Index of the calibration on the updated calibrations list. If the calibration was added, it
        points to the last element of a list. If not, it points to already existing element.
    """
    new_pairs = set(calibration.pairs)
    for index in pairs_map.values():
        assert calibration.gate == calibrations[index].gate
        assert calibration.options == calibrations[index].options
        existing_pairs = calibrations[index].pairs
        if new_pairs.issubset(existing_pairs):
            return index
        elif new_pairs.issuperset(existing_pairs):
            calibrations[index] = calibration
            return index
        else:
            new_qubit_pairs = calibration.qubit_to_pair
            existing_qubit_pairs = calibrations[index].qubit_to_pair
            if all((new_qubit_pairs[q] == existing_qubit_pairs[q]
                    for q in set(new_qubit_pairs.keys()).intersection(
                        existing_qubit_pairs.keys()))):
                calibrations[index] = FloquetPhasedFSimCalibrationRequest(
                    gate=calibration.gate,
                    pairs=tuple(sorted(new_pairs.union(existing_pairs))),
                    options=options,
                )
                return index

    index = len(calibrations)
    calibrations.append(calibration)
    pairs_map[calibration.pairs] = index
    return index
Esempio n. 6
0
def test_floquet_parse_result_failure():
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=(),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )

    result = cirq_google.CalibrationResult(
        code=cirq_google.api.v2.calibration_pb2.ERROR_CALIBRATION_FAILED,
        error_message="Test message",
        token=None,
        valid_until=None,
        metrics=cirq_google.Calibration(),
    )

    with pytest.raises(PhasedFSimCalibrationError, match='Test message'):
        request.parse_result(result)
Esempio n. 7
0
def test_run_characterization_with_simulator():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    gate = SQRT_ISWAP_GATE

    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )

    simulator = PhasedFSimEngineSimulator.create_with_ideal_sqrt_iswap()

    actual = workflow.run_calibrations([request], simulator)

    assert actual == [
        PhasedFSimCalibrationResult(
            parameters={
                (q_00, q_01):
                PhasedFSimCharacterization(theta=np.pi / 4,
                                           zeta=0.0,
                                           chi=None,
                                           gamma=None,
                                           phi=0.0),
                (q_02, q_03):
                PhasedFSimCharacterization(theta=np.pi / 4,
                                           zeta=0.0,
                                           chi=None,
                                           gamma=None,
                                           phi=0.0),
            },
            gate=SQRT_ISWAP_GATE,
            options=FloquetPhasedFSimCalibrationOptions(
                characterize_theta=True,
                characterize_zeta=True,
                characterize_chi=False,
                characterize_gamma=False,
                characterize_phi=True,
            ),
        )
    ]
Esempio n. 8
0
def prepare_floquet_characterization_for_moment(
    moment: Moment,
    options: FloquetPhasedFSimCalibrationOptions,
    gates_translator: Callable[
        [Gate],
        Optional[PhaseCalibratedFSimGate]] = try_convert_sqrt_iswap_to_fsim,
    canonicalize_pairs: bool = False,
    sort_pairs: bool = False,
) -> Optional[FloquetPhasedFSimCalibrationRequest]:
    """Describes a given moment in terms of a Floquet characterization request.

    Args:
        moment: Moment to characterize.
        options: Options that are applied to each characterized gate within a moment.
        gates_translator: Function that translates a gate to a supported FSimGate which will undergo
            characterization. Defaults to sqrt_iswap_gates_translator.
        canonicalize_pairs: Whether to sort each of the qubit pair so that the first qubit
            is always lower than the second.
        sort_pairs: Whether to sort all the qutibt pairs extracted from the moment which will
            undergo characterization.

    Returns:
        Instance of FloquetPhasedFSimCalibrationRequest that characterizes a given moment, or None
        when it is an empty, measurement or single-qubit gates only moment.

    Raises:
        IncompatibleMomentError when a moment contains operations other than the operations matched
        by gates_translator, or it mixes a single qubit and two qubit gates.
    """
    pairs_and_gate = _list_moment_pairs_to_characterize(
        moment,
        gates_translator,
        canonicalize_pairs=canonicalize_pairs,
        permit_mixed_moments=False)
    if pairs_and_gate is None:
        return None

    pairs, gate = pairs_and_gate
    return FloquetPhasedFSimCalibrationRequest(
        pairs=tuple(sorted(pairs) if sort_pairs else pairs),
        gate=gate,
        options=options)
Esempio n. 9
0
def test_from_moment():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    m = cirq.Moment(cirq.ISWAP(q_00, q_01)**0.5, cirq.ISWAP(q_02, q_03)**0.5)
    options = FloquetPhasedFSimCalibrationOptions(
        characterize_theta=True,
        characterize_zeta=True,
        characterize_chi=False,
        characterize_gamma=False,
        characterize_phi=True,
    )
    request = FloquetPhasedFSimCalibrationRequest.from_moment(m, options)
    assert request == FloquetPhasedFSimCalibrationRequest(gate=cirq.ISWAP**0.5,
                                                          pairs=((q_00, q_01),
                                                                 (q_02, q_03)),
                                                          options=options)

    non_identical = cirq.Moment(
        cirq.ISWAP(q_00, q_01)**0.5, cirq.ISWAP(q_02, q_03))
    with pytest.raises(ValueError, match='must be identical'):
        _ = FloquetPhasedFSimCalibrationRequest.from_moment(
            non_identical, options)

    sq = cirq.Moment(cirq.X(q_00))
    with pytest.raises(ValueError, match='must be two qubit gates'):
        _ = FloquetPhasedFSimCalibrationRequest.from_moment(sq, options)

    threeq = cirq.Moment(cirq.TOFFOLI(q_00, q_01, q_02))
    with pytest.raises(ValueError, match='must be two qubit gates'):
        _ = FloquetPhasedFSimCalibrationRequest.from_moment(threeq, options)

    not_gate = cirq.Moment(cirq.CircuitOperation(cirq.FrozenCircuit()))
    with pytest.raises(ValueError, match='must be two qubit gates'):
        _ = FloquetPhasedFSimCalibrationRequest.from_moment(not_gate, options)

    empty = cirq.Moment()
    with pytest.raises(ValueError, match='No gates found'):
        _ = FloquetPhasedFSimCalibrationRequest.from_moment(empty, options)
Esempio n. 10
0
def test_run_characterization():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)

    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )

    result = cirq_google.CalibrationResult(
        code=cirq_google.api.v2.calibration_pb2.SUCCESS,
        error_message=None,
        token=None,
        valid_until=None,
        metrics=cirq_google.Calibration(
            cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[
                cirq_google.api.v2.metrics_pb2.Metric(
                    name='angles',
                    targets=[
                        '0_qubit_a',
                        '0_qubit_b',
                        '0_theta_est',
                        '0_zeta_est',
                        '0_phi_est',
                        '1_qubit_a',
                        '1_qubit_b',
                        '1_theta_est',
                        '1_zeta_est',
                        '1_phi_est',
                    ],
                    values=[
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_0'),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_1'),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.1),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.2),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.3),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_2'),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_3'),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.4),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.5),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.6),
                    ],
                )
            ])),
    )

    job = cirq_google.engine.EngineJob('', '', '', None)
    job._calibration_results = [result]

    engine = mock.MagicMock(spec=cirq_google.Engine)
    engine.run_calibration.return_value = job

    progress_calls = []

    def progress(step: int, steps: int) -> None:
        progress_calls.append((step, steps))

    actual = workflow.run_calibrations([request],
                                       engine,
                                       'qproc',
                                       cirq_google.FSIM_GATESET,
                                       progress_func=progress)

    expected = [
        PhasedFSimCalibrationResult(
            parameters={
                (q_00, q_01):
                PhasedFSimCharacterization(theta=0.1,
                                           zeta=0.2,
                                           chi=None,
                                           gamma=None,
                                           phi=0.3),
                (q_02, q_03):
                PhasedFSimCharacterization(theta=0.4,
                                           zeta=0.5,
                                           chi=None,
                                           gamma=None,
                                           phi=0.6),
            },
            gate=gate,
            options=FloquetPhasedFSimCalibrationOptions(
                characterize_theta=True,
                characterize_zeta=True,
                characterize_chi=False,
                characterize_gamma=False,
                characterize_phi=True,
            ),
        )
    ]

    assert actual == expected
    assert progress_calls == [(1, 1)]
Esempio n. 11
0
def test_floquet_parse_result():
    q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)]
    gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0)
    request = FloquetPhasedFSimCalibrationRequest(
        gate=gate,
        pairs=((q_00, q_01), (q_02, q_03)),
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )

    result = cirq_google.CalibrationResult(
        code=cirq_google.api.v2.calibration_pb2.SUCCESS,
        error_message=None,
        token=None,
        valid_until=None,
        metrics=cirq_google.Calibration(
            cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[
                cirq_google.api.v2.metrics_pb2.Metric(
                    name='angles',
                    targets=[
                        '0_qubit_a',
                        '0_qubit_b',
                        '0_theta_est',
                        '0_zeta_est',
                        '0_phi_est',
                        '1_qubit_a',
                        '1_qubit_b',
                        '1_theta_est',
                        '1_zeta_est',
                        '1_phi_est',
                    ],
                    values=[
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_0'),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_1'),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.1),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.2),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.3),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_2'),
                        cirq_google.api.v2.metrics_pb2.Value(str_val='0_3'),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.4),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.5),
                        cirq_google.api.v2.metrics_pb2.Value(double_val=0.6),
                    ],
                )
            ])),
    )

    assert request.parse_result(result) == PhasedFSimCalibrationResult(
        parameters={
            (q_00, q_01):
            PhasedFSimCharacterization(theta=0.1,
                                       zeta=0.2,
                                       chi=None,
                                       gamma=None,
                                       phi=0.3),
            (q_02, q_03):
            PhasedFSimCharacterization(theta=0.4,
                                       zeta=0.5,
                                       chi=None,
                                       gamma=None,
                                       phi=0.6),
        },
        gate=gate,
        options=FloquetPhasedFSimCalibrationOptions(
            characterize_theta=True,
            characterize_zeta=True,
            characterize_chi=False,
            characterize_gamma=False,
            characterize_phi=True,
        ),
    )
Esempio n. 12
0
def prepare_floquet_characterization_for_operations(
    circuit: Union[Circuit, Iterable[Circuit]],
    options:
    FloquetPhasedFSimCalibrationOptions = WITHOUT_CHI_FLOQUET_PHASED_FSIM_CHARACTERIZATION,
    gates_translator: Callable[
        [Gate],
        Optional[PhaseCalibratedFSimGate]] = try_convert_sqrt_iswap_to_fsim,
    permit_mixed_moments: bool = False,
) -> List[FloquetPhasedFSimCalibrationRequest]:
    """Extracts a minimal set of Floquet characterization requests necessary to characterize all the
    operations within a circuit(s).

    This variant of prepare method works on two-qubit operations of the circuit. The method extracts
    all the operations and groups them in a way to minimize the number of characterizations
    requested, depending on the connectivity.

    Contrary to prepare_floquet_characterization_for_moments, this method ignores moments structure
    and is less accurate because certain errors caused by cross-talks are ignored.

    The major advantage of this method is that the number of generated characterization requests is
    bounded by four for grid-like devices, where for the
    prepare_floquet_characterization_for_moments the number of characterizations is bounded by
    number of moments in a circuit.

    The circuit can only be composed of single qubit operations, wait operations, measurement
    operations and operations supported by gates_translator.

    Args:
        circuit: Circuit or circuits to characterize. Only circuits with qubits of type GridQubit
            that can be covered by HALF_GRID_STAGGERED_PATTERN are supported
        options: Options that are applied to each characterized gate within a moment. Defaults
            to all_except_for_chi_options which is the broadest currently supported choice.
        gates_translator: Function that translates a gate to a supported FSimGate which will undergo
            characterization. Defaults to sqrt_iswap_gates_translator.
        permit_mixed_moments: Whether to allow a mix of two-qubit gates with other irrelevant
            single-qubit gates.

    Returns:
        List of PhasedFSimCalibrationRequest for each group of operations to characterize.

    Raises:
        IncompatibleMomentError when circuit contains a moment with operations other than the
        operations matched by gates_translator, or it mixes a single qubit and two qubit gates.
    """

    circuits = [circuit] if isinstance(circuit, Circuit) else circuit
    pairs, gate = _extract_all_pairs_to_characterize(circuits,
                                                     gates_translator,
                                                     permit_mixed_moments)

    if gate is None:
        return []

    characterizations = []
    for pattern in HALF_GRID_STAGGERED_PATTERN:
        pattern_pairs = [pair for pair in pairs if pair in pattern]
        if pattern_pairs:
            characterizations.append(
                FloquetPhasedFSimCalibrationRequest(pairs=tuple(
                    sorted(pattern_pairs)),
                                                    gate=gate,
                                                    options=options))

    if sum((len(characterization.pairs)
            for characterization in characterizations)) != len(pairs):
        raise ValueError(
            'Unable to cover all interactions with HALF_GRID_STAGGERED_PATTERN'
        )

    return characterizations