Skip to content

Commit 9f8ef24

Browse files
ammareltiganirht
authored andcommitted
Adds AbstractInitialMapper base class and IdentityInitialMapper (quantumlib#5829)
* added abstract initial mapper and identity initial mapper * added __str__ and __repr__ for MappingManager * minor bug * made MappingManager not serializable * removed unused import * addressed comments * fixed bug with edges not being sorted for graph equality testing * fixed bug with digraphs repr method in MappingManager and added test for it * rebase * minor lint fix * addressed comments * addressed some comments * changed interface for AbstractInitialMapper * made MappingManager serializable * removed print statements * ready for merging * nit * temp * fix lint * removed serialization * removed unused imports * addressed comments and made HardCodedInitialMapper not serializable * fixed nit * fixed raises docstring * forgot to add import statement * import bug * removed debug print
1 parent ad3f649 commit 9f8ef24

File tree

6 files changed

+115
-1
lines changed

6 files changed

+115
-1
lines changed

Diff for: cirq-core/cirq/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@
326326
)
327327

328328
from cirq.transformers import (
329+
AbstractInitialMapper,
329330
align_left,
330331
align_right,
331332
CompilationTargetGateset,
@@ -345,6 +346,7 @@
345346
eject_phased_paulis,
346347
eject_z,
347348
expand_composite,
349+
HardCodedInitialMapper,
348350
is_negligible_turn,
349351
MappingManager,
350352
map_moments,

Diff for: cirq-core/cirq/protocols/json_test_data/spec.py

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
'TransformerLogger',
8585
'TransformerContext',
8686
# Routing utilities
87+
'HardCodedInitialMapper',
8788
'MappingManager',
8889
# global objects
8990
'CONTROL_TAG',

Diff for: cirq-core/cirq/transformers/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
two_qubit_gate_product_tabulation,
4545
)
4646

47-
from cirq.transformers.routing import MappingManager
47+
from cirq.transformers.routing import AbstractInitialMapper, HardCodedInitialMapper, MappingManager
4848

4949
from cirq.transformers.target_gatesets import (
5050
create_transformer_with_kwargs,

Diff for: cirq-core/cirq/transformers/routing/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414

1515
"""Routing utilities in Cirq."""
1616

17+
from cirq.transformers.routing.initial_mapper import AbstractInitialMapper, HardCodedInitialMapper
1718
from cirq.transformers.routing.mapping_manager import MappingManager
+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Copyright 2022 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from typing import TYPE_CHECKING, Dict
16+
import abc
17+
18+
from cirq import value
19+
20+
if TYPE_CHECKING:
21+
import cirq
22+
23+
24+
class AbstractInitialMapper(metaclass=abc.ABCMeta):
25+
"""Base class for creating custom initial mapping strategies.
26+
27+
An initial mapping strategy is a placement strategy that places logical qubit variables in an
28+
input circuit onto physical qubits that correspond to a specified device. This placment can be
29+
thought of as a mapping k -> m[k] where k is a logical qubit and m[k] is the physical qubit it
30+
is mapped to. Any initial mapping strategy must satisfy two constraints:
31+
1. all logical qubits must be placed on the device if the number of logical qubits is <=
32+
than the number of physical qubits.
33+
2. if two logical qubits interact (i.e. there exists a 2-qubit operation on them) at any
34+
point in the input circuit, then they must lie in the same connected components of the
35+
device graph induced on the physical qubits in the initial mapping.
36+
37+
"""
38+
39+
@abc.abstractmethod
40+
def initial_mapping(self, circuit: 'cirq.AbstractCircuit') -> Dict['cirq.Qid', 'cirq.Qid']:
41+
"""Maps the logical qubits of a circuit onto physical qubits on a device.
42+
43+
Args:
44+
circuit: the input circuit with logical qubits.
45+
46+
Returns:
47+
qubit_map: the initial mapping of logical qubits to physical qubits.
48+
"""
49+
50+
51+
@value.value_equality
52+
class HardCodedInitialMapper(AbstractInitialMapper):
53+
"""Initial Mapper class takes a hard-coded mapping and returns it."""
54+
55+
def __init__(self, _map: Dict['cirq.Qid', 'cirq.Qid']) -> None:
56+
self._map = _map
57+
58+
def initial_mapping(self, circuit: 'cirq.AbstractCircuit') -> Dict['cirq.Qid', 'cirq.Qid']:
59+
"""Returns the hard-coded initial mapping.
60+
61+
Args:
62+
circuit: the input circuit with logical qubits.
63+
64+
Returns:
65+
the hard-codded initial mapping.
66+
67+
Raises:
68+
ValueError: if the qubits in circuit are not a subset of the qubit keys in the mapping.
69+
"""
70+
if not circuit.all_qubits().issubset(set(self._map.keys())):
71+
raise ValueError("The qubits in circuit must be a subset of the keys in the mapping")
72+
return self._map
73+
74+
def _value_equality_values_(self):
75+
return tuple(sorted(self._map.items()))
76+
77+
def __repr__(self) -> str:
78+
return f'cirq.HardCodedInitialMapper({self._map})'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2022 The Cirq Developers
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import pytest
16+
import cirq
17+
18+
19+
def test_hardcoded_initial_mapper():
20+
input_map = {cirq.NamedQubit(str(i)): cirq.NamedQubit(str(-i)) for i in range(1, 6)}
21+
circuit = cirq.Circuit([cirq.H(cirq.NamedQubit(str(i))) for i in range(1, 6)])
22+
initial_mapper = cirq.HardCodedInitialMapper(input_map)
23+
24+
assert input_map == initial_mapper.initial_mapping(circuit)
25+
assert str(initial_mapper) == f'cirq.HardCodedInitialMapper({input_map})'
26+
cirq.testing.assert_equivalent_repr(initial_mapper)
27+
28+
circuit.append(cirq.H(cirq.NamedQubit(str(6))))
29+
with pytest.raises(
30+
ValueError, match="The qubits in circuit must be a subset of the keys in the mapping"
31+
):
32+
initial_mapper.initial_mapping(circuit)

0 commit comments

Comments
 (0)