Skip to content
This repository was archived by the owner on Oct 11, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/demo/Readme.md
Original file line number Diff line number Diff line change
@@ -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...
383 changes: 383 additions & 0 deletions docs/demo/demo_bb84.ipynb
Original file line number Diff line number Diff line change
@@ -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
}
Empty file.
Empty file added docs/demo/discrete_bb84/bob.py
Empty file.
Empty file.
Loading