Skip to content

Commit f66fafa

Browse files
committed
Update documentation of the simulaqron.sdk package
1 parent f29cc80 commit f66fafa

File tree

4 files changed

+176
-10
lines changed

4 files changed

+176
-10
lines changed

docs/simulaqron.sdk.rst

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
simulaqron.sdk package
22
======================
33

4-
.. warning:: UPDATE THIS STRUCTURE!
5-
64
Submodules
75
----------
86

9-
simulaqron.run.run module
7+
simulaqron.sdk.broadcast_channel module
8+
-------------------------
9+
10+
.. automodule:: simulaqron.sdk.broadcast_channel
11+
:members:
12+
:undoc-members:
13+
:show-inheritance:
14+
15+
simulaqron.sdk.connection module
1016
-------------------------
1117

12-
.. automodule:: simulaqron.run.run
18+
.. automodule:: simulaqron.sdk.connection
1319
:members:
1420
:undoc-members:
1521
:show-inheritance:
1622

23+
simulaqron.sdk.socket module
24+
-------------------------
25+
26+
.. automodule:: simulaqron.sdk.socket
27+
:members:
28+
:undoc-members:
29+
:show-inheritance:
1730

1831
Module contents
1932
---------------

simulaqron/sdk/broadcast_channel.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,9 @@
44

55

66
class BroadcastChannel(BroadcastChannelBySockets):
7+
"""
8+
Implement a Broadcast channel over sockets
9+
10+
.. warning:: This class is candidate to be deleted. Test and delete if possible!
11+
"""
712
_socket_class = Socket

simulaqron/sdk/connection.py

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ def __init__(
4848
conn_retry_time: float = 0.1,
4949
network_name: str = "default",
5050
):
51+
"""
52+
Main class representing the connection from NetQASM to the SimulaQron simulator.
53+
This class implements the
54+
55+
:param app_name: Name of the app to run.
56+
:type app_name: str
57+
:param app_id: The ID of the application. If not given, a new one will be created.
58+
:type app_id: int | None
59+
:param max_qubits: Maximum number of qubits tu simulate in the simulator.
60+
:type max_qubits: int
61+
:param log_config: Configuration of the logging. Check the documentation of
62+
``netqasm.sdk.config.LogConfig`` for more information about this.
63+
:type log_config: LogConfig
64+
:param epr_sockets: List of ``EPRSocket``s to use in the simulator.
65+
:type epr_sockets: List[EPRSocket]
66+
:param compiler: A transpiler object that transpiles the NetQASM instructions.
67+
:type compiler: Type[SubroutineTranspiler] | None
68+
:param socket_address: A tuple containing a hostname and port to use to connect to the QNodeOS server.
69+
:type socket_address: Tuple[str, int]
70+
:param conn_retry_time: Maximum time in seconds to wait between attempts to connect to the QNoseOS server.
71+
:type conn_retry_time: float
72+
:param network_name: The name of the network to connect to
73+
:type network_name: str
74+
"""
5175
super().__init__(
5276
app_name=app_name,
5377
# NOTE currently node_name and app_name are the same in simulaqron
@@ -98,6 +122,21 @@ def try_connection(
98122
socket_address: Optional[Tuple[str, int]] = None,
99123
network_name: str = "default",
100124
):
125+
"""
126+
Try to establish a connection to the specified node name. The connection can be made
127+
by specifying the ``socket_address`` tuple (as a hostname and port number tuple) or
128+
by specifying the node and network names. In the latter case, SimulaQron will search
129+
for that node and network names on the loaded network configuration, and get the
130+
corresponding socket configuration (hostname and port number) to connect to.
131+
132+
:param name: The name of the node to connect to.
133+
:type name: str
134+
:param socket_address: A hostname-port pair to specify the hostname and port number
135+
to connect to. This argument is optional.
136+
:type socket_address: Tuple[str, int] | None
137+
:param network_name: The name of the network to search the node name.
138+
:type network_name: str
139+
"""
101140
# NOTE using retry_time=None causes an error to be raised of the connection cannot
102141
# be established, which can be used to check if the connection is available
103142
logger.debug("Trying if connection is up yet")
@@ -325,6 +364,9 @@ def _handle_reply(self) -> int:
325364
raise NotImplementedError(f"Unknown return message of type {type(ret_msg)}")
326365

327366
def block(self):
367+
"""
368+
Blocks the handling of new messages until all the pending message IDs are acknowledged.
369+
"""
328370
while len(self._waiting_msg_ids) > 0:
329371
self._logger.debug(
330372
"Blocking and waiting for msg IDs %s", self._waiting_msg_ids
@@ -417,6 +459,15 @@ class GetQubitStateMessage(Message):
417459
TYPE = NewMessageType.GET_QUBIT_STATE
418460

419461
def __init__(self, app_id: int = 0, qubit_id: int = 0):
462+
"""
463+
Implements a specific NetQASM message to get the state of a qubit from the
464+
SimulaQron simulator.
465+
466+
:param app_id: The app ID to get the qubit from.
467+
:type app_id: int
468+
:param qubit_id: The qubit ID to retrieve the state.
469+
:type qubit_id: int
470+
"""
420471
super().__init__(self.TYPE.value)
421472
self.app_id = app_id
422473
self.qubit_id = qubit_id
@@ -431,8 +482,6 @@ class NewReturnMessageType(Enum):
431482

432483

433484
class RichErrorMessage(ReturnMessage):
434-
"""Enriched message to the Host that an error occurred at the quantum node controller."""
435-
436485
_fields_ = [
437486
("err_code", ctypes.c_uint8),
438487
("err_msg_len", ctypes.c_uint32),
@@ -443,6 +492,14 @@ class RichErrorMessage(ReturnMessage):
443492
TYPE = NewReturnMessageType.ERR
444493

445494
def __init__(self, err_code: ErrorCode, err_msg: str):
495+
"""
496+
Enriched message to the Host that an error occurred at the quantum node controller.
497+
498+
:param err_code: The error code to report.
499+
:type err_code: ErrorCode
500+
:param err_msg: The error message.
501+
:type err_msg: str
502+
"""
446503
super().__init__(self.TYPE.value)
447504
err_bytes = err_msg.encode("utf-8")
448505
if len(err_bytes) > MAX_ERR_MSG_LEN:
@@ -471,6 +528,16 @@ class ReturnQubitStateMessage(ReturnMessage):
471528
TYPE = NewReturnMessageType.RET_QUBIT_STATE
472529

473530
def __init__(self, qubit_id: int, real_part: List[List[float]], imag_part: List[List[float]]):
531+
"""
532+
Specific NetQASM message used to transmit the qubit state back to the application.
533+
534+
:param qubit_id: The qubit ID.
535+
:type qubit_id: int
536+
:param real_part: The real part of the qubit state.
537+
:type real_part: List[List[float]]
538+
:param imag_part: The imaginary part of the qubit state.
539+
:type imag_part: List[List[float]]
540+
"""
474541
super().__init__(self.TYPE.value)
475542

476543
# Sanity checks - given matrices are square
@@ -558,12 +625,26 @@ def _get_node_name(cls, node_id: int) -> str:
558625

559626
@classmethod
560627
def get_node_id_for_app(cls, app_name: str) -> int:
561-
"""Returns the node id for the app with the given name"""
628+
"""
629+
Returns the node id for the app with the given name.
630+
631+
:param app_name: The app name.
632+
:type app_name: str
633+
:return: The node ID.
634+
:rtype: int
635+
"""
562636
# NOTE app_name and node_name are for now the same in simulaqron
563637
return cls._get_node_id(node_name=app_name)
564638

565639
@classmethod
566640
def get_node_name_for_app(cls, app_name: str) -> str:
567-
"""Returns the node name for the app with the given name"""
641+
"""
642+
Returns the node name for the app with the given name.
643+
644+
:param app_name: The app name.
645+
:type app_name: str
646+
:return: The node name.
647+
:rtype: str
648+
"""
568649
# NOTE app_name and node_name are for now the same in simulaqron
569650
return app_name

simulaqron/sdk/socket.py

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,42 @@ def __del__(self):
4444
self.close()
4545

4646
def close(self):
47+
"""
48+
Closes this socket. Mo more messages can be sent or received after
49+
invoking this method.
50+
"""
4751
if self._app_socket:
4852
self._app_socket.close()
4953

5054
def send(self, msg: str):
51-
"""Sends a message to the remote node."""
55+
"""
56+
Sends a message to the remote node.
57+
58+
:param msg: The message to send.
59+
:type msg: str
60+
"""
5261
self._logger.debug("Sending msg '%s'", msg)
5362
raw_msg = self._serialize_msg(msg=msg)
5463
self._app_socket.send(raw_msg)
5564

5665
def send_structured(self, msg: StructuredMessage):
66+
"""
67+
Sends a message to the remote node as a ``StructuredMessage`` object.
68+
69+
:param msg: The message to send.
70+
:type msg: StructuredMessage
71+
"""
5772
self._logger.debug("Sending structured msg '%s'", msg)
5873
raw_msg = self._serialize_structured_msg(msg=msg)
5974
self._app_socket.send(raw_msg)
6075

6176
def send_silent(self, msg: str):
77+
"""
78+
Sends a message to the remote node without logging it.
79+
80+
:param msg: The message to send.
81+
:type msg: str
82+
"""
6283
self.send(msg)
6384

6485
def _base_recv(self, block: bool, timeout: float, maxsize: int) -> bytes:
@@ -80,7 +101,18 @@ def recv(
80101
timeout: Optional[float] = None,
81102
maxsize: Optional[int] = 1024
82103
) -> str:
83-
"""Receive a message from the remote node."""
104+
"""
105+
Receive a message from the remote node.
106+
107+
:param block: Whether the underlying read operation should be blocking or not.
108+
:type block: bool
109+
:param timeout: Max time (in seconds) to wait for a message from the remote.
110+
:type timeout: float | None
111+
:param maxsize: Maximum size of bytes to read from the remote.
112+
:type maxsize: int | None
113+
:return: The received message as a string.
114+
:rtype: str
115+
"""
84116
self._logger.debug("Receiving msg")
85117
raw_msg = self._base_recv(block, timeout, maxsize)
86118
msg = self._deserialize_msg(raw_msg=raw_msg)
@@ -93,6 +125,18 @@ def recv_structured(
93125
timeout: Optional[float] = None,
94126
maxsize: Optional[int] = 1024,
95127
) -> StructuredMessage:
128+
"""
129+
Receives a message from the remote node and parses it as a ``StructuredMessage``.
130+
131+
:param block: Whether the underlying read operation should be blocking or not.
132+
:type block: bool
133+
:param timeout: Max time (in seconds) to wait for a message from the remote.
134+
:type timeout: float | None
135+
:param maxsize: Maximum size of bytes to read from the remote.
136+
:type maxsize: int | None
137+
:return: The parsed message.
138+
:rtype: StructuredMessage
139+
"""
96140
self._logger.debug("Receiving structured msg")
97141
raw_msg = self._base_recv(block, timeout, maxsize)
98142
msg = self._deserialize_structured_msg(raw_msg=raw_msg)
@@ -105,6 +149,20 @@ def recv_silent(
105149
timeout: Optional[float] = None,
106150
maxsize: Optional[int] = None,
107151
) -> str:
152+
"""
153+
Receives a message without logging it. All arguments passed to this
154+
invocation are ignored. For more fine-grain control, please check the
155+
:py:meth:`recv` method.
156+
157+
:param block: Ignored
158+
:type block: bool
159+
:param timeout: Ignored
160+
:type timeout: float | None
161+
:param maxsize: Ignored
162+
:type maxsize: int | None
163+
:return: The received message.
164+
:rtype: str
165+
"""
108166
return self.recv()
109167

110168
@staticmethod
@@ -125,6 +183,15 @@ def _deserialize_structured_msg(raw_msg: bytes) -> StructuredMessage:
125183

126184
@property
127185
def is_server(self) -> bool:
186+
"""
187+
Check whether the local end of this socket will be acting as server or not. The decision
188+
is made based on the node names: the name which is alphabetically before will act as server.
189+
For example: If the socket connects "Alice" with "Bob", "Alice" will act as server, since
190+
the string "Alice" comes lexicographically before the string "Bob".
191+
192+
:return: Whether this end of the socket should act as server or not.
193+
:rtype: bool
194+
"""
128195
# Server will always be the "first"
129196
return self._node_name < self._remote_node_name
130197

0 commit comments

Comments
 (0)