Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit a3076a50524a72f1bc91cb633ec5c67a765ef937
Merge: 06dfe40 b7e6329
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Wed Oct 5 09:02:28 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit 06dfe40
Author: ewinston <ewinston@us.ibm.com>
Date:   Tue Oct 4 23:34:42 2022 -0400

    Update qiskit/transpiler/passes/routing/stochastic_swap.py

    Co-authored-by: Jake Lishman <jake@binhbar.com>

commit 1487b80
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 23:33:34 2022 -0400

    simplify function and naming of control flow layer transpilation
    function

commit 5477c50
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 21:44:18 2022 -0400

    replace "maxind" with "deepest_index"

commit 02e704f
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 21:40:06 2022 -0400

    simplify determining idle qubits

commit 753a637
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 20:39:11 2022 -0400

    fix layer bug

    this fixes a bug where gates were dropped if they shared a layer with a
    control flow op.

commit 4dd68a9
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 11:48:01 2022 -0400

    remove _idle_wires function

commit d74b6ee
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 11:40:22 2022 -0400

    remove utils function for getting qubit order

commit 56029b1
Merge: 9d16884 53e215c
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 09:30:58 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit 9d16884
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Oct 4 03:00:22 2022 -0400

    make sure stochastic swap child instances get new seeds

commit dc5b23c
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 30 04:39:29 2022 -0400

    linting. fix merge error.

commit 302320d
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 30 04:32:39 2022 -0400

    merged main and renabled checkmap tests

commit 8ec9259
Merge: cb32908 3c9d8d5
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 30 04:14:53 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit cb32908
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 30 02:28:01 2022 -0400

    updated to allow cf blocks with different registers than containing
    circuit.

commit fb0496e
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 29 15:38:28 2022 -0400

    fix while loop test

commit 463a466
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Wed Sep 28 14:26:14 2022 -0400

    simplify dadnode handling of swap and cz

commit 4f1af5b
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 8 13:16:15 2022 -0400

    remove merge artifact

commit 3133949
Merge: 3c85677 53231fb
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 8 13:15:18 2022 -0400

    Merge branch 'test_merge' into controlflow/stochastic_swap

commit 53231fb
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 8 12:24:55 2022 -0400

    remove redefiing coupling map in control flow context

commit 0161913
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Wed Jul 20 09:56:28 2022 -0400

    add controlflow handling to stochastic swap pass

commit 072c550
Author: Junye Huang <h.jun.ye@gmail.com>
Date:   Thu Sep 8 14:22:12 2022 +0200

    Add common usage explanations and code examples to qiskit.visualization module API page (Qiskit#8569)

    * add draft

    * revert unintended changes

    * revert unintended changes

    * add example usage

    * add common keyword arguments section

    * add sections to apis

    * fix internal links

    * remove generated hist figure

    * lint

    * use matplotlib instead of Matplotlib in class reference

    * change to a valid denisty matrix in examples

    * import from qiskit.visualization instead of qiskit.tools.visualization

    * remove unintended changes

    * split counts and state visualizations

    * remove overview and prerequisite headings

    * move common kwargs sections to the top level

    * remove link to api table

    * remove apis headings

    * remove extra blank lines

    * remove extra blank lines

    * minor twig on the counts to make them 1000 shots in total

    * add an intro sentence before the example for common kwargs

    Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit 64bbeff
Author: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>
Date:   Thu Sep 8 19:38:53 2022 +0900

    Add an error check for Sampler (Qiskit#8678)

    * add an error check for sampler

    * update

    * Update qiskit/primitives/base_sampler.py

    Co-authored-by: Julien Gacon <gaconju@gmail.com>

    * remove a duplicate check

    * update an error messgage

    Co-authored-by: Julien Gacon <gaconju@gmail.com>

commit bb41815
Author: Luciano Bello <bel@zurich.ibm.com>
Date:   Thu Sep 8 00:52:46 2022 +0200

    Remove deprecated pulse-builder contexts (Qiskit#8697)

    * Remove qiskit.pulse.builder.inline as deprecated in 0.18.0 (2021-07-13)

    * remove imports

    * remove test

    * Remove qiskit.pulse.builder.pad as deprecated in 0.18.0 (2021-07-13)

    * reno

    * Reword removal note

    Co-authored-by: Jake Lishman <jake.lishman@ibm.com>

commit ee0a4f1
Author: Manoel Marques <Manoel.Marques@ibm.com>
Date:   Wed Sep 7 14:35:47 2022 -0400

    Improve HHL/Shor deprecated messages (Qiskit#8699)

commit ea4ebed
Author: a-matsuo <47442626+a-matsuo@users.noreply.github.com>
Date:   Wed Sep 7 17:33:53 2022 +0900

    Include primitive's run_options (Qiskit#8694)

    * include primitive's run_options

    * rename to get_local_run_options

commit a842f40
Author: Edwin Navarro <enavarro@comcast.net>
Date:   Tue Sep 6 18:12:00 2022 -0700

    Move circuit drawer files to `qiskit.visualization.circuit` (Qiskit#8306)

    * Add graph and circuit dirs

    * Move files to new folders

    * Finishing transition to circuit and graph dirs

    * Finish import changes

    * Positioning files and setting init entries

    * Final tweaks to compatibility and lint

    * Reduce to circuit dir only

    * Cleanup

    * Add qcstyle stub for docs

    * Merge main conflicts fix

    * Lint

    * Change test message

    * Fix _directive change

    * Fix op.condition reference

    * Change to _utils and cleanup

    * Lint

    * Fix _trim and dag_drawer test

    * Allow direct import of text, etc.

    * Add comment explaining backwards-compatibility imports

    * Add release note

    Co-authored-by: Jake Lishman <jake.lishman@ibm.com>

commit f4a5241
Author: Ikko Hamamura <ikkoham@users.noreply.github.com>
Date:   Tue Sep 6 00:37:43 2022 +0900

    Default run_options for Primitives (Qiskit#8513)

    * Add run_options to Primitives

    * rm unnecessary comments

    * initial commit of Settings dataclass

    * Revert "initial commit of Settings dataclass"

    This reverts commit 96b8479.

    * fix lint, improve docs, don't return self

    Co-authored-by: Julien Gacon <gaconju@gmail.com>
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

commit a8e553c
Author: a-matsuo <47442626+a-matsuo@users.noreply.github.com>
Date:   Mon Sep 5 21:05:35 2022 +0900

    Gradients with the primitives (Qiskit#8528)

    * added the gradients with the primitives

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * add run_options and supported gate

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * added unittests

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * lint

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix based on the comments

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * add spsa gradient

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * simplify + async

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * added gradient variance

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * lint

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * added the run_options field

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix lint

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix based on comments

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * wip fix2

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * lint

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix epsilon and doc

    * lint

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix

    * Update qiskit/algorithms/gradients/base_sampler_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/base_sampler_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/base_estimator_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/base_sampler_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/base_estimator_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/base_estimator_gradient.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * change epsilon error

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/estimator_gradient_result.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * Update qiskit/algorithms/gradients/sampler_gradient_result.py

    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * add gradient test

    * added batch size in spsa gradients

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * fix

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * lint

    * Update qiskit/algorithms/gradients/lin_comb_estimator_gradient.py

    Co-authored-by: Julien Gacon <gaconju@gmail.com>

    * add operator tests

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * consistent name

    * rewrite spsa

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>

    * use algorithm job

    Co-authored-by: Ikko Hamamura <ikkoham@users.noreply.github.com>
    Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com>
    Co-authored-by: Julien Gacon <gaconju@gmail.com>
    Co-authored-by: Takashi Imamichi <imamichi@jp.ibm.com>

commit 879f7ba
Author: dalin27 <77298980+dalin27@users.noreply.github.com>
Date:   Mon Sep 5 05:02:11 2022 +0300

    fixed issue 8670 by inverting qubits_coordinates and coupling_map (Qiskit#8671)

commit 3c85677
Merge: 33e0007 e9913e8
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 8 12:30:39 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit 33e0007
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 8 12:24:55 2022 -0400

    remove redefiing coupling map in control flow context

commit cd9c5cf
Merge: ca4f477 aca01eb
Author: ewinston <ewinston@us.ibm.com>
Date:   Sat Sep 3 02:15:59 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit ca4f477
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 2 16:15:08 2022 -0400

    remove breakpoint

commit ee78880
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 2 16:13:38 2022 -0400

    fix check_map

commit ef35278
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Fri Sep 2 01:13:12 2022 -0400

    add check_map to tests. tests passing

commit 349dca4
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Thu Sep 1 11:29:47 2022 -0400

    add check_map

commit cb1398d
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Wed Aug 31 22:29:37 2022 -0400

    convert up to for loop

commit 3169afd
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Tue Aug 30 15:54:53 2022 -0400

    lint

commit 2b8d5bb
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Mon Aug 29 16:02:12 2022 -0400

    rmove `continue` handling. raise error on unsupported control flow op.

commit 12fb4bc
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Mon Aug 29 15:55:44 2022 -0400

    remove DAGCircuit.control_flow_ops

commit 9a0ad5c
Merge: 09f8490 82e38d1
Author: ewinston <ewinston@us.ibm.com>
Date:   Fri Aug 12 10:46:41 2022 -0400

    Merge branch 'main' into controlflow/stochastic_swap

commit 09f8490
Author: Erick Winston <ewinston@us.ibm.com>
Date:   Wed Jul 20 09:56:28 2022 -0400

    add controlflow handling to stochastic swap pass
  • Loading branch information
ewinston committed Oct 5, 2022
1 parent b7e6329 commit 2efddcb
Show file tree
Hide file tree
Showing 8 changed files with 1,019 additions and 52 deletions.
1 change: 0 additions & 1 deletion qiskit/circuit/instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ def __eq__(self, other):
or self.definition != other.definition
):
return False

for self_param, other_param in zip_longest(self.params, other.params):
try:
if self_param == other_param:
Expand Down
57 changes: 57 additions & 0 deletions qiskit/dagcircuit/dagcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,63 @@ def remove_cregs(self, *cregs):
for creg in cregs:
del self.cregs[creg.name]

def remove_qubits(self, *qubits):
"""
Remove quantum bits from the circuit. All bits MUST be idle.
Any registers with references to at least one of the specified bits will
also be removed.
Args:
qubits (List[Qubit]): The bits to remove.
Raises:
DAGCircuitError: a qubit is not a :obj:`.Qubit`, is not in the circuit,
or is not idle.
"""
if any(not isinstance(qubit, Qubit) for qubit in qubits):
raise DAGCircuitError(
"qubits not of type Qubit: %s" % [b for b in qubits if not isinstance(b, Qubit)]
)

qubits = set(qubits)
unknown_qubits = qubits.difference(self.qubits)
if unknown_qubits:
raise DAGCircuitError("qubits not in circuit: %s" % unknown_qubits)

busy_qubits = {bit for bit in qubits if not self._is_wire_idle(bit)}
if busy_qubits:
raise DAGCircuitError("qubits not idle: %s" % busy_qubits)

# remove any references to bits
qregs_to_remove = {qreg for qreg in self.qregs.values() if not qubits.isdisjoint(qreg)}
self.remove_qregs(*qregs_to_remove)

for qubit in qubits:
self._remove_idle_wire(qubit)
self.qubits.remove(qubit)

def remove_qregs(self, *qregs):
"""
Remove classical registers from the circuit, leaving underlying bits
in place.
Raises:
DAGCircuitError: a qreg is not a QuantumRegister, or is not in
the circuit.
"""
if any(not isinstance(qreg, QuantumRegister) for qreg in qregs):
raise DAGCircuitError(
"qregs not of type QuantumRegister: %s"
% [r for r in qregs if not isinstance(r, QuantumRegister)]
)

unknown_qregs = set(qregs).difference(self.qregs.values())
if unknown_qregs:
raise DAGCircuitError("qregs not in circuit: %s" % unknown_qregs)

for qreg in qregs:
del self.qregs[qreg.name]

def _is_wire_idle(self, wire):
"""Check if a wire is idle.
Expand Down
3 changes: 1 addition & 2 deletions qiskit/dagcircuit/dagnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def semantic_eq(node1, node2, bit_indices1=None, bit_indices2=None):
node2_cargs = [bit_indices2[carg] for carg in node2.cargs]

# For barriers, qarg order is not significant so compare as sets
if "barrier" == node1.op.name == node2.op.name:
if node1.op.name == node2.op.name and node1.name in {"barrier", "swap"}:
return set(node1_qargs) == set(node2_qargs)

if node1_qargs == node2_qargs:
Expand All @@ -87,7 +87,6 @@ def semantic_eq(node1, node2, bit_indices1=None, bit_indices2=None):
):
if bit_indices1.get(node1.wire, None) == bit_indices2.get(node2.wire, None):
return True

return False


Expand Down
14 changes: 12 additions & 2 deletions qiskit/transpiler/passes/routing/layout_transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(
to_layout: Union[Layout, str],
seed: Union[int, np.random.default_rng] = None,
trials=4,
inplace=True,
):
"""LayoutTransformation initializer.
Expand All @@ -55,6 +56,10 @@ def __init__(
trials (int):
How many randomized trials to perform, taking the best circuit as output.
inplace (bool): Whether to apply transform to dag in-place. If False, the
orginal dag is returned. The swap network on the physical qubits, however,
can be retrieved from the ``perm_circ`` attribute.
"""
super().__init__()
self.from_layout = from_layout
Expand All @@ -67,6 +72,9 @@ def __init__(
graph = self.coupling_map.graph.to_undirected()
self.token_swapper = ApproximateTokenSwapper(graph, seed)
self.trials = trials
self.perm_circ = None
self.perm_qubits = None
self.inplace = inplace

def run(self, dag):
"""Apply the specified partial permutation to the circuit.
Expand Down Expand Up @@ -106,9 +114,11 @@ def run(self, dag):
pqubit: to_layout.get_virtual_bits()[vqubit]
for vqubit, pqubit in from_layout.get_virtual_bits().items()
}

perm_circ = self.token_swapper.permutation_circuit(permutation, self.trials)

qubits = [dag.qubits[i[0]] for i in sorted(perm_circ.inputmap.items(), key=lambda x: x[0])]
dag.compose(perm_circ.circuit, qubits=qubits)
self.property_set["perm_circ"] = perm_circ
self.property_set["perm_qubits"] = qubits

dag.compose(perm_circ.circuit, qubits=qubits, inplace=self.inplace)
return dag
167 changes: 123 additions & 44 deletions qiskit/transpiler/passes/routing/stochastic_swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
from qiskit.dagcircuit import DAGCircuit
from qiskit.circuit.library.standard_gates import SwapGate
from qiskit.transpiler.layout import Layout
from qiskit.transpiler.passes.routing.utils import (
route_cf_multiblock,
route_cf_looping,
combine_permutations,
)
from qiskit.circuit import IfElseOp, WhileLoopOp, ForLoopOp, ControlFlowOp

from qiskit._accelerate import stochastic_swap as stochastic_swap_rs

Expand All @@ -43,7 +49,9 @@ class StochasticSwap(TransformationPass):
the circuit.
"""

def __init__(self, coupling_map, trials=20, seed=None, fake_run=False):
_instance_num = 0 # track number of instances of this class

def __init__(self, coupling_map, trials=20, seed=None, fake_run=False, initial_layout=None):
"""StochasticSwap initializer.
The coupling map is a connected graph
Expand All @@ -57,16 +65,18 @@ def __init__(self, coupling_map, trials=20, seed=None, fake_run=False):
seed (int): seed for random number generator
fake_run (bool): if true, it only pretend to do routing, i.e., no
swap is effectively added.
initial_layout (Layout): starting layout at beginning of pass.
"""
super().__init__()
self.coupling_map = coupling_map
self.trials = trials
self.seed = seed
self.fake_run = fake_run
self.qregs = None
self.rng = None
self.trivial_layout = None
self.initial_layout = initial_layout
self._qubit_indices = None
self._instance_num += 1

def run(self, dag):
"""Run the StochasticSwap pass on `dag`.
Expand All @@ -89,7 +99,8 @@ def run(self, dag):
raise TranspilerError("The layout does not match the amount of qubits in the DAG")

canonical_register = dag.qregs["q"]
self.trivial_layout = Layout.generate_trivial_layout(canonical_register)
if self.initial_layout is None:
self.initial_layout = Layout.generate_trivial_layout(canonical_register)
self._qubit_indices = {bit: idx for idx, bit in enumerate(dag.qubits)}

self.qregs = dag.qregs
Expand Down Expand Up @@ -205,8 +216,8 @@ def _layer_permutation(self, layer_partition, layout, qubit_subset, coupling, tr

edges = best_edges.edges()
for idx in range(len(edges) // 2):
swap_src = self.trivial_layout._p2v[edges[2 * idx]]
swap_tgt = self.trivial_layout._p2v[edges[2 * idx + 1]]
swap_src = self.initial_layout._p2v[edges[2 * idx]]
swap_tgt = self.initial_layout._p2v[edges[2 * idx + 1]]
trial_circuit.apply_operation_back(SwapGate(), [swap_src, swap_tgt], [])
best_circuit = trial_circuit

Expand All @@ -229,7 +240,7 @@ def _layer_update(self, dag, layer, best_layout, best_depth, best_circuit):
"""
layout = best_layout
logger.debug("layer_update: layout = %s", layout)
logger.debug("layer_update: self.trivial_layout = %s", self.trivial_layout)
logger.debug("layer_update: self.initial_layout = %s", self.initial_layout)

# Output any swaps
if best_depth > 0:
Expand All @@ -239,14 +250,16 @@ def _layer_update(self, dag, layer, best_layout, best_depth, best_circuit):
logger.debug("layer_update: there are no swaps in this layer")
# Output this layer
layer_circuit = layer["graph"]
order = layout.reorder_bits(dag.qubits)
initial_v2p = self.initial_layout.get_virtual_bits()
new_v2p = layout.get_virtual_bits()
initial_order = [initial_v2p[qubit] for qubit in dag.qubits]
new_order = [new_v2p[qubit] for qubit in dag.qubits]
order = combine_permutations(initial_order, new_order)
dag.compose(layer_circuit, qubits=order)

def _mapper(self, circuit_graph, coupling_graph, trials=20):
"""Map a DAGCircuit onto a CouplingMap using swap gates.
Use self.trivial_layout for the initial layout.
Args:
circuit_graph (DAGCircuit): input DAG circuit
coupling_graph (CouplingMap): coupling graph to map onto
Expand All @@ -266,28 +279,34 @@ def _mapper(self, circuit_graph, coupling_graph, trials=20):
for i, v in enumerate(layerlist):
logger.debug(" %d: %s", i, v["partition"])

qubit_subset = self.trivial_layout.get_virtual_bits().keys()
qubit_subset = self.initial_layout.get_virtual_bits().keys()

# Find swap circuit to precede each layer of input circuit
layout = self.trivial_layout.copy()
layout = self.initial_layout.copy()

# Construct an empty DAGCircuit with the same set of
# qregs and cregs as the input circuit
dagcircuit_output = None
if not self.fake_run:
dagcircuit_output = circuit_graph.copy_empty_like()

logger.debug("trivial_layout = %s", layout)
logger.debug("layout = %s", layout)

# Iterate over layers
for i, layer in enumerate(layerlist):
layer_dag = layer["graph"]
cf_nodes = layer_dag.op_nodes(op=ControlFlowOp)
if cf_nodes:
# handle layers with control flow serially
success_flag = False
else:
# Attempt to find a permutation for this layer
success_flag, best_circuit, best_depth, best_layout = self._layer_permutation(
layer["partition"], layout, qubit_subset, coupling_graph, trials
)

# Attempt to find a permutation for this layer
success_flag, best_circuit, best_depth, best_layout = self._layer_permutation(
layer["partition"], layout, qubit_subset, coupling_graph, trials
)
logger.debug("mapper: layer %d", i)
logger.debug("mapper: success_flag=%s,best_depth=%s", success_flag, str(best_depth))
logger.debug("mapper: layer %d", i)
logger.debug("mapper: success_flag=%s,best_depth=%s", success_flag, str(best_depth))

# If this fails, try one gate at a time in this layer
if not success_flag:
Expand All @@ -296,34 +315,45 @@ def _mapper(self, circuit_graph, coupling_graph, trials=20):

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

success_flag, best_circuit, best_depth, best_layout = self._layer_permutation(
serial_layer["partition"], layout, qubit_subset, coupling_graph, trials
)
logger.debug("mapper: layer %d, sublayer %d", i, j)
logger.debug(
"mapper: success_flag=%s,best_depth=%s,", success_flag, str(best_depth)
)

# Give up if we fail again
if not success_flag:
raise TranspilerError(
"swap mapper failed: " + "layer %d, sublayer %d" % (i, j)
)

# Update the record of qubit positions
# for each inner iteration
layout = best_layout
# Update the DAG
if not self.fake_run:
self._layer_update(
dagcircuit_output,
serial_layerlist[j],
best_layout,
best_depth,
layer_dag = serial_layer["graph"]
# layer_dag has only one operation
op_node = layer_dag.op_nodes()[0]
if not isinstance(op_node.op, ControlFlowOp):
(
success_flag,
best_circuit,
best_depth,
best_layout,
) = self._layer_permutation(
serial_layer["partition"], layout, qubit_subset, coupling_graph, trials
)
logger.debug("mapper: layer %d, sublayer %d", i, j)
logger.debug(
"mapper: success_flag=%s,best_depth=%s,", success_flag, str(best_depth)
)

# Give up if we fail again
if not success_flag:
raise TranspilerError(
"swap mapper failed: " + "layer %d, sublayer %d" % (i, j)
)

# Update the record of qubit positions
# for each inner iteration
layout = best_layout
# Update the DAG
if not self.fake_run:
self._layer_update(
dagcircuit_output,
serial_layerlist[j],
best_layout,
best_depth,
best_circuit,
)
else:
layout = self._controlflow_layer_update(
dagcircuit_output, layer_dag, layout, circuit_graph, _seed=self.seed
)
else:
# Update the record of qubit positions for each iteration
layout = best_layout
Expand All @@ -339,7 +369,56 @@ def _mapper(self, circuit_graph, coupling_graph, trials=20):
logger.debug("mapper: self.trivial_layout = %s", self.trivial_layout)
logger.debug("mapper: layout = %s", layout)

self.property_set["final_layout"] = layout
if self.fake_run:
self.property_set["final_layout"] = layout
return circuit_graph
return dagcircuit_output

def _controlflow_layer_update(
self, dagcircuit_output, layer_dag, current_layout, root_dag, _seed=None
):
"""
Updates the new dagcircuit with a routed control flow operation.
Args:
dagcircuit_output (DAGCircuit): dagcircuit that is being built with routed operations.
layer_dag (DAGCircuit): layer to route containing a single controlflow operation.
current_layout (Layout): current layout coming into this layer.
root_dag (DAGCircuit): root dag of pass
_seed (int or None): seed used to derive seeds for child instances of this pass where
it is used by stochastic_swap_rs.swap_trials as well as LayoutTransformation. If
the seed is not None the instance_num class variable gets added to this seed to
seed other instances.
Returns:
Layout: updated layout after this layer has been routed.
Raises:
TranspilerError: if layer_dag does not contain a recognized ControlFlowOp.
"""
cf_opnode = layer_dag.op_nodes()[0]
seed = _seed if _seed is None else _seed + self._instance_num
_pass = self.__class__(self.coupling_map, initial_layout=current_layout, seed=seed)
if isinstance(cf_opnode.op, IfElseOp):
updated_ctrl_op, cf_layout, idle_qubits = route_cf_multiblock(
_pass, cf_opnode, current_layout, self.qregs, root_dag, seed=self.seed
)
elif isinstance(cf_opnode.op, (ForLoopOp, WhileLoopOp)):
updated_ctrl_op, cf_layout, idle_qubits = route_cf_looping(
_pass, cf_opnode, current_layout, root_dag, seed=self.seed
)
else:
raise TranspilerError(f"unsupported control flow operation: {cf_opnode}")

cf_layer_dag = DAGCircuit()
cf_qubits = [qubit for qubit in root_dag.qubits if qubit not in idle_qubits]
qreg = QuantumRegister(len(cf_qubits), "q")
cf_layer_dag.add_qreg(qreg)
for creg in layer_dag.cregs.values():
cf_layer_dag.add_creg(creg)
cf_layer_dag.apply_operation_back(updated_ctrl_op, cf_layer_dag.qubits, cf_opnode.cargs)
target_qubits = [qubit for qubit in dagcircuit_output.qubits if qubit not in idle_qubits]
order = current_layout.reorder_bits(target_qubits)
dagcircuit_output.compose(cf_layer_dag, qubits=order)
return cf_layout
Loading

0 comments on commit 2efddcb

Please sign in to comment.