Beispiel #1
0
    def cmd_reset(self, qubit_id, correct=True):
        r"""
        Reset Qubit to \|0\>
        """
        self._logger.debug(f"Reset physical qubit id {qubit_id}")
        virt_qubit = self.get_virt_qubit(qubit_id=qubit_id)
        outcome = yield call_method(virt_qubit, "measure", inplace=True)

        # If state is |1> do correction
        if correct and outcome:
            yield call_method(virt_qubit, "apply_X")
Beispiel #2
0
 def get_virt_qubit_num(self, qubit_id):
     """
     Get NUMBER (not reference!) to virtual qubit in SimulaQron specific to this connection.
     If not found, send back no qubit error.
     """
     # First let's get the general virtual qubit reference, if any
     virt = self.get_virt_qubit(qubit_id=qubit_id)
     num = yield call_method(virt, "get_virt_num")
     return num
Beispiel #3
0
 def apply_two_qubit_gate(self, gate, qubit_id1, qubit_id2):
     self._logger.debug(
         f"Applying {gate} to physical qubit id {qubit_id1} target {qubit_id2}"
     )
     control = self.get_virt_qubit(qubit_id=qubit_id1)
     target = self.get_virt_qubit(qubit_id=qubit_id2)
     if control == target:
         raise ValueError(
             "target and control in two-qubit gate cannot be equal")
     yield call_method(control, gate, target)
Beispiel #4
0
 def apply_rotation(self, axis, angle, qubit_id):
     """
     Apply a rotation of the qubit specified in cmd with an angle specified in xtra
     around the axis
     """
     self._logger.debug(
         f"Applying a rotation around {axis} to physical qubit id {qubit_id}"
     )
     virt_qubit = self.get_virt_qubit(qubit_id=qubit_id)
     yield call_method(virt_qubit, "apply_rotation", axis, angle)
Beispiel #5
0
    def cmd_epr_recv(self, epr_socket_id, qubit_id=None):
        """
        Receive half of epr from another node. Block until qubit is received.
        """
        self._logger.debug(
            f"Asking to receive for EPR socket ID {epr_socket_id}")

        # This will block until a qubit is received.
        no_gen = True
        virt_qubit = None
        ent_info = None
        # recv_timeout is in 100ms (for legacy reasons there are no plans to change it to seconds)
        sleep_time = simulaqron_settings.recv_retry_time
        for _ in range(int(simulaqron_settings.recv_timeout * 0.1 /
                           sleep_time)):
            data = yield call_method(self.factory.virtRoot,
                                     "netqasm_get_epr_recv", epr_socket_id)
            if data:
                no_gen = False
                (virt_qubit, raw_ent_info) = data
                ent_info = self._unpack_ent_info(raw_ent_info=raw_ent_info)
                if isinstance(ent_info, LinkLayerOKTypeK):
                    ent_info = self._update_qubit_id(ent_info=ent_info,
                                                     qubit_id=qubit_id)
                break
            else:
                yield from self._do_wait(delay=sleep_time)
        if no_gen:
            raise TimeoutError("TIMEOUT, no EPR generation received.")

        if isinstance(ent_info, LinkLayerOKTypeK):
            self._logger.debug(
                f"Qubit received for EPR socket ID {epr_socket_id}, "
                f"will use {qubit_id} as physical qubit ID")

            # Once we have the qubit, add it to the local list and send a reply we received it. Note that we will
            # recheck whether it exists: it could have been added by another connection in the mean time
            try:
                self.factory._lock.acquire()

                if qubit_id in self.factory.qubitList:
                    raise RuntimeError(
                        f"Qubit with ID {qubit_id} already in use")

                q = VirtualQubitRef(qubit_id, int(time.time()), virt_qubit)
                self.factory.qubitList[qubit_id] = q
            finally:
                self.factory._lock.release()
        elif isinstance(ent_info, LinkLayerOKTypeM):
            self._logger.debug(
                f"Measure directly EPR request received for EPR socket ID {epr_socket_id}."
            )

        self._handle_epr_response(response=ent_info)
Beispiel #6
0
 def cmd_measure(self, qubit_id, inplace=True):
     """
     Measure
     """
     self._logger.debug(f"Measuring physical qubit id {qubit_id}")
     virt_qubit = self.get_virt_qubit(qubit_id=qubit_id)
     outcome = yield call_method(virt_qubit, "measure", inplace)
     if outcome is None:
         raise RuntimeError("Measurement failed")
     self._logger.debug(f"Measured outcome {outcome}")
     return outcome
Beispiel #7
0
    def cmd_new(self, physical_address):
        """
        Request a new qubit. Since we don't need it, this python NetQASM just provides very crude timing information.
        (return_q_id is used internally)
        (ignore_max_qubits is used internally to ignore the check of number of virtual qubits at the node
        such that the node can temporarily create a qubit for EPR creation.)
        """
        try:
            yield self.factory._lock.acquire()
            virt = yield call_method(self.factory.virtRoot, "new_qubit")
            q_id = physical_address
            q = VirtualQubitRef(q_id, int(time.time()), virt)
            self.factory.qubitList[q_id] = q
            self._logger.info(f"Requested new physical qubit {q_id})")

        finally:
            self.factory._lock.release()
Beispiel #8
0
    def send_epr_half(self, qubit_id, epr_socket_id, remote_node_name,
                      remote_epr_socket_id, ent_info):
        """
        Send qubit to another node.
        """
        # Lookup the virtual qubit from identifier
        virt_num = yield self.get_virt_qubit_num(qubit_id=qubit_id)

        # Update raw entanglement information for remote node
        remote_ent_info = LinkLayerOKTypeK(
            type=ent_info.type,
            create_id=ent_info.create_id,
            logical_qubit_id=qubit_id,
            directionality_flag=1,
            sequence_number=ent_info.sequence_number,
            # NOTE We use EPR socket ID
            purpose_id=remote_epr_socket_id,
            remote_node_id=self.node_id,
            goodness=ent_info.goodness,
            goodness_time=ent_info.goodness_time,
            bell_state=ent_info.bell_state,
        )

        # Send instruction to transfer the qubit
        remote_ent_info = tuple(v.value if isinstance(v, Enum) else v
                                for v in remote_ent_info)
        yield call_method(
            self.factory.virtRoot,
            "netqasm_send_epr_half",
            virt_num,
            remote_node_name,
            epr_socket_id,
            remote_epr_socket_id,
            remote_ent_info,
        )

        self._logger.debug(
            f"Sent half a EPR pair as qubit id {qubit_id} to {remote_node_name}"
        )
        # Remove from active mapped qubits
        self.remove_qubit_id(qubit_id=qubit_id)
Beispiel #9
0
    def send_epr_outcome_half(self, epr_socket_id, remote_node_name,
                              remote_epr_socket_id, ent_info, remote_outcome,
                              remote_basis):
        """
        Send outcome from measure directly to another node.
        """

        # Update raw entanglement information for remote node
        remote_ent_info = LinkLayerOKTypeM(
            type=ent_info.type,
            create_id=ent_info.create_id,
            measurement_outcome=remote_outcome,
            measurement_basis=remote_basis,
            directionality_flag=1,
            sequence_number=ent_info.sequence_number,
            # NOTE We use EPR socket ID
            purpose_id=remote_epr_socket_id,
            remote_node_id=self.node_id,
            goodness=ent_info.goodness,
            bell_state=ent_info.bell_state,
        )

        # Transfer info to remote node
        remote_ent_info = tuple(v.value if isinstance(v, Enum) else v
                                for v in remote_ent_info)
        yield call_method(
            self.factory.virtRoot,
            "netqasm_send_epr_half",
            None,
            remote_node_name,
            epr_socket_id,
            remote_epr_socket_id,
            remote_ent_info,
        )

        self._logger.debug(
            f"Sent half a measure direclty EPR pair to {remote_node_name}")
Beispiel #10
0
 def apply_single_qubit_gate(self, gate, qubit_id):
     virt_qubit = self.get_virt_qubit(qubit_id=qubit_id)
     yield call_method(virt_qubit, gate)