Exemplo n.º 1
0
def replace_acquaintance_with_swap_network(
        circuit: 'cirq.Circuit',
        qubit_order: Sequence['cirq.Qid'],
        acquaintance_size: Optional[int] = 0,
        swap_gate: 'cirq.Gate' = ops.SWAP) -> bool:
    """
    Replace every moment containing acquaintance gates (after
    rectification) with a generalized swap network, with the partition
    given by the acquaintance gates in that moment (and singletons for the
    free qubits). Accounts for reversing effect of swap networks.

    Args:
        circuit: The acquaintance strategy.
        qubit_order: The qubits, in order, on which the replacing swap network
            gate acts on.
        acquaintance_size: The acquaintance size of the new swap network gate.
        swap_gate: The gate used to swap logical indices.

    Returns: Whether or not the overall effect of the inserted swap network
        gates is to reverse the order of the qubits, i.e. the parity of the
        number of swap network gates inserted.

    Raises:
        TypeError: circuit is not an acquaintance strategy.
    """

    if not is_acquaintance_strategy(circuit):
        raise TypeError('not is_acquaintance_strategy(circuit)')

    rectify_acquaintance_strategy(circuit)
    reflected = False
    reverse_map = {q: r for q, r in zip(qubit_order, reversed(qubit_order))}
    for moment_index, moment in enumerate(circuit):
        if reflected:
            moment = moment.transform_qubits(reverse_map.__getitem__)
        if all(
                ops.op_gate_isinstance(op, AcquaintanceOpportunityGate)
                for op in moment.operations):
            swap_network_gate = SwapNetworkGate.from_operations(
                qubit_order, moment.operations, acquaintance_size, swap_gate)
            swap_network_op = swap_network_gate(*qubit_order)
            moment = ops.Moment([swap_network_op])
            reflected = not reflected
        circuit._moments[moment_index] = moment
    return reflected
Exemplo n.º 2
0
 def keep(potential_op: ops.Operation) -> bool:
     # The order of this is optimized to call has_xxx methods first.
     return (protocols.has_unitary(potential_op)
             or protocols.has_mixture(potential_op)
             or protocols.is_measurement(potential_op)
             or ops.op_gate_isinstance(potential_op, ops.ResetChannel))
Exemplo n.º 3
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: Union[int, np.ndarray],
        perform_measurements: bool = True,
    ) -> Iterator:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state,
                                                    num_qubits,
                                                    qid_shape=qid_shape,
                                                    dtype=self._dtype)
        if len(circuit) == 0:
            yield SparseSimulatorStep(state, {}, qubit_map, self._dtype)

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate unknown operations that don't specify a "
                "_unitary_ method, a _decompose_ method, "
                "(_has_unitary_ + _apply_unitary_) methods,"
                "(_has_mixture_ + _mixture_) methods, or are measurements."
                ": {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            # The order of this is optimized to call has_xxx methods first.
            return (protocols.has_unitary(potential_op)
                    or protocols.has_mixture(potential_op)
                    or protocols.is_measurement(potential_op)
                    or ops.op_gate_isinstance(potential_op, ops.ResetChannel))

        data = _StateAndBuffer(state=np.reshape(state, qid_shape),
                               buffer=np.empty(qid_shape, dtype=self._dtype))
        for moment in circuit:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[int]]

            non_display_ops = (op for op in moment
                               if not isinstance(op, (
                                   ops.SamplesDisplay, ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay)))
            unitary_ops_and_measurements = protocols.decompose(
                non_display_ops, keep=keep, on_stuck_raise=on_stuck)

            for op in unitary_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if ops.op_gate_isinstance(op, ops.ResetChannel):
                    self._simulate_reset(op, data, indices)
                elif protocols.has_unitary(op):
                    self._simulate_unitary(op, data, indices)
                elif protocols.is_measurement(op):
                    # Do measurements second, since there may be mixtures that
                    # operate as measurements.
                    # TODO: support measurement outside the computational basis.
                    if perform_measurements:
                        self._simulate_measurement(op, data, indices,
                                                   measurements, num_qubits)
                elif protocols.has_mixture(op):
                    self._simulate_mixture(op, data, indices)

            yield SparseSimulatorStep(state_vector=data.state,
                                      measurements=measurements,
                                      qubit_map=qubit_map,
                                      dtype=self._dtype)