def test_measurement_result_parameters_repeated_execution_final_measurements( backend, accelerators): original_backend = qibo.get_backend() qibo.set_backend(backend) from qibo import K from qibo.tests_new.test_core_gates import random_state test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) K.set_seed(123) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RY(0, theta=np.pi * output / 3)) c.add(gates.RY(2, theta=np.pi * output / 4)) c.add(gates.M(0, 1, 2, 3)) result = c(initial_state=np.copy(initial_state), nshots=30) K.set_seed(123) target_samples = [] with K.device(test_device): for _ in range(30): collapse = gates.M(1, collapse=True) target_state = collapse(np.copy(initial_state)) if int(collapse.result.outcome()): target_state = gates.RY(0, theta=np.pi / 3)(target_state) target_state = gates.RY(2, theta=np.pi / 4)(target_state) with K.device(K.default_device): target_result = gates.M(0, 1, 2, 3)(target_state) target_samples.append(target_result.decimal[0]) np.testing.assert_allclose(result.samples(binary=False), target_samples) qibo.set_backend(original_backend)
def zero_state(cls, circuit): state = cls(circuit) state.create_pieces() with K.device(state.device): piece = K.initial_state(nqubits=state.nlocal) state.pieces[0] = K.optimization.Variable(piece, dtype=piece.dtype) return state
def reprepare(self): unitary, phi = self.parameters matrix = K.qnp.zeros(5) matrix[:4] = K.qnp.reshape(unitary, (4, )) matrix[4] = K.qnp.exp(-1j * phi) with K.device(self.device): self.matrix = K.cast(matrix)
def create_pieces(self): n = 2**(self.nqubits - self.nglobal) with K.device(self.device): self.pieces = [ K.optimization.Variable(K.zeros(n)) for _ in range(self.ndevices) ]
def test_measurement_result_parameters_repeated_execution_final_measurements( backend): initial_state = random_state(4) K.set_seed(123) c = models.Circuit(4) output = c.add(gates.M(1, collapse=True)) c.add(gates.RY(0, theta=np.pi * output / 3)) c.add(gates.RY(2, theta=np.pi * output / 4)) c.add(gates.M(0, 1, 2, 3)) result = c(initial_state=np.copy(initial_state), nshots=30) final_samples = result.samples(binary=False) K.set_seed(123) target_samples = [] for _ in range(30): collapse = gates.M(1, collapse=True) target_state = collapse(K.cast(np.copy(initial_state))) if int(collapse.result.outcome()): target_state = gates.RY(0, theta=np.pi / 3)(target_state) target_state = gates.RY(2, theta=np.pi / 4)(target_state) with K.device(K.default_device): target_result = gates.M(0, 1, 2, 3)(target_state) target_samples.append(target_result.decimal[0]) target_samples = K.stack(target_samples) K.assert_allclose(final_samples, target_samples)
def reprepare(self): theta, phi = self.parameters cos, isin = K.qnp.cos(theta), -1j * K.qnp.sin(theta) phase = K.qnp.exp(-1j * phi) matrix = K.qnp.cast([cos, isin, isin, cos, phase]) with K.device(self.device): self.matrix = K.cast(matrix)
def test_measurement_result_parameters_repeated_execution( backend, accelerators, use_loop): original_backend = qibo.get_backend() qibo.set_backend(backend) from qibo import K from qibo.tests_new.test_core_gates import random_state test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) K.set_seed(123) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RX(2, theta=np.pi * output / 4)) if use_loop: final_states = [] for _ in range(20): final_states.append(c(np.copy(initial_state)).state()) else: final_states = c(initial_state=np.copy(initial_state), nshots=20) K.set_seed(123) target_states = [] with K.device(test_device): for _ in range(20): collapse = gates.M(1, collapse=True) target_state = collapse(np.copy(initial_state)) if int(collapse.result.outcome()): target_state = gates.RX(2, theta=np.pi / 4)(target_state) target_states.append(np.copy(target_state)) np.testing.assert_allclose(final_states, target_states) qibo.set_backend(original_backend)
def test_measurement_result_parameters_repeated_execution( backend, accelerators, use_loop): test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) set_device_seed(123, accelerators) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RX(2, theta=np.pi * output / 4)) if use_loop: final_states = [] for _ in range(20): final_states.append(c(np.copy(initial_state)).state()) else: final_states = c(initial_state=np.copy(initial_state), nshots=20) set_device_seed(123, accelerators) target_states = [] with K.device(test_device): for _ in range(20): collapse = gates.M(1, collapse=True) target_state = collapse(K.cast(np.copy(initial_state))) if int(collapse.result.outcome()): target_state = gates.RX(2, theta=np.pi / 4)(target_state) target_states.append(np.copy(target_state)) final_states = K.stack(final_states) target_states = K.stack(target_states) K.assert_allclose(final_states, target_states)
def plus_state(cls, circuit): state = cls(circuit) state.create_pieces() with K.device(state.device): norm = K.cast(2 ** float(state.nqubits / 2.0), dtype=state.dtype) state.pieces = [K.optimization.Variable(K.ones_like(p) / norm) for p in state.pieces] return state
def _swap(self, state, global_qubit: int, local_qubit: int): m = self.queues.qubits.reduced_global[global_qubit] m = self.nglobal - m - 1 t = 1 << m for g in range(self.ndevices // 2): i = ((g >> m) << (m + 1)) + (g & (t - 1)) local_eff = self.queues.qubits.reduced_local[local_qubit] with K.device(self.memory_device): K.op.swap_pieces(state.pieces[i], state.pieces[i + t], local_eff, self.nlocal, get_threads())
def tensor(self): """Returns the full state vector as a tensor of shape ``(2 ** nqubits,)``. This is done by merging the state pieces to a single tensor. Using this method will double memory usage. """ if self.qubits.list == list(range(self.nglobal)): with K.device(self.device): state = K.concatenate([x[K.newaxis] for x in self.pieces], axis=0) state = K.reshape(state, self.shapes["full"]) elif self.qubits.list == list(range(self.nlocal, self.nqubits)): with K.device(self.device): state = K.concatenate([x[:, K.newaxis] for x in self.pieces], axis=1) state = K.reshape(state, self.shapes["full"]) else: # fall back to the transpose op with K.device(self.device): state = K.zeros(self.shapes["full"]) state = K.transpose_state(self.pieces, state, self.nqubits, self.qubits.reverse_transpose_order) return state
def _device_execute(self, initial_state=None): """Executes circuit on the specified device and checks for OOM errors.""" device = K.default_device try: with K.device(device): state = self._execute(initial_state=initial_state) except K.oom_error: raise_error( RuntimeError, f"State does not fit in {device} memory." "Please switch the execution device to a " "different one using ``qibo.set_device``.") return state
def prepare(self): """Prepares the gate for application to state vectors.""" self.is_prepared = True targets = K.qnp.cast(self.target_qubits, dtype="int32") controls = K.qnp.cast(self.control_qubits, dtype="int32") qubits = list(self.nqubits - controls - 1) qubits.extend(self.nqubits - targets - 1) qubits = sorted(qubits) with K.device(self.device): self.qubits_tensor = K.cast(qubits, dtype="int32") if self.density_matrix: self.target_qubits_dm = tuple(targets + self.nqubits) self.qubits_tensor_dm = self.qubits_tensor + self.nqubits
def _apply_gates(state, gates, device): """Applies gates on a state using the specified device. Args: state (K.Tensor): State piece tensor to apply the gate to. gates (list): List of gate objects to apply to the state piece. device (str): GPU device to use for gate application. """ with K.device(device): state = K.cast(state) for gate in gates: state = gate(state) return state
def _normalize(self, state): """Normalizes state by summing the norms of each state piece. To be used after ``Collapse`` gates because normalization should be applied collectively and not in each piece seperately. The full calculation happens on CPU. (may not be efficient) """ total_norm = 0 with K.device(self.memory_device): for piece in state.pieces: total_norm += K.sum(K.square(K.abs(piece))) total_norm = K.cast(K.sqrt(total_norm), dtype=state.dtype) for piece in state.pieces: piece.assign(piece / total_norm)
def _sample_shots(self): self._frequencies = None if self.probabilities is None or not self.nshots: raise_error(RuntimeError, "Cannot sample measurement shots if " "a probability distribution is not " "provided.") if math.log2(self.nshots) + self.nqubits > 31: # pragma: no cover # case not covered by GitHub workflows because it requires large example # Use CPU to avoid "aborted" error with K.device(K.get_cpu()): result = K.sample_shots(self.probabilities, self.nshots) else: result = K.cpu_fallback(K.sample_shots, self.probabilities, self.nshots) return result
def assign_pieces(self, full_state): """Splits a full state vector and assigns it to the ``tf.Variable`` pieces. Args: full_state (array): Full state vector as a tensor of shape ``(2 ** nqubits)``. """ if self.pieces is None: self.create_pieces() with K.device(self.device): full_state = K.reshape(full_state, self.shapes["device"]) pieces = [full_state[i] for i in range(self.ndevices)] new_state = K.zeros(self.shapes["device"]) new_state = K.transpose_state(pieces, new_state, self.nqubits, self.qubits.transpose_order) for i in range(self.ndevices): self.pieces[i].assign(new_state[i])
def _special_gate_execute(self, state, gate: Union["BackendGate"]): """Executes special gates on ``memory_device``. Currently special gates are ``Flatten`` or ``CallbackGate``. This method calculates the full state vector because special gates are not implemented for state pieces. """ with K.device(self.memory_device): # Reverse all global SWAPs that happened so far self._revert_swaps(state, reversed(gate.swap_reset)) full_state = state.tensor if isinstance(gate, gates.CallbackGate): gate(full_state) else: full_state = gate(full_state) state.assign_pieces(full_state) # Redo all global SWAPs that happened so far self._revert_swaps(state, gate.swap_reset)
def test_measurement_result_parameters_random(backend, accelerators): test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) set_device_seed(123, accelerators) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RY(0, theta=np.pi * output / 5)) c.add(gates.RX(2, theta=np.pi * output / 4)) result = c(initial_state=np.copy(initial_state)) assert len(output.frequencies()) == 1 set_device_seed(123, accelerators) with K.device(test_device): collapse = gates.M(1, collapse=True) target_state = collapse(K.cast(np.copy(initial_state))) if int(collapse.result.outcome()): target_state = gates.RY(0, theta=np.pi / 5)(target_state) target_state = gates.RX(2, theta=np.pi / 4)(target_state) K.assert_allclose(result, target_state)
def test_measurement_result_parameters_random(backend, accelerators): original_backend = qibo.get_backend() qibo.set_backend(backend) from qibo import K from qibo.tests_new.test_core_gates import random_state test_device = K.cpu_devices[0] if accelerators else K.default_device initial_state = random_state(4) K.set_seed(123) c = models.Circuit(4, accelerators) output = c.add(gates.M(1, collapse=True)) c.add(gates.RY(0, theta=np.pi * output / 5)) c.add(gates.RX(2, theta=np.pi * output / 4)) result = c(initial_state=np.copy(initial_state)) K.set_seed(123) with K.device(test_device): collapse = gates.M(1, collapse=True) target_state = collapse(np.copy(initial_state)) if int(collapse.result.outcome()): target_state = gates.RY(0, theta=np.pi / 5)(target_state) target_state = gates.RX(2, theta=np.pi / 4)(target_state) np.testing.assert_allclose(result, target_state) qibo.set_backend(original_backend)
def device_job(ids, device): for i in ids: with K.device(device): piece = self._device_job(state.pieces[i], queues[i]) state.pieces[i].assign(piece) del(piece)
def calculate_callbacks_distributed(state): with K.device(memory_device): if not isinstance(state, K.tensor_types): state = state.tensor calculate_callbacks(state)
def reprepare(self): with K.device(self.device): self.matrix = K.cast(K.qnp.exp(1j * self.parameters), dtype='DTYPECPX')
def reprepare(self): with K.device(self.device): self.matrix = K.cast(self.construct_unitary(), dtype='DTYPECPX')