def mutate_config(stra: int, strb: int, term: Tuple[Tuple[int, int]]) -> Tuple[int, int, int]: """Apply creation and annihilation operators to a configuration in the bitstring representation and return the new configuration and the parity. Args: stra (bitstring) - the alpha string to be manipulated stra (bitstring) - the beta string to be manipulated term (Operators) - the operations to apply Returns: tuple(bitstring, bitstring, int) - the mutated alpha and beta \ configuration and the parity to go with it. """ newa = stra newb = strb parity = 1 for ops in reversed(term): if ops[0] % 2: abits = count_bits(newa) indx = (ops[0] - 1) // 2 if ops[1] == 1: if newb & 2**indx: # return -1, -1, 0 return stra, strb, 0 newb += 2**indx else: if not newb & 2**indx: # return -1, -1, 0 return stra, strb, 0 newb -= 2**indx lowbit = (1 << (indx)) - 1 parity *= (-1)**(count_bits(lowbit & newb) + abits) else: indx = ops[0] // 2 if ops[1] == 1: if newa & 2**indx: # return -1, -1, 0 return stra, strb, 0 newa += 2**indx else: if not newa & 2**indx: # return -1, -1, 0 return stra, strb, 0 newa -= 2**indx lowbit = (1 << (indx)) - 1 parity *= (-1)**count_bits(lowbit & newa) return newa, newb, parity
def __setitem__(self, key: Tuple[int, int], value: complex) -> None: """Element write access to the wave function. Args: key (Tuple[int, int]) - a pair of strings for alpha and beta value (complex) - the value to be set to the wave function """ astr, bstr = key[0], key[1] sector = (count_bits(astr) + count_bits(bstr), count_bits(astr) - count_bits(bstr)) self._civec[sector][key] = value
def __getitem__(self, key: Tuple[int, int]) -> complex: """Element read access to the wave function. Args: key (Tuple[int, int]) - a pair of strings for alpha and beta Returns: (complex) - the value of the wave function """ astr, bstr = key[0], key[1] sector = (count_bits(astr) + count_bits(bstr), count_bits(astr) - count_bits(bstr)) return self._civec[sector][key]
def qubit_config_sector(nqubits: int, pnum: int, m_s: int) -> List[numpy.ndarray]: """Generate the basis vectors into the qubit basis representing all states which have a definite particle number and spin. Args: nqubits (int) - the number of qubits in the qpu pnum (int) - the number of particles to build vectors into m_s (int) - the s_z spin quantum number Returns: list[numpy.array(dtype=numpy.complex64)] """ occ = numpy.array([0, 1], dtype=numpy.int) uno = numpy.array([1, 0], dtype=numpy.int) seed = init_bitstring_groundstate(pnum) achk = 0 bchk = 0 pn_set = [] for num in range(nqubits): if num % 2: bchk += 2**num else: achk += 2**num initpn = lexicographic_bitstring_generator(seed, nqubits) for occu in initpn: if (count_bits(occu & achk) - count_bits(occu & bchk)) == m_s: pn_set.append(occu) vectors = [] for orbocc in pn_set: if orbocc & 1: vec = occ else: vec = uno orbocc = orbocc >> 1 for _ in range(nqubits - 1): if orbocc & 1: vec = numpy.kron(vec, occ) else: vec = numpy.kron(vec, uno) orbocc = orbocc >> 1 vectors.append(vec) return vectors
def test_count_bits(self): """Return the number of set bits in the bitstring """ self.assertEqual(bitstring.count_bits(0), 0) self.assertEqual(bitstring.count_bits(1 + 2 + 4 + 8 + 32), 5)