示例#1
0
    def validate_schedule(self, schedule):
        """
        Raises an error if the given schedule is invalid on this device.

        Args:
            schedule: The schedule to validate

        Raises:
            ValueError: If the schedule is invalid
        """
        super().validate_schedule(schedule)
        # Validate each scheduled operation in the schedule
        # If operation is a measurement, ensure only measurements come after it
        measurement_check_performed = False
        for so in schedule.scheduled_operations:
            self.validate_scheduled_operation(schedule, so)
            if (ops.op_gate_of_type(so.operation, ops.MeasurementGate)
                    and not measurement_check_performed):
                later_ops = [
                    op for op in schedule.scheduled_operations
                    if op.time + op.duration > so.time + so.duration
                ]
                for op in later_ops:
                    if not ops.op_gate_of_type(op, ops.MeasurementGate):
                        raise ValueError("Non-measurement operation after"
                                         " measurement")
                measurement_check_performed = True
示例#2
0
 def duration_of(self, operation):
     if ops.op_gate_of_type(operation, ops.XXPowGate):
         return self._twoq_gates_duration
     if (ops.op_gate_of_type(operation, ops.XPowGate)
             or ops.op_gate_of_type(operation, ops.YPowGate)
             or ops.op_gate_of_type(operation, ops.ZPowGate)):
         return self._oneq_gates_duration
     if ops.op_gate_of_type(operation, ops.MeasurementGate):
         return self._measurement_duration
     raise ValueError('Unsupported gate type: {!r}'.format(operation))
示例#3
0
    def duration_of(self, operation):
        if ops.op_gate_of_type(operation, ops.HPowGate):
            return cirq.Duration(nanos=10)
        if ops.op_gate_of_type(operation, ops.ZPowGate):
            return cirq.Duration(nanos=10)
        if ops.op_gate_of_type(operation, ops.CNotPowGate):
            return cirq.Duration(nanos=200)
        if ops.op_gate_of_type(operation, ops.MeasurementGate):
            return cirq.Duration(nanos=100)

        raise ValueError('Unsupported gate type: {!r}'.format(operation))
示例#4
0
 def continue_condition(op: ops.Operation,
                        current_string: ops.PauliStringPhasor,
                        is_first: bool) -> int:
     if ops.op_gate_of_type(op, ops.SingleQubitCliffordGate):
         return (CONTINUE
                 if len(current_string.pauli_string) != 1 else STOP)
     if ops.op_gate_of_type(op, ops.CZPowGate):
         return STOP if stop_at_cz else CONTINUE
     if (isinstance(op, ops.PauliStringPhasor) and len(op.qubits) == 1
             and (op.pauli_string[op.qubits[0]]
                  == current_string.pauli_string[op.qubits[0]])):
         return SKIP
     return STOP
示例#5
0
文件: eject_z.py 项目: zhiyuzh/Cirq
def _is_swaplike(op: ops.Operation):
    gate1 = ops.op_gate_of_type(op, ops.SwapPowGate)
    if gate1:
        return gate1.exponent == 1

    gate2 = ops.op_gate_of_type(op, ops.ISwapPowGate)
    if gate2:
        return _is_integer((gate2.exponent - 1) / 2)

    gate3 = ops.op_gate_of_type(op, ops.FSimGate)
    if gate3:
        return _is_integer((gate3.theta - (np.pi / 2)) / np.pi)

    return False
示例#6
0
 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)))
    def _keep(self, op: ops.Operation) -> bool:
        # Check if this is a CZ
        # Only keep partial CZ gates if allow_partial_czs
        cz_gate = ops.op_gate_of_type(op, ops.CZPowGate)
        if (cz_gate
                and (self.allow_partial_czs
                     or value.canonicalize_half_turns(cz_gate.exponent) == 1)):
            return True

        # Measurement in Z basis?
        if ops.op_gate_of_type(op, ops.MeasurementGate):
            return True

        # SingleQubit known matrix
        if len(op.qubits) == 1 and protocols.has_unitary(op):
            return True
        return False
示例#8
0
文件: eject_z.py 项目: yijingS/Cirq
    def optimize_circuit(self, circuit: circuits.Circuit):
        # Tracks qubit phases (in half turns; multiply by pi to get radians).
        qubit_phase = defaultdict(lambda: 0)  # type: Dict[ops.Qid, float]

        def dump_tracked_phase(qubits: Iterable[ops.Qid], index: int) -> None:
            """Zeroes qubit_phase entries by emitting Z gates."""
            for q in qubits:
                p = qubit_phase[q]
                if not decompositions.is_negligible_turn(p, self.tolerance):
                    dump_op = ops.Z(q)**(p * 2)
                    insertions.append((index, dump_op))
                qubit_phase[q] = 0

        deletions = []  # type: List[Tuple[int, ops.Operation]]
        inline_intos = []  # type: List[Tuple[int, ops.Operation]]
        insertions = []  # type: List[Tuple[int, ops.Operation]]
        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                # Move Z gates into tracked qubit phases.
                h = _try_get_known_z_half_turns(op)
                if h is not None:
                    q = op.qubits[0]
                    qubit_phase[q] += h / 2
                    deletions.append((moment_index, op))
                    continue

                # Z gate before measurement is a no-op. Drop tracked phase.
                if ops.op_gate_of_type(op, ops.MeasurementGate):
                    for q in op.qubits:
                        qubit_phase[q] = 0

                # If there's no tracked phase, we can move on.
                phases = [qubit_phase[q] for q in op.qubits]
                if all(
                        decompositions.is_negligible_turn(p, self.tolerance)
                        for p in phases):
                    continue

                # Try to move the tracked phasing over the operation.
                phased_op = op
                for i, p in enumerate(phases):
                    if not decompositions.is_negligible_turn(
                            p, self.tolerance):
                        phased_op = protocols.phase_by(phased_op,
                                                       -p,
                                                       i,
                                                       default=None)
                if phased_op is not None:
                    deletions.append((moment_index, op))
                    inline_intos.append(
                        (moment_index, cast(ops.Operation, phased_op)))
                else:
                    dump_tracked_phase(op.qubits, moment_index)

        dump_tracked_phase(qubit_phase.keys(), len(circuit))
        circuit.batch_remove(deletions)
        circuit.batch_insert_into(inline_intos)
        circuit.batch_insert(insertions)
示例#9
0
def _verify_unique_measurement_keys(operations: Iterable[ops.Operation]):
    seen: Set[str] = set()
    for op in operations:
        meas = ops.op_gate_of_type(op, ops.MeasurementGate)
        if meas:
            key = protocols.measurement_key(meas)
            if key in seen:
                raise ValueError('Measurement key {} repeated'.format(key))
            seen.add(key)
示例#10
0
def get_op_string(op_obj: ops.Operation):
    """Find the string representation for a given gate
    Params:
        op_obj: Gate object, out of: XXPowGate, XPowGate, YPowGate"""
    if isinstance(op_obj, ops.XXPowGate) or ops.op_gate_of_type(
            op_obj, ops.XXPowGate):
        op_str = 'MS'
    elif isinstance(op_obj, ops.XPowGate) or ops.op_gate_of_type(
            op_obj, ops.XPowGate):
        op_str = 'X'
    elif isinstance(op_obj, ops.YPowGate) or ops.op_gate_of_type(
            op_obj, ops.YPowGate):
        op_str = 'Y'
    elif isinstance(op_obj, ops.MeasurementGate) or ops.op_gate_of_type(
            op_obj, ops.MeasurementGate):
        op_str = 'Meas'
    else:
        raise ValueError('Got unknown gate:', op_obj)
    return op_str
示例#11
0
    def can_add_operation_into_moment(self, operation: ops.Operation,
                                      moment: ops.Moment) -> bool:

        if not super().can_add_operation_into_moment(operation, moment):
            return False
        if ops.op_gate_of_type(operation, ops.XXPowGate):
            return not self._check_if_XXPow_operation_interacts_with_any(
                cast(ops.GateOperation, operation),
                cast(Iterable[ops.GateOperation], moment.operations))
        return True
示例#12
0
    def optimize_circuit(self, circuit: circuits.Circuit):
        state = _OptimizerState()

        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                affected = [q for q in op.qubits
                            if state.held_w_phases.get(q) is not None]

                # Collect, phase, and merge Ws.
                w = _try_get_known_phased_pauli(op)
                if w is not None:
                    if decompositions.is_negligible_turn(
                            w[0] - 1,
                            self.tolerance):
                        _potential_cross_whole_w(moment_index,
                                                 op,
                                                 self.tolerance,
                                                 state)
                    else:
                        _potential_cross_partial_w(moment_index, op, state)
                    continue

                if not affected:
                    continue

                # Absorb Z rotations.
                t = _try_get_known_z_half_turns(op)
                if t is not None:
                    _absorb_z_into_w(moment_index, op, state)
                    continue

                # Dump coherent flips into measurement bit flips.
                if ops.op_gate_of_type(op, ops.MeasurementGate):
                    _dump_into_measurement(moment_index, op, state)

                # Cross CZs using kickback.
                if _try_get_known_cz_half_turns(op) is not None:
                    if len(affected) == 1:
                        _single_cross_over_cz(moment_index,
                                              op,
                                              affected[0],
                                              state)
                    else:
                        _double_cross_over_cz(op, state)
                    continue

                # Don't know how to handle this situation. Dump the gates.
                _dump_held(op.qubits, moment_index, state)

        # Put anything that's still held at the end of the circuit.
        _dump_held(state.held_w_phases.keys(), len(circuit), state)

        circuit.batch_remove(state.deletions)
        circuit.batch_insert_into(state.inline_intos)
        circuit.batch_insert(state.insertions)
示例#13
0
 def validate_moment(self, moment: 'cirq.Moment'):
     super().validate_moment(moment)
     for op in moment.operations:
         if ops.op_gate_of_type(op, ops.CZPowGate):
             for other in moment.operations:
                 if (other is not op
                         and self._check_if_exp11_operation_interacts(
                             cast(ops.GateOperation, op),
                             cast(ops.GateOperation, other))):
                     raise ValueError(
                         'Adjacent Exp11 operations: {}.'.format(moment))
示例#14
0
    def can_add_operation_into_moment(self, operation: 'cirq.Operation',
                                      moment: 'cirq.Moment') -> bool:
        self.validate_moment(moment)

        if not super().can_add_operation_into_moment(operation, moment):
            return False
        if ops.op_gate_of_type(operation, ops.CZPowGate):
            return not self._check_if_exp11_operation_interacts_with_any(
                cast(ops.GateOperation, operation),
                cast(Iterable['cirq.GateOperation'], moment.operations))
        return True
示例#15
0
 def _simulate_measurement(self, op: ops.Operation, data: _StateAndBuffer,
                           indices: List[int],
                           measurements: Dict[str, List[bool]],
                           num_qubits: int) -> None:
     """Simulate an op that is a measurement in the computataional basis."""
     meas = ops.op_gate_of_type(op, ops.MeasurementGate)
     # TODO: support measurement outside computational basis.
     if meas:
         invert_mask = meas.invert_mask or num_qubits * (False, )
         # Measure updates inline.
         bits, _ = wave_function.measure_state_vector(
             data.state, indices, data.state)
         corrected = [bit ^ mask for bit, mask in zip(bits, invert_mask)]
         key = protocols.measurement_key(meas)
         measurements[key].extend(corrected)
示例#16
0
 def _simulate_reset(self, op: ops.Operation, data: _StateAndBuffer,
                     indices: List[int]) -> None:
     """Simulate an op that is a reset to the |0> state."""
     reset = ops.op_gate_of_type(op, ops.ResetChannel)
     if reset:
         # Do a silent measurement.
         bits, _ = wave_function.measure_state_vector(
             data.state,
             indices,
             out=data.state,
             qid_shape=data.state.shape)
         # Apply bit flip(s) to change the reset the bits to 0.
         for b, i, d in zip(bits, indices, protocols.qid_shape(reset)):
             if b == 0:
                 continue  # Already zero, no reset needed
             reset_unitary = _FlipGate(d, reset_value=b)(*op.qubits)
             self._simulate_unitary(reset_unitary, data, [i])
示例#17
0
 def duration_of(self, operation):
     if ops.op_gate_of_type(operation, ops.CZPowGate):
         return self._exp_z_duration
     if ops.op_gate_of_type(operation, ops.MeasurementGate):
         return self._measurement_duration
     if (ops.op_gate_of_type(operation, ops.XPowGate)
             or ops.op_gate_of_type(operation, ops.YPowGate)
             or ops.op_gate_of_type(operation, ops.PhasedXPowGate)):
         return self._exp_w_duration
     if ops.op_gate_of_type(operation, ops.ZPowGate):
         # Z gates are performed in the control software.
         return value.Duration()
     raise ValueError('Unsupported gate type: {!r}'.format(operation))
示例#18
0
    def optimization_at(
            self, circuit: circuits.Circuit, index: int,
            op: ops.Operation) -> Optional[circuits.PointOptimizationSummary]:
        if len(op.qubits) != 2:
            return None

        old_operations, indices, matrix = (
            self._scan_two_qubit_ops_into_matrix(circuit, index, op.qubits))

        old_interaction_count = len(
            [old_op for old_op in old_operations if len(old_op.qubits) == 2])

        switch_to_new = False
        switch_to_new |= any(
            len(old_op.qubits) == 2
            and not ops.op_gate_of_type(old_op, ops.CZPowGate)
            for old_op in old_operations)
        if not self.allow_partial_czs:
            switch_to_new |= any(
                isinstance(old_op, ops.GateOperation) and isinstance(
                    old_op.gate, ops.CZPowGate) and old_op.gate.exponent != 1
                for old_op in old_operations)

        # This point cannot be optimized using this method
        if not switch_to_new and old_interaction_count <= 1:
            return None

        # Find a max-3-cz construction.
        new_operations = (
            two_qubit_decompositions.two_qubit_matrix_to_operations(
                op.qubits[0], op.qubits[1], matrix, self.allow_partial_czs,
                self.tolerance, False))
        new_interaction_count = len(
            [new_op for new_op in new_operations if len(new_op.qubits) == 2])

        switch_to_new |= new_interaction_count < old_interaction_count

        if not switch_to_new:
            return None

        return circuits.PointOptimizationSummary(clear_span=max(indices) + 1 -
                                                 index,
                                                 clear_qubits=op.qubits,
                                                 new_operations=new_operations)
示例#19
0
文件: qasm_output.py 项目: wabei/Cirq
 def __init__(self,
              operations: ops.OP_TREE,
              qubits: Tuple[ops.Qid, ...],
              header: str = '',
              precision: int = 10,
              version: str = '2.0') -> None:
     self.operations = tuple(ops.flatten_op_tree(operations))
     self.qubits = qubits
     self.header = header
     self.measurements = tuple(
         op for op in self.operations
         if ops.op_gate_of_type(op, ops.MeasurementGate))  # type: ignore
     meas_key_id_map, meas_comments = self._generate_measurement_ids()
     self.meas_comments = meas_comments
     qubit_id_map = self._generate_qubit_ids()
     self.args = protocols.QasmArgs(precision=precision,
                                    version=version,
                                    qubit_id_map=qubit_id_map,
                                    meas_key_id_map=meas_key_id_map)
示例#20
0
    def optimization_at(self, circuit: circuits.Circuit, index: int,
                        op: ops.Operation):
        if ops.op_gate_of_type(op, AcquaintanceOpportunityGate):
            logical_indices = tuple(self.mapping[q] for q in op.qubits)
            logical_operations = self.execution_strategy.get_operations(
                logical_indices, op.qubits)
            clear_span = int(not self.execution_strategy.keep_acquaintance)

            return circuits.PointOptimizationSummary(
                clear_span=clear_span,
                clear_qubits=op.qubits,
                new_operations=logical_operations)

        if (isinstance(op, ops.GateOperation)
                and isinstance(op.gate, PermutationGate)):
            op.gate.update_mapping(self.mapping, op.qubits)
            return

        raise TypeError('Can only execute a strategy consisting of gates that '
                        'are instances of AcquaintanceOpportunityGate or '
                        'PermutationGate.')
示例#21
0
    def validate_circuit(self, circuit: circuits.Circuit):
        """
        Raises an error if the given circuit is invalid on this device. A
        circuit is invalid if any of its moments are invalid or if there is a
        non-empty moment after a moment with a measurement.

        Args:
            circuit: The circuit to validate

        Raises:
            ValueError: If the given circuit can't be run on this device
        """
        super().validate_circuit(circuit)

        # Measurements must be in the last non-empty moment
        has_measurement_occurred = False
        for moment in circuit:
            if has_measurement_occurred:
                if len(moment.operations) > 0:
                    raise ValueError("Non-empty moment after measurement")
            for operation in moment.operations:
                if ops.op_gate_of_type(operation, ops.MeasurementGate):
                    has_measurement_occurred = True
示例#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)}
        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)
示例#23
0
def _cz_count(circuit):
    return sum(bool(ops.op_gate_of_type(op, ops.CZPowGate)) for op in circuit)
示例#24
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)
示例#25
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)
示例#26
0
 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))
示例#27
0
 def _keep(self, op: ops.Operation) -> bool:
     # Don't change if it's already a SingleQubitCliffordGate
     return bool(ops.op_gate_of_type(op, ops.SingleQubitCliffordGate))
示例#28
0
 def __init__(self):
     circuits.PointOptimizer.__init__(self)
     self.no_decomp = lambda op: (not get_acquaintance_size(
         op) or ops.op_gate_of_type(op, AcquaintanceOpportunityGate))
    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)