|
15 | 15 | """Define detuning gates for Analog Experiment usage."""
|
16 | 16 | from __future__ import annotations
|
17 | 17 |
|
18 |
| -from typing import AbstractSet, Any, TYPE_CHECKING |
| 18 | +from typing import AbstractSet, Any, Iterable, TYPE_CHECKING |
19 | 19 |
|
20 | 20 | import cirq
|
| 21 | +from cirq_google.ops import coupler |
21 | 22 | from cirq_google.study import symbol_util as su
|
22 | 23 |
|
23 | 24 | if TYPE_CHECKING:
|
@@ -59,6 +60,7 @@ def __init__(
|
59 | 60 | linear_rise: bool = True,
|
60 | 61 | ):
|
61 | 62 | """Inits AnalogDetuneQubit.
|
| 63 | +
|
62 | 64 | Args:
|
63 | 65 | length: The duration of gate.
|
64 | 66 | w: Width of the step envelope raising edge.
|
@@ -171,3 +173,180 @@ def _json_dict_(self):
|
171 | 173 | 'linear_rise',
|
172 | 174 | ],
|
173 | 175 | )
|
| 176 | + |
| 177 | + |
| 178 | +@cirq.value_equality(approximate=True) |
| 179 | +class AnalogDetuneCouplerOnly(cirq.ops.Gate): |
| 180 | + """Set a coupler detuning from g_0 to g_max according to analog model. |
| 181 | +
|
| 182 | + The shape of pulse followed by the g=g_0+A*t^g_exp (1 gives linear ramp), |
| 183 | + where the coefficient is auto calculated by the g_max. |
| 184 | +
|
| 185 | + Pulse shape: |
| 186 | +
|
| 187 | + .. svgbob:: |
| 188 | + :align: center |
| 189 | +
|
| 190 | + | ,--------|---- amp_max (parsed from g_max) |
| 191 | + | / | |
| 192 | + amp_0---|-' - - - - -| - - |
| 193 | + | |
| 194 | + | |-w -| | |
| 195 | + | |---length --| |
| 196 | + | |
| 197 | + --------------------------(calculated from the g_0) |
| 198 | + """ |
| 199 | + |
| 200 | + def __init__( |
| 201 | + self, |
| 202 | + length: su.ValueOrSymbol, |
| 203 | + w: su.ValueOrSymbol, |
| 204 | + g_0: su.ValueOrSymbol, |
| 205 | + g_max: su.ValueOrSymbol, |
| 206 | + g_ramp_exponent: cirq.TParamVal = 1.0, |
| 207 | + neighbor_qubits_freq: tuple[su.ValueOrSymbol | None, su.ValueOrSymbol | None] = ( |
| 208 | + None, |
| 209 | + None, |
| 210 | + ), |
| 211 | + prev_neighbor_qubits_freq: tuple[su.ValueOrSymbol | None, su.ValueOrSymbol | None] = ( |
| 212 | + None, |
| 213 | + None, |
| 214 | + ), |
| 215 | + interpolate_coupling_cal: bool = True, |
| 216 | + analog_cal_for_pulseshaping: bool = False, |
| 217 | + ): |
| 218 | + """Inits AnalogDetuneCouplerOnly. |
| 219 | +
|
| 220 | + Args: |
| 221 | + length: The duration of gate. |
| 222 | + w: Width of the step envelope raising edge. |
| 223 | + g_0: The pulse shape is specified with the equation g(t) = g_0+A*t^g_exp. |
| 224 | + where g(0)=g_0 and g(w)=g_max. The ramp is according to the power law |
| 225 | + with exponent specified by g_ramp_exponent. |
| 226 | + g_max: See g_0. |
| 227 | + g_ramp_exponent: See g_0. |
| 228 | + neighbor_qubits_freq: Two frequency of the neighbor qubits at the moment. |
| 229 | + If the provided value is None, we assume neighbor qubits are at idle freq. |
| 230 | + prev_neighbor_qubits_freq: Two frequency of the neighbor qubits at preivous moment. |
| 231 | + interpolate_coupling_cal: If true, find the required amp for the coupling strength |
| 232 | + through interpolation. If not true, require all coupling strength has associated |
| 233 | + amp calibrated in the registry. |
| 234 | + analog_cal_for_pulseshaping: If ture, using the analog model instead of |
| 235 | + standard transmon model to find the amp of pulse. |
| 236 | + """ |
| 237 | + self.length = length |
| 238 | + self.w = w |
| 239 | + self.g_0 = g_0 |
| 240 | + self.g_max = g_max |
| 241 | + self.g_ramp_exponent = g_ramp_exponent |
| 242 | + self.neighbor_qubits_freq = tuple(neighbor_qubits_freq) |
| 243 | + self.prev_neighbor_qubits_freq = tuple(prev_neighbor_qubits_freq) |
| 244 | + self.interpolate_coupling_cal = interpolate_coupling_cal |
| 245 | + self.analog_cal_for_pulseshaping = analog_cal_for_pulseshaping |
| 246 | + |
| 247 | + def _unitary_(self) -> np.ndarray: |
| 248 | + return NotImplemented # pragma: no cover |
| 249 | + |
| 250 | + def on(self, *qubits: cirq.Qid) -> cirq.Operation: |
| 251 | + """Returns an application of this gate to the given qubits. |
| 252 | +
|
| 253 | + Coupler gate will silently change two qubit Qids into |
| 254 | + a single Coupler Qid object so that adjacent couplers |
| 255 | + can be simultaneously acted on in the same moment. |
| 256 | + """ |
| 257 | + if len(qubits) == 2: |
| 258 | + return super().on(coupler.Coupler(qubits[0], qubits[1])) |
| 259 | + else: |
| 260 | + return super().on(*qubits) |
| 261 | + |
| 262 | + def on_each(self, *targets: cirq.Qid | Iterable[Any]) -> list[cirq.Operation]: |
| 263 | + """Returns a list of operations applying the gate to all targets.""" |
| 264 | + return [self.on(t) if isinstance(t, cirq.Qid) else self.on(*t) for t in targets] |
| 265 | + |
| 266 | + def _num_qubits_(self) -> int: |
| 267 | + return 1 |
| 268 | + |
| 269 | + def _is_parameterized_(self) -> bool: |
| 270 | + return ( |
| 271 | + cirq.is_parameterized(self.length) |
| 272 | + or cirq.is_parameterized(self.w) |
| 273 | + or cirq.is_parameterized(self.g_0) |
| 274 | + or cirq.is_parameterized(self.g_max) |
| 275 | + or cirq.is_parameterized(self.g_ramp_exponent) |
| 276 | + or cirq.is_parameterized(self.neighbor_qubits_freq) |
| 277 | + or cirq.is_parameterized(self.prev_neighbor_qubits_freq) |
| 278 | + ) |
| 279 | + |
| 280 | + def _parameter_names_(self) -> AbstractSet[str]: |
| 281 | + return ( |
| 282 | + cirq.parameter_names(self.length) |
| 283 | + | cirq.parameter_names(self.w) |
| 284 | + | cirq.parameter_names(self.g_0) |
| 285 | + | cirq.parameter_names(self.g_max) |
| 286 | + | cirq.parameter_names(self.g_ramp_exponent) |
| 287 | + | cirq.parameter_names(self.neighbor_qubits_freq) |
| 288 | + | cirq.parameter_names(self.prev_neighbor_qubits_freq) |
| 289 | + ) |
| 290 | + |
| 291 | + def _resolve_parameters_( |
| 292 | + self, resolver: cirq.ParamResolverOrSimilarType, recursive: bool |
| 293 | + ) -> AnalogDetuneCouplerOnly: |
| 294 | + resolver_ = cirq.ParamResolver(resolver) |
| 295 | + return AnalogDetuneCouplerOnly( |
| 296 | + length=su.direct_symbol_replacement(self.length, resolver_), |
| 297 | + w=su.direct_symbol_replacement(self.w, resolver_), |
| 298 | + g_0=su.direct_symbol_replacement(self.g_0, resolver_), |
| 299 | + g_max=su.direct_symbol_replacement(self.g_max, resolver_), |
| 300 | + g_ramp_exponent=su.direct_symbol_replacement(self.g_ramp_exponent, resolver_), |
| 301 | + neighbor_qubits_freq=tuple( |
| 302 | + su.direct_symbol_replacement(f, resolver_) for f in self.neighbor_qubits_freq |
| 303 | + ), |
| 304 | + prev_neighbor_qubits_freq=tuple( |
| 305 | + su.direct_symbol_replacement(f, resolver_) for f in self.prev_neighbor_qubits_freq |
| 306 | + ), |
| 307 | + interpolate_coupling_cal=self.interpolate_coupling_cal, |
| 308 | + analog_cal_for_pulseshaping=self.analog_cal_for_pulseshaping, |
| 309 | + ) |
| 310 | + |
| 311 | + def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> str: |
| 312 | + return f"AnalogDetuneCouplerOnly(length={self.length}, g_max={self.g_max})" |
| 313 | + |
| 314 | + def __repr__(self) -> str: |
| 315 | + return ( |
| 316 | + f'AnalogDetuneCouplerOnly(length={self.length}, ' |
| 317 | + f'w={self.w}, ' |
| 318 | + f'g_0={self.g_0}, ' |
| 319 | + f'g_max={self.g_max}, ' |
| 320 | + f'g_ramp_exponent={self.g_ramp_exponent}, ' |
| 321 | + f'neighbor_qubits_freq={self.neighbor_qubits_freq}, ' |
| 322 | + f'prev_neighbor_qubits_freq={self.prev_neighbor_qubits_freq})' |
| 323 | + ) |
| 324 | + |
| 325 | + def _value_equality_values_(self) -> Any: |
| 326 | + return ( |
| 327 | + self.length, |
| 328 | + self.w, |
| 329 | + self.g_0, |
| 330 | + self.g_max, |
| 331 | + self.g_ramp_exponent, |
| 332 | + self.neighbor_qubits_freq, |
| 333 | + self.prev_neighbor_qubits_freq, |
| 334 | + self.interpolate_coupling_cal, |
| 335 | + self.analog_cal_for_pulseshaping, |
| 336 | + ) |
| 337 | + |
| 338 | + def _json_dict_(self): |
| 339 | + return cirq.obj_to_dict_helper( |
| 340 | + self, |
| 341 | + [ |
| 342 | + 'length', |
| 343 | + 'w', |
| 344 | + 'g_0', |
| 345 | + 'g_max', |
| 346 | + 'g_ramp_exponent', |
| 347 | + 'neighbor_qubits_freq', |
| 348 | + 'prev_neighbor_qubits_freq', |
| 349 | + 'interpolate_coupling_cal', |
| 350 | + 'analog_cal_for_pulseshaping', |
| 351 | + ], |
| 352 | + ) |
0 commit comments