예제 #1
0
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
예제 #2
0
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
예제 #3
0
 def decompose_complete(self, qubits: Sequence[ops.Qid]) -> ops.OP_TREE:
     swap_gate = SwapPermutationGate(self.swap_gate)
     if self.part_size == 1:
         yield acquaint(*qubits)
         return
     for k in range(-self.part_size + 1, self.part_size - 1):
         for x in range(abs(k), 2 * self.part_size - abs(k), 2):
             yield acquaint(*qubits[x:x + 2])
             yield swap_gate(*qubits[x:x + 2])
     yield acquaint(qubits[self.part_size - 1], qubits[self.part_size])
     for k in reversed(range(-self.part_size + 1, self.part_size - 1)):
         for x in range(abs(k), 2 * self.part_size - abs(k), 2):
             yield acquaint(*qubits[x:x + 2])
             yield swap_gate(*qubits[x:x + 2])
예제 #4
0
    def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
        part_lens = list(
            itertools.chain(*(self.part_lens[side]
                              for side in ('left', 'right'))))

        n_qubits = 0
        parts = []
        for part_len in part_lens:
            parts.append(list(qubits[n_qubits:n_qubits + part_len]))
            n_qubits += part_len

        n_parts = len(part_lens)
        n_left_parts = len(self.part_lens['left'])
        n_right_parts = n_parts - n_left_parts

        mins = itertools.chain(range(n_left_parts - 1, 0, -1),
                               range(n_right_parts))
        maxs = itertools.chain(range(n_left_parts, n_parts),
                               range(n_parts - 1, n_right_parts, -1))
        SHIFT = functools.partial(CircularShiftGate, swap_gate=self.swap_gate)

        for i, j in zip(mins, maxs):
            for k in range(i, j, 2):
                left_part, right_part = parts[k:k + 2]
                parts_qubits = left_part + right_part
                yield acquaint(*parts_qubits)
                yield SHIFT(len(parts_qubits), len(left_part))(*parts_qubits)
                parts[k] = parts_qubits[:len(right_part)]
                parts[k + 1] = parts_qubits[len(right_part):]
예제 #5
0
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
예제 #6
0
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
예제 #7
0
 def decompose_matching(self, qubits: Sequence[ops.Qid]) -> ops.OP_TREE:
     swap_gate = SwapPermutationGate(self.swap_gate)
     for k in range(-self.part_size + 1, self.part_size):
         for x in range(abs(k), 2 * self.part_size - abs(k), 2):
             if (x + 1) % self.part_size:
                 yield swap_gate(*qubits[x:x + 2])
             else:
                 yield acquaint(*qubits[x:x + 2])
예제 #8
0
파일: cubic.py 프로젝트: PWJ1900/Rlearncirq
def cubic_acquaintance_strategy(
        qubits: Iterable['cirq.Qid'],
        swap_gate: 'cirq.Gate' = ops.SWAP) -> 'cirq.Circuit':
    """Acquaints every triple of qubits.

    Exploits the fact that in a simple linear swap network every pair of
    logical qubits that starts at distance two remains so (except temporarily
    near the edge), and that every third one `goes through` the pair at some
    point in the network. The strategy then iterates through a series of
    mappings in which qubits i and i + k are placed at distance two, for k = 1
    through n / 2. Linear swap networks are used in between to effect the
    permutation.
    """

    qubits = tuple(qubits)
    n_qubits = len(qubits)

    swap_gate = SwapPermutationGate(swap_gate)

    moments = []
    index_order = tuple(range(n_qubits))
    max_separation = max(((n_qubits - 1) // 2) + 1, 2)
    for separation in range(1, max_separation):
        stepped_indices_concatenated = tuple(
            itertools.chain(*(range(offset, n_qubits, separation)
                              for offset in range(separation))))
        new_index_order = skip_and_wrap_around(stepped_indices_concatenated)
        permutation = {
            i: new_index_order.index(j)
            for i, j in enumerate(index_order)
        }
        permutation_gate = LinearPermutationGate(n_qubits, permutation,
                                                 swap_gate)
        moments.append(ops.Moment([permutation_gate(*qubits)]))
        for i in range(n_qubits + 1):
            for offset in range(3):
                moment = ops.Moment(
                    acquaint(*qubits[j:j + 3])
                    for j in range(offset, n_qubits - 2, 3))
                moments.append(moment)
            if i < n_qubits:
                moment = ops.Moment(
                    swap_gate(*qubits[j:j + 2])
                    for j in range(i % 2, n_qubits - 1, 2))
                moments.append(moment)
        index_order = new_index_order[::-1]
    return circuits.Circuit(moments, device=UnconstrainedAcquaintanceDevice)
예제 #9
0
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