def sample_bitstrings(self, n_samples: int, tol_factor: float = 1e8) -> np.ndarray: """ Sample bitstrings from the distribution defined by the wavefunction. Qubit 0 is at ``out[:, 0]``. :param n_samples: The number of bitstrings to sample :param tol_factor: Tolerance to set imaginary probabilities to zero, relative to machine epsilon. :return: An array of shape (n_samples, n_qubits) """ if self.rs is None: raise ValueError( "You have tried to perform a stochastic operation without setting the " "random state of the simulator. Might I suggest using a PyQVM object?" ) # for np.real_if_close the actual tolerance is (machine_eps * tol_factor), # where `machine_epsilon = np.finfo(float).eps`. If we use tol_factor = 1e8, then the # overall tolerance is \approx 2.2e-8. probabilities = np.real_if_close(np.diagonal(self.density), tol=tol_factor) # type: ignore # Next set negative probabilities to zero probabilities = np.array([0 if p < 0.0 else p for p in probabilities]) # Ensure they sum to one probabilities = probabilities / np.sum(probabilities) possible_bitstrings = all_bitstrings(self.n_qubits) inds = self.rs.choice(2**self.n_qubits, n_samples, p=probabilities) bitstrings = possible_bitstrings[inds, :] bitstrings = np.flip(bitstrings, axis=1) # qubit ordering: 0 on the left. return bitstrings # type: ignore
def sample_bitstrings(self, n_samples: int) -> np.ndarray: """ Sample bitstrings from the distribution defined by the wavefunction. Qubit 0 is at ``out[:, 0]``. :param n_samples: The number of bitstrings to sample :return: An array of shape (n_samples, n_qubits) """ if self.rs is None: raise ValueError( "You have tried to perform a stochastic operation without setting the " "random state of the simulator. Might I suggest using a PyQVM object?" ) probabilities = np.abs(self.wf)**2 possible_bitstrings = all_bitstrings(self.n_qubits) inds = self.rs.choice(2**self.n_qubits, n_samples, p=probabilities) bitstrings = possible_bitstrings[inds, :] bitstrings = np.flip(bitstrings, axis=1) # qubit ordering: 0 on the left. return bitstrings # type: ignore
def sample_bitstrings(self, n_samples: int) -> np.ndarray: """ Sample bitstrings from the distribution defined by the wavefunction. Qubit 0 is at ``out[:, 0]``. :param n_samples: The number of bitstrings to sample :return: An array of shape (n_samples, n_qubits) """ if self.rs is None: raise ValueError( "You have tried to perform a stochastic operation without setting the " "random state of the simulator. Might I suggest using a PyQVM object?" ) # note on reshape: it puts bitstrings in lexicographical order. # would you look at that .. _all_bitstrings returns things in lexicographical order! # reminder: qubit 0 is on the left in einsum simulator. probabilities = np.abs(self.wf.reshape(-1))**2 possible_bitstrings = all_bitstrings(self.n_qubits) inds = self.rs.choice(2**self.n_qubits, n_samples, p=probabilities) return possible_bitstrings[inds, :]