Example #1
0
    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)
Example #2
0
    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)
Example #3
0
    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
Example #4
0
 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)
Example #5
0
 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)
Example #6
0
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)
Example #7
0
 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)
Example #8
0
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
Example #9
0
 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)
Example #10
0
 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)
Example #11
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
    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)