def test_default_gates_and_qbit_reorder(self): gcirq = cirq.Circuit() qreg1 = [cirq.GridQubit(i, 0) for i in range(2)] qreg2 = [cirq.LineQubit(0)] qreg3 = [cirq.LineQubit(i) for i in range(1, 3)] for op in gates_1qb: gcirq.append(op(qreg2[0])**-1.0) for op in gates_2qb: gcirq.append(op(qreg3[0], qreg1[1])**-1.0) gcirq.append(cirq.CCX(qreg1[0], qreg3[1], qreg2[0])) gcirq.append(cirq.CSWAP(qreg1[0], qreg3[1], qreg2[0])) gcirq.append(cirq.CCZ(qreg1[0], qreg3[1], qreg2[0])) # Toffoli | (qreg3[1], qreg1[0], qreg2[0]) for qbit in qreg1 + qreg2 + qreg3: gcirq.append(cirq.measure(qbit)) # Generating qlm circuit result = cirq_to_qlm(gcirq) # Generating equivalent qlm circuit prog = Program() qubits = prog.qalloc(5) cbits = prog.calloc(5) for op in pygates_1qb: prog.apply(op.dag(), qubits[2]) for op in pygates_2qb: prog.apply(op.dag(), qubits[3], qubits[1]) prog.apply(CCNOT, qubits[0], qubits[4], qubits[2]) prog.apply(SWAP.ctrl(), qubits[0], qubits[4], qubits[2]) prog.apply(Z.ctrl().ctrl(), qubits[0], qubits[4], qubits[2]) for i in range(5): prog.measure(qubits[i], cbits[i]) expected = prog.to_circ() self.assertEqual(len(result.ops), len(expected.ops)) for i in range(len(result.ops)): res_op = result.ops[i] exp_op = expected.ops[i] if res_op.type == OpType.MEASURE: self.assertEqual(res_op, exp_op) continue result_gate_name, result_gate_params = extract_syntax( result.gateDic[res_op.gate], result.gateDic) # print("got gate {} with params {} on qbits {}" # .format(result_gate_name, result_gate_params, # res_op.qbits)) expected_gate_name, expected_gate_params = extract_syntax( expected.gateDic[exp_op.gate], expected.gateDic) # print("expected gate {} with params {} on qbits {}" # .format(expected_gate_name, expected_gate_params, # exp_op.qbits)) self.assertEqual(expected_gate_name, result_gate_name) self.assertEqual(expected_gate_params, result_gate_params)
def test_default_gates_and_qbit_reorder(self): aq = AqasmPrinter(MainEngine) eng = AqasmEngine(aq, engine_list=[aq]) qreg1 = eng.allocate_qureg(2) qreg2 = eng.allocate_qureg(1) qreg3 = eng.allocate_qureg(2) for op in gates_1qb: op | qreg2[0] for op in gates_2qb: op | (qreg3[0], qreg1[1]) ControlledGate(ops.Swap, n=1) | (qreg3[1], qreg1[0], qreg2[0]) Toffoli | (qreg3[1], qreg1[0], qreg2[0]) All(Measure) | qreg1 All(Measure) | qreg2 All(Measure) | qreg3 # Generating qlm circuit result = eng.projectq_to_qlm() # Generating equivalent qlm circuit prog = Program() qubits = prog.qalloc(5) cbits = prog.calloc(5) for op in pygates_1qb: prog.apply(op, qubits[2]) for op in pygates_2qb: prog.apply(op, qubits[3], qubits[1]) prog.apply(SWAP, qubits[1], qubits[3]) prog.apply(SWAP.ctrl(), qubits[4], qubits[0], qubits[2]) prog.apply(X.ctrl().ctrl(), qubits[0], qubits[4], qubits[2]) for i in range(5): prog.measure(qubits[i], cbits[i]) expected = prog.to_circ() self.assertEqual(len(result.ops), len(expected.ops)) for i in range(len(result.ops)): res_op = result.ops[i] exp_op = expected.ops[i] if res_op.type == OpType.MEASURE: self.assertEqual(res_op, exp_op) continue result_gate_name, result_gate_params = extract_syntax( result.gateDic[res_op.gate], result.gateDic) # print("got gate {} with params {} on qbits {}" # .format(result_gate_name, result_gate_params, # res_op.qbits)) expected_gate_name, expected_gate_params = extract_syntax( expected.gateDic[exp_op.gate], expected.gateDic) # print("expected gate {} with params {} on qbits {}" # .format(expected_gate_name, expected_gate_params, # exp_op.qbits)) self.assertEqual(expected_gate_name, result_gate_name) self.assertEqual(expected_gate_params, result_gate_params) self.assertEqual(exp_op.qbits, res_op.qbits)
def test_valid_powers(self): gcirq = cirq.Circuit() qreg = [cirq.LineQubit(i) for i in range(5)] gcirq.append(cirq.X(qreg[0])**-3.67) gcirq.append(cirq.Y(qreg[0])**7.9) gcirq.append(cirq.Z(qreg[0])**sqrt(5)) gcirq.append(cirq.S(qreg[0])**-pi) gcirq.append(cirq.T(qreg[0])**(sqrt(7) - pi)) gcirq.append(cirq.SWAP(qreg[0], qreg[1])**-0.5) gcirq.append(cirq.ISWAP(qreg[0], qreg[1])**16.0) result = cirq_to_qlm(gcirq) for i, op in enumerate(result.ops): name, params = extract_syntax(result.gateDic[op.gate], result.gateDic) if i == 0: self.assertEqual(params[0], -3.67 * pi) elif i == 1: self.assertEqual(params[0], 7.9 * pi) elif i == 2: self.assertEqual(params[0], sqrt(5) * pi) elif i == 3: self.assertEqual(params[0], -pi * pi / 2) elif i == 4: self.assertEqual(params[0], (sqrt(7) - pi) * pi / 4) else: continue
def test__routines_of_routines(self): """ Testing routines using other routines """ oq_parser = OqasmParser() oq_parser.build(debug=True) reverse_dic = {v: k for k, v in oq_parser.standard_gates.items()} data = "gate tst(p) a1,a2,a3,a4 {\n" for op in GATE_DATA[0:4]: data += reverse_dic[op[0]] + " a1" for q in range(1, op[2]): data += ", a" + str(q + 1) data += ";\n" data += "}\ngate tst2(p) b1, b2, b3, b4 {\n" for op in GATE_DATA[5:7]: if op[3] > 0: if op[0] == "U": data += reverse_dic[op[0]] + "(p,0,0) b1" else: data += reverse_dic[op[0]] + "(p) b1" else: data += reverse_dic[op[0]] + " b1" for q in range(1, op[2]): data += ", b" + str(q + 1) data += ";\n" data += "tst(p) b1, b2, b3, b4;\n}\n"\ + "tst2(pi) q[0], q[1], q[2], q[3];" print(data) res = oq_parser.parse(HEADER + data) circ = oq_parser.compiler.gen_circuit() for op in circ.ops: gate_name, gate_params = extract_syntax(circ.gateDic[op.gate], circ.gateDic) print("gate {} with params {} on qbits {}".format( gate_name, gate_params, op.qbits)) self.assertEqual(res, 1)
def test__standard_operations(self): """ Testing standard gates and operators work correctly """ oq_parser = OqasmParser() oq_parser.build(debug=True) reverse_dic = {v: k for k, v in oq_parser.standard_gates.items()} print(reverse_dic) data = "" for op in GATE_DATA: if op[3] > 0: data += reverse_dic[op[0]] + "(1" for p in range(1, op[3]): data += ", 2" data += ") q[0]" else: data += reverse_dic[op[0]] + " q[0]" for q in range(1, op[2]): data += ", q[" + str(q) + "]" data += " ;\n" print(HEADER + data) res = oq_parser.parse(HEADER + data) circ = oq_parser.compiler.gen_circuit() for op in circ.ops: gate_name, gate_params = extract_syntax(circ.gateDic[op.gate], circ.gateDic) print("gate {} with params {} on qbits {}".format( gate_name, gate_params, op.qbits)) self.assertEqual(res, 1)
def build_gate(dic, ident, qubits): """ Builds a pyquil operation from a QLM circuit's operation Args: dic: QLM circuit's GateDictionary ident: string identifying the gate used in this operation qubits: qubits on which to apply Returns: A pyquil gate operation """ qlm_gate = dic[ident] name = extract_syntax(dic[qlm_gate.name], dic)[0] basename = name.rsplit("C-", 1)[-1].rsplit("D-", 1)[-1] nbctrls = name.count("C-") dag = name.count("D-") if basename == "PH": basename = "PHASE" if nbctrls > 0: # build control and targets targets = [] arity = len(qubits) - nbctrls targets = qubits[-arity:] controls = list(qubits[:nbctrls]) # base gate try: params = [ param.double_p for param in dic[qlm_gate.subgate].syntax.parameters ] except AttributeError: params = [] quil_gate = pyquil.quilbase.Gate(basename, params, targets) # applying controls (order isn't important) for ctrl in controls: quil_gate = quil_gate.controlled(ctrl) if dag: quil_gate = quil_gate.dagger() return quil_gate if dag: params = [param.double_p for param in qlm_gate.syntax.parameters] # if it's a pair numbr of times, then it goes back to normal return pyquil.quilbase.Gate(basename, params, qubits).dagger() params = [param.double_p for param in qlm_gate.syntax.parameters] if None in params: raise TypeError("Unsupported parameter type") return pyquil.quilbase.Gate(basename, params, qubits)
def test__rec_routines_eval_params(self): """Testing arithmetic expressions in parameters of recursive routines""" oq_parser = OqasmParser() oq_parser.build() reverse_dic = {v: k for k, v in oq_parser.standard_gates.items()} data = "gate rp(p) a1, a2{\n" nb_gates = 0 for op in GATE_DATA: if op[3] > 0: nb_gates += 1 if op[0] == "U" or op[0] == "u3": data += "U (-p, p, 0) a1;\n" elif op[0] == "U2": data += "u2 (-p, p) a1;\n" elif op[0] == "U3": data += "u3 (-p, p, p) a1;\n" elif op[0] == "CU1": data += "cu1 (-p) a1, a2;\n" elif op[0] == "CU2": data += "cu2 (-p, p) a1, a2;\n" elif op[0] == "CU3": data += "cu3 (-p, p, p) a1, a2;\n" elif op[0] == "CRZ": data += "crz (-p) a1, a2;\n" else: data += reverse_dic[op[0]] + "(-p) a1;\n" data += "}\ngate rrp(q) a1, a2{\nrp(3*(-q)+2) a1, a2;\n}\n" data += "rrp(-pi/2) q[1], q[0];\n" data += "rrp(-3*5+4) q[2], q[0];\n" data += "rrp(-3+5*4) q[3], q[0];\n" data += "rrp(-3*(5+4)) q[3], q[0];\n" print(data) res = oq_parser.parse(HEADER + data) circ = oq_parser.compiler.gen_circuit() i = 0 for op in circ.ops: gate_name, gate_params = extract_syntax(circ.gateDic[op.gate], circ.gateDic) print("gate {} with params {} on qbits {}".format( gate_name, gate_params, op.qbits)) if i < nb_gates: self.assertEqual(gate_params[0], -(pi * 1.5 + 2)) elif i >= nb_gates and i < nb_gates * 2: self.assertEqual(gate_params[0], -35) elif i >= nb_gates * 2 and i < nb_gates * 3: self.assertEqual(gate_params[0], 49) else: self.assertEqual(gate_params[0], -83) i += 1 self.assertTrue(res, 1)
def qlm_to_cirq(qlm_circuit): """ Converts a QLM circuit to a cirq circuit. Args: qlm_circuit: the input QLM circuit to convert Returns: A cirq Circuit object resulting from the conversion """ cirq_circ = cirq.Circuit() qreg = [cirq.LineQubit(i + 1) for i in range(qlm_circuit.nbqbits)] for op in qlm_circuit.ops: if op.type == 0: name, params = extract_syntax(qlm_circuit.gateDic[op.gate], qlm_circuit.gateDic) nbctrls = name.count('C-') dag = name.count('D-') if name == "I": continue gate = QLM_GATE_DIC[name.rsplit('-', 1)[-1]] if len(params) > 0: for i, param in enumerate(params): if isinstance(param, Variable): params[i] = sympy.symbols(param.name) elif isinstance(param, ArithExpression): params[i] = _qat2sympy(param) if name.rsplit('-', 1)[-1] == 'PH': gate = gate(exponent=params[0] / pi) else: gate = gate(*params) if dag % 2 == 1: gate = cirq.inverse(gate) if nbctrls > 0: for _ in range(nbctrls): gate = ops.ControlledGate(gate) cirq_circ.append(gate.on(*[qreg[i] for i in op.qbits])) elif op.type == 1: for qb in op.qbits: cirq_circ.append(cirq.measure(qreg[qb])) # to unify the interface adding measures here for qbit in qreg: cirq_circ.append(cirq.measure(qbit)) return cirq_circ
def test__normal_routines(self): """ Testing normal routines work correctly """ oq_parser = OqasmParser() oq_parser.build(debug=True) reverse_dic = {v: k for k, v in oq_parser.standard_gates.items()} data = "gate tst(p) a1, a2, a3, a4 {" for op in GATE_DATA[0:4]: data += reverse_dic[op[0]] + " a1" for q in range(1, op[2]): data += ", a" + str(q + 1) data += ";" data += "} tst(pi) q[0], q[1], q[2], q[3];" print(data) res = oq_parser.parse(HEADER + data, debug=False) circ = oq_parser.compiler.gen_circuit() for op in circ.ops: gate_name, gate_params = extract_syntax(circ.gateDic[op.gate], circ.gateDic) print("gate {} with params {} on qbits {}".format( gate_name, gate_params, op.qbits)) self.assertEqual(res, 1)
def test__implemented_if(self): """ Testing behavior with implemented if """ oq_parser = OqasmParser() oq_parser.build() data = "if (c==13) U(0,pi/2,0) q[1];\nif (c==20) x q[1];\nx q[2];" print(data) res = oq_parser.parse(HEADER + data) circ = oq_parser.compiler.gen_circuit() # 20 > 2^4-1 so no op created as it's always false self.assertEqual(len(circ.ops), 2) for op in circ.ops: gate_name, gate_params = extract_syntax(circ.gateDic[op.gate], circ.gateDic) print("gate {} with params{} on qbits {}".format( gate_name, gate_params, op.qbits)) if op.type == OpType.CLASSICCTRL: self.assertEqual(op.cbits, None) if gate_name == "U": self.assertEqual(op.formula, "AND AND AND 0 1 NOT 2 3 ") else: self.assertEqual(op.formula, None) self.assertEqual(res, 1)
def qlm_to_qiskit(qlm_circuit, qubits=None): """ Converts a QLM circuit to a Qiskit circuit. The supported translatable gates are: :code:`H`, :code:`X`, :code:`Y`, :code:`Z`, :code:`SWAP`, :code:`I`, :code:`S`, :code:`S.dag()`, :code:`T`, :code:`T.dag()`, :code:`RX`, :code:`RY`, :code:`RZ`, :code:`H.ctrl()`, :code:`CNOT`, :code:`Y.ctrl()`, :code:`CSIGN`, :code:`RZ.ctrl()`, :code:`CCNOT`, :code:`SWAP.ctrl()`, :code:`U`, :code:`RXX`, :code:`RZZ`, :code:`R`, :code:`MS` Args: qlm_circuit: The input QLM circuit to convert qubits (list<int>, optional): measured qubits Returns: A QuantumCircuit Qiskit object resulting from the conversion """ # Init measured qubits if qubits is None: qubits = list(range(qlm_circuit.nbqbits)) qreg = QuantumRegister(qlm_circuit.nbqbits) creg = None param_list = [] if qlm_circuit.nbcbits > 0: creg = ClassicalRegister(max(qlm_circuit.nbcbits, len(qubits))) q_circ = QuantumCircuit(qreg, creg) else: q_circ = QuantumCircuit(qreg) dic = _gen_qiskit_gateset(q_circ) for gate_op in qlm_circuit: if gate_op.type == OpType.GATETYPE: name, params = extract_syntax( qlm_circuit.gateDic[gate_op.gate], qlm_circuit.gateDic, var_dic=qlm_circuit.var_dic) nbctrls = name.count('C-') # changes variables and expressions to format used by Qiskit for index, param in enumerate(params): if isinstance(param, Variable): params[index] = _variable_to_parameter( param_list, variable=param) elif isinstance(param, ArithExpression): arith_expr_list = param.to_thrift().split() params[index] = _arith_expr_list_to_parameter_expression( param_list, arith_expr_list, param) try: if name == "MS": q_circ.ms(params[0], [qreg[i] for i in gate_op.qbits]) else: if name.endswith("U2"): # u2(phi, lambda) = u(pi/2, phi, lambda) params = [np.pi] + params name = name[:-1] if (nbctrls > 0 and name not in SUPPORTED_CTRLS): tmp = name count = 0 gate = None while True: last = tmp tmp = tmp.replace("C-", "", 1) if last == tmp: raise ValueError( f"Gate {name} not supported by Qiskit API" ) count += 1 gate = _get_qiskit_gate_from_name(tmp) if gate is not None: gate = gate(*params).control(count) break if gate is not None: q_circ.append(gate, [qreg[i] for i in gate_op.qbits]) else: dic[name](* params + [qreg[i] for i in gate_op.qbits]) except KeyError as err: raise ValueError( f"Gate {name} not supported by Qiskit API" ) from err elif gate_op.type == OpType.MEASURE: for index, qbit in enumerate(gate_op.qbits): q_circ.measure(qbit, gate_op.cbits[index]) # pylint:disable=no-member # Adding measures to unify the interface for qbit_index, cbit in zip(qubits, creg): q_circ.measure(qreg[qbit_index], cbit) # pylint: disable=no-member return q_circ
def qlm_to_qiskit(qlm_circuit, qubits=None): """ Converts a QLM circuit to a Qiskit circuit. Not all gates are supported so exceptions will be raised if the gate isn't supported. List of supported gates : H, X, Y, Z, SWAP, I, S, D-S, T, D-T, RX, RY, RZ, C-H, CNOT, C-Y, CSIGN, C-RZ, CCNOT, C-SWAP, U, RXX, RZZ, R, MS Args: qlm_circuit: The input QLM circuit to convert qubits (list<int>, optional): measured qubits Returns: A QuantumCircuit Qiskit object resulting from the conversion """ # Init measured qubits if qubits is None: qubits = list(range(qlm_circuit.nbqbits)) qreg = QuantumRegister(qlm_circuit.nbqbits) creg = None param_list = [] if qlm_circuit.nbcbits > 0: creg = ClassicalRegister(max(qlm_circuit.nbcbits, len(qubits))) q_circ = QuantumCircuit(qreg, creg) else: q_circ = QuantumCircuit(qreg) dic = _gen_qiskit_gateset(q_circ) for gate_op in qlm_circuit: if gate_op.type == OpType.GATETYPE: name, params = extract_syntax( qlm_circuit.gateDic[gate_op.gate], qlm_circuit.gateDic, var_dic=qlm_circuit.var_dic) nbctrls = name.count('C-') # changes variables and expressions to format used by Qiskit for index, param in enumerate(params): if isinstance(param, Variable): params[index] = _variable_to_parameter( param_list, variable=param) elif isinstance(param, ArithExpression): arith_expr_list = param.to_thrift().split() params[index] = _arith_expr_list_to_parameter_expression( param_list, arith_expr_list, param) try: if name == "MS": q_circ.ms(params[0], [qreg[i] for i in gate_op.qbits]) else: if (nbctrls > 0 and name not in SUPPORTED_CTRLS): tmp = name count = 0 gate = None while True: last = tmp tmp = tmp.replace("C-", "", 1) if last == tmp: raise ValueError( "Gate {} not supported by Qiskit API".format(name) ) else: count += 1 gate = _get_qiskit_gate_from_name(tmp) if gate != None: gate = gate(*params).control(count) break if gate != None: q_circ.append(gate, [qreg[i] for i in gate_op.qbits]) else: dic[name](* params + [qreg[i] for i in gate_op.qbits]) except KeyError: raise ValueError( "Gate {} not supported by Qiskit API".format(name) ) elif gate_op.type == OpType.MEASURE: for index in range(len(gate_op.qbits)): q_circ.measure(gate_op.qbits[index], gate_op.cbits[index]) # Adding measures to unify the interface for qbit_index, cbit in zip(qubits, creg): q_circ.measure(qreg[qbit_index], cbit) return q_circ
def simulate(circuit): """ Computes state vector at the output of provided circuit. State vector is stored as a :code:`numpy.ndarray` It is initialized at :math:`|0^n\\rangle`. Then, loop over gates, updating the state vector using `np.tensordot` Args: circuit (:class:`~qat.core.Circuit`): Input circuit. The circuit to simulate. Returns: tuple: a tuple composed of a state vector and intermediate measurements: - state vector: :code:`numpy.ndarray` containing the final state vector. It has one 2-valued index per qubits. - intermediate measurements: :code:`list` of :class:`qat.comm.shared.ttypes.IntermediateMeasurement`. List containing descriptors of the intermediate measurements that occurred within the circuit, so that the classical branching is known to the user. """ # Initialization at |0...0> shape = tuple([2 for _ in range(circuit.nbqbits)]) state_vec = np.zeros(shape, dtype=np.complex128) state_vec[tuple([0 for _ in range(circuit.nbqbits)])] = 1 # cbits initilization. cbits = [0] * circuit.nbcbits interm_measurements = [] # Loop over gates. for op_pos, op in enumerate(circuit): if op.type == datamodel_types.OpType.MEASURE: # measure op.qbits on state_vec and store in op.cbits intprob_list = measure(state_vec, op.qbits) state_vec = project(state_vec, op.qbits, intprob_list[0]) res_int, prob = intprob_list[0] for k in range(len(op.qbits)): cbits[op.cbits[k]] = res_int >> (len(op.qbits) - k - 1) & 1 interm_measurements.append(shared_types.IntermediateMeasurement( gate_pos=op_pos, cbits=[(res_int >> (len(op.qbits) - k - 1) & 1) for k in range(len(op.qbits))], probability=prob )) continue if op.type == datamodel_types.OpType.RESET: # measure, if result is 1 apply X. state_vec, res, prob = reset(state_vec, op.qbits) # contains actual implem. for cb in op.cbits: cbits[cb] = 0 interm_measurements.append(shared_types.IntermediateMeasurement( gate_pos=op_pos, cbits=[(res >> (len(op.qbits) - k - 1) & 1) for k in range(len(op.qbits))], probability=prob )) continue if op.type == datamodel_types.OpType.CLASSIC: # compute result bit of formula cbits[op.cbits[0]] = int(feval.evaluate(op.formula, cbits)) continue if op.type == datamodel_types.OpType.BREAK: # evaluate formula and break if verdict is 1. verdict = feval.evaluate(op.formula, cbits) if verdict: raise_break(op, op_pos, cbits) continue if op.type == datamodel_types.OpType.CLASSICCTRL: # continue only if control cbits are all at 1. if not all([cbits[x] for x in op.cbits]): continue gdef = circuit.gateDic[op.gate] # retrieving useful info. # Checking if the matrix has a matrix if not gdef.matrix: gname = extract_syntax(gdef, circuit.gateDic)[0] if gname == "STATE_PREPARATION": matrix = gdef.syntax.parameters[0].matrix_p np_matrix = mat2nparray(matrix) if np_matrix.shape != (2**circuit.nbqbits, 1): raise exceptions_types.QPUException(code=exceptions_types.ErrorType.ILLEGAL_GATES, modulename="qat.pylinalg", file="qat/pylinalg/simulator.py", line=103, message="Gate {} has wrong shape {}, should be {}!"\ .format(gname, np_matrix.shape, (2**circuit.nbqbits, 1))) state_vec[:] = np_matrix[:, 0].reshape(shape) norm = np.linalg.norm(state_vec) if abs(norm - 1.0) > 1e-10: raise exceptions_types.QPUException(code=exceptions_types.ErrorType.ILLEGAL_GATES, modulename="qat.pylinalg", file="qat/pylinalg/simulator.py", line=103, message="State preparation should be normalized, got norm = {} instead!"\ .format(norm)) continue try: nctrls, matrix = get_gate_matrix(gdef, circuit.gateDic) except AttributeError as excp: raise exceptions_types.QPUException(code=exceptions_types.ErrorType.ILLEGAL_GATES, modulename="qat.pylinalg", file="qat/pylinalg/simulator.py", line=103, message="Gate {} has no matrix!"\ .format(extract_syntax(gdef, circuit.gateDic)[0])) from excp # Moving qubits axis in first positions state_vec = np.moveaxis(state_vec, op.qbits, range(len(op.qbits))) # Reshaping for block multiplication state_vec = state_vec.reshape((1 << nctrls, matrix.shape[0], 1 << (circuit.nbqbits - len(op.qbits)))) # If controled, only applying the gate on the last block if nctrls: state_vec[-1] = np.dot(matrix, state_vec[-1]) else: state_vec = np.dot(matrix, state_vec) # Going back to a split shape state_vec = state_vec.reshape(tuple(2 for _ in range(circuit.nbqbits))) # moving qubit back to their position state_vec = np.moveaxis(state_vec, range(len(op.qbits)), op.qbits) return state_vec, interm_measurements
def test0_default_gates_and_qbit_reorder(self): """ Tries out every default gate and check that they match once the Qiskit circuit is translated into a QLM circuit. """ qreg1 = QuantumRegister(2) qreg2 = QuantumRegister(1) qreg3 = QuantumRegister(2) creg = ClassicalRegister(5) ocirc = QuantumCircuit(qreg1, qreg2, qreg3, creg) gates_1qb_0prm, gates_1qb_1prm, gates_2qb_0prm, \ gates_2qb_1prm, gates_3qb_0prm = gen_gates(ocirc) for gate_op in gates_1qb_0prm: gate_op(qreg2[0]) for gate_op in gates_1qb_1prm: gate_op(3.14, qreg2[0]) for gate_op in gates_2qb_0prm: gate_op(qreg3[0], qreg1[1]) for gate_op in gates_2qb_1prm: gate_op(3.14, qreg3[0], qreg1[1]) for gate_op in gates_3qb_0prm: gate_op(qreg2[0], qreg3[1], qreg1[1]) ocirc.u(3.14, 3.14, 3.14, qreg3[0]) ocirc.r(3.14, 3.14, qreg3[0]) ocirc.ms(3.14, [qreg1[1], qreg2[0], qreg3[0]]) ocirc.measure(qreg1[0], creg[4]) ocirc.measure(qreg1[1], creg[3]) ocirc.measure(qreg2[0], creg[2]) ocirc.measure(qreg3[0], creg[1]) ocirc.measure(qreg3[1], creg[0]) result = qiskit_to_qlm(ocirc) prog = Program() qubits = prog.qalloc(5) cbits = prog.calloc(5) for gate_op in PYGATES_1QB: prog.apply(gate_op, qubits[2]) for gate_op in PYGATES_2QB: prog.apply(gate_op, qubits[3], qubits[1]) prog.apply(SWAP.ctrl(), qubits[2], qubits[4], qubits[1]) prog.apply(X.ctrl().ctrl(), qubits[2], qubits[4], qubits[1]) prog.apply(U3(3.14, 3.14, 3.14), qubits[3]) prog.apply(R(3.14, 3.14), qubits[3]) prog.apply(MS(3.14, 3), qubits[1], qubits[2], qubits[3]) for i in range(5): prog.measure(qubits[i], cbits[4 - i]) expected = prog.to_circ() self.assertEqual(len(result.ops), len(expected.ops)) for res_op, exp_op in zip(result.ops, expected.ops): if res_op.type == OpType.MEASURE: self.assertEqual(res_op, exp_op) continue result_gate_name, result_gate_params = extract_syntax( result.gateDic[res_op.gate], result.gateDic) LOGGER.debug("got gate {} with params {} on qbits {}".format( result_gate_name, result_gate_params, res_op.qbits)) expected_gate_name, expected_gate_params = extract_syntax( expected.gateDic[exp_op.gate], expected.gateDic) LOGGER.debug("expected gate {} with params {} on qbits {}".format( expected_gate_name, expected_gate_params, exp_op.qbits)) self.assertEqual(expected_gate_name, result_gate_name) self.assertEqual(expected_gate_params, result_gate_params) self.assertEqual(exp_op.qbits, res_op.qbits) LOGGER.debug("\nResults obtained:") qpu = BackendToQPU() result_job = result.to_job(nbshots=1024) qiskit_result = qpu.submit(result_job) for entry in qiskit_result.raw_data: LOGGER.debug("State: {}\t probability: {}".format( entry.state, entry.probability)) LOGGER.debug("\nResults expected:") expected_job = expected.to_job(nbshots=1024) qlm_result = qpu.submit(expected_job) for entry in qlm_result.raw_data: LOGGER.debug("State: {}\t probability: {}".format( entry.state, entry.probability)) self.assertEqual(len(qiskit_result.raw_data), len(qlm_result.raw_data)) states_expected = [str(entry.state) for entry in qlm_result.raw_data] for entry in qiskit_result.raw_data: self.assertTrue(str(entry.state) in states_expected)