Ejemplo n.º 1
0
    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}")
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
 def u_B(beta):
     op = QRoutine()
     for qbit in range(graph.V):
         op.apply(RX(-beta * 2), qbit)
     return op
Ejemplo n.º 8
0
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