diff --git a/docs/demo/Readme.md b/docs/demo/Readme.md new file mode 100644 index 0000000..20dd71a --- /dev/null +++ b/docs/demo/Readme.md @@ -0,0 +1,10 @@ + +# Demo +## This file consist two type of simulation way: +### Continuous application all in one python file: +This able to simulate a large number of node easier, also is easier for development and analysis. +more example and explaination... + +### Descrete application, which each node and settings will have its own seperate file: +Which can be use for complex simulation as well as use in real application +more example and explaination... diff --git a/docs/demo/demo_bb84.ipynb b/docs/demo/demo_bb84.ipynb new file mode 100644 index 0000000..dc0b818 --- /dev/null +++ b/docs/demo/demo_bb84.ipynb @@ -0,0 +1,383 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BB84_Demo\n", + "## import and tools setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import random\n", + "\n", + "from qiskit_network.components import Network\n", + "from qiskit_network.components.storage import QuantumStorage, ClassicalStorage\n", + "from qiskit_network.channels import Channels, QuantumChannels, ClassicalChannels\n", + "from qiskit_network import logger\n", + "from qiskit_network.kernel import Timeline\n", + "\n", + "from qiskit.utils import QuantumInstance\n", + "from qiskit import Aer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# the backend to run the circuit\n", + "qi = QuantumInstance(Aer.get_backend('aer_simulator_statevector'), shots=1)\n", + "\n", + "# pennylane-qiskit plugin may use here, but not sure if plugin will include pennylane-pulse.\n", + "#pennylane = qml.device('default.qubit', wires=1)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Node" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#alice will create its own network, it also can interact with other network, we should auto determind backend.\n", + "network = Network.Environment(name='alice_net', user_nodes=['Alice', 'Bob','Eve'], backend=qi, hardware_node = None) \n", + "\n", + "Alice = network.get_user_node('Alice')\n", + "Bob = network.get_user_node('Bob')\n", + "# so this will be seperate out from normal setup.\n", + "# todo: set eve\n", + "Eve = network.get_user_node('Eve').eve_interception()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create Network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# auto, which it will depend on the action and hardware to determine the timeline length\n", + "timeline = Timeline('auto')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# set all network with idendical setup\n", + "# this will use for storing packet message\n", + "Cstorage = ClassicalStorage()\n", + "# Not sure how quantum storage will works out with real device yet, but we want to simulate the photon components in pulse, \n", + "# there should be some research paper for references in #14 or pennylane photon.\n", + "# todo: need more inventigation to how to tranform it into pulse level\n", + "Qstorage = QuantumStorage(name=\"\", timeline=timeline, num_memories=16,fidelity=0.85, frequency=80e6, efficiency=1, coherence_time=-1, wavelength=500)\n", + "\n", + "# if any settings require qiskit pulse, will automatically turn into qiskit-pulse scheduler, but it only work for clean simulator.\n", + "QKD_QC = QuantumChannels(name=\"\", timeline=timeline,distance = 1000,attenuation=0, polarization_fidelity = 1.0, light_speed=2e-4, frequency=8e7) \n", + "ethernet_CC = ClassicalChannels(name=\"\",timeline=timeline, distance = 1000,delay=1e9)\n", + "#other type of channels, like service channels for other protocols\n", + "# todo: how to setup custom encryption, will need to look into https://github.com/OpenKMIP/PyKMIP/tree/master/kmip/demos\n", + "encrypted_CC = ClassicalChannels(name=\"encrypted data over fiber\",timeline= timeline, distance = 1000,delay=1e9, ) \n", + "\n", + "# todo: what else need to set here, need to learn more about channels from different quantum internet Standardization and latest research\n", + "channels = Channels(Classical=[ethernet_CC,encrypted_CC], Quantum=QKD_QC, ) \n", + "# connection can be any known type of ethernet connection or custom coupling map\n", + "# (which can be useful for vqe optimize quantum network connection, link: https://pennylane.ai/blog/2022/10/the-quantum-internet-and-variational-quantum-optimization/)\n", + "network.setup_all(storage=[Qstorage,Cstorage], channels=channels, connection='mesh') " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## setup Action function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#cascade, reference: https://github.com/upsideon/qkd-qchack-2022/blob/main/qkd/src/cascade.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this will be action of the node whether its a receiver or a sender\n", + "class all_func:\n", + " def __init__(self, sender, receiver, n=10):\n", + " self.sender = sender\n", + " self.receiver = receiver\n", + " self.n = n\n", + "\n", + " self.bit_flips = [None for _ in range(self.n)]\n", + " self.basis_flips = [random.randint(0, 1) for _ in range(self.n)]\n", + " self.num_test_bits = max(self.n // 4, 1)\n", + "\n", + " def distribute_bb84_states(self, conn, epr_socket, sender=False):\n", + " for i in range(self.n):\n", + " # Note that we will need to inlcude other things like bsm node, so this is where everything is differnet\n", + " if sender:\n", + " qc = epr_socket.create_epr(num_qubit=1)\n", + " else:\n", + " qc = epr_socket.receive_epr(num_qubit=1)\n", + "\n", + " if self.basis_flips[i]:\n", + " qc.h(0)\n", + " # todo: maybe include different measurement or settings\n", + " m = qc.run_measure(0,0,)\n", + "\n", + " conn.flush()\n", + " self.bit_flips[i] = int(m)\n", + " return self.bit_flips, self.basis_flips\n", + " \n", + " def estimate_error_rate(self,socket,key,start = None, end = None, sender = True):\n", + " if sender:\n", + " test_outcomes = key[start:end]\n", + " test_indices = start,end\n", + "\n", + " socket.send_structured(StructuredMessage(\"Test indices\", test_indices))\n", + " target_test_outcomes = socket.recv_structured().payload\n", + " socket.send_structured(StructuredMessage(\"Test outcomes\", test_outcomes))\n", + " else:\n", + " test_indices = socket.recv_structured().payload\n", + " start,end = test_indices\n", + " test_outcomes = key[start:end]\n", + "\n", + " #logger.info(f\"bob test indices: {test_indices}\")\n", + " #logger.info(f\"bob test outcomes: {test_outcomes}\")\n", + "\n", + " socket.send_structured(StructuredMessage(\"Test outcomes\", test_outcomes))\n", + " target_test_outcomes = socket.recv_structured().payload\n", + "\n", + " num_error = 0\n", + " for (i1, i2) in zip(test_outcomes, target_test_outcomes):\n", + " #assert i1 == i2\n", + " if i1 != i2:\n", + " num_error += 1\n", + "\n", + " return (num_error / (end - start))*100\n", + " \n", + " def start_sender(self,start, end):\n", + " self.start, self.end = start, end\n", + " bit_flips, basis_flips = self.distribute_bb84_states(\n", + " self.sender, channels.quantum(receiver = self.receiver)\n", + " )\n", + "\n", + " #logger.info(f\"sender outcomes: {bit_flips}\")\n", + " #logger.info(f\"sender theta: {basis_flips}\")\n", + " \n", + " socket = channels.classical(sender = self.sender, receiver = self.receiver)\n", + " error_rate = self.estimate_error_rate(socket,bit_flips, start, end)\n", + "\n", + " socket.send('1' if error_rate<=0.0 else '0')\n", + " return {\n", + " \"error_rate\" : error_rate,\n", + " \"secret_key\" : self.basis_flips,\n", + " }\n", + "\n", + " def start_receiver(self):\n", + " bit_flips, basis_flips = self.distribute_bb84_states(\n", + " self.receiver, channels.quantum(sender = self.receiver), sender = False\n", + " )\n", + "\n", + " #logger.info(f\"receiver outcomes: {bit_flips}\")\n", + " #logger.info(f\"receiver theta: {basis_flips}\")\n", + "\n", + " socket = channels.classical(sender = self.sender, receiver = self.receiver)\n", + " error_rate = self.estimate_error_rate(socket,bit_flips, sender = False)\n", + " \n", + " accept_string = socket.recv()\n", + " accept_key = True if accept_string == '1' else False\n", + " return {\n", + " \"error_rate\" : error_rate,\n", + " \"secret_key\" : self.basis_flips,\n", + " \"accept\" : accept_key\n", + " }\n", + "\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this will insert in the middle of circuit\n", + "def eve(qc):\n", + " result = []\n", + " key_string = random.randint(0, 1)\n", + " if key_string == 0:\n", + " qc.x(0)\n", + " elif key_string == 1:\n", + " qc.h(0)\n", + " # qiskit dynamic circuit here\n", + " result.append(qc.run_measure(0,0))\n", + " Eve.get_classical(Alice, )\n", + " \n", + " \n", + " # todo: eve tracking classical channels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# which may include more function settings, all_func will always include sender and receiver variable to run analysis or any thing.\n", + "network.set_function(all_func, interception=eve)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Action timeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Alice.start_sender(timeline=timeline, receiver=Bob)\n", + "Bob.start_receiver(timeline=timeline, sender=Alice)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# how the overall circuit look like\n", + "network.construct_circuit().draw('mpl')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### start timeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "result = network.run(run_time=False)\n", + "print(result)\n", + "# sample output:\n", + "\"\"\"\n", + "{\"Alice\": {\"error_rate\": 6.2, \"secret_key\": xxxxxx}, \"Bob\": {\"error_rate\": 6.2, \"secret_key\": xxxxxx, \"accept\" : 0} }\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#result.logger" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# visualization the timeline and result with widget, like\n", + "#result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# or setup for individually\n", + "#alice = network.get_node('Alice')\n", + "\n", + "\n", + "# seperate for the node\n", + "#def alice_func(Alice):\n", + "# msg_buff = []\n", + "# distribute_bb84_states(alice, msg_buff, secret_key, network.get_node('eve'))\n", + "# estimate_error_rate(alice,key, )\n", + "#\n", + "#def bob_func(bob):\n", + "# msg_buff = []\n", + "# distribute_bb84_states(bob, msg_buff, secret_key, network.get_node('eve'))\n", + "# estimate_error_rate(bob,key, )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.8.5 ('base')", + "language": "python", + "name": "python3" + }, + "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.8.5 (default, Sep 3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "cfc6018f50c06ad9d7e17a7fe21ab56b98ad21c1ebae78e6fadfee463f6ace79" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/demo/discrete_bb84/alice.py b/docs/demo/discrete_bb84/alice.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/demo/discrete_bb84/bob.py b/docs/demo/discrete_bb84/bob.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/demo/discrete_bb84/network.py b/docs/demo/discrete_bb84/network.py new file mode 100644 index 0000000..e69de29 diff --git a/docs/tutorial/1 different Node.ipynb b/docs/tutorial/1 different Node.ipynb new file mode 100644 index 0000000..a5e12ba --- /dev/null +++ b/docs/tutorial/1 different Node.ipynb @@ -0,0 +1,30 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.0 64-bit", + "language": "python", + "name": "python3" + }, + "language_info": { + "name": "python", + "version": "3.10.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "0cc6fef2abb65beb60a121de5f4f89280da74c656e642b572c90966ff10b4cc0" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/backend/metal_backend.py b/src/backend/metal_backend.py new file mode 100644 index 0000000..70b06d2 --- /dev/null +++ b/src/backend/metal_backend.py @@ -0,0 +1,2 @@ +#where qiskit metal fake backend import and setup will include here. + diff --git a/src/channels/channel.py b/src/channels/channel.py index 5caacf9..051f9e0 100644 --- a/src/channels/channel.py +++ b/src/channels/channel.py @@ -43,4 +43,3 @@ def get_nature(self) -> str: """ Return the nature of the channel: Quantum/Classic. """ - return self.get_nature diff --git a/src/channels/model/binary.py b/src/channels/model/binary.py new file mode 100644 index 0000000..858c6e5 --- /dev/null +++ b/src/channels/model/binary.py @@ -0,0 +1 @@ +# where package drop probability, which mimic the real situation \ No newline at end of file diff --git a/src/channels/model/optical.py b/src/channels/model/optical.py new file mode 100644 index 0000000..7aea744 --- /dev/null +++ b/src/channels/model/optical.py @@ -0,0 +1 @@ +#setting up optical fiber connection, adding condition \ No newline at end of file diff --git a/src/channels/model/wireless.py b/src/channels/model/wireless.py new file mode 100644 index 0000000..2fb3865 --- /dev/null +++ b/src/channels/model/wireless.py @@ -0,0 +1 @@ +# maybe it is setalite connection \ No newline at end of file diff --git a/src/components/network.py b/src/components/network.py new file mode 100644 index 0000000..f04fd1a --- /dev/null +++ b/src/components/network.py @@ -0,0 +1,2 @@ +# here will include and where the node will be build up using rustworkx, reference QuNetSim/component/network + diff --git a/src/components/node.py b/src/components/node.py index f5c399d..619b180 100644 --- a/src/components/node.py +++ b/src/components/node.py @@ -62,4 +62,3 @@ def ports(self) -> list: """ Return ports within the Node. """ - return self.ports diff --git a/src/components/protocols.py b/src/components/protocols.py new file mode 100644 index 0000000..ec51abf --- /dev/null +++ b/src/components/protocols.py @@ -0,0 +1 @@ +#this file will include all the tools for sending keys, reference QuNetSim \ No newline at end of file diff --git a/src/components/storage.py b/src/components/storage.py new file mode 100644 index 0000000..c7d579b --- /dev/null +++ b/src/components/storage.py @@ -0,0 +1 @@ +#here will include quantum storage and classical storage, reference QuNetSim \ No newline at end of file diff --git a/src/kernel/event.py b/src/kernel/event.py new file mode 100644 index 0000000..3efca6b --- /dev/null +++ b/src/kernel/event.py @@ -0,0 +1 @@ +# where saving what node will do \ No newline at end of file diff --git a/src/kernel/eventList.py b/src/kernel/eventList.py new file mode 100644 index 0000000..caea6a0 --- /dev/null +++ b/src/kernel/eventList.py @@ -0,0 +1 @@ +# class for packing event \ No newline at end of file diff --git a/src/kernel/timeline.py b/src/kernel/timeline.py new file mode 100644 index 0000000..807f116 --- /dev/null +++ b/src/kernel/timeline.py @@ -0,0 +1 @@ +# where everything will save and happen here \ No newline at end of file diff --git a/src/utils/cascade.py b/src/utils/cascade.py new file mode 100644 index 0000000..e69de29 diff --git a/src/utils/entanglements.py b/src/utils/entanglements.py new file mode 100644 index 0000000..16e68f6 --- /dev/null +++ b/src/utils/entanglements.py @@ -0,0 +1 @@ +#this file will include all type of entanglements, reference Sequences/entanglement_management \ No newline at end of file diff --git a/src/utils/logging.py b/src/utils/logging.py new file mode 100644 index 0000000..e69de29 diff --git a/src/visual/plot.py b/src/visual/plot.py new file mode 100644 index 0000000..b18ecbe --- /dev/null +++ b/src/visual/plot.py @@ -0,0 +1,2 @@ +#maybe make a thing that can plot something cool, like timeline of all the action, or simple node connection prinout. +