forked from Qiskit/qiskit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Adding qobj converters * Adding circuit_to_dag * Tests * Cleaning up * Adding changes * Adding more * Lint * Update test_circuit_operations.py * Cleaning up
- Loading branch information
1 parent
e8d60bb
commit 6525615
Showing
18 changed files
with
309 additions
and
249 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright 2018, IBM. | ||
# | ||
# This source code is licensed under the Apache License, Version 2.0 found in | ||
# the LICENSE.txt file in the root directory of this source tree. | ||
|
||
# pylint: disable=redefined-builtin | ||
|
||
"""Helper module for simplified Qiskit usage. | ||
The functions in this module provide convenience converters | ||
""" | ||
|
||
from .qobj_to_circuits import qobj_to_circuits | ||
from .circuits_to_qobj import circuits_to_qobj | ||
from .circuit_to_dag import circuit_to_dag | ||
from .dag_to_circuit import dag_to_circuit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright 2018, IBM. | ||
# | ||
# This source code is licensed under the Apache License, Version 2.0 found in | ||
# the LICENSE.txt file in the root directory of this source tree. | ||
|
||
"""Helper function for converting a circuit to a dag""" | ||
|
||
import copy | ||
|
||
from qiskit import _compositegate | ||
from qiskit.dagcircuit._dagcircuit import DAGCircuit | ||
|
||
|
||
def circuit_to_dag(circuit, expand_gates=True): | ||
"""Build a ``DAGCircuit`` object from a ``QuantumCircuit``. | ||
Args: | ||
circuit (QuantumCircuit): the input circuit. | ||
expand_gates (bool): if ``False``, none of the gates are expanded, | ||
i.e. the gates that are defined in the circuit are included in | ||
the DAG basis. | ||
Return: | ||
DAGCircuit: the DAG representing the input circuit. | ||
""" | ||
circuit = copy.deepcopy(circuit) | ||
|
||
dagcircuit = DAGCircuit() | ||
dagcircuit.name = circuit.name | ||
for register in circuit.qregs: | ||
dagcircuit.add_qreg(register) | ||
for register in circuit.cregs: | ||
dagcircuit.add_creg(register) | ||
# Add user gate definitions | ||
for name, data in circuit.definitions.items(): | ||
dagcircuit.add_basis_element(name, data["n_bits"], 0, data["n_args"]) | ||
dagcircuit.add_gate_data(name, data) | ||
# Add instructions | ||
builtins = { | ||
"U": ["U", 1, 0, 3], | ||
"CX": ["CX", 2, 0, 0], | ||
"measure": ["measure", 1, 1, 0], | ||
"reset": ["reset", 1, 0, 0], | ||
"barrier": ["barrier", -1, 0, 0] | ||
} | ||
# Add simulator instructions | ||
simulator_instructions = { | ||
"snapshot": ["snapshot", -1, 0, 1], | ||
"save": ["save", -1, 0, 1], | ||
"load": ["load", -1, 0, 1], | ||
"noise": ["noise", -1, 0, 1] | ||
} | ||
for main_instruction in circuit.data: | ||
# TODO: generate definitions and nodes for CompositeGates, | ||
# for now simply drop their instructions into the DAG | ||
instruction_list = [] | ||
is_composite = isinstance(main_instruction, | ||
_compositegate.CompositeGate) | ||
if is_composite and expand_gates: | ||
instruction_list = main_instruction.instruction_list() | ||
else: | ||
instruction_list.append(main_instruction) | ||
|
||
for instruction in instruction_list: | ||
# Add OpenQASM built-in gates on demand | ||
if instruction.name in builtins: | ||
dagcircuit.add_basis_element(*builtins[instruction.name]) | ||
# Add simulator extension instructions | ||
if instruction.name in simulator_instructions: | ||
dagcircuit.add_basis_element(*simulator_instructions[instruction.name]) | ||
# Get arguments for classical control (if any) | ||
if instruction.control is None: | ||
control = None | ||
else: | ||
control = (instruction.control[0], instruction.control[1]) | ||
|
||
dagcircuit.apply_operation_back(instruction, instruction.qargs, | ||
instruction.cargs, control) | ||
|
||
return dagcircuit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright 2018, IBM. | ||
# | ||
# This source code is licensed under the Apache License, Version 2.0 found in | ||
# the LICENSE.txt file in the root directory of this source tree. | ||
|
||
"""Helper function for converting a list of circuits to a qobj""" | ||
from copy import deepcopy | ||
import uuid | ||
|
||
from qiskit.qobj import Qobj, QobjConfig, QobjExperiment, QobjItem, QobjHeader | ||
from qiskit._quantumcircuit import QuantumCircuit | ||
|
||
|
||
def circuits_to_qobj(circuits, backend_name, config=None, shots=1024, | ||
max_credits=10, qobj_id=None, basis_gates=None, coupling_map=None, | ||
seed=None): | ||
"""Convert a list of circuits into a qobj. | ||
Args: | ||
circuits (list[QuantumCircuits] or QuantumCircuit): circuits 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 {}) | ||
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 | ||
|
||
if isinstance(circuits, QuantumCircuit): | ||
circuits = [circuits] | ||
|
||
for circuit in circuits: | ||
qobj.experiments.append(_circuit_to_experiment(circuit, | ||
config, | ||
basis_gates, | ||
coupling_map)) | ||
|
||
# Update the global `memory_slots` and `n_qubits` values. | ||
qobj.config.memory_slots = max(experiment.config.memory_slots for | ||
experiment in qobj.experiments) | ||
|
||
qobj.config.n_qubits = max(experiment.config.n_qubits for | ||
experiment in qobj.experiments) | ||
|
||
return qobj | ||
|
||
|
||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
# Copyright 2018, IBM. | ||
# | ||
# This source code is licensed under the Apache License, Version 2.0 found in | ||
# the LICENSE.txt file in the root directory of this source tree. | ||
|
||
"""Helper function for converting a dag to a circuit""" | ||
from copy import deepcopy | ||
import random | ||
import string | ||
import networkx as nx | ||
|
||
from qiskit._quantumcircuit import QuantumCircuit | ||
|
||
|
||
def dag_to_circuit(dag): | ||
"""Build a ``QuantumCircuit`` object from a ``DAGCircuit``. | ||
Args: | ||
dag (DAGCircuit): the input dag. | ||
Return: | ||
QuantumCircuit: the circuit representing the input dag. | ||
""" | ||
circuit = QuantumCircuit() | ||
random_name = QuantumCircuit.cls_prefix() + \ | ||
str(''.join(random.choice(string.ascii_lowercase) for i in range(8))) | ||
circuit.name = dag.name or random_name | ||
for qreg in dag.qregs.values(): | ||
circuit.add_register(qreg) | ||
for creg in dag.cregs.values(): | ||
circuit.add_register(creg) | ||
graph = dag.multi_graph | ||
for node in nx.topological_sort(graph): | ||
n = graph.nodes[node] | ||
if n['type'] == 'op': | ||
op = deepcopy(n['op']) | ||
op.qargs = n['qargs'] | ||
op.cargs = n['cargs'] | ||
op.circuit = circuit | ||
if 'condition' in n and n['condition']: | ||
op = op.c_if(*n['condition']) | ||
circuit._attach(op) | ||
|
||
return circuit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.