def remote_receive_one_qubit(self, virtualNum, cnot_direction=0): """ Recover the qubit from teleportation. Arguments a,b received measurement outcomes from Alice virtualNum number of the virtual qubit corresponding to the EPR pair received """ logging.debug("LOCAL %s: Getting reference to qubit number %d.", self.node.name, virtualNum) # Get a reference to our side of the EPR pair qA = yield self.virtRoot.callRemote("get_virtual_ref", virtualNum) # Create a fresh qubit q = yield self.virtRoot.callRemote("new_qubit_inreg", self.qReg) # Create the GHZ state by entangling the fresh qubit if cnot_direction == 0: yield qA.callRemote("apply_H") yield qA.callRemote("cnot_onto", q) else: yield q.callRemote("apply_H") yield q.callRemote("cnot_onto", qA) if simulaqron_settings.sim_backend == SimBackend.QUTIP.value: # Output state (realRho, imagRho) = yield self.virtRoot.callRemote("get_multiple_qubits", [qA, q]) rho = assemble_qubit(realRho, imagRho) expectedRho = [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]] correct = np.all(np.isclose(rho, expectedRho)) elif simulaqron_settings.sim_backend == SimBackend.PROJECTQ.value: (realvec, imagvec) = yield self.virtRoot.callRemote("get_register_RI", qA) state = [r + (1j * j) for r, j in zip(realvec, imagvec)] expectedState = [1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)] correct = np.all(np.isclose(state, expectedState)) elif simulaqron_settings.sim_backend == SimBackend.STABILIZER.value: (array, _) = yield self.virtRoot.callRemote("get_register_RI", qA) state = StabilizerState(array) expectedState = StabilizerState([[1, 1, 0, 0], [0, 0, 1, 1]]) correct = state == expectedState else: ValueError("Unknown backend {}".format( simulaqron_settings.sim_backend)) return bool(correct)
def alice(cls, qReg, virtRoot, myName, classicalNet, send_end): """ Code to execute for the local client node. Called if all connections are established. Arguments qReg quantum register (twisted object supporting remote method calls) virtRoot virtual quantum ndoe (twisted object supporting remote method calls) myName name of this node (string) classicalNet servers in the classical communication network (dictionary of hosts) """ logging.debug("LOCAL %s: Runing client side program.", myName) # Create a second register newReg = yield virtRoot.callRemote("add_register") # Create 2 qubits qA = yield virtRoot.callRemote("new_qubit_inreg", qReg) qB = yield virtRoot.callRemote("new_qubit_inreg", newReg) # Put qubits A and B in an EPR state yield qA.callRemote("apply_H") yield qA.callRemote("cnot_onto", qB) if simulaqron_settings.sim_backend == SimBackend.QUTIP.value: # Output state (realRho, imagRho) = yield virtRoot.callRemote("get_multiple_qubits", [qA, qB]) rho = assemble_qubit(realRho, imagRho) expectedRho = [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]] correct = np.all(np.isclose(rho, expectedRho)) elif simulaqron_settings.sim_backend == SimBackend.PROJECTQ.value: (realvec, imagvec, _, _, _) = yield virtRoot.callRemote("get_register", qA) state = [r + (1j * j) for r, j in zip(realvec, imagvec)] expectedState = [1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)] correct = np.all(np.isclose(state, expectedState)) elif simulaqron_settings.sim_backend == SimBackend.STABILIZER.value: (array, _, _, _, _) = yield virtRoot.callRemote("get_register", qA) state = StabilizerState(array) expectedState = StabilizerState([[1, 1, 0, 0], [0, 0, 1, 1]]) correct = state == expectedState else: ValueError("Unknown backend {}".format( simulaqron_settings.sim_backend)) send_end.send(correct) reactor.stop()
def got_both(self): """ Recover the qubit from Bob. We should now have a tripartite GHZ state Arguments virtualNum number of the virtual qubit corresponding to the EPR pair received """ logging.debug("LOCAL %s: Got both qubits from Alice and Bob.", self.node.name) # We'll test an operation that will cause a merge of the two remote registers yield self.q1.callRemote("apply_H") yield self.q1.callRemote("cnot_onto", self.q2) if simulaqron_settings.sim_backend == SimBackend.QUTIP.value: # Output state (realRho, imagRho) = yield self.virtRoot.callRemote("get_multiple_qubits", [self.q1, self.q2]) rho = assemble_qubit(realRho, imagRho) expectedRho = [[0.5, 0, 0, 0.5], [0, 0, 0, 0], [0, 0, 0, 0], [0.5, 0, 0, 0.5]] correct = np.all(np.isclose(rho, expectedRho)) elif simulaqron_settings.sim_backend == SimBackend.PROJECTQ.value: (realvec, imagvec) = yield self.virtRoot.callRemote("get_register_RI", self.q1) state = [r + (1j * j) for r, j in zip(realvec, imagvec)] expectedState = [1 / np.sqrt(2), 0, 0, 1 / np.sqrt(2)] correct = np.all(np.isclose(state, expectedState)) elif simulaqron_settings.sim_backend == SimBackend.STABILIZER.value: (array, _) = yield self.virtRoot.callRemote("get_register_RI", self.q1) state = StabilizerState(array) expectedState = StabilizerState([[1, 1, 0, 0], [0, 0, 1, 1]]) correct = state == expectedState else: ValueError("Unknown backend {}".format( simulaqron_settings.sim_backend)) return bool(correct)
def remote_recover_teleport(self, a, b, virtualNum): """ Recover the qubit from teleportation. Arguments a,b received measurement outcomes from Alice virtualNum number of the virtual qubit corresponding to the EPR pair received """ logging.debug("LOCAL %s: Getting reference to qubit number %d.", self.node.name, virtualNum) eprB = yield self.virtRoot.callRemote("get_virtual_ref", virtualNum) # Apply the desired correction info logging.debug("LOCAL %s: Correction info is a=%d, b=%d.", self.node.name, a, b) if b == 1: yield eprB.callRemote("apply_X") if a == 1: yield eprB.callRemote("apply_Z") # Just print the qubit we received if simulaqron_settings.backend == "qutip": print("here") (realRho, imagRho) = yield eprB.callRemote("get_qubit") state = np.array(assemble_qubit(realRho, imagRho), dtype=complex) elif simulaqron_settings.backend == "projectq": realvec, imagvec = yield self.virtRoot.callRemote( "get_register_RI", eprB) state = [r + (1j * j) for r, j in zip(realvec, imagvec)] elif simulaqron_settings.backend == "stabilizer": array, _, = yield self.virtRoot.callRemote("get_register_RI", eprB) state = StabilizerState(array) else: ValueError("Unknown backend {}".format( simulaqron_settings.backend)) print("Qubit is:\n{}".format(state))
def runClientNode(qReg, virtRoot, myName, classicalNet): """ Code to execute for the local client node. Called if all connections are established. Arguments qReg quantum register (twisted object supporting remote method calls) virtRoot virtual quantum ndoe (twisted object supporting remote method calls) myName name of this node (string) classicalNet servers in the classical communication network (dictionary of hosts) """ logging.debug("LOCAL %s: Runing client side program.", myName) # Create 3 qubits q1 = yield virtRoot.callRemote("new_qubit_inreg", qReg) # Prepare the first one in the |-> state # yield q1.callRemote("apply_X") yield q1.callRemote("apply_H") # For information purposes, let's print the state of that qubit if simulaqron_settings.backend == "qutip": realRho, imagRho = yield q1.callRemote("get_qubit") state = np.array(assemble_qubit(realRho, imagRho), dtype=complex) elif simulaqron_settings.backend == "projectq": realvec, imagvec = yield virtRoot.callRemote("get_register_RI", q1) state = [r + (1j * j) for r, j in zip(realvec, imagvec)] elif simulaqron_settings.backend == "stabilizer": array, _ = yield virtRoot.callRemote("get_register_RI", q1) state = StabilizerState(array) else: ValueError("Unknown backend {}".format(simulaqron_settings.backend)) print("Qubit to be teleported is:\n{}".format(state)) # Create qubit for teleportation qA = yield virtRoot.callRemote("new_qubit_inreg", qReg) qB = yield virtRoot.callRemote("new_qubit_inreg", qReg) # Put qubits A and B in an EPR state yield qA.callRemote("apply_H") yield qA.callRemote("cnot_onto", qB) # Send qubit B to Bob # Instruct the virtual node to transfer the qubit remoteNum = yield virtRoot.callRemote("send_qubit", qB, "Bob") logging.debug("LOCAL %s: Remote qubit is %d.", myName, remoteNum) # Apply the local teleportation operations yield q1.callRemote("cnot_onto", qA) yield q1.callRemote("apply_H") a = yield q1.callRemote("measure") b = yield qA.callRemote("measure") logging.debug("LOCAL %s: Correction info is a=%d, b=%d.", myName, a, b) # Tell Bob the number of the virtual qubit so the can use it locally bob = classicalNet.hostDict["Bob"] yield bob.root.callRemote("recover_teleport", a, b, remoteNum) reactor.stop()