def generate_program(cls, nqbits: int): pr = Program() # TODO extend to nqbits nqbits = 1 to_teleport = pr.qalloc(nqbits) to_teleport_c = pr.calloc(nqbits) epr_pair_a = pr.qalloc() epr_pair_a_c = pr.calloc() epr_pair_b = pr.qalloc() # Prepare EPR pair pr.apply(H, *epr_pair_a) pr.apply(CNOT, *epr_pair_a, *epr_pair_b) # Prepare random state using 3 random rotation around the 3 axis pr.apply(RY(random() * pi), *to_teleport) pr.apply(RX(random() * pi), *to_teleport) pr.apply(RZ(random() * pi), *to_teleport) # Encode pr.apply(CNOT, *to_teleport, *epr_pair_a) pr.apply(H, *to_teleport) # Teleport pr.measure(to_teleport, to_teleport_c) pr.measure(epr_pair_a, epr_pair_a_c) # Decode pr.cc_apply(epr_pair_a_c[0], X, epr_pair_b[0]) pr.cc_apply(to_teleport_c[0], Z, epr_pair_b[0]) return pr, None
def main(): # _a is for Alice, _b is for Bob, _c is for classical pr = Program() to_teleport = pr.qalloc() epr_pair_a = pr.qalloc() epr_pair_a_c = pr.calloc() to_teleport_c = pr.calloc() epr_pair_b = pr.qalloc() # Prepare EPR pair pr.apply(H, *epr_pair_a) pr.apply(CNOT, *epr_pair_a, *epr_pair_b) # Now Alice has her half of the EPR pair (epr_pair_a) and Bob the other one # (epr_pair_b qubit) # Prepare random state on the qubit(s) to teleport pr.apply(RY(random() * pi), *to_teleport) pr.apply(RX(random() * pi), *to_teleport) pr.apply(RZ(random() * pi), *to_teleport) # At this point we make a copy of the original program. The idea is to show # the state we would obtain if we would stop at this stage, before the # teleportation. pr2 = deepcopy(pr) # We continue with the teleportation circuit # Alice interact her to_teleport_qubit with her half of the EPR pair pr.apply(CNOT, *to_teleport, *epr_pair_a) pr.apply(H, *to_teleport) # ... and then she measures her 2 qubits pr.measure(to_teleport, to_teleport_c) pr.measure(epr_pair_a, epr_pair_a_c) # She then sends her measured qubits to Bob which, depending on their value # being 0 or 1, performs the classically controlled X and Z on his own half of the EPR pair pr.cc_apply(epr_pair_a_c[0], X, epr_pair_b[0]) pr.cc_apply(to_teleport_c[0], Z, epr_pair_b[0]) # circ = pr.to_circ() circ2 = pr2.to_circ() # simulation qpu = PyLinalg() res = qpu.submit(circ.to_job(qubits=[epr_pair_b])) res2 = qpu.submit(circ2.to_job(qubits=[to_teleport])) print("Original state, measured on to_teleport qubit") for sample in res2: # print(f"state {sample.state} with amplitude {sample.amplitude} and probability {sample.probability}") print(f"state {sample.state} with amplitude {sample.probability}") print("Teleported state, measured on ") for sample in res: print(f"state {sample.state} with probability {sample.probability}")
def test_no_state_modification_circuit(self) -> None: """ We apply Sabre on a circuit which doesn't modify the initial state (|0^n> here) and we verify Sabre circuit modifications don't modify the state. """ for nbqbit in range(min_nbqbit, max_nbqbit): prog = Program() qbits = prog.qalloc(nbqbit) random_angles = [ rd.random() * 2 * np.pi for _ in range(3 * nbqbit) ] for i in range(len(qbits)): prog.apply(RX(random_angles[3 * i]), qbits[i]) prog.apply(RX(random_angles[3 * i + 1]), qbits[i]) prog.apply(RX(random_angles[3 * i + 2]), qbits[i]) prog.apply(QFT(nbqbit), qbits) prog.apply(QFT(nbqbit).dag(), qbits) for i in range(len(qbits)): prog.apply(RX(random_angles[3 * i]).dag(), qbits[i]) prog.apply(RX(random_angles[3 * i + 1]).dag(), qbits[i]) prog.apply(RX(random_angles[3 * i + 2]).dag(), qbits[i]) circuit = prog.to_circ(inline=True) for topology in generate_custom_topologies(nbqbit): qpu = Sabre() | (QuameleonPlugin(topology=topology) | PyLinalg()) result = qpu.submit(circuit.to_job()) assert result.raw_data[0].state.int == 0
def process_RX(exp): """ Generates the myQLM gates corresponding to the matrix RX ** exp Args: exp (float): exposant Returns: Gate """ # pylint: disable=invalid-name return RX(pi * exp)
def process_X(exp): """ Generates the myQLM gates corresponding to the matrix X ** exp Args: exp (float): exposant Returns: Gate """ # pylint: disable=invalid-name if isinstance(exp, (int, float)) and abs(exp) == 1.0: return X return RX(pi * exp)
def generate_teleportation(split_measures: bool): """ Generates a circuit corresponding to the teleportation circuit Args: split_measures (bool): split measures Returns: :class:`~qat.core.Circuit`: generated circuit """ # Init program prog = Program() source = prog.qalloc(1) bell_pair = prog.qalloc(2) cbits = prog.calloc(2) # Init source qubit prog.apply(RX(1.23), source) prog.apply(RZ(4.56), source) # Init Bell pair prog.apply(H, bell_pair[0]) prog.apply(CNOT, bell_pair) # Bell pair measurement between source qubit and bell_pair[0] prog.apply(CNOT, source, bell_pair[0]) prog.apply(H, source) if split_measures: prog.measure(source[0], cbits[0]) prog.measure(bell_pair[0], cbits[1]) else: prog.measure([source[0], bell_pair[0]], cbits) # Classic control prog.cc_apply(cbits[1], X, bell_pair[1]) prog.cc_apply(cbits[0], Z, bell_pair[1]) # Return circuit return prog.to_circ()
def u_B(beta): op = QRoutine() for qbit in range(graph.V): op.apply(RX(-beta * 2), qbit) return op
def bipartition(s, p): ###Define a variational circuit #As a Program prog = Program() #With n qubits nqbits = len(s) qbits = prog.qalloc(nqbits) #Define the variational states (einsatz) #|psi(theta)> = Rx1(theta1x)...Rxn(theta1n)|0,...,0> for i in range(0, nqbits): for j in range(1): #H(qbits[i]) thetaij = prog.new_var(float, "theta"+str(i)+str(j)) if j == 0 : RX(np.pi*thetaij)(qbits[i]) #RZ(thetaij)(qbits[i]) #H Rz H method #elif j ==1 : # RY(thetaij)(qbits[i]) #elif j == 2: # RZ(thetaij)(qbits[i]) # elif j == 3 : # RY(thetaij)(qbits[i]) # elif j == 4 : # RX(thetaij)(qbits[i]) #H(qbits[i]) #export program into a quntum circuit circuit = prog.to_circ() #print created variables" print("Variables:", circuit.get_variables()) ###Define an observable #Initialization obs = Observable(nqbits) #Observable = Hamiltonian we want to minimize # => Reformulate bi-partition problem in Hamiltonian minimalization problem : #Bi-partition problem : Find A1,A2 such that A1 u A2 = s and minimizes |sum_{n1 in A1}n1 - sum_{n2 in A2}n2| #Optimization Problem : Find e = {ei} in {-1,1}^n minimizing |sum_{1<=i<=n}ei.si| #Non-Linear Integer Programming Optimization Problem Find e = {ei} in {-1,1}^n minimizing (sum_{1<=i<=n}ei.si)^2 #Ising problem : Find e = {ei} in {-1,1}^n minimizing sum_{1<=i<=n}(si)^2 + sum_{1<=i<=n, 1<=i<j<=n} (si.sj).ei.ej)^2 (si^2 = 1) J = [[si*sj for si in s] for sj in s] b = [si**2 for si in s] obs += sum(b)*Observable(nqbits, constant_coeff = sum(b)) for i in range(nqbits): for j in range(i-1): obs += Observable(nqbits, pauli_terms = [Term(J[i][j], "ZZ", [i, j])]) #Term(coefficient, tensorprod, [qubits]) ###Create a quantum job #Made of a circuit and and an observable job = circuit.to_job(observable = obs) #nbshots=inf ###Define classical optimizer : scipy.optimia.minimize method_name = "COBYLA" #"Nelder-Mead", "Powell", "CG",... optimize = ScipyMinimizePlugin(method = method_name, tol = 1e-3, options = {"maxiter" : p}) ###Define qpu on which to run quantum job stack = optimize | get_default_qpu() optimizer_args = {"method": method_name, "tol":1e-3, "options":{"maxiter":p}} result = stack.submit(job, meta_data ={"ScipyMinimizePlugin": json.dumps(optimizer_args)}) ###Get characteristics of best parametrized circuit found final_energy = result.value parameters = json.loads(result.meta_data['parameters']) print("final energy:", final_energy) print('best parameters:', parameters) #print('trace:', result.meta_data['optimization_trace']) ###Deduce the most probable state => solution of the problem #Probability to measure qubit i in state |0> : cos(theta_i)^2 #Probability to measure qubit i in state |1> : sin(theta_i)^2 states = {} best_state = '' max_proba = 0 for i in range(2**nqbits): state = bin(i)[2:].zfill(nqbits) proba = 1 for i in range(nqbits): proba = proba/2*((1+(-1)**int(state[nqbits-i-1]))*np.cos(parameters[i]*np.pi/2)+(1+(-1)**(int(state[nqbits-i-1])+1))*np.sin(parameters[i]*np.pi/2)) if max_proba < proba: max_proba = proba best_state = state states[state] = proba print(states) A1 = [] A2 = [] for i in range(nqbits): if best_state[i] == '0': A1.append(s[i]) elif best_state[i] == '1': A2.append(s[i]) return A1, A2