def getUnitary(ham1, ham2, dt): ''' Unitary operator construction ham1 is Hamiltonian for t = [0,T/2) and ham2 is for t = [T/2,T) ''' U1 = (spsla.expm(-1j * dt * ham1)).toarray() U2 = (spsla.expm(-1j * dt * ham2)).toarray() return np.dot(U2, U1)
def discretize( A, B, F, dT = 1): nx = A.shape[0] Ad = expm(A * dT) M = expm(dT * vstack([hstack([A, eye(nx)]), csc_matrix((nx, 2 * nx))])) integral = M[:nx, nx:] Bd = integral * B Fd = integral * F return Ad, Bd, Fd
def test_expm(B): if B.__class__.__name__[:3] != 'csc': return Bmat = scipy.sparse.csc_matrix(B) C = spla.expm(B) assert C._is_array npt.assert_allclose(C.todense(), spla.expm(Bmat).todense())
def sp_expm(A, sparse=False): """ Sparse matrix exponential. """ if _isdiag(A.indices, A.indptr, A.shape[0]): A.data = np.exp(A.data) return A if sparse: E = spla.expm(A.tocsc()) else: E = spla.expm(A.toarray()) return sp.csr_matrix(E)
def sp_expm(A, sparse=False): """ Sparse matrix exponential. """ if _isdiag(A.indices, A.indptr, A.shape[0]): A = sp.diags(np.exp(A.diagonal()), shape=A.shape, format='csr', dtype=complex) return A if sparse: E = spla.expm(A.tocsc()) else: E = spla.expm(A.toarray()) return sp.csr_matrix(E)
def lti_disc(F, L=None, Q=None, dt=1): ''' LTI_DISC Discretize LTI ODE with Gaussian Noise Syntax: [A,Q] = lti_disc(F,L,Qc,dt) In: F - NxN Feedback matrix L - NxL Noise effect matrix (optional, default identity) Qc - LxL Diagonal Spectral Density (optional, default zeros) dt - Time Step (optional, default 1) Out: A - Transition matrix Q - Discrete Process Covariance Description: Discretize LTI ODE with Gaussian Noise. The original ODE model is in form dx/dt = F x + L w, w ~ N(0,Qc) Result of discretization is the model x[k] = A x[k-1] + q, q ~ N(0,Q) Which can be used for integrating the model exactly over time steps, which are multiples of dt. ''' n = np.shape(F)[0] if L is None: L = np.eye(n) if Q is None: Q = np.zeros((n, n)) # Closed form integration of transition matrix A = expm(F * dt) # Closed form integration of covariance # by matrix fraction decomposition Phi = np.vstack((np.hstack((F, np.dot(np.dot(L, Q), L.T))), np.hstack((np.zeros((n, n)), -F.T)))) AB = np.dot(expm(Phi * dt), np.vstack((np.zeros((n, n)), np.eye(n)))) #Q = AB[:n, :] / AB[n:(2 * n), :] Q = np.linalg.solve(AB[n:(2 * n), :].T, AB[:n, :].T) return A, Q
def lti_disc(F, L=None, Q=None, dt=1): """LTI_DISC Discretize LTI ODE with Gaussian Noise. Syntax: [A,Q] = lti_disc(F,L,Qc,dt) In: F - NxN Feedback matrix L - NxL Noise effect matrix (optional, default identity) Qc - LxL Diagonal Spectral Density (optional, default zeros) dt - Time Step (optional, default 1) Out: A - Transition matrix Q - Discrete Process Covariance Description: Discretize LTI ODE with Gaussian Noise. The original ODE model is in form dx/dt = F x + L w, w ~ N(0,Qc) Result of discretization is the model x[k] = A x[k-1] + q, q ~ N(0,Q) Which can be used for integrating the model exactly over time steps, which are multiples of dt. """ n = np.shape(F)[0] if L is None: L = np.eye(n) if Q is None: Q = np.zeros((n, n)) # Closed form integration of transition matrix A = expm(F * dt) # Closed form integration of covariance # by matrix fraction decomposition Phi = np.vstack((np.hstack( (F, np.dot(np.dot(L, Q), L.T))), np.hstack((np.zeros((n, n)), -F.T)))) AB = np.dot(expm(Phi * dt), np.vstack((np.zeros((n, n)), np.eye(n)))) # Q = AB[:n, :] / AB[n:(2 * n), :] Q = np.linalg.solve(AB[n:(2 * n), :].T, AB[:n, :].T) return A, Q
def Transient_EIEW(x, alpha_start, alpha, Sn, Sn_inv, omega, wis): """ Evaluates the cost function given all parameters. In here, we used the FORTRAN dgem-functions instead of @ for efficient matrix multiplication. """ N = x.shape[0] m = alpha.shape[1] P_alpha_F = alpha_start cost = omega * np.sum(x) # cost of clients already entered (only waiting time) for i in range(1, wis + 1): cost += (omega - 1) * np.sum( dgemm(1, P_alpha_F, Sn_inv[0:i * m, 0:i * m])) F = 1 - np.sum(P_alpha_F) P_alpha_F = np.hstack((np.matrix(P_alpha_F), alpha * F)) # cost of clients to be scheduled for i in range(wis + 1, N + wis + 1): exp_Si = expm(Sn[0:i * m, 0:i * m] * x[i - wis - 1]) cost += float( dgemv(1, dgemm(1, P_alpha_F, Sn_inv[0:i * m, 0:i * m]), np.sum(omega * np.eye(i * m) - exp_Si, 1))) P = dgemm(1, P_alpha_F, exp_Si) F = 1 - np.sum(P) P_alpha_F = np.hstack((np.matrix(P), alpha * F)) return cost
def expm_affine_2D(A_and_T): """ Assumes, but doesn't check, that A.shape = (3,3) """ # need_to_return = False A,T=A_and_T A2x2 = A[:2,:2] det_A2x2 = A[0,0]*A[1,1]-A[0,1]*A[1,0] if det_A2x2: inv_A2x2_00=A2x2[1,1] / det_A2x2 inv_A2x2_11=A2x2[0,0] / det_A2x2 inv_A2x2_01=-A2x2[0,1] / det_A2x2 inv_A2x2_10=-A2x2[1,0] / det_A2x2 T[-1]=0,0,1 _expm_2x2(A2x2,T[:2,:2]) if 0: T[:2,2]=(T[:2,:2]-_eye2).dot( inv_A2x2).dot(A[:2,2]) else: a = inv_A2x2_00*A[0,2]+inv_A2x2_01*A[1,2] b = inv_A2x2_10*A[0,2]+inv_A2x2_11*A[1,2] T[0,2] = (T[0,0]-1)*a + (T[0,1] )*b T[1,2] = (T[1,0] )*a + (T[1,1]-1)*b else: # I didn't work out this case yet, so default to expm T[:]=expm(A)
def test_simulate_overlapping_number_and_hopping_terms(self): hamiltonian = (0.37 * FermionOperator('1^ 0^ 1 0') + FermionOperator('2^ 0') + FermionOperator('0^ 2')) projectq.ops.All(projectq.ops.H) | self.register _low_depth_trotter_simulation.simulate_dual_basis_evolution( self.register, hamiltonian, trotter_steps=2, first_order=False) self.engine.flush() # get_sparse_operator reverses the indices, so reverse the sites # the Hamiltonian acts on so as to compare them. reversed_operator = (0.37 * FermionOperator('3^ 2^ 3 2') + FermionOperator('3^ 1') + FermionOperator('1^ 3')) evol_matrix = expm(-1j * get_sparse_operator( reversed_operator, n_qubits=self.size)).todense() expected = evol_matrix * numpy.matrix( [2**(-self.size / 2.)] * 2**self.size).T self.assertTrue( numpy.allclose(ordered_wavefunction(self.engine), expected.T, atol=1e-2), msg=str( numpy.array(ordered_wavefunction(self.engine) - expected.T)))
def __init__(self, H, dt): # Assert(isinstance(H, Hamiltonian) or isinstance( # H, HamiltonianL), "H is not Hamiltonian") Assert(isinstance(dt, (int, float)), "dt is not numeric") Assert(dt > 0, "dt <= 0") # H_data = np.array(H.matrix.data, dtype=np.complex128) # self.data = np.matrix(lg.expm(-1j * H_data * dt), dtype=np.complex128) # print(type(H.matrix.data)) # print(type(H.data)) data = lg.expm(-1j * csc_matrix(H.data) * dt) # print(type(data)) data = csc_matrix(data, dtype=np.complex128) # self.data = lg.expm(-1j * H.data * dt) # self.data = lg.expm(-1j * H.data.data * dt) # print(np.shape(self.data)) # self.data = csc_matrix(self.data, dtype=np.complex128) super(Unitary, self).__init__(m=H.size, n=H.size, dtype=np.complex128, data=data) self.check_unitarity()
def test_lie_algebra_evolution(circuit, hamiltonian): """Test that the optimizer produces the correct unitary to append.""" # pylint: disable=no-member nqubits = max([max(ps.wires) for ps in hamiltonian.ops]) + 1 wires = range(nqubits) dev = qml.device("default.qubit", wires=nqubits) @qml.qnode(dev) def get_state(): circuit() return qml.state() @qml.qnode(dev) def lie_circuit(): circuit() return qml.expval(hamiltonian) phi = get_state() rho = np.outer(phi, phi.conj()) hamiltonian_np = qml.utils.sparse_hamiltonian(hamiltonian, wires).toarray() lie_algebra_np = hamiltonian_np @ rho - rho @ hamiltonian_np phi_exact = expm(-0.001 * lie_algebra_np) @ phi rho_exact = np.outer(phi_exact, phi_exact.conj()) opt = LieAlgebraOptimizer(circuit=lie_circuit, stepsize=0.001, exact=True) opt.step() cost_pl = opt.circuit() cost_exact = np.trace(rho_exact @ hamiltonian_np) assert np.allclose(cost_pl, cost_exact, atol=1e-2)
def hamiltonian2cell_tensor(h, tau, way='shift'): # h has to be a two-body hamiltonian at least """ The indexes of the out put tensor are ordered as: 1 | 0 - T - 3 | 2 :param h: :param tau: :param way: :return: """ dd = h.shape[0] d = round(dd**0.5) if way is 'shift': h = np.eye(dd) - tau * h else: h = la.expm(-tau * h) h = h.reshape(d, d, d, d) tmp = h.transpose(1, 3, 2, 4).reshape(dd, dd) vl, lm, vr = np.linalg.svd(tmp) lm = np.diag(lm**0.5) vl = vl.dot(lm).reshape(d, d, dd) vr = lm.dot(vr).reshape(dd, d, d) tensor = cont([h, vr, vl], [[1, 2, -4, -5], [-2, 1, -1], [-6, -3, 2]]) tensor = tensor.reshape(dd, dd, dd, dd) return tensor
def test_padecases_dtype(self): for dtype in [np.float32, np.float64, np.complex64, np.complex128]: # test double-precision cases for scale in [1e-2, 1e-1, 5e-1, 1, 10]: a = scale * identity(3, dtype=dtype) e = exp(scale) * identity(3, dtype=dtype) assert_array_almost_equal_nulp(expm(a), e, nulp=100)
def test_padecases_dtype(self): for dtype in [np.float32, np.float64, np.complex64, np.complex128]: # test double-precision cases for scale in [1e-2, 1e-1, 5e-1, 1, 10]: a = scale * eye(3, dtype=dtype) e = exp(scale) * eye(3, dtype=dtype) assert_array_almost_equal_nulp(expm(a), e, nulp=100)
def __init__(self, n_steps, time_segment, initial_state, n_directions, seed_initial_state=None, initiate_target_state=True, **other_params): # self.system defined in subclass, as they have different # store_gates values depending self.n_steps = n_steps self.time_segment = time_segment self.unitary_evolution = \ expm(-1j * self.time_segment * self.system.hamiltonian) self.set_initial_state(seed_initial_state, initial_state, initiate_target_state) # use single-qubit gates in one (z-only) or two (z and x) directions self.n_directions = n_directions self.action_sequence = None self.state_sequence = None self.lastaction = None self.s = None
def init_matrices(self): 'initialize the one-step basis and input effects matrices' dims = self.dims Timers.tic('expm') self.one_step_matrix_exp = expm(self.a_csc * self.time_elapser.step_size) Timers.toc('expm') Timers.tic('toarray') self.one_step_matrix_exp = self.one_step_matrix_exp.toarray() Timers.toc('toarray') if self.b_csc is not None: self.one_step_input_effects_matrix = np.zeros(self.b_csc.shape, dtype=float) for c in range(self.time_elapser.inputs): # create the a_matrix augmented with a column of the b_matrix as an affine term indptr = self.b_csc.indptr data = np.concatenate((self.a_csc.data, self. b_csc.data[indptr[c]:indptr[c+1]])) indices = np.concatenate((self.a_csc.indices, self.b_csc.indices[indptr[c]:indptr[c+1]])) indptr = np.concatenate((self.a_csc.indptr, [len(data)])) aug_a_csc = csc_matrix((data, indices, indptr), shape=(dims + 1, dims + 1)) mat = aug_a_csc * self.time_elapser.step_size # the last column of matrix_exp is the same as multiplying it by the initial state [0, 0, ..., 1] init_state = np.zeros(dims + 1, dtype=float) init_state[dims] = 1.0 col = expm_multiply(mat, init_state) self.one_step_input_effects_matrix[:, c] = col[:dims]
def test_simulate_dual_basis_hamiltonian(self): hamiltonian = dual_basis_hamiltonian(1, self.size) self.engine.flush() # Choose random state. initial_state = numpy.zeros(2**self.size, dtype=complex) for i in range(len(initial_state)): initial_state[i] = (random.random() * numpy.exp(1j * 2 * numpy.pi * random.random())) initial_state /= numpy.linalg.norm(initial_state) # Put randomly chosen state in the registers. self.engine.backend.set_wavefunction(initial_state, self.register) _low_depth_trotter_simulation.simulate_dual_basis_evolution( self.register, hamiltonian, trotter_steps=7, first_order=False) self.engine.flush() # get_sparse_operator reverses the indices, but the jellium # Hamiltonian is symmetric. evol_matrix = expm( -1j * get_sparse_operator(hamiltonian, n_qubits=self.size)).todense() initial_state = numpy.matrix(initial_state).T expected = evol_matrix * initial_state self.assertTrue( numpy.allclose(ordered_wavefunction(self.engine), expected.T, atol=1e-2), msg=str( numpy.array(ordered_wavefunction(self.engine) - expected.T)))
def minimalControlEnergy(adjacencyMatrix, WcI, x0, xf, T, normalise=True): ''' Aim: Calculate minimal control energy to transition between states, using the whole brain as control matrix Inputs: adjacencyMatrix: the structural matrix (N,N) as np.array WcI: the gramian inverse for control horizon T as a n (N,N) matrix x0: the initial state as a vector (N,1) xf: the final state as a vector (N,1) T: the control time horizon Output: the minimal control energy needed to transition Details: Adapted from matlab code by Cornblath et al. Nature Comms Biology 2020, repository: https://github.com/ejcorn/brain_states/ ''' # Normalise if not already done if normalise==True: adjacencyMatrix = adjacencyMatrix / (np.full((adjacencyMatrix.shape), fill_value= sla.eigs(adjacencyMatrix)[0][0] + 1)) # System size n = adjacencyMatrix.shape[0] # State transition to achieve exponentialMatrix = sla.expm(adjacencyMatrix*T) Phi = np.dot(exponentialMatrix, x0) - xf # Calculate energy needed to transition E = np.sum(np.multiply(np.dot(WcI,Phi),(Phi))) return(E)
def c2s(self, a, b, dt): """ Convert a continuous state space model in a discrete one Parameters: ----------- a : ndarray The continuous state space A matrix b : ndarray The continuous state space B matrix dt: float The discrete model sampling time Returns: -------- ad, bd : the discrete state space A and B matrices """ em_upper = sparse.hstack((a, b)) em_lower = sparse.hstack((sparse.csr_matrix((b.shape[1], a.shape[0])), sparse.csr_matrix((b.shape[1], b.shape[1])))) em = sparse.vstack((em_upper, em_lower)).tocsc() ms = slinalg.expm(dt * em) ms = ms[:a.shape[0], :] ad = ms[:, 0:a.shape[1]] bd = ms[:, a.shape[1]:] return ad.tocsr(), bd.toarray()
def calc_trajectory(self, pa_space, pat, pts, dt, nTimeSteps, nStepsODEsolver=100, mysign=1): """ Returns: trajectories trajectories.shape = (nTimeSteps,nPts,pa_space.dim_domain) """ if pts.ndim != 2: raise ValueError(pts.shape) if pts.shape[1] != pa_space.dim_domain: raise ValueError(pts.shape) x, y = pts.T x_old = x.copy() y_old = y.copy() nPts = x_old.size history_x = np.zeros((nTimeSteps, nPts), dtype=self.my_dtype) history_y = np.zeros_like(history_x) history_x.fill(np.nan) history_y.fill(np.nan) afs = pat.affine_flows As = mysign * np.asarray([c.A for c in afs]).astype(self.my_dtype) Trels = np.asarray([expm(dt * c.A * mysign) for c in afs]) xmins = np.asarray([c.xmins for c in afs]).astype(self.my_dtype) xmaxs = np.asarray([c.xmaxs for c in afs]).astype(self.my_dtype) xmins[xmins <= self.XMINS] = -self._LargeNumber xmaxs[xmaxs >= self.XMAXS] = +self._LargeNumber if pa_space.has_GPU == False or self.use_GPU_if_possible == False: Warning("Not using GPU!") raise NotImplementedError else: pts_at_0 = np.zeros((nPts, pa_space.dim_domain)) pts_at_0[:, 0] = x_old.ravel() pts_at_0[:, 1] = y_old.ravel() trajectories = pa_space._calcs_gpu.calc_trajectory( xmins, xmaxs, Trels, As, pts_at_0, dt, nTimeSteps, nStepsODEsolver) # add the starting points trajectories = np.vstack([pts_at_0, trajectories]) # reshaping trajectories = trajectories.reshape(1 + nTimeSteps, nPts, pa_space.dim_domain) return trajectories
def test_padecases_dtype_sparse(self): # float32 and complex64 lead to errors in spsolve/UMFpack for dtype in [np.float64, np.complex128]: # test double-precision cases for scale in [1e-2, 1e-1, 5e-1, 1, 10]: a = scale * speye(3, 3, dtype=dtype, format='csc') e = exp(scale) * eye(3, dtype=dtype) assert_array_almost_equal_nulp(expm(a).toarray(), e, nulp=100)
def test_padecases_dtype_sparse(self): # float32 and complex64 lead to errors in spsolve/UMFpack for dtype in [np.float64, np.complex128]: # test double-precision cases for scale in [1e-2, 1e-1, 5e-1, 1, 10]: a = scale * speye(3, 3, dtype=dtype, format='csc') e = exp(scale) * identity(3, dtype=dtype) assert_array_almost_equal_nulp(expm(a).toarray(), e, nulp=100)
def discretize(self, delta=None): delta = delta or 1.0 A = expm(self.transition_matrix * delta) Q = self.Pinf - A @ self.Pinf @ A.T H = self.observation_matrix m_0 = np.zeros((A.shape[0], 1)) P_0 = self.Pinf return A, Q, H, m_0, P_0
def _log_target_tau(self, tau, S, phi, sigma2, tau_mu0, tau_si0): """ Calculates target density for MH. """ if S is None: S = expm(tau * self.data.W) Omega_tilde = S.T @ S / sigma2 lt = - phi.T @ Omega_tilde @ phi / 2 \ - (tau - tau_mu0)**2 / 2 / tau_si0**2 return lt, S
def generator(x: List[float]): # Must provide imports in the function! from scipy.sparse.linalg import expm from openfermion.ops import QubitOperator from openfermion.transforms import get_sparse_operator qop = QubitOperator('X0 Y1') - QubitOperator('Y0 X1') qubit_sparse = get_sparse_operator(qop) return expm(0.5j * x[0] * qubit_sparse).todense()
def coherent(N, alpha): """Generates a coherent state with eigenvalue alpha. Constructed using displacement operator on vacuum state. Modified from Qutip. Parameters ---------- N : int Number of Fock states in Hilbert space. alpha : float/complex Eigenvalue of coherent state. offset : int (default 0) The lowest number state that is included in the finite number state representation of the state. Using a non-zero offset will make the default method 'analytic'. method : string {'operator', 'analytic'} Method for generating coherent state. Returns ------- state : qobj Qobj quantum object for coherent state Examples -------- >>> coherent(5,0.25j) Quantum object: dims = [[5], [1]], shape = [5, 1], type = ket Qobj data = [[ 9.69233235e-01+0.j ] [ 0.00000000e+00+0.24230831j] [ -4.28344935e-02+0.j ] [ 0.00000000e+00-0.00618204j] [ 7.80904967e-04+0.j ]] Notes ----- Select method 'operator' (default) or 'analytic'. With the 'operator' method, the coherent state is generated by displacing the vacuum state using the displacement operator defined in the truncated Hilbert space of size 'N'. This method guarantees that the resulting state is normalized. With 'analytic' method the coherent state is generated using the analytical formula for the coherent state coefficients in the Fock basis. This method does not guarantee that the state is normalized if truncated to a small number of Fock states, but would in that case give more accurate coefficients. """ x = basis(N, 0) a = destroy(N) D = la.expm(alpha * dag(a) - np.conj(alpha) * a) return D @ x
def generate(self, fixed, random, mess): """ Generates synthetic data. """ #Fixed parameters if fixed: beta = np.array([0.25, -0.25, 0.25, -0.25]) n_fix = beta.shape[0] x_fix = -3 + 6 * np.random.rand(self.N, n_fix) psi_fix = x_fix @ beta else: x_fix = None psi_fix = 0 #Random parameters if random: gamma_mu = np.array([0.25, -0.25, 0.25, -0.25]) n_rnd = gamma_mu.shape[0] gamma_sd = np.sqrt(0.5 * np.abs(gamma_mu)) gamma_corr = 0.4 * np.array([[0, 1, 0, 1], [1, 0, 0, 0], [0, 0, 0, 1], [1, 0, 1, 0] ]) + np.eye(n_rnd) gamma_cov = np.diag(gamma_sd) @ gamma_corr @ np.diag(gamma_sd) gamma_ch = np.linalg.cholesky(gamma_cov) gamma = gamma_mu.reshape(1,n_rnd) \ + (gamma_ch @ np.random.randn(n_rnd, self.N)).T x_rnd = -3 + 6 * np.random.rand(self.N, n_rnd) x_rnd[:, 0] = 1 psi_rnd = np.sum(x_rnd * gamma, axis=1) else: x_rnd = None psi_rnd = 0 #Spatial error if mess: tau = -0.9 W = self._draw_W_matrix() S = expm(tau * W) sigma = 0.3 eps = sigma * np.random.randn(self.N) phi = np.linalg.solve(S, eps) else: W = None phi = 0 #Link function psi = psi_fix + psi_rnd + phi #Success rate r = 6.0 #Generate synthetic observations p_rng = 1 / (1 + np.exp(psi)) y = np.random.negative_binomial(r, p_rng) #Create data object data = Data(y, x_fix, x_rnd, W) return data
def __init__(self, network_file): """ Input: kernel_file - a tab-delimited matrix file with both a header and first-row labels, in the same order. """ # might have multiple kernels here self.labels = {} self.ncols = {} self.nrows = {} # parse the network, build the graph laplacian edges, nodes, node_out_degrees = self.parseNet(network_file) num_nodes = len(nodes) node_order = list(nodes) index2node = {} node2index = {} for i in range(0, num_nodes): index2node[i] = node_order[i] node2index[node_order[i]] = i # construct the diagonals row = array('i') col = array('i') data = array('f') for i in range(0, num_nodes): # diag entries: out degree degree = 0 if index2node[i] in node_out_degrees: degree = node_out_degrees[index2node[i]] # append to the end data.insert(len(data), degree) row.insert(len(row), i) col.insert(len(col), i) # add edges for i in range(0, num_nodes): for j in range(0, num_nodes): if i == j: continue if (index2node[i], index2node[j]) not in edges: continue # append index to i-th row, j-th column row.insert(len(row), i) col.insert(len(col), j) # -1 for laplacian edges data.insert(len(data), -1) # graph laplacian L = coo_matrix((data, (row, col)), shape=(num_nodes, num_nodes)).tocsc() time_T = -0.1 self.laplacian = L self.index2node = index2node self.kernel = expm(time_T * L) self.labels = node_order
def to_discrete_time_mat(a_mat, b_mat, dt, quick=False): 'convert an a and b matrix to a discrete time version' rv_a = None rv_b = None if quick: if not isinstance(a_mat, np.ndarray): a_mat = np.array(a_mat, dtype=float) rv_a = np.identity(a_mat.shape[0], dtype=float) + a_mat * dt if b_mat is not None: if not isinstance(b_mat, np.ndarray): b_mat = np.array(b_mat, dtype=float) rv_b = b_mat * dt else: # first convert both to csc matrices a_mat = csc_matrix(a_mat, dtype=float) dims = a_mat.shape[0] rv_a = expm(a_mat * dt) rv_a = rv_a.toarray() if b_mat is not None: b_mat = csc_matrix(b_mat, dtype=float) rv_b = np.zeros(b_mat.shape, dtype=float) inputs = b_mat.shape[1] for c in range(inputs): # create the a_matrix augmented with a column of the b_matrix as an affine term indptr = b_mat.indptr data = np.concatenate( (a_mat.data, b_mat.data[indptr[c]:indptr[c + 1]])) indices = np.concatenate( (a_mat.indices, b_mat.indices[indptr[c]:indptr[c + 1]])) indptr = np.concatenate((a_mat.indptr, [len(data)])) aug_a_csc = csc_matrix((data, indices, indptr), shape=(dims + 1, dims + 1)) mat = aug_a_csc * dt # the last column of matrix_exp is the same as multiplying it by the initial state [0, 0, ..., 1] init_state = np.zeros(dims + 1, dtype=float) init_state[dims] = 1.0 col = expm_multiply(mat, init_state) rv_b[:, c] = col[:dims] return rv_a, rv_b
def cumulant_generating_function(self, chi): W = self.hm_chi(chi).tocsc() ss = spla.eigs(W, k=1, sigma=0, which='LM', maxiter=1000, v0=self.init_ss_vector)[1] #ss = spla.svds(W, k=1, which='SM', maxiter=10000, v0=self.init_ss_vector)[0] ss /= np.trace(self.hs.extract_system_density_matrix(ss)) dv_pops = np.zeros(4 * self.hs.number_density_matrices()) dv_pops[:4] = np.array([1., 0, 0, 1.]) #ss = utils.stationary_state_svd(W.todense(), dv_pops) return np.log(dv_pops.dot(spla.expm(W.multiply(self.dt)).dot(ss)))
def ansatz(q: qreg, x: List[float]): X(q[0]) with decompose(q, kak) as u: from scipy.sparse.linalg import expm from openfermion.ops import QubitOperator from openfermion.transforms import get_sparse_operator qop = QubitOperator('X0 Y1') - QubitOperator('Y0 X1') qubit_sparse = get_sparse_operator(qop) u = expm(0.5j * x[0] * qubit_sparse).todense()
def plot_entropy_time_evo_lin(spin, N, h, c, phi, start_time, end_start, points): """ This function plots the time evolution of von Neuman entropy over a linear time axis. Args: "spin" is the spin of the individual particles "N" is the system size "h" is the strength of the pseudo-random field "c" is the angular frequency of the field "phi" is the phase shift "start_time" is the first point in the plot, in time "end_start" is the last point in the plot, in time "points" is the number points to plot Returns: "imbalance_plot" is a list of values to be plotted. "error" is the status of the state choosing function that is called from this function. If "error" is True, then no state of a zero total <Sz> with an energy density could be found for the current configuration. """ D = int(2 * spin + 1) ** N Sx, Sy, Sz = qm.init(spin) entropy_plot = np.zeros(points) delta_t = (end_start - start_time) / (points - 1) # The spin 0 block of H H = aubryH.blk_full(N, h, c, 0, phi).tocsc() E, V = np.linalg.eigh(H.toarray()) psi, error = aubryC.get_state_blk(H, N) # psi = psi.toarray() if not error: # Plot the first point which requires a special kind of time evolution. psi = expm_multiply(-1j * H * start_time, psi) # psi = aubryC.time_evo_exact_diag(E, V, psi, start_time) # psi = lil_matrix(psi) # psi in the full spin basis psi_long = aubryC.recast(N, psi) psi_tz = aubryC.spin2z(D, N, psi_long) # psi in the total Sz basis entropy_plot[0] += qm.get_vn_entropy(psi_tz, spin, N, mode='eqsplit') U = expm(-1j * H * delta_t) psi_time_evolved = psi # Plot the rest of the points. for plot_point in range(1, points): psi_time_evolved = U * psi_time_evolved # psi_time_evolved = aubryC.time_evo_exact_diag(E, V, psi_time_evolved ,delta_t) # psi_time_evolved = lil_matrix(psi_time_evolved) # Rewrite the time evolved state in the total Sz basis # before passing it onto the entropy function. psi_tevo_long = aubryC.recast(N, psi_time_evolved) psi_time_evolved_tz = aubryC.spin2z(D, N, psi_tevo_long) entropy_plot[plot_point] = qm.get_vn_entropy(psi_time_evolved_tz, spin, N, mode='eqsplit') return entropy_plot, error
def __init__(self, network_file): """ Input: kernel_file - a tab-delimited matrix file with both a header and first-row labels, in the same order. """ # might have multiple kernels here self.labels = {} self.ncols = {} self.nrows = {} # parse the network, build the graph laplacian edges, nodes, node_out_degrees = self.parseNet(network_file) num_nodes = len(nodes) node_order = list(nodes) index2node = {} node2index = {} for i in range(0, num_nodes): index2node[i] = node_order[i] node2index[node_order[i]] = i # construct the diagonals row = array('i') col = array('i') data = array('f') for i in range(0, num_nodes): # diag entries: out degree degree = 0 if index2node[i] in node_out_degrees: degree = node_out_degrees[index2node[i]] # append to the end data.insert(len(data), degree) row.insert(len(row), i) col.insert(len(col), i) # add edges for i in range(0, num_nodes): for j in range(0, num_nodes): if i == j: continue if (index2node[i], index2node[j]) not in edges: continue # append index to i-th row, j-th column row.insert(len(row), i) col.insert(len(col), j) # -1 for laplacian edges data.insert(len(data), -1) # graph laplacian L = coo_matrix((data,(row, col)), shape=(num_nodes,num_nodes)).tocsc() time_T = -0.1 self.laplacian = L self.index2node = index2node self.kernel = expm(time_T*L) self.labels = node_order
def subgraph_centrality(graph, weights=True, normalize="max_centrality"): ''' Subgraph centrality, accordign to [Estrada2005], for each node in the graph. **[Estrada2005]:** Ernesto Estrada and Juan A. Rodríguez-Velázquez, Subgraph centrality in complex networks, PHYSICAL REVIEW E 71, 056103 (2005), `available on ArXiv <http://www.arxiv.org/pdf/cond-mat/0504730>`_. Parameters ---------- graph : :class:`~nngt.Graph` or subclass Network to analyze. weights : bool or string, optional (default: True) Whether weights should be taken into account; if True, then connections are weighed by their synaptic strength, if False, then a binary matrix is returned, if `weights` is a string, then the ponderation is the correponding value of the edge attribute (e.g. "distance" will return an adjacency matrix where each connection is multiplied by its length). normalize : str, optional (default: "max_centrality") Whether the centrality should be normalized. Accepted normalizations are "max_eigenvalue" and "max_centrality"; the first rescales the adjacency matrix by the its largest eigenvalue before taking the exponential, the second sets the maximum centrality to one. Returns ------- centralities : :class:`numpy.ndarray` The subgraph centrality of each node. ''' adj_mat = graph.adjacency_matrix(types=False, weights=weights) centralities = None if normalize == "max_centrality": centralities = spl.expm(adj_mat / adj_mat.max()).diagonal() centralities /= centralities.max() elif normalize == "max_eigenvalue": norm, _ = spl.eigs(adj_mat, k=1) centralities = spl.expm(adj_mat / norm).diagonal() else: raise InvalidArgument('`normalize` should be either False, "eigenmax",' ' or "centralmax".') return centralities
def expm(A, herm=False): """Matrix exponential, can be accelerated if explicitly hermitian. Parameters ---------- A : dense or sparse operator Operator to exponentiate. herm : bool, optional If True (not default), and ``A`` is dense, digonalize the matrix in order to perform the exponential. """ if issparse(A): # convert to and from csc to suppress scipy warning return spla.expm(A.tocsc()).tocsr() elif not herm: return qarray(spla.expm(A)) else: evals, evecs = eigh(A) return evecs @ ldmul(np.exp(evals), dag(evecs))
def test_logm_consistency(self): random.seed(1234) for dtype in [np.float32, np.float64, np.complex64, np.complex128]: for n in range(1, 10): for scale in [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2]: # make logm(a) be of a given scale a = (eye(n) + random.rand(n, n) * scale).astype(dtype) if np.iscomplexobj(a): a = a + 1j * random.rand(n, n) * scale assert_array_almost_equal(expm(logm(a)), a)
def test_logm_consistency(self): random.seed(1234) for dtype in [np.float32, np.float64, np.complex64, np.complex128]: for n in range(1, 10): for scale in [1e-4, 1e-3, 1e-2, 1e-1, 1, 1e1, 1e2]: # make logm(a) be of a given scale a = (identity(n) + random.rand(n, n) * scale).astype(dtype) if np.iscomplexobj(a): a = a + 1j * random.rand(n, n) * scale assert_array_almost_equal(expm(logm(a)), a)
def plot_imbalance(Sz,N,time_range,sample_size): init_delta_t,r = get_init_delta_t() H,E,psi = get_random_state(Sx,Sy,Sz,spin,N,h,mode='expm',seed=True) imbalance_plot = np.zeros(sample_size) psi_Szs = np.empty(N,dtype=object) full_Szs = np.empty(N,dtype=object) # Plot the first point which does not require time evolution. for k in range(N): Sz_full_k = get_full_matrix(Sz,k,N) psi_Sz = psi.transpose().conjugate().dot(Sz_full_k) full_Szs[k] = Sz_full_k.copy() psi_Szs[k] = psi_Sz.copy() imbalance_plot[0] += np.real(psi_Sz.dot(Sz_full_k.dot(psi))[0,0]) # Plot the second point which requires the first time evolution. current_delta_t = init_delta_t U_delta_t = expm(-1j*H*current_delta_t) U_delta_t_dag = U_delta_t.transpose().conjugate() psi_time_evolved = U_delta_t.dot(psi) for k in range(N): psi_Szs[k] = psi_Szs[k].dot(U_delta_t_dag) imbalance_plot[1] += np.real(psi_Szs[k].dot( full_Szs[k].dot( psi_time_evolved))[0,0]) # Plot the rest of the points with time evolution. for plot_point in range(2,sample_size): delta_delta_t = get_delta_delta_t(plot_point,r) current_delta_t += delta_delta_t U_delta_t = expm(-1j*H*current_delta_t) U_delta_t_dag = U_delta_t.transpose().conjugate() psi_time_evolved = U_delta_t.dot(psi_time_evolved) for k in range(N): psi_Szs[k] = psi_Szs[k].dot(U_delta_t_dag) imbalance_plot[plot_point] += np.real(psi_Szs[k].dot( full_Szs[k].dot( psi_time_evolved))[0,0]) return 4/N*imbalance_plot
def gen_model (self): # Hamiltonian if isfile(self.ham_path): print('Importing Hamiltonian...') H = sio.mmread(self.ham_path).tocsc() else: print('Building Hamiltonian...') H = sum ([(self.N2(k) + self.N3(k)) for k in range(2, self.L-2)]) for matlistb in self.boundary_terms_gen(self.L): matlistb = [OPS[key] for key in matlistb] H = H + spmatkron(matlistb) self.ham = H # Propogator if isfile(self.prop_path): print('Importing propagator...') U0 = np.fromfile (self.prop_path) U_dim = 2**(self.L) U0 = ( U0[0:len(U0)-1:2] + 1j*U0[1:len(U0):2] ).reshape((U_dim,U_dim)) else: print('Building propagator...') U0 = spsla.expm(-1j*self.dt*H).todense() self.prop = np.asarray(U0)
expm_eff = ExpmEff(nC=nC,use_parallel=use_parallel) print 'As.shape',As.shape tic = time.clock() expm_eff.calc(As,Ts) toc = time.clock() print 'time (calc):' ,toc-tic # print np.abs(Ts[:,0,0]).min() # To check we already got the result sanity_check = True and 0 if sanity_check: Ts2=np.zeros_like(Ts) tic = time.clock() for i in range(nC): Ts2[i]=expm(As[i]) toc = time.clock() print 'time (simple serial):' ,toc-tic print 'results are the same:', np.allclose(Ts2,Ts) if As.shape[1]==3: Ts3=np.zeros_like(Ts) tic = time.clock() expm_eff.calc_scipy_parallel(As,Ts3) toc = time.clock() print 'time (calc_scipy_parallel):' ,toc-tic print 'results are the same:', np.allclose(Ts3,Ts) if As.shape[1]==5: Ts4=np.zeros_like(Ts) tic = time.clock()
def plot_imbalance_time_evo_log(spin, N, h, c, phi, time_range_lower_lim, time_range_upper_lim, sample_size): """ This function plots the time evolution of spin imbalance Σ<psi|Sz(0)Sz(t)|psi> over a logarithmic time axis. Args: "spin" is the spin of the individual particles "N" is the system size "h" is the strength of the pseudo-random field "c" is the angular frequency of the field "phi" is the phase shift "time_range_lower_lim" is the first point in the plot, in time "time_range_upper_lim" is the last point in the plot, in time "sample_size" is the number points to plot Returns: "imbalance_plot" is a list of values to be plotted. "error" is the status of the state choosing function that is called from this function. If "error" is True, then no state of a zero total <Sz> with an energy density could be found for the current configuration. """ Sx, Sy, Sz = qm.init(spin) D = 2**N H = aubryH.blk_full(N, h, c, 0, phi).tocsc() psi, error = aubryC.get_state_blk(H, N) # So in a nutshell, the following process is all carried out in the # block spin basis. The Pauli Sz spin operator is rearranged into # the block spin basis and only the center block (spin 0 block) is # sliced out and kept. Everything else happens as usual. if not error: imbalance_plot = np.zeros(sample_size) psi_Szs = np.empty(N, dtype=object) full_Szs = np.empty(N, dtype=object) ctr_blk_sz = H.get_shape()[0] shift = int(round(0.5 * (D - ctr_blk_sz))) # Plot the first point which requires a different kind of time # evolution and set up the rest of the calculations by storing # all the Sz operators and the <psi|Sz(0) row vectors. U_delta_t_0 = expm(-1j * H * time_range_lower_lim) U_delta_t_dag_0 = U_delta_t_0.transpose().conjugate() psi_tevo = U_delta_t_0.dot(psi) for k in range(N): Sz_full_k = qm.get_full_matrix(Sz, k, N) # Rewrite Sz_full_k into the block Hamiltonian spin basis. Sz_full_k_sb = aubryC.Sz2spin_basis(N, Sz_full_k) # Slice out the center block which is the only part that matters. Sz_full_k_sb = Sz_full_k_sb[shift:shift + ctr_blk_sz, shift:shift + ctr_blk_sz] psi_Sz = psi.transpose().conjugate().dot(Sz_full_k_sb) psi_Sz_tevo = psi_Sz.dot(U_delta_t_dag_0) full_Szs[k] = Sz_full_k_sb.copy() psi_Szs[k] = psi_Sz_tevo.copy() imbalance_plot[0] += np.real(psi_Sz_tevo.dot( Sz_full_k_sb.dot(psi_tevo))[0, 0]) # Plot the rest of the points with time evolution. for plot_point in range(1, sample_size): if plot_point == 1: current_delta_t, r = qm.get_init_delta_t(time_range_lower_lim, time_range_upper_lim, sample_size) elif plot_point > 1: delta_delta_t = qm.get_delta_delta_t(time_range_lower_lim, plot_point, r) current_delta_t += delta_delta_t U_delta_t = expm(-1j * H * current_delta_t) U_delta_t_dag = U_delta_t.transpose().conjugate() psi_tevo = U_delta_t.dot(psi_tevo) for k in range(N): psi_Szs[k] = psi_Szs[k].dot(U_delta_t_dag) imbalance_plot[plot_point] += np.real(psi_Szs[k].dot( full_Szs[k].dot( psi_tevo))[0, 0]) return 4 / N * imbalance_plot, error
def test_zero_sparse(self): a = csc_matrix([[0.,0],[0,0]]) assert_array_almost_equal(expm(a).toarray(),[[1,0],[0,1]])
def test_zero(self): a = array([[0.,0],[0,0]]) assert_array_almost_equal(expm(a),[[1,0],[0,1]])
def calc_trajectory(self,pa_space,pat,pts,dt,nTimeSteps,nStepsODEsolver=100,mysign=1): """ Returns: trajectories trajectories.shape = (nTimeSteps,nPts,pa_space.dim_domain) """ if pts.ndim != 2: raise ValueError(pts.shape) if pts.shape[1] != pa_space.dim_domain: raise ValueError(pts.shape) x,y = pts.T x_old=x.copy() y_old=y.copy() nPts = x_old.size history_x = np.zeros((nTimeSteps,nPts),dtype=self.my_dtype) history_y = np.zeros_like(history_x) history_x.fill(np.nan) history_y.fill(np.nan) afs=pat.affine_flows As = mysign*np.asarray([c.A for c in afs]).astype(self.my_dtype) Trels = np.asarray([expm(dt*c.A*mysign) for c in afs ]) xmins = np.asarray([c.xmins for c in afs]).astype(self.my_dtype) xmaxs = np.asarray([c.xmaxs for c in afs]).astype(self.my_dtype) xmins[xmins<=self.XMINS]=-self._LargeNumber xmaxs[xmaxs>=self.XMAXS]=+self._LargeNumber if pa_space.has_GPU == False or self.use_GPU_if_possible==False : Warning("Not using GPU!") raise NotImplementedError else: pts_at_0 = np.zeros((nPts,pa_space.dim_domain)) pts_at_0[:,0]=x_old.ravel() pts_at_0[:,1]=y_old.ravel() trajectories = pa_space._calcs_gpu.calc_trajectory(xmins,xmaxs, Trels,As, pts_at_0, dt, nTimeSteps, nStepsODEsolver) # add the starting points trajectories = np.vstack([pts_at_0,trajectories]) # reshaping trajectories = trajectories.reshape(1+nTimeSteps,nPts,pa_space.dim_domain) return trajectories
def exponentiate(mat): """ Return the matrix exponential of A, exp(A). """ exp_mat = linalg.expm(mat.tocsc()).tocsr() return exp_mat
# The last row of each "A" is all zeros. As[:,:-1]=np.random.standard_normal(As[:,:-1].shape) # # print map(det,As[:,:-1,:-1]) # # A = As[0] T = np.empty_like(A) expm_affine_2D((A,T)) if not np.allclose(T,expm(A)): raise ValueError tic = time.clock() res1=map(expm,As) toc = time.clock() t1=toc-tic print 'time (scipy)',t1 tic = time.clock() res2 = copy.deepcopy(res1) map(expm_affine_2D,zip(As,res2)) toc = time.clock() t2=toc-tic
def __init__(self, network, time_T = 0.1): """ Input: network: one of the following: - a tab-delimited file in .sif network format: <source> <interaction> <target> - an iterable (set, list, tuple, etc.) of edges: (<source>, <target>) Returns: Kernel object. """ self.time_T=time_T self.labels = {} # The number of rows and columns for each kernel self.ncols = {} self.nrows = {} # parse the network, build indexes try: # assume network is a filename edges, nodes, node_out_degrees = self.parseNet(network) except TypeError: # assume network is an edge list edges = set(network) nodes = set() node_out_degrees = defaultdict(int) for source, target in edges: nodes.add(source) nodes.add(target) node_out_degrees[source] += 1 node_out_degrees[target] += 1 # build indexes num_nodes = len(nodes) node_order = list(nodes) index2node = {} node2index = {} for i in range(0, num_nodes): index2node[i] = node_order[i] node2index[node_order[i]] = i # construct the diagonals # SCIPY uses row and column indexes to build the matrix # row and columns are just indexes: the data column stores # the actual entries of the matrix row = array('i') col = array('i') data = array('f') # build the diagonals, including the out-degree for i in range(0, num_nodes): # diag entries: out degree degree = 0 if index2node[i] in node_out_degrees: degree = node_out_degrees[index2node[i]] # append to the end # array object: first argument is the index, the second is the data value # append the out-degree to the data array data.insert(len(data), degree) # build the diagonals row.insert(len(row), i) col.insert(len(col), i) # add off-diagonal edges for i in range(0, num_nodes): for j in range(0, num_nodes): if i == j: continue if (index2node[i], index2node[j]) not in edges: continue # append index to i-th row, j-th column row.insert(len(row), i) col.insert(len(col), j) # -1 for laplacian: i.e. the negative of the adjacency matrix data.insert(len(data), -1) # Build the graph laplacian: the CSC matrix provides a sparse matrix format # that can be exponentiated efficiently L = coo_matrix((data,(row, col)), shape=(num_nodes,num_nodes)).tocsc() self.laplacian = L self.index2node = index2node # this is the matrix exponentiation calculation. # Uses the Pade approximiation for accurate approximation. Computationally expensive. # O(n^2), n= # of features, in memory as well. self.kernel = expm(-self.time_T*L) self.labels = node_order
def create_kernel(self, network_url, time_t=0.1): start = time.clock() edges, nodes, node_out_degrees = self.__parse_net(network_url) num_nodes = len(nodes) node_order = list(nodes) index2node = {} node2index = {} logging.debug('Network source: ' + str(network_url)) logging.debug('# of Nodes: ' + str(num_nodes)) logging.debug('# of Edges: ' + str(len(edges))) for i in range(0, num_nodes): index2node[i] = node_order[i] node2index[node_order[i]] = i # construct the diagonals # SCIPY uses row and column indexes to build the matrix # row and columns are just indexes: the data column stores # the actual entries of the matrix row = array('i') col = array('i') data = array('f') # build the diagonals, including the out-degree for i in range(0, num_nodes): # diag entries: out degree degree = 0 if index2node[i] in node_out_degrees: degree = node_out_degrees[index2node[i]] # append to the end # array object: first argument is the index, the second is the data value # append the out-degree to the data array data.insert(len(data), degree) # build the diagonals row.insert(len(row), i) col.insert(len(col), i) # add off-diagonal edges for i in range(0, num_nodes): for j in range(0, num_nodes): if i == j: continue if (index2node[i], index2node[j]) not in edges: continue # append index to i-th row, j-th column row.insert(len(row), i) col.insert(len(col), j) # -1 for laplacian: i.e. the negative of the adjacency matrix data.insert(len(data), -1) # Build the graph laplacian: the CSC matrix provides a sparse matrix format # that can be exponentiated efficiently l = coo_matrix((data, (row, col)), shape=(num_nodes, num_nodes)).tocsc() end = time.clock() logging.debug('Data preparation done in ' + str(end - start) + ' sec.') # this is the matrix exponentiation calculation. # Uses the Pade approximiation for accurate approximation. # Computationally expensive. # O(n^2), n= # of features, in memory as well. start = time.clock() kernel = expm(-time_t * l) end = time.clock() logging.debug('expm done in ' + str(end - start) + ' sec.') return Kernel(kernel=kernel, labels=node_order, index2node=index2node)