Ejemplo n.º 1
0
def test_swap_permutation_gate():
    no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate ==
                            cirq.SWAP)
    a, b = cirq.NamedQubit('a'), cirq.NamedQubit('b')
    expander = cirq.ExpandComposite(no_decomp=no_decomp)
    circuit = cirq.Circuit.from_ops(SwapPermutationGate()(a, b))
    expander(circuit)
    assert tuple(circuit.all_operations()) == (cirq.SWAP(a, b), )

    no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate ==
                            cirq.CZ)
    expander = cirq.ExpandComposite(no_decomp=no_decomp)
    circuit = cirq.Circuit.from_ops(SwapPermutationGate(cirq.CZ)(a, b))
    expander(circuit)
    assert tuple(circuit.all_operations()) == (cirq.CZ(a, b), )
Ejemplo n.º 2
0
def test_update_mapping():
    gate = SwapPermutationGate()
    a, b, c = (cirq.NamedQubit(s) for s in 'abc')
    mapping = {s: i for i, s in enumerate((a, b, c))}
    ops = [gate(a, b), gate(b, c)]
    update_mapping(mapping, ops)
    assert mapping == {a: 1, b: 2, c: 0}
Ejemplo n.º 3
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])
Ejemplo n.º 4
0
def test_validate_permutation_errors():
    validate_permutation = PermutationGate.validate_permutation
    validate_permutation({})

    with pytest.raises(IndexError,
                       message='key and value sets must be the same.'):
        validate_permutation({0: 2, 1: 3})

    with pytest.raises(
            IndexError,
            message='keys of the permutation must be non-negative.'):
        validate_permutation({-1: 0, 0: -1})

    with pytest.raises(IndexError, message='key is out of bounds.'):
        validate_permutation({0: 3, 3: 0}, 2)

    gate = SwapPermutationGate()
    args = cirq.TextDiagramInfoArgs.UNINFORMED_DEFAULT
    assert gate.text_diagram_info(args) == NotImplemented
Ejemplo n.º 5
0
 def _decompose_(self, qubits: Sequence[QubitId]) -> OP_TREE:
     n = len(qubits)
     left_shift = self.shift % n
     right_shift = n - left_shift
     mins = chain(range(left_shift - 1, 0, -1), range(right_shift))
     maxs = chain(range(left_shift, n), range(n - 1, right_shift, -1))
     swap_gate = SwapPermutationGate(self.swap_gate)
     for i, j in zip(mins, maxs):
         for k in range(i, j, 2):
             yield swap_gate(*qubits[k:k + 2])
Ejemplo n.º 6
0
def test_diagram():
    gate = SwapPermutationGate()
    a, b = cirq.NamedQubit('a'), cirq.NamedQubit('b')
    circuit = cirq.Circuit.from_ops([gate(a, b)])
    actual_text_diagram = circuit.to_text_diagram()
    expected_text_diagram = """
a: ───0↦1───
      │
b: ───1↦0───
    """.strip()
    assert actual_text_diagram == expected_text_diagram
Ejemplo n.º 7
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])
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
def test_validate_permutation_errors():
    validate_permutation = PermutationGate.validate_permutation
    validate_permutation({})

    with pytest.raises(IndexError,
            message='key and value sets must be the same.'):
        validate_permutation({0: 2, 1: 3})

    with pytest.raises(IndexError,
            message='keys of the permutation must be non-negative.'):
        validate_permutation({-1: 0, 0: -1})

    with pytest.raises(IndexError, message='key is out of bounds.'):
        validate_permutation({0: 3, 3: 0}, 2)

    gate = SwapPermutationGate()
    assert cirq.circuit_diagram_info(gate, default=None) is None
Ejemplo n.º 10
0
def acquaint_insides(
    swap_gate: 'cirq.Gate',
    acquaintance_gate: 'cirq.Operation',
    qubits: Sequence['cirq.Qid'],
    before: bool,
    layers: Layers,
    mapping: Dict[ops.Qid, int],
) -> None:
    """Acquaints each of the qubits with another set specified by an
    acquaintance gate.

    Args:
        qubits: The list of qubits of which half are individually acquainted
            with another list of qubits.
        layers: The layers to put gates into.
        acquaintance_gate: The acquaintance gate that acquaints the end qubit
            with another list of qubits.
        before: Whether the acquainting is done before the shift.
        swap_gate: The gate used to swap logical indices.
        mapping: The mapping from qubits to logical indices. Used to keep track
            of the effect of inside-acquainting swaps.
    """

    max_reach = _get_max_reach(len(qubits), round_up=before)
    reaches = itertools.chain(range(1, max_reach + 1),
                              range(max_reach, -1, -1))
    offsets = (0, 1) * max_reach
    swap_gate = SwapPermutationGate(swap_gate)
    ops = []
    for offset, reach in zip(offsets, reaches):
        if offset == before:
            ops.append(acquaintance_gate)
        for dr in range(offset, reach, 2):
            ops.append(swap_gate(*qubits[dr:dr + 2]))
    intrastitial_layer = getattr(layers, 'pre' if before else 'post')
    intrastitial_layer += ops

    # add interstitial gate
    interstitial_layer = getattr(layers, ('prior' if before else 'posterior') +
                                 '_interstitial')
    interstitial_layer.append(acquaintance_gate)

    # update mapping
    reached_qubits = qubits[:max_reach + 1]
    positions = list(mapping[q] for q in reached_qubits)
    mapping.update(zip(reached_qubits, reversed(positions)))
Ejemplo n.º 11
0
def test_rectification():
    qubits = cirq.LineQubit.range(4)

    with pytest.raises(TypeError):
        rectify_acquaintance_strategy(cirq.Circuit())

    perm_gate = SwapPermutationGate()
    operations = [
        perm_gate(*qubits[:2]),
        ACQUAINT(*qubits[2:]),
        ACQUAINT(*qubits[:2]),
        perm_gate(*qubits[2:])
    ]

    strategy = cirq.Circuit.from_ops(operations,
                                     device=UnconstrainedAcquaintanceDevice)
    rectify_acquaintance_strategy(strategy)
    actual_text_diagram = strategy.to_text_diagram().strip()
    expected_text_diagram = """
0: ───────0↦1─────────█───
          │           │
1: ───────1↦0─────────█───

2: ───█─────────0↦1───────
      │         │
3: ───█─────────1↦0───────
    """.strip()
    assert actual_text_diagram == expected_text_diagram

    strategy = cirq.Circuit.from_ops(operations,
                                     device=UnconstrainedAcquaintanceDevice)
    rectify_acquaintance_strategy(strategy, False)
    actual_text_diagram = strategy.to_text_diagram()
    expected_text_diagram = """
0: ───0↦1───────█─────────
      │         │
1: ───1↦0───────█─────────

2: ─────────█───────0↦1───
            │       │
3: ─────────█───────1↦0───
    """.strip()
    assert actual_text_diagram == expected_text_diagram