Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace DAGNode class with OpNode, InNode, and OutNode classes #6567

Merged
merged 55 commits into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
d41727e
First dagcircuit dagnode changes
enavarro51 Jun 5, 2021
35b6e30
Stage 2 OpNode, etc
enavarro51 Jun 5, 2021
fc8bf1c
Update node ops and node types
enavarro51 Jun 6, 2021
9d58862
More predecessor testing
enavarro51 Jun 6, 2021
8661860
Further testing
enavarro51 Jun 7, 2021
69ae524
Put op in OpNode and further testing of dagcircuit
enavarro51 Jun 11, 2021
be6738e
Passing dagcircuit tests
enavarro51 Jun 11, 2021
4cdc91b
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 11, 2021
30a02db
Final dagcircuit cleanup
enavarro51 Jun 11, 2021
318c0b5
Transpiler mods for node.type
enavarro51 Jun 11, 2021
7d5558a
Final transpiler tests
enavarro51 Jun 12, 2021
559e9e8
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 12, 2021
f8cbd63
Fix transpiler tests, change to DAGNodeP
enavarro51 Jun 12, 2021
5d28436
Fix minimal InNode and OutNode
enavarro51 Jun 13, 2021
5853cde
Doc changes
enavarro51 Jun 13, 2021
6cd9bae
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 13, 2021
803eaf2
More docs
enavarro51 Jun 13, 2021
2991e4d
Opflow bug
enavarro51 Jun 14, 2021
17d7745
Finish doc changes and testing
enavarro51 Jun 14, 2021
c1f25b8
Deprecations
enavarro51 Jun 15, 2021
8937e3f
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 15, 2021
c9124f5
Fix merge conflict
enavarro51 Jun 15, 2021
09dfa0a
Make DAGNode parent also
enavarro51 Jun 16, 2021
5324544
Fix _op
enavarro51 Jun 16, 2021
e4d5a9f
Final deprecations for DAGNode
enavarro51 Jun 17, 2021
de56e10
Fix semantic_eq
enavarro51 Jun 17, 2021
88a4875
Update semantic_eq op check
enavarro51 Jun 17, 2021
b99faa8
Add semantic_eq test
enavarro51 Jun 17, 2021
d555f41
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 17, 2021
f6a97f3
Lint
enavarro51 Jun 17, 2021
736357f
Merge branch 'dag_node_op_io' of github.com:enavarro51/qiskit-terra i…
enavarro51 Jun 17, 2021
c985848
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 17, 2021
95f3b47
Fix node.condition and reno
enavarro51 Jun 18, 2021
ac0a881
Merge branch 'dag_node_op_io' of github.com:enavarro51/qiskit-terra i…
enavarro51 Jun 18, 2021
8f87581
Cleanup doc and reno
enavarro51 Jun 20, 2021
bd94850
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 20, 2021
205ac26
Put DAG in class names, cleanup isinstances, add type to new classes-…
enavarro51 Jun 24, 2021
fe1ab48
Lint
enavarro51 Jun 24, 2021
a990ded
Remove condition from apply_operation_back and front
enavarro51 Jun 24, 2021
d19e3f4
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 26, 2021
72fd91f
Fix merge conflicts from 6534
enavarro51 Jun 28, 2021
acdd6c1
Fix latex conflict
enavarro51 Jun 28, 2021
be2002f
Unused import
enavarro51 Jun 28, 2021
92c3693
Fix sort_key, qargs, and cargs and add deprecation testing
enavarro51 Jun 29, 2021
20a0fd6
Merge branch 'main' into dag_node_op_io
enavarro51 Jun 29, 2021
7947061
Move deprecations to 0.19.0 and remove DAGOpNode condition deprecation
enavarro51 Jul 7, 2021
0f6b4b1
Merge branch 'dag_node_op_io' of github.com:enavarro51/qiskit-terra i…
enavarro51 Jul 7, 2021
4bef5d6
Merge branch 'main' into dag_node_op_io
enavarro51 Jul 21, 2021
d763557
Convert type to DAGOpNode and DAGInNode in bip_mapping and dynamical_…
enavarro51 Jul 21, 2021
ddbc425
Several dagcircuit changes and more release note
enavarro51 Aug 2, 2021
054c487
Simplify idle_wires
enavarro51 Aug 2, 2021
82059d2
Merge branch 'main' into dag_node_op_io
enavarro51 Aug 2, 2021
8d5a430
Fix meth
enavarro51 Aug 3, 2021
7d58994
Merge branch 'dag_node_op_io' of github.com:enavarro51/qiskit-terra i…
enavarro51 Aug 3, 2021
1a2150b
Merge branch 'main' into dag_node_op_io
enavarro51 Aug 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions qiskit/dagcircuit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
# (C) Copyright IBM 2017, 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -25,6 +25,9 @@

DAGCircuit
DAGNode
OpNode
InNode
OutNode
kdk marked this conversation as resolved.
Show resolved Hide resolved
DAGDepNode
DAGDependency

Expand All @@ -37,7 +40,7 @@
DAGCircuitError
"""
from .dagcircuit import DAGCircuit
from .dagnode import DAGNode
from .dagnode import DAGNode, OpNode, InNode, OutNode
from .dagdepnode import DAGDepNode
from .exceptions import DAGCircuitError
from .dagdependency import DAGDependency
155 changes: 79 additions & 76 deletions qiskit/dagcircuit/dagcircuit.py

Large diffs are not rendered by default.

158 changes: 123 additions & 35 deletions qiskit/dagcircuit/dagnode.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2019.
# (C) Copyright IBM 2017, 2019, 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
Expand All @@ -12,25 +12,37 @@

# pylint: disable=redefined-builtin

"""Object to represent the information at a node in the DAGCircuit."""
"""Objects to represent the information at a node in the DAGCircuit."""

import warnings

from qiskit.exceptions import QiskitError


class DAGNode:
"""Object to represent the information at a node in the DAGCircuit.

It is used as the return value from `*_nodes()` functions and can
be supplied to functions that take a node.
"""
"""Parent class for OpNode, InNode, and OutNode."""

__slots__ = ["type", "_op", "_qargs", "cargs", "_wire", "sort_key", "_node_id"]

def __init__(self, type=None, op=None, name=None, qargs=None, cargs=None, wire=None, nid=-1):
"""Create a node"""
if type is not None:
warnings.warn(
"The DAGNode 'type' attribute is deprecated as of 0.18.0 and "
"will be removed no earlier than 3 months after the release date. "
"Use OpNode, InNode, or OutNode instead of DAGNode.",
DeprecationWarning,
2,
)
kdk marked this conversation as resolved.
Show resolved Hide resolved
self.type = type
if op is not None:
warnings.warn(
"The DAGNode 'op' attribute is deprecated as of 0.18.0 and "
"will be removed no earlier than 3 months after the release date."
"Use OpNode instead of DAGNode.",
DeprecationWarning,
2,
)
self._op = op
if name is not None:
warnings.warn(
Expand All @@ -42,6 +54,14 @@ def __init__(self, type=None, op=None, name=None, qargs=None, cargs=None, wire=N
)
self._qargs = qargs if qargs is not None else []
self.cargs = cargs if cargs is not None else []
if wire is not None:
warnings.warn(
"The DAGNode 'wire' attribute is deprecated as of 0.18.0 and "
"will be removed no earlier than 3 months after the release date."
"Use InNode or OutNode instead of DAGNode.",
DeprecationWarning,
2,
)
self._wire = wire
self._node_id = nid
self.sort_key = str(self._qargs)
Expand All @@ -61,13 +81,14 @@ def op(self, data):
def name(self):
"""Returns the Instruction name corresponding to the op for this node"""
if self.type and self.type == "op":
return self._op.name
return self.op.name
return None

@name.setter
def name(self, name):
"""Sets the Instruction name corresponding to the op for this node"""
if self.type and self.type == "op":
self._op.name = name
self.op.name = name

@property
def condition(self):
Expand All @@ -81,7 +102,7 @@ def condition(self):
DeprecationWarning,
2,
)
return self._op.condition
return self.op.condition

@condition.setter
def condition(self, new_condition):
Expand All @@ -95,7 +116,7 @@ def condition(self, new_condition):
DeprecationWarning,
2,
)
self._op.condition = new_condition
self.op.condition = new_condition

@property
def qargs(self):
Expand Down Expand Up @@ -140,8 +161,8 @@ def semantic_eq(node1, node2, bit_indices1=None, bit_indices2=None):
Check if DAG nodes are considered equivalent, e.g., as a node_match for nx.is_isomorphic.

Args:
node1 (DAGNode): A node to compare.
node2 (DAGNode): The other node to compare.
node1 (OpNode, InNode, OutNode): A node to compare.
node2 (OpNode, InNode, OutNode): The other node to compare.
bit_indices1 (dict): Dictionary mapping Bit instances to their index
within the circuit containing node1
bit_indices2 (dict): Dictionary mapping Bit instances to their index
Expand All @@ -163,26 +184,93 @@ def semantic_eq(node1, node2, bit_indices1=None, bit_indices2=None):
bit_indices1 = {arg: arg for arg in node1.qargs + node1.cargs}
bit_indices2 = {arg: arg for arg in node2.qargs + node2.cargs}

node1_qargs = [bit_indices1[qarg] for qarg in node1.qargs]
node1_cargs = [bit_indices1[carg] for carg in node1.cargs]

node2_qargs = [bit_indices2[qarg] for qarg in node2.qargs]
node2_cargs = [bit_indices2[carg] for carg in node2.cargs]

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

if node1.type == node2.type:
if node1._op == node2._op:
if node1.name == node2.name:
if node1_qargs == node2_qargs:
if node1_cargs == node2_cargs:
if node1.type == "op":
if node1._op.condition != node2._op.condition:
return False
if bit_indices1.get(node1._wire, None) == bit_indices2.get(
node2._wire, None
):
return True
if isinstance(node1, OpNode) and isinstance(node2, OpNode):
node1_qargs = [bit_indices1[qarg] for qarg in node1.qargs]
node1_cargs = [bit_indices1[carg] for carg in node1.cargs]

node2_qargs = [bit_indices2[qarg] for qarg in node2.qargs]
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:
return set(node1_qargs) == set(node2_qargs)

if node1_qargs == node2_qargs:
if node1_cargs == node2_cargs:
if node1.op.condition == node2.op.condition:
if node1.op == node2.op:
return True
elif (isinstance(node1, InNode) and isinstance(node2, InNode)) or (
isinstance(node1, OutNode) and isinstance(node2, OutNode)
):
if bit_indices1.get(node1.wire, None) == bit_indices2.get(node2.wire, None):
return True

return False


class OpNode(DAGNode):
"""Object to represent an Instruction at a node in the DAGCircuit."""

__slots__ = ["op"]

def __init__(self, op, qargs=None, cargs=None):
"""Create an Instruction node"""
self.op = op
super().__init__(qargs=qargs, cargs=cargs)
kdk marked this conversation as resolved.
Show resolved Hide resolved

@property
def name(self):
"""Returns the Instruction name corresponding to the op for this node"""
return self.op.name

@name.setter
def name(self, new_name):
"""Sets the Instruction name corresponding to the op for this node"""
self.op.name = new_name

@property
def condition(self):
"""Returns the condition of the node.op"""
warnings.warn(
"The OpNode 'condition' attribute is deprecated as of 0.18.0 and "
"will be removed no earlier than 3 months after the release date. "
"You can use 'OpNode.op.condition'.",
DeprecationWarning,
2,
)
return self.op.condition

@condition.setter
def condition(self, new_condition):
"""Sets the node.condition which sets the node.op.condition."""
warnings.warn(
"The OpNode 'condition' attribute is deprecated as of 0.18.0 and "
"will be removed no earlier than 3 months after the release date. "
"You can use 'OpNode.op.condition'.",
DeprecationWarning,
2,
)
self.op.condition = new_condition


class InNode(DAGNode):
"""Object to represent an incoming wire node in the DAGCircuit."""

__slots__ = ["wire"]

def __init__(self, wire):
"""Create an incoming node"""
self.wire = wire
super().__init__()


class OutNode(DAGNode):
"""Object to represent an outgoing wire node in the DAGCircuit."""

__slots__ = ["wire"]

def __init__(self, wire):
"""Create an outgoing node"""
self.wire = wire
super().__init__()
2 changes: 1 addition & 1 deletion qiskit/transpiler/passes/analysis/dag_longest_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


class DAGLongestPath(AnalysisPass):
"""Return the longest path in a DAGcircuit as a list of DAGNodes."""
"""Return the longest path in a DAGcircuit as a list of OpNodes, InNodes, and OutNodes."""

def run(self, dag):
"""Run the DAGLongestPath pass on `dag`."""
Expand Down
4 changes: 2 additions & 2 deletions qiskit/transpiler/passes/layout/apply_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""Transform a circuit with virtual qubits into a circuit with physical qubits."""

from qiskit.circuit import QuantumRegister
from qiskit.dagcircuit import DAGCircuit
from qiskit.dagcircuit import DAGCircuit, OpNode
from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler.exceptions import TranspilerError

Expand Down Expand Up @@ -59,7 +59,7 @@ def run(self, dag):
for creg in dag.cregs.values():
new_dag.add_creg(creg)
for node in dag.topological_op_nodes():
if node.type == "op":
if isinstance(node, OpNode):
kdk marked this conversation as resolved.
Show resolved Hide resolved
qargs = [q[layout[qarg]] for qarg in node.qargs]
new_dag.apply_operation_back(node.op, qargs, node.cargs)
new_dag._global_phase = dag._global_phase
Expand Down
Loading