Skip to content

Commit

Permalink
fix toffoli gate bug
Browse files Browse the repository at this point in the history
  • Loading branch information
bencbartlett committed Jul 12, 2018
1 parent 9a6e8f7 commit 556bedf
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 82 deletions.
22 changes: 21 additions & 1 deletion demos/man-in-the-middle-attack.ipynb

Large diffs are not rendered by default.

34 changes: 13 additions & 21 deletions demos/quantum-error-correction-shor-code.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -101,7 +101,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -139,7 +139,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -163,7 +163,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -206,7 +206,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -228,7 +228,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -259,13 +259,13 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7a5887a58ffd480c995c55512ae2c536",
"model_id": "29229dbd4cdb4c03a636b18faa750908",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -279,7 +279,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b80e8f7dccf54f6cbc63da783e8c9007",
"model_id": "db9e516734df46b5ab3f21dc59288085",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -293,7 +293,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "57a92036d4d74232b933229dc840d8f7",
"model_id": "42a5f6f17b8544e2870fdcef92a08a05",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -307,7 +307,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f9daa1c577c94ed49bca6ae20f5a57fe",
"model_id": "a45e2384cc50465c8b78d03ff66da44c",
"version_major": 2,
"version_minor": 0
},
Expand All @@ -327,8 +327,7 @@
"\n",
"\n",
"DumbAlice sent: Peter Shor once lived in Ruddock 238! But who was Airman?\n",
"DumbBob received: \u0007fá[0\u0013`ëf%\u0006\u000f§} ÍéþE~¼åNª\u0018Ôdf.ãs\"2a=#°ƒ[Ô _d 9\u0017\u0000\u0001\u001e",
"bNiv7\n",
"DumbBob received: Ò$tu€>›èk`Bn+ú%\u0002jé$\u0017A(`l¬ÒÍPäz#\u0007(Á{Ø5$Z·P$i|#}\u0001{ k+pi#®\n",
"\n",
"Alice sent: Peter Shor once lived in Ruddock 238! But who was Airman?\n",
"Bob received: Peter Shor once lived in Ruddock 238! But who was Airman?\n"
Expand All @@ -353,7 +352,7 @@
"# Alice and Bob will use error correction\n",
"alice = Alice(mem, out)\n",
"bob = Bob(mem, out)\n",
"alice.qconnect(bob)#, ShorQChannel)\n",
"alice.qconnect(bob, ShorQChannel)\n",
"\n",
"# Dumb agents won't use error correction\n",
"mem2 = copy.deepcopy(mem)\n",
Expand All @@ -370,13 +369,6 @@
"print(\"Alice sent: {}\".format(msg))\n",
"print(\"Bob received: {}\".format(from_bits(out[\"Bob\"])))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
6 changes: 3 additions & 3 deletions demos/quantum-teleportation.ipynb

Large diffs are not rendered by default.

78 changes: 49 additions & 29 deletions demos/superdense-coding.ipynb

Large diffs are not rendered by default.

46 changes: 32 additions & 14 deletions docs/source/demos/superdense-coding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ We'll be using the above circuit diagram to describe a three-party quantum super

3. Bob disentangles the X and Z components of the qubit by applying CNOT and H to Alice's qubit and Charlie's qubit. He then measures each of Alice's and Charlie's qubits to obtain :math:`b_1` and :math:`b_2`, respectively.

We'll also use SQUANCH's built-in timing functionality to track the simulated time for each agent to complete their part of the protocol assuming a photon pulse interval of 1ns.

Implementation
--------------

Expand Down Expand Up @@ -48,6 +50,7 @@ Now, as usual, we'll want to define child `Agent` classes that implement the beh
CNOT(a, b)
self.qsend(alice, a)
self.qsend(bob, b)
self.output({"t": self.time})
For Alice, we'll want to include the transmission behavior. We'll pass in the data that she wants to transmit as a 1D array in an input argument when we instantiate her, and it will be stored in `self.data`.

Expand All @@ -64,6 +67,7 @@ For Alice, we'll want to include the transmission behavior. We'll pass in the da
if bit2 == 1: X(q)
if bit1 == 1: Z(q)
self.qsend(bob, q)
self.output({"t": self.time})
Finally, for Bob, we'll want to include the disentangling and measurement behavior, and we'll want to output his measured data using `self.output`, which passes it to the parent process through the `sharedOutputDict` that is provided to agents on instantiation.

Expand All @@ -82,7 +86,7 @@ Finally, for Bob, we'll want to include the disentangling and measurement behavi
bits.extend([a.measure(), c.measure()])
else:
bits.extend([0,0])
self.output(bits)
self.output({"t": self.time, "bits": bits})
Now, we want to instantiate Alice, Bob, and Charlie, and run the protocol. To do this, we'll need to pass in the data that Alice will send to Bob (which will be an image serialized to a 1D array of bits), and we'll also need to provide the agents with appropriate arguments for the Hilbert space they will share as well as an output structure to push their data to. (This is necessary because all agents run in separate processes, so explicitly shared memory structures must be passed to them.)

Expand All @@ -101,6 +105,11 @@ Now, we want to instantiate Alice, Bob, and Charlie, and run the protocol. To do
bob = Bob(mem, out)
charlie = Charlie(mem, out)
# Set photon transmission rate
alice.pulse_length = 1e-9
bob.pulse_length = 1e-9
charlie.pulse_length = 1e-9
For agents to communicate with each other, they must be connected via quantum or classical channels. The `Agent.qconnect` and `Agent.cconnect` methods add a bidirectional quantum or classical channel, repsectively, to two agent instances and take as arguments a channel model and associated keyword arguments. SQUANCH includes several built-in rudimentary channel models, including a fiber optic cabel model which simulates attenuation errors. Let's say that Alice and Bob are separated by a 1km fiber optic cable, and Charlie is at the midpoint, 0.5km away from each.

.. code:: python
Expand All @@ -115,24 +124,33 @@ Once we've connected the agents, we just need to run all of the agent processes
.. code:: python
# Run the agents
start = time.time()
Simulation(alice, bob, charlie).run()
print("Transmitted {} bits in {:.3f}s.".format(len(out["Bob"]), time.time() - start))
start = time.time()
Simulation(alice, bob, charlie).run()
print("Transmitted {} bits in {:.3f}s.".format(len(out["Bob"]), time.time() - start))
t_alice, t_bob, t_charlie = out["Alice"]["t"], out["Bob"]["t"], out["Charlie"]["t"]
print("Simulated time: Alice: {:.2e}s, Bob: {:.2e}s, Charlie: {:.2e}s"
.format(t_alice, t_bob, t_charlie))
.. parsed-literal::
Transmitted 2 bits in 74.323s.
Simulated time: Alice: 4.16e-04s, Bob: 4.20e-04s, Charlie: 4.15e-04s
Finally, let's retrieve Bob's data and repackage it into an image array, then compare the results.

.. code:: python
received = np.reshape(np.packbits(out["Bob"]), img.shape)
f, ax = plt.subplots(1, 2, figsize = (8, 4))
ax[0].imshow(received)
ax[0].axis('off')
ax[0].title.set_text("Alice's image")
ax[1].imshow(received)
ax[1].axis('off')
ax[1].title.set_text("Bob's image")
plt.tight_layout()
plt.show()
received = np.reshape(np.packbits(out["Bob"]["bits"]), img.shape)
f, ax = plt.subplots(1, 2, figsize = (8, 4))
ax[0].imshow(img)
ax[0].axis('off')
ax[0].title.set_text("Alice's image")
ax[1].imshow(received)
ax[1].axis('off')
ax[1].title.set_text("Bob's image")
plt.tight_layout()
plt.show()
.. image:: ../img/transmissionDemo.png

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="SQUANCH",
version="0.0.2",
version="1.0.0",
author="Ben Bartlett",
author_email="[email protected]",
description="Simulator for Quantum Networks and Channels",
Expand Down
21 changes: 9 additions & 12 deletions squanch/gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,15 @@ def TOFFOLI(control1, control2, target):
key = "CCNOT" + str(c1) + "," + str(c2) + "," + str(target.index)
# Generate the gate if needed
if key not in _expandedGateCache:
# Represent CCNOT(i,j) as |0i><0i| x |0j><0j| x I x ... x I + |1i><1i| x |1j><1j| x I x ... x Xtarg x I x ...
proj0ij = linalg.tensors([
linalg.tensors([np.eye(2)] * c1), _M0,
linalg.tensors([np.eye(2)] * (c2 - (c1 + 1))), _M0,
linalg.tensors([np.eye(2)] * (num_qubits - (c2 + 1)))
])
proj1gates = [_I for _ in range(num_qubits)]
proj1gates[c1] = _M1
proj1gates[c2] = _M1
proj1gates[target.index] = _X
proj1ijk = linalg.tensors(proj1gates)
CNOTijk = proj0ij + proj1ijk
gates_list = [[_M0, _M0, _I], [_M0, _M1, _I], [_M1, _M0, _I], [_M1, _M1, _X]]
CNOTijk = 0
for gates in gates_list:
ops = [_I for _ in range(num_qubits)]
ops[c1] = gates[0]
ops[c2] = gates[1]
ops[target.index] = gates[2]
operator = linalg.tensors(ops)
CNOTijk += operator
# Cache the gate
_expandedGateCache[key] = CNOTijk
# Apply the gate
Expand Down
2 changes: 1 addition & 1 deletion squanch/qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def __init__(self, num_qubits, index = None, state = None):
self.index = index
# Register the state or generate a new one
if state is not None:
self.state = state # density matrix should be passed by reference and will modiy the QStream.state
self.state = state # density matrix should be passed by reference and will modify the QStream.state
else:
# Initialize each qubit state
initial_qubit_state = np.outer(_0, _0) # each qubit is initialized as |0><0|
Expand Down

0 comments on commit 556bedf

Please sign in to comment.