1 / 23

A practical framework for simulating quantum networking protocols over noisy information channels

8 September 2017. Ben Bartlett INQNET – Palo Alto Foundry. A practical framework for simulating quantum networking protocols over noisy information channels. Motivation: q uantum algorithms for classical networks. Using superdense coding to improve fiber optic bandwidth.

cgates
Download Presentation

A practical framework for simulating quantum networking protocols over noisy information channels

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 8 September 2017 Ben Bartlett INQNET –Palo Alto Foundry A practical framework for simulating quantum networking protocols over noisy information channels

  2. Motivation: quantum algorithms for classical networks Using superdense coding to improve fiber optic bandwidth

  3. Introduction – quantum superdense coding • Superdense coding allows you to send two bits with one photon. Alice encodes two bits in the sign and phase of her photon: Alice and Bob share an entangled resource: Bob disentangled sign and phase and reconstructs the bits from measurement:

  4. Superdense coding in networks • Superdense coding for increased transmission rate • Quantum superdense coding allows you to send two classical bits with one photon in a pre-distributed entangled pair • Network distributes entangled pairs between talkative nodes during low-demand times, stored in “memory” • During periods of high demand, entanglement is consumed via QSDC to (up to) double network transmission speed Effective transmission speed Channel use Distribute entangled pairs during down time Spike in network demand Transmission rate is doubled while pairs are being consumed Entanglement distribution doesn’t transmit data

  5. Simulating quantum networks What we can learn from it and how we do it

  6. Simulating quantum networks – motivation • Why simulate? • Simulating quantum networks allows us to test ideas and protocols for technology that is being developed • Over 70% of (classical) network research papers reference a network simulator • No widespread simulation framework for quantum networks • Can help us better define the needed technology to implement a networking idea • Characterize and simulate errors, figure out how to correct / compensate for them • Example: simulating superdense coding scheme realistically with published experimental values • Quantum gates: error rates • Fiber optic lines: attenuation, depolarizing/dephasing errors • Quantum memories: qubit type, coherence times, manipulation fidelity • Quantum node-channel links: properties taken from electro-optic coupling • Given these technologies, how well can our protocol perform?

  7. Simulating quantum networks –a practical framework • SQUANCH – a simulator for quantum networks and channels • SQUANCH is a Python framework for creating performant simulations of quantum information processing and transmission • Computationally optimized for dealing with large numbers of entangled quantum subsystems • Simulating large amounts of entangled photons to transmit classical or quantum data • SQUANCH can also be used as a general-purpose quantum computing library, but it has a different focus: quantum computing vs quantum networks • Existing quantum computing frameworks such as Rigetti Forest and Microsoft LIQ are more developed/flexible • Both are limited to simulating a single system of qubits at a time • Simulating many smaller quantum systems involves lots of computational overhead • SQUANCH is capable of efficiently simulating hundreds of millions of disjoint quantum systems simultaneously

  8. SQUANCH design overview Qubit Agent Channels Gates Errors QSystem QStream • Maintains references to the -qubit parent QSystem and an index ranging from to • Computationally cheap to use • Represents the state of a multi-particle quantum system • Can be instantiated as a wrapper for QStream for better cache locality • Includes methods for applying quantum gates and simulating wavefunction collapse • Applies unitary operators to the state of a QSystem or Qubit • Tensor-expands operators to fit an -qubit system and caches the results • Simulates corruption, attenuation, dephasing errors on qubits • Customizable error models • Represents an ensemble of disjoint -qubit systems • State is shared 1D array of C-doubles, behaves like 3D array of complex64 • Generalizes the notion of an actor (Alice, Bob, etc.) that can send/receive and process classical and quantum information • Run in separate processes • Connected by channels • Simulates noisy classical and quantum channels • Synchronizes clocks between agents on qubit transfer • Inherits configurable error models Qubit Qubit QStream QSystem

  9. Building complex networks in SQUANCH • Agents and channels • Agents are entities that can process and share quantum and classical information • Classical memory and channels • Quantum memory and channels • Simulate errors on qubit transfer and in memory • Processor implemented by overriding agent.run() • Agents maintain their own clocks and memory pools • Different QStreams point to the same region of memory • Channels allow agents to communicate • Channels track speed-of-light delays and synchronize clocks between agents exchanging dependencies • Quantum channels simulate errors on transmitted qubits • Qubits passed by index to channel queues; clocks synchronized and various error models applied on retrieval Quantum-classical “agent” Processor Quantum memory Classical memory Quantum channel Classical channel Quantum channel Apply errors From agent To agent

  10. QStream Apply errors • Memory structure and time-synchronization • Agents run concurrently in their own processes, extend base Agent() class and override run() • Process objects point to shared memory space to operate on Hilbert space • Qubits passed between processes by (system, qubit) index • Natural runtime concurrency safety from qubit ownership (processes block to wait on qubit transfer) alice= Alice(mem, data=data) bob = Bob(mem, out=outDict) Process <Alice> Process <Bob> connectAgents(alice, bob, length=1.0) class Bob(Agent):defrun(self):fori, qSysinenumerate(self.stream): a= self.qrecv(alice)_, b= qSys.qubitsifaisnotNoneandbisnotNone:CNOT(a, b)H(a)self.data[2*i] = a.measure()self.data[2*i+1] = b.measure()self.output(self.data) classAlice(Agent):defrun(self):forqSysinself.stream:bit1 = self.data.pop(0) bit2 = self.data.pop(0)q, _= qSys.qubitsifqisnotNone:ifbit2 == 1: X(q)ifbit1 == 1: Z(q)self.qsend(bob, q) qChannelOut stream other stream cmem qmem cmem qmem qChannelIn other Memory mem = sharedctypes.RawArray(ctypes.c_double, numSystems* dim * dim)arr= np.frombuffer(mem, dtype= np.complex64).reshape((numSystems, dim, dim))QStream.reformatArray(arr) Memory

  11. QStream Apply errors • Memory structure and time-synchronization • Agents maintain their own clocks, synchronize on dependent qubit transfer • Example: Alice is at 1.5 s, Bob is at 2s, separated by 300 m. Alice transfers qubits with 10 ps pulse width to Bob. Alice’s clock is now s, and Bob’s clock is s. • Time-synchronization allows for performance metrics on networking algorithms alice= Alice(mem, data=data) bob = Bob(mem, out=outDict) Process <Alice> Process <Bob> connectAgents(alice, bob, length=1.0) class Bob(Agent):defrun(self):fori, qSysinenumerate(self.stream): a= self.qrecv(alice)_, b= qSys.qubitsifaisnotNoneandbisnotNone:CNOT(a, b)H(a)self.data[2*i] = a.measure()self.data[2*i+1] = b.measure()self.output(self.data) classAlice(Agent):defrun(self):forqSysinself.stream:bit1 = self.data.pop(0) bit2 = self.data.pop(0)q, _= qSys.qubitsifqisnotNone:ifbit2 == 1: X(q)ifbit1 == 1: Z(q)self.qsend(bob, q) qChannelOut stream other stream cmem qmem cmem qmem qChannelIn other Memory mem = sharedctypes.RawArray(ctypes.c_double, numSystems* dim * dim)arr= np.frombuffer(mem, dtype= np.complex64).reshape((numSystems, dim, dim))QStream.reformatArray(arr) Memory

  12. Performance and ease of use How does SQUANCH compare to similar frameworks?

  13. Performance comparisons • Test metric: serializing an image (12800 bits) and sending it via superdense coding over a noisy quantum channel • Results: • IBM Q: • Running locally with Quintuple (Python): 5.47 sec • Rigetti Forest / pyQuil: • Running on Rigetti QVM (Lisp backend): 418.5 sec • Running locally (Python backend): 101.2 sec • SQUANCH (running locally): • Without agents: 0.68 sec • With two agents: 0.78 sec • Key point: not necessarily better; SQUANCH is designed for different use cases than a quantum computing simulator Quantum channel

  14. IBM Q Rigetti Forest Microsoft LIQ SQUANCH (with agents) #if INTERACTIVE #r @"..\bin\Liquid1.dll"                  #else namespace Microsoft.Research.Liquid // Tell the compiler our namespace #endif open System                         // Open any support libraries open Microsoft.Research.Liquid      // Get necessary Liquid libraries open Util                           // General utilites open Operations                     // Basic gates and operations open Tests                          // Just gets us the RenderTest call fordumping module Script =                     // The script module allows forincr. loading     // Define an EPR function let EPR (qs:Qubits) =          H qs; CNOT qs     let teleport (qs:Qubits) = let q0,q1,q2    = qs.[0],qs.[1],qs.[2]      // Extract 3 qubits         // Give names to the first three qubits         LabelL "Src" [q0]         LabelL "\\ket{0}" [q1]         LabelL "\\ket{0}" [q2]         EPR[q1;q2]; CNOT qs; H qs               // EPR 1,2, then CNOT 0,1 and H 0         M[q1]; BC X [q1;q2]                     // Conditionally apply X         M[q0]; BC Z [q0;q2]                     // Conditionally apply Z         LabelR "Dest" [q2]                      // Label output     let teleportRun (teleF:Qubits->unit) (cnt:int) =         show "============ TELEPORT ============="         let k   = Ket()         // Get a random number between -1.0and +1.0 let rVal = let rnd = Random(DateTime.Now.Ticks |> int)             fun () -> 2.0 * rnd.NextDouble() - 1.0 for i in 0..(cnt-1) do letqs      = k.Reset(3)             let q0      =qs.[0]             // Force the first qubit into a random location on the Bloch sphere             q0.StateSet(rVal(),rVal(),rVal(),rVal())             show "Initial State: %O"q0 let _   = teleF qs             show "Final   State: %O (bits:%d%d)"qs.[2] (q0.Bit.v) (qs.[1].Bit.v)         show "=================================="         show ""     [<LQD>] let Teleport()    =         // Run directly         teleportRun teleport 10         // Look up the teleport circuit let ket     = Ket(3) let circ    = Circuit.Compile teleport ket.Qubits let circ2   = circ.Fold()         circ2.Dump()         // Don't do render's if we're really running under HPC (wasn't portable) iftrue then              RenderTest "Teleport" circ ket         // Run the circuit let teleF (qs:Qubits) = circ.Run qs         teleportRun teleF 10         // Maked a wrapped gate out of teleport         let teleGate    =             let gate (qs:Qubits) = new Gate(                     Qubits  = qs.Length,                     Name    = "teleGate",                     Op      = WrapOp teleport                 )             fun (qs:Qubits) -> (gate qs).Run qs let ket     = Ket(3) let circ    = Circuit.Compile teleGate ket.Qubits let circ2   = circ.GrowGates(ket)         show "Original circuit gates: %d" (circ.GateCount())         show "   Grown circuit gates: %d" (circ2.GateCount())         show "Original circuit:"         circ.Dump()         show "Grown circuit:"         circ2.Dump() let teleF (qs:Qubits) = circ2.Run qs         teleportRun teleF 10 #if INTERACTIVE do Script.Teleport()        // If interactive, then run the routine automatically #endif """ Quantum teleportation example based on an OpenQASM example. """ importsys importos sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) fromqiskitimportQuantumProgram importQconfig backend ="ibmqx_qasm_simulator" coupling_map= {0: [1, 2], 1: [2], 2: [], 3: [2, 4], 4: [2]} QPS_SPECS = { "circuits": [{ "name": "teleport", "quantum_registers": [{ "name": "q", "size": 3         }], "classical_registers": [             {"name": "c0", "size": 1},             {"name": "c1", "size": 1},             {"name": "c2", "size": 1},         ]}] } qp=QuantumProgram(specs=QPS_SPECS) qc =qp.get_circuit("teleport") q =qp.get_quantum_register("q") c0 =qp.get_classical_register("c0") c1 =qp.get_classical_register("c1") c2 =qp.get_classical_register("c2") # Prepare an initial state qc.u3(0.3, 0.2, 0.1, q[0]) # Prepare a Bell pair qc.h(q[1]) qc.cx(q[1], q[2]) # Barrier following state preparation qc.barrier(q) # Measure in the Bell basis qc.cx(q[0], q[1]) qc.h(q[0]) qc.measure(q[0], c0[0]) qc.measure(q[1], c1[0]) # Apply a correction qc.z(q[2]).c_if(c0, 1) qc.x(q[2]).c_if(c1, 1) qc.measure(q[2], c2[0]) qp.set_api(Qconfig.APItoken, Qconfig.config["url"]) # Experiment does not support feedback, so we use the simulator # First version: not mapped result =qp.execute(["teleport"], backend=backend, coupling_map=None, shots=1024) print(result) print(result.get_counts("teleport")) # Second version: mapped to qx2 coupling graph result =qp.execute(["teleport"], backend=backend, coupling_map=coupling_map, shots=1024) print(result) print(result.get_ran_qasm("teleport")) print(result.get_counts("teleport")) frompyquil.quilimport Program importpyquil.apiasapi frompyquil.gatesimport X, Z, H, CNOT defmake_bell_pair(q1, q2): """Makes a bell pair between qubits q1 and q2     """ return Program(H(q1), CNOT(q1, q2)) defteleport(start_index, end_index, ancilla_index): """Teleport a qubit from start to end using an ancilla qubit     """     p =make_bell_pair(end_index, ancilla_index) # do the teleportation p.inst(CNOT(start_index, ancilla_index)) p.inst(H(start_index)) # measure the results and store them in registers [0] and [1] p.measure(start_index, 0) p.measure(ancilla_index, 1) p.if_then(1, X(2)) p.if_then(0, Z(2)) p.measure(end_index, 2) return p if __name__ =='__main__': qvm=api.SyncConnection() # initialize qubit 0 in |1> teleport_demo= Program(X(0)) teleport_demo+= teleport(0, 2, 1) print"Teleporting |1> state: ", qvm.run(teleport_demo, [2]) # initialize qubit 0 in |0> teleport_demo= Program() teleport_demo+= teleport(0, 2, 1) print"Teleporting |0> state: ", qvm.run(teleport_demo, [2]) # initialize qubit 0 in |+> teleport_demo= Program(H(0)) teleport_demo+= teleport(0, 2, 1) print"Teleporting |+> state: ", qvm.run(teleport_demo, [2], 10) print Program(X(0)).measure(0, 0).if_then(0, Program(X(1))) fromsquanch.agentimport* fromsquanch.gatesimport* fromsquanch.qstreamimport* classAlice(Agent): '''Alice sends qubits to Bob using a shared Bell pair''' defrun(self): forqSysinself.stream: # Generate a Bell pair and send half of it to Bob             q, a, b =qSys.qubits             H(a)             CNOT(a, b) self.qsend(bob, b) # Perform the teleportation             CNOT(q, a)             H(q) bobZ=q.measure() bobX=a.measure() self.csend(bob, [bobX, bobZ]) classBob(Agent): '''Bob receives qubits from Alice and measures the results''' defrun(self):         results = [] for _ inself.stream:             b =self.qrecv(alice) doX, doZ=self.crecv(alice) ifdoX==1and b isnotNone: X(b) ifdoZ==1and b isnotNone: Z(b) results.append(b.measure()) self.output(results) # Allocate memory and output structures mem =sharedHilbertSpace(3, 10) out =sharedOutputDict() # Prepare the initial states stream =QStream.fromArray(mem) states = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0] forqSys, state inzip(stream, states): if state ==1: X(qSys.qubit(0))  # Flip the qubits for 1's # Make the agents alice=Alice(mem) bob =Bob(mem, out = out) connectAgents(alice, bob, length =0.0) # Run everything alice.start(); bob.start() alice.join(); bob.join() print out["Bob"]

  15. IBM Q Rigetti Forest Microsoft LIQ SQUANCH (without agents) #if INTERACTIVE #r @"..\bin\Liquid1.dll"                  #else namespace Microsoft.Research.Liquid // Tell the compiler our namespace #endif open System                         // Open any support libraries open Microsoft.Research.Liquid      // Get necessary Liquid libraries open Util                           // General utilites open Operations                     // Basic gates and operations open Tests                          // Just gets us the RenderTest call fordumping module Script =                     // The script module allows forincr. loading     // Define an EPR function let EPR (qs:Qubits) =          H qs; CNOT qs     let teleport (qs:Qubits) = let q0,q1,q2    = qs.[0],qs.[1],qs.[2]      // Extract 3 qubits         // Give names to the first three qubits         LabelL "Src" [q0]         LabelL "\\ket{0}" [q1]         LabelL "\\ket{0}" [q2]         EPR[q1;q2]; CNOT qs; H qs               // EPR 1,2, then CNOT 0,1 and H 0         M[q1]; BC X [q1;q2]                     // Conditionally apply X         M[q0]; BC Z [q0;q2]                     // Conditionally apply Z         LabelR "Dest" [q2]                      // Label output     let teleportRun (teleF:Qubits->unit) (cnt:int) =         show "============ TELEPORT ============="         let k   = Ket()         // Get a random number between -1.0and +1.0 let rVal = let rnd = Random(DateTime.Now.Ticks |> int)             fun () -> 2.0 * rnd.NextDouble() - 1.0 for i in 0..(cnt-1) do letqs      = k.Reset(3)             let q0      =qs.[0]             // Force the first qubit into a random location on the Bloch sphere             q0.StateSet(rVal(),rVal(),rVal(),rVal())             show "Initial State: %O"q0 let _   = teleF qs             show "Final   State: %O (bits:%d%d)"qs.[2] (q0.Bit.v) (qs.[1].Bit.v)         show "=================================="         show ""     [<LQD>] let Teleport()    =         // Run directly         teleportRun teleport 10         // Look up the teleport circuit let ket     = Ket(3) let circ    = Circuit.Compile teleport ket.Qubits let circ2   = circ.Fold()         circ2.Dump()         // Don't do render's if we're really running under HPC (wasn't portable) iftrue then              RenderTest "Teleport" circ ket         // Run the circuit let teleF (qs:Qubits) = circ.Run qs         teleportRun teleF 10         // Maked a wrapped gate out of teleport         let teleGate    =             let gate (qs:Qubits) = new Gate(                     Qubits  = qs.Length,                     Name    = "teleGate",                     Op      = WrapOp teleport                 )             fun (qs:Qubits) -> (gate qs).Run qs let ket     = Ket(3) let circ    = Circuit.Compile teleGate ket.Qubits let circ2   = circ.GrowGates(ket)         show "Original circuit gates: %d" (circ.GateCount())         show "   Grown circuit gates: %d" (circ2.GateCount())         show "Original circuit:"         circ.Dump()         show "Grown circuit:"         circ2.Dump() let teleF (qs:Qubits) = circ2.Run qs         teleportRun teleF 10 #if INTERACTIVE do Script.Teleport()        // If interactive, then run the routine automatically #endif """ Quantum teleportation example based on an OpenQASM example. """ importsys importos sys.path.append(os.path.join(os.path.dirname(__file__), '../..')) fromqiskitimportQuantumProgram importQconfig backend ="ibmqx_qasm_simulator" coupling_map= {0: [1, 2], 1: [2], 2: [], 3: [2, 4], 4: [2]} QPS_SPECS = { "circuits": [{ "name": "teleport", "quantum_registers": [{ "name": "q", "size": 3         }], "classical_registers": [             {"name": "c0", "size": 1},             {"name": "c1", "size": 1},             {"name": "c2", "size": 1},         ]}] } qp=QuantumProgram(specs=QPS_SPECS) qc =qp.get_circuit("teleport") q =qp.get_quantum_register("q") c0 =qp.get_classical_register("c0") c1 =qp.get_classical_register("c1") c2 =qp.get_classical_register("c2") # Prepare an initial state qc.u3(0.3, 0.2, 0.1, q[0]) # Prepare a Bell pair qc.h(q[1]) qc.cx(q[1], q[2]) # Barrier following state preparation qc.barrier(q) # Measure in the Bell basis qc.cx(q[0], q[1]) qc.h(q[0]) qc.measure(q[0], c0[0]) qc.measure(q[1], c1[0]) # Apply a correction qc.z(q[2]).c_if(c0, 1) qc.x(q[2]).c_if(c1, 1) qc.measure(q[2], c2[0]) qp.set_api(Qconfig.APItoken, Qconfig.config["url"]) # Experiment does not support feedback, so we use the simulator # First version: not mapped result =qp.execute(["teleport"], backend=backend, coupling_map=None, shots=1024) print(result) print(result.get_counts("teleport")) # Second version: mapped to qx2 coupling graph result =qp.execute(["teleport"], backend=backend, coupling_map=coupling_map, shots=1024) print(result) print(result.get_ran_qasm("teleport")) print(result.get_counts("teleport")) frompyquil.quilimport Program importpyquil.apiasapi frompyquil.gatesimport X, Z, H, CNOT defmake_bell_pair(q1, q2): """Makes a bell pair between qubits q1 and q2     """ return Program(H(q1), CNOT(q1, q2)) defteleport(start_index, end_index, ancilla_index): """Teleport a qubit from start to end using an ancilla qubit     """     p =make_bell_pair(end_index, ancilla_index) # do the teleportation p.inst(CNOT(start_index, ancilla_index)) p.inst(H(start_index)) # measure the results and store them in registers [0] and [1] p.measure(start_index, 0) p.measure(ancilla_index, 1) p.if_then(1, X(2)) p.if_then(0, Z(2)) p.measure(end_index, 2) return p if __name__ =='__main__': qvm=api.SyncConnection() # initialize qubit 0 in |1> teleport_demo= Program(X(0)) teleport_demo+= teleport(0, 2, 1) print"Teleporting |1> state: ", qvm.run(teleport_demo, [2]) # initialize qubit 0 in |0> teleport_demo= Program() teleport_demo+= teleport(0, 2, 1) print"Teleporting |0> state: ", qvm.run(teleport_demo, [2]) # initialize qubit 0 in |+> teleport_demo= Program(H(0)) teleport_demo+= teleport(0, 2, 1) print"Teleporting |+> state: ", qvm.run(teleport_demo, [2], 10) print Program(X(0)).measure(0, 0).if_then(0, Program(X(1))) fromsquanch.gatesimport* fromsquanch.qstreamimport* # Prepare the initial states stream = QStream(3, 10) states = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0] forqSys, state inzip(stream, states): if state ==1: X(qSys.qubit(0))  # Flip the qubits for 1's # Do the teleportation  forqSysin stream:     q, a, b =qSys.qubits     H(a)     CNOT(a, b)     CNOT(q, a)     H(q) ifa.measure(): X(b) ifq.measure(): Z(b) print"Qubit collapses to {}".format(q.measure())

  16. SQUANCH: live coding demo A demonstration of simulating complex scenarios easily with SQUANCH (Alternately, a demonstration of my propensity to make careless coding mistakes)

  17. Simulating the superdense network protocol with agents 648,000 bits sent via 324,000 photons Bob’s image Alice’s image Bob Charlie Alice Classical memory Processor Processor Processor 1km attenuated channel Classical memory Quantum memory Quantum memory 0.5km attenuated channel 0.5km attenuated channel

  18. More simulations: naïve interception attack Eve Bob Charlie Alice Bob’s data is half corrupted, reveals eavesdropper. Eve recovers only random noise. Classical memory Classical memory Processor Processor Processor Processor 0.5km Classical memory Quantum memory Quantum memory 0.5km 0.5km 0.5km

  19. Additional demonstrations, documentation, and more Repository Documentation

  20. Future work Creating a quantum networking playground

  21. Future work • SQUANCH framework development • GPU vectorization • Possible with shared GPU memory in CUDA • Implement more sophisticated characterization of errors in channels and quantum memories • Release the framework as an open source project • In later stages of getting intellectual property rights and licensing from AT&T • Deploy package on pip • Host documentation on readthedocs.io • Things to do with SQUANCH • More demonstrations for documentation • Calgary three-party teleportation experiment (Valivarthi, et al.) • Counterfactual quantum communication (Cao, et al.) • Use SQUANCH to simulate and characterize AT&T + Fermilab teleportation experiments

  22. Ben Bartlett INQNET –Palo Alto Foundry

More Related