def test_dm_two_mode(self, setup_eng, hbar, cutoff, tol): """Tests multimode dm preparation""" eng, prog = setup_eng(2) ket0 = np.random.uniform( -1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket0 = ket0 / np.linalg.norm(ket0) ket1 = np.random.uniform( -1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket1 = ket1 / np.linalg.norm(ket1) ket = np.outer(ket0, ket1) rho = np.einsum("ij,kl->ikjl", ket, ket.conj()) with prog.context as q: ops.DensityMatrix(rho) | q state = eng.run(prog).state assert np.allclose(state.dm(), rho, atol=tol, rtol=0) eng.reset() prog = sf.Program(2) state1 = BaseFockState(rho, 2, False, cutoff) with prog.context as q: ops.DensityMatrix(state1) | q state2 = eng.run(prog).state assert np.allclose(state1.dm(), state2.dm(), atol=tol, rtol=0)
def probability(self, wires=None): """Return the (marginal) probability of each computational basis state from the last run of the device. Args: wires (Iterable[Number, str], Number, str, Wires): wires to return marginal probabilities for. Wires not provided are traced out of the system. Returns: OrderedDict[tuple, float]: Dictionary mapping a tuple representing the state to the resulting probability. The dictionary should be sorted such that the state tuples are in lexicographical order. """ wires = wires or self.wires # convert to a wires object wires = Wires(wires) # translate to wires used by device device_wires = self.map_wires(wires) N = len(wires) cutoff = getattr(self, "cutoff", 10) if N == self.state.num_modes: # probabilities of the entire system probs = self.state.all_fock_probs(cutoff=cutoff).flat else: if isinstance(self.state, BaseFockState): rdm = self.state.reduced_dm(modes=device_wires.tolist()) new_state = BaseFockState(rdm, N, pure=False, cutoff_dim=cutoff) elif isinstance(self.state, BaseGaussianState): # Reduced Gaussian state mu, cov = self.state.reduced_gaussian( modes=device_wires.tolist()) # scale so that hbar = 2 mu /= np.sqrt(sf.hbar / 2) cov /= sf.hbar / 2 # create reduced Gaussian state new_state = BaseGaussianState((mu, cov), N) probs = new_state.all_fock_probs(cutoff=cutoff).flat ind = np.indices([cutoff] * N).reshape(N, -1).T probs = OrderedDict((tuple(k), v) for k, v in zip(ind, probs)) return probs
def test_ket_one_mode(self, setup_eng, hbar, cutoff, tol): """Tests single mode ket preparation""" eng, prog = setup_eng(2) ket0 = np.random.uniform(-1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket0 = ket0 / np.linalg.norm(ket0) with prog.context as q: ops.Ket(ket0) | q[0] state = eng.run(prog, modes=[0]) assert np.allclose(state.dm(), np.outer(ket0, ket0.conj()), atol=tol, rtol=0) eng.reset() prog = sf.Program(2) state1 = BaseFockState(ket0, 1, True, cutoff, hbar) with prog.context as q: ops.Ket(state1) | q[0] state2 = eng.run(prog, modes=[0]) assert np.allclose(state1.dm(), state2.dm(), atol=tol, rtol=0)
def state(self, modes=None, **kwargs): s, pure = self.circuit.get_state() if modes is None: # reduced state is full state red_state = s num_modes = len(s.shape) if pure else len(s.shape) // 2 modes = [m for m in range(num_modes)] else: # convert to mixed state representation if pure: num_modes = len(s.shape) left_str = [indices[i] for i in range(0, 2 * num_modes, 2)] right_str = [indices[i] for i in range(1, 2 * num_modes, 2)] out_str = [indices[: 2 * num_modes]] einstr = ''.join(left_str + [','] + right_str + ['->'] + out_str) rho = np.einsum(einstr, s, s.conj()) else: rho = s # reduce rho down to specified subsystems if isinstance(modes, int): modes = [modes] if len(modes) != len(set(modes)): raise ValueError("The specified modes cannot be duplicated.") num_modes = len(rho.shape) // 2 if len(modes) > num_modes: raise ValueError("The number of specified modes cannot be larger than the number of subsystems.") keep_indices = indices[: 2 * len(modes)] trace_indices = indices[2 * len(modes) : len(modes) + num_modes] ind = [i * 2 for i in trace_indices] ctr = 0 for m in range(num_modes): if m in modes: ind.insert(m, keep_indices[2 * ctr : 2 * (ctr + 1)]) ctr += 1 indStr = ''.join(ind) + '->' + keep_indices red_state = np.einsum(indStr, rho) # permute indices of returned state to reflect the ordering of modes (we know and hence can assume that red_state is a mixed state) if modes != sorted(modes): mode_permutation = np.argsort(modes) index_permutation = [2*x+i for x in mode_permutation for i in (0, 1)] red_state = np.transpose(red_state, np.argsort(index_permutation)) cutoff = self.circuit._trunc mode_names = ["q[{}]".format(i) for i in np.array(self.get_modes())[modes]] state = BaseFockState(red_state, len(modes), pure, cutoff, mode_names) return state
def test_dm_one_mode(self, setup_eng, hbar, cutoff, tol): """Tests single mode DM preparation""" eng, prog = setup_eng(2) ket = np.random.uniform(-1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket = ket / np.linalg.norm(ket) rho = np.outer(ket, ket.conj()) with prog.context as q: ops.DensityMatrix(rho) | q[0] state = eng.run(prog, modes=[0]) assert np.allclose(state.dm(), rho, atol=tol, rtol=0) eng.reset() prog = sf.Program(2) state1 = BaseFockState(rho, 1, False, cutoff, hbar) with prog.context as q: ops.DensityMatrix(state1) | q[0] state2 = eng.run(prog, modes=[0]) assert np.allclose(state1.dm(), state2.dm(), atol=tol, rtol=0)
def test_ket_input_validation(self, setup_eng, hbar, cutoff): """Test exceptions""" mu = np.array([0.0, 0.0]) cov = np.identity(2) state1 = GaussianState((mu, cov), 1, True, hbar) state2 = BaseFockState(np.zeros(cutoff), 1, False, cutoff, hbar) eng, prog = setup_eng(2) with prog.context as q: with pytest.raises(ValueError, match="Gaussian states are not supported"): ops.Ket(state1) | q[0] with pytest.raises(ValueError, match="not pure"): ops.Ket(state2) | q[0]
def test_ket_two_mode(self, setup_eng, hbar, cutoff, tol): """Tests multimode ket preparation""" eng, prog = setup_eng(2) ket0 = np.random.uniform(-1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket0 = ket0 / np.linalg.norm(ket0) ket1 = np.random.uniform(-1, 1, cutoff) + 1j * np.random.uniform(-1, 1, cutoff) ket1 = ket1 / np.linalg.norm(ket1) ket = np.outer(ket0, ket1) with prog.context as q: ops.Ket(ket) | q state = eng.run(prog) assert np.allclose( state.dm(), np.einsum("ij,kl->ikjl", ket, ket.conj()), atol=tol, rtol=0 ) eng.reset() prog = sf.Program(2) state1 = BaseFockState(ket, 2, True, cutoff, hbar) with prog.context as q: ops.Ket(state1) | q state2 = eng.run(prog) assert np.allclose(state1.dm(), state2.dm(), atol=tol, rtol=0)