Ejemplo n.º 1
0
    def setUp(self):
        self.seed = 88
        qasm_filename = self._get_resource_path('qasm/example.qasm')
        unroller = unroll.Unroller(
            qasm.Qasm(filename=qasm_filename).parse(), unroll.JsonBackend([]))
        circuit = QobjExperiment.from_dict(unroller.execute())
        circuit.config = QobjItem(coupling_map=None,
                                  basis_gates='u1,u2,u3,cx,id',
                                  layout=None,
                                  seed=self.seed)
        circuit.header.name = 'test'

        self.qobj = Qobj(qobj_id='test_sim_single_shot',
                         config=QobjConfig(shots=1024,
                                           memory_slots=6,
                                           max_credits=3),
                         experiments=[circuit],
                         header=QobjHeader(backend_name='qasm_simulator_py'))
Ejemplo n.º 2
0
 def setUp(self):
     self.seed = 88
     self.qasmFileName = os.path.join(qiskit.__path__[0],
                                      '../test/python/qasm/example.qasm')
     self.qp = QuantumProgram()
     shots = 1
     self.qp.load_qasm_file(self.qasmFileName, name='example')
     basis_gates = []  # unroll to base gates
     unroller = unroll.Unroller(
         qasm.Qasm(data=self.qp.get_qasm("example")).parse(),
         unroll.JsonBackend(basis_gates))
     circuit = unroller.execute()
     self.job = {
         'compiled_circuit': circuit,
         'config': {
             'shots': shots,
             'seed': random.randint(0, 10)
         }
     }
def _unroller_code(qasm_circuit, basis_gates=None):
    """ Unroll the code.

    Circuit is the circuit to unroll using the DAG representation.
    This is an internal function.

    Args:
        qasm_circuit (str): a circuit representation as qasm text.
        basis_gates (str): a comma seperated string and are the base gates,
                           which by default are: u1,u2,u3,cx,id
    Return:
        object: a dag representation of the circuit unrolled to basis gates
    """
    if not basis_gates:
        basis_gates = "u1,u2,u3,cx,id"  # QE target basis
    program_node_circuit = qasm.Qasm(data=qasm_circuit).parse()
    unroller_circuit = unroll.Unroller(
        program_node_circuit, unroll.DAGBackend(basis_gates.split(",")))
    dag_circuit_unrolled = unroller_circuit.execute()
    return dag_circuit_unrolled
    def setUp(self):
        self.seed = 88
        self.qasm_filename = self._get_resource_path('qasm/example.qasm')
        with open(self.qasm_filename, 'r') as qasm_file:
            self.qasm_text = qasm_file.read()
            self.qasm_ast = qasm.Qasm(data=self.qasm_text).parse()
            self.qasm_be = unroll.CircuitBackend(
                ['u1', 'u2', 'u3', 'id', 'cx'])
            self.qasm_circ = unroll.Unroller(self.qasm_ast,
                                             self.qasm_be).execute()
        qr = QuantumRegister(2, 'q')
        cr = ClassicalRegister(2, 'c')
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[0])
        qc.measure(qr[0], cr[0])
        self.qc = qc

        # create qobj
        compiled_circuit1 = QobjExperiment.from_dict(
            transpile_dag(DAGCircuit.fromQuantumCircuit(self.qc),
                          format='json'))

        compiled_circuit2 = QobjExperiment.from_dict(
            transpile_dag(DAGCircuit.fromQuantumCircuit(self.qasm_circ),
                          format='json'))

        self.qobj = Qobj(qobj_id='test_qobj',
                         config=QobjConfig(shots=2000,
                                           memory_slots=1,
                                           max_credits=3,
                                           seed=1111),
                         experiments=[compiled_circuit1, compiled_circuit2],
                         header=QobjHeader(backend_name='qasm_simulator'))
        self.qobj.experiments[0].header.name = 'test_circuit1'
        self.qobj.experiments[0].config = QobjItem(
            basis_gates='u1,u2,u3,cx,id')
        self.qobj.experiments[1].header.name = 'test_circuit2'
        self.qobj.experiments[1].config = QobjItem(
            basis_gates='u1,u2,u3,cx,id')
        self.backend = QasmSimulator()
    def test_if_statement(self):
        logging.info('test_if_statement_x')
        shots = 100
        max_qubits = 3
        qp = QuantumProgram()
        qr = qp.create_quantum_register('qr', max_qubits)
        cr = qp.create_classical_register('cr', max_qubits)
        circuit = qp.create_circuit('test_if', [qr], [cr])
        circuit.x(qr[0])
        circuit.x(qr[1])
        circuit.measure(qr[0], cr[0])
        circuit.measure(qr[1], cr[1])
        circuit.x(qr[2]).c_if(cr, 0x3)
        circuit.measure(qr[0], cr[0])
        circuit.measure(qr[1], cr[1])
        circuit.measure(qr[2], cr[2])
        basis_gates = []  # unroll to base gates
        unroller = unroll.Unroller(
            qasm.Qasm(data=qp.get_qasm('test_if')).parse(),
            unroll.JsonBackend(basis_gates))
        ucircuit = json.loads(unroller.execute())
        config = {'shots': shots, 'seed': self.seed}
        job = {'compiled_circuit': json.dumps(ucircuit), 'config': config}
        result_if_true = QasmSimulator(job).run()
        del ucircuit['operations'][1]  # remove x(qr[1]) operation
        job = {'compiled_circuit': json.dumps(ucircuit), 'config': config}
        result_if_false = QasmSimulator(job).run()

        logging.info('result_if_true circuit:')
        logging.info(circuit.qasm())
        logging.info('result_if_true={0}'.format(result_if_true))

        del circuit.data[1]
        logging.info('result_if_false circuit:')
        logging.info(circuit.qasm())
        logging.info('result_if_false={0}'.format(result_if_false))
        self.assertTrue(result_if_true['data']['counts']['111'] == 100)
        self.assertTrue(result_if_false['data']['counts']['001'] == 100)
Ejemplo n.º 6
0
 def setUp(self):
     self.seed = 88
     self.qasm_filename = self._get_resource_path('qasm/example.qasm')
     self.qp = QuantumProgram()
     self.qp.load_qasm_file(self.qasm_filename, name='example')
     basis_gates = []  # unroll to base gates
     unroller = unroll.Unroller(
         qasm.Qasm(data=self.qp.get_qasm('example')).parse(),
         unroll.JsonBackend(basis_gates))
     circuit = unroller.execute()
     circuit_config = {
         'coupling_map': None,
         'basis_gates': 'u1,u2,u3,cx,id',
         'layout': None,
         'seed': self.seed
     }
     resources = {'max_credits': 3}
     self.qobj = {
         'id':
         'test_sim_single_shot',
         'config': {
             'max_credits': resources['max_credits'],
             'shots': 1024,
             'backend_name': 'local_qasm_simulator_py',
         },
         'circuits': [{
             'name': 'test',
             'compiled_circuit': circuit,
             'compiled_circuit_qasm': None,
             'config': circuit_config
         }]
     }
     self.q_job = QuantumJob(self.qobj,
                             backend=QasmSimulatorPy(),
                             circuit_config=circuit_config,
                             seed=self.seed,
                             resources=resources,
                             preformatted=True)
Ejemplo n.º 7
0
def dag2json(dag_circuit, basis_gates='u1,u2,u3,cx,id'):
    """Make a Json representation of the circuit.

    Takes a circuit dag and returns json circuit obj. This is an internal
    function.

    Args:
        dag_ciruit (dag object): a dag representation of the circuit.
        basis_gates (str): a comma seperated string and are the base gates,
                               which by default are: u1,u2,u3,cx,id

    Returns:
        the json version of the dag
    """
    # TODO: Jay: I think this needs to become a method like .qasm() for the DAG.
    try:
        circuit_string = dag_circuit.qasm(qeflag=True)
    except TypeError:
        circuit_string = dag_circuit.qasm()
    unroller = unroll.Unroller(qasm.Qasm(data=circuit_string).parse(),
                               unroll.JsonBackend(basis_gates.split(",")))
    json_circuit = unroller.execute()
    return json_circuit
Ejemplo n.º 8
0
 def test_qasm_simulator(self):
     """Test data counts output for single circuit run against reference."""
     shots = 1024
     self.qp.load_qasm_file(self.qasmFileName, name='example')
     basis_gates = []  # unroll to base gates
     unroller = unroll.Unroller(
         qasm.Qasm(data=self.qp.get_qasm("example")).parse(),
         unroll.JsonBackend(basis_gates))
     circuit = unroller.execute()
     config = {'shots': shots, 'seed': self.seed}
     job = {'compiled_circuit': circuit, 'config': config}
     result = QasmSimulator(job).run()
     expected = {
         '100 100': 137,
         '011 011': 131,
         '101 101': 117,
         '111 111': 127,
         '000 000': 131,
         '010 010': 141,
         '110 110': 116,
         '001 001': 124
     }
     self.assertEqual(result['data']['counts'], expected)
Ejemplo n.º 9
0
    def test_if_statement(self):
        self.log.info('test_if_statement_x')
        shots = 100
        max_qubits = 3
        qr = QuantumRegister(max_qubits, 'qr')
        cr = ClassicalRegister(max_qubits, 'cr')
        circuit_if_true = QuantumCircuit(qr, cr, name='test_if_true')
        circuit_if_true.x(qr[0])
        circuit_if_true.x(qr[1])
        circuit_if_true.measure(qr[0], cr[0])
        circuit_if_true.measure(qr[1], cr[1])
        circuit_if_true.x(qr[2]).c_if(cr, 0x3)
        circuit_if_true.measure(qr[0], cr[0])
        circuit_if_true.measure(qr[1], cr[1])
        circuit_if_true.measure(qr[2], cr[2])
        circuit_if_false = QuantumCircuit(qr, cr, name='test_if_false')
        circuit_if_false.x(qr[0])
        circuit_if_false.measure(qr[0], cr[0])
        circuit_if_false.measure(qr[1], cr[1])
        circuit_if_false.x(qr[2]).c_if(cr, 0x3)
        circuit_if_false.measure(qr[0], cr[0])
        circuit_if_false.measure(qr[1], cr[1])
        circuit_if_false.measure(qr[2], cr[2])
        basis_gates = []  # unroll to base gates
        unroller = unroll.Unroller(
            qasm.Qasm(data=circuit_if_true.qasm()).parse(),
            unroll.JsonBackend(basis_gates))
        ucircuit_true = QobjExperiment.from_dict(unroller.execute())
        unroller = unroll.Unroller(
            qasm.Qasm(data=circuit_if_false.qasm()).parse(),
            unroll.JsonBackend(basis_gates))
        ucircuit_false = QobjExperiment.from_dict(unroller.execute())

        # Customize the experiments and create the qobj.
        ucircuit_true.config = QobjItem(coupling_map=None,
                                        basis_gates='u1,u2,u3,cx,id',
                                        layout=None,
                                        seed=None)
        ucircuit_true.header.name = 'test_if_true'
        ucircuit_false.config = QobjItem(coupling_map=None,
                                         basis_gates='u1,u2,u3,cx,id',
                                         layout=None,
                                         seed=None)
        ucircuit_false.header.name = 'test_if_false'

        qobj = Qobj(id='test_if_qobj',
                    config=QobjConfig(max_credits=3,
                                      shots=shots,
                                      memory_slots=max_qubits),
                    experiments=[ucircuit_true, ucircuit_false],
                    header=QobjHeader(backend_name='local_qasm_simulator_py'))

        result = QasmSimulatorPy().run(qobj).result()
        result_if_true = result.get_data('test_if_true')
        self.log.info('result_if_true circuit:')
        self.log.info(circuit_if_true.qasm())
        self.log.info('result_if_true=%s', result_if_true)

        result_if_false = result.get_data('test_if_false')
        self.log.info('result_if_false circuit:')
        self.log.info(circuit_if_false.qasm())
        self.log.info('result_if_false=%s', result_if_false)
        self.assertTrue(result_if_true['counts']['111'] == 100)
        self.assertTrue(result_if_false['counts']['001'] == 100)
Ejemplo n.º 10
0
def optimize_1q_gates(circuit):
    """Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    """
    qx_basis = ["u1", "u2", "u3", "cx", "id"]
    urlr = unroll.Unroller(
        Qasm(data=circuit.qasm(qeflag=True)).parse(),
        unroll.DAGBackend(qx_basis))
    unrolled = urlr.execute()

    runs = unrolled.collect_runs(["u1", "u2", "u3", "id"])
    for run in runs:
        qname = unrolled.multi_graph.node[run[0]]["qargs"][0]
        right_name = "u1"
        right_parameters = (0.0, 0.0, 0.0)  # (theta, phi, lambda)
        for node in run:
            nd = unrolled.multi_graph.node[node]
            assert nd["condition"] is None, "internal error"
            assert len(nd["qargs"]) == 1, "internal error"
            assert nd["qargs"][0] == qname, "internal error"
            left_name = nd["name"]
            assert left_name in ["u1", "u2", "u3", "id"], "internal error"
            if left_name == "u1":
                left_parameters = (0.0, 0.0, float(nd["params"][0]))
            elif left_name == "u2":
                left_parameters = (math.pi / 2, float(nd["params"][0]),
                                   float(nd["params"][1]))
            elif left_name == "u3":
                left_parameters = tuple(map(float, nd["params"]))
            else:
                left_name = "u1"  # replace id with u1
                left_parameters = (0.0, 0.0, 0.0)
            # Compose gates
            name_tuple = (left_name, right_name)
            if name_tuple == ("u1", "u1"):
                # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2)
                right_parameters = (0.0, 0.0,
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u2"):
                # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2)
                right_parameters = (math.pi / 2,
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u2", "u1"):
                # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2)
                right_name = "u2"
                right_parameters = (math.pi / 2, left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u3"):
                # u1(lambda1) * u3(theta2, phi2, lambda2) =
                #     u3(theta2, phi2 + lambda1, lambda2)
                right_parameters = (right_parameters[0],
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u3", "u1"):
                # u3(theta1, phi1, lambda1) * u1(lambda2) =
                #     u3(theta1, phi1, lambda1 + lambda2)
                right_name = "u3"
                right_parameters = (left_parameters[0], left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u2", "u2"):
                # Using Ry(pi/2).Rz(2*lambda).Ry(pi/2) =
                #    Rz(pi/2).Ry(pi-2*lambda).Rz(pi/2),
                # u2(phi1, lambda1) * u2(phi2, lambda2) =
                #    u3(pi - lambda1 - phi2, phi1 + pi/2, lambda2 + pi/2)
                right_name = "u3"
                right_parameters = (math.pi - left_parameters[2] -
                                    right_parameters[1],
                                    left_parameters[1] + math.pi / 2,
                                    right_parameters[2] + math.pi / 2)
            else:
                # For composing u3's or u2's with u3's, use
                # u2(phi, lambda) = u3(pi/2, phi, lambda)
                # together with the qiskit.mapper.compose_u3 method.
                right_name = "u3"
                right_parameters = compose_u3(left_parameters[0],
                                              left_parameters[1],
                                              left_parameters[2],
                                              right_parameters[0],
                                              right_parameters[1],
                                              right_parameters[2])
            # Here down, when we simplify, we add f(theta) to lambda to correct
            # the global phase when f(theta) is 2*pi. This isn't necessary but
            # the other steps preserve the global phase, so we continue.
            epsilon = 1e-9  # for comparison with zero
            # Y rotation is 0 mod 2*pi, so the gate is a u1
            if abs(right_parameters[0] % 2.0 * math.pi) < epsilon \
               and right_name != "u1":
                right_name = "u1"
                right_parameters = (0.0, 0.0, right_parameters[1] +
                                    right_parameters[2] + right_parameters[0])
            # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2
            if right_name == "u3":
                # theta = pi/2 + 2*k*pi
                if abs((right_parameters[0] - math.pi / 2) % 2.0 * math.pi) \
                   < epsilon:
                    right_name = "u2"
                    right_parameters = (math.pi / 2, right_parameters[1],
                                        right_parameters[2] +
                                        (right_parameters[0] - math.pi / 2))
                # theta = -pi/2 + 2*k*pi
                if abs((right_parameters[0] + math.pi / 2) % 2.0 * math.pi) \
                   < epsilon:
                    right_name = "u2"
                    right_parameters = (math.pi / 2,
                                        right_parameters[1] + math.pi,
                                        right_parameters[2] - math.pi +
                                        (right_parameters[0] + math.pi / 2))
            # u1 and lambda is 0 mod 4*pi so gate is nop
            if right_name == "u1" and \
               abs(right_parameters[2] % 4.0 * math.pi) < epsilon:
                right_name = "nop"
        # Replace the data of the first node in the run
        new_params = []
        if right_name == "u1":
            new_params.append(right_parameters[2])
        if right_name == "u2":
            new_params = [right_parameters[1], right_parameters[2]]
        if right_name == "u3":
            new_params = list(right_parameters)
        nx.set_node_attributes(unrolled.multi_graph, 'name',
                               {run[0]: right_name})
        nx.set_node_attributes(unrolled.multi_graph, 'params',
                               {run[0]: tuple(map(str, new_params))})
        # Delete the other nodes in the run
        for node in run[1:]:
            unrolled._remove_op_node(node)
        if right_name == "nop":
            unrolled._remove_op_node(run[0])
    return unrolled
Ejemplo n.º 11
0
def compiler_function(dag_circuit, coupling_map=None, gate_costs=None):
    """
    Modify a DAGCircuit based on a gate cost function.

    Instructions:
        Your submission involves filling in the implementation
        of this function. The function takes as input a DAGCircuit
        object, which can be generated from a QASM file by using the
        function 'qasm_to_dag_circuit' from the included
        'submission_evaluation.py' module. For more information
        on the DAGCircuit object see the or QISKit documentation
        (eg. 'help(DAGCircuit)').

    Args:
        dag_circuit (DAGCircuit): DAGCircuit object to be compiled.
        coupling_circuit (list): Coupling map for device topology.
                                 A coupling map of None corresponds an
                                 all-to-all connected topology.
        gate_costs (dict) : dictionary of gate names and costs.

    Returns:
        A modified DAGCircuit object that satisfies an input coupling_map
        and has as low a gate_cost as possible.
    """

    qasm_in = dag_circuit.qasm()
    Q_program = QuantumProgram()
    qcircuit_name = Q_program.load_qasm_text(qasm_in)
    qcircuit = Q_program.get_circuit(qcircuit_name)

    tuple_map = {}
    if coupling_map is None:
        # todo: make all-to-all map
        raise ValueError
    else:
        for key in coupling_map.keys():
            tuple_map[key] = tuple(coupling_map[key])

    result, cost = Embed(qcircuit, tuple_map)
    compiled_dag = DAGCircuit.fromQuantumCircuit(result)
    return compiled_dag

    if False:
        # Example using mapper passes in Qiskit
        import copy
        from qiskit.mapper import swap_mapper, direction_mapper, cx_cancellation, optimize_1q_gates, Coupling
        from qiskit import qasm, unroll
        initial_layout = None
        coupling = Coupling(coupling_map)
        compiled_dag, final_layout = swap_mapper(copy.deepcopy(dag_circuit),
                                                 coupling,
                                                 initial_layout,
                                                 trials=40,
                                                 seed=19)
        # Expand swaps
        basis_gates = "u1,u2,u3,cx,id"  # QE target basis
        program_node_circuit = qasm.Qasm(data=compiled_dag.qasm()).parse()
        unroller_circuit = unroll.Unroller(
            program_node_circuit, unroll.DAGBackend(basis_gates.split(",")))
        compiled_dag = unroller_circuit.execute()
        # Change cx directions
        compiled_dag = direction_mapper(compiled_dag, coupling)
        # Simplify cx gates
        cx_cancellation(compiled_dag)
        # Simplify single qubit gates
        compiled_dag = optimize_1q_gates(compiled_dag)

        # Return the compiled dag circuit
        return compiled_dag
Ejemplo n.º 12
0
def swap_mapper(circuit_graph, coupling_graph,
                initial_layout=None,
                basis="cx,u1,u2,u3,id", verbose=False):
    """Map a Circuit onto a CouplingGraph using swap gates.

    circuit_graph = input Circuit
    coupling_graph = CouplingGraph to map onto
    initial_layout = dict from qubits of circuit_graph to qubits
      of coupling_graph (optional)
    basis = basis string specifying basis of output Circuit
    verbose = optional flag to print more information

    Returns a Circuit object containing a circuit equivalent to
    circuit_graph that respects couplings in coupling_graph, and
    a layout dict mapping qubits of circuit_graph into qubits
    of coupling_graph. The layout may differ from the initial_layout
    if the first layer of gates cannot be executed on the
    initial_layout.
    """
    if circuit_graph.width() > coupling_graph.size():
        raise QISKitException("Not enough qubits in CouplingGraph")

    # Schedule the input circuit
    layerlist = circuit_graph.layers()
    if verbose:
        print("schedule:")
        for i in range(len(layerlist)):
            print("    %d: %s" % (i, layerlist[i]["partition"]))

    # Check input layout and create default layout if necessary
    if initial_layout is not None:
        circ_qubits = circuit_graph.get_qubits()
        coup_qubits = coupling_graph.get_qubits()
        qubit_subset = []
        for k, v in initial_layout.values():
            qubit_subset.append(v)
            if k not in circ_qubits:
                raise QISKitException("initial_layout qubit %s[%d] not " +
                                      "in input Circuit" % (k[0], k[1]))
            if v not in coup_qubits:
                raise QISKitException("initial_layout qubit %s[%d] not " +
                                      " in input CouplingGraph" % (v[0], v[1]))
    else:
        # Supply a default layout
        qubit_subset = coupling_graph.get_qubits()
        qubit_subset = qubit_subset[0:circuit_graph.width()]
        initial_layout = {a: b for a, b in
                          zip(circuit_graph.get_qubits(), qubit_subset)}

    # Find swap circuit to preceed to each layer of input circuit
    layout = copy.deepcopy(initial_layout)
    openqasm_output = ""
    first_layer = True  # True until first layer is output
    first_swapping_layer = True  # True until first swap layer is output
    # Iterate over layers
    for i in range(len(layerlist)):
        # Attempt to find a permutation for this layer
        success_flag, best_circ, best_d, best_layout, trivial_flag \
            = layer_permutation(layerlist[i]["partition"], layout,
                                qubit_subset, coupling_graph, 20)
        # If this fails, try one gate at a time in this layer
        if not success_flag:
            if verbose:
                print("swap_mapper: failed, layer %d, " % i,
                      " retrying sequentially")
            serial_layerlist = layerlist[i]["graph"].serial_layers()
            # Go through each gate in the layer
            for j in range(len(serial_layerlist)):
                success_flag, best_circ, best_d, best_layout, trivial_flag \
                    = layer_permutation(serial_layerlist[j]["partition"],
                                        layout, qubit_subset, coupling_graph,
                                        20)
                # Give up if we fail again
                if not success_flag:
                    raise QISKitException("swap_mapper failed: " +
                                          "layer %d, sublayer %d" % (i, j) +
                                          ", \"%s\"" %
                                          serial_layerlist[j]["graph"].qasm(
                                              no_decls=True,
                                              aliases=layout))
                else:
                    # Update the qubit positions each iteration
                    layout = best_layout
                    if best_d == 0:
                        # Output qasm without swaps
                        if first_layer:
                            openqasm_output += circuit_graph.qasm(
                                add_swap=True,
                                decls_only=True,
                                aliases=layout)
                            first_layer = False
                        if not trivial_flag and first_swapping_layer:
                            initial_layout = layout
                            first_swapping_layer = False
                    else:
                        # Output qasm with swaps
                        if first_layer:
                            openqasm_output += circuit_graph.qasm(
                                add_swap=True,
                                decls_only=True,
                                aliases=layout)
                            first_layer = False
                            initial_layout = layout
                            first_swapping_layer = False
                        else:
                            if not first_swapping_layer:
                                if verbose:
                                    print("swap_mapper: layer %d (%d), depth %d"
                                          % (i, j, best_d))
                                openqasm_output += best_circ
                            else:
                                initial_layout = layout
                                first_swapping_layer = False
                        openqasm_output += serial_layerlist[j]["graph"].qasm(
                                    no_decls=True,
                                    aliases=layout)
        else:
            # Update the qubit positions each iteration
            layout = best_layout
            if best_d == 0:
                # Output qasm without swaps
                if first_layer:
                    openqasm_output += circuit_graph.qasm(
                                add_swap=True,
                                decls_only=True,
                                aliases=layout)
                    first_layer = False
                if not trivial_flag and first_swapping_layer:
                    initial_layout = layout
                    first_swapping_layer = False
            else:
                # Output qasm with swaps
                if first_layer:
                    openqasm_output += circuit_graph.qasm(
                                add_swap=True,
                                decls_only=True,
                                aliases=layout)
                    first_layer = False
                    initial_layout = layout
                    first_swapping_layer = False
                else:
                    if not first_swapping_layer:
                        if verbose:
                            print("swap_mapper: layer %d, depth %d"
                                  % (i, best_d))
                        openqasm_output += best_circ
                    else:
                        initial_layout = layout
                        first_swapping_layer = False
            openqasm_output += layerlist[i]["graph"].qasm(
                                    no_decls=True,
                                    aliases=layout)
    # Parse openqasm_output into Circuit object
    basis += ",swap"
    ast = Qasm(data=openqasm_output).parse()
    u = unroll.Unroller(ast, unroll.CircuitBackend(basis.split(",")))
    u.execute()
    return u.backend.circuit, initial_layout
Ejemplo n.º 13
0
def swap_mapper(circuit_graph,
                coupling_graph,
                initial_layout=None,
                basis="cx,u1,u2,u3,id",
                trials=20):
    """Map a DAGCircuit onto a CouplingGraph using swap gates.

    Args:
        circuit_graph (DAGCircuit): input DAG circuit
        coupling_graph (CouplingGraph): coupling graph to map onto
        initial_layout (dict): dict from qubits of circuit_graph to qubits
            of coupling_graph (optional)
        basis (str, optional): basis string specifying basis of output
            DAGCircuit

    Returns:
        Returns a DAGCircuit object containing a circuit equivalent to
        circuit_graph that respects couplings in coupling_graph, and
        a layout dict mapping qubits of circuit_graph into qubits
        of coupling_graph. The layout may differ from the initial_layout
        if the first layer of gates cannot be executed on the
        initial_layout.
    """
    if circuit_graph.width() > coupling_graph.size():
        raise MapperError("Not enough qubits in CouplingGraph")

    # Schedule the input circuit
    layerlist = circuit_graph.layers()
    logger.debug("schedule:")
    for i in range(len(layerlist)):
        logger.debug("    %d: %s", i, layerlist[i]["partition"])

    if initial_layout is not None:
        # Check the input layout
        circ_qubits = circuit_graph.get_qubits()
        coup_qubits = coupling_graph.get_qubits()
        qubit_subset = []
        for k, v in initial_layout.items():
            qubit_subset.append(v)
            if k not in circ_qubits:
                raise MapperError("initial_layout qubit %s[%d] not in input "
                                  "DAGCircuit" % (k[0], k[1]))
            if v not in coup_qubits:
                raise MapperError("initial_layout qubit %s[%d] not in input "
                                  "CouplingGraph" % (v[0], v[1]))
    else:
        # Supply a default layout
        qubit_subset = coupling_graph.get_qubits()
        qubit_subset = qubit_subset[0:circuit_graph.width()]
        initial_layout = {
            a: b
            for a, b in zip(circuit_graph.get_qubits(), qubit_subset)
        }

    # Find swap circuit to preceed to each layer of input circuit
    layout = copy.deepcopy(initial_layout)
    openqasm_output = ""
    first_layer = True  # True until first layer is output
    logger.debug("initial_layout = %s", layout)

    # Iterate over layers
    for i, layer in enumerate(layerlist):

        # Attempt to find a permutation for this layer
        success_flag, best_circ, best_d, best_layout, trivial_flag \
            = layer_permutation(layer["partition"], layout,
                                qubit_subset, coupling_graph, trials)
        logger.debug("swap_mapper: layer %d", i)
        logger.debug("swap_mapper: success_flag=%s,best_d=%s,trivial_flag=%s",
                     success_flag, str(best_d), trivial_flag)

        # If this layer is only single-qubit gates,
        # and we have yet to see multi-qubit gates,
        # continue to the next iteration
        if trivial_flag and first_layer:
            logger.debug("swap_mapper: skip to next layer")
            continue

        # If this fails, try one gate at a time in this layer
        if not success_flag:
            logger.debug(
                "swap_mapper: failed, layer %d, "
                "retrying sequentially", i)
            serial_layerlist = layer["graph"].serial_layers()

            # Go through each gate in the layer
            for j, serial_layer in enumerate(serial_layerlist):

                success_flag, best_circ, best_d, best_layout, trivial_flag \
                    = layer_permutation(serial_layer["partition"],
                                        layout, qubit_subset, coupling_graph,
                                        trials)
                logger.debug("swap_mapper: layer %d, sublayer %d", i, j)
                logger.debug(
                    "swap_mapper: success_flag=%s,best_d=%s,"
                    "trivial_flag=%s", success_flag, str(best_d), trivial_flag)

                # Give up if we fail again
                if not success_flag:
                    raise MapperError("swap_mapper failed: " +
                                      "layer %d, sublayer %d" % (i, j) +
                                      ", \"%s\"" % serial_layer["graph"].qasm(
                                          no_decls=True, aliases=layout))

                # If this layer is only single-qubit gates,
                # and we have yet to see multi-qubit gates,
                # continue to the next inner iteration
                if trivial_flag and first_layer:
                    logger.debug("swap_mapper: skip to next sublayer")
                    continue

                # Update the record of qubit positions for each inner iteration
                layout = best_layout
                # Update the QASM
                openqasm_output += update_qasm(j, first_layer, best_layout,
                                               best_d, best_circ,
                                               circuit_graph, serial_layerlist)
                # Update initial layout
                if first_layer:
                    initial_layout = layout
                    first_layer = False

        else:
            # Update the record of qubit positions for each iteration
            layout = best_layout

            # Update the QASM
            openqasm_output += update_qasm(i, first_layer, best_layout, best_d,
                                           best_circ, circuit_graph, layerlist)
            # Update initial layout
            if first_layer:
                initial_layout = layout
                first_layer = False

    # If first_layer is still set, the circuit only has single-qubit gates
    # so we can use the initial layout to output the entire circuit
    if first_layer:
        layout = initial_layout
        openqasm_output += circuit_graph.qasm(add_swap=True,
                                              decls_only=True,
                                              aliases=layout)
        for i, layer in enumerate(layerlist):
            openqasm_output += layer["graph"].qasm(no_decls=True,
                                                   aliases=layout)

    # Parse openqasm_output into DAGCircuit object
    basis += ",swap"
    ast = Qasm(data=openqasm_output).parse()
    u = unroll.Unroller(ast, unroll.DAGBackend(basis.split(",")))
    return u.execute(), initial_layout
Ejemplo n.º 14
0
    def test_if_statement(self):
        self.log.info('test_if_statement_x')
        shots = 100
        max_qubits = 3
        qp = QuantumProgram()
        qr = qp.create_quantum_register('qr', max_qubits)
        cr = qp.create_classical_register('cr', max_qubits)
        circuit_if_true = qp.create_circuit('test_if_true', [qr], [cr])
        circuit_if_true.x(qr[0])
        circuit_if_true.x(qr[1])
        circuit_if_true.measure(qr[0], cr[0])
        circuit_if_true.measure(qr[1], cr[1])
        circuit_if_true.x(qr[2]).c_if(cr, 0x3)
        circuit_if_true.measure(qr[0], cr[0])
        circuit_if_true.measure(qr[1], cr[1])
        circuit_if_true.measure(qr[2], cr[2])
        circuit_if_false = qp.create_circuit('test_if_false', [qr], [cr])
        circuit_if_false.x(qr[0])
        circuit_if_false.measure(qr[0], cr[0])
        circuit_if_false.measure(qr[1], cr[1])
        circuit_if_false.x(qr[2]).c_if(cr, 0x3)
        circuit_if_false.measure(qr[0], cr[0])
        circuit_if_false.measure(qr[1], cr[1])
        circuit_if_false.measure(qr[2], cr[2])
        basis_gates = []  # unroll to base gates
        unroller = unroll.Unroller(
            qasm.Qasm(data=qp.get_qasm('test_if_true')).parse(),
            unroll.JsonBackend(basis_gates))
        ucircuit_true = unroller.execute()
        unroller = unroll.Unroller(
            qasm.Qasm(data=qp.get_qasm('test_if_false')).parse(),
            unroll.JsonBackend(basis_gates))
        ucircuit_false = unroller.execute()
        qobj = {
            'id':
            'test_if_qobj',
            'config': {
                'max_credits': 3,
                'shots': shots,
                'backend_name': 'local_qasm_simulator_py',
            },
            'circuits': [{
                'name': 'test_if_true',
                'compiled_circuit': ucircuit_true,
                'compiled_circuit_qasm': None,
                'config': {
                    'coupling_map': None,
                    'basis_gates': 'u1,u2,u3,cx,id',
                    'layout': None,
                    'seed': None
                }
            }, {
                'name': 'test_if_false',
                'compiled_circuit': ucircuit_false,
                'compiled_circuit_qasm': None,
                'config': {
                    'coupling_map': None,
                    'basis_gates': 'u1,u2,u3,cx,id',
                    'layout': None,
                    'seed': None
                }
            }]
        }
        q_job = QuantumJob(qobj, backend=QasmSimulatorPy(), preformatted=True)
        result = QasmSimulatorPy().run(q_job).result()
        result_if_true = result.get_data('test_if_true')
        self.log.info('result_if_true circuit:')
        self.log.info(circuit_if_true.qasm())
        self.log.info('result_if_true=%s', result_if_true)

        result_if_false = result.get_data('test_if_false')
        self.log.info('result_if_false circuit:')
        self.log.info(circuit_if_false.qasm())
        self.log.info('result_if_false=%s', result_if_false)
        self.assertTrue(result_if_true['counts']['111'] == 100)
        self.assertTrue(result_if_false['counts']['001'] == 100)
Ejemplo n.º 15
0
def optimize_1q_gates(circuit):
    """Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    """
    qx_basis = ["u1", "u2", "u3", "cx", "id"]
    urlr = unroll.Unroller(
        Qasm(data=circuit.qasm()).parse(), unroll.DAGBackend(qx_basis))
    unrolled = urlr.execute()

    runs = unrolled.collect_runs(["u1", "u2", "u3", "id"])
    for run in runs:
        qname = unrolled.multi_graph.node[run[0]]["qargs"][0]
        right_name = "u1"
        right_parameters = (N(0), N(0), N(0))  # (theta, phi, lambda)
        for node in run:
            nd = unrolled.multi_graph.node[node]
            assert nd["condition"] is None, "internal error"
            assert len(nd["qargs"]) == 1, "internal error"
            assert nd["qargs"][0] == qname, "internal error"
            left_name = nd["name"]
            assert left_name in ["u1", "u2", "u3", "id"], "internal error"
            if left_name == "u1":
                left_parameters = (N(0), N(0), nd["params"][0])
            elif left_name == "u2":
                left_parameters = (sympy.pi / 2, nd["params"][0],
                                   nd["params"][1])
            elif left_name == "u3":
                left_parameters = tuple(nd["params"])
            else:
                left_name = "u1"  # replace id with u1
                left_parameters = (N(0), N(0), N(0))
            # Compose gates
            name_tuple = (left_name, right_name)
            if name_tuple == ("u1", "u1"):
                # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2)
                right_parameters = (N(0), N(0),
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u2"):
                # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2)
                right_parameters = (sympy.pi / 2,
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u2", "u1"):
                # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2)
                right_name = "u2"
                right_parameters = (sympy.pi / 2, left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u3"):
                # u1(lambda1) * u3(theta2, phi2, lambda2) =
                #     u3(theta2, phi2 + lambda1, lambda2)
                right_parameters = (right_parameters[0],
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u3", "u1"):
                # u3(theta1, phi1, lambda1) * u1(lambda2) =
                #     u3(theta1, phi1, lambda1 + lambda2)
                right_name = "u3"
                right_parameters = (left_parameters[0], left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u2", "u2"):
                # Using Ry(pi/2).Rz(2*lambda).Ry(pi/2) =
                #    Rz(pi/2).Ry(pi-2*lambda).Rz(pi/2),
                # u2(phi1, lambda1) * u2(phi2, lambda2) =
                #    u3(pi - lambda1 - phi2, phi1 + pi/2, lambda2 + pi/2)
                right_name = "u3"
                right_parameters = (sympy.pi - left_parameters[2] -
                                    right_parameters[1],
                                    left_parameters[1] + sympy.pi / 2,
                                    right_parameters[2] + sympy.pi / 2)
            elif name_tuple[1] == "nop":
                right_name = left_name
                right_parameters = left_parameters
            else:
                # For composing u3's or u2's with u3's, use
                # u2(phi, lambda) = u3(pi/2, phi, lambda)
                # together with the qiskit.mapper.compose_u3 method.
                right_name = "u3"
                # Evaluate the symbolic expressions for efficiency
                left_parameters = tuple(
                    map(lambda x: x.evalf(), list(left_parameters)))
                right_parameters = tuple(
                    map(lambda x: x.evalf(), list(right_parameters)))
                right_parameters = compose_u3(left_parameters[0],
                                              left_parameters[1],
                                              left_parameters[2],
                                              right_parameters[0],
                                              right_parameters[1],
                                              right_parameters[2])
                # Why evalf()? This program:
                #   OPENQASM 2.0;
                #   include "qelib1.inc";
                #   qreg q[2];
                #   creg c[2];
                #   u3(0.518016983430947*pi,1.37051598592907*pi,1.36816383603222*pi) q[0];
                #   u3(1.69867232277986*pi,0.371448347747471*pi,0.461117217930936*pi) q[0];
                #   u3(0.294319836336836*pi,0.450325871124225*pi,1.46804720442555*pi) q[0];
                #   measure q -> c;
                # took >630 seconds (did not complete) to optimize without
                # calling evalf() at all, 19 seconds to optimize calling
                # evalf() AFTER compose_u3, and 1 second to optimize
                # calling evalf() BEFORE compose_u3.
            # 1. Here down, when we simplify, we add f(theta) to lambda to
            # correct the global phase when f(theta) is 2*pi. This isn't
            # necessary but the other steps preserve the global phase, so
            # we continue in that manner.
            # 2. The final step will remove Z rotations by 2*pi.
            # 3. Note that is_zero is true only if the expression is exactly
            # zero. If the input expressions have already been evaluated
            # then these final simplifications will not occur.
            # TODO After we refactor, we should have separate passes for
            # exact and approximate rewriting.

            # Y rotation is 0 mod 2*pi, so the gate is a u1
            if (right_parameters[0] % (2 * sympy.pi)).is_zero \
                    and right_name != "u1":
                right_name = "u1"
                right_parameters = (0, 0, right_parameters[1] +
                                    right_parameters[2] + right_parameters[0])
            # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2
            if right_name == "u3":
                # theta = pi/2 + 2*k*pi
                if ((right_parameters[0] - sympy.pi / 2) %
                    (2 * sympy.pi)).is_zero:
                    right_name = "u2"
                    right_parameters = (sympy.pi / 2, right_parameters[1],
                                        right_parameters[2] +
                                        (right_parameters[0] - sympy.pi / 2))
                # theta = -pi/2 + 2*k*pi
                if ((right_parameters[0] + sympy.pi / 2) %
                    (2 * sympy.pi)).is_zero:
                    right_name = "u2"
                    right_parameters = (sympy.pi / 2,
                                        right_parameters[1] + sympy.pi,
                                        right_parameters[2] - sympy.pi +
                                        (right_parameters[0] + sympy.pi / 2))
            # u1 and lambda is 0 mod 2*pi so gate is nop (up to a global phase)
            if right_name == "u1" and (right_parameters[2] %
                                       (2 * sympy.pi)).is_zero:
                right_name = "nop"
            # Simplify the symbolic parameters
            right_parameters = tuple(
                map(sympy.simplify, list(right_parameters)))
        # Replace the data of the first node in the run
        new_params = []
        if right_name == "u1":
            new_params = [right_parameters[2]]
        if right_name == "u2":
            new_params = [right_parameters[1], right_parameters[2]]
        if right_name == "u3":
            new_params = list(right_parameters)

        nx.set_node_attributes(unrolled.multi_graph,
                               name='name',
                               values={run[0]: right_name})
        # params is a list of sympy symbols and the str() method
        # will return Python expressions. To get the correct
        # OpenQASM expression, we need to replace "**" with "^".
        nx.set_node_attributes(unrolled.multi_graph,
                               name='params',
                               values={
                                   run[0]:
                                   tuple(
                                       map(lambda x: str(x).replace("**", "^"),
                                           new_params))
                               })
        # Delete the other nodes in the run
        for node in run[1:]:
            unrolled._remove_op_node(node)
        if right_name == "nop":
            unrolled._remove_op_node(run[0])
    return unrolled
Ejemplo n.º 16
0
def optimize_1q_gates(circuit):
    """Simplify runs of single qubit gates in the QX basis.

    Return a new circuit that has been optimized.
    """
    qx_basis = ["u1", "u2", "u3", "cx", "id"]
    urlr = unroll.Unroller(
        Qasm(data=circuit.qasm(qeflag=True)).parse(),
        unroll.DAGBackend(qx_basis))
    unrolled = urlr.execute()

    runs = unrolled.collect_runs(["u1", "u2", "u3", "id"])
    for run in runs:
        qname = unrolled.multi_graph.node[run[0]]["qargs"][0]
        right_name = "u1"
        right_parameters = (0, 0, 0)  # (theta, phi, lambda)
        for node in run:
            nd = unrolled.multi_graph.node[node]
            assert nd["condition"] is None, "internal error"
            assert len(nd["qargs"]) == 1, "internal error"
            assert nd["qargs"][0] == qname, "internal error"
            left_name = nd["name"]
            assert left_name in ["u1", "u2", "u3", "id"], "internal error"
            if left_name == "u1":
                left_parameters = (0, 0, sympy.sympify(nd["params"][0]))
            elif left_name == "u2":
                left_parameters = (sympy.pi / 2,
                                   sympy.sympify(nd["params"][0]),
                                   sympy.sympify(nd["params"][1]))
            elif left_name == "u3":
                left_parameters = tuple(sympy.sympify(nd["params"]))
            else:
                left_name = "u1"  # replace id with u1
                left_parameters = (0, 0, 0)
            # Compose gates
            name_tuple = (left_name, right_name)
            if name_tuple == ("u1", "u1"):
                # u1(lambda1) * u1(lambda2) = u1(lambda1 + lambda2)
                right_parameters = (0, 0,
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u2"):
                # u1(lambda1) * u2(phi2, lambda2) = u2(phi2 + lambda1, lambda2)
                right_parameters = (sympy.pi / 2,
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u2", "u1"):
                # u2(phi1, lambda1) * u1(lambda2) = u2(phi1, lambda1 + lambda2)
                right_name = "u2"
                right_parameters = (sympy.pi / 2, left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u1", "u3"):
                # u1(lambda1) * u3(theta2, phi2, lambda2) =
                #     u3(theta2, phi2 + lambda1, lambda2)
                right_parameters = (right_parameters[0],
                                    right_parameters[1] + left_parameters[2],
                                    right_parameters[2])
            elif name_tuple == ("u3", "u1"):
                # u3(theta1, phi1, lambda1) * u1(lambda2) =
                #     u3(theta1, phi1, lambda1 + lambda2)
                right_name = "u3"
                right_parameters = (left_parameters[0], left_parameters[1],
                                    right_parameters[2] + left_parameters[2])
            elif name_tuple == ("u2", "u2"):
                # Using Ry(pi/2).Rz(2*lambda).Ry(pi/2) =
                #    Rz(pi/2).Ry(pi-2*lambda).Rz(pi/2),
                # u2(phi1, lambda1) * u2(phi2, lambda2) =
                #    u3(pi - lambda1 - phi2, phi1 + pi/2, lambda2 + pi/2)
                right_name = "u3"
                right_parameters = (sympy.pi - left_parameters[2] -
                                    right_parameters[1],
                                    left_parameters[1] + sympy.pi / 2,
                                    right_parameters[2] + sympy.pi / 2)
            else:
                # For composing u3's or u2's with u3's, use
                # u2(phi, lambda) = u3(pi/2, phi, lambda)
                # together with the qiskit.mapper.compose_u3 method.
                right_name = "u3"
                right_parameters = compose_u3(left_parameters[0],
                                              left_parameters[1],
                                              left_parameters[2],
                                              right_parameters[0],
                                              right_parameters[1],
                                              right_parameters[2])
                # Evaluate the symbolic expressions for efficiency
                right_parameters = tuple(map(sympy.N, list(right_parameters)))

            # 1. Here down, when we simplify, we add f(theta) to lambda to
            # correct the global phase when f(theta) is 2*pi. This isn't
            # necessary but the other steps preserve the global phase, so
            # we continue in that manner.
            # 2. The final step will remove Z rotations by 2*pi.
            # 3. Note that is_zero is true only if the expression is exactly
            # zero. If the input expressions have already been evaluated
            # then these final simplifications will not occur.
            # TODO After we refactor, we should have separate passes for
            # exact and approximate rewriting.

            # Y rotation is 0 mod 2*pi, so the gate is a u1
            if (right_parameters[0] % (2 * sympy.pi)).is_zero \
               and right_name != "u1":
                right_name = "u1"
                right_parameters = (0, 0, right_parameters[1] +
                                    right_parameters[2] + right_parameters[0])
            # Y rotation is pi/2 or -pi/2 mod 2*pi, so the gate is a u2
            if right_name == "u3":
                # theta = pi/2 + 2*k*pi
                if ((right_parameters[0] - sympy.pi / 2) %
                    (2 * sympy.pi)).is_zero:
                    right_name = "u2"
                    right_parameters = (sympy.pi / 2, right_parameters[1],
                                        right_parameters[2] +
                                        (right_parameters[0] - sympy.pi / 2))
                # theta = -pi/2 + 2*k*pi
                if ((right_parameters[0] + sympy.pi / 2) %
                    (2 * sympy.pi)).is_zero:
                    right_name = "u2"
                    right_parameters = (sympy.pi / 2,
                                        right_parameters[1] + sympy.pi,
                                        right_parameters[2] - sympy.pi +
                                        (right_parameters[0] + sympy.pi / 2))
            # u1 and lambda is 0 mod 2*pi so gate is nop (up to a global phase)
            if right_name == "u1" and (right_parameters[2] %
                                       (2 * sympy.pi)).is_zero:
                right_name = "nop"
            # Simplify the symbolic parameters
            right_parameters = tuple(
                map(sympy.simplify, list(right_parameters)))
        # Replace the data of the first node in the run
        new_params = []
        if right_name == "u1":
            new_params = [right_parameters[2]]
        if right_name == "u2":
            new_params = [right_parameters[1], right_parameters[2]]
        if right_name == "u3":
            new_params = list(right_parameters)

        nx.set_node_attributes(unrolled.multi_graph, 'name',
                               {run[0]: right_name})
        # params is a list of sympy symbols and the str() method
        # will return Python expressions. To get the correct
        # OpenQASM expression, we need to replace "**" with "^".
        nx.set_node_attributes(unrolled.multi_graph, 'params', {
            run[0]:
            tuple(map(lambda x: str(x).replace("**", "^"), new_params))
        })

        # Delete the other nodes in the run
        for node in run[1:]:
            unrolled._remove_op_node(node)
        if right_name == "nop":
            unrolled._remove_op_node(run[0])
    return unrolled
Ejemplo n.º 17
0
def my_swap_mapper(circuit_graph,
                   coupling,
                   speedup=False,
                   initial_layout=None):
    """ TODO: add description"""
    gates = read_gates(circuit_graph)
    qubits = coupling.get_qubits()
    if initial_layout == None:
        # We start with a trivial layout, no significat improvement, especially
        # for large circuits, could be achived by optimizing the initial layout
        initial_layout = {qubit: qubit for qubit in qubits}
    qasm_string = ""
    # Set the depth we are actually going to use. If speedup is true, use
    # a depth one smaller than usually
    used_depth = DEPTH
    if speedup:
        used_depth -= 1
    # This value gives a good compromise between speed and final score
    max_gates = 50 + 10 * len(coupling.get_qubits())

    # Build the initial tree
    node = build_tree(None,
                      gates,
                      coupling,
                      initial_layout,
                      used_depth,
                      width=WIDTH,
                      max_gates=max_gates)
    # Now actually start compiling
    run = True
    while run:
        # if no gates are left, stop ater this iteration
        run = node["remaining_gates"] != []
        # add the swap of the top node to the qasm string
        if node["swap"] != None:
            edge = node["swap"]
            qasm_string += "swap %s[%d],%s[%d]; " % (edge[0][0], edge[0][1],
                                                     edge[1][0], edge[1][1])
        # add all executed gates to the qasm string
        for gate in node["executed_gates"]:
            qasm_string += gate_to_qasm(gate, node["layout"])
        last_layout = node["layout"]
        # Go one step deeper into the tree. For this, choose the child with the
        # best score. This is the child whose score matches the score of the node
        for n in node["children"]:
            if n["score"] == node["score"]:
                node = n
                break
        # append one layer to the tree
        update_tree(node, coupling, width=WIDTH, max_gates=max_gates)

    # complete the qasm string
    swap_decl = "gate swap a,b { cx a,b; cx b,a; cx a,b;}"
    end_str = "barrier "  # end of the qasm code
    for q in coupling.get_qubits():
        end_str += "%s[%d]," % q
    end_str = end_str[:-1] + ";\n"
    # Assume that each qubit q[i] gets measured to c[i]
    for q in circuit_graph.get_qubits():
        end_str += qubit_to_measure_string(q, last_layout, q[1])
    qasm_string = circuit_graph.qasm(
        decls_only=True) + swap_decl + qasm_string + end_str
    # convert qasm to a dag circuit
    basis = "u1,u2,u3,cx,id,swap"
    ast = Qasm(data=qasm_string).parse()
    u = unroll.Unroller(ast, unroll.DAGBackend(basis.split(",")))
    return u.execute()
Ejemplo n.º 18
0
def my_swap_mapper_recursive(circuit_graph, coupling):
    print_mem()
    qasm_str2 = circuit_graph.qasm()
    print_mem()
    gates = circuit_graph.serial_layers()
    print_mem()
    qubits = coupling.get_qubits()
    layout = {qubit: qubit for qubit in qubits}
    #layout_copy = deepcopy(layout)

    end_nodes = []
    count = 0
    while gates[count]["partition"] != []:
        count += 1
    end_nodes = gates[count:]
    gates = gates[:count]
    #gates_copy = deepcopy(gates)

    #qasm_string = ""
    """executed_gates, gates, cnots = execute_free_gates(gates, coupling, layout)
    for gate in executed_gates:
        qasm_string += gate["graph"].qasm(no_decls = True, aliases = layout)

    while len(gates) > 0:
        #print(len(gates))
        score, executions, remaining = get_best_action(gates, coupling, layout, DEPTH, width = WIDTH)
        #print("stop")
        for i in range(1):
            edge = executions[i][0]
            qasm_string += "swap %s[%d],%s[%d]; " % (edge[0][0],
                                                    edge[0][1],
                                                    edge[1][0],
                                                    edge[1][1])
            swaped_layout = deepcopy(layout)
            swaped_layout[reverse_layout_lookup(layout, edge[0])] = edge[1]
            swaped_layout[reverse_layout_lookup(layout, edge[1])] = edge[0]
            layout = swaped_layout

            for gate in executions[i][1]:
                qasm_string += gate["graph"].qasm(no_decls = True, aliases = layout)
                gates.remove(gate)

    swap_decl = "gate swap a,b { cx a,b; cx b,a; cx a,b;}"
    end_nodes_qasm = ""
    for n in end_nodes:
        end_nodes_qasm += n["graph"].qasm(no_decls=True, aliases =layout)
    qasm_string = circuit_graph.qasm(decls_only=True)+swap_decl+qasm_string+end_nodes_qasm

    print(qasm_string)
    print("")"""

    qasm_string = ""
    node = build_tree(None, gates, coupling, layout, DEPTH + 1, width=WIDTH)
    #print("stop")
    run = True
    while run:
        run = node["remaining_gates"] != []
        if node["swap"] != None:
            edge = node["swap"]
            qasm_string += "swap %s[%d],%s[%d]; " % (edge[0][0], edge[0][1],
                                                     edge[1][0], edge[1][1])
        for gate in node["executed_gates"]:
            qasm_string += gate["graph"].qasm(no_decls=True,
                                              aliases=node["layout"])
        last_layout = node["layout"]
        #scores = []
        #for n in node["next_nodes"]:
        #    scores.append(n["score"])
        #print(scores)
        for n in node["next_nodes"]:
            if n["score"] == node["score"]:
                node = n
                break
        #print(node["score"])
        update_tree(node, coupling, width=WIDTH)
        #print("stop")

    swap_decl = "gate swap a,b { cx a,b; cx b,a; cx a,b;}"
    end_nodes_qasm = ""
    for n in end_nodes:
        end_nodes_qasm += n["graph"].qasm(no_decls=True, aliases=last_layout)
    qasm_string = circuit_graph.qasm(
        decls_only=True) + swap_decl + qasm_string + end_nodes_qasm

    #print(qasm_string)
    basis = "u1,u2,u3,cx,id,swap"
    ast = Qasm(data=qasm_string).parse()
    u = unroll.Unroller(ast, unroll.DAGBackend(basis.split(",")))
    #print("Done.")

    return u.execute(), layout