def can_add_operation_into_moment(self, operation: ops.Operation, moment: ops.Moment) -> bool:
        """
        Determines if it's possible to add an operation into a moment. An
        operation can be added if the moment with the operation added is valid

        Args:
            operation: The operation being added.
            moment: The moment being transformed.

        Returns:
            Whether or not the moment will validate after adding the operation.

        Raises:
            ValueError: If either of the given moment or operation is invalid
        """
        if not super().can_add_operation_into_moment(operation, moment):
            return False
        try:
            self.validate_moment(moment.with_operation(operation))
        except:
            return False
        return True
예제 #2
0
파일: workflow.py 프로젝트: zchen088/Cirq
def _make_zeta_chi_gamma_compensation(
    circuit_with_calibration: CircuitWithCalibration,
    characterizations: List[PhasedFSimCalibrationResult],
    gates_translator: Callable[[Gate], Optional[PhaseCalibratedFSimGate]],
    permit_mixed_moments: bool,
) -> CircuitWithCalibration:

    if permit_mixed_moments:
        raise NotImplementedError(
            'Mixed moments compensation ist supported yet')

    if len(circuit_with_calibration.circuit) != len(
            circuit_with_calibration.moment_to_calibration):
        raise ValueError('Moment allocations does not match circuit length')

    default_phases = PhasedFSimCharacterization(zeta=0.0, chi=0.0, gamma=0.0)

    compensated = Circuit()
    compensated_moment_to_calibration: List[Optional[int]] = []
    for moment, characterization_index in zip(
            circuit_with_calibration.circuit,
            circuit_with_calibration.moment_to_calibration):
        parameters = None
        if characterization_index is not None:
            parameters = characterizations[characterization_index]

        decompositions: List[Tuple[Tuple[Operation, ...], ...]] = []
        other: List[Operation] = []
        new_moment_moment_to_calibration: Optional[List[Optional[int]]] = None
        for op in moment:
            if not isinstance(op, GateOperation):
                raise IncompatibleMomentError(
                    'Moment contains operation different than GateOperation')

            if isinstance(op.gate, _CALIBRATION_IRRELEVANT_GATES):
                other.append(op)
                continue

            a, b = op.qubits
            translated = gates_translator(op.gate)
            if translated is None:
                raise IncompatibleMomentError(
                    f'Moment {moment} contains unsupported non-single qubit operation {op}'
                )

            if parameters is None:
                raise ValueError(
                    f'Missing characterization data for moment {moment}')

            pair_parameters = parameters.get_parameters(a, b)
            if pair_parameters is None:
                raise ValueError(
                    f'Missing characterization data for pair {(a, b)} in {parameters}'
                )
            pair_parameters = pair_parameters.merge_with(default_phases)

            corrections = FSimPhaseCorrections.from_characterization(
                (a, b),
                translated,
                pair_parameters,
                characterization_index,
            )
            decompositions.append(corrections.operations)

            if new_moment_moment_to_calibration is None:
                new_moment_moment_to_calibration = corrections.moment_to_calibration
            else:
                assert (
                    new_moment_moment_to_calibration ==
                    corrections.moment_to_calibration
                ), f'Inconsistent decompositions with a moment {moment}'

        if other and decompositions:
            raise IncompatibleMomentError(
                f'Moment {moment} contains mixed operations')
        elif other:
            compensated += Moment(other)
            compensated_moment_to_calibration.append(characterization_index)
        elif decompositions:
            for operations in itertools.zip_longest(*decompositions,
                                                    fillvalue=()):
                compensated += Moment(operations)
            assert new_moment_moment_to_calibration is not None  # Required for mypy
            compensated_moment_to_calibration += new_moment_moment_to_calibration

    return CircuitWithCalibration(compensated,
                                  compensated_moment_to_calibration)
예제 #3
0
def zeta_chi_gamma_calibration_for_moments(
    circuit_with_calibration: CircuitWithCalibration,
    characterizations: List[PhasedFSimCalibrationResult],
    gates_translator: Callable[[Gate], Optional[FSimGate]] = try_convert_sqrt_iswap_to_fsim,
) -> CircuitWithCalibration:
    """Compensates circuit against errors in zeta, chi and gamma angles.

    This method creates a new circuit with a single-qubit Z gates added in a such way so that
    zeta, chi and gamma angles discovered by characterizations are cancelled-out and set to 0.

    This function preserves a moment structure of the circuit. All single qubit gates appear on new
    moments in the final circuit.

    Args:
        circuit_with_calibration: A CircuitWithCalibration (likely returned from run_calibrations)
            whose mapping argument corresponds to the results in the characterizations argument.
        characterizations: List of characterization results (likely returned from run_calibrations).
            This should correspond to the circuit and mapping in the circuit_with_calibration
            argument.
        gates_translator: Function that translates a gate to a supported FSimGate which will undergo
            characterization. Defaults to sqrt_iswap_gates_translator.

    Returns:
        Calibrated circuit together with its calibration metadata in CircuitWithCalibration object.
        The calibrated circuit has single-qubit Z gates added which compensates for the true gates
        imperfections.
        The moment to calibration mapping is updated for the new circuit so that successive
        calibrations could be applied.
    """
    if len(circuit_with_calibration.circuit) != len(circuit_with_calibration.moment_to_calibration):
        raise ValueError('Moment allocations does not match circuit length')

    default_phases = PhasedFSimCharacterization(zeta=0.0, chi=0.0, gamma=0.0)

    compensated = Circuit()
    compensated_moment_to_calibration: List[Optional[int]] = []
    for moment, characterization_index in zip(
        circuit_with_calibration.circuit, circuit_with_calibration.moment_to_calibration
    ):
        parameters = None
        if characterization_index is not None:
            parameters = characterizations[characterization_index]

        decompositions: List[Tuple[Tuple[Operation, ...], ...]] = []
        other: List[Operation] = []
        new_moment_moment_to_calibration: Optional[List[Optional[int]]] = None
        for op in moment:
            if not isinstance(op, GateOperation):
                raise IncompatibleMomentError(
                    'Moment contains operation different than GateOperation'
                )

            if isinstance(op.gate, (MeasurementGate, SingleQubitGate)):
                other.append(op)
                continue

            a, b = op.qubits
            translated_gate = gates_translator(op.gate)
            if translated_gate is None:
                raise IncompatibleMomentError(
                    f'Moment {moment} contains unsupported non-single qubit operation {op}'
                )

            if parameters is None:
                raise ValueError(f'Missing characterization data for moment {moment}')

            pair_parameters = parameters.get_parameters(a, b)
            if pair_parameters is None:
                raise ValueError(f'Missing characterization data for pair {(a, b)} in {parameters}')
            pair_parameters = pair_parameters.merge_with(default_phases)

            corrections = FSimPhaseCorrections.from_characterization(
                (a, b), translated_gate, pair_parameters, characterization_index
            )
            decompositions.append(corrections.operations)

            if new_moment_moment_to_calibration is None:
                new_moment_moment_to_calibration = corrections.moment_to_calibration
            else:
                assert (
                    new_moment_moment_to_calibration == corrections.moment_to_calibration
                ), f'Inconsistent decompositions with a moment {moment}'

        if other and decompositions:
            raise IncompatibleMomentError(f'Moment {moment} contains mixed operations')
        elif other:
            compensated += Moment(other)
            compensated_moment_to_calibration.append(characterization_index)
        elif decompositions:
            for operations in zip_longest(*decompositions, fillvalue=()):
                compensated += Moment(operations)
            assert new_moment_moment_to_calibration is not None  # Required for mypy
            compensated_moment_to_calibration += new_moment_moment_to_calibration

    return CircuitWithCalibration(compensated, compensated_moment_to_calibration)