Exemplo n.º 1
0
    def test_break(self):

        circ = generate_break()
        task = Task(circ, get_qpu_server())
        exp = exception_types.QPUException(exception_types.ErrorType.BREAK)
        exp = exception_types.QPUException(exception_types.ErrorType.BREAK)
        raised = False

        try:
            res = task.execute()
        except exception_types.QPUException as Exp:
            self.assertEqual(Exp.code, 10)
            self.assertEqual(Exp.modulename, "qat.pylinalg")
            raised = True

        self.assertTrue(raised)
Exemplo n.º 2
0
def raise_break(op, op_pos, cbits):
    """
    Raises break exception, as a result of a boolean classical formula being
    evaluated to True.
    """
    present_cbits = []
    for i in op.formula.split(" "):
        try:
            present_cbits += [int(i)]
        except ValueError:
            pass
    message = "BREAK at gate #%s : formula : %s, cbits : %s"%(op_pos, op.formula,
                [(k, bool(cbits[k])) for k in present_cbits])
    exp = exceptions_types.QPUException(code=exceptions_types.ErrorType.BREAK,
                                        modulename="qat.pylinalg",
                                        message=message)

    raise exp
Exemplo n.º 3
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