コード例 #1
0
 def _instruction_to_superop(cls, obj):
     """Return superop for instruction if defined or None otherwise."""
     if not isinstance(obj, Instruction):
         raise QiskitError("Input is not an instruction.")
     chan = None
     if obj.name == "reset":
         # For superoperator evolution we can simulate a reset as
         # a non-unitary superoperator matrix
         chan = SuperOp(
             np.array([[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0],
                       [0, 0, 0, 0]]))
     if obj.name == "kraus":
         kraus = obj.params
         dim = len(kraus[0])
         chan = SuperOp(_to_superop("Kraus", (kraus, None), dim, dim))
     elif hasattr(obj, "to_matrix"):
         # If instruction is a gate first we see if it has a
         # `to_matrix` definition and if so use that.
         try:
             kraus = [obj.to_matrix()]
             dim = len(kraus[0])
             chan = SuperOp(_to_superop("Kraus", (kraus, None), dim, dim))
         except QiskitError:
             pass
     return chan
コード例 #2
0
 def _append_instruction(self, obj, qargs=None):
     """Update the current Operator by apply an instruction."""
     if isinstance(obj, Instruction):
         chan = None
         if obj.name == 'reset':
             # For superoperator evolution we can simulate a reset as
             # a non-unitary superoperator matrix
             chan = SuperOp(
                 np.array([[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0],
                           [0, 0, 0, 0]]))
         if obj.name == 'kraus':
             kraus = obj.params
             dim = len(kraus[0])
             chan = SuperOp(_to_superop('Kraus', (kraus, None), dim, dim))
         elif hasattr(obj, 'to_matrix'):
             # If instruction is a gate first we see if it has a
             # `to_matrix` definition and if so use that.
             try:
                 kraus = [obj.to_matrix()]
                 dim = len(kraus[0])
                 chan = SuperOp(
                     _to_superop('Kraus', (kraus, None), dim, dim))
             except QiskitError:
                 pass
         if chan is not None:
             # Perform the composition and in-place update the current state
             # of the operator
             op = self.compose(chan, qargs=qargs)
             self._data = op.data
         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))
             for instr, qregs, cregs in obj.definition:
                 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)
     else:
         raise QiskitError('Input is not an instruction.')
コード例 #3
0
ファイル: superop.py プロジェクト: jagunnels/qiskit-sdk-py
 def __init__(self, data, input_dims=None, output_dims=None):
     """Initialize a SuperOp quantum channel operator."""
     if issubclass(data.__class__, BaseOperator):
         # If not a channel we use `to_operator` method to get
         # the unitary-representation matrix for input
         if not issubclass(data.__class__, QuantumChannel):
             data = data.to_operator()
         input_dim, output_dim = data.dim
         super_mat = _to_superop(data.rep, data._data, input_dim,
                                 output_dim)
         if input_dims is None:
             input_dims = data.input_dims()
         if output_dims is None:
             output_dims = data.output_dims()
     elif isinstance(data, (list, np.ndarray)):
         # We initialize directly from superoperator matrix
         super_mat = np.array(data, dtype=complex)
         # Determine total input and output dimensions
         dout, din = super_mat.shape
         input_dim = int(np.sqrt(din))
         output_dim = int(np.sqrt(dout))
         if output_dim**2 != dout or input_dim**2 != din:
             raise QiskitError("Invalid shape for SuperOp matrix.")
     else:
         raise QiskitError("Invalid input data format for SuperOp")
     # Check and format input and output dimensions
     input_dims = self._automatic_dims(input_dims, input_dim)
     output_dims = self._automatic_dims(output_dims, output_dim)
     super().__init__('SuperOp', super_mat, input_dims, output_dims)
コード例 #4
0
    def __init__(self, data, input_dims=None, output_dims=None):
        """Initialize a quantum channel Superoperator operator.

        Args:
            data (QuantumCircuit or
                  Instruction or
                  BaseOperator or
                  matrix): data to initialize superoperator.
            input_dims (tuple): the input subsystem dimensions.
                                [Default: None]
            output_dims (tuple): the output subsystem dimensions.
                                 [Default: None]

        Raises:
            QiskitError: if input data cannot be initialized as a
                         superoperator.

        Additional Information:
            If the input or output dimensions are None, they will be
            automatically determined from the input data. If the input data is
            a Numpy array of shape (4**N, 4**N) qubit systems will be used. If
            the input operator is not an N-qubit operator, it will assign a
            single subsystem with dimension specified by the shape of the input.
        """
        # If the input is a raw list or matrix we assume that it is
        # already a superoperator.
        if isinstance(data, (list, np.ndarray)):
            # We initialize directly from superoperator matrix
            super_mat = np.asarray(data, dtype=complex)
            # Determine total input and output dimensions
            dout, din = super_mat.shape
            input_dim = int(np.sqrt(din))
            output_dim = int(np.sqrt(dout))
            if output_dim**2 != dout or input_dim**2 != din:
                raise QiskitError("Invalid shape for SuperOp matrix.")
            op_shape = OpShape.auto(dims_l=output_dims,
                                    dims_r=input_dims,
                                    shape=(output_dim, input_dim))
        else:
            # Otherwise we initialize by conversion from another Qiskit
            # object into the QuantumChannel.
            if isinstance(data, (QuantumCircuit, Instruction)):
                # If the input is a Terra QuantumCircuit or Instruction we
                # perform a simulation to construct the circuit superoperator.
                # This will only work if the circuit or instruction can be
                # defined in terms of instructions which have no classical
                # register components. The instructions can be gates, reset,
                # or Kraus instructions. Any conditional gates or measure
                # will cause an exception to be raised.
                data = self._init_instruction(data)
            else:
                # We use the QuantumChannel init transform to initialize
                # other objects into a QuantumChannel or Operator object.
                data = self._init_transformer(data)
            # Now that the input is an operator we convert it to a
            # SuperOp object
            op_shape = data._op_shape
            input_dim, output_dim = data.dim
            rep = getattr(data, "_channel_rep", "Operator")
            super_mat = _to_superop(rep, data._data, input_dim, output_dim)
        # Initialize QuantumChannel
        super().__init__(super_mat, op_shape=op_shape)