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
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)
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)