def __init__(self, n_dims, sys_hamiltonian, sys_op, corr): """ Parameters ---------- n_dims : np.ndarray a vector representing the possible n sys_hamiltionian : np.ndarray H_s sys_op : X_s in in H_sb X_s (x) X_b corr : Correlation Correlation caused by X_b """ self.n_dims = n_dims self.k_max = len(n_dims) assert isinstance(corr, Correlation) assert self.k_max == corr.k_max self._q = len(n_dims) self._p = len(n_dims) + 1 self.corr = corr assert sys_op.ndim == 2 assert sys_op.shape == sys_hamiltonian.shape self.n_states = sys_op.shape[0] self.op = np.transpose(sys_op) self.h = np.transpose(sys_hamiltonian) return
def _diff_k(self, k): c_k = self.corr.symm_coeff[k] + 1.0j * self.corr.asymm_coeff[k] numberer = self._numberer(k) raiser = self._raiser(k) lower = self._lower(k) return [ [(self._i, -1.0j / self.hbar * np.transpose(self.op)), (k, lower)], [(self._j, 1.0j / self.hbar * self.op), (k, lower)], [(self._i, -1.0j / self.hbar * c_k * np.transpose(self.op)), (k, raiser @ numberer)], [(self._j, 1.0j / self.hbar * np.conj(c_k) * self.op), (k, raiser @ numberer)], ]
def _orthonormalize(self, use_svd=True): if use_svd and self._trial_vecs: trial_mat = np.transpose(np.array(self._trial_vecs)) trial_mat = orth(trial_mat) self._trial_vecs = list(np.transpose(trial_mat)) elif self._trial_vecs: vecs = [] for vec_i in self._trial_vecs: for vec_j in vecs: vec_i -= vec_j * np.dot(vec_j.conj(), vec_i) norm_ = norm(vec_i) if norm_ > 1.e-7: vecs.append(vec_i / norm_) self._trial_vecs = vecs return self._trial_vecs
def _move_left(mat, mat_prev, _trunc): shape = np.shape(mat) mat = np.reshape( np.transpose(mat, (1, 0, 2)), # mat[i, s, j] (shape[1], shape[0] * shape[2])) # SVD on mat[i, sj] U, S, V = np.linalg.svd(mat, full_matrices=0) # truncated to compress. U, S, V, compress_error = compress_svd(U, S, V, _trunc) mat = np.reshape(V, (-1, shape[0], shape[2])) # V[m, sj] mat = np.transpose(mat, (1, 0, 2)) # mat[s, m, j] US = np.matmul(U, np.diag(S)) mat_prev = np.einsum('rhi,im->rhm', mat_prev, US) return mat, mat_prev
def solve(self, n_state=1, davidson=False): r"""Solve the TISE with the potential energy given. Parameters ---------- n_state : int, optional Number of states to be calculated, sorted by energy from low to high. davidson : bool, optional Whether use Davidson method. Returns ------- energy : [float] eigenstates : np.ndarray """ h_op = self.h_mat() v = self.init_state() if davidson: solver = DavidsonAlgorithm(h_op.dot, [v], n_vals=n_state) self.energy, self.eigenstates = solver.kernel() else: self.energy, v = eigsh(h_op, k=n_state, which='SA', v0=v) self.eigenstates = np.transpose(v) return self.energy, self.eigenstates
def propagator(self, tau=0.1, method='Trotter'): r"""Construct the propagator Parameters ---------- tau : float Time interval at each step. Returns ------- p1 : (n, n) ndarray :math:`e^{-iV\tau/2}` p2 : (n, n) ndarray :math:`e^{-iV\tau}` p3 : (n, n) ndarray :math:`e^{-iT\tau}` """ hbar = self.hbar if 'Trotter' in method: diag, v = scipy.linalg.eigh(self.t_mat()) p3 = np.exp(-1.0j * hbar * tau * diag) p3 = np.dot(v, np.dot(np.diag(p3), np.transpose(v))) p2 = np.exp(-1.0j * hbar * tau * np.diag(self.v_mat())) p2 = np.diag(p2) p1 = np.exp(-1.0j * hbar * tau * np.diag(0.5 * self.v_mat())) p1 = np.diag(p1) return p1, p2, p3
def init_state(self): r"""Form the initial vector according to shape list:: n_0| | |n_p-1 C_0 ... C_p-1 \ | / m_0 \|/ m_p-1 A Returns ------- init : (self.size,) ndarray Formally, init = np.concatenate([C_0, ..., C_p-1, A], axis=None), where C_i is a (n_i * m_i,) ndarray, i <- {0, ..., p-1}, A is a (M,) ndarray, and M = m_0 * ... * m_p-1, m_i < n_i. """ dvr_list = self.dvr_list c_list = [] for i, (_, m_i) in enumerate(self.shape_list[:-1]): _, v_i = dvr_list[i].solve(n_state=m_i) v_i = np.transpose(v_i) c_list.append(np.reshape(v_i, -1)) vec_a = np.zeros(self.size_list[-1]) vec_a[0] = 1.0 vec_list = c_list + [vec_a] init = np.concatenate(vec_list, axis=None) self.vec = init self.update_mod_terms() return init
def _sp_op(self, i, mat, h_list, mod_term, err=1.e-6): if not h_list: return np.zeros((mat.shape)) logging.debug(__('> OP on mat {}...', i)) n, m = mat.shape partial_transform = self._partial_transform a = self.get_sub_vec(-1) a_h = np.conj(a) density = self._partial_product(i, a, a_h) inv_density = linalg.inv(density + np.identity(m) * err) sp = self.get_sub_vec(i) sp_h = np.conj(np.transpose(sp)) projection = np.identity(n) - np.dot(sp, sp_h) tmp = partial_transform(i, a, mat) for mat_j in h_list: tmp = partial_transform(i, tmp, mat_j) for j, mat_j in mod_term: if j != i: tmp = partial_transform(j, tmp, mat_j) tmp = self._partial_product(i, tmp, a_h) ans = np.dot(projection, np.dot(tmp, inv_density)) return ans
def solve(self, n_state=None): r"""Solve the TISE with the potential energy given. Parameters ---------- n_state : int, optional Number of states to be calculated, sorted by energy from low to high. Returns ------- energy : [float] eigenstates : np.ndarray See Also ________ DVR : Definition of all attributes. """ if n_state is None: n_state = self.n - 1 self._h_mat = self.h_mat() self.energy, v = eigsh(self._h_mat, k=n_state, which='SA') # self.energy, v = scipy.linalg.eigh( # self._h_mat, eigvals=(0, n_state - 1)) tmp = np.transpose(v) es = [] for i in tmp: vi = i if i[0] >= 0.0 else -i es.append(vi) self.eigenstates = np.array(es) return self.energy, self.eigenstates
def fine_grain_mps(C, dims, direction, _trunc=False): """Fine-graining of one-site MPS into three site by SVD.:: |st |s |t -i- C -k- = -i- A -m- B -k- Parameters ---------- C : (st, i, k) ndarray A MPS matrix. dims : (int, int) [s, t]. direction : {'>', '<'} '>': move to right; '<' move to left _trunc : int, optional Set m in compress_svd to _trunc. Not compressed if not _trunc. Returns ------- A : (s, i, m) ndarray A MPS matrix. B : (t, m, k) ndarray A MPS matrix. Notes ----- If direction == '>', A is (left-)canonical; if direction == '<', B is (right-)canonical. """ sh = dims + [C.shape[1], C.shape[2]] # [s, t, i, k] mat = np.reshape(C, sh) mat = np.transpose(mat, (0, 2, 1, 3)) # mat[s, i, t, k] mat = np.reshape(mat, (sh[0] * sh[2], sh[1] * sh[3])) # mat[si, tk] U, S, V = np.linalg.svd(mat, full_matrices=0) if _trunc: U, S, V, compress_error = compress_svd(U, S, V, _trunc) if direction == '>': A = U B = np.matmul(np.diag(S), V) # [m, tk] elif direction == '<': A = np.matmul(U, np.diag(S)) B = V A = np.reshape(A, (sh[0], sh[2], -1)) # [s, i, m] B = np.reshape(B, (-1, sh[1], sh[3])) # [m, t, k] B = np.transpose(B, (1, 0, 2)) # [t, m, k] return A, B
def get_ext_wfns(n_states, wfns, op, search_method='krylov'): wfns = np.array(wfns) n_states = np.shape(wfns)[1] space = np.transpose(np.array(wfns)) vecs = np.transpose(np.array(wfns)) assert np.shape(space)[1] <= n_states if search_method == 'krylov': while True: space = linalg.orth(vecs) if np.shape(space)[0] >= n_states: break vecs = list(op @ vecs) np.concatenate((space, vecs), axis=1) psi = space[:, :n_states] return np.transpose(psi) else: raise NotImplementedError
def _diff_ij(self): # delta = self.corr.delta_coeff return [ [(self._i, -1.0j * np.transpose(self.h))], [(self._j, 1.0j * self.h)], # [(self._i, -delta * np.transpose(self.op @ self.op))], # [(self._i, np.sqrt(2.0) * delta * np.transpose(self.op)), # (self._j, np.sqrt(2.0) * delta * self.op)], # [(self._j, -delta * (self.op @ self.op))], ]
def dvr2fbr_mat(self, mat): r"""Transform a matrix from DVR to FBR. Parameters ---------- mat : (n, n) ndarray Returns ------- (n, n) ndarray """ return np.dot(self._u_mat, np.dot(mat, np.transpose(self._u_mat)))
def fbr2dvr_mat(self, mat): r"""Transform a matrix from FBR to DVR. Parameters ---------- mat : (n, n) ndarray Returns ------- (n, n) ndarray """ return np.dot(np.transpose(self._u_mat), np.dot(mat, self._u_mat))
def fbr2dvr_vec(self, vec): r"""Transform a vector from FBR to DVR. Parameters ---------- mat : (n,) ndarray Returns ------- (n,) ndarray """ vec = np.reshape(vec, -1) return np.dot(np.transpose(self._u_mat), vec)
def _calc_ritz_pairs(self): def _trans_vec(vec, basis): new_vec = sum(map(lambda x, y: x * y, vec, basis)) return new_vec n_space = len(self._search_space) n_state = min(n_space, self._n_vals) self._ritz_vals, v = eigh( self._submatrix[:n_space, :n_space], eigvals=(0, n_state - 1) ) v = np.transpose(v) self._get_ritz_vecs = ( lambda: (_trans_vec(v_i, self._search_space) for v_i in v) ) self._get_col_ritz_vecs = ( lambda: (_trans_vec(v_i, self._column_space) for v_i in v) ) return self._ritz_vals, self._get_ritz_vecs
def projector(self, comp=False): """[Deprecated] Return the projector corresponding to self. Returns ------- ans : ndarray """ axis = self.axis if axis is not None: array = self.array shape = self.shape dim = shape.pop(self.axis) comp_dim = np.prod(shape) array = np.moveaxis(array, axis, -1) array = np.reshape(array, (-1, dim)) array_h = np.conj(np.transpose(array)) ans = np.dot(array, array_h) if comp: identity = np.identity(comp_dim) ans = identity - ans ans = np.reshape(ans, shape * 2) return ans else: raise RuntimeError('Need to specific the normalization axis!')
def _diff_ij(self): # delta = self.corr.delta_coeff return [ [(self._i, -1.0j * np.transpose(self.h))], [(self._j, 1.0j * self.h)], ]
def _eval(op, vec): vec_h = np.conj(np.transpose(vec)) mod_op = np.dot(vec_h, np.dot(op, vec)) return mod_op