def __call__(self, strategy: 'cirq.Circuit'): if not is_acquaintance_strategy(strategy): raise TypeError('not is_acquaintance_strategy(strategy)') expose_acquaintance_gates(strategy) strategy.device = self.execution_strategy.device super().optimize_circuit(strategy) return self.mapping.copy()
def remove_redundant_acquaintance_opportunities( strategy: circuits.Circuit) -> None: """Removes redundant acquaintance opportunities.""" if not is_acquaintance_strategy(strategy): raise TypeError('not is_acquaintance_strategy(circuit)') qubits = tuple(strategy.all_qubits()) mapping = {q: i for i, q in enumerate(qubits)} expose_acquaintance_gates(strategy) annotated_strategy = strategy.copy() LogicalAnnotator(mapping)(annotated_strategy) new_moments = [] # type: List[ops.Moment] acquaintance_opps = set() # type: Set[FrozenSet[int]] for moment in annotated_strategy: new_moment = [] # type: List[ops.Operation] for op in moment: if isinstance(op, AcquaintanceOperation): opp = frozenset(cast(Sequence[int], op.logical_indices)) if opp not in acquaintance_opps: acquaintance_opps.add(opp) new_moment.append(acquaint(*op.qubits)) else: new_moment.append(op) new_moments.append(ops.Moment(new_moment)) strategy._moments = new_moments
def complete_acquaintance_strategy(qubit_order: Sequence[ops.Qid], acquaintance_size: int=0, ) -> circuits.Circuit: """ Returns an acquaintance strategy capable of executing a gate corresponding to any set of at most acquaintance_size qubits. Args: qubit_order: The qubits on which the strategy should be defined. acquaintance_size: The maximum number of qubits to be acted on by an operation. Returns: An circuit capable of implementing any set of k-local operation. """ if acquaintance_size < 0: raise ValueError('acquaintance_size must be non-negative.') elif acquaintance_size == 0: return circuits.Circuit(device=UnconstrainedAcquaintanceDevice) if acquaintance_size > len(qubit_order): return circuits.Circuit(device=UnconstrainedAcquaintanceDevice) if acquaintance_size == len(qubit_order): return circuits.Circuit.from_ops( acquaint(*qubit_order), device=UnconstrainedAcquaintanceDevice) strategy = circuits.Circuit.from_ops( (acquaint(q) for q in qubit_order), device=UnconstrainedAcquaintanceDevice) for size_to_acquaint in range(2, acquaintance_size + 1): expose_acquaintance_gates(strategy) replace_acquaintance_with_swap_network( strategy, qubit_order, size_to_acquaint) return strategy
def remove_redundant_acquaintance_opportunities(strategy: 'cirq.Circuit') -> int: """Removes redundant acquaintance opportunities.""" qubits = sorted(strategy.all_qubits()) mapping = {q: i for i, q in enumerate(qubits)} expose_acquaintance_gates(strategy) annotated_strategy = strategy.copy() LogicalAnnotator(mapping)(annotated_strategy) new_moments: List['cirq.Moment'] = [] acquaintance_opps: Set[FrozenSet[int]] = set() n_removed = 0 for moment in annotated_strategy: new_moment: List['cirq.Operation'] = [] for op in moment: if isinstance(op, AcquaintanceOperation): opp = frozenset(cast(Sequence[int], op.logical_indices)) if opp not in acquaintance_opps: acquaintance_opps.add(opp) new_moment.append(acquaint(*op.qubits)) else: n_removed += 1 else: new_moment.append(op) new_moments.append(ops.Moment(new_moment)) strategy._moments = new_moments return n_removed
def complete_acquaintance_strategy( qubit_order: Sequence['cirq.Qid'], acquaintance_size: int = 0, swap_gate: 'cirq.Gate' = ops.SWAP) -> 'cirq.Circuit': """Returns an acquaintance strategy with can handle the given number of qubits. Args: qubit_order: The qubits on which the strategy should be defined. acquaintance_size: The maximum number of qubits to be acted on by an operation. swap_gate: The gate used to swap logical indices. Returns: A circuit capable of implementing any set of k-local operations. Raises: ValueError: If `acquaintance_size` is negative. """ if acquaintance_size < 0: raise ValueError('acquaintance_size must be non-negative.') if acquaintance_size == 0: return circuits.Circuit() if acquaintance_size > len(qubit_order): return circuits.Circuit() if acquaintance_size == len(qubit_order): return circuits.Circuit(acquaint(*qubit_order)) strategy = circuits.Circuit((acquaint(q) for q in qubit_order)) for size_to_acquaint in range(2, acquaintance_size + 1): expose_acquaintance_gates(strategy) replace_acquaintance_with_swap_network(strategy, qubit_order, size_to_acquaint, swap_gate) return strategy
def get_acquaintance_dag(strategy: 'cirq.Circuit', initial_mapping: LogicalMapping): strategy = strategy.copy() expose_acquaintance_gates(strategy) LogicalAnnotator(initial_mapping)(strategy) acquaintance_ops = (op for moment in strategy._moments for op in moment.operations if isinstance(op, AcquaintanceOperation)) return circuits.CircuitDag.from_ops(acquaintance_ops)
def quartic_paired_acquaintance_strategy( qubit_pairs: Iterable[Tuple['cirq.Qid', ops.Qid]] ) -> Tuple['cirq.Circuit', Sequence['cirq.Qid']]: """Acquaintance strategy for pairs of pairs. Implements UpCCGSD ansatz from arXiv:1810.02327. """ qubit_pairs = tuple( cast(Tuple['cirq.Qid', ops.Qid], tuple(qubit_pair)) for qubit_pair in qubit_pairs ) qubits = qubit_pairs_to_qubit_order(qubit_pairs) n_qubits = len(qubits) swap_network = SwapNetworkGate((1,) * n_qubits, 2)(*qubits) strategy = circuits.Circuit(swap_network, device=UnconstrainedAcquaintanceDevice) expose_acquaintance_gates(strategy) for i in reversed(range(0, n_qubits, 2)): moment = ops.Moment([acquaint(*qubits[j : j + 4]) for j in range(i % 4, n_qubits - 3, 4)]) strategy.insert(2 * i, moment) return strategy, qubits
def __call__(self, strategy: 'cirq.Circuit'): expose_acquaintance_gates(strategy) super().optimize_circuit(strategy) return self.mapping.copy()