-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #169 from sequence-toolbox/RnD
Version 0.6.2
- Loading branch information
Showing
22 changed files
with
1,204 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,360 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Network with Applications\n", | ||
"\n", | ||
"In this file, we'll demonstrate the simulation of a more complicated network topology with applications. These applications will act on each node, requesting memories to be entangled and then recording metrics. The network topology, including hardware components, is shown below:\n", | ||
"\n", | ||
"<img src=\"./images/star_network.png\" width=\"800\"/>\n", | ||
"\n", | ||
"In this file, we construct the network described above and add a custom app to two nodes. Most of the code has been written, but some will need to be filled in. We'll be building the topology from an external json file constructed using the GUI.\n", | ||
"\n", | ||
"## Imports\n", | ||
"We must first import the necessary tools from SeQUeNCe. For building our specific request, we will import:\n", | ||
"\n", | ||
"- `RequestApp` is an example application included with SeQUeNCe. We will investigate its behavior through a class that inherits from this.\n", | ||
"- `Message` is a wrapper for classical messages to exchange between nodes.\n", | ||
"\n", | ||
"Finally, for creating the network itself, we will import:\n", | ||
"\n", | ||
"- `Topology` is a powerful class for creating and managing complex network topologies. We'll be using the `RouterNetTopo` subclass to build our network and intefrace with specific nodes and node types." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from ipywidgets import interact\n", | ||
"import time\n", | ||
"\n", | ||
"# for building application\n", | ||
"from sequence.app.request_app import RequestApp\n", | ||
"from sequence.message import Message\n", | ||
"\n", | ||
"# for building network\n", | ||
"from sequence.topology.router_net_topo import RouterNetTopo" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Custom Application\n", | ||
"\n", | ||
"We may now define our custom application. When receiving an entangled memory, we will announce its reception; we will then use the new `AppMessage` class to communicate results to the other node. The receiving node will wait when receiving an entangled memory. Once the classical message is received from the originator, it will release its local memory to be reused. This mimics the behavior of a teleportation operation." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 13, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"START_TIME = 1e12\n", | ||
"\n", | ||
"class TeleportMessage(Message):\n", | ||
" def __init__(self, msg_type, receiver, memo_name: str):\n", | ||
" super().__init__(msg_type, receiver)\n", | ||
" self.memo_name = memo_name\n", | ||
"\n", | ||
"class TeleportApp(RequestApp):\n", | ||
" def __init__(self, node, name, other_name):\n", | ||
" super().__init__(node)\n", | ||
" self.name = name\n", | ||
" self.other_name = other_name\n", | ||
" node.protocols.append(self)\n", | ||
" self.memos_to_measure = {}\n", | ||
" \n", | ||
" # collect metrics:\n", | ||
" self.latency = 0\n", | ||
" self.count = 0\n", | ||
" \n", | ||
" def get_memory(self, info: \"MemoryInfo\") -> None:\n", | ||
" \"\"\"Method to receive entangled memories.\n", | ||
"\n", | ||
" Will check if the received memory is qualified.\n", | ||
" If it's a qualified memory, the application sets memory to RAW state\n", | ||
" and release back to resource manager.\n", | ||
" The counter of entanglement memories, 'memory_counter', is added.\n", | ||
" Otherwise, the application does not modify the state of memory and\n", | ||
" release back to the resource manager.\n", | ||
"\n", | ||
" Args:\n", | ||
" info (MemoryInfo): info on the qualified entangled memory.\n", | ||
" \"\"\"\n", | ||
"\n", | ||
" if info.state != \"ENTANGLED\":\n", | ||
" return\n", | ||
"\n", | ||
" if info.index in self.memo_to_reserve:\n", | ||
" reservation = self.memo_to_reserve[info.index]\n", | ||
" \n", | ||
" if info.remote_node == reservation.responder and info.fidelity >= reservation.fidelity:\n", | ||
" # we are initiator, and want to teleport qubit\n", | ||
" print(\"node {} memory {} entangled with other memory {}\".format(\n", | ||
" self.node.name, info.index, info.remote_memo))\n", | ||
" \n", | ||
" # record metrics\n", | ||
" if self.count == 0:\n", | ||
" # record latency\n", | ||
" pass\n", | ||
" \n", | ||
" # send message to other node\n", | ||
" message = TeleportMessage(None, self.other_name, info.remote_memo)\n", | ||
" \n", | ||
" # reset local memory\n", | ||
" \n", | ||
" elif info.remote_node == reservation.initiator and info.fidelity >= reservation.fidelity:\n", | ||
" # we are responder, and want to receive qubit\n", | ||
" # need to wait on message from sender to correct entanled memory\n", | ||
" self.memos_to_measure[info.memory.name] = info.memory\n", | ||
" \n", | ||
" def received_message(self, src, message):\n", | ||
" memo_name = message.memo_name\n", | ||
" \n", | ||
" print(\"node {} received teleportation message for memory {}\".format(\n", | ||
" self.node.name, memo_name))\n", | ||
" \n", | ||
" # reset local memory\n", | ||
" memory = self.memos_to_measure.pop(memo_name)\n", | ||
" self.node.resource_manager.update(None, memory, \"RAW\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Building the Simulation\n", | ||
"\n", | ||
"We'll now construct the network and add our applications. This example follows the usual process to ensure that all tools function properly:\n", | ||
"1. Create the topology instance for the simulation to manage our network\n", | ||
" - This class will create a simulation timeline\n", | ||
" - This instantiates the Simulation Kernel (see below)\n", | ||
"2. Create the simulated network topology. In this case, we are using an external JSON file to specify nodes and their connectivity.\n", | ||
" - This includes specifying hardware parameters in the `set_parameters` function, defined later\n", | ||
" - This instantiates the Hardware, Entanglement Management, Resource Management, and Network Management modules\n", | ||
"3. Install custom protocols/applications and ensure all are set up properly\n", | ||
" - This instantiates the Application module\n", | ||
"4. Initialize and run the simulation\n", | ||
"5. Collect and display the desired metrics\n", | ||
"\n", | ||
"The JSON file specifies that network nodes should be of type `QuantumRouter`, a node type defined by SeQUeNCe. This will automatically create all necessary hardware and protocol instances on the nodes, and the `Topology` class will automatically generate `BSMNode` instances on the quantum channels between such nodes.\n", | ||
"\n", | ||
"To construct an application, we need:\n", | ||
"- The node to attach the application to\n", | ||
"- The name of the application instance\n", | ||
"- The name of the node to teleport qubits to.\n", | ||
"\n", | ||
"We can get a list of all desired application nodes, in this case routers, from the `Topology` class with the `get_nodes_by_type` method. We then set an application on each one." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 24, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def test(sim_time=1.5, qc_atten=1e-5):\n", | ||
" \"\"\"\n", | ||
" sim_time: duration of simulation time (s)\n", | ||
" qc_atten: quantum channel attenuation (dB/km)\n", | ||
" \"\"\"\n", | ||
" \n", | ||
" network_config = \"star_network.json\"\n", | ||
" \n", | ||
" # here, we make a new topology using the configuration JSON file.\n", | ||
" # we then modify some of the simulation parameters of the network.\n", | ||
" network_topo = RouterNetTopo(network_config)\n", | ||
" set_parameters(network_topo, sim_time, qc_atten)\n", | ||
" \n", | ||
" # get two end nodes\n", | ||
" start_node_name = \"router1\"\n", | ||
" end_node_name = \"router2\"\n", | ||
" node1 = node2 = None\n", | ||
"\n", | ||
" for router in network_topo.get_nodes_by_type(RouterNetTopo.QUANTUM_ROUTER):\n", | ||
" if router.name == start_node_name:\n", | ||
" node1 = router\n", | ||
" elif router.name == end_node_name:\n", | ||
" node2 = router\n", | ||
" \n", | ||
" start_app_name = \"start_app\"\n", | ||
" end_app_name = \"end_app\"\n", | ||
"\n", | ||
" # create applications\n", | ||
" start_app = None\n", | ||
" end_app = None\n", | ||
" \n", | ||
" # run the simulation\n", | ||
" tl = network_topo.get_timeline()\n", | ||
" tl.show_progress = False\n", | ||
" tl.init()\n", | ||
" \n", | ||
" start_app.start(end_node_name, START_TIME, 2e12, 10, 0.9)\n", | ||
" tick = time.time()\n", | ||
" tl.run()\n", | ||
" \n", | ||
" print(\"\\n\")\n", | ||
" print(\"Execution time: {:.3f} seconds\".format(time.time() - tick))\n", | ||
" \n", | ||
" print(\"\\n\")\n", | ||
" print(\"Latency: {:.3f} s\".format(start_app.latency))\n", | ||
" print(\"Number of entangled memories:\", start_app.count)\n", | ||
" print(\"Average throughput: {:.3f} pairs/s\".format(\n", | ||
" start_app.count / (sim_time - (START_TIME * 1e-12))))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Setting parameters\n", | ||
"\n", | ||
"Here we define the `set_parameters` function we used earlier. This function will take a `Topology` as input and change many parameters to desired values. This will be covered in greater detail in workshop 3.\n", | ||
"\n", | ||
"The simulation time limit will be set using the `get_timeline` method.\n", | ||
"\n", | ||
"Quantum memories and detectors are hardware elements, and so parameters are changed by accessing the hardware included with the `QuantumRouter` and `BSMNode` node types. Many complex hardware elements, such as bsm devices or memory arrays, have methods to update parameters for all included hardware elements. This includes `update_memory_params` to change all memories in an array or `update_detector_params` to change all detectors.\n", | ||
"\n", | ||
"We will also set the success probability and swapping degradation of the entanglement swapping protocol. This will be set in the Network management Module (specifically the reservation protocol), as this information is necessary to create and manage the rules for the Resource Management module.\n", | ||
"\n", | ||
"Lastly, we'll update some parameters of the quantum channels. Quantum channels (and, similarly, classical channels) can be accessed from the `Topology` class as the `qchannels` field. Since these are individual hardware elements, we will set the parameters directly." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def set_parameters(topology, simulation_time, attenuation):\n", | ||
" \"\"\"\n", | ||
" simulation_time: duration of simulation time (s)\n", | ||
" attenuation: attenuation on quantum channels (db/m)\n", | ||
" \"\"\"\n", | ||
" \n", | ||
" PS_PER_S = 1e12\n", | ||
" \n", | ||
" # set timeline stop time\n", | ||
" topology.get_timeline().stop_time = (simulation_time * PS_PER_S)\n", | ||
" \n", | ||
" # set memory parameters\n", | ||
" MEMO_FREQ = 2e3\n", | ||
" MEMO_EXPIRE = 0\n", | ||
" MEMO_EFFICIENCY = 1\n", | ||
" MEMO_FIDELITY = 0.9349367588934053\n", | ||
" for node in topology.get_nodes_by_type(RouterNetTopo.QUANTUM_ROUTER):\n", | ||
" memory_array = node.get_components_by_type(\"MemoryArray\")[0]\n", | ||
" memory_array.update_memory_params(\"frequency\", MEMO_FREQ)\n", | ||
" memory_array.update_memory_params(\"coherence_time\", MEMO_EXPIRE)\n", | ||
" memory_array.update_memory_params(\"efficiency\", MEMO_EFFICIENCY)\n", | ||
" memory_array.update_memory_params(\"raw_fidelity\", MEMO_FIDELITY)\n", | ||
"\n", | ||
" # set detector parameters\n", | ||
" DETECTOR_EFFICIENCY = 0.9\n", | ||
" DETECTOR_COUNT_RATE = 5e7\n", | ||
" DETECTOR_RESOLUTION = 100\n", | ||
" for node in topology.get_nodes_by_type(RouterNetTopo.BSM_NODE):\n", | ||
" bsm = node.get_components_by_type(\"SingleAtomBSM\")[0]\n", | ||
" bsm.update_detectors_params(\"efficiency\", DETECTOR_EFFICIENCY)\n", | ||
" bsm.update_detectors_params(\"count_rate\", DETECTOR_COUNT_RATE)\n", | ||
" bsm.update_detectors_params(\"time_resolution\", DETECTOR_RESOLUTION)\n", | ||
" \n", | ||
" # set entanglement swapping parameters\n", | ||
" SWAP_SUCC_PROB = 0.90\n", | ||
" SWAP_DEGRADATION = 0.99\n", | ||
" for node in topology.get_nodes_by_type(RouterNetTopo.QUANTUM_ROUTER):\n", | ||
" node.network_manager.protocol_stack[1].set_swapping_success_rate(SWAP_SUCC_PROB)\n", | ||
" node.network_manager.protocol_stack[1].set_swapping_degradation(SWAP_DEGRADATION)\n", | ||
" \n", | ||
" # set quantum channel parameters\n", | ||
" ATTENUATION = attenuation\n", | ||
" QC_FREQ = 1e11\n", | ||
" for qc in topology.qchannels:\n", | ||
" qc.attenuation = ATTENUATION\n", | ||
" qc.frequency = QC_FREQ" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Running the Simulation\n", | ||
"\n", | ||
"All that is left is to run the simulation with user input. We'll specify:\n", | ||
"\n", | ||
" sim_time: duration of simulation time (s)\n", | ||
" qc_atten: attenuation on quantum channels (dB/m)\n", | ||
"\n", | ||
"Note that different hardware parameters or network topologies may cause the simulation to run for a very long time." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 25, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"application/vnd.jupyter.widget-view+json": { | ||
"model_id": "3015b584b71c4bcd9eaa6db134a806de", | ||
"version_major": 2, | ||
"version_minor": 0 | ||
}, | ||
"text/plain": [ | ||
"interactive(children=(FloatSlider(value=1.5, description='sim_time', max=2.0, min=1.0), Dropdown(description='…" | ||
] | ||
}, | ||
"metadata": {}, | ||
"output_type": "display_data" | ||
}, | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"<function __main__.test(sim_time=1.5, qc_atten=1e-05)>" | ||
] | ||
}, | ||
"execution_count": 25, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"interact(test, sim_time=(1, 2, 0.1), qc_atten=[0, 1e-5, 2e-5])" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "venv", | ||
"language": "python", | ||
"name": "venv" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.2" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
Oops, something went wrong.