def __init__(self, data, input_dims=None, output_dims=None): """Initialize a PTM quantum channel operator.""" # If the input is a raw list or matrix we assume that it is # already a Chi matrix. if isinstance(data, (list, np.ndarray)): # Should we force this to be real? ptm = np.array(data, dtype=complex) # Determine input and output dimensions dout, din = ptm.shape if input_dims: input_dim = np.product(input_dims) else: input_dim = int(np.sqrt(din)) if output_dims: output_dim = np.product(input_dims) else: output_dim = int(np.sqrt(dout)) if output_dim**2 != dout or input_dim**2 != din or input_dim != output_dim: raise QiskitError("Invalid shape for PTM matrix.") 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 # convert it to a SuperOp data = SuperOp._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) input_dim, output_dim = data.dim # Now that the input is an operator we convert it to a PTM object ptm = _to_ptm(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() # Check input is N-qubit channel n_qubits = int(np.log2(input_dim)) if 2**n_qubits != input_dim: raise QiskitError("Input is not an n-qubit Pauli transfer matrix.") # 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__('PTM', ptm, input_dims, output_dims)
def __init__(self, data, input_dims=None, output_dims=None): """Initialize a PTM 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 ptm = _to_ptm(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)): # Should we force this to be real? ptm = np.array(data, dtype=complex) # Determine input and output dimensions dout, din = ptm.shape if input_dims: input_dim = np.product(input_dims) else: input_dim = int(np.sqrt(din)) if output_dims: output_dim = np.product(input_dims) else: output_dim = int(np.sqrt(dout)) if output_dim**2 != dout or input_dim**2 != din or input_dim != output_dim: raise QiskitError("Invalid shape for PTM matrix.") else: raise QiskitError("Invalid input data format for PTM") nqubits = int(np.log2(input_dim)) if 2**nqubits != input_dim: raise QiskitError("Input is not an n-qubit Pauli transfer matrix.") # 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__('PTM', ptm, input_dims, output_dims)
def __init__(self, data, input_dims=None, output_dims=None): """Initialize a PTM quantum channel 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 is not an N-qubit channel or cannot be initialized as a PTM. Additional Information: If the input or output dimensions are None, they will be automatically determined from the input data. The PTM representation is only valid for N-qubit channels. """ # If the input is a raw list or matrix we assume that it is # already a Chi matrix. if isinstance(data, (list, np.ndarray)): # Should we force this to be real? ptm = np.asarray(data, dtype=complex) # Determine input and output dimensions dout, din = ptm.shape if input_dims: input_dim = np.product(input_dims) else: input_dim = int(np.sqrt(din)) if output_dims: output_dim = np.product(input_dims) else: output_dim = int(np.sqrt(dout)) if output_dim**2 != dout or input_dim**2 != din or input_dim != output_dim: raise QiskitError("Invalid shape for PTM matrix.") 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 # convert it to a SuperOp data = SuperOp._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) input_dim, output_dim = data.dim # Now that the input is an operator we convert it to a PTM object rep = getattr(data, '_channel_rep', 'Operator') ptm = _to_ptm(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() # Check input is N-qubit channel n_qubits = int(np.log2(input_dim)) if 2**n_qubits != input_dim: raise QiskitError("Input is not an n-qubit Pauli transfer matrix.") # 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__(ptm, input_dims, output_dims, 'PTM')