def one_particle(H: sparse.coo_matrix) -> pyquil.paulis.PauliSum: """ Generates a PauliSum(pyquil) given a Hamiltonian-matrix. Creates a Hamiltonian operator from a (sparse) matrix. This function uses a one-particle formulation and, thus, requires N qubits for an N-dimensional Hilbert space. @author: Axel, Joel :param H: An array (array_like) representing the hamiltonian. :return: Hamiltonian as PyQuil PauliSum. """ # Create the Hamiltonian with a and a^dagger Hamiltonian = FermionOperator() if sparse.issparse(H): H = H.tocoo() for i, j, data in zip(H.row, H.col, H.data): Hamiltonian += data * FermionOperator(((int(i), 1), (int(j), 0))) else: if not isinstance(H, np.ndarray): H = np.asanyarray(H) for i in range(H.shape[0]): for j in range(H.shape[1]): Hamiltonian += H[i, j] * FermionOperator(((i, 1), (j, 0))) Hamiltonian = jordan_wigner(Hamiltonian) Hamiltonian = qubitop_to_pyquilpauli(Hamiltonian) return Hamiltonian
def multi_particle(H: sparse.coo_matrix) -> pyquil.paulis.PauliSum: """ Creates a Qubit-operator from a (sparse) matrix. This function uses (almost) all states and, thus, requires (approximately) log(N) qubits for an N-dimensional Hilbert space. The idea for converting a matrix element to an operator is to raise/lower the qubits differing between two states to convert one basis-state to the other. The qubits that are not negated must be checked to have the correct value (using an analogue of the counting operator) to not get extra terms (one could perhaps allow for extra terms and compensate for them later?). 0 = up 1 = down (1+Zi)/2 checks that qubit i is 0 (up) (1-Zi)/2 checks that qubit i is 1 (down) (Xi+1j*Yi)/2 lowers qubit from 1 (down) to 0 (up) (Xi-1j*Yi)/2 raises qubit from 0 (up) to 1 (down) @author: Joel :param H: An array (array-like) representing the hamiltonian. :return: Hamiltonian as PyQuil PauliSum. """ # Convert to sparse coo_matrix if not sparse.issparse(H): H = sparse.coo_matrix(H) elif H.getformat() != "coo": H = H.tocoo() # The main part of the function H_op = QubitOperator() for i, j, data in zip(H.row, H.col, H.data): new_term = QubitOperator(()) # = I for qubit in range(int.bit_length(H.shape[0] - 1)): if (i ^ j) & (1 << qubit): # lower/raise qubit new_term *= QubitOperator((qubit, "X"), 1 / 2) + \ QubitOperator((qubit, "Y"), 1j * (int( j & (1 << qubit) != 0) - 1 / 2)) else: # check that qubit has correct value (same as i and j) new_term *= QubitOperator((), 1 / 2) + \ QubitOperator((qubit, "Z"), 1 / 2 - int(j & (1 << qubit) != 0)) H_op += data * new_term return qubitop_to_pyquilpauli(H_op)
def compute_transition_matrix(self, knn: sparse.coo_matrix, x: np.ndarray, v: np.ndarray, epsilon: float = 0.0, reverse: bool = False) -> sparse.csr_matrix: """ Compute a right-stochastic matrix representing transition probabilities from each node Args: knn KNN graph (n_cells, n_cells) x Embedding positions (n_cells, n_dims) v Velocities on the embedding (n_cells, n_dims) reverse Compute the reverse transition matrix (for backwards diffusion) Remarks: Computes a Markov transition matrix for the KNN graph. The probability of transition along an edge is proportional to the scalar projection of the velocity vector onto that edge, times the reciprocal of the edge length. Edges that get negative scalar projections are clipped to zero and the total non-zero outgoing edges are normalized to a sum of 1.0. """ # vertices for each edge knn = knn.tocoo() (v0, v1) = (knn.row, knn.col) # calculate edge unit vectors uv = x[v1] - x[ v0] # Vector corresponding to an edge from v0 to v1, shape (n_edges, n_dims) norms = np.linalg.norm(uv, axis=1) uv = uv / norms[:, None] # Convert to unit vector # Project the velocity vectors onto edges, and clip to zero scalar_projection = np.array([a.dot(b) for a, b in zip(v[v0], uv) ]) # Shape: (n_edges) if reverse: scalar_projection = -scalar_projection scalar_projection += epsilon # scalar_projection += scalar_projection.min() np.clip(scalar_projection, a_min=0, a_max=None, out=scalar_projection) # Calculate transition probabilities p = scalar_projection * (1 / norms) tr = normalize(sparse.coo_matrix((p, (v0, v1))).tocsr(), axis=1, norm='l1') return tr