Beispiel #1
0
    def reset(self, qargs=None):
        """Reset state or subsystems to the 0-state.

        Args:
            qargs (list or None): subsystems to reset, if None all
                                  subsystems will be reset to their 0-state
                                  (Default: None).

        Returns:
            DensityMatrix: the reset state.

        Additional Information:
            If all subsystems are reset this will return the ground state
            on all subsystems. If only a some subsystems are reset this
            function will perform evolution by the reset
            :class:`~qiskit.quantum_info.SuperOp` of the reset subsystems.
        """
        if qargs is None:
            # Resetting all qubits does not require sampling or RNG
            ret = copy.copy(self)
            state = np.zeros(self._op_shape.shape, dtype=complex)
            state[0, 0] = 1
            ret._data = state
            return ret

        # Reset by evolving by reset SuperOp
        dims = self.dims(qargs)
        reset_superop = SuperOp(ScalarOp(dims, coeff=0))
        reset_superop.data[0] = Operator(ScalarOp(dims)).data.ravel()
        return self.evolve(reset_superop, qargs=qargs)
Beispiel #2
0
    def _add(self, other, qargs=None):
        """Return the operator self + other.

        If ``qargs`` are specified the other operator will be added
        assuming it is identity on all other subsystems.

        Args:
            other (Operator): an operator object.
            qargs (None or list): optional subsystems to add on
                                  (Default: None)

        Returns:
            Operator: the operator self + other.

        Raises:
            QiskitError: if other is not an operator, or has incompatible
                         dimensions.
        """
        # pylint: disable=cyclic-import
        from qiskit.quantum_info.operators.scalar_op import ScalarOp

        if qargs is None:
            qargs = getattr(other, 'qargs', None)

        if not isinstance(other, Operator):
            other = Operator(other)

        self._op_shape._validate_add(other._op_shape, qargs)
        other = ScalarOp._pad_with_identity(self, other, qargs)

        ret = copy.copy(self)
        ret._data = self.data + other.data
        return ret
Beispiel #3
0
    def _add(self, other, qargs=None):
        """Return the QuantumChannel self + other.

        If ``qargs`` are specified the other channel will be added
        assuming it is the identity channel on all other subsystems.

        Args:
            other (QuantumChannel): a quantum channel.
            qargs (None or list): optional subsystems to add on
                                  (Default: None)

        Returns:
            QuantumChannel: the linear addition self + other as a SuperOp object.

        Raises:
            QiskitError: if other cannot be converted to a channel or
                         has incompatible dimensions.
        """
        # NOTE: this method must be overriden for subclasses
        # that don't have a linear matrix representation
        # ie Kraus and Stinespring

        if qargs is None:
            qargs = getattr(other, 'qargs', None)

        if not isinstance(other, self.__class__):
            other = self.__class__(other)

        self._validate_add_dims(other, qargs)
        other = ScalarOp._pad_with_identity(self, other, qargs)

        ret = copy.copy(self)
        ret._data = self._data + other._data
        return ret
Beispiel #4
0
    def _append_instruction(self, obj, qargs=None):
        """Update the current Operator by apply an instruction."""
        from qiskit.circuit.barrier import Barrier
        from .scalar_op import ScalarOp

        mat = self._instruction_to_matrix(obj)
        if mat is not None:
            # Perform the composition and inplace update the current state
            # of the operator
            op = self.compose(mat, qargs=qargs)
            self._data = op.data
        elif isinstance(obj, Barrier):
            return
        else:
            # If the instruction doesn't have a matrix defined we use its
            # circuit decomposition definition if it exists, otherwise we
            # cannot compose this gate and raise an error.
            if obj.definition is None:
                raise QiskitError(f"Cannot apply Operation: {obj.name}")
            if not isinstance(obj.definition, QuantumCircuit):
                raise QiskitError(
                    'Operation "{}" '
                    "definition is {} but expected QuantumCircuit.".format(
                        obj.name, type(obj.definition)))
            if obj.definition.global_phase:
                dimension = 2**obj.num_qubits
                op = self.compose(
                    ScalarOp(dimension,
                             np.exp(1j * float(obj.definition.global_phase))),
                    qargs=qargs,
                )
                self._data = op.data
            flat_instr = obj.definition
            bit_indices = {
                bit: index
                for bits in [flat_instr.qubits, flat_instr.clbits]
                for index, bit in enumerate(bits)
            }

            for instruction in flat_instr:
                if instruction.clbits:
                    raise QiskitError(
                        "Cannot apply operation with classical bits:"
                        f" {instruction.operation.name}")
                # Get the integer position of the flat register
                if qargs is None:
                    new_qargs = [
                        bit_indices[tup] for tup in instruction.qubits
                    ]
                else:
                    new_qargs = [
                        qargs[bit_indices[tup]] for tup in instruction.qubits
                    ]
                self._append_instruction(instruction.operation,
                                         qargs=new_qargs)
Beispiel #5
0
 def _add(self, other, qargs=None):
     # NOTE: this method must be overridden for subclasses
     # that don't have a linear matrix representation
     # ie Kraus and Stinespring
     if not isinstance(other, type(self)):
         other = type(self)(other)
     self._op_shape._validate_add(other._op_shape, qargs)
     other = ScalarOp._pad_with_identity(self, other, qargs)
     ret = copy.copy(self)
     ret._data = self._data + other._data
     return ret
Beispiel #6
0
    def _append_instruction(self, obj, qargs=None):
        """Update the current Operator by apply an instruction."""
        from qiskit.circuit.barrier import Barrier
        from .scalar_op import ScalarOp

        mat = self._instruction_to_matrix(obj)
        if mat is not None:
            # Perform the composition and inplace update the current state
            # of the operator
            op = self.compose(mat, qargs=qargs)
            self._data = op.data
        elif isinstance(obj, Barrier):
            return
        else:
            # If the instruction doesn't have a matrix defined we use its
            # circuit decomposition definition if it exists, otherwise we
            # cannot compose this gate and raise an error.
            if obj.definition is None:
                raise QiskitError('Cannot apply Instruction: {}'.format(
                    obj.name))
            if not isinstance(obj.definition, QuantumCircuit):
                raise QiskitError(
                    'Instruction "{}" '
                    'definition is {} but expected QuantumCircuit.'.format(
                        obj.name, type(obj.definition)))
            if obj.definition.global_phase:
                dimension = 2**self.num_qubits
                op = self.compose(ScalarOp(
                    dimension,
                    np.exp(1j * float(obj.definition.global_phase))),
                                  qargs=qargs)
                self._data = op.data
            flat_instr = obj.definition.to_instruction()
            for instr, qregs, cregs in flat_instr.definition.data:
                if cregs:
                    raise QiskitError(
                        'Cannot apply instruction with classical registers: {}'
                        .format(instr.name))
                # Get the integer position of the flat register
                if qargs is None:
                    new_qargs = [tup.index for tup in qregs]
                else:
                    new_qargs = [qargs[tup.index] for tup in qregs]
                self._append_instruction(instr, qargs=new_qargs)