def build_hamiltonian(self): hilbertspc = self.hilbertspace_initialize() [transmon1, transmon2, resonator] = hilbertspc hres = hilbertspc.diag_hamiltonian(resonator) h1 = hilbertspc.diag_hamiltonian(transmon1) h2 = hilbertspc.diag_hamiltonian(transmon2) g1 = 0.1 # coupling resonator-transmon1 (without charge matrix elements) g2 = 0.2 # coupling resonator-transmon2 (without charge matrix elements) dim1 = transmon1.truncated_dim dim2 = transmon2.truncated_dim _, evecs1 = transmon1.eigensys(dim1) _, evecs2 = transmon2.eigensys(dim2) gmat1 = g1 * get_matrixelement_table( transmon1.n_operator(), evecs1) # coupling constants for transmon1 gmat2 = g2 * get_matrixelement_table(transmon2.n_operator(), evecs2) # and for transmon2 hbd = hilbertspc.hubbard_operator a = hilbertspc.annihilate(resonator) hamiltonian0 = h1 + h2 + hres vcpb1 = sum([ gmat1[j][k] * hbd(j, k, transmon1) for j in range(dim1) for k in range(dim1) ]) vcpb2 = sum([ gmat2[j][k] * hbd(j, k, transmon2) for j in range(dim2) for k in range(dim2) ]) hamiltonian1 = (vcpb1 + vcpb2) * (a + a.dag()) return hamiltonian0 + hamiltonian1
def matrixelement_table(self, operator: str, evecs: ndarray = None, evals_count: int = 6, filename: str = None, return_datastore: bool = False) -> ndarray: """Returns table of matrix elements for `operator` with respect to the eigenstates of the qubit. The operator is given as a string matching a class method returning an operator matrix. E.g., for an instance `trm` of Transmon, the matrix element table for the charge operator is given by `trm.op_matrixelement_table('n_operator')`. When `esys` is set to `None`, the eigensystem is calculated on-the-fly. Parameters ---------- operator: name of class method in string form, returning operator matrix in qubit-internal basis. evecs: if not provided, then the necessary eigenstates are calculated on the fly evals_count: number of desired matrix elements, starting with ground state (default value = 6) filename: output file name return_datastore: if set to true, the returned data is provided as a DataStore object (default value = False) """ if evecs is None: _, evecs = self.eigensys(evals_count=evals_count) operator_matrix = getattr(self, operator)() table = get_matrixelement_table(operator_matrix, evecs) if filename or return_datastore: data_store = DataStore(system_params=self.get_initdata(), matrixelem_table=table) if filename: data_store.filewrite(filename) return data_store if return_datastore else table
def _zeropi_operator_in_product_basis(self, zeropi_operator, zeropi_evecs=None): """Helper method that converts a zeropi operator into one in the product basis. Returns ------- scipy.sparse.csc_matrix operator written in the product basis """ zeropi_dim = self.zeropi_cutoff zeta_dim = self.zeta_cutoff if zeropi_evecs is None: _, zeropi_evecs = self._zeropi.eigensys(evals_count=zeropi_dim) op_eigen_basis = sparse.dia_matrix( (zeropi_dim, zeropi_dim), dtype=np.complex_) # is this guaranteed to be zero? op_zeropi = get_matrixelement_table(zeropi_operator, zeropi_evecs) for n in range(zeropi_dim): for m in range(zeropi_dim): op_eigen_basis += op_zeropi[n, m] * op.hubbard_sparse( n, m, zeropi_dim) return sparse.kron(op_eigen_basis, sparse.identity(zeta_dim, format='csc', dtype=np.complex_), format='csc')
def g_phi_coupling_matrix(self, zeropi_states: ndarray) -> ndarray: """Returns a matrix of coupling strengths g^\\phi_{ll'} [cmp. Dempster et al., Eq. (18)], using the states from the list `zeropi_states`. Most commonly, `zeropi_states` will contain eigenvectors of the `DisorderedZeroPi` type. """ prefactor = self.EL * (self.dEL / 2.0) * (8.0 * self.EC / self.EL) ** 0.25 return prefactor * spec_utils.get_matrixelement_table(self._zeropi.phi_operator(), zeropi_states)
def g_theta_coupling_matrix(self, zeropi_states): """Returns a matrix of coupling strengths i*g^\\theta_{ll'} [cmp. Dempster et al., Eq. (17)], using the states from the list 'zeropi_states'. """ prefactor = 1j * self.ECS * (self.dC / 2.0) * (32.0 * self.EL / self.EC)**0.25 return prefactor * get_matrixelement_table( self._zeropi.n_theta_operator(), zeropi_states)
def manual_hamiltonian(self, esys1=None, esys2=None): hilbertspc = self.hilbertspace_initialize() [fluxonium, zpifull] = hilbertspc g1 = 0.1 dim1 = fluxonium.truncated_dim if esys1 is None: evals1, evecs1 = fluxonium.eigensys(dim1) else: evals1, evecs1 = esys1 dim2 = zpifull.truncated_dim if esys2 is None: evals2, evecs2 = zpifull.eigensys(dim1) else: evals2, evecs2 = esys2 h1 = hilbertspc.diag_hamiltonian(fluxonium, evals=evals1) h2 = hilbertspc.diag_hamiltonian(zpifull, evals=evals2) nmat1 = get_matrixelement_table( fluxonium.n_operator(), evecs1 ) # coupling constants for fluxonium nmat2 = get_matrixelement_table( zpifull.n_theta_operator(), evecs2 ) # coupling constants for zeropi hbd = hilbertspc.hubbard_operator vfl = sum( [ nmat1[j][k] * hbd(j, k, fluxonium) for j in range(dim1) for k in range(dim1) ] ) vzp = sum( [nmat2[j][k] * hbd(j, k, zpifull) for j in range(dim2) for k in range(dim2)] ) bare_hamiltonian = h1 + h2 interaction_hamiltonian = g1 * vfl * vzp return bare_hamiltonian, interaction_hamiltonian
def matrixelement_table(self, operator: str) -> ndarray: """Returns table of matrix elements for `operator` with respect to the eigenstates of the qubit. The operator is given as a string matching a class method returning an operator matrix. Parameters ---------- operator: name of class method in string form, returning operator matrix in qubit-internal basis. """ _, evecs = self.eigensys() operator_matrix = getattr(self, operator)() table = get_matrixelement_table(operator_matrix, evecs) return table
def hamiltonian(self, flux): hilbertspc = self.hilbertspace_initialize() [transmon1, transmon2, resonator] = hilbertspc hres = hilbertspc.diag_hamiltonian(resonator) # Get diagonalized transmon1 Hamiltonian as full-system operator via tensor product with identities. g1 = 0.1 # coupling resonator-transmon1 (without charge matrix elements) g2 = 0.2 # coupling resonator-transmon2 (without charge matrix elements) dim1 = transmon1.truncated_dim dim2 = transmon2.truncated_dim _, evecs1 = transmon1.eigensys(dim1) _, evecs2 = transmon2.eigensys(dim2) gmat1 = g1 * get_matrixelement_table( transmon1.n_operator(), evecs1) # coupling constants for transmon1 gmat2 = g2 * get_matrixelement_table(transmon2.n_operator(), evecs2) # and for transmon2 hbd = hilbertspc.hubbard_operator a = hilbertspc.annihilate(resonator) vcpb1 = sum([ gmat1[j][k] * hbd(j, k, transmon1) for j in range(dim1) for k in range(dim1) ]) vcpb2 = sum([ gmat2[j][k] * hbd(j, k, transmon2) for j in range(dim2) for k in range(dim2) ]) transmon1.EJ = 40.0 * np.cos(np.pi * flux) h1 = hilbertspc.diag_hamiltonian(transmon1) h2 = hilbertspc.diag_hamiltonian(transmon2) return h1 + h2 + hres + (vcpb1 + vcpb2) * (a + a.dag())
def qubit_matrixelement(sweep, param_index, qubit_subsys, qubit_operator): """ For given ParameterSweep and parameter_index, calculate the matrix elements for the provided qubit operator. Parameters ---------- sweep: ParameterSweep param_index: int qubit_subsys: QuantumSystem qubit_operator: ndarray operator within the qubit subspace Returns ------- ndarray """ bare_evecs = sweep.lookup.bare_eigenstates(param_index, qubit_subsys) return spectrum_utils.get_matrixelement_table(qubit_operator, bare_evecs)
def identity_wrap(self, operator, subsystem, op_in_eigenbasis=False, evecs=None): """Wrap given operator in subspace `subsystem` in identity operators to form full Hilbert-space operator. Parameters ---------- operator: ndarray or qutip.Qobj or str operator acting in Hilbert space of `subsystem`; if str, then this should be an operator name in the subsystem, typically not in eigenbasis subsystem: object derived from QuantumSystem subsystem where diagonal operator is defined op_in_eigenbasis: bool whether `operator` is given in the `subsystem` eigenbasis; otherwise, the internal QuantumSystem basis is assumed evecs: ndarray, optional internal QuantumSystem eigenstates, used to convert `operator` into eigenbasis Returns ------- qutip.Qobj operator """ dim = subsystem.truncated_dim if isinstance(operator, np.ndarray): if op_in_eigenbasis is False: if evecs is None: _, evecs = subsystem.eigensys(evals_count=subsystem.truncated_dim) operator_matrixelements = get_matrixelement_table(operator, evecs) subsys_operator = qt.Qobj(inpt=operator_matrixelements) else: subsys_operator = qt.Qobj(inpt=operator[:dim, :dim]) elif isinstance(operator, str): if evecs is None: _, evecs = subsystem.eigensys(evals_count=subsystem.truncated_dim) operator_matrixelements = subsystem.matrixelement_table(operator, evecs=evecs) subsys_operator = qt.Qobj(inpt=operator_matrixelements) elif isinstance(operator, qt.Qobj): subsys_operator = operator else: raise TypeError('Unsupported operator type: ', type(operator)) operator_identitywrap_list = [qt.operators.qeye(the_subsys.truncated_dim) for the_subsys in self] subsystem_index = self.get_subsys_index(subsystem) operator_identitywrap_list[subsystem_index] = subsys_operator return qt.tensor(operator_identitywrap_list)
def qubit_matrixelement( sweep: "ParameterSweep", param_index: int, qubit_subsys: "QubitBaseClass", qubit_operator: ndarray, ) -> ndarray: """ For given ParameterSweep and parameter_index, calculate the matrix elements for the provided qubit operator. Parameters ---------- sweep: param_index: qubit_subsys: qubit_operator: operator within the qubit subspace """ bare_evecs = sweep.lookup.bare_eigenstates(qubit_subsys, param_index=param_index) return spec_utils.get_matrixelement_table(qubit_operator, bare_evecs)
def matrixelement_table(self, operator, evecs=None, evals_count=6, filename=None): """Returns table of matrix elements for `operator` with respect to the eigenstates of the qubit. The operator is given as a string matching a class method returning an operator matrix. E.g., for an instance `trm` of Transmon, the matrix element table for the charge operator is given by `trm.op_matrixelement_table('n_operator')`. When `esys` is set to `None`, the eigensystem is calculated on-the-fly. Parameters ---------- operator: str name of class method in string form, returning operator matrix in qubit-internal basis. evecs: ndarray, optional if not provided, then the necesssary eigenstates are calculated on the fly evals_count: int, optional number of desired matrix elements, starting with ground state (default value = 6) filename: str, optional output file name Returns ------- ndarray """ if evecs is None: _, evecs = self.eigensys(evals_count=evals_count) operator_matrix = getattr(self, operator)() table = get_matrixelement_table(operator_matrix, evecs) if filename: specdata = SpectrumData(energy_table=np.empty(0), system_params=self._get_metadata_dict(), param_name='const_parameters', param_vals=np.empty(0), matrixelem_table=table) specdata.filewrite(filename) return table