def convert(self, op: ops.Operation) -> ops.OP_TREE:
     return protocols.decompose(
         op,
         intercepting_decomposer=self._convert_one,
         keep=self._keep,
         on_stuck_raise=(None if self.ignore_failures else self._on_stuck_raise),
     )
Exemplo n.º 2
0
    def convert(self, op: 'cirq.Operation') -> List['cirq.Operation']:

        a = protocols.decompose(op,
                                keep=is_sqrt_iswap_compatible,
                                intercepting_decomposer=self._convert_one,
                                on_stuck_raise=(None if self.ignore_failures
                                                else self._on_stuck_raise))
        return a
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[simulator.StepResult]:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state, num_qubits,
                                                    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, or "
                "(_has_unitary_ + _apply_unitary_) methods"
                ": {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_unitary(potential_op)
                    or ops.MeasurementGate.is_measurement(potential_op))

        state = np.reshape(state, (2, ) * num_qubits)
        buffer = np.empty((2, ) * num_qubits, dtype=self._dtype)
        for moment in circuit:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            unitary_ops_and_measurements = protocols.decompose(
                moment.operations, 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.MeasurementGate.is_measurement(op):
                    gate = cast(ops.MeasurementGate,
                                cast(ops.GateOperation, op).gate)
                    if perform_measurements:
                        invert_mask = gate.invert_mask or num_qubits * (
                            False, )
                        # Measure updates inline.
                        bits, _ = wave_function.measure_state_vector(
                            state, indices, state)
                        corrected = [
                            bit ^ mask for bit, mask in zip(bits, invert_mask)
                        ]
                        measurements[cast(str, gate.key)].extend(corrected)
                else:
                    result = protocols.apply_unitary(
                        op,
                        args=protocols.ApplyUnitaryArgs(
                            state, buffer, indices))
                    if result is buffer:
                        buffer = state
                    state = result
            yield SimulatorStep(state, measurements, qubit_map, self._dtype)
Exemplo n.º 4
0
    def decompose_operation(self,
                            operation: 'cirq.Operation') -> 'cirq.OP_TREE':
        if self.is_native_or_final(operation):
            return operation

        return protocols.decompose(
            operation,
            intercepting_decomposer=self.operation_decomposer,
            keep=self.is_native_or_final,
            on_stuck_raise=None)
Exemplo n.º 5
0
    def optimization_at(self, circuit, index, op):
        decomposition = protocols.decompose(op, keep=self.no_decomp,
                                            on_stuck_raise=None)
        if decomposition is op:
            return None

        return PointOptimizationSummary(
            clear_span=1,
            clear_qubits=op.qubits,
            new_operations=decomposition)
Exemplo n.º 6
0
    def optimization_at(
            self, circuit: 'cirq.Circuit', index: int,
            op: 'cirq.Operation') -> Optional['cirq.PointOptimizationSummary']:
        decomposition = protocols.decompose(op,
                                            keep=self.no_decomp,
                                            on_stuck_raise=None)
        if decomposition == [op]:
            return None

        return PointOptimizationSummary(clear_span=1,
                                        clear_qubits=op.qubits,
                                        new_operations=decomposition)
Exemplo n.º 7
0
def assert_decompose_ends_at_default_gateset(val: Any):
    """Asserts that cirq.decompose(val) ends at default cirq gateset or a known gate."""
    if _known_gate_with_no_decomposition(val):
        return  # coverage: ignore
    args = () if isinstance(val, ops.Operation) else (tuple(
        devices.LineQid.for_gate(val)), )
    dec_once = protocols.decompose_once(val, [val(*args[0]) if args else val],
                                        *args)
    for op in [*ops.flatten_to_ops(protocols.decompose(d) for d in dec_once)]:
        assert _known_gate_with_no_decomposition(op.gate) or (
            op in protocols.decompose_protocol.DECOMPOSE_TARGET_GATESET
        ), f'{val} decomposed to {op}, which is not part of default cirq target gateset.'
Exemplo n.º 8
0
    def convert(self, op: ops.Operation) -> List[ops.Operation]:
        def on_stuck_raise(bad):
            return TypeError("Don't know how to work with {!r}. "
                             "It isn't a native xmon operation, "
                             "a 1 or 2 qubit gate with a known unitary, "
                             "or composite.".format(bad))

        return protocols.decompose(
            op,
            keep=xmon_gates.is_native_xmon_op,
            intercepting_decomposer=self._convert_one,
            on_stuck_raise=None if self.ignore_failures else on_stuck_raise)
Exemplo n.º 9
0
    def _write_operations(
        self,
        op_tree: 'cirq.OP_TREE',
        output: Callable[[str], None],
        output_line_gap: Callable[[int], None],
    ) -> None:
        def keep(op: 'cirq.Operation') -> bool:
            return protocols.qasm(op, args=self.args, default=None) is not None

        def fallback(op):
            if len(op.qubits) not in [1, 2]:
                return NotImplemented

            mat = protocols.unitary(op, None)
            if mat is None:
                return NotImplemented

            if len(op.qubits) == 1:
                return QasmUGate.from_matrix(mat).on(*op.qubits)
            return QasmTwoQubitGate.from_matrix(mat).on(*op.qubits)

        def on_stuck(bad_op):
            return ValueError(
                'Cannot output operation as QASM: {!r}'.format(bad_op))

        for main_op in ops.flatten_op_tree(op_tree):
            decomposed = protocols.decompose(main_op,
                                             keep=keep,
                                             fallback_decomposer=fallback,
                                             on_stuck_raise=on_stuck)

            qasms = [protocols.qasm(op, args=self.args) for op in decomposed]

            should_annotate = decomposed != [main_op
                                             ] or qasms[0].count('\n') > 1
            if should_annotate:
                output_line_gap(1)
                if isinstance(main_op, ops.GateOperation):
                    x = str(main_op.gate).replace('\n', '\n //')
                    output('// Gate: {!s}\n'.format(x))
                else:
                    x = str(main_op).replace('\n', '\n //')
                    output('// Operation: {!s}\n'.format(x))

            for qasm in qasms:
                output(qasm)

            if should_annotate:
                output_line_gap(1)
Exemplo n.º 10
0
    def __init__(self,
                 circuit: circuits.Circuit,
                 initial_state: Union[int, np.ndarray]):
        self.grouping = _QubitGrouping(circuit)
        self.circuit = circuits.Circuit(
            protocols.decompose(
                circuit,
                intercepting_decomposer=self.grouping.intercept_decompose_func,
                keep=self.grouping.decompose_keep_func))
        self.layers = _circuit_as_layers(self.circuit, self.grouping)
        self.feed_dict = {}  # type: Dict[tf.Tensor, Any]

        # Capture initial state.
        self._initial_state_func = self._pick_initial_state_func(initial_state)

        # Store list of CZ indices for each layer.
        max_czs = 0
        if self.layers:
            max_czs = max(len(e.cz_indices) for e in self.layers)
        max_czs = max(1, max_czs)
        self.secret_cz_indices = tf.placeholder(
            name='cz_indices',
            dtype=tf.int32,
            shape=(len(self.layers), max_czs, 2))
        padded_cz_indices = np.array(
            [
                e.cz_indices + [(-1, -1)] * (max_czs - len(e.cz_indices))
                for e in self.layers
            ],
            dtype=np.int32
        ).reshape((len(self.layers), max_czs, 2))
        self.feed_dict[self.secret_cz_indices] = padded_cz_indices

        # Store matrices for each qubit group at each layer.
        self.secret_group_matrices = [
            tf.placeholder(
                name='group_matrices_{}'.format(i),
                dtype=tf.complex64,
                shape=(len(self.layers),
                       1 << len(g),
                       1 << len(g)))
            for i, g in enumerate(self.grouping.groups)
        ]
        for i in range(len(self.grouping.groups)):
            j = len(self.grouping.groups) - i - 1
            self.feed_dict[self.secret_group_matrices[j]] = np.array([
                e.group_matrices[j]
                for e in self.layers
            ])
    def optimization_at(
            self, circuit: circuits.Circuit, index: int,
            op: ops.Operation) -> Optional[circuits.PointOptimizationSummary]:
        converted = protocols.decompose(
            op,
            intercepting_decomposer=self._decompose_two_qubit_unitaries,
            keep=self._keep,
            on_stuck_raise=(None
                            if self.ignore_failures else self._on_stuck_raise))
        if converted == [op]:
            return None

        return circuits.PointOptimizationSummary(clear_span=1,
                                                 new_operations=converted,
                                                 clear_qubits=op.qubits)
Exemplo n.º 12
0
    def _write_quil(self, output_func: Callable[[str], None]) -> None:
        output_func('# Created using Cirq.\n\n')
        if len(self.measurements) > 0:
            measurements_declared: Set[str] = set()
            for m in self.measurements:
                key = protocols.measurement_key(m)
                if key in measurements_declared:
                    continue
                measurements_declared.add(key)
                output_func(
                    f'DECLARE {self.measurement_id_map[key]} BIT[{len(m.qubits)}]\n'
                )
            output_func('\n')

        def keep(op: 'cirq.Operation') -> bool:
            return protocols.quil(op, formatter=self.formatter) is not None

        def fallback(op):
            if len(op.qubits) not in [1, 2]:
                return NotImplemented

            mat = protocols.unitary(op, None)
            if mat is None:
                return NotImplemented

            # Following code is a safety measure
            # Could not find a gate that doesn't decompose into a gate
            # with a _quil_ implementation
            # coverage: ignore
            if len(op.qubits) == 1:
                return QuilOneQubitGate(mat).on(*op.qubits)
            return QuilTwoQubitGate(mat).on(*op.qubits)

        def on_stuck(bad_op):
            return ValueError(f'Cannot output operation as QUIL: {bad_op!r}')

        for main_op in self.operations:
            decomposed = protocols.decompose(main_op,
                                             keep=keep,
                                             fallback_decomposer=fallback,
                                             on_stuck_raise=on_stuck)

            for decomposed_op in decomposed:
                output_func(
                    protocols.quil(decomposed_op, formatter=self.formatter))
Exemplo n.º 13
0
 def decompose_operation(self, operation: 'ops.Operation') -> 'ops.OP_TREE':
     if isinstance(operation.gate, self.auto_decompose_gates):
         return protocols.decompose(operation)
     return operation
Exemplo n.º 14
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)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        matrix = density_matrix_utils.to_valid_density_matrix(
            initial_state, num_qubits, self._dtype)
        if len(circuit) == 0:
            yield DensityMatrixStepResult(matrix, {}, qubit_map, self._dtype)
        matrix = np.reshape(matrix, (2,) * num_qubits * 2)

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate operations that don't implement "
                "SupportsUnitary, SupportsApplyUnitary, SupportsMixture, "
                "SupportsChannel or is a measurement: {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_channel(potential_op)
                    or (ops.op_gate_of_type(potential_op,
                                            ops.MeasurementGate) is not None)
                    or isinstance(potential_op,
                                  (ops.SamplesDisplay,
                                   ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay))
                    )

        matrix = np.reshape(matrix, (2,) * num_qubits * 2)
        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))

        for moment in noisy_moments:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            channel_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in channel_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if isinstance(op,
                              (ops.SamplesDisplay,
                                  ops.WaveFunctionDisplay,
                                  ops.DensityMatrixDisplay)):
                    continue
                # TODO: support more general measurements.
                meas = ops.op_gate_of_type(op, ops.MeasurementGate)
                if meas:
                    if perform_measurements:
                        invert_mask = meas.invert_mask or num_qubits * (False,)
                        # Measure updates inline.
                        bits, _ = density_matrix_utils.measure_density_matrix(
                            matrix, indices, matrix)
                        corrected = [bit ^ mask for bit, mask in
                                     zip(bits, invert_mask)]
                        key = protocols.measurement_key(meas)
                        measurements[key].extend(corrected)
                else:
                    # TODO: Use apply_channel similar to apply_unitary.
                    gate = cast(ops.GateOperation, op).gate
                    channel = protocols.channel(gate)
                    sum_buffer = np.zeros((2,) * 2 * num_qubits,
                                          dtype=self._dtype)
                    buffer = np.empty((2,) * 2 * num_qubits, dtype=self._dtype)
                    out = np.empty((2,) * 2 * num_qubits, dtype=self._dtype)
                    for krauss in channel:
                        krauss_tensor = np.reshape(krauss.astype(self._dtype),
                                                   (2,) * gate.num_qubits() * 2)
                        result = linalg.targeted_conjugate_about(krauss_tensor,
                                                                 matrix,
                                                                 indices,
                                                                 buffer=buffer,
                                                                 out=out)
                        sum_buffer += result
                    np.copyto(dst=matrix, src=sum_buffer)
            yield DensityMatrixStepResult(
                    density_matrix=matrix,
                    measurements=measurements,
                    qubit_map=qubit_map,
                    dtype=self._dtype)
Exemplo n.º 15
0
 def _decompose_(self) -> 'cirq.OP_TREE':
     return protocols.decompose(self.sub_operation)
    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)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        matrix = density_matrix_utils.to_valid_density_matrix(
            initial_state, num_qubits, self._dtype)
        if len(circuit) == 0:
            yield DensityMatrixStepResult(matrix, {}, qubit_map, self._dtype)

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate operations that don't implement "
                "SupportsUnitary, SupportsApplyUnitary, SupportsMixture, "
                "SupportsChannel or is a measurement: {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_channel(potential_op)
                    or (ops.op_gate_of_type(potential_op, ops.MeasurementGate)
                        is not None)
                    or isinstance(potential_op,
                                  (ops.SamplesDisplay, ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay)))

        matrix = np.reshape(matrix, (2**num_qubits, 2**num_qubits))
        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))

        state = qulacs.DensityMatrix(num_qubits)
        state.load(matrix)

        for moment in noisy_moments:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            channel_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in channel_ops_and_measurements:
                #indices = [qubit_map[qubit] for qubit in op.qubits]
                indices = [
                    num_qubits - 1 - qubit_map[qubit] for qubit in op.qubits
                ]
                indices.reverse()
                if isinstance(op, (ops.SamplesDisplay, ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay)):
                    continue
                # TODO: support more general measurements.

                meas = ops.op_gate_of_type(op, ops.MeasurementGate)
                if meas:
                    # Not implemented
                    raise NotImplementedError(
                        "Measurement is not supported in qulacs simulator")

                else:
                    # TODO: Use apply_channel similar to apply_unitary.
                    gate = cast(ops.GateOperation, op).gate
                    channel = protocols.channel(gate)

                    qulacs_gates = []
                    for krauss in channel:
                        krauss = krauss.astype(np.complex128)
                        qulacs_gate = qulacs.gate.DenseMatrix(indices, krauss)
                        qulacs_gates.append(qulacs_gate)
                    qulacs_cptp_map = qulacs.gate.CPTP(qulacs_gates)
                    qulacs_cptp_map.update_quantum_state(state)

            matrix = state.get_matrix()
            matrix = np.reshape(matrix, (2, ) * num_qubits * 2)

            yield DensityMatrixStepResult(density_matrix=matrix,
                                          measurements=measurements,
                                          qubit_map=qubit_map,
                                          dtype=self._dtype)
Exemplo n.º 17
0
    def _base_iterator(
            self,
            circuit: circuits.Circuit,
            qubit_order: ops.QubitOrderOrList,
            initial_state: 'cirq.STATE_VECTOR_LIKE',
            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 = qis.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
                    isinstance(potential_op.gate, 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]]

            unitary_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in unitary_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if isinstance(op.gate, 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.
                    # Github issue:
                    # https://github.com/quantumlib/Cirq/issues/1357
                    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)
Exemplo n.º 18
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)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state, num_qubits,
                                                    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, or "
                "(_has_unitary_ + _apply_unitary_) methods"
                ": {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_unitary(potential_op)
                    or protocols.is_measurement(potential_op))

        state = np.reshape(state, (2, ) * num_qubits)
        buffer = np.empty((2, ) * num_qubits, dtype=self._dtype)
        for moment in circuit:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            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]
                # TODO: Support measurements outside of computational basis.
                # TODO: Support mixtures.
                meas = ops.op_gate_of_type(op, ops.MeasurementGate)
                if meas:
                    if perform_measurements:
                        invert_mask = meas.invert_mask or num_qubits * (
                            False, )
                        # Measure updates inline.
                        bits, _ = wave_function.measure_state_vector(
                            state, indices, state)
                        corrected = [
                            bit ^ mask for bit, mask in zip(bits, invert_mask)
                        ]
                        key = protocols.measurement_key(meas)
                        measurements[key].extend(corrected)
                else:
                    result = protocols.apply_unitary(
                        op,
                        args=protocols.ApplyUnitaryArgs(
                            state, buffer, indices))
                    if result is buffer:
                        buffer = state
                    state = result
            yield SparseSimulatorStep(state_vector=state,
                                      measurements=measurements,
                                      qubit_map=qubit_map,
                                      dtype=self._dtype)
Exemplo n.º 19
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: Union[np.ndarray, 'cirq.STATE_VECTOR_LIKE'],
        all_measurements_are_terminal=False,
        is_raw_state=False,
    ) -> Iterator:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        initial_matrix = (qis.to_valid_density_matrix(initial_state,
                                                      len(qid_shape),
                                                      qid_shape=qid_shape,
                                                      dtype=self._dtype)
                          if not is_raw_state else initial_state)
        if np.may_share_memory(initial_matrix, initial_state):
            initial_matrix = initial_matrix.copy()
        measured = collections.defaultdict(
            bool)  # type: Dict[Tuple[cirq.Qid, ...], bool]
        if len(circuit) == 0:
            yield DensityMatrixStepResult(initial_matrix, {}, qubit_map,
                                          self._dtype)
            return

        state = _StateAndBuffers(
            len(qid_shape),
            initial_matrix.reshape(qid_shape *
                                   2) if not is_raw_state else initial_matrix,
        )

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate operations that don't implement "
                "SupportsUnitary, SupportsConsistentApplyUnitary, "
                "SupportsMixture, SupportsChannel or is a measurement: {!r}".
                format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return protocols.has_channel(
                potential_op, allow_decompose=False) or isinstance(
                    potential_op.gate, ops.MeasurementGate)

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))

        for moment in noisy_moments:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[int]]

            channel_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in channel_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                # TODO: support more general measurements.
                # Github issue: https://github.com/quantumlib/Cirq/issues/1357
                if all_measurements_are_terminal and measured[op.qubits]:
                    continue
                if isinstance(op.gate, ops.MeasurementGate):
                    measured[op.qubits] = True
                    meas = op.gate
                    if all_measurements_are_terminal:
                        continue
                    if self._ignore_measurement_results:
                        for i, q in enumerate(op.qubits):
                            self._apply_op_channel(
                                ops.phase_damp(1).on(q), state, [indices[i]])
                    else:
                        invert_mask = meas.full_invert_mask()
                        # Measure updates inline.
                        bits, _ = density_matrix_utils.measure_density_matrix(
                            state.tensor,
                            indices,
                            qid_shape=qid_shape,
                            out=state.tensor,
                            seed=self._prng,
                        )
                        corrected = [
                            bit ^ (bit < 2 and mask)
                            for bit, mask in zip(bits, invert_mask)
                        ]
                        key = protocols.measurement_key(meas)
                        measurements[key].extend(corrected)
                else:
                    self._apply_op_channel(op, state, indices)
            yield DensityMatrixStepResult(
                density_matrix=state.tensor,
                measurements=measurements,
                qubit_map=qubit_map,
                dtype=self._dtype,
            )
Exemplo n.º 20
0
 def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
     if context and context.deep and isinstance(op.untagged,
                                                circuits.CircuitOperation):
         return op
     return protocols.decompose(op, keep=no_decomp, on_stuck_raise=None)
Exemplo n.º 21
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)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state, num_qubits,
                                                    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))

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

            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 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)
Exemplo n.º 22
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)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state, num_qubits,
                                                    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))

        data = _StateAndBuffer(state=np.reshape(state, (2, ) * num_qubits),
                               buffer=np.empty((2, ) * num_qubits,
                                               dtype=self._dtype))

        shape = np.array(data.state).shape

        # Qulacs
        qulacs_flag = 0
        qulacs_state = qulacs.QuantumStateGpu(int(num_qubits))
        qulacs_circuit = qulacs.QuantumCircuit(int(num_qubits))

        for moment in circuit:

            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            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 = [
                    num_qubits - 1 - qubit_map[qubit] for qubit in op.qubits
                ]
                if protocols.has_unitary(op):

                    # single qubit unitary gates
                    if isinstance(op.gate, ops.pauli_gates._PauliX):
                        qulacs_circuit.add_X_gate(indices[0])
                    elif isinstance(op.gate, ops.pauli_gates._PauliY):
                        qulacs_circuit.add_Y_gate(indices[0])
                    elif isinstance(op.gate, ops.pauli_gates._PauliZ):
                        qulacs_circuit.add_Z_gate(indices[0])
                    elif isinstance(op.gate, ops.common_gates.HPowGate):
                        qulacs_circuit.add_H_gate(indices[0])
                    elif isinstance(op.gate, ops.common_gates.XPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.common_gates.YPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.common_gates.ZPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, circuits.qasm_output.QasmUGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate,
                                    ops.matrix_gates.SingleQubitMatrixGate):
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())

                    # Two Qubit Unitary Gates
                    elif isinstance(op.gate, ops.common_gates.CNotPowGate):
                        qulacs_circuit.add_CNOT_gate(indices[0], indices[1])
                    elif isinstance(op.gate, ops.common_gates.CZPowGate):
                        qulacs_circuit.add_CZ_gate(indices[0], indices[1])
                    elif isinstance(op.gate, ops.common_gates.SwapPowGate):
                        qulacs_circuit.add_SWAP_gate(indices[0], indices[1])
                    elif isinstance(op.gate, ops.common_gates.ISwapPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.parity_gates.XXPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.parity_gates.YYPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.parity_gates.ZZPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate,
                                    ops.matrix_gates.TwoQubitMatrixGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())

                    # Three Qubit Unitary Gates
                    elif isinstance(op.gate, ops.three_qubit_gates.CCXPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.three_qubit_gates.CCZPowGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())
                    elif isinstance(op.gate, ops.three_qubit_gates.CSwapGate):
                        indices.reverse()
                        qulacs_circuit.add_dense_matrix_gate(
                            indices, op._unitary_())

                    qulacs_flag = 1

                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:
                        if qulacs_flag == 1:
                            self._simulate_on_qulacs(data, shape, qulacs_state,
                                                     qulacs_circuit)
                            qulacs_flag = 0
                        self._simulate_measurement(op, data, indices,
                                                   measurements, num_qubits)

                elif protocols.has_mixture(op):
                    if qulacs_flag == 1:
                        self._simulate_on_qulacs(data, shape, qulacs_state,
                                                 qulacs_circuit)
                        qulacs_flag = 0
                        qulacs_circuit = qulacs.QuantumCircuit(int(num_qubits))
                    self._simulate_mixture(op, data, indices)

        if qulacs_flag == 1:
            self._simulate_on_qulacs(data, shape, qulacs_state, qulacs_circuit)
            qulacs_flag = 0

        del qulacs_state
        del qulacs_circuit

        yield SparseSimulatorStep(state_vector=data.state,
                                  measurements=measurements,
                                  qubit_map=qubit_map,
                                  dtype=self._dtype)
Exemplo n.º 23
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())
        qid_shape = protocols.qid_shape(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        initial_matrix = density_matrix_utils.to_valid_density_matrix(
            initial_state,
            len(qid_shape),
            qid_shape=qid_shape,
            dtype=self._dtype)
        if len(circuit) == 0:
            yield DensityMatrixStepResult(initial_matrix, {}, qubit_map,
                                          self._dtype)
            return

        state = _StateAndBuffers(len(qid_shape),
                                 initial_matrix.reshape(qid_shape * 2))

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate operations that don't implement "
                "SupportsUnitary, SupportsConsistentApplyUnitary, "
                "SupportsMixture, SupportsChannel or is a measurement: {!r}".
                format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_channel(potential_op)
                    or (ops.op_gate_of_type(potential_op, ops.MeasurementGate)
                        is not None)
                    or isinstance(potential_op,
                                  (ops.SamplesDisplay, ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay)))

        noisy_moments = self.noise.noisy_moments(circuit,
                                                 sorted(circuit.all_qubits()))

        for moment in noisy_moments:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[int]]

            channel_ops_and_measurements = protocols.decompose(
                moment, keep=keep, on_stuck_raise=on_stuck)

            for op in channel_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if isinstance(op, (ops.SamplesDisplay, ops.WaveFunctionDisplay,
                                   ops.DensityMatrixDisplay)):
                    continue
                # TODO: support more general measurements.
                meas = ops.op_gate_of_type(op, ops.MeasurementGate)
                if meas:
                    if perform_measurements:
                        invert_mask = meas.full_invert_mask()
                        # Measure updates inline.
                        bits, _ = density_matrix_utils.measure_density_matrix(
                            state.tensor,
                            indices,
                            qid_shape=qid_shape,
                            out=state.tensor)
                        corrected = [
                            bit ^ (bit < 2 and mask)
                            for bit, mask in zip(bits, invert_mask)
                        ]
                        key = protocols.measurement_key(meas)
                        measurements[key].extend(corrected)
                else:
                    # TODO: Use apply_channel similar to apply_unitary.
                    self._apply_op_channel(op, state, indices)
            yield DensityMatrixStepResult(density_matrix=state.tensor,
                                          measurements=measurements,
                                          qubit_map=qubit_map,
                                          dtype=self._dtype)
Exemplo n.º 24
0
 def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
     return protocols.decompose(op, keep=no_decomp, on_stuck_raise=None)