def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation) -> Optional[cirq.PointOptimizationSummary]: if isinstance( op.gate, (cirq.MeasurementGate, cirq.SingleQubitGate, cirq.WaitGate)): new_op = op else: if op.gate is None: raise IncompatibleMomentError( f'Operation {op} has a missing gate') translated = self._simulator.gates_translator(op.gate) if translated is None: raise IncompatibleMomentError( f'Moment contains non-single qubit operation ' f'{op} with unsupported gate') a, b = op.qubits new_op = self._simulator.create_gate_with_drift(a, b, translated).on( a, b) return cirq.PointOptimizationSummary(clear_span=1, clear_qubits=op.qubits, new_operations=new_op)
def map_func(op: cirq.Operation, _) -> cirq.Operation: if op.gate is None: raise IncompatibleMomentError(f'Operation {op} has a missing gate') if (isinstance(op.gate, (cirq.MeasurementGate, cirq.WaitGate)) or cirq.num_qubits(op.gate) == 1): return op translated = simulator.gates_translator(op.gate) if translated is None: raise IncompatibleMomentError( f'Moment contains non-single qubit operation ' f'{op} with unsupported gate') a, b = op.qubits return simulator.create_gate_with_drift(a, b, translated).on(a, b)
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 _list_moment_pairs_to_characterize( moment: Moment, gates_translator: Callable[[Gate], Optional[PhaseCalibratedFSimGate]], canonicalize_pairs: bool, permit_mixed_moments: bool, ) -> Optional[Tuple[List[Tuple[Qid, Qid]], Gate]]: """Helper function to describe a given moment in terms of a characterization request. Args: moment: Moment to characterize. gates_translator: Function that translates a gate to a supported FSimGate which will undergo characterization. canonicalize_pairs: Whether to sort each of the qubit pair so that the first qubit is always lower than the second. permit_mixed_moments: Whether to allow a mix of two-qubit gates with other irrelevant single-qubit gates. Returns: Tuple with list of pairs to characterize and gate that should be used for characterization, or None when no gate to characterize exists in a given 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. """ other_operation = False gate: Optional[FSimGate] = None pairs = [] 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_operation = True else: translated = gates_translator(op.gate) if translated is None: raise IncompatibleMomentError( f'Moment {moment} contains unsupported non-single qubit operation {op}' ) if gate is not None and gate != translated.engine_gate: raise IncompatibleMomentError( f'Moment {moment} contains operations resolved to two different gates {gate} ' f'and {translated.engine_gate}') else: gate = translated.engine_gate pair = cast( Tuple[Qid, Qid], tuple(sorted(op.qubits) if canonicalize_pairs else op.qubits)) pairs.append(pair) if gate is None: # Either empty, single-qubit or measurement moment. return None elif not permit_mixed_moments and other_operation: raise IncompatibleMomentError( f'Moment contains mixed two-qubit operations and either single-qubit measurement or ' f'wait operations.') return pairs, gate