def test2_abstract_variables(self): """ Tests the translation of abstract variables and ArithExpression into Qiskit via qlm_to_qiskit() """ prog = Program() qubits = prog.qalloc(1) var2 = prog.new_var(float, "param2") var3 = prog.new_var(float, "param3") var4 = 1.0 + 3.14 + var2 - var3 var5 = 1.0 * 3.14 * (var2 + 4.54) * var3 var6 = -var5 * var4 var7 = var4 / (var2 - 7) prog.apply(RX(1.0), qubits[0]) prog.apply(RX(3.14), qubits[0]) prog.apply(RX(var2), qubits[0]) prog.apply(RX(var3), qubits[0]) prog.apply(RX(var4), qubits[0]) prog.apply(RX(var5), qubits[0]) prog.apply(RX(var6), qubits[0]) prog.apply(RX(var7), qubits[0]) qlm_circ = prog.to_circ() qiskit_circ = qlm_to_qiskit(qlm_circ) LOGGER.debug("Parameters gotten:") for gate_op in qiskit_circ.data: for param in gate_op[0]._params: LOGGER.debug(param) qreg = QuantumRegister(1) circ = QuantumCircuit(qreg) param2 = Parameter("param2") param3 = Parameter("param3") param4 = 1.0 + 3.14 + param2 - param3 param5 = 1.0 * 3.14 * (param2 + 4.54) * param3 param6 = -param5 * param4 param7 = param4 / (param2 - 7.0) circ.rx(1.0, 0) circ.rx(3.14, 0) circ.rx(param2, 0) circ.rx(param3, 0) circ.rx(param4, 0) circ.rx(param5, 0) circ.rx(param6, 0) circ.rx(param7, 0) LOGGER.debug("Parameters expected:") for gate_op in circ.data: for param in gate_op[0]._params: LOGGER.debug(param) for gotten, expected in zip(qiskit_circ.data, circ.data): self.assertEqual(str(gotten[0]._params[0]), str(expected[0]._params[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
def test1_abstract_variables(self): """ Tests the conversion of Parameter objects from Qiskit into abstract Variable objects in QLM via qiskit_to_qlm. """ qreg = QuantumRegister(1) circ = QuantumCircuit(qreg) param0 = Parameter("param0") param1 = Parameter("param1") param2 = Parameter("param2") param3 = Parameter("param3") param0.expr = 1 param1.expr = 3.14 param4 = param0 + param1 + param2 - param3 param5 = param0 * param1 * (param2 + 4.54) * param3 param6 = param5 * param4 param7 = param4 / (param2 - 7) circ.rx(param0, 0) circ.rx(param1, 0) circ.rx(param2, 0) circ.rx(param3, 0) circ.rx(param4, 0) circ.rx(param5, 0) circ.rx(param6, 0) circ.rx(param7, 0) qlm_circ = qiskit_to_qlm(circ) i = 0 for _, params, _ in qlm_circ.iterate_simple(): for param in params: LOGGER.debug(param.to_thrift()) if i == 0: self.assertEqual(param.to_thrift(), "param0") if i == 1: self.assertEqual(param.to_thrift(), "param1") if i == 2: self.assertEqual(param.to_thrift(), "param2") if i == 3: self.assertEqual(param.to_thrift(), "param3") if i == 4: self.assertEqual( param.to_thrift(), "+ + + * -1.0 param3 param2 param0 param1") if i == 5: self.assertEqual( param.to_thrift(), "* * * + 4.54 param2 param0 param1 param3") if i == 6: self.assertEqual( param.to_thrift(), "* * * * + + + * -1.0 param3 param2 param0 param1 " + "+ 4.54 param2 param0 param1 param3") if i == 7: self.assertEqual( param.to_thrift(), "* + + + * -1.0 param3 param2 param0 param1" + " ** + -7.0 param2 -1.0") i += 1 prog = Program() qubits = prog.qalloc(1) var0 = prog.new_var(float, "param0") var1 = prog.new_var(float, "param1") var2 = prog.new_var(float, "param2") var3 = prog.new_var(float, "param3") var4 = var0 + var1 + var2 - var3 var5 = var0 * var1 * (var2 + 4.54) * var3 var6 = var5 * var4 var7 = var4 / (var2 - 7) prog.apply(RX(var0), qubits[0]) prog.apply(RX(var1), qubits[0]) prog.apply(RX(var2), qubits[0]) prog.apply(RX(var3), qubits[0]) prog.apply(RX(var4), qubits[0]) prog.apply(RX(var5), qubits[0]) prog.apply(RX(var6), qubits[0]) prog.apply(RX(var7), qubits[0]) qlm_circ_expected = prog.to_circ() qlm_circ_expected(var0=1) qlm_circ_expected(var1=3.14) for _, params, _ in qlm_circ_expected.iterate_simple(): for param in params: LOGGER.debug(param.to_thrift())