Template: Getting started ========================= SimulaQron provides two starter templates in ``examples/new-sdk/``: - ``template-quantum-local/`` — single node, local qubit operations only - ``template-client-server/`` — two nodes with classical messaging and quantum operations Single-node template -------------------- The simplest possible program: create a qubit, apply gates, measure. Found in ``examples/new-sdk/template-quantum-local/nodeTest.py``:: def run_node(this_node_name: str) -> int: # sim_conn is our connection to the quantum backend (SimulaQron). # All qubit operations are queued through this connection. sim_conn = NetQASMConnection(this_node_name) # Create a qubit — note we pass sim_conn so the backend knows where # to allocate it. q = Qubit(sim_conn) # Perform some local quantum operations q.H() q.X() m1 = q.measure() # flush() executes all queued quantum operations and makes measurement # results available. Before flush(), m1 is just a future/promise. sim_conn.flush() # int(m) extracts the measurement outcome — only valid after flush(). m1_val = int(m1) sim_conn.close() return m1_val Key points: - ``NetQASMConnection`` connects to the local SimulaQron backend, not to another node. - ``Qubit(sim_conn)`` allocates a qubit on that backend. - Gates like ``H()``, ``X()`` are queued — nothing executes until ``flush()``. - ``int(m)`` only works after ``flush()``. Client-server template ---------------------- For two-node programs, one node runs as a **client** and the other as a **server**. Found in ``examples/new-sdk/template-client-server/``. The server (``nodeTest-server.py``) starts first and listens for connections:: server = SimulaQronClassicalServer(sockets_config, "Bob") server.register_client_handler(run_bob) server.start_serving() The client (``nodeTest-client.py``) connects to the server:: client = SimulaQronClassicalClient(sockets_config) results = client.run_client("Bob", run_alice) Both ``run_alice`` and ``run_bob`` receive ``(reader, writer)`` for classical messaging. Inside these functions you can also create quantum connections:: async def run_alice(reader: StreamReader, writer: StreamWriter): # Classical messaging writer.write(b"Hello World") answer = await reader.read(100) # Quantum operations epr_socket = EPRSocket("Bob") sim_conn = NetQASMConnection("Alice", epr_sockets=[epr_socket]) epr = epr_socket.create_keep()[0] m = epr.measure() sim_conn.flush() result = int(m) sim_conn.close() Configuration files ------------------- ``simulaqron_network.json`` defines the nodes and their socket ports:: [ { "name": "default", "nodes": [ { "Alice": { "app_socket": ["localhost", 8821], "qnodeos_socket": ["localhost", 8822], "vnode_socket": ["localhost", 8823] } }, { "Bob": { "app_socket": ["localhost", 8831], "qnodeos_socket": ["localhost", 8832], "vnode_socket": ["localhost", 8833] } } ], "topology": null } ] ``simulaqron_settings.json`` configures the simulation backend:: { "max_qubits": 20, "max_registers": 1000, "sim_backend": "qutip", ... } Use ``qutip`` backend by default. Use ``stabilizer`` when you need Clifford gates. Running ------- :: cd examples/new-sdk/template-client-server bash run.sh