def setUp(self):
        qasm_filename = self._get_resource_path('qasm/example.qasm')
        qasm_ast = Qasm(filename=qasm_filename).parse()
        qasm_dag = Unroller(qasm_ast, DAGBackend()).execute()
        qasm_json = DagUnroller(qasm_dag,
                                JsonBackend(qasm_dag.basis)).execute()

        qr = QuantumRegister(2, 'q')
        cr = ClassicalRegister(2, 'c')
        qc = QuantumCircuit(qr, cr)
        qc.h(qr[0])
        qc.measure(qr[0], cr[0])
        qc_dag = DAGCircuit.fromQuantumCircuit(qc)
        qc_json = DagUnroller(qc_dag, JsonBackend(qc_dag.basis)).execute()

        # create qobj
        compiled_circuit1 = QobjExperiment.from_dict(qc_json)
        compiled_circuit2 = QobjExperiment.from_dict(qasm_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[1].header.name = 'test_circuit2'
        self.backend = QasmSimulator()
Пример #2
0
    def setUp(self):
        self.seed = 88
        self.qasm_filename = self._get_resource_path('qasm/example.qasm')
        self.qasm_circ = QuantumCircuit.from_qasm_file(self.qasm_filename)
        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
        dag = DAGCircuit.fromQuantumCircuit(self.qc)
        json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute()
        compiled_circuit1 = QobjExperiment.from_dict(json_circuit)

        dag = DAGCircuit.fromQuantumCircuit(self.qasm_circ)
        json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute()
        compiled_circuit2 = QobjExperiment.from_dict(json_circuit)

        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()
Пример #3
0
 def test_from_dag_to_json_with_basis(self):
     ast = qasm.Qasm(
         filename=self._get_resource_path('qasm/example.qasm')).parse()
     dag_circuit = Unroller(ast, DAGBackend(["cx", "u1", "u2",
                                             "u3"])).execute()
     dag_unroller = DagUnroller(dag_circuit,
                                JsonBackend(["cx", "u1", "u2", "u3"]))
     json_circuit = dag_unroller.execute()
     expected_result = \
         {'operations':
             [{'qubits': [5], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793],
               'name': 'u2'},
              {'qubits': [5, 2], 'texparams': [], 'params': [], 'name': 'cx'},
              {'qubits': [2], 'clbits': [2], 'name': 'measure'},
              {'qubits': [4], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793],
               'name': 'u2'},
              {'qubits': [4, 1], 'texparams': [], 'params': [], 'name': 'cx'},
              {'qubits': [1], 'clbits': [1], 'name': 'measure'},
              {'qubits': [3], 'texparams': ['0', '\\pi'], 'params': [0.0, 3.141592653589793],
               'name': 'u2'},
              {'qubits': [3, 0], 'texparams': [], 'params': [], 'name': 'cx'},
              {'qubits': [3, 4, 5], 'name': 'barrier'},
              {'qubits': [5], 'clbits': [5], 'name': 'measure'},
              {'qubits': [4], 'clbits': [4], 'name': 'measure'},
              {'qubits': [3], 'clbits': [3], 'name': 'measure'},
              {'qubits': [0], 'clbits': [0], 'name': 'measure'}],
          'header':
              {'clbit_labels': [['d', 3], ['c', 3]],
               'number_of_qubits': 6,
               'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]],
               'number_of_clbits': 6
               }
          }
     self.assertEqual(json_circuit, expected_result)
Пример #4
0
    def test_dag_to_json(self):
        """Test DagUnroller with JSON backend."""
        ast = qasm.Qasm(filename=self._get_resource_path('qasm/example.qasm')).parse()
        dag_circuit = Unroller(ast, DAGBackend()).execute()
        dag_unroller = DagUnroller(dag_circuit, JsonBackend())
        json_circuit = dag_unroller.execute()
        expected_result = {
            'operations':
                [
                    {'qubits': [5], 'texparams': ['0.5 \\pi', '0', '\\pi'],
                     'name': 'U', 'params': [1.5707963267948966, 0.0, 3.141592653589793]},
                    {'name': 'CX', 'qubits': [5, 2]},
                    {'clbits': [2], 'name': 'measure', 'qubits': [2]},
                    {'qubits': [4], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U',
                     'params': [1.5707963267948966, 0.0, 3.141592653589793]},
                    {'name': 'CX', 'qubits': [4, 1]},
                    {'clbits': [1], 'name': 'measure', 'qubits': [1]},
                    {'qubits': [3], 'texparams': ['0.5 \\pi', '0', '\\pi'], 'name': 'U',
                     'params': [1.5707963267948966, 0.0, 3.141592653589793]},
                    {'name': 'CX', 'qubits': [3, 0]},
                    {'name': 'barrier', 'qubits': [3, 4, 5]},
                    {'clbits': [5], 'name': 'measure', 'qubits': [5]},
                    {'clbits': [4], 'name': 'measure', 'qubits': [4]},
                    {'clbits': [3], 'name': 'measure', 'qubits': [3]},
                    {'clbits': [0], 'name': 'measure', 'qubits': [0]}
                ],
            'header':
                {
                    'memory_slots': 6,
                    'qubit_labels': [['r', 0], ['r', 1], ['r', 2], ['q', 0], ['q', 1], ['q', 2]],
                    'n_qubits': 6, 'clbit_labels': [['d', 3], ['c', 3]]
                }
        }

        self.assertEqual(json_circuit, expected_result)
Пример #5
0
def _dags_2_qobj_parallel(dag, config=None, basis_gates=None,
                          coupling_map=None):
    """Helper function for dags to qobj in parallel (if available).

    Args:
        dag (DAGCircuit): DAG to compile
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (list[str])): basis gates for the experiment
        coupling_map (list): coupling map (perhaps custom) to target in mapping

    Returns:
        Qobj: Qobj to be run on the backends
    """
    json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute()
    # Step 3a: create the Experiment based on json_circuit
    experiment = QobjExperiment.from_dict(json_circuit)
    # Step 3b: populate the Experiment configuration and header
    experiment.header.name = dag.name
    # TODO: place in header or config?
    experiment_config = deepcopy(config or {})
    experiment_config.update({
        'coupling_map': coupling_map,
        'basis_gates': basis_gates,
        'layout': dag.layout,
        'memory_slots': sum(dag.cregs.values()),
        # TODO: `n_qubits` is not part of the qobj spec, but needed for the simulator.
        'n_qubits': sum(dag.qregs.values())})
    experiment.config = QobjItem(**experiment_config)

    # set eval_symbols=True to evaluate each symbolic expression
    # TODO: after transition to qobj, we can drop this
    experiment.header.compiled_circuit_qasm = dag.qasm(
        qeflag=True, eval_symbols=True)
    # Step 3c: add the Experiment to the Qobj
    return experiment
Пример #6
0
    def test_pass_manager_none(self):
        """Test passing the default (None) pass manager to the transpiler.

        It should perform the default qiskit flow:
        unroll, swap_mapper, direction_mapper, cx cancellation, optimize_1q_gates
        and should be equivalent to using wrapper.compile
        """
        q = QuantumRegister(2)
        circ = QuantumCircuit(q)
        circ.h(q[0])
        circ.h(q[0])
        circ.cx(q[0], q[1])
        circ.cx(q[0], q[1])
        circ.cx(q[0], q[1])
        circ.cx(q[0], q[1])

        coupling_map = [[1, 0]]
        basis_gates = 'u1,u2,u3,cx,id'

        dag_circuit = DAGCircuit.fromQuantumCircuit(circ)
        dag_circuit = transpile(dag_circuit, coupling_map=coupling_map,
                                basis_gates=basis_gates, pass_manager=None)
        transpiler_json = DagUnroller(dag_circuit, JsonBackend(dag_circuit.basis)).execute()

        qobj = wrapper.compile(circ, backend='local_qasm_simulator',
                               coupling_map=coupling_map, basis_gates=basis_gates)
        compiler_json = qobj.experiments[0].as_dict()

        # Remove extra Qobj header parameters.
        compiler_json.pop('config')
        compiler_json['header'].pop('name')
        compiler_json['header'].pop('compiled_circuit_qasm')

        self.assertDictEqual(transpiler_json, compiler_json)
Пример #7
0
    def _create_qobj(self, circuits, circuit_config, backend, seed,
                     resources, shots, do_compile):
        # local and remote backends currently need different
        # compilied circuit formats
        formatted_circuits = []
        if do_compile:
            for circuit in circuits:
                formatted_circuits.append(None)
        else:
            if backend in backends.local_backends():
                for circuit in self.circuits:
                    basis = ['u1', 'u2', 'u3', 'cx', 'id']
                    unroller = Unroller
                    # TODO: No instanceof here! Refactor this class
                    if isinstance(circuit, DAGCircuit):
                        unroller = DagUnroller
                    elif isinstance(circuit, QuantumCircuit):
                        # TODO: We should remove this code path (it's redundant and slow)
                        circuit = Qasm(data=circuit.qasm()).parse()
                    unroller_instance = unroller(circuit, JsonBackend(basis))
                    compiled_circuit = unroller_instance.execute()
                    formatted_circuits.append(compiled_circuit)

            else:
                for circuit in self.circuits:
                    formatted_circuits.append(circuit.qasm(qeflag=True))

        # create circuit component of qobj
        circuit_records = []
        if circuit_config is None:
            config = {'coupling_map': None,
                      'basis_gates': 'u1,u2,u3,cx,id',
                      'layout': None,
                      'seed': seed}
            circuit_config = [config] * len(self.circuits)

        for circuit, fcircuit, name, config in zip(self.circuits,
                                                   formatted_circuits,
                                                   self.names,
                                                   circuit_config):
            record = {
                'name': name,
                'compiled_circuit': None if do_compile else fcircuit,
                'compiled_circuit_qasm': None if do_compile else fcircuit,
                'circuit': circuit,
                'config': config
            }
            circuit_records.append(record)

        return {'id': self._generate_job_id(length=10),
                'config': {
                    'max_credits': resources['max_credits'],
                    'shots': shots,
                    'backend': backend
                },
                'circuits': circuit_records}
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_circuit (QuantumCircuit): 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:
        json: the json version of the dag
    """
    return DagUnroller(dag_circuit, JsonBackend(basis_gates)).execute()
Пример #9
0
    def setUp(self):
        self.seed = 88
        self.backend = QasmSimulatorPy()
        backend_basis = self.backend.configuration().basis_gates
        qasm_filename = self._get_resource_path('qasm/example.qasm')
        qasm_ast = Qasm(filename=qasm_filename).parse()
        qasm_dag = Unroller(qasm_ast, DAGBackend()).execute()
        qasm_dag = DagUnroller(qasm_dag, DAGBackend(backend_basis)).expand_gates()
        qasm_json = DagUnroller(qasm_dag, JsonBackend(qasm_dag.basis)).execute()
        compiled_circuit = QobjExperiment.from_dict(qasm_json)
        compiled_circuit.header.name = 'test'

        self.qobj = Qobj(
            qobj_id='test_sim_single_shot',
            config=QobjConfig(
                shots=1024, memory_slots=6,
                max_credits=3, seed=self.seed
            ),
            experiments=[compiled_circuit],
            header=QobjHeader(backend_name='qasm_simulator_py')
        )
Пример #10
0
def _circuit_to_experiment(circuit,
                           config=None,
                           basis_gates=None,
                           coupling_map=None):
    """Helper function for dags to qobj in parallel (if available).

    Args:
        circuit (QuantumCircuit): QuantumCircuit to convert into qobj experiment
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (list[str])): basis gates for the experiment
        coupling_map (list): coupling map (perhaps custom) to target in mapping

    Returns:
        Qobj: Qobj to be run on the backends
    """
    # pylint: disable=unused-argument
    #  TODO: if arguments are really unused, consider changing the signature
    # TODO: removed the DAG from this function
    from qiskit.converters import circuit_to_dag
    from qiskit.unroll import DagUnroller, JsonBackend
    dag = circuit_to_dag(circuit)
    json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute()
    # Step 3a: create the Experiment based on json_circuit
    experiment = QobjExperiment.from_dict(json_circuit)
    # Step 3b: populate the Experiment configuration and header
    experiment.header.name = circuit.name
    experiment_config = deepcopy(config or {})
    experiment_config.update({
        'memory_slots':
        sum([creg.size for creg in dag.cregs.values()]),
        'n_qubits':
        sum([qreg.size for qreg in dag.qregs.values()])
    })
    experiment.config = QobjItem(**experiment_config)

    # set eval_symbols=True to evaluate each symbolic expression
    # TODO: after transition to qobj, we can drop this
    experiment.header.compiled_circuit_qasm = circuit.qasm()
    # Step 3c: add the Experiment to the Qobj
    return experiment
Пример #11
0
def transpile(dag_circuit,
              basis_gates='u1,u2,u3,cx,id',
              coupling_map=None,
              initial_layout=None,
              get_layout=False,
              format='dag',
              seed=None,
              pass_manager=None):
    """Transform a dag circuit into another dag circuit (transpile), through
    consecutive passes on the dag.

    Args:
        dag_circuit (DAGCircuit): dag circuit to transform via transpilation
        basis_gates (str): a comma seperated string for the target basis gates
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (dict): A mapping of qubit to qubit::

                              {
                                ("q", start(int)): ("q", final(int)),
                                ...
                              }
                              eg.
                              {
                                ("q", 0): ("q", 0),
                                ("q", 1): ("q", 1),
                                ("q", 2): ("q", 2),
                                ("q", 3): ("q", 3)
                              }
        get_layout (bool): flag for returning the layout
        format (str): The target format of the compilation:
            {'dag', 'json', 'qasm'}
        seed (int): random seed for simulators
        pass_manager (PassManager): pass manager instance for the tranpilation process
            If None, a default set of passes are run.
            Otherwise, the passes defined in it will run.
            If contains no passes in it, no dag transformations occur.

    Returns:
        object: If get_layout == False, the compiled circuit in the specified
            format. If get_layout == True, a tuple is returned, with the
            second element being the layout.

    Raises:
        TranspilerError: if the format is not valid.
    """
    final_layout = None

    if pass_manager:
        # run the passes specified by the pass manager
        for pass_ in pass_manager.passes():
            pass_.run(dag_circuit)
    else:
        # default set of passes
        # TODO: move each step here to a pass, and use a default passmanager below
        basis = basis_gates.split(',') if basis_gates else []
        dag_unroller = DagUnroller(dag_circuit, DAGBackend(basis))
        dag_circuit = dag_unroller.expand_gates()
        # if a coupling map is given compile to the map
        if coupling_map:
            logger.info("pre-mapping properties: %s",
                        dag_circuit.property_summary())
            # Insert swap gates
            coupling = Coupling(coupling_list2dict(coupling_map))
            logger.info("initial layout: %s", initial_layout)
            dag_circuit, final_layout = swap_mapper(dag_circuit,
                                                    coupling,
                                                    initial_layout,
                                                    trials=20,
                                                    seed=seed)
            logger.info("final layout: %s", final_layout)
            # Expand swaps
            dag_unroller = DagUnroller(dag_circuit, DAGBackend(basis))
            dag_circuit = dag_unroller.expand_gates()
            # Change cx directions
            dag_circuit = direction_mapper(dag_circuit, coupling)
            # Simplify cx gates
            cx_cancellation(dag_circuit)
            # Simplify single qubit gates
            dag_circuit = optimize_1q_gates(dag_circuit)
            logger.info("post-mapping properties: %s",
                        dag_circuit.property_summary())

    # choose output format
    # TODO: do we need all of these formats, or just the dag?
    if format == 'dag':
        compiled_circuit = dag_circuit
    elif format == 'json':
        # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list
        dag_unroller = DagUnroller(dag_circuit, JsonBackend(dag_circuit.basis))
        compiled_circuit = dag_unroller.execute()
    elif format == 'qasm':
        compiled_circuit = dag_circuit.qasm()
    else:
        raise TranspilerError('unrecognized circuit format')

    if get_layout:
        return compiled_circuit, final_layout
    return compiled_circuit
Пример #12
0
def _compile_single_circuit(circuit,
                            backend,
                            config=None,
                            basis_gates=None,
                            coupling_map=None,
                            initial_layout=None,
                            seed=None,
                            pass_manager=None):
    """Compile a single circuit into a QobjExperiment.

    Args:
        circuit (QuantumCircuit): circuit to compile
        backend (BaseBackend): a backend to compile for
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (str): comma-separated basis gate set to compile to
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        seed (int): random seed for simulators
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        QobjExperiment: the QobjExperiment to be run on the backends
    """
    # TODO: A better solution is to have options to enable/disable optimizations
    num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values()))
    if num_qubits == 1 or coupling_map == "all-to-all":
        coupling_map = None
    # Step 2a: circuit -> dag
    dag_circuit = DAGCircuit.fromQuantumCircuit(circuit)

    # TODO: move this inside the mapper pass
    # pick a good initial layout if coupling_map is not already satisfied
    # otherwise keep it as q[i]->q[i]
    if (initial_layout is None and not backend.configuration['simulator']
            and not _matches_coupling_map(circuit.data, coupling_map)):
        initial_layout = _pick_best_layout(backend, num_qubits,
                                           circuit.get_qregs())

    # Step 2b: transpile (dag -> dag)
    dag_circuit, final_layout = transpile(dag_circuit,
                                          basis_gates=basis_gates,
                                          coupling_map=coupling_map,
                                          initial_layout=initial_layout,
                                          get_layout=True,
                                          seed=seed,
                                          pass_manager=pass_manager)

    # Step 2c: dag -> json
    # the compiled circuit to be run saved as a dag
    # we assume that transpile() has already expanded gates
    # to the target basis, so we just need to generate json
    list_layout = [[k, v]
                   for k, v in final_layout.items()] if final_layout else None

    json_circuit = DagUnroller(dag_circuit,
                               JsonBackend(dag_circuit.basis)).execute()

    # Step 3a: create the Experiment based on json_circuit
    experiment = QobjExperiment.from_dict(json_circuit)
    # Step 3b: populate the Experiment configuration and header
    experiment.header.name = circuit.name
    # TODO: place in header or config?
    experiment_config = deepcopy(config or {})
    experiment_config.update({
        'coupling_map':
        coupling_map,
        'basis_gates':
        basis_gates,
        'layout':
        list_layout,
        'memory_slots':
        sum(register.size for register in circuit.get_cregs().values())
    })
    experiment.config = QobjItem(**experiment_config)

    # set eval_symbols=True to evaluate each symbolic expression
    # TODO after transition to qobj, we can drop this
    experiment.header.compiled_circuit_qasm = dag_circuit.qasm(
        qeflag=True, eval_symbols=True)

    return experiment
Пример #13
0
def compile(quantum_circuit, basis_gates='u1,u2,u3,cx,id', coupling_map=None,
            initial_layout=None, get_layout=False, format='dag'):
    """Compile the circuit.

    This builds the internal "to execute" list which is list of quantum
    circuits to run on different backends.

    Args:
        quantum_circuit (QuantumCircuit): circuit to compile
        basis_gates (str): a comma seperated string and are the base gates,
                           which by default are: u1,u2,u3,cx,id
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (dict): A mapping of qubit to qubit::

                              {
                                ("q", start(int)): ("q", final(int)),
                                ...
                              }
                              eg.
                              {
                                ("q", 0): ("q", 0),
                                ("q", 1): ("q", 1),
                                ("q", 2): ("q", 2),
                                ("q", 3): ("q", 3)
                              }
        get_layout (bool): flag for returning the layout.
        format (str): The target format of the compilation:
            {'dag', 'json', 'qasm'}

    Returns:
        object: If get_layout == False, the compiled circuit in the specified
            format. If get_layout == True, a tuple is returned, with the
            second element being the layout.

    Raises:
        QISKitCompilerError: if the format is not valid.
    """
    compiled_dag_circuit = DAGCircuit.fromQuantumCircuit(quantum_circuit)
    basis = basis_gates.split(',') if basis_gates else []

    dag_unroller = DagUnroller(compiled_dag_circuit, DAGBackend(basis))
    compiled_dag_circuit = dag_unroller.expand_gates()
    final_layout = None
    # if a coupling map is given compile to the map
    if coupling_map:
        logger.info("pre-mapping properties: %s",
                    compiled_dag_circuit.property_summary())
        # Insert swap gates
        coupling = mapper.Coupling(mapper.coupling_list2dict(coupling_map))
        logger.info("initial layout: %s", initial_layout)
        compiled_dag_circuit, final_layout = mapper.swap_mapper(
            compiled_dag_circuit, coupling, initial_layout, trials=20, seed=13)
        logger.info("final layout: %s", final_layout)
        # Expand swaps
        dag_unroller = DagUnroller(compiled_dag_circuit, DAGBackend(basis))
        compiled_dag_circuit = dag_unroller.expand_gates()
        # Change cx directions
        compiled_dag_circuit = mapper.direction_mapper(compiled_dag_circuit, coupling)
        # Simplify cx gates
        mapper.cx_cancellation(compiled_dag_circuit)
        # Simplify single qubit gates
        compiled_dag_circuit = mapper.optimize_1q_gates(compiled_dag_circuit)
        logger.info("post-mapping properties: %s",
                    compiled_dag_circuit.property_summary())
    # choose output format
    if format == 'dag':
        compiled_circuit = compiled_dag_circuit
    elif format == 'json':
        dag_unroller = DagUnroller(compiled_dag_circuit,
                                   JsonBackend(list(compiled_dag_circuit.basis.keys())))
        compiled_circuit = dag_unroller.execute()
    elif format == 'qasm':
        compiled_circuit = compiled_dag_circuit.qasm()
    else:
        raise QISKitCompilerError('unrecognized circuit format')

    if get_layout:
        return compiled_circuit, final_layout
    return compiled_circuit
Пример #14
0
def compile(circuits,
            backend,
            config=None,
            basis_gates=None,
            coupling_map=None,
            initial_layout=None,
            shots=1024,
            max_credits=10,
            seed=None,
            qobj_id=None,
            hpc=None,
            pass_manager=None):
    """Compile a list of circuits into a qobj.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to compile
        backend (BaseBackend): a backend to compile for
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (str): comma-separated basis gate set to compile to
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        shots (int): number of repetitions of each circuit, for sampling
        max_credits (int): maximum credits to use
        seed (int): random seed for simulators
        qobj_id (int): identifier for the generated qobj
        hpc (dict): HPC simulator parameters
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        obj: the qobj to be run on the backends

    Raises:
        TranspilerError: in case of bad compile options, e.g. the hpc options.
    """
    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    backend_conf = backend.configuration
    backend_name = backend_conf['name']

    qobj = {}

    # step 1: populate the qobj-level `id`
    qobj_id = qobj_id or str(uuid.uuid4())
    qobj['id'] = qobj_id

    # step 2: populate the qobj-level `config`
    qobj['config'] = {
        'max_credits': max_credits,
        'shots': shots,
        'backend_name': backend_name
    }

    if hpc is not None and \
            not all(key in hpc for key in ('multi_shot_optimization', 'omp_num_threads')):
        raise TranspilerError('Unknown HPC parameter format!')

    # step 3: populate the `circuits` in qobj, after compiling each circuit
    qobj['circuits'] = []
    if not basis_gates:
        basis_gates = backend_conf['basis_gates']
    if not coupling_map:
        coupling_map = backend_conf['coupling_map']

    for circuit in circuits:
        job = {}

        # step 1: populate the circuit-level `name`
        job["name"] = circuit.name

        # step 2: populate the circuit-level `config`
        if config is None:
            config = {}
        job["config"] = copy.deepcopy(config)
        # TODO: A better solution is to have options to enable/disable optimizations
        num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values()))
        if num_qubits == 1 or coupling_map == "all-to-all":
            coupling_map = None
        job["config"]["coupling_map"] = coupling_map
        job["config"]["basis_gates"] = basis_gates
        job["config"]["seed"] = seed

        # step 3: populate the circuit `instructions` after compilation
        # step 3a: circuit -> dag
        dag_circuit = DAGCircuit.fromQuantumCircuit(circuit)

        # TODO: move this inside the mapper pass
        # pick a good initial layout if coupling_map is not already satisfied
        # otherwise keep it as q[i]->q[i]
        if (initial_layout is None and not backend_conf['simulator']
                and not _matches_coupling_map(circuit.data, coupling_map)):
            initial_layout = _pick_best_layout(backend, num_qubits,
                                               circuit.get_qregs())

        # step 3b: transpile (dag -> dag)
        dag_circuit, final_layout = transpile(dag_circuit,
                                              basis_gates=basis_gates,
                                              coupling_map=coupling_map,
                                              initial_layout=initial_layout,
                                              get_layout=True,
                                              seed=seed,
                                              pass_manager=pass_manager)

        # step 3c: dag -> json
        # TODO: populate the Qobj object when Qobj class exists
        # the compiled circuit to be run saved as a dag
        # we assume that transpile() has already expanded gates
        # to the target basis, so we just need to generate json
        list_layout = [[k, v] for k, v in final_layout.items()
                       ] if final_layout else None
        job["config"]["layout"] = list_layout
        json_circuit = DagUnroller(dag_circuit,
                                   JsonBackend(dag_circuit.basis)).execute()
        job["compiled_circuit"] = json_circuit

        # set eval_symbols=True to evaluate each symbolic expression
        # TODO after transition to qobj, we can drop this
        job["compiled_circuit_qasm"] = dag_circuit.qasm(qeflag=True,
                                                        eval_symbols=True)

        # add job to the qobj
        qobj["circuits"].append(job)

    return qobj
Пример #15
0
def compile(circuits,
            backend,
            config=None,
            basis_gates=None,
            coupling_map=None,
            initial_layout=None,
            shots=1024,
            max_credits=10,
            seed=None,
            qobj_id=None,
            hpc=None,
            pass_manager=None):
    """Compile a list of circuits into a qobj.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to compile
        backend (BaseBackend): a backend to compile for
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (str): comma-separated basis gate set to compile to
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        shots (int): number of repetitions of each circuit, for sampling
        max_credits (int): maximum credits to use
        seed (int): random seed for simulators
        qobj_id (int): identifier for the generated qobj
        hpc (dict): HPC simulator parameters
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        Qobj: the Qobj to be run on the backends

    Raises:
        TranspilerError: in case of bad compile options, e.g. the hpc options.
    """
    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    backend_conf = backend.configuration
    backend_name = backend_conf['name']

    # Step 1: create the Qobj, with empty experiments.
    # Copy the configuration: the values in `config` have prefern
    qobj_config = deepcopy(config or {})
    # TODO: "register_slots" is required by the qobj schema in the top-level
    # qobj.config. In this implementation, is overridden by the individual
    # experiment.config entries (hence the 0 should never be used).
    qobj_config.update({
        'shots': shots,
        'max_credits': max_credits,
        'register_slots': 0
    })

    qobj = Qobj(id=qobj_id or str(uuid.uuid4()),
                config=QobjConfig(**qobj_config),
                experiments=[],
                header=QobjHeader(backend_name=backend_name))
    if seed:
        qobj.config.seed = seed

    # Check for valid parameters for the experiments.
    if hpc is not None and \
            not all(key in hpc for key in ('multi_shot_optimization', 'omp_num_threads')):
        raise TranspilerError('Unknown HPC parameter format!')
    basis_gates = basis_gates or backend_conf['basis_gates']
    coupling_map = coupling_map or backend_conf['coupling_map']

    # Step 2 and 3: transpile and populate the circuits
    for circuit in circuits:
        # TODO: A better solution is to have options to enable/disable optimizations
        num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values()))
        if num_qubits == 1 or coupling_map == "all-to-all":
            coupling_map = None
        # Step 2a: circuit -> dag
        dag_circuit = DAGCircuit.fromQuantumCircuit(circuit)

        # TODO: move this inside the mapper pass
        # pick a good initial layout if coupling_map is not already satisfied
        # otherwise keep it as q[i]->q[i]
        if (initial_layout is None and not backend_conf['simulator']
                and not _matches_coupling_map(circuit.data, coupling_map)):
            initial_layout = _pick_best_layout(backend, num_qubits,
                                               circuit.get_qregs())

        # Step 2b: transpile (dag -> dag)
        dag_circuit, final_layout = transpile(dag_circuit,
                                              basis_gates=basis_gates,
                                              coupling_map=coupling_map,
                                              initial_layout=initial_layout,
                                              get_layout=True,
                                              seed=seed,
                                              pass_manager=pass_manager)

        # Step 2c: dag -> json
        # the compiled circuit to be run saved as a dag
        # we assume that transpile() has already expanded gates
        # to the target basis, so we just need to generate json
        list_layout = [[k, v] for k, v in final_layout.items()
                       ] if final_layout else None

        json_circuit = DagUnroller(dag_circuit,
                                   JsonBackend(dag_circuit.basis)).execute()

        # Step 3a: create the Experiment based on json_circuit
        experiment = QobjExperiment.from_dict(json_circuit)
        # Step 3b: populate the Experiment configuration and header
        experiment.header.name = circuit.name
        # TODO: place in header or config?
        experiment_config = deepcopy(config or {})
        experiment_config.update({
            'coupling_map':
            coupling_map,
            'basis_gates':
            basis_gates,
            'layout':
            list_layout,
            'register_slots':
            sum(register.size for register in circuit.get_cregs().values())
        })
        experiment.config = QobjItem(**experiment_config)

        # set eval_symbols=True to evaluate each symbolic expression
        # TODO after transition to qobj, we can drop this
        experiment.header.compiled_circuit_qasm = dag_circuit.qasm(
            qeflag=True, eval_symbols=True)

        # Step 3c: add the Experiment to the Qobj
        qobj.experiments.append(experiment)

    return qobj
Пример #16
0
def transpile(dag,
              basis_gates='u1,u2,u3,cx,id',
              coupling_map=None,
              initial_layout=None,
              get_layout=False,
              format='dag',
              seed=None,
              pass_manager=None):
    """Transform a dag circuit into another dag circuit (transpile), through
    consecutive passes on the dag.

    Args:
        dag (DAGCircuit): dag circuit to transform via transpilation
        basis_gates (str): a comma separated string for the target basis gates
        coupling_map (list): A graph of coupling::

            [
             [control0(int), target0(int)],
             [control1(int), target1(int)],
            ]

            eg. [[0, 2], [1, 2], [1, 3], [3, 4]}

        initial_layout (dict): A mapping of qubit to qubit::

                              {
                                ("q", start(int)): ("q", final(int)),
                                ...
                              }
                              eg.
                              {
                                ("q", 0): ("q", 0),
                                ("q", 1): ("q", 1),
                                ("q", 2): ("q", 2),
                                ("q", 3): ("q", 3)
                              }
        get_layout (bool): flag for returning the final layout after mapping
        format (str): The target format of the compilation:
            {'dag', 'json', 'qasm'}
        seed (int): random seed for the swap mapper
        pass_manager (PassManager): pass manager instance for the transpilation process
            If None, a default set of passes are run.
            Otherwise, the passes defined in it will run.
            If contains no passes in it, no dag transformations occur.

    Returns:
        DAGCircuit: transformed dag
        DAGCircuit, dict: transformed dag along with the final layout on backend qubits

    Raises:
        TranspilerError: if the format is not valid.
    """
    # TODO: `basis_gates` will be removed after we have the unroller pass.
    # TODO: `coupling_map`, `initial_layout`, `get_layout`, `seed` removed after mapper pass.

    # TODO: move this to the mapper pass
    num_qubits = sum(dag.qregs.values())
    if num_qubits == 1 or coupling_map == "all-to-all":
        coupling_map = None

    final_layout = None

    if pass_manager:
        # run the passes specified by the pass manager
        # TODO return the property set too. See #1086
        dag = pass_manager.run_passes(dag)
    else:
        # default set of passes
        # TODO: move each step here to a pass, and use a default passmanager below
        basis = basis_gates.split(',') if basis_gates else []
        dag_unroller = DagUnroller(dag, DAGBackend(basis))
        dag = dag_unroller.expand_gates()
        # if a coupling map is given compile to the map
        if coupling_map:
            logger.info("pre-mapping properties: %s", dag.property_summary())
            # Insert swap gates
            coupling = Coupling(coupling_list2dict(coupling_map))
            removed_meas = remove_last_measurements(dag)
            logger.info("measurements moved: %s", removed_meas)
            logger.info("initial layout: %s", initial_layout)
            dag, final_layout, last_layout = swap_mapper(dag,
                                                         coupling,
                                                         initial_layout,
                                                         trials=20,
                                                         seed=seed)
            logger.info("final layout: %s", final_layout)
            # Expand swaps
            dag_unroller = DagUnroller(dag, DAGBackend(basis))
            dag = dag_unroller.expand_gates()
            # Change cx directions
            dag = direction_mapper(dag, coupling)
            # Simplify cx gates
            cx_cancellation(dag)
            # Simplify single qubit gates
            dag = optimize_1q_gates(dag)
            return_last_measurements(dag, removed_meas, last_layout)
            logger.info("post-mapping properties: %s", dag.property_summary())

    # choose output format
    # TODO: do we need all of these formats, or just the dag?
    if format == 'dag':
        compiled_circuit = dag
    elif format == 'json':
        # FIXME: JsonBackend is wrongly taking an ordered dict as basis, not list
        dag_unroller = DagUnroller(dag, JsonBackend(dag.basis))
        compiled_circuit = dag_unroller.execute()
    elif format == 'qasm':
        compiled_circuit = dag.qasm()
    else:
        raise TranspilerError('unrecognized circuit format')

    if get_layout:
        return compiled_circuit, final_layout
    return compiled_circuit
Пример #17
0
def _dags_2_qobj(dags,
                 backend_name,
                 config=None,
                 shots=None,
                 max_credits=None,
                 qobj_id=None,
                 basis_gates=None,
                 coupling_map=None,
                 seed=None):
    """Convert a list of dags into a qobj.

    Args:
        dags (list[DAGCircuit]): dags to compile
        backend_name (str): name of runner backend
        config (dict): dictionary of parameters (e.g. noise) used by runner
        shots (int): number of repetitions of each circuit, for sampling
        max_credits (int): maximum credits to use
        qobj_id (int): identifier for the generated qobj
        basis_gates (list[str])): basis gates for the experiment
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        seed (int): random seed for simulators

    Returns:
        Qobj: the Qobj to be run on the backends
    """
    # TODO: the following will be removed from qobj and thus removed here:
    # `basis_gates`, `coupling_map`

    # Step 1: create the Qobj, with empty experiments.
    # Copy the configuration: the values in `config` have preference
    qobj_config = deepcopy(config or {})
    # TODO: "memory_slots" is required by the qobj schema in the top-level
    # qobj.config, and is user-defined. At the moment is set to the maximum
    # number of *register* slots for the circuits, in order to have `measure`
    # behave properly until the transition is over; and each circuit stores
    # its memory_slots in its configuration.
    qobj_config.update({
        'shots': shots,
        'max_credits': max_credits,
        'memory_slots': 0
    })

    qobj = Qobj(qobj_id=qobj_id or str(uuid.uuid4()),
                config=QobjConfig(**qobj_config),
                experiments=[],
                header=QobjHeader(backend_name=backend_name))
    if seed:
        qobj.config.seed = seed

    for dag in dags:
        json_circuit = DagUnroller(dag, JsonBackend(dag.basis)).execute()
        # Step 3a: create the Experiment based on json_circuit
        experiment = QobjExperiment.from_dict(json_circuit)
        # Step 3b: populate the Experiment configuration and header
        experiment.header.name = dag.name
        # TODO: place in header or config?
        experiment_config = deepcopy(config or {})
        experiment_config.update({
            'coupling_map': coupling_map,
            'basis_gates': basis_gates,
            'layout': dag.layout,
            'memory_slots': sum(dag.cregs.values()),
            # TODO: `n_qubits` is not part of the qobj spec, but needed for the simulator.
            'n_qubits': sum(dag.qregs.values())
        })
        experiment.config = QobjItem(**experiment_config)

        # set eval_symbols=True to evaluate each symbolic expression
        # TODO: after transition to qobj, we can drop this
        experiment.header.compiled_circuit_qasm = dag.qasm(qeflag=True,
                                                           eval_symbols=True)
        # Step 3c: add the Experiment to the Qobj
        qobj.experiments.append(experiment)

    # Update the `memory_slots` value.
    # TODO: remove when `memory_slots` can be provided by the user.
    qobj.config.memory_slots = max(experiment.config.memory_slots
                                   for experiment in qobj.experiments)

    # Update the `n_qubits` global value.
    # TODO: num_qubits is not part of the qobj specification, but needed
    # for the simulator.
    qobj.config.n_qubits = max(experiment.config.n_qubits
                               for experiment in qobj.experiments)

    return qobj
Пример #18
0
def compile(circuits,
            backend,
            config=None,
            basis_gates=None,
            coupling_map=None,
            initial_layout=None,
            shots=1024,
            max_credits=10,
            seed=None,
            qobj_id=None,
            hpc=None,
            pass_manager=None):
    """Compile a list of circuits into a qobj.

    Args:
        circuits (QuantumCircuit or list[QuantumCircuit]): circuits to compile
        backend (BaseBackend): a backend to compile for
        config (dict): dictionary of parameters (e.g. noise) used by runner
        basis_gates (str): comma-separated basis gate set to compile to
        coupling_map (list): coupling map (perhaps custom) to target in mapping
        initial_layout (list): initial layout of qubits in mapping
        shots (int): number of repetitions of each circuit, for sampling
        max_credits (int): maximum credits to use
        seed (int): random seed for simulators
        qobj_id (int): identifier for the generated qobj
        hpc (dict): HPC simulator parameters
        pass_manager (PassManager): a pass_manager for the transpiler stage

    Returns:
        Qobj: the Qobj to be run on the backends

    Raises:
        TranspilerError: in case of bad compile options, e.g. the hpc options.
    """
    if isinstance(circuits, QuantumCircuit):
        circuits = [circuits]

    backend_conf = backend.configuration
    backend_name = backend_conf['name']

    # Step 1: create the Qobj, with empty circuits
    qobj = Qobj(id=qobj_id or str(uuid.uuid4()),
                config=QobjConfig(max_credits=max_credits,
                                  shots=shots,
                                  backend_name=backend_name),
                circuits=[])

    # Check for valid parameters for the experiments.
    if hpc is not None and \
            not all(key in hpc for key in ('multi_shot_optimization', 'omp_num_threads')):
        raise TranspilerError('Unknown HPC parameter format!')
    basis_gates = basis_gates or backend_conf['basis_gates']
    coupling_map = coupling_map or backend_conf['coupling_map']

    for circuit in circuits:
        # Step 1: create the experiment configuration.
        config = config or {}
        circuit_config = copy.deepcopy(config)

        # TODO: A better solution is to have options to enable/disable optimizations
        num_qubits = sum((len(qreg) for qreg in circuit.get_qregs().values()))
        if num_qubits == 1 or coupling_map == "all-to-all":
            coupling_map = None
        circuit_config["coupling_map"] = coupling_map
        circuit_config["basis_gates"] = basis_gates
        circuit_config["seed"] = seed
        circuit_config["layout"] = None  # set during step 3.

        # Step 2: create the QobjExperiment, with empty compiled circuits.
        experiment = QobjExperiment(
            name=circuit.name,
            config=QobjExperimentConfig(**circuit_config),
            compiled_circuit=None,
            compiled_circuit_qasm=None)

        # Step 3: populate the circuit `instructions` after compilation
        # Step 3a: circuit -> dag
        dag_circuit = DAGCircuit.fromQuantumCircuit(circuit)

        # TODO: move this inside the mapper pass
        # pick a good initial layout if coupling_map is not already satisfied
        # otherwise keep it as q[i]->q[i]
        if (initial_layout is None and not backend_conf['simulator']
                and not _matches_coupling_map(circuit.data, coupling_map)):
            initial_layout = _pick_best_layout(backend, num_qubits,
                                               circuit.get_qregs())

        # Step 3b: transpile (dag -> dag)
        dag_circuit, final_layout = transpile(dag_circuit,
                                              basis_gates=basis_gates,
                                              coupling_map=coupling_map,
                                              initial_layout=initial_layout,
                                              get_layout=True,
                                              seed=seed,
                                              pass_manager=pass_manager)

        # Step 3c: dag -> json
        # the compiled circuit to be run saved as a dag
        # we assume that transpile() has already expanded gates
        # to the target basis, so we just need to generate json
        list_layout = [[k, v] for k, v in final_layout.items()
                       ] if final_layout else None
        experiment.config.layout = list_layout
        json_circuit = DagUnroller(dag_circuit,
                                   JsonBackend(dag_circuit.basis)).execute()
        experiment.compiled_circuit = QobjCompiledCircuit.from_dict(
            json_circuit)

        # set eval_symbols=True to evaluate each symbolic expression
        # TODO after transition to qobj, we can drop this
        experiment.compiled_circuit_qasm = dag_circuit.qasm(qeflag=True,
                                                            eval_symbols=True)

        # add job to the qobj
        qobj.circuits.append(experiment)

    return qobj