def entangle(host): # 01 - 10 q1 = Qubit(host) q2 = Qubit(host) q1.X() q1.H() q2.X() q1.cnot(q2) return q1, q2
def alice(alice, bob, number_of_entanglement_pairs): angles = [0, np.pi / 4, np.pi / 2] bases_choice = [ random.randint(1, 3) for i in range(number_of_entanglement_pairs) ] test_results_alice = [] test_bases_alice = [] sifted_key_alice = [] for i in range(number_of_entanglement_pairs): qubit_a = Qubit(alice) qubit_b = Qubit(alice) # preparation of singlet state (1/sqrt(2))*(|01> - |10>) qubit_a.X() qubit_b.X() qubit_a.H() qubit_a.cnot(qubit_b) print('Sending EPR pair %d' % (i + 1)) _, ack_arrived = alice.send_qubit(bob, qubit_b, await_ack=True) if ack_arrived: #rotate qubit and measure base_a = bases_choice[i] qubit_a.rz(angles[base_a - 1]) meas_a = qubit_a.measure() ack_arrived = alice.send_classical(bob, base_a, await_ack=True) if not ack_arrived: print("Send data failed!") message = alice.get_next_classical(bob, wait=2) if message is not None: base_b = message.content if (base_a == 2 and base_b == 1) or (base_a == 3 and base_b == 2): sifted_key_alice.append(meas_a) elif (base_a == 1 and base_b == 1) or (base_a == 1 and base_b == 3) or ( base_a == 3 and base_b == 1) or (base_a == 3 and base_b == 3): test_bases_alice.append('a' + str(base_a)) test_results_alice.append(str(meas_a)) else: print("The message did not arrive") else: print('The EPR pair was not properly established') ack_arrived = alice.send_classical(bob, (test_results_alice, test_bases_alice), await_ack=True) if not ack_arrived: print("Send data failed!") print("Sifted_key_alice: ", sifted_key_alice)
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_receiver(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: print('qb_2 is None') return False message_recv = host.get_classical(sender_id, (latest_seq_num + 1), wait=WAIT_TIME) if not message_recv: print('No message has arrived') return False message_recv = message_recv.content if message_recv == '10': print("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: print('ACK is not received') return False _, ack_received = host.send_qubit(sender_id, qb_3, await_ack=True) if ack_received is False: print('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_receiver(sender_id) # Receive the ACK message. message = host.get_classical(sender_id, latest_seq_num, wait=WAIT_TIME) if message is None: print('ACK was not received by Bob') return False if message.content == '01': print('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: print("TCP connection established.") return True else: print("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: print('ACK is not received') return False ack_received = host.send_classical(receiver_id, SYN, await_ack=True) if ack_received is False: print('ACK is not received') return False syn_seq_num = host.get_sequence_number_receiver(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_classical(receiver_id, syn_seq_num + 2, wait=WAIT_TIME) if message_recv is None: return False if message_recv.content == '11': print("SYN-ACK is received by Alice") else: print('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: ack_received = host.send_classical(receiver_id, ACK, await_ack=True) if ack_received is False: print('ACK is not received') return False _, ack_received = host.send_qubit(receiver_id, qb_3, await_ack=True) if ack_received is False: print('ACK is not received') return False return True else: print("Something is wrong.") return False