Пример #1
0
 def probabilities(self, qubits=None, measurement_gate=None):
     unmeasured_qubits = tuple(i for i in range(self.nqubits)
                               if i not in qubits)
     tensor = self.tensor
     with K.on_cpu():
         state = K.reshape(K.square(K.abs(tensor)), self.nqubits * (2, ))
         return K.sum(state, axis=unmeasured_qubits)
Пример #2
0
def test_qaoa_callbacks(backend, accelerators):
    from qibo import callbacks
    # use ``Y`` Hamiltonian so that there are no errors
    # in the Trotter decomposition
    if accelerators:
        with K.on_cpu():
            h = hamiltonians.Y(5)
    else:
        h = hamiltonians.Y(5)
    energy = callbacks.Energy(h)
    params = 0.1 * np.random.random(4)
    state = random_state(5)

    ham = hamiltonians.Y(5, dense=False)
    qaoa = models.QAOA(ham, callbacks=[energy], accelerators=accelerators)
    qaoa.set_parameters(params)
    final_state = qaoa(np.copy(state))

    h_matrix = K.to_numpy(h.matrix)
    m_matrix = K.to_numpy(qaoa.mixer.matrix)
    calc_energy = lambda s: (s.conj() * h_matrix.dot(s)).sum()
    target_state = np.copy(state)
    target_energy = [calc_energy(target_state)]
    for i, p in enumerate(params):
        if i % 2:
            u = expm(-1j * p * m_matrix)
        else:
            u = expm(-1j * p * h_matrix)
        target_state = u @ target_state
        target_energy.append(calc_energy(target_state))
    K.assert_allclose(energy[:], target_energy)
Пример #3
0
 def create_pieces(self):
     """Creates :class:`qibo.core.states.DistributedState` pieces on CPU."""
     n = 2**self.nlocal
     with K.on_cpu():
         self.pieces = [
             K.cpu_tensor(K.zeros(n)) for _ in range(self.ndevices)
         ]
Пример #4
0
 def zero_state(cls, circuit):
     """Creates ``|00...0>`` as a distributed state."""
     state = cls(circuit)
     state.create_pieces()
     with K.on_cpu():
         piece = K.initial_state(nqubits=state.nlocal)
         state.pieces[0] = K.cpu_tensor(piece, dtype=state.dtype)
     return state
Пример #5
0
    def assign_pieces(self, tensor):
        """Assigns state pieces from a given full state vector.

        Args:
            tensor (K.Tensor): The full state vector as a tensor supported by
                the underlying backend.
        """
        if self.pieces is None:
            self.create_pieces()
        with K.on_cpu():
            tensor = K.reshape(K.cpu_cast(tensor), self.shapes["device"])
            pieces = [tensor[i] for i in range(self.ndevices)]
            new_tensor = K.zeros(self.shapes["device"])
        with K.on_cpu():
            new_tensor = K.transpose_state(pieces, new_tensor, self.nqubits,
                                           self.qubits.transpose_order)
        for i in range(self.ndevices):
            K.cpu_assign(self, i, new_tensor[i])
Пример #6
0
 def plus_state(cls, circuit):
     """Creates ``|++...+>`` as a distributed state."""
     state = cls(circuit)
     with K.on_cpu():
         n = K.cast(2**state.nlocal, dtype=K.dtypes('DTYPEINT'))
         norm = K.cast(2**float(state.nqubits / 2.0))
         state.pieces = [
             K.cpu_tensor(K.ones(n) / norm) for _ in range(state.ndevices)
         ]
     return state
Пример #7
0
    def _special_gate_execute(self, state, gate: Union["BackendGate"]):
        """Executes special gates on CPU.

        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.on_cpu():
            # Reverse all global SWAPs that happened so far
            self._revert_swaps(state, reversed(gate.swap_reset))
            full_state = state.tensor
        with K.on_cpu():
            if isinstance(gate, gates.CallbackGate):
                gate(full_state)
            else:
                full_state = gate(full_state)
                state.assign_pieces(full_state)
        with K.on_cpu():
            # Redo all global SWAPs that happened so far
            self._revert_swaps(state, gate.swap_reset)
Пример #8
0
    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.on_cpu():
                tensor = K.concatenate([x[K.newaxis] for x in self.pieces],
                                       axis=0)
                tensor = K.reshape(tensor, self.shapes["full"])
        elif self.qubits.list == list(range(self.nlocal, self.nqubits)):
            with K.on_cpu():
                tensor = K.concatenate([x[:, K.newaxis] for x in self.pieces],
                                       axis=1)
                tensor = K.reshape(tensor, self.shapes["full"])
        else:  # fall back to the transpose op
            with K.on_cpu():
                tensor = K.zeros(self.shapes["full"])
                tensor = K.transpose_state(self.pieces, tensor, self.nqubits,
                                           self.qubits.reverse_transpose_order)
        return tensor
def set_device_seed(seed, accelerators):
    if accelerators:
        with K.on_cpu():
            K.set_seed(seed)
    else:
        K.set_seed(seed)
Пример #10
0
 def _device(self):
     return K.on_cpu()
Пример #11
0
 def calculate_callbacks_distributed(state):
     with K.on_cpu():
         if not isinstance(state, K.tensor_types):
             state = state.tensor
     with K.on_cpu():
         calculate_callbacks(state)