def sample(self, shots: int = 1024, massive: bool = False, reverse_endianness: bool = False) -> dict: """ Sample the state function as a normalized probability distribution. Returns dict of bitstrings in order of probability, with values being probability. """ OperatorBase._check_massive('sample', False, self.num_qubits, massive) qc = self.to_circuit(meas=True) qasm_backend = BasicAer.get_backend('qasm_simulator') counts = execute(qc, qasm_backend, optimization_level=0, shots=shots).result().get_counts() if reverse_endianness: scaled_dict = { bstr[::-1]: (prob / shots) for (bstr, prob) in counts.items() } else: scaled_dict = { bstr: (prob / shots) for (bstr, prob) in counts.items() } return dict( sorted(scaled_dict.items(), key=lambda x: x[1], reverse=True))
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive("to_matrix", True, self.num_qubits, massive) if isinstance(self.coeff, ParameterExpression): return (self.primitive.to_matrix( sparse=True)).toarray() * self.coeff return (self.primitive.to_matrix(sparse=True) * self.coeff).toarray()
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive) states = int(2 ** self.num_qubits) probs = np.zeros(states) + 0.j for k, v in self.primitive.items(): probs[int(k, 2)] = v vec = probs * self.coeff # Reshape for measurements so np.dot still works for composition. return vec if not self.is_measurement else vec.reshape(1, -1)
def to_density_matrix(self, massive: bool = False) -> np.ndarray: """ Return numpy matrix of density operator, warn if more than 16 qubits to force the user to set massive=True if they want such a large matrix. Generally big methods like this should require the use of a converter, but in this case a convenience method for quick hacking and access to classical tools is appropriate. """ OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive) return self.primitive.to_matrix() * self.coeff
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive) # Need to adjoint to get forward statevector and then reverse if self.is_measurement: return np.conj(self.adjoint().to_matrix(massive=massive)) qc = self.to_circuit(meas=False) statevector_backend = BasicAer.get_backend('statevector_simulator') transpiled = transpile(qc, statevector_backend, optimization_level=0) statevector = statevector_backend.run(transpiled).result().get_statevector() from ..operator_globals import EVAL_SIG_DIGITS return np.round(statevector * self.coeff, decimals=EVAL_SIG_DIGITS)
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive('to_matrix', True, self.num_qubits, massive) # Combination function must be able to handle classical values. # Note: this can end up, when we have list operators containing other list operators, as a # ragged array and numpy 1.19 raises a deprecation warning unless this is explicitly # done as object type now - was implicit before. mat = self.combo_fn( np.asarray([op.to_matrix(massive=massive) * self.coeff for op in self.oplist], dtype=object)) # Note: As ComposedOp has a combo function of inner product we can end up here not with # a matrix (array) but a scalar. In which case we make a single element array of it. if isinstance(mat, Number): mat = [mat] return np.asarray(mat, dtype=complex)
def to_matrix(self, massive: bool = False) -> np.ndarray: r""" Note: this does not return a density matrix, it returns a classical matrix containing the quantum or classical vector representing the evaluation of the state function on each binary basis state. Do not assume this is is a normalized quantum or classical probability vector. If we allowed this to return a density matrix, then we would need to change the definition of composition to be ~Op @ StateFn @ Op for those cases, whereas by this methodology we can ensure that composition always means Op @ StateFn. Return numpy vector of state vector, warn if more than 16 qubits to force the user to set massive=True if they want such a large vector. Args: massive: Whether to allow large conversions, e.g. creating a matrix representing over 16 qubits. Returns: np.ndarray: Vector of state vector Raises: ValueError: Invalid parameters. """ OperatorBase._check_massive('to_matrix', False, self.num_qubits, massive) # Operator - return diagonal (real values, not complex), # not rank 1 decomposition (statevector)! mat = self.primitive.to_matrix(massive=massive) # TODO change to weighted sum of eigenvectors' StateFns? # ListOp primitives can return lists of matrices (or trees for nested ListOps), # so we need to recurse over the # possible tree. def diag_over_tree(op): if isinstance(op, list): return [diag_over_tree(o) for o in op] else: vec = np.diag(op) * self.coeff # Reshape for measurements so np.dot still works for composition. return vec if not self.is_measurement else vec.reshape(1, -1) return diag_over_tree(mat)
def to_density_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive) states = int(2 ** self.num_qubits) return self.to_matrix(massive=massive) * np.eye(states) * self.coeff
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive("to_matrix", True, self.num_qubits, massive) return self.primitive.to_matrix() * self.coeff
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive("to_matrix", True, self.num_qubits, massive) unitary = qiskit.quantum_info.Operator(self.to_circuit()).data return unitary * self.coeff
def to_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive("to_matrix", False, self.num_qubits, massive) vec = self.primitive.data * self.coeff return vec if not self.is_measurement else vec.reshape(1, -1)
def to_density_matrix(self, massive: bool = False) -> np.ndarray: OperatorBase._check_massive('to_density_matrix', True, self.num_qubits, massive) return self.primitive.to_operator().data * self.coeff