def test_hermitian(self, hbar): """Test output is hermitian""" H, _ = kerr(self.kappa, hbar=hbar) assert is_hermitian(H) assert is_hermitian(get_quad_operator(H))
def test_quad_operator_nonhermitian(self): op = QuadOperator('q0 p1 q1') self.assertFalse(is_hermitian(op))
def test_qubit_operator_identity(self): op = QubitOperator(()) self.assertTrue(is_hermitian(op))
def test_boson_operator_zero(self): op = BosonOperator() self.assertTrue(is_hermitian(op))
def test_boson_operator_nonhermitian(self): op = BosonOperator('0^ 1 2^ 3') self.assertFalse(is_hermitian(op))
def get_diagonal_coulomb_hamiltonian(fermion_operator, n_qubits=None, ignore_incompatible_terms=False): r"""Convert a FermionOperator to a DiagonalCoulombHamiltonian. Args: fermion_operator(FermionOperator): The operator to convert. n_qubits(int): Optionally specify the total number of qubits in the system ignore_incompatible_terms(bool): This flag determines the behavior of this method when it encounters terms that are not represented by the DiagonalCoulombHamiltonian class, namely, terms that are not quadratic and not quartic of the form a^\dagger_p a_p a^\dagger_q a_q. If set to True, this method will simply ignore those terms. If False, then this method will raise an error if it encounters such a term. The default setting is False. """ if not isinstance(fermion_operator, FermionOperator): raise TypeError('Input must be a FermionOperator.') if n_qubits is None: n_qubits = count_qubits(fermion_operator) if n_qubits < count_qubits(fermion_operator): raise ValueError('Invalid number of qubits specified.') fermion_operator = normal_ordered(fermion_operator) constant = 0. one_body = numpy.zeros((n_qubits, n_qubits), complex) two_body = numpy.zeros((n_qubits, n_qubits), float) for term, coefficient in fermion_operator.terms.items(): # Ignore this term if the coefficient is zero if abs(coefficient) < EQ_TOLERANCE: continue if len(term) == 0: constant = coefficient else: actions = [operator[1] for operator in term] if actions == [1, 0]: p, q = [operator[0] for operator in term] one_body[p, q] = coefficient elif actions == [1, 1, 0, 0]: p, q, r, s = [operator[0] for operator in term] if p == r and q == s: if abs(numpy.imag(coefficient)) > EQ_TOLERANCE: raise ValueError( 'FermionOperator does not map to ' 'DiagonalCoulombHamiltonian (not Hermitian).') coefficient = numpy.real(coefficient) two_body[p, q] = -.5 * coefficient two_body[q, p] = -.5 * coefficient elif not ignore_incompatible_terms: raise ValueError('FermionOperator does not map to ' 'DiagonalCoulombHamiltonian ' '(contains terms with indices ' '{}).'.format((p, q, r, s))) elif not ignore_incompatible_terms: raise ValueError('FermionOperator does not map to ' 'DiagonalCoulombHamiltonian (contains terms ' 'with action {}.'.format(tuple(actions))) # Check that the operator is Hermitian if not is_hermitian(one_body): raise ValueError( 'FermionOperator does not map to DiagonalCoulombHamiltonian ' '(not Hermitian).') return DiagonalCoulombHamiltonian(one_body, two_body, constant)
def test_sparse_matrix_Y(self): term = QubitOperator(((0, 'Y'), )) sparse_operator = get_sparse_operator(term) self.assertEqual(list(sparse_operator.data), [1j, -1j]) self.assertEqual(list(sparse_operator.indices), [1, 0]) self.assertTrue(is_hermitian(sparse_operator))
def test_sparse_matrix_and_numpy_array_zero(self): op = numpy.zeros((4, 4)) self.assertTrue(is_hermitian(op)) op = csc_matrix(op) self.assertTrue(is_hermitian(op))
def test_sparse_matrix_and_numpy_array_identity(self): op = numpy.eye(4) self.assertTrue(is_hermitian(op)) op = csc_matrix(op) self.assertTrue(is_hermitian(op))
def get_quadratic_hamiltonian(fermion_operator, chemical_potential=0., n_qubits=None): """Convert a quadratic fermionic operator to QuadraticHamiltonian. This function should only be called on fermionic operators which consist of only a_p^\dagger a_q, a_p^\dagger a_q^\dagger, and a_p a_q terms. Returns: quadratic_hamiltonian: An instance of the QuadraticHamiltonian class. Raises: TypeError: Input must be a FermionOperator. TypeError: FermionOperator does not map to QuadraticHamiltonian. Warning: Even assuming that each creation or annihilation operator appears at most a constant number of times in the original operator, the runtime of this method is exponential in the number of qubits. """ if not isinstance(fermion_operator, FermionOperator): raise TypeError('Input must be a FermionOperator.') if n_qubits is None: n_qubits = count_qubits(fermion_operator) if n_qubits < count_qubits(fermion_operator): raise ValueError('Invalid number of qubits specified.') # Normal order the terms and initialize. fermion_operator = normal_ordered(fermion_operator) constant = 0. combined_hermitian_part = numpy.zeros((n_qubits, n_qubits), complex) antisymmetric_part = numpy.zeros((n_qubits, n_qubits), complex) # Loop through terms and assign to matrix. for term in fermion_operator.terms: coefficient = fermion_operator.terms[term] # Ignore this term if the coefficient is zero if abs(coefficient) < EQ_TOLERANCE: continue if len(term) == 0: # Constant term constant = coefficient elif len(term) == 2: ladder_type = [operator[1] for operator in term] p, q = [operator[0] for operator in term] if ladder_type == [1, 0]: combined_hermitian_part[p, q] = coefficient elif ladder_type == [1, 1]: # Need to check that the corresponding [0, 0] term is present conjugate_term = ((p, 0), (q, 0)) if conjugate_term not in fermion_operator.terms: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') else: matching_coefficient = -fermion_operator.terms[ conjugate_term].conjugate() discrepancy = abs(coefficient - matching_coefficient) if discrepancy > EQ_TOLERANCE: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') antisymmetric_part[p, q] += .5 * coefficient antisymmetric_part[q, p] -= .5 * coefficient else: # ladder_type == [0, 0] # Need to check that the corresponding [1, 1] term is present conjugate_term = ((p, 1), (q, 1)) if conjugate_term not in fermion_operator.terms: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') else: matching_coefficient = -fermion_operator.terms[ conjugate_term].conjugate() discrepancy = abs(coefficient - matching_coefficient) if discrepancy > EQ_TOLERANCE: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') antisymmetric_part[p, q] -= .5 * coefficient.conjugate() antisymmetric_part[q, p] += .5 * coefficient.conjugate() else: # Operator contains non-quadratic terms raise QuadraticHamiltonianError('FermionOperator does not map ' 'to QuadraticHamiltonian ' '(contains non-quadratic terms).') # Compute Hermitian part hermitian_part = (combined_hermitian_part + chemical_potential * numpy.eye(n_qubits)) # Check that the operator is Hermitian if not is_hermitian(hermitian_part): raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') # Form QuadraticHamiltonian and return. discrepancy = numpy.max(numpy.abs(antisymmetric_part)) if discrepancy < EQ_TOLERANCE: # Hamiltonian conserves particle number quadratic_hamiltonian = QuadraticHamiltonian( hermitian_part, constant=constant, chemical_potential=chemical_potential) else: # Hamiltonian does not conserve particle number quadratic_hamiltonian = QuadraticHamiltonian(hermitian_part, antisymmetric_part, constant, chemical_potential) return quadratic_hamiltonian
def test_qubit_operator_hermitian(self): op = QubitOperator('X0 Y2 Z5', 1. + 2.j) op += QubitOperator('X0 Y2 Z5', 1. - 2.j) self.assertTrue(is_hermitian(op))
def __init__(self, operator, t=1, mode='local', hbar=None): super().__init__([t, operator]) try: # pylint: disable=protected-access self.hbar = _Engine._current_context.hbar except AttributeError: if hbar is None: raise ValueError( "Either specify the hbar keyword argument, " "or use this operator inside an engine context.") else: self.hbar = hbar if not is_hermitian(operator): raise ValueError("Hamiltonian must be Hermitian.") if mode == 'local': quad_operator = prune_unused_indices(operator) elif mode == 'global': quad_operator = operator if isinstance(quad_operator, BosonOperator): quad_operator = get_quad_operator(quad_operator, hbar=self.hbar) A, d = quadratic_coefficients(quad_operator) if mode == 'local': self.ns = A.shape[0] // 2 elif mode == 'global': # pylint: disable=protected-access self.ns = _Engine._current_context.num_subsystems if A.shape[0] < 2 * self.ns: # expand the quadratic coefficient matrix to take # into account the extra modes A_n = A.shape[0] // 2 tmp = np.zeros([2 * self.ns, 2 * self.ns]) tmp[:A_n, :A_n] = A[:A_n, :A_n] tmp[:A_n, self.ns:self.ns + A_n] = A[:A_n, A_n:] tmp[self.ns:self.ns + A_n, :A_n] = A[A_n:, :A_n] tmp[self.ns:self.ns + A_n, self.ns:self.ns + A_n] = A[A_n:, A_n:] A = tmp self.S = expm(sympmat(self.ns) @ A * t) self.disp = False if not np.all(d == 0.): self.disp = True if np.all(A == 0.): self.d = d * t else: if np.linalg.cond(A) >= 1 / sys.float_info.epsilon: # the matrix is singular, add a small epsilon eps = 1e-9 epsI = eps * np.identity(2 * self.ns) s = inv(A + epsI) @ d tmp = (np.identity(2*self.ns) \ - expm(sympmat(self.ns) @ (A+epsI) * t).T) @ s / eps else: s = inv(A) @ d tmp = s - self.S.T @ s self.d = np.zeros([2 * self.ns]) self.d[self.ns:] = tmp[:self.ns] self.d[:self.ns] = tmp[self.ns:]
def test_hermitian(self): """Test output is hermitian""" H, _ = zdisplacement(self.p) self.assertTrue(is_hermitian(H)) self.assertTrue(is_hermitian(get_boson_operator(H, hbar=self.hbar)))
def test_hermitian(self, hbar): """Test output is hermitian""" H, _ = xdisplacement(self.x) assert is_hermitian(H) assert is_hermitian(get_boson_operator(H, hbar=hbar))
def test_hermitian(self): """Test output is hermitian""" self.logTestName() H, _ = xdisplacement(self.x) self.assertTrue(is_hermitian(H)) self.assertTrue(is_hermitian(get_boson_operator(H, hbar=self.hbar)))
def test_sparse_matrix_and_numpy_array_nonhermitian(self): op = numpy.arange(16).reshape((4, 4)) self.assertFalse(is_hermitian(op)) op = csc_matrix(op) self.assertFalse(is_hermitian(op))
def get_quadratic_hamiltonian(fermion_operator, chemical_potential=0., n_qubits=None, ignore_incompatible_terms=False): r"""Convert a quadratic fermionic operator to QuadraticHamiltonian. Args: fermion_operator(FermionOperator): The operator to convert. chemical_potential(float): A chemical potential to include in the returned operator n_qubits(int): Optionally specify the total number of qubits in the system ignore_incompatible_terms(bool): This flag determines the behavior of this method when it encounters terms that are not quadratic that is, terms that are not of the form a^\dagger_p a_q. If set to True, this method will simply ignore those terms. If False, then this method will raise an error if it encounters such a term. The default setting is False. Returns: quadratic_hamiltonian: An instance of the QuadraticHamiltonian class. Raises: TypeError: Input must be a FermionOperator. TypeError: FermionOperator does not map to QuadraticHamiltonian. Warning: Even assuming that each creation or annihilation operator appears at most a constant number of times in the original operator, the runtime of this method is exponential in the number of qubits. """ if not isinstance(fermion_operator, FermionOperator): raise TypeError('Input must be a FermionOperator.') if n_qubits is None: n_qubits = count_qubits(fermion_operator) if n_qubits < count_qubits(fermion_operator): raise ValueError('Invalid number of qubits specified.') # Normal order the terms and initialize. fermion_operator = normal_ordered(fermion_operator) constant = 0. combined_hermitian_part = numpy.zeros((n_qubits, n_qubits), complex) antisymmetric_part = numpy.zeros((n_qubits, n_qubits), complex) # Loop through terms and assign to matrix. for term in fermion_operator.terms: coefficient = fermion_operator.terms[term] # Ignore this term if the coefficient is zero if abs(coefficient) < EQ_TOLERANCE: continue if len(term) == 0: # Constant term constant = coefficient elif len(term) == 2: ladder_type = [operator[1] for operator in term] p, q = [operator[0] for operator in term] if ladder_type == [1, 0]: combined_hermitian_part[p, q] = coefficient elif ladder_type == [1, 1]: # Need to check that the corresponding [0, 0] term is present conjugate_term = ((p, 0), (q, 0)) if conjugate_term not in fermion_operator.terms: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') else: matching_coefficient = -fermion_operator.terms[ conjugate_term].conjugate() discrepancy = abs(coefficient - matching_coefficient) if discrepancy > EQ_TOLERANCE: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') antisymmetric_part[p, q] += .5 * coefficient antisymmetric_part[q, p] -= .5 * coefficient else: # ladder_type == [0, 0] # Need to check that the corresponding [1, 1] term is present conjugate_term = ((p, 1), (q, 1)) if conjugate_term not in fermion_operator.terms: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') else: matching_coefficient = -fermion_operator.terms[ conjugate_term].conjugate() discrepancy = abs(coefficient - matching_coefficient) if discrepancy > EQ_TOLERANCE: raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') antisymmetric_part[p, q] -= .5 * coefficient.conjugate() antisymmetric_part[q, p] += .5 * coefficient.conjugate() elif not ignore_incompatible_terms: # Operator contains non-quadratic terms raise QuadraticHamiltonianError('FermionOperator does not map ' 'to QuadraticHamiltonian ' '(contains non-quadratic terms).') # Compute Hermitian part hermitian_part = (combined_hermitian_part + chemical_potential * numpy.eye(n_qubits)) # Check that the operator is Hermitian if not is_hermitian(hermitian_part): raise QuadraticHamiltonianError( 'FermionOperator does not map ' 'to QuadraticHamiltonian (not Hermitian).') # Form QuadraticHamiltonian and return. discrepancy = numpy.max(numpy.abs(antisymmetric_part)) if discrepancy < EQ_TOLERANCE: # Hamiltonian conserves particle number quadratic_hamiltonian = QuadraticHamiltonian( hermitian_part, constant=constant, chemical_potential=chemical_potential) else: # Hamiltonian does not conserve particle number quadratic_hamiltonian = QuadraticHamiltonian(hermitian_part, antisymmetric_part, constant, chemical_potential) return quadratic_hamiltonian
def test_plane_wave_period_cutoff(self): # TODO: After figuring out the correct formula for period cutoff for # dual basis, change period_cutoff to default, and change # h_1 to also accept period_cutoff for real integration test. ''' Key: Spatial dimension. Value: List of geometries. ''' geometry_sets = { 2: [[('H', (0., 0.)), ('H', (0.8, 0.))], [('H', (0.1, 0.))]], 3: [[('H', (0., 0., 0.)), ('H', (0.8, 0., 0.))], [('H', (0.1, 0., 0.))]] } # [[spatial dimension, fieldline dimension]] dims = [[2, 2], [2, 3], [3, 3]] spinless_set = [True, False] scale = 8 * 1. for dim in dims: for geometry in geometry_sets[dim[0]]: for spinless in spinless_set: grid = Grid(dimensions=dim[0], scale=scale, length=2) period_cutoff = grid.volume_scale() ** (1. / grid.dimensions) h_1 = plane_wave_hamiltonian(grid, geometry, spinless=True, plane_wave=True, include_constant=False, e_cutoff=None, fieldlines=dim[1]) jw_1 = jordan_wigner(h_1) spectrum_1 = eigenspectrum(jw_1) h_2 = plane_wave_hamiltonian(grid, geometry, spinless=True, plane_wave=True, include_constant=False, e_cutoff=None, non_periodic=True, period_cutoff=period_cutoff, fieldlines=dim[1]) jw_2 = jordan_wigner(h_2) spectrum_2 = eigenspectrum(jw_2) max_diff = numpy.amax(numpy.absolute(spectrum_1 - spectrum_2)) # Checks if non-periodic and periodic cases are different. self.assertGreater(max_diff, 0.) # TODO: This is only for code coverage. Remove after having real # integration test. momentum_hamiltonian = plane_wave_hamiltonian(grid, geometry, spinless=True, plane_wave=True, include_constant=False, e_cutoff=None, non_periodic=True, period_cutoff=period_cutoff, fieldlines=dim[1]) position_hamiltonian = plane_wave_hamiltonian(grid, geometry, spinless=True, plane_wave=False, include_constant=False, e_cutoff=None, non_periodic=True, period_cutoff=period_cutoff, fieldlines=dim[1]) # Confirm they are Hermitian momentum_hamiltonian_operator = ( get_sparse_operator(momentum_hamiltonian)) self.assertTrue(is_hermitian(momentum_hamiltonian_operator)) position_hamiltonian_operator = ( get_sparse_operator(position_hamiltonian)) self.assertTrue(is_hermitian(position_hamiltonian_operator)) # Diagonalize. jw_momentum = jordan_wigner(momentum_hamiltonian) jw_position = jordan_wigner(position_hamiltonian) momentum_spectrum = eigenspectrum(jw_momentum) position_spectrum = eigenspectrum(jw_position) # Confirm spectra are the same. difference = numpy.amax( numpy.absolute(momentum_spectrum - position_spectrum)) self.assertAlmostEqual(difference, 0.)
def jw_get_ground_states_by_particle_number(sparse_operator, particle_number, sparse=True, num_eigs=3): """For a Jordan-Wigner encoded Hermitian operator, compute the lowest eigenvalue and eigenstates at a particular particle number. The operator must conserve particle number. Args: sparse_operator(sparse): A Jordan-Wigner encoded sparse operator. particle_number(int): The particle number at which to compute ground states. sparse(boolean, optional): Whether to use sparse eigensolver. Default is True. num_eigs(int, optional): The number of eigenvalues to request from the sparse eigensolver. Needs to be at least as large as the degeneracy of the ground energy in order to obtain all ground states. Only used if `sparse=True`. Default is 3. Returns: ground_energy(float): The lowest eigenvalue of sparse_operator within the eigenspace of the number operator corresponding to particle_number. ground_states(list[ndarray]): A list of the corresponding eigenstates. Warning: The running time of this method is exponential in the number of qubits. """ # Check if operator is Hermitian if not is_hermitian(sparse_operator): raise ValueError('sparse_operator must be Hermitian.') n_qubits = int(numpy.log2(sparse_operator.shape[0])) # Check if operator conserves particle number sparse_num_op = jordan_wigner_sparse(number_operator(n_qubits)) com = commutator(sparse_num_op, sparse_operator) if com.nnz: maxval = max(map(abs, com.data)) if maxval > EQ_TOLERANCE: raise ValueError('sparse_operator must conserve particle number.') # Get the operator restricted to the subspace of the desired # particle number restricted_operator = jw_number_restrict_operator(sparse_operator, particle_number, n_qubits) if sparse and num_eigs >= restricted_operator.shape[0] - 1: # Restricted operator too small for sparse eigensolver sparse = False # Compute eigenvalues and eigenvectors if sparse: eigvals, eigvecs = scipy.sparse.linalg.eigsh(restricted_operator, k=num_eigs, which='SA') if abs(max(eigvals) - min(eigvals)) < EQ_TOLERANCE: warnings.warn( 'The lowest {} eigenvalues are degenerate. ' 'There may be more ground states; increase ' 'num_eigs or set sparse=False to get ' 'them.'.format(num_eigs), RuntimeWarning) else: dense_restricted_operator = restricted_operator.toarray() eigvals, eigvecs = numpy.linalg.eigh(dense_restricted_operator) # Get the ground energy if sparse: ground_energy = sorted(eigvals)[0] else: # No need to sort in the case of dense eigenvalue computation ground_energy = eigvals[0] # Get the indices of eigenvectors corresponding to the ground energy ground_state_indices = numpy.where( abs(eigvals - ground_energy) < EQ_TOLERANCE) ground_states = list() for i in ground_state_indices[0]: restricted_ground_state = eigvecs[:, i] # Expand this ground state to the whole vector space number_indices = jw_number_indices(particle_number, n_qubits) expanded_ground_state = scipy.sparse.csc_matrix( (restricted_ground_state.flatten(), (number_indices, [0] * len(number_indices))), shape=(2**n_qubits, 1)) # Add the expanded ground state to the list ground_states.append(expanded_ground_state) return ground_energy, ground_states
def build_hamiltonian(ops: Union[FermionOperator, hamiltonian.Hamiltonian], norb: int = 0, conserve_number: bool = True, e_0: complex = 0. + 0.j) -> 'hamiltonian.Hamiltonian': """Build a Hamiltonian object for the fqe Args: ops (FermionOperator, hamiltonian.Hamiltonian) - input operator as \ FermionOperator. If a Hamiltonian is passed as an argument, \ this function returns as is. norb (int) - the number of orbitals in the system conserve_number (bool) - whether the operator conserves the number e_0 (complex) - the scalar part of the operator Returns: (hamiltonian.Hamiltonian) - General Hamiltonian that is created from ops """ if isinstance(ops, hamiltonian.Hamiltonian): return ops if isinstance(ops, tuple): validate_tuple(ops) return general_hamiltonian.General(ops, e_0=e_0) if not isinstance(ops, FermionOperator): raise TypeError('Expected FermionOperator' \ ' but received {}.'.format(type(ops))) assert is_hermitian(ops) out: Any if len(ops.terms) <= 2: out = sparse_hamiltonian.SparseHamiltonian(ops, e_0=e_0) else: if not conserve_number: ops = transform_to_spin_broken(ops) ops = normal_ordered(ops) ops_rank, e_0 = split_openfermion_tensor(ops) # type: ignore if norb == 0: for term in ops_rank.values(): ablk, bblk = largest_operator_index(term) norb = max(norb, ablk // 2 + 1, bblk // 2 + 1) else: norb = norb ops_mat = {} maxrank = 0 for rank, term in ops_rank.items(): index = rank // 2 - 1 ops_mat[index] = fermionops_tomatrix(term, norb) maxrank = max(index, maxrank) if len(ops_mat) == 1 and (0 in ops_mat): out = process_rank2_matrix(ops_mat[0], norb=norb, e_0=e_0) elif len(ops_mat) == 1 and \ (1 in ops_mat) and \ check_diagonal_coulomb(ops_mat[1]): out = diagonal_coulomb.DiagonalCoulomb(ops_mat[1], e_0=e_0) else: dtypes = [xx.dtype for xx in ops_mat.values()] dtypes = numpy.unique(dtypes) if len(dtypes) != 1: raise TypeError( "Non-unique coefficient types for input operator") for i in range(maxrank + 1): if i not in ops_mat: mat_dim = tuple([2 * norb for _ in range((i + 1) * 2)]) ops_mat[i] = numpy.zeros(mat_dim, dtype=dtypes[0]) ops_mat2 = [] for i in range(maxrank + 1): ops_mat2.append(ops_mat[i]) out = general_hamiltonian.General(tuple(ops_mat2), e_0=e_0) out._conserve_number = conserve_number return out
def test_exceptions(self): with self.assertRaises(TypeError): _ = is_hermitian('a') with self.assertRaises(TypeError): _ = hermitian_conjugated(1)
def test_hermitian(self): """Test output is hermitian""" self.logTestName() H, _ = rotation(self.phi, hbar=self.hbar) self.assertTrue(is_hermitian(H)) self.assertTrue(is_hermitian(get_quad_operator(H)))
def test_boson_operator_identity(self): op = BosonOperator(()) self.assertTrue(is_hermitian(op))
def test_hermitian(self): """Test output is hermitian""" self.logTestName() H, _ = displacement(self.alpha, hbar=self.hbar) self.assertTrue(is_hermitian(H)) self.assertTrue(is_hermitian(get_quad_operator(H)))
def test_boson_operator_hermitian(self): op = BosonOperator('0^ 1 2^ 3') op += BosonOperator('3^ 2 1^ 0') self.assertTrue(is_hermitian(op))
def test_hermitian(self): """Test output is hermitian""" self.logTestName() self.assertTrue(is_hermitian(self.H)) self.assertTrue( is_hermitian(get_boson_operator(self.H, hbar=self.hbar)))
def test_qubit_operator_zero(self): op = QubitOperator() self.assertTrue(is_hermitian(op))
def test_hermitian(self): """Test output is hermitian""" self.logTestName() self.assertTrue(is_hermitian(self.H)) self.assertTrue(is_hermitian(get_quad_operator(self.H)))
def test_qubit_operator_nonhermitian(self): op = QubitOperator('X0 Y2 Z5', 1. + 2.j) self.assertFalse(is_hermitian(op))
def test_hermitian(self, hbar): """Test output is hermitian""" assert is_hermitian(self.H) assert is_hermitian(get_boson_operator(self.H, hbar=hbar))