cirq-core 1.4.0.dev20240402234712__py3-none-any.whl → 1.4.0.dev20240403011731__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/_version.py +1 -1
- cirq/sim/state_vector_simulator.py +11 -1
- cirq/transformers/__init__.py +13 -0
- cirq/transformers/gauge_compiling/__init__.py +26 -0
- cirq/transformers/gauge_compiling/cz_gauge.py +46 -0
- cirq/transformers/gauge_compiling/cz_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/gauge_compiling.py +178 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test.py +41 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +83 -0
- cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py +52 -0
- cirq/transformers/gauge_compiling/iswap_gauge.py +105 -0
- cirq/transformers/gauge_compiling/iswap_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge.py +33 -0
- cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +29 -0
- cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py +23 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py +94 -0
- cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py +22 -0
- {cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/METADATA +2 -1
- {cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/RECORD +23 -8
- {cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/LICENSE +0 -0
- {cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/WHEEL +0 -0
- {cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.4.0.
|
|
1
|
+
__version__ = "1.4.0.dev20240403011731"
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import abc
|
|
17
17
|
from functools import cached_property
|
|
18
18
|
from typing import Any, Dict, Iterator, Sequence, Type, TYPE_CHECKING, Generic, TypeVar
|
|
19
|
+
import warnings
|
|
19
20
|
|
|
20
21
|
import numpy as np
|
|
21
22
|
|
|
@@ -124,7 +125,16 @@ class StateVectorTrialResult(
|
|
|
124
125
|
|
|
125
126
|
@cached_property
|
|
126
127
|
def final_state_vector(self) -> np.ndarray:
|
|
127
|
-
|
|
128
|
+
ret = self._get_merged_sim_state().target_tensor.reshape(-1)
|
|
129
|
+
norm = np.linalg.norm(ret)
|
|
130
|
+
if abs(norm - 1) > np.sqrt(np.finfo(ret.dtype).eps):
|
|
131
|
+
warnings.warn(
|
|
132
|
+
f"final state vector's {norm=} is too far from 1,"
|
|
133
|
+
f" {abs(norm-1)} > {np.sqrt(np.finfo(ret.dtype).eps)}."
|
|
134
|
+
"skipping renormalization"
|
|
135
|
+
)
|
|
136
|
+
return ret
|
|
137
|
+
return ret / norm
|
|
128
138
|
|
|
129
139
|
def state_vector(self, copy: bool = False) -> np.ndarray:
|
|
130
140
|
"""Return the state vector at the end of the computation.
|
cirq/transformers/__init__.py
CHANGED
|
@@ -119,3 +119,16 @@ from cirq.transformers.transformer_primitives import (
|
|
|
119
119
|
unroll_circuit_op_greedy_earliest,
|
|
120
120
|
unroll_circuit_op_greedy_frontier,
|
|
121
121
|
)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
from cirq.transformers.gauge_compiling import (
|
|
125
|
+
CZGaugeTransformer,
|
|
126
|
+
ConstantGauge,
|
|
127
|
+
Gauge,
|
|
128
|
+
GaugeSelector,
|
|
129
|
+
GaugeTransformer,
|
|
130
|
+
ISWAPGaugeTransformer,
|
|
131
|
+
SpinInversionGaugeTransformer,
|
|
132
|
+
SqrtCZGaugeTransformer,
|
|
133
|
+
SqrtISWAPGaugeTransformer,
|
|
134
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
17
|
+
ConstantGauge,
|
|
18
|
+
Gauge,
|
|
19
|
+
GaugeSelector,
|
|
20
|
+
GaugeTransformer,
|
|
21
|
+
)
|
|
22
|
+
from cirq.transformers.gauge_compiling.sqrt_cz_gauge import SqrtCZGaugeTransformer
|
|
23
|
+
from cirq.transformers.gauge_compiling.spin_inversion_gauge import SpinInversionGaugeTransformer
|
|
24
|
+
from cirq.transformers.gauge_compiling.cz_gauge import CZGaugeTransformer
|
|
25
|
+
from cirq.transformers.gauge_compiling.iswap_gauge import ISWAPGaugeTransformer
|
|
26
|
+
from cirq.transformers.gauge_compiling.sqrt_iswap_gauge import SqrtISWAPGaugeTransformer
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2024 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 Gauge Transformer for the CZ gate."""
|
|
16
|
+
|
|
17
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
18
|
+
GaugeTransformer,
|
|
19
|
+
GaugeSelector,
|
|
20
|
+
ConstantGauge,
|
|
21
|
+
)
|
|
22
|
+
from cirq.ops.common_gates import CZ
|
|
23
|
+
from cirq import ops
|
|
24
|
+
|
|
25
|
+
CZGaugeSelector = GaugeSelector(
|
|
26
|
+
gauges=[
|
|
27
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.I, post_q0=ops.I, post_q1=ops.I),
|
|
28
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.X, post_q0=ops.Z, post_q1=ops.X),
|
|
29
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.Y, post_q0=ops.Z, post_q1=ops.Y),
|
|
30
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.I, pre_q1=ops.Z, post_q0=ops.I, post_q1=ops.Z),
|
|
31
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.I, post_q0=ops.X, post_q1=ops.Z),
|
|
32
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.X, post_q0=ops.Y, post_q1=ops.Y),
|
|
33
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.Y, post_q0=ops.Y, post_q1=ops.X),
|
|
34
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.X, pre_q1=ops.Z, post_q0=ops.X, post_q1=ops.I),
|
|
35
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.I, post_q0=ops.Y, post_q1=ops.Z),
|
|
36
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.X, post_q0=ops.X, post_q1=ops.Y),
|
|
37
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.Y, post_q0=ops.X, post_q1=ops.X),
|
|
38
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Y, pre_q1=ops.Z, post_q0=ops.Y, post_q1=ops.I),
|
|
39
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.I, post_q0=ops.Z, post_q1=ops.I),
|
|
40
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.X, post_q0=ops.I, post_q1=ops.X),
|
|
41
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.Y, post_q0=ops.I, post_q1=ops.Y),
|
|
42
|
+
ConstantGauge(two_qubit_gate=CZ, pre_q0=ops.Z, pre_q1=ops.Z, post_q0=ops.Z, post_q1=ops.Z),
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
CZGaugeTransformer = GaugeTransformer(target=CZ, gauge_selector=CZGaugeSelector)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
import cirq
|
|
17
|
+
from cirq.transformers.gauge_compiling import CZGaugeTransformer
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestCZGauge(GaugeTester):
|
|
22
|
+
two_qubit_gate = cirq.CZ
|
|
23
|
+
gauge_transformer = CZGaugeTransformer
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
"""Creates the abstraction for gauge compiling as a cirq transformer."""
|
|
16
|
+
|
|
17
|
+
from typing import Callable, Tuple, Optional, Sequence, Union, List
|
|
18
|
+
import abc
|
|
19
|
+
import itertools
|
|
20
|
+
import functools
|
|
21
|
+
|
|
22
|
+
from dataclasses import dataclass
|
|
23
|
+
from attrs import frozen, field
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
26
|
+
from cirq.transformers import transformer_api
|
|
27
|
+
from cirq import ops, circuits
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Gauge(abc.ABC):
|
|
31
|
+
"""A gauge replaces a two qubit gate with an equivalent subcircuit.
|
|
32
|
+
0: pre_q0───────two_qubit_gate───────post_q0
|
|
33
|
+
|
|
|
34
|
+
1: pre_q1───────two_qubit_gate───────post_q1
|
|
35
|
+
|
|
36
|
+
The Gauge class in general represents a family of closely related gauges
|
|
37
|
+
(e.g. random z-rotations); Use `sample` method to get a specific gauge.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def weight(self) -> float:
|
|
41
|
+
"""Returns the relative frequency for selecting this gauge."""
|
|
42
|
+
return 1.0
|
|
43
|
+
|
|
44
|
+
@abc.abstractmethod
|
|
45
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> "ConstantGauge":
|
|
46
|
+
"""Returns a ConstantGauge sampled from a family of gauges.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
gate: The two qubit gate to replace.
|
|
50
|
+
prng: A numpy random number generator.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
A ConstantGauge.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@frozen
|
|
58
|
+
class ConstantGauge(Gauge):
|
|
59
|
+
"""A gauge that replaces a two qubit gate with a constant gauge."""
|
|
60
|
+
|
|
61
|
+
two_qubit_gate: ops.Gate
|
|
62
|
+
pre_q0: Tuple[ops.Gate, ...] = field(
|
|
63
|
+
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
64
|
+
)
|
|
65
|
+
pre_q1: Tuple[ops.Gate, ...] = field(
|
|
66
|
+
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
67
|
+
)
|
|
68
|
+
post_q0: Tuple[ops.Gate, ...] = field(
|
|
69
|
+
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
70
|
+
)
|
|
71
|
+
post_q1: Tuple[ops.Gate, ...] = field(
|
|
72
|
+
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> "ConstantGauge":
|
|
76
|
+
return self
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def pre(self) -> Tuple[Tuple[ops.Gate, ...], Tuple[ops.Gate, ...]]:
|
|
80
|
+
"""A tuple (ops to apply to q0, ops to apply to q1)."""
|
|
81
|
+
return self.pre_q0, self.pre_q1
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def post(self) -> Tuple[Tuple[ops.Gate, ...], Tuple[ops.Gate, ...]]:
|
|
85
|
+
"""A tuple (ops to apply to q0, ops to apply to q1)."""
|
|
86
|
+
return self.post_q0, self.post_q1
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _select(choices: Sequence[Gauge], probabilites: np.ndarray, prng: np.random.Generator) -> Gauge:
|
|
90
|
+
return choices[prng.choice(len(choices), p=probabilites)]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass(frozen=True)
|
|
94
|
+
class GaugeSelector:
|
|
95
|
+
"""Samples a gauge from a list of gauges."""
|
|
96
|
+
|
|
97
|
+
gauges: Sequence[Gauge]
|
|
98
|
+
|
|
99
|
+
@functools.cached_property
|
|
100
|
+
def _weights(self) -> np.ndarray:
|
|
101
|
+
weights = np.array([g.weight() for g in self.gauges])
|
|
102
|
+
return weights / np.sum(weights)
|
|
103
|
+
|
|
104
|
+
def __call__(self, prng: np.random.Generator) -> Gauge:
|
|
105
|
+
"""Randomly selects a gauge with probability proportional to its weight."""
|
|
106
|
+
return _select(self.gauges, self._weights, prng)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@transformer_api.transformer
|
|
110
|
+
class GaugeTransformer:
|
|
111
|
+
def __init__(
|
|
112
|
+
self,
|
|
113
|
+
# target can be either a specific gate, gatefamily or gateset
|
|
114
|
+
# which allows matching parametric gates.
|
|
115
|
+
target: Union[ops.Gate, ops.Gateset, ops.GateFamily],
|
|
116
|
+
gauge_selector: Callable[[np.random.Generator], Gauge],
|
|
117
|
+
) -> None:
|
|
118
|
+
"""Constructs a GaugeTransformer.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
target: Target two-qubit gate, a gate-family or a gate-set of two-qubit gates.
|
|
122
|
+
gauge_selector: A callable that takes a numpy random number generator
|
|
123
|
+
as an argument and returns a Gauge.
|
|
124
|
+
"""
|
|
125
|
+
self.target = ops.GateFamily(target) if isinstance(target, ops.Gate) else target
|
|
126
|
+
self.gauge_selector = gauge_selector
|
|
127
|
+
|
|
128
|
+
def __call__(
|
|
129
|
+
self,
|
|
130
|
+
circuit: circuits.AbstractCircuit,
|
|
131
|
+
*,
|
|
132
|
+
context: Optional[transformer_api.TransformerContext] = None,
|
|
133
|
+
prng: Optional[np.random.Generator] = None,
|
|
134
|
+
) -> circuits.AbstractCircuit:
|
|
135
|
+
rng = np.random.default_rng() if prng is None else prng
|
|
136
|
+
if context is None:
|
|
137
|
+
context = transformer_api.TransformerContext(deep=False)
|
|
138
|
+
if context.deep:
|
|
139
|
+
raise ValueError('GaugeTransformer cannot be used with deep=True')
|
|
140
|
+
new_moments = []
|
|
141
|
+
left: List[List[ops.Operation]] = []
|
|
142
|
+
right: List[List[ops.Operation]] = []
|
|
143
|
+
for moment in circuit:
|
|
144
|
+
left.clear()
|
|
145
|
+
right.clear()
|
|
146
|
+
center: List[ops.Operation] = []
|
|
147
|
+
for op in moment:
|
|
148
|
+
if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
|
|
149
|
+
context.tags_to_ignore
|
|
150
|
+
):
|
|
151
|
+
center.append(op)
|
|
152
|
+
continue
|
|
153
|
+
if op.gate is not None and len(op.qubits) == 2 and op in self.target:
|
|
154
|
+
gauge = self.gauge_selector(rng).sample(op.gate, rng)
|
|
155
|
+
q0, q1 = op.qubits
|
|
156
|
+
left.extend([g(q) for g in gs] for q, gs in zip(op.qubits, gauge.pre))
|
|
157
|
+
center.append(gauge.two_qubit_gate(q0, q1))
|
|
158
|
+
right.extend([g(q) for g in gs] for q, gs in zip(op.qubits, gauge.post))
|
|
159
|
+
else:
|
|
160
|
+
center.append(op)
|
|
161
|
+
if left:
|
|
162
|
+
new_moments.extend(_build_moments(left))
|
|
163
|
+
new_moments.append(center)
|
|
164
|
+
if right:
|
|
165
|
+
new_moments.extend(_build_moments(right))
|
|
166
|
+
return circuits.Circuit.from_moments(*new_moments)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[ops.Operation]]:
|
|
170
|
+
"""Builds moments from a list of operations grouped by qubits.
|
|
171
|
+
|
|
172
|
+
Returns a list of moments from a list whose ith element is a list of operations applied
|
|
173
|
+
to qubit i.
|
|
174
|
+
"""
|
|
175
|
+
moments = []
|
|
176
|
+
for moment in itertools.zip_longest(*operation_by_qubits):
|
|
177
|
+
moments.append([op for op in moment if op is not None])
|
|
178
|
+
return moments
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2024 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 numpy as np
|
|
17
|
+
import cirq
|
|
18
|
+
from cirq.transformers.gauge_compiling import GaugeTransformer, CZGaugeTransformer
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_deep_transformation_not_supported():
|
|
22
|
+
|
|
23
|
+
with pytest.raises(ValueError, match="cannot be used with deep=True"):
|
|
24
|
+
_ = GaugeTransformer(target=cirq.CZ, gauge_selector=lambda _: None)(
|
|
25
|
+
cirq.Circuit(), context=cirq.TransformerContext(deep=True)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_ignore_tags():
|
|
30
|
+
c = cirq.Circuit(cirq.CZ(*cirq.LineQubit.range(2)).with_tags('foo'))
|
|
31
|
+
assert c == CZGaugeTransformer(c, context=cirq.TransformerContext(tags_to_ignore={"foo"}))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_target_can_be_gateset():
|
|
35
|
+
qs = cirq.LineQubit.range(2)
|
|
36
|
+
c = cirq.Circuit(cirq.CZ(*qs))
|
|
37
|
+
transformer = GaugeTransformer(
|
|
38
|
+
target=cirq.Gateset(cirq.CZ), gauge_selector=CZGaugeTransformer.gauge_selector
|
|
39
|
+
)
|
|
40
|
+
want = cirq.Circuit(cirq.Y.on_each(qs), cirq.CZ(*qs), cirq.X.on_each(qs))
|
|
41
|
+
assert transformer(c, prng=np.random.default_rng(0)) == want
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
from unittest.mock import patch
|
|
17
|
+
import pytest
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
import cirq
|
|
22
|
+
from cirq.transformers.gauge_compiling import GaugeTransformer, GaugeSelector
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GaugeTester:
|
|
26
|
+
|
|
27
|
+
two_qubit_gate: cirq.Gate
|
|
28
|
+
gauge_transformer: GaugeTransformer
|
|
29
|
+
must_fail: bool = False
|
|
30
|
+
|
|
31
|
+
@pytest.mark.parametrize(
|
|
32
|
+
['generation_seed', 'transformation_seed'],
|
|
33
|
+
np.random.RandomState(0).randint(2**31, size=(5, 2)).tolist(),
|
|
34
|
+
)
|
|
35
|
+
def test_gauge_transformer(self, generation_seed, transformation_seed):
|
|
36
|
+
c = cirq.Circuit()
|
|
37
|
+
while not any(op.gate == self.two_qubit_gate for op in c.all_operations()):
|
|
38
|
+
c = cirq.testing.random_circuit(
|
|
39
|
+
qubits=3,
|
|
40
|
+
n_moments=3,
|
|
41
|
+
op_density=1,
|
|
42
|
+
gate_domain={self.two_qubit_gate: 2, cirq.X: 1, cirq.Y: 1, cirq.H: 1, cirq.Z: 1},
|
|
43
|
+
random_state=generation_seed,
|
|
44
|
+
)
|
|
45
|
+
generation_seed += 1
|
|
46
|
+
nc = self.gauge_transformer(c, prng=np.random.default_rng(transformation_seed))
|
|
47
|
+
if self.must_fail:
|
|
48
|
+
with pytest.raises(AssertionError):
|
|
49
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
50
|
+
nc, c, qubit_map={q: q for q in c.all_qubits()}
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
54
|
+
nc, c, qubit_map={q: q for q in c.all_qubits()}
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
@patch('cirq.transformers.gauge_compiling.gauge_compiling._select', autospec=True)
|
|
58
|
+
@pytest.mark.parametrize('seed', range(5))
|
|
59
|
+
def test_all_gauges(self, mock_select, seed):
|
|
60
|
+
assert isinstance(
|
|
61
|
+
self.gauge_transformer.gauge_selector, GaugeSelector
|
|
62
|
+
), 'When using a custom selector, please override this method to properly test all gauges'
|
|
63
|
+
c = cirq.Circuit(self.two_qubit_gate(cirq.LineQubit(0), cirq.LineQubit(1)))
|
|
64
|
+
prng = np.random.default_rng(seed)
|
|
65
|
+
for gauge in self.gauge_transformer.gauge_selector.gauges:
|
|
66
|
+
mock_select.return_value = gauge
|
|
67
|
+
assert self.gauge_transformer.gauge_selector(prng) == gauge
|
|
68
|
+
nc = self.gauge_transformer(c, prng=prng)
|
|
69
|
+
|
|
70
|
+
if self.must_fail:
|
|
71
|
+
with pytest.raises(AssertionError):
|
|
72
|
+
_check_equivalent_with_error_message(c, nc, gauge)
|
|
73
|
+
else:
|
|
74
|
+
_check_equivalent_with_error_message(c, nc, gauge)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _check_equivalent_with_error_message(c: cirq.AbstractCircuit, nc: cirq.AbstractCircuit, gauge):
|
|
78
|
+
try:
|
|
79
|
+
cirq.testing.assert_circuits_have_same_unitary_given_final_permutation(
|
|
80
|
+
nc, c, qubit_map={q: q for q in c.all_qubits()}
|
|
81
|
+
)
|
|
82
|
+
except AssertionError as ex:
|
|
83
|
+
raise AssertionError(f"{gauge=} didn't result in an equivalent circuit") from ex
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
import cirq
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
+
from cirq.transformers import GaugeTransformer, GaugeSelector, ConstantGauge
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ExampleGate(cirq.testing.TwoQubitGate):
|
|
23
|
+
unitary = cirq.unitary(cirq.CZ**0.123)
|
|
24
|
+
|
|
25
|
+
def _unitary_(self) -> np.ndarray:
|
|
26
|
+
return self.unitary
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_EXAMPLE_TARGET = ExampleGate()
|
|
30
|
+
|
|
31
|
+
_GOOD_TRANSFORMER = GaugeTransformer(
|
|
32
|
+
target=_EXAMPLE_TARGET,
|
|
33
|
+
gauge_selector=GaugeSelector(gauges=[ConstantGauge(two_qubit_gate=_EXAMPLE_TARGET)]),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
_BAD_TRANSFORMER = GaugeTransformer(
|
|
37
|
+
target=_EXAMPLE_TARGET,
|
|
38
|
+
gauge_selector=GaugeSelector(
|
|
39
|
+
gauges=[ConstantGauge(two_qubit_gate=_EXAMPLE_TARGET, pre_q0=cirq.X)]
|
|
40
|
+
),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class TestValidTransformer(GaugeTester):
|
|
45
|
+
two_qubit_gate = _EXAMPLE_TARGET
|
|
46
|
+
gauge_transformer = _GOOD_TRANSFORMER
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TestInvalidTransformer(GaugeTester):
|
|
50
|
+
two_qubit_gate = _EXAMPLE_TARGET
|
|
51
|
+
gauge_transformer = _BAD_TRANSFORMER
|
|
52
|
+
must_fail = True
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Copyright 2024 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 Gauge transformer for ISWAP gate."""
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
|
|
19
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
20
|
+
ConstantGauge,
|
|
21
|
+
Gauge,
|
|
22
|
+
GaugeTransformer,
|
|
23
|
+
GaugeSelector,
|
|
24
|
+
)
|
|
25
|
+
from cirq import ops
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class RZRotation(Gauge):
|
|
29
|
+
"""Represents an ISWAP Gauge composed of Rz rotations.
|
|
30
|
+
|
|
31
|
+
The gauge replaces an ISWAP gate with either
|
|
32
|
+
0: ───Rz(t)──────iSwap───Rz(sgn*t)───
|
|
33
|
+
│
|
|
34
|
+
1: ───Rz(-sgn*t)───iSwap───Rz(-t)───
|
|
35
|
+
|
|
36
|
+
where t is uniformly sampled from [0, 2π) and sgn is uniformly sampled from {-1, 1}.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def weight(self) -> float:
|
|
40
|
+
return 2.0
|
|
41
|
+
|
|
42
|
+
def _rz(self, theta, sgn: int) -> ConstantGauge:
|
|
43
|
+
"""Returns an ISWAP Gauge composed of Rz rotations.
|
|
44
|
+
|
|
45
|
+
0: ───Rz(theta)──────iSwap───Rz(sgn*theta)───
|
|
46
|
+
│
|
|
47
|
+
1: ───Rz(-sgn*theta)───iSwap───Rz(-theta)───
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
flip_diangonal = sgn == -1
|
|
51
|
+
rz = ops.rz(theta)
|
|
52
|
+
n_rz = ops.rz(-theta)
|
|
53
|
+
return ConstantGauge(
|
|
54
|
+
two_qubit_gate=ops.ISWAP,
|
|
55
|
+
pre_q0=rz,
|
|
56
|
+
pre_q1=n_rz if flip_diangonal else rz,
|
|
57
|
+
post_q0=rz if flip_diangonal else n_rz,
|
|
58
|
+
post_q1=n_rz,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> ConstantGauge:
|
|
62
|
+
theta = prng.random() * 2 * np.pi
|
|
63
|
+
return self._rz(theta, prng.choice([-1, 1]))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class XYRotation(Gauge):
|
|
67
|
+
"""Represents an ISWAP Gauge composed of XY rotations.
|
|
68
|
+
|
|
69
|
+
The gauge replaces an ISWAP gate with either
|
|
70
|
+
0: ───XY(a)───iSwap───XY(b)───
|
|
71
|
+
│
|
|
72
|
+
1: ───XY(b)───iSwap───XY(a)───
|
|
73
|
+
|
|
74
|
+
where a and b are uniformly sampled from [0, 2π) and XY is a single-qubit rotation defined as
|
|
75
|
+
XY(theta) = cos(theta) X + sin(theta) Y
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def weight(self) -> float:
|
|
79
|
+
return 2.0
|
|
80
|
+
|
|
81
|
+
def _xy(self, theta: float) -> ops.PhasedXZGate:
|
|
82
|
+
unitary = np.cos(theta) * np.array([[0, 1], [1, 0]]) + np.sin(theta) * np.array(
|
|
83
|
+
[[0, -1j], [1j, 0]]
|
|
84
|
+
)
|
|
85
|
+
return ops.PhasedXZGate.from_matrix(unitary)
|
|
86
|
+
|
|
87
|
+
def _xy_gauge(self, a: float, b: float) -> ConstantGauge:
|
|
88
|
+
xy_a = self._xy(a)
|
|
89
|
+
xy_b = self._xy(b)
|
|
90
|
+
return ConstantGauge(
|
|
91
|
+
two_qubit_gate=ops.ISWAP, pre_q0=xy_a, pre_q1=xy_b, post_q0=xy_b, post_q1=xy_a
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> ConstantGauge:
|
|
95
|
+
a = prng.random() * 2 * np.pi
|
|
96
|
+
if prng.choice([0, 1]):
|
|
97
|
+
return self._xy_gauge(a, a)
|
|
98
|
+
else:
|
|
99
|
+
b = prng.random() * 2 * np.pi
|
|
100
|
+
return self._xy_gauge(a, b)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
ISWAPGaugeTransformer = GaugeTransformer(
|
|
104
|
+
target=ops.ISWAP, gauge_selector=GaugeSelector(gauges=[RZRotation(), XYRotation()])
|
|
105
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
import cirq
|
|
17
|
+
from cirq.transformers.gauge_compiling import ISWAPGaugeTransformer
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestISWAPGauge(GaugeTester):
|
|
22
|
+
two_qubit_gate = cirq.ISWAP
|
|
23
|
+
gauge_transformer = ISWAPGaugeTransformer
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
"""The spin inversion gauge transformer."""
|
|
16
|
+
|
|
17
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
18
|
+
GaugeTransformer,
|
|
19
|
+
GaugeSelector,
|
|
20
|
+
ConstantGauge,
|
|
21
|
+
)
|
|
22
|
+
from cirq import ops
|
|
23
|
+
|
|
24
|
+
SpinInversionGaugeSelector = GaugeSelector(
|
|
25
|
+
gauges=[
|
|
26
|
+
ConstantGauge(two_qubit_gate=ops.ZZ, pre_q0=ops.X, post_q0=ops.X),
|
|
27
|
+
ConstantGauge(two_qubit_gate=ops.ZZ, pre_q1=ops.X, post_q1=ops.X),
|
|
28
|
+
]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
SpinInversionGaugeTransformer = GaugeTransformer(
|
|
32
|
+
target=ops.ZZ, gauge_selector=SpinInversionGaugeSelector
|
|
33
|
+
)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
import cirq
|
|
17
|
+
from cirq.transformers.gauge_compiling import SpinInversionGaugeTransformer
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestSpinInversionGauge(GaugeTester):
|
|
22
|
+
two_qubit_gate = cirq.ZZ
|
|
23
|
+
gauge_transformer = SpinInversionGaugeTransformer
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 2024 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 Gauge transformer for CZ**0.5 gate."""
|
|
16
|
+
|
|
17
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
18
|
+
GaugeTransformer,
|
|
19
|
+
GaugeSelector,
|
|
20
|
+
ConstantGauge,
|
|
21
|
+
)
|
|
22
|
+
from cirq.ops.common_gates import CZ
|
|
23
|
+
from cirq import ops
|
|
24
|
+
|
|
25
|
+
SqrtCZGaugeSelector = GaugeSelector(
|
|
26
|
+
gauges=[ConstantGauge(pre_q0=ops.X, post_q0=ops.X, post_q1=ops.Z**0.5, two_qubit_gate=CZ**-0.5)]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
SqrtCZGaugeTransformer = GaugeTransformer(target=CZ**0.5, gauge_selector=SqrtCZGaugeSelector)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
|
|
16
|
+
import cirq
|
|
17
|
+
from cirq.transformers.gauge_compiling import SqrtCZGaugeTransformer
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestSqrtCZGauge(GaugeTester):
|
|
22
|
+
two_qubit_gate = cirq.CZ**0.5
|
|
23
|
+
gauge_transformer = SqrtCZGaugeTransformer
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Copyright 2024 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 Gauge transformer for SQRT_ISWAP gate."""
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
19
|
+
ConstantGauge,
|
|
20
|
+
Gauge,
|
|
21
|
+
GaugeTransformer,
|
|
22
|
+
GaugeSelector,
|
|
23
|
+
)
|
|
24
|
+
from cirq import ops
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class RZRotation(Gauge):
|
|
28
|
+
"""Represents a SQRT_ISWAP Gauge composed of Rz rotations.
|
|
29
|
+
|
|
30
|
+
The gauge replaces an SQRT_ISWAP gate with either
|
|
31
|
+
0: ───Rz(t)───iSwap───────Rz(-t)───
|
|
32
|
+
│
|
|
33
|
+
1: ───Rz(t)───iSwap^0.5───Rz(-t)───
|
|
34
|
+
|
|
35
|
+
where t is uniformly sampled from [0, 2π).
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def weight(self) -> float:
|
|
39
|
+
return 1.0
|
|
40
|
+
|
|
41
|
+
def _rz(self, theta: float) -> ConstantGauge:
|
|
42
|
+
"""Returns a SQRT_ISWAP Gauge composed of Rz rotations.
|
|
43
|
+
|
|
44
|
+
0: ───Rz(theta)────iSwap───Rz(theta)───
|
|
45
|
+
│
|
|
46
|
+
1: ───Rz(theta)───iSwap^0.5───Rz(theta)───
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
rz = ops.rz(theta)
|
|
50
|
+
n_rz = ops.rz(-theta)
|
|
51
|
+
return ConstantGauge(
|
|
52
|
+
two_qubit_gate=ops.SQRT_ISWAP, pre_q0=rz, pre_q1=rz, post_q0=n_rz, post_q1=n_rz
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> ConstantGauge:
|
|
56
|
+
return self._rz(prng.random() * 2 * np.pi)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class XYRotation(Gauge):
|
|
60
|
+
"""Represents a SQRT_ISWAP Gauge composed of XY rotations.
|
|
61
|
+
|
|
62
|
+
The gauge replaces an SQRT_ISWAP gate with either
|
|
63
|
+
0: ───XY(t)───iSwap───────XY(t)───
|
|
64
|
+
│
|
|
65
|
+
1: ───XY(t)───iSwap^0.5───XY(t)───
|
|
66
|
+
|
|
67
|
+
where t is uniformly sampled from [0, 2π) and
|
|
68
|
+
XY(theta) = cos(theta) X + sin(theta) Y
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def weight(self) -> float:
|
|
72
|
+
return 1.0
|
|
73
|
+
|
|
74
|
+
def _xy(self, theta: float) -> ops.PhasedXZGate:
|
|
75
|
+
unitary = np.cos(theta) * np.array([[0, 1], [1, 0]]) + np.sin(theta) * np.array(
|
|
76
|
+
[[0, -1j], [1j, 0]]
|
|
77
|
+
)
|
|
78
|
+
return ops.PhasedXZGate.from_matrix(unitary)
|
|
79
|
+
|
|
80
|
+
def _xy_gauge(self, theta: float) -> ConstantGauge:
|
|
81
|
+
xy = self._xy(theta)
|
|
82
|
+
return ConstantGauge(
|
|
83
|
+
two_qubit_gate=ops.SQRT_ISWAP, pre_q0=xy, pre_q1=xy, post_q0=xy, post_q1=xy
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
def sample(self, gate: ops.Gate, prng: np.random.Generator) -> ConstantGauge:
|
|
87
|
+
return self._xy_gauge(prng.random() * 2 * np.pi)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
SqrtISWAPGaugeSelector = GaugeSelector(gauges=[RZRotation(), XYRotation()])
|
|
91
|
+
|
|
92
|
+
SqrtISWAPGaugeTransformer = GaugeTransformer(
|
|
93
|
+
target=ops.SQRT_ISWAP, gauge_selector=SqrtISWAPGaugeSelector
|
|
94
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copyright 2024 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 cirq
|
|
16
|
+
from cirq.transformers.gauge_compiling import SqrtISWAPGaugeTransformer
|
|
17
|
+
from cirq.transformers.gauge_compiling.gauge_compiling_test_utils import GaugeTester
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestSqrtISWAPGauge(GaugeTester):
|
|
21
|
+
two_qubit_gate = cirq.SQRT_ISWAP
|
|
22
|
+
gauge_transformer = SqrtISWAPGaugeTransformer
|
{cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cirq-core
|
|
3
|
-
Version: 1.4.0.
|
|
3
|
+
Version: 1.4.0.dev20240403011731
|
|
4
4
|
Summary: A framework for creating, editing, and invoking Noisy Intermediate Scale Quantum (NISQ) circuits.
|
|
5
5
|
Home-page: http://github.com/quantumlib/cirq
|
|
6
6
|
Author: The Cirq Developers
|
|
@@ -8,6 +8,7 @@ Author-email: cirq-dev@googlegroups.com
|
|
|
8
8
|
License: Apache 2
|
|
9
9
|
Requires-Python: >=3.9.0
|
|
10
10
|
License-File: LICENSE
|
|
11
|
+
Requires-Dist: attrs
|
|
11
12
|
Requires-Dist: duet >=0.2.8
|
|
12
13
|
Requires-Dist: matplotlib ~=3.0
|
|
13
14
|
Requires-Dist: networkx >=2.4
|
{cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/RECORD
RENAMED
|
@@ -4,7 +4,7 @@ cirq/_compat_test.py,sha256=Qq3ZcfgD-Nb81cEppQdJqhAyrVqXKtfXZYGXT0p-Wh0,34718
|
|
|
4
4
|
cirq/_doc.py,sha256=yDyWUD_2JDS0gShfGRb-rdqRt9-WeL7DhkqX7np0Nko,2879
|
|
5
5
|
cirq/_import.py,sha256=p9gMHJscbtDDkfHOaulvd3Aer0pwUF5AXpL89XR8dNw,8402
|
|
6
6
|
cirq/_import_test.py,sha256=6K_v0riZJXOXUphHNkGA8MY-JcmGlezFaGmvrNhm3OQ,1015
|
|
7
|
-
cirq/_version.py,sha256=
|
|
7
|
+
cirq/_version.py,sha256=8wUDndCJvT5IPWRPX7VzDqaJanKPlInnAFaWJF-lUJU,40
|
|
8
8
|
cirq/_version_test.py,sha256=yYS6xm5-nuBRQJa9R3n41WdvFtVyY7Lb5Q8bea3VgBI,133
|
|
9
9
|
cirq/conftest.py,sha256=X7yLFL8GLhg2CjPw0hp5e_dGASfvHx1-QT03aUbhKJw,1168
|
|
10
10
|
cirq/json_resolver_cache.py,sha256=9g_JQMmfBzTuV-3s2flUbXIgcLjs4K7LjAFFgngdG1U,13204
|
|
@@ -909,7 +909,7 @@ cirq/sim/sparse_simulator_test.py,sha256=3EAeCHUQeKllAAtdw14X592zBsGQY_vwfIYK-gE
|
|
|
909
909
|
cirq/sim/state_vector.py,sha256=N6N9EELlW66UaLTBaq62ms0XkfIK7CzN9SBM7t52dXo,13428
|
|
910
910
|
cirq/sim/state_vector_simulation_state.py,sha256=e4it_DT1J-30S3OX_gfMJiWAttFaVOMEPQ-Y1ARWnDg,17616
|
|
911
911
|
cirq/sim/state_vector_simulation_state_test.py,sha256=UtGMIurlV6N74nX7qoVnGoRhwF35-ghDEIP7Mj5AXmI,9841
|
|
912
|
-
cirq/sim/state_vector_simulator.py,sha256=
|
|
912
|
+
cirq/sim/state_vector_simulator.py,sha256=M3k9VR7nht1gcovBjc3CaEoKbYIsCImAJyjS0_wb3ko,7942
|
|
913
913
|
cirq/sim/state_vector_simulator_test.py,sha256=wJq1OZRzKokeM9cJyaJXi6wHH2qi97h0HmJlYOEBDzU,7864
|
|
914
914
|
cirq/sim/state_vector_test.py,sha256=OjhAL2tWqJWstHV8RvJYQVqg95zm0PcS9nQKrLOhMmQ,16934
|
|
915
915
|
cirq/sim/clifford/__init__.py,sha256=lD7l6JuE5n0xwvOYNYH-giCH3qAEVH1SUwDrZM1jKKY,636
|
|
@@ -1013,7 +1013,7 @@ cirq/testing/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
1013
1013
|
cirq/testing/test_data/test_module_missing_json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1014
1014
|
cirq/testing/test_data/test_module_missing_testspec/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1015
1015
|
cirq/testing/test_data/test_module_missing_testspec/json_test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1016
|
-
cirq/transformers/__init__.py,sha256=
|
|
1016
|
+
cirq/transformers/__init__.py,sha256=Omi-8NLq9lMbMHV-eXxwrpX5_zw-ZyRJKPmIL_mIzMg,4145
|
|
1017
1017
|
cirq/transformers/align.py,sha256=B4DuX84DWd4tLfMH21JviMZSOFYu7KCOMSEMALYsQpw,2727
|
|
1018
1018
|
cirq/transformers/align_test.py,sha256=M4etT2cgESv1RdkKASguiGxEuqY7kmI1IswjSi-1jjY,7174
|
|
1019
1019
|
cirq/transformers/drop_empty_moments.py,sha256=Rtn_BrpwkLXyZBdLzwdnsnEGWTdYuf1xOPakzbpv7-w,1517
|
|
@@ -1071,6 +1071,21 @@ cirq/transformers/analytical_decompositions/two_qubit_to_ms.py,sha256=Awr7WvaJe_
|
|
|
1071
1071
|
cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py,sha256=85MbuIAos7o1371wXs_KH-Bk6jsPqSBKAx9GJ9c-wVo,4160
|
|
1072
1072
|
cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py,sha256=F_XpM4ApYHxV6hbWnV3C7Ud9L1BnpvBHBXShPh2mP3k,25397
|
|
1073
1073
|
cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py,sha256=eKOzjWkR7xs-CL2oPj__nWXR0LL9oO42wEHibnvWq-o,20618
|
|
1074
|
+
cirq/transformers/gauge_compiling/__init__.py,sha256=dmgVx7_yfsO9TarOCMBfVuZjza_6_MmUyAfM_eo698E,1146
|
|
1075
|
+
cirq/transformers/gauge_compiling/cz_gauge.py,sha256=TNZviXFu4j-lCF87QMGYVdb2RC_ePHLdI6FRCqh9go4,2550
|
|
1076
|
+
cirq/transformers/gauge_compiling/cz_gauge_test.py,sha256=_2RMzwuMoqytgsVZEET2m6QsGoZ2_uWgBfSGGvhZEWo,854
|
|
1077
|
+
cirq/transformers/gauge_compiling/gauge_compiling.py,sha256=GCYpaZIUxkcz16s8DI64dtpHhSGiIy6JIplvM6GUklc,6662
|
|
1078
|
+
cirq/transformers/gauge_compiling/gauge_compiling_test.py,sha256=xVeoaaMuenlp_pxqmZO89kJEeBV0iapK7-JDTUuC7Lg,1565
|
|
1079
|
+
cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py,sha256=6mpF2ftcDtWQEsZNr-m16GkDOn5WBWV08JB4ZS5rf8M,3408
|
|
1080
|
+
cirq/transformers/gauge_compiling/gauge_compiling_test_utils_test.py,sha256=HQw1xeko9OAD0PCuKcehUiy8mbxeRza4nE-6E8MGVME,1584
|
|
1081
|
+
cirq/transformers/gauge_compiling/iswap_gauge.py,sha256=UGJ_061h65Rfgb9LWREjxC8OSt01ZqP9TGnacL8VAuk,3500
|
|
1082
|
+
cirq/transformers/gauge_compiling/iswap_gauge_test.py,sha256=HEIIwKlX5ixau1e_etSUj5NvYOVTT-Gc3kuHcyKAeJ4,866
|
|
1083
|
+
cirq/transformers/gauge_compiling/spin_inversion_gauge.py,sha256=BMt1g2h23J9jb6LTlZsNczMKIY8J0duHhZNu0jRB48M,1107
|
|
1084
|
+
cirq/transformers/gauge_compiling/spin_inversion_gauge_test.py,sha256=PtbHNvh6Oz-n6Tn0fdvpgHGgaPuJQPlJ8UfHd59-dks,887
|
|
1085
|
+
cirq/transformers/gauge_compiling/sqrt_cz_gauge.py,sha256=l0Dkz2a7_ljKzzP-Rr9f_yY4pqJ8TGY_R-FVEkBb77I,1050
|
|
1086
|
+
cirq/transformers/gauge_compiling/sqrt_cz_gauge_test.py,sha256=wB_WezbTBbkwnTs7hz_tXmU4syuMulGirDDDjzqvNt0,871
|
|
1087
|
+
cirq/transformers/gauge_compiling/sqrt_iswap_gauge.py,sha256=dqQa-UWq31bE_jF3KMhU76sND5GuqTpEp9-wVuXdWVM,3126
|
|
1088
|
+
cirq/transformers/gauge_compiling/sqrt_iswap_gauge_test.py,sha256=0CLZoLw-WK3aKEIoaKBrQZ-qvaprOVLad-dVyWFmSiU,882
|
|
1074
1089
|
cirq/transformers/heuristic_decompositions/__init__.py,sha256=2KBAUk-vsVku-HuahLbDQxp8bjEQMZUUNiBz_cvUMUw,831
|
|
1075
1090
|
cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils.py,sha256=j9bbiIbC2rvwG830gTTf9zr9C7RVA5Ilhka_ZNF-N7w,10785
|
|
1076
1091
|
cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py,sha256=N02nlz7tISYVArvWNILwg-hnDB5Y9PCHbwIxk42Afv8,1534
|
|
@@ -1154,8 +1169,8 @@ cirq/work/sampler.py,sha256=JEAeQQRF3bqlO9AkOf4XbrTATDI5f5JgyM_FAUCNxao,19751
|
|
|
1154
1169
|
cirq/work/sampler_test.py,sha256=B2ZsuqGT854gQtBIAh8k0LiG9Vj5wSzcGvkxOUoTcW4,13217
|
|
1155
1170
|
cirq/work/zeros_sampler.py,sha256=x1C7cup66a43n-3tm8QjhiqJa07qcJW10FxNp9jJ59Q,2356
|
|
1156
1171
|
cirq/work/zeros_sampler_test.py,sha256=JIkpBBFPJe5Ba4142vzogyWyboG1Q1ZAm0UVGgOoZn8,3279
|
|
1157
|
-
cirq_core-1.4.0.
|
|
1158
|
-
cirq_core-1.4.0.
|
|
1159
|
-
cirq_core-1.4.0.
|
|
1160
|
-
cirq_core-1.4.0.
|
|
1161
|
-
cirq_core-1.4.0.
|
|
1172
|
+
cirq_core-1.4.0.dev20240403011731.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
|
1173
|
+
cirq_core-1.4.0.dev20240403011731.dist-info/METADATA,sha256=8nMDDTBH7qzIe21E0j2k4Hqzj4fYEk3Tmwh4Hc0qDGY,2099
|
|
1174
|
+
cirq_core-1.4.0.dev20240403011731.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
1175
|
+
cirq_core-1.4.0.dev20240403011731.dist-info/top_level.txt,sha256=Sz9iOxHU0IEMLSFGwiwOCaN2e9K-jFbBbtpPN1hB73g,5
|
|
1176
|
+
cirq_core-1.4.0.dev20240403011731.dist-info/RECORD,,
|
{cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/LICENSE
RENAMED
|
File without changes
|
{cirq_core-1.4.0.dev20240402234712.dist-info → cirq_core-1.4.0.dev20240403011731.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|