def qubit_send_w_retransmission(host, q_size, receiver_id, checksum_size_per_qubit): """ Sends the data qubits along with checksum qubits , with the possibility of retransmission. :param host: Sender of qubits :param q_size: Number of qubits to be sent :param receiver_id: ID of the receiver :param checksum_size_per_qubit: Checksum qubit per data qubit size :return: """ bit_arr = np.random.randint(2, size=q_size) print('Bit array to be sent: ' + str(bit_arr)) qubits = [] for i in range(q_size): q_tmp = Qubit(host) if bit_arr[i] == 1: q_tmp.X() qubits.append(q_tmp) check_qubits = host.add_checksum(qubits, checksum_size_per_qubit) checksum_size = int(q_size / checksum_size_per_qubit) qubits.append(check_qubits) checksum_cnt = 0 for i in range(q_size + checksum_size): if i < q_size: q = qubits[i] else: q = qubits[q_size][checksum_cnt] checksum_cnt = checksum_cnt + 1 q_success = False got_ack = False number_of_retransmissions = 0 while not got_ack and number_of_retransmissions < MAX_NUM_OF_TRANSMISSIONS: print('Alice prepares qubit') err_1 = Qubit(host) # encode logical qubit q.cnot(err_1) _, ack_received = host.send_qubit(receiver_id, q, await_ack=True) if ack_received: err_1.release() got_ack = True q_success = True if not q_success: print('Alice: Bob did not receive the qubit') # re-introduce a qubit to the system and correct the error q = Qubit(host) err_1.cnot(q) number_of_retransmissions += 1 if number_of_retransmissions == 10: print("Alice: too many attempts made") return False return True
def _establish_epr(self, sender, receiver, q_id, o_seq_num, blocked): """ Instead doing an entanglement swap, for efficiency we establish EPR pairs directly for simulation, if an entanglement swap would have been possible. Args: sender (Host): Sender of the EPR pair receiver (Host): Receiver of the EPR pair q_id (str): Qubit ID of the sent EPR pair o_seq_num (int): The original sequence number blocked (bool): If the pair being distributed is blocked or not """ host_sender = self.get_host(sender) host_receiver = self.get_host(receiver) q1 = Qubit(host_sender) q2 = Qubit(host_sender) q1.H() q1.cnot(q2) host_sender.add_epr(receiver, q1, q_id, blocked) host_receiver.add_epr(sender, q2, q_id, blocked) host_receiver.send_ack(sender, o_seq_num)
def handshake_receiver(host, sender_id): """ Establishes a classical TCP-like handshake with the sender . If successful starts to receive the qubits , otherwise terminated the connection. :param host: Receiver host :param sender_id: ID of the sender :return: If successful returns True, otherwise False """ latest_seq_num = host.get_sequence_number(sender_id) # Receive the EPR half of Alice and the SYN message qb_2 = host.get_data_qubit(sender_id, wait=WAIT_TIME) if qb_2 is None: Logger.get_instance().log('qb_2 is None') return False qb_2 = qb_2['q'] message_recv = host.get_message_w_seq_num(sender_id, (latest_seq_num + 1), wait=WAIT_TIME) if not message_recv: Logger.get_instance().log('No message has arrived') return False message_recv = message_recv[0]['message'] if message_recv == '10': Logger.get_instance().log("SYN is received by Bob") else: return False # Create an EPR pair. qb_3 = Qubit(host) qb_4 = Qubit(host) qb_3.H() qb_3.cnot(qb_4) # Send half of the EPR pair created (qubit 3) and send back the qubit 2 that Alice has sent first. _, ack_received = host.send_qubit(sender_id, qb_2, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False _, ack_received = host.send_qubit(sender_id, qb_3, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False # Send SYN-ACK message. host.send_classical(sender_id, SYN_ACK, True) latest_seq_num = host.get_sequence_number(sender_id) # Receive the ACK message. message = host.get_message_w_seq_num(sender_id, latest_seq_num, wait=WAIT_TIME) if message is None: Logger.get_instance().log('ACK was not received by Bob') return False if message.content == '01': Logger.get_instance().log('ACK was received by Bob') # Receive the qubit 3. qa_3 = host.get_data_qubit(sender_id, wait=WAIT_TIME) if qa_3 is None: return False # Make a Bell State measurement in qubit 3 and qubit 4. qa_3.cnot(qb_4) qa_3.H() qa_3_check = qa_3.measure() qb_4_check = qb_4.measure() # If measurement results are as expected , establish the TCP connection. # Else report that there is something wrong. if qa_3_check == 0 and qb_4_check == 0: Logger.get_instance().log("TCP connection established.") return True else: Logger.get_instance().log("Something is wrong.") return False
def handshake_sender(host, receiver_id): """ Establishes a classical TCP-like handshake with the receiver . If successful starts the transmission of qubits , otherwise terminated the connection. :param host: Sender of qubits :param receiver_id: ID of the receiver :return: If successful returns True, otherwise False """ # Create an EPR pair. qa_1 = Qubit(host) qa_2 = Qubit(host) qa_1.H() qa_1.cnot(qa_2) # Send a half of EPR pair and the SYN message to Bob. _, ack_received = host.send_qubit(receiver_id, qa_2, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False ack_received = host.send_classical(receiver_id, SYN, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False syn_seq_num = host.get_sequence_number(receiver_id) # Receive the qubits Bob has sent (qubit 2 and qubit 3) for SYN-ACK. qb_2 = host.get_data_qubit(receiver_id, wait=WAIT_TIME) if qb_2 is None: return False qb_3 = host.get_data_qubit(receiver_id, wait=WAIT_TIME) if qb_3 is None: return False # Receive the classical message Bob has sent for SYN-ACK. message_recv = host.get_message_w_seq_num(receiver_id, syn_seq_num + 2, wait=WAIT_TIME) if message_recv is None: return False if message_recv.content == '11': Logger.get_instance().log("SYN-ACK is received by Alice") else: Logger.get_instance().log('Connection terminated - 1 ') return False # Make a Bell State measurement on qubit 1 and qubit 2. qa_1.cnot(qb_2) qa_1.H() qa_1_check = qa_1.measure() qb_2_check = qb_2.measure() # If measurement results are as expected, send Bob a ACK message and the qubit 3 that he has sent previously. # Else report that there is something wrong. if qa_1_check == 0 and qb_2_check == 0: latest_seq_num = host.get_sequence_number(receiver_id) ack_received = host.send_classical(receiver_id, ACK, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False _, ack_received = host.send_qubit(receiver_id, qb_3, await_ack=True) if ack_received is False: Logger.get_instance().log('ACK is not received') return False message = host.get_message_w_seq_num(receiver_id, latest_seq_num + 2, wait=WAIT_TIME) return message.content == 'ACK' else: Logger.get_instance().log("Something is wrong.") return False
def RepeaterProtocol(host, alice, bob): timeout = 180 start = time.time() logrepeater = open("logs/repeater.txt", "w") bit_count = 0 while bit_count < 1: if time.time() - start > timeout: return host.empty_classical() time.sleep(1) # Synchronize with Alice and Bob host.send_broadcast(str(bit_count)) wait = True messages = [] while wait: messages = host.classical if len(messages) == 2: wait = False host.empty_classical() basis = random.randint(0, 1) ack_arrived = host.send_classical(alice, basis, await_ack = True) if not ack_arrived: logrepeater.write("Repeater: Failed to send basis %d to Alice\n"%bit_count) print("Repeater: Failed to send basis %d to Alice"%bit_count) continue ack_arrived = host.send_classical(bob, basis, await_ack = True) if not ack_arrived: logrepeater.write("Repeater: Failed to send basis %d to Bob\n"%bit_count) print("Repeater: Failed to send basis %d to Bob"%bit_count) continue # Generate two qubits q_alice = Qubit(host) q_mem_alice = Qubit(host) # Entangle the two qubits to create an entangled pair q_alice.H() q_alice.cnot(q_mem_alice) # Send one of the qubits of the entangled state to Alice q_alice_id, ack_arrived = host.send_qubit(alice, q_alice, await_ack=True) if not ack_arrived: # Alice did not receive qubit logrepeater.write("Repeater: Alice did not receive EPR %d\n"%bit_count) print("Repeater: Alice did not receive EPR %d"%bit_count) #q_alice.measure() q_mem_alice.measure() continue else: alice_bit = host.get_next_classical(alice, wait=5) if alice_bit is not None: logrepeater.write("Repeater: Alice received entangled qubit %d and measured %s\n"%(bit_count, str(alice_bit.content))) print("Repeater: Alice received entangled qubit %d and measured %s"%(bit_count, str(alice_bit.content))) else: continue # Generate two qubits q_bob = Qubit(host) q_mem_bob = Qubit(host) # Entangle the two qubits to create an entangled pair q_bob.H() q_bob.cnot(q_mem_bob) q_bob_id, ack_arrived = host.send_qubit(bob, q_bob, await_ack=True) if not ack_arrived: # Bob did not receive qubit #print("Repeater: Bob did not receive EPR") logrepeater.write("Repeater: Bob did not receive EPR %d\n"%bit_count) print("Repeater: Bob did not receive EPR %d"%bit_count) #q_bob.measure() q_mem_bob.measure() q_mem_alice.measure() continue else: bob_bit = host.get_next_classical(bob, wait=5) if bob_bit is not None: logrepeater.write("Repeater: Bob received entangled qubit %d and measured %s\n"%(bit_count, str(bob_bit.content))) print("Repeater: Bob received entangled qubit %d and measured %s"%(bit_count, str(bob_bit.content))) else: continue # Both Alice and Bob have successfully made BB84 measurements # Perform Bell state measurement on the two qubits present in the memory q_mem_alice.cnot(q_mem_bob) q_mem_alice.H() alice_bit = q_mem_alice.measure() bob_bit = q_mem_bob.measure() # Send results of measurement to Bob ack_arrived = host.send_classical(bob, "%d:%d"%(alice_bit, bob_bit), await_ack = True) if not ack_arrived: logrepeater.write("Repeater: Bell State Measurement %d void\n"%bit_count) print("Repeater: Bell State Measurement %d void"%bit_count) q_mem_alice.release() q_mem_bob.release() continue else: # Communicate Bob's success to Alice ack_arrived = host.send_classical(alice, str(bit_count), await_ack=True) if not ack_arrived: print("Repeater: Alice did not acknowledge Bob's success for bit %d"%bit_count) logrepeater.write("Repeater: Alice did not acknowledge Bob's success for bit %d\n"%bit_count) continue bit_count += 1 logrepeater.close()