Skip to content

Commit 7d0ca0d

Browse files
authored
Add cirq.google.optimized_for_xmon() (#647)
- This is an all-in-one method for producing xmon-optimized circuits. For example, it decomposes this: ``` 0: ───iSwap───────────iSwap───M─── │ │ │ 1: ───iSwap───iSwap───iSwap───M─── │ │ 2: ───iSwap───iSwap───iSwap───M─── │ │ │ 3: ───iSwap───────────iSwap───M─── ``` into this: ``` 0: ───W(0.25)^-0.5───@───W(0.25)^0.5────@───W(0.75)^0.5──────────────────────────────────────────@───W(0.25)^-0.5───@───W(0.25)^0.5────M─── │ │ │ │ │ 1: ───W(0.25)^0.5────@───W(0.25)^-0.5───@───W(0.75)^0.5────@───W(0.25)^0.5────@───W(0.75)^-0.5───@───W(0.25)^-0.5───@───W(0.25)^0.5────M─── │ │ │ 2: ───W(0.25)^-0.5───@───W(0.25)^0.5────@───W(0.75)^-0.5───@───W(0.25)^-0.5───@───W(0.75)^0.5────@───W(0.25)^0.5────@───W(0.25)^-0.5───M─── │ │ │ │ │ 3: ───W(0.25)^0.5────@───W(0.25)^-0.5───@───W(0.75)^-0.5─────────────────────────────────────────@───W(0.25)^0.5────@───W(0.25)^-0.5───M─── ``` Obsoletes #488 Obsoletes #644 Obsoletes #645
1 parent 5dc7f35 commit 7d0ca0d

File tree

4 files changed

+122
-3
lines changed

4 files changed

+122
-3
lines changed

cirq/circuits/optimization_pass.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,12 @@ def optimization_at(self,
115115
pass
116116

117117
def optimize_circuit(self, circuit: Circuit):
118-
walls = defaultdict(lambda: 0) # type: Dict[QubitId, int]
118+
frontier = defaultdict(lambda: 0) # type: Dict[QubitId, int]
119119
i = 0
120120
while i < len(circuit): # Note: circuit may mutate as we go.
121121
for op in circuit[i].operations:
122122
# Don't touch stuff inserted by previous optimizations.
123-
if any(walls[q] > i for q in op.qubits):
123+
if any(frontier[q] > i for q in op.qubits):
124124
continue
125125

126126
# Skip if an optimization removed the circuit underneath us.
@@ -138,7 +138,7 @@ def optimize_circuit(self, circuit: Circuit):
138138
circuit.clear_operations_touching(
139139
opt.clear_qubits,
140140
[e for e in range(i, i + opt.clear_span)])
141-
circuit.insert_at_frontier(opt.new_operations, i, walls)
141+
circuit.insert_at_frontier(opt.new_operations, i, frontier)
142142

143143
i += 1
144144

cirq/google/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@
4444
from cirq.google.xmon_gate_extensions import (
4545
xmon_gate_ext,
4646
)
47+
from cirq.google.optimize import (
48+
optimized_for_xmon,
49+
)
4750
from cirq.google.xmon_gates import (
4851
Exp11Gate,
4952
ExpWGate,

cirq/google/optimize.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2018 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+
"""A combination of several optimizations targeting XmonDevice."""
16+
17+
from cirq import circuits
18+
from cirq.google import (
19+
convert_to_xmon_gates,
20+
merge_rotations,
21+
merge_interactions,
22+
eject_full_w,
23+
eject_z,
24+
)
25+
26+
_TOLERANCE = 1e-5
27+
28+
_OPTIMIZERS = [
29+
convert_to_xmon_gates.ConvertToXmonGates(),
30+
31+
merge_interactions.MergeInteractions(tolerance=_TOLERANCE),
32+
merge_rotations.MergeRotations(tolerance=_TOLERANCE),
33+
eject_full_w.EjectFullW(tolerance=_TOLERANCE),
34+
eject_z.EjectZ(tolerance=_TOLERANCE),
35+
circuits.DropNegligible(tolerance=_TOLERANCE),
36+
]
37+
38+
39+
def optimized_for_xmon(circuit: circuits.Circuit) -> circuits.Circuit:
40+
"""Optimizes a circuit with XmonDevice in mind.
41+
42+
Starts by converting the circuit's operations to the xmon gate set, then
43+
begins merging interactions and rotations, ejecting pi-rotations and phasing
44+
operations, dropping unnecessary operations, and pushing operations earlier.
45+
46+
Args:
47+
circuit: The circuit to optimize.
48+
49+
Returns:
50+
The optimized circuit.
51+
"""
52+
copy = circuit.copy()
53+
for optimizer in _OPTIMIZERS:
54+
optimizer.optimize_circuit(copy)
55+
56+
return circuits.Circuit().from_ops(
57+
copy.all_operations(),
58+
strategy=circuits.InsertStrategy.EARLIEST)

cirq/google/optimize_test.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2018 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+
17+
import cirq
18+
import cirq.google as cg
19+
20+
from cirq.testing import (
21+
assert_circuits_with_terminal_measurements_are_equivalent,
22+
)
23+
24+
25+
@pytest.mark.parametrize('n,d', [
26+
(3, 2),
27+
(4, 3),
28+
(4, 4),
29+
(5, 4),
30+
(22, 4),
31+
])
32+
def test_swap_field(n: int, d: int):
33+
before = cirq.Circuit.from_ops(
34+
cirq.ISWAP(cirq.LineQubit(j), cirq.LineQubit(j + 1))
35+
for i in range(d)
36+
for j in range(i % 2, n - 1, 2)
37+
)
38+
before.append(cirq.measure(*before.all_qubits()))
39+
40+
after = cg.optimized_for_xmon(before)
41+
42+
assert len(after) == d*4 + 2
43+
if n <= 5:
44+
assert_circuits_with_terminal_measurements_are_equivalent(
45+
before, after, atol=1e-4)
46+
47+
48+
def test_ccz():
49+
before = cirq.Circuit.from_ops(
50+
cirq.CCZ(cirq.GridQubit(5, 5),
51+
cirq.GridQubit(5, 6),
52+
cirq.GridQubit(5, 7)))
53+
54+
after = cg.optimized_for_xmon(before)
55+
56+
assert len(after) <= 22
57+
assert_circuits_with_terminal_measurements_are_equivalent(
58+
before, after, atol=1e-4)

0 commit comments

Comments
 (0)