Skip to content

Commit b459480

Browse files
committed
Rename MultiQubitGateManager to GateManager and update docstrings
1 parent d221ac8 commit b459480

File tree

5 files changed

+118
-86
lines changed

5 files changed

+118
-86
lines changed

docs/projectq.cengines.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ The ProjectQ compiler engines package.
66
.. autosummary::
77
projectq.cengines.AutoReplacer
88
projectq.cengines.BasicEngine
9-
projectq.cengines.BasicMapper
9+
projectq.cengines.BasicMapperEngine
1010
projectq.cengines.CommandModifier
1111
projectq.cengines.CompareEngine
1212
projectq.cengines.DecompositionRule
@@ -37,9 +37,9 @@ Module contents
3737
Helper sub-modules
3838
------------------
3939

40-
Multi-qubit gate sub-module
41-
^^^^^^^^^^^^^^^^^^^^^^^^^^^
40+
Gate manager sub-module
41+
^^^^^^^^^^^^^^^^^^^^^^^
4242

43-
.. automodule:: projectq.cengines._multi_qubit_gate_manager
43+
.. automodule:: projectq.cengines._gate_manager
4444
:members:
4545
:imported-members:

projectq/cengines/_multi_qubit_gate_manager.py renamed to projectq/cengines/_gate_manager.py

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,30 @@
2222
"""
2323

2424
import networkx as nx
25-
import statistics
2625
import math
2726
from projectq.ops import (AllocateQubitGate, DeallocateQubitGate)
2827

2928
# ==============================================================================
3029

3130

3231
def _topological_sort(dag):
32+
"""
33+
Returns a generator of nodes in topologically sorted order.
34+
35+
A topological sort is a nonunique permutation of the nodes such that an
36+
edge from u to v implies that u appears before v in the topological sort
37+
order.
38+
39+
Args:
40+
dag (networkx.DiGraph): A Directed Acyclic Graph (DAG)
41+
42+
Returns:
43+
An iterable of node names in topological sorted order.
44+
45+
Note:
46+
This implementation is based on
47+
:py:func:`networkx.algorithms.dag.topological_sort`
48+
"""
3349
indegree_map = {}
3450
zero_indegree = []
3551
for node, degree in dag.in_degree():
@@ -50,6 +66,18 @@ def _topological_sort(dag):
5066

5167
# Coffaman-Graham algorithm with infinite width
5268
def _coffman_graham_ranking(dag):
69+
"""
70+
Apply the Coffman-Grapham layering algorithm to a DAG (with infinite width)
71+
72+
Args:
73+
dag (networkx.DiGraph): A Directed Acyclic Graph (DAG)
74+
75+
Returns:
76+
A list of layers (Python list of lists).
77+
78+
Note:
79+
This function does not limit the width of any layers.
80+
"""
5381
layers = [[]]
5482
levels = {}
5583

@@ -86,7 +114,7 @@ def _sum_distance_over_gates(node_list, mapping, distance_matrix):
86114
gate_list (list): List of 2-qubit gates
87115
mapping (dict): Current mapping
88116
distance_matrix (dict): Distance matrix within the hardware coupling
89-
graph
117+
graph
90118
91119
Returns:
92120
Sum of all pair-wise distances between qubits
@@ -118,10 +146,10 @@ def nearest_neighbours_cost_fun(gates_dag, mapping, distance_matrix, swap,
118146
gates_dag (CommandDAG): Direct acyclic graph of future quantum gates
119147
mapping (dict): Current mapping
120148
distance_matrix (dict): Distance matrix within the hardware coupling
121-
graph
149+
graph
122150
swap (tuple): Candidate swap (not used by this function)
123151
opts (dict): Miscellaneous parameters for cost function (not used by
124-
this function)
152+
this function)
125153
126154
Returns:
127155
Score of current swap operations
@@ -159,7 +187,7 @@ def look_ahead_parallelism_cost_fun(gates_dag, mapping, distance_matrix, swap,
159187
gates_dag (CommandDAG): Direct acyclic graph of future quantum gates
160188
mapping (dict): Current mapping
161189
distance_matrix (dict): Distance matrix within the hardware coupling
162-
graph
190+
graph
163191
swap (tuple): Candidate swap operation
164192
opts (dict): Miscellaneous parameters for cost function
165193
@@ -237,8 +265,8 @@ class DecayManager(object):
237265
"""
238266
Class managing the decay information about a list of backend qubit IDs
239267
240-
User should call the :py:meth:`step` method each time a swap gate is added and
241-
:py:meth:`remove_decay` once a 2-qubit gate is executed.
268+
User should call the :py:meth:`step` method each time a swap gate is added
269+
and :py:meth:`remove_decay` once a 2-qubit gate is executed.
242270
"""
243271
def __init__(self, delta, max_lifetime):
244272
"""
@@ -247,7 +275,7 @@ def __init__(self, delta, max_lifetime):
247275
Args:
248276
delta (float): Decay parameter
249277
max_lifetime (int): Maximum lifetime of decay information for a
250-
particular qubit
278+
particular qubit
251279
"""
252280
self._delta = delta
253281
self._cutoff = max_lifetime
@@ -389,7 +417,9 @@ def size(self):
389417
Return the size of the DAG (ie. number of nodes)
390418
391419
Note:
392-
This need not be the number of commands stored within the DAG.
420+
This may not be equal to the number of commands stored within the
421+
DAG as some nodes might store more than one gate if they are
422+
compatible.
393423
"""
394424
return self._dag.number_of_nodes()
395425

@@ -521,7 +551,7 @@ def calculate_qubit_interaction_subgraphs(self, max_order=2):
521551
522552
Args:
523553
max_order (int): Maximum degree of the nodes in the resulting
524-
graph
554+
graph
525555
526556
Returns:
527557
A list of list of graph nodes corresponding to all the connected
@@ -607,7 +637,7 @@ def remove_command(self, cmd):
607637
# ==============================================================================
608638

609639

610-
class MultiQubitGateManager(object):
640+
class GateManager(object):
611641
"""
612642
Class managing qubit interactions
613643
"""
@@ -689,16 +719,15 @@ def generate_swaps(self,
689719
Args:
690720
mapping (dict): Current mapping
691721
cost_fun (function): Cost function to rank swap candidates
692-
Must accept the following parameters:
693-
- dag (_GatesDAG)
694-
- new_mapping (dict)
695-
- distance_matrix (dict)
696-
- swap_candidate (tuple)
722+
Must accept the following parameters:
723+
- dag (_GatesDAG)
724+
- new_mapping (dict)
725+
- distance_matrix (dict)
726+
- swap_candidate (tuple)
697727
max_steps (int): (optional) Maximum number of swap steps to
698-
attempt before giving up
728+
attempt before giving up
699729
opts (dict): (optional) Extra parameters for cost function call
700730
701-
702731
.. seealso::
703732
:py:meth:`nearest_neighbours_cost_fun`
704733
:py:meth:`look_ahead_parallelism_cost_fun`
@@ -851,7 +880,7 @@ def calculate_qubit_interaction_subgraphs(self, max_order=2):
851880
852881
Args:
853882
max_order (int): Maximum degree of the nodes in the resulting
854-
interaction graph
883+
interaction graph
855884
856885
Returns:
857886
A list of list of graph nodes corresponding to all the connected
@@ -873,11 +902,11 @@ def _generate_one_swap_step(self, mapping, cost_fun, opts):
873902
Args:
874903
mapping (dict): Current mapping
875904
cost_fun (function): Cost function to rank swap candidates
876-
Must accept the following parameters:
877-
- dag (_GatesDAG)
878-
- new_mapping (dict)
879-
- distance_matrix (dict)
880-
- swap_candidate (tuple)
905+
Must accept the following parameters:
906+
- dag (_GatesDAG)
907+
- new_mapping (dict)
908+
- distance_matrix (dict)
909+
- swap_candidate (tuple)
881910
882911
Returns:
883912
Tuple with (logical_id0, backend_id0, logical_id1, backend_id1)

projectq/cengines/_multi_qubit_gate_manager_test.py renamed to projectq/cengines/_gate_manager_test.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from projectq.ops import (Allocate, Command, Deallocate, X, H)
2222
from projectq.types import WeakQubitRef
2323

24-
from projectq.cengines import _multi_qubit_gate_manager as multi
24+
from projectq.cengines import _gate_manager as gatemgr
2525

2626
# ==============================================================================
2727

@@ -31,8 +31,8 @@ def dagnode_to_string(self):
3131
return '{} {}'.format(self.__class__.__name__, tuple(self.logical_ids))
3232

3333

34-
multi._DAGNodeBase.__str__ = dagnode_to_string
35-
multi._DAGNodeBase.__repr__ = dagnode_to_string
34+
gatemgr._DAGNodeBase.__str__ = dagnode_to_string
35+
gatemgr._DAGNodeBase.__repr__ = dagnode_to_string
3636

3737
Command.__repr__ = Command.__str__
3838

@@ -118,17 +118,17 @@ def grid33_graph():
118118

119119
@pytest.fixture
120120
def decay_manager():
121-
return multi.DecayManager(0.001, 5)
121+
return gatemgr.DecayManager(0.001, 5)
122122

123123

124124
@pytest.fixture
125125
def command_dag():
126-
return multi.CommandDAG()
126+
return gatemgr.CommandDAG()
127127

128128

129129
@pytest.fixture
130130
def qubit_manager():
131-
return multi.MultiQubitGateManager(generate_grid_graph(3, 3))
131+
return gatemgr.GateManager(generate_grid_graph(3, 3))
132132

133133

134134
# ==============================================================================
@@ -612,18 +612,18 @@ def test_qubit_manager_valid_and_invalid_graphs(simple_graph):
612612
graph = nx.Graph()
613613
graph.add_nodes_from('abcd')
614614
with pytest.raises(RuntimeError):
615-
multi.MultiQubitGateManager(graph=graph)
615+
gatemgr.GateManager(graph=graph)
616616

617617
graph.add_edges_from([('a', 'b'), ('b', 'c'), ('c', 'd'), ('d', 'a')])
618618
with pytest.raises(RuntimeError):
619-
multi.MultiQubitGateManager(graph=graph)
619+
gatemgr.GateManager(graph=graph)
620620

621621
graph = deepcopy(simple_graph)
622622
graph.remove_edge(0, 1)
623623
with pytest.raises(RuntimeError):
624-
multi.MultiQubitGateManager(graph=graph)
624+
gatemgr.GateManager(graph=graph)
625625

626-
manager = multi.MultiQubitGateManager(graph=simple_graph)
626+
manager = gatemgr.GateManager(graph=simple_graph)
627627
dist = manager.distance_matrix
628628

629629
assert dist[0][1] == 1
@@ -693,7 +693,7 @@ def test_qubit_manager_generate_one_swap_step(qubit_manager):
693693
mapping = {i: i for i in range(9)}
694694
(logical_id0, backend_id0, logical_id1,
695695
backend_id1) = manager._generate_one_swap_step(
696-
mapping, multi.nearest_neighbours_cost_fun, {})
696+
mapping, gatemgr.nearest_neighbours_cost_fun, {})
697697

698698
assert logical_id0 in (0, 8)
699699
if logical_id0 == 0:
@@ -704,7 +704,7 @@ def test_qubit_manager_generate_one_swap_step(qubit_manager):
704704
mapping = {0: 0, 8: 8}
705705
(logical_id0, backend_id0, logical_id1,
706706
backend_id1) = manager._generate_one_swap_step(
707-
mapping, multi.nearest_neighbours_cost_fun, {})
707+
mapping, gatemgr.nearest_neighbours_cost_fun, {})
708708

709709
assert logical_id1 == -1
710710
if logical_id0 == 0:
@@ -721,7 +721,7 @@ def test_qubit_manager_generate_one_swap_step(qubit_manager):
721721
mapping = {i: i for i in range(9)}
722722
(logical_id0, backend_id0, logical_id1,
723723
backend_id1) = manager._generate_one_swap_step(
724-
mapping, multi.nearest_neighbours_cost_fun, {})
724+
mapping, gatemgr.nearest_neighbours_cost_fun, {})
725725

726726
# In this case, the only swap that does not increases the overall distance
727727
# is (0, 1)
@@ -739,7 +739,7 @@ def test_qubit_manager_generate_swaps(qubit_manager):
739739
mapping = {i: i for i in range(9)}
740740

741741
swaps, all_qubits = manager.generate_swaps(
742-
mapping, multi.nearest_neighbours_cost_fun)
742+
mapping, gatemgr.nearest_neighbours_cost_fun)
743743

744744
assert not swaps
745745
assert not all_qubits
@@ -751,14 +751,14 @@ def test_qubit_manager_generate_swaps(qubit_manager):
751751

752752
with pytest.raises(RuntimeError):
753753
manager.generate_swaps(mapping,
754-
multi.nearest_neighbours_cost_fun,
754+
gatemgr.nearest_neighbours_cost_fun,
755755
max_steps=2)
756756

757757
# ----------------------------------
758758

759759
mapping = {i: i for i in range(9)}
760760
swaps, _ = manager.generate_swaps(mapping,
761-
multi.nearest_neighbours_cost_fun)
761+
gatemgr.nearest_neighbours_cost_fun)
762762

763763
# Make sure the original mapping was not modified
764764
assert mapping == {i: i for i in range(9)}
@@ -775,7 +775,7 @@ def test_qubit_manager_generate_swaps(qubit_manager):
775775

776776
mapping = {i: i for i in range(9)}
777777
swaps, _ = manager.generate_swaps(mapping,
778-
multi.look_ahead_parallelism_cost_fun,
778+
gatemgr.look_ahead_parallelism_cost_fun,
779779
opts={'W': 0.5})
780780
reverse_mapping = {v: k for k, v in mapping.items()}
781781
for id0, id1 in swaps:
@@ -794,7 +794,7 @@ def test_qubit_manager_generate_swaps(qubit_manager):
794794
assert manager.size() == 2
795795

796796
swaps, all_qubits = manager.generate_swaps(
797-
mapping, multi.look_ahead_parallelism_cost_fun, opts={
797+
mapping, gatemgr.look_ahead_parallelism_cost_fun, opts={
798798
'W': 0.5,
799799
})
800800

@@ -913,7 +913,7 @@ def test_qubit_manager_generate_swaps_change_mapping(qubit_manager):
913913
mapping = {i: i for i in range(9)}
914914

915915
swaps, all_qubits = qubit_manager.generate_swaps(
916-
mapping, multi.look_ahead_parallelism_cost_fun, {'W': 0.5})
916+
mapping, gatemgr.look_ahead_parallelism_cost_fun, {'W': 0.5})
917917

918918
reverse_mapping = {v: k for k, v in mapping.items()}
919919
for bqb0, bqb1 in swaps:
@@ -939,7 +939,7 @@ def test_qubit_manager_generate_swaps_change_mapping(qubit_manager):
939939
mapping = {i: i for i in range(9)}
940940

941941
swaps, all_qubits = qubit_manager.generate_swaps(
942-
mapping, multi.look_ahead_parallelism_cost_fun, {'W': 0.5})
942+
mapping, gatemgr.look_ahead_parallelism_cost_fun, {'W': 0.5})
943943

944944
reverse_mapping = {v: k for k, v in mapping.items()}
945945
for bqb0, bqb1 in swaps:
@@ -954,7 +954,7 @@ def test_qubit_manager_generate_swaps_change_mapping(qubit_manager):
954954

955955

956956
def test_qubit_manager_str():
957-
qubit_manager = multi.MultiQubitGateManager(generate_grid_graph(3, 3))
957+
qubit_manager = gatemgr.GateManager(generate_grid_graph(3, 3))
958958

959959
qb, allocate_cmds = allocate_all_qubits_cmd(9)
960960
cmd_list = [
@@ -979,7 +979,7 @@ def test_qubit_manager_str():
979979
qubit_manager.get_executable_commands(mapping)
980980

981981
swaps, all_qubits = qubit_manager.generate_swaps(
982-
mapping, multi.look_ahead_parallelism_cost_fun, {'W': 0.5})
982+
mapping, gatemgr.look_ahead_parallelism_cost_fun, {'W': 0.5})
983983

984984
reverse_mapping = {v: k for k, v in mapping.items()}
985985
for bqb0, bqb1 in swaps:

0 commit comments

Comments
 (0)