|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | | -from cirq import testing |
16 | | -from cirq import circuits |
17 | | -from cirq import ops |
18 | | -from cirq.google import ExpZGate, MergeInteractions, MergeRotations |
19 | | -from cirq.value import Symbol |
| 15 | +import cirq |
| 16 | +import cirq.google as cg |
20 | 17 |
|
21 | 18 |
|
22 | | -def assert_optimizes(before, after): |
23 | | - opt = MergeInteractions() |
24 | | - opt.optimize_circuit(before) |
| 19 | +def assert_optimizes(before: cirq.Circuit, expected: cirq.Circuit): |
| 20 | + actual = cirq.Circuit(before) |
| 21 | + opt = cg.MergeInteractions() |
| 22 | + opt.optimize_circuit(actual) |
25 | 23 |
|
26 | 24 | # Ignore differences that would be caught by follow-up optimizations. |
27 | 25 | followup_optimizations = [ |
28 | | - MergeRotations(), |
29 | | - circuits.DropNegligible(), |
30 | | - circuits.DropEmptyMoments() |
| 26 | + cg.MergeRotations(), |
| 27 | + cg.EjectFullW(), |
| 28 | + cg.EjectZ(), |
| 29 | + cirq.DropNegligible(), |
| 30 | + cirq.DropEmptyMoments() |
31 | 31 | ] |
32 | 32 | for post in followup_optimizations: |
33 | | - post.optimize_circuit(before) |
34 | | - post.optimize_circuit(after) |
| 33 | + post.optimize_circuit(actual) |
| 34 | + post.optimize_circuit(expected) |
35 | 35 |
|
36 | | - if before != after: |
| 36 | + if actual != expected: |
37 | 37 | # coverage: ignore |
38 | 38 | print('ACTUAL') |
39 | | - print(before) |
| 39 | + print(actual) |
40 | 40 | print('EXPECTED') |
41 | | - print(after) |
42 | | - assert before == after |
| 41 | + print(expected) |
| 42 | + assert actual == expected |
43 | 43 |
|
44 | 44 |
|
45 | 45 | def assert_optimization_not_broken(circuit): |
46 | 46 | """Check that the unitary matrix for the input circuit is the same (up to |
47 | 47 | global phase and rounding error) as the unitary matrix of the optimized |
48 | 48 | circuit.""" |
49 | 49 | u_before = circuit.to_unitary_matrix() |
50 | | - MergeInteractions().optimize_circuit(circuit) |
| 50 | + cg.MergeInteractions().optimize_circuit(circuit) |
51 | 51 | u_after = circuit.to_unitary_matrix() |
52 | 52 |
|
53 | | - testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8) |
| 53 | + cirq.testing.assert_allclose_up_to_global_phase( |
| 54 | + u_before, u_after, atol=1e-8) |
54 | 55 |
|
55 | 56 |
|
56 | 57 | def test_clears_paired_cnot(): |
57 | | - q0 = ops.QubitId() |
58 | | - q1 = ops.QubitId() |
| 58 | + a, b = cirq.LineQubit.range(2) |
59 | 59 | assert_optimizes( |
60 | | - before=circuits.Circuit([ |
61 | | - circuits.Moment([ops.CNOT(q0, q1)]), |
62 | | - circuits.Moment([ops.CNOT(q0, q1)]), |
| 60 | + before=cirq.Circuit([ |
| 61 | + cirq.Moment([cirq.CNOT(a, b)]), |
| 62 | + cirq.Moment([cirq.CNOT(a, b)]), |
63 | 63 | ]), |
64 | | - after=circuits.Circuit()) |
| 64 | + expected=cirq.Circuit()) |
65 | 65 |
|
66 | 66 |
|
67 | 67 | def test_ignores_czs_separated_by_parameterized(): |
68 | | - q0 = ops.QubitId() |
69 | | - q1 = ops.QubitId() |
| 68 | + a, b = cirq.LineQubit.range(2) |
70 | 69 | assert_optimizes( |
71 | | - before=circuits.Circuit([ |
72 | | - circuits.Moment([ops.CZ(q0, q1)]), |
73 | | - circuits.Moment([ExpZGate( |
74 | | - half_turns=Symbol('boo'))(q0)]), |
75 | | - circuits.Moment([ops.CZ(q0, q1)]), |
| 70 | + before=cirq.Circuit([ |
| 71 | + cirq.Moment([cirq.CZ(a, b)]), |
| 72 | + cirq.Moment([cg.ExpZGate( |
| 73 | + half_turns=cirq.Symbol('boo'))(a)]), |
| 74 | + cirq.Moment([cirq.CZ(a, b)]), |
76 | 75 | ]), |
77 | | - after=circuits.Circuit([ |
78 | | - circuits.Moment([ops.CZ(q0, q1)]), |
79 | | - circuits.Moment([ExpZGate( |
80 | | - half_turns=Symbol('boo'))(q0)]), |
81 | | - circuits.Moment([ops.CZ(q0, q1)]), |
| 76 | + expected=cirq.Circuit([ |
| 77 | + cirq.Moment([cirq.CZ(a, b)]), |
| 78 | + cirq.Moment([cg.ExpZGate( |
| 79 | + half_turns=cirq.Symbol('boo'))(a)]), |
| 80 | + cirq.Moment([cirq.CZ(a, b)]), |
82 | 81 | ])) |
83 | 82 |
|
84 | 83 |
|
85 | 84 | def test_ignores_czs_separated_by_outer_cz(): |
86 | | - q00 = ops.QubitId() |
87 | | - q01 = ops.QubitId() |
88 | | - q10 = ops.QubitId() |
| 85 | + q00 = cirq.GridQubit(0, 0) |
| 86 | + q01 = cirq.GridQubit(0, 1) |
| 87 | + q10 = cirq.GridQubit(1, 0) |
89 | 88 | assert_optimizes( |
90 | | - before=circuits.Circuit([ |
91 | | - circuits.Moment([ops.CZ(q00, q01)]), |
92 | | - circuits.Moment([ops.CZ(q00, q10)]), |
93 | | - circuits.Moment([ops.CZ(q00, q01)]), |
| 89 | + before=cirq.Circuit([ |
| 90 | + cirq.Moment([cirq.CZ(q00, q01)]), |
| 91 | + cirq.Moment([cirq.CZ(q00, q10)]), |
| 92 | + cirq.Moment([cirq.CZ(q00, q01)]), |
94 | 93 | ]), |
95 | | - after=circuits.Circuit([ |
96 | | - circuits.Moment([ops.CZ(q00, q01)]), |
97 | | - circuits.Moment([ops.CZ(q00, q10)]), |
98 | | - circuits.Moment([ops.CZ(q00, q01)]), |
| 94 | + expected=cirq.Circuit([ |
| 95 | + cirq.Moment([cirq.CZ(q00, q01)]), |
| 96 | + cirq.Moment([cirq.CZ(q00, q10)]), |
| 97 | + cirq.Moment([cirq.CZ(q00, q01)]), |
99 | 98 | ])) |
100 | 99 |
|
101 | 100 |
|
102 | 101 | def test_cnots_separated_by_single_gates_correct(): |
103 | | - q0 = ops.QubitId() |
104 | | - q1 = ops.QubitId() |
| 102 | + a, b = cirq.LineQubit.range(2) |
105 | 103 | assert_optimization_not_broken( |
106 | | - circuits.Circuit.from_ops( |
107 | | - ops.CNOT(q0, q1), |
108 | | - ops.H(q1), |
109 | | - ops.CNOT(q0, q1), |
| 104 | + cirq.Circuit.from_ops( |
| 105 | + cirq.CNOT(a, b), |
| 106 | + cirq.H(b), |
| 107 | + cirq.CNOT(a, b), |
110 | 108 | )) |
111 | 109 |
|
112 | 110 |
|
113 | 111 | def test_czs_separated_by_single_gates_correct(): |
114 | | - q0 = ops.QubitId() |
115 | | - q1 = ops.QubitId() |
| 112 | + a, b = cirq.LineQubit.range(2) |
116 | 113 | assert_optimization_not_broken( |
117 | | - circuits.Circuit.from_ops( |
118 | | - ops.CZ(q0, q1), |
119 | | - ops.X(q1), |
120 | | - ops.X(q1), |
121 | | - ops.X(q1), |
122 | | - ops.CZ(q0, q1), |
| 114 | + cirq.Circuit.from_ops( |
| 115 | + cirq.CZ(a, b), |
| 116 | + cirq.X(b), |
| 117 | + cirq.X(b), |
| 118 | + cirq.X(b), |
| 119 | + cirq.CZ(a, b), |
123 | 120 | )) |
124 | 121 |
|
125 | 122 |
|
126 | 123 | def test_inefficient_circuit_correct(): |
127 | 124 | t = 0.1 |
128 | 125 | v = 0.11 |
129 | | - q0 = ops.QubitId() |
130 | | - q1 = ops.QubitId() |
| 126 | + a, b = cirq.LineQubit.range(2) |
131 | 127 | assert_optimization_not_broken( |
132 | | - circuits.Circuit.from_ops( |
133 | | - ops.H(q1), |
134 | | - ops.CNOT(q0, q1), |
135 | | - ops.H(q1), |
136 | | - ops.CNOT(q0, q1), |
137 | | - ops.CNOT(q1, q0), |
138 | | - ops.H(q0), |
139 | | - ops.CNOT(q0, q1), |
140 | | - ops.Z(q0)**t, ops.Z(q1)**-t, |
141 | | - ops.CNOT(q0, q1), |
142 | | - ops.H(q0), ops.Z(q1)**v, |
143 | | - ops.CNOT(q0, q1), |
144 | | - ops.Z(q0)**-v, ops.Z(q1)**-v, |
| 128 | + cirq.Circuit.from_ops( |
| 129 | + cirq.H(b), |
| 130 | + cirq.CNOT(a, b), |
| 131 | + cirq.H(b), |
| 132 | + cirq.CNOT(a, b), |
| 133 | + cirq.CNOT(b, a), |
| 134 | + cirq.H(a), |
| 135 | + cirq.CNOT(a, b), |
| 136 | + cirq.Z(a)**t, cirq.Z(b)**-t, |
| 137 | + cirq.CNOT(a, b), |
| 138 | + cirq.H(a), cirq.Z(b)**v, |
| 139 | + cirq.CNOT(a, b), |
| 140 | + cirq.Z(a)**-v, cirq.Z(b)**-v, |
145 | 141 | )) |
| 142 | + |
| 143 | + |
| 144 | +def test_optimizes_single_iswap(): |
| 145 | + a, b = cirq.LineQubit.range(2) |
| 146 | + c = cirq.Circuit.from_ops(cirq.ISWAP(a, b)) |
| 147 | + assert_optimization_not_broken(c) |
| 148 | + cg.MergeInteractions().optimize_circuit(c) |
| 149 | + assert len([1 for op in c.all_operations() if len(op.qubits) == 2]) == 2 |
| 150 | + assert all(cg.XmonGate.is_xmon_op(op) |
| 151 | + for op in c.all_operations()) |
0 commit comments