-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Use cirq.q instead of str in analog #7736
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 11 commits
008f022
560b859
7b39c07
6c04d43
3056980
b7a588a
7518a2f
ebe8ae1
17e4e85
3a3a613
8456674
bb21594
6d7bf89
fb178ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,8 @@ | |
| if TYPE_CHECKING: | ||
| from matplotlib.axes import Axes | ||
|
|
||
| from cirq_google.ops import coupler as cgc | ||
|
|
||
|
|
||
| @attrs.mutable | ||
| class FrequencyMap: | ||
|
|
@@ -40,8 +42,8 @@ class FrequencyMap: | |
| """ | ||
|
|
||
| duration: su.ValueOrSymbol | ||
| qubit_freqs: dict[str, su.ValueOrSymbol | None] | ||
| couplings: dict[tuple[str, str], su.ValueOrSymbol] | ||
| qubit_freqs: dict[cirq.Qid, su.ValueOrSymbol | None] | ||
| couplings: dict[cgc.Coupler, su.ValueOrSymbol] | ||
| is_wait_step: bool | ||
|
|
||
| def _is_parameterized_(self) -> bool: | ||
|
|
@@ -86,8 +88,8 @@ def __init__( | |
| self, | ||
| *, | ||
| full_trajectory: list[FrequencyMap], | ||
| qubits: list[str], | ||
| pairs: list[tuple[str, str]], | ||
| qubits: list[cirq.Qid], | ||
| pairs: list[cgc.Coupler], | ||
| ): | ||
| self.full_trajectory = full_trajectory | ||
| self.qubits = qubits | ||
|
|
@@ -99,39 +101,39 @@ def from_sparse_trajectory( | |
| sparse_trajectory: list[ | ||
| tuple[ | ||
| tu.Value, | ||
| dict[str, su.ValueOrSymbol | None], | ||
| dict[tuple[str, str], su.ValueOrSymbol], | ||
| dict[cirq.Qid, su.ValueOrSymbol | None], | ||
| dict[cgc.Coupler, su.ValueOrSymbol], | ||
| ], | ||
| ], | ||
| qubits: list[str] | None = None, | ||
| pairs: list[tuple[str, str]] | None = None, | ||
| qubits: list[cirq.Qid] | None = None, | ||
| pairs: list[cgc.Coupler] | None = None, | ||
| ): | ||
| """Construct AnalogTrajectory from sparse trajectory. | ||
|
|
||
| Args: | ||
| sparse_trajectory: A list of tuples, where each tuple defines a `FrequencyMap` | ||
| and contains three elements: (duration, qubit_freqs, coupling_strengths). | ||
| `duration` is a tunits value, `qubit_freqs` is a dictionary mapping qubit strings | ||
|
||
| to detuning frequencies, and `coupling_strengths` is a dictionary mapping qubit | ||
| pairs to their coupling strength. This format is considered "sparse" because each | ||
| to detuning frequencies, and `coupling_strengths` is a dictionary mapping | ||
| coupler to their coupling strength. This format is considered "sparse" because each | ||
|
||
| tuple does not need to fully specify all qubits and coupling pairs; any missing | ||
| detuning frequency or coupling strength will be set to the same value as the | ||
| previous value in the list. | ||
| qubits: The qubits in interest. If not provided, automatically parsed from trajectory. | ||
| pairs: The pairs in interest. If not provided, automatically parsed from trajectory. | ||
| """ | ||
| if qubits is None or pairs is None: | ||
| qubits_in_traj: list[str] = [] | ||
| pairs_in_traj: list[tuple[str, str]] = [] | ||
| qubits_in_traj: list[cirq.Qid] = [] | ||
| pairs_in_traj: list[cgc.Coupler] = [] | ||
| for _, q, p in sparse_trajectory: | ||
| qubits_in_traj.extend(q.keys()) | ||
| pairs_in_traj.extend(p.keys()) | ||
| qubits = list(set(qubits_in_traj)) | ||
| pairs = list(set(pairs_in_traj)) | ||
|
|
||
| full_trajectory: list[FrequencyMap] = [] | ||
| init_qubit_freq_dict: dict[str, tu.Value | None] = {q: None for q in qubits} | ||
| init_g_dict: dict[tuple[str, str], tu.Value] = {p: 0 * tu.MHz for p in pairs} | ||
| init_qubit_freq_dict: dict[cirq.Qid, tu.Value | None] = {q: None for q in qubits} | ||
| init_g_dict: dict[cgc.Coupler, tu.Value] = {c: 0 * tu.MHz for c in pairs} | ||
| full_trajectory.append(FrequencyMap(0 * tu.ns, init_qubit_freq_dict, init_g_dict, False)) | ||
|
|
||
| for dt, qubit_freq_dict, g_dict in sparse_trajectory: | ||
|
|
@@ -142,15 +144,15 @@ def from_sparse_trajectory( | |
| q: qubit_freq_dict.get(q, full_trajectory[-1].qubit_freqs.get(q)) for q in qubits | ||
| } | ||
| # If no g provided, set equal to previous | ||
| new_g_dict: dict[tuple[str, str], tu.Value] = { | ||
| p: g_dict.get(p, full_trajectory[-1].couplings.get(p)) for p in pairs # type: ignore[misc] | ||
| new_g_dict: dict[cgc.Coupler, tu.Value] = { | ||
| c: g_dict.get(c, full_trajectory[-1].couplings.get(c)) for c in pairs # type: ignore[misc] | ||
| } | ||
|
|
||
| full_trajectory.append(FrequencyMap(dt, new_qubit_freq_dict, new_g_dict, is_wait_step)) | ||
| return cls(full_trajectory=full_trajectory, qubits=qubits, pairs=pairs) | ||
|
|
||
| def get_full_trajectory_with_resolved_idles( | ||
| self, idle_freq_map: dict[str, tu.Value] | ||
| self, idle_freq_map: dict[cirq.Qid, tu.Value] | ||
| ) -> list[FrequencyMap]: | ||
| """Insert idle frequencies instead of None in trajectory.""" | ||
|
|
||
|
|
@@ -164,13 +166,19 @@ def get_full_trajectory_with_resolved_idles( | |
|
|
||
| def plot( | ||
| self, | ||
| idle_freq_map: dict[str, tu.Value] | None = None, | ||
| default_idle_freq: tu.Value = 6.5 * tu.GHz, | ||
| idle_freq_map: dict[cirq.Qid, tu.Value] | None = None, | ||
| resolver: cirq.ParamResolverOrSimilarType | None = None, | ||
| axes: tuple[Axes, Axes] | None = None, | ||
| ) -> tuple[Axes, Axes]: | ||
| if idle_freq_map is None: | ||
| idle_freq_map = {q: default_idle_freq for q in self.qubits} | ||
| # Because we use relative frequencies and we do not expose the idle frequencies, | ||
| # we randomly assign idle frequencies for plotting purposes only. | ||
| idle_freq_map = {q: np.random.randn() * 50 * tu.MHz for q in self.qubits} | ||
| else: # pragma: no cover | ||
| for q in self.qubits: | ||
| if q not in idle_freq_map: # Fill in missing idle freqs | ||
| idle_freq_map[q] = np.random.randn() * 50 * tu.MHz | ||
|
|
||
| full_trajectory_resolved = cirq.resolve_parameters( | ||
| self.get_full_trajectory_with_resolved_idles(idle_freq_map), resolver | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,15 +17,15 @@ | |
|
|
||
| import cirq | ||
| from cirq_google.experimental.analog_experiments import analog_trajectory_util as atu | ||
| from cirq_google.ops import analog_detune_gates as adg, wait_gate as wg | ||
| from cirq_google.ops import analog_detune_gates as adg, coupler as cgc, wait_gate as wg | ||
| from cirq_google.study import symbol_util as su | ||
|
|
||
|
|
||
| def _get_neighbor_freqs( | ||
| qubit_pair: tuple[str, str], qubit_freq_dict: dict[str, su.ValueOrSymbol | None] | ||
| coupler: cgc.Coupler, qubit_freq_dict: dict[cirq.Qid, su.ValueOrSymbol | None] | ||
| ) -> tuple[su.ValueOrSymbol | None, su.ValueOrSymbol | None]: | ||
| """Get neighbor freqs from qubit_freq_dict given the pair.""" | ||
| sorted_pair = sorted(qubit_pair, key=_to_grid_qubit) | ||
| sorted_pair = sorted(coupler.qubits) | ||
| return (qubit_freq_dict[sorted_pair[0]], qubit_freq_dict[sorted_pair[1]]) | ||
|
|
||
|
|
||
|
|
@@ -37,19 +37,19 @@ def _to_grid_qubit(qubit_name: str) -> cirq.GridQubit: | |
| return cirq.GridQubit(int(match[1]), int(match[2])) | ||
|
|
||
|
|
||
| def _coupler_name_from_qubit_pair(qubit_pair: tuple[str, str]) -> str: | ||
| sorted_pair = sorted(qubit_pair, key=_to_grid_qubit) | ||
| return f"c_{sorted_pair[0]}_{sorted_pair[1]}" | ||
| def _coupler_name(coupler: cgc.Coupler) -> str: | ||
| q1, q2 = sorted(coupler.qubits) | ||
| return f"c_q{q1.row}_{q1.col}_q{q2.row}_{q2.col}" # type: ignore[attr-defined] | ||
|
Comment on lines
+40
to
+42
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this function?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, that is because analog code is still quite close to the internal code. The str coupler representation is still needed in the low-level |
||
|
|
||
|
|
||
| def _get_neighbor_coupler_freqs( | ||
| qubit_name: str, coupler_g_dict: dict[tuple[str, str], su.ValueOrSymbol] | ||
| qubit: cirq.Qid, coupler_g_dict: dict[cgc.Coupler, su.ValueOrSymbol] | ||
| ) -> dict[str, su.ValueOrSymbol]: | ||
| """Get neighbor coupler coupling strength g given qubit name.""" | ||
| return { | ||
| _coupler_name_from_qubit_pair(pair): g | ||
| for pair, g in coupler_g_dict.items() | ||
| if qubit_name in pair | ||
| _coupler_name(coupler): g | ||
| for coupler, g in coupler_g_dict.items() | ||
| if qubit in coupler.qubits | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -90,7 +90,7 @@ def make_circuit(self) -> cirq.Circuit: | |
| moments = [] | ||
| for freq_map in self.trajectory.full_trajectory[1:]: | ||
| if freq_map.is_wait_step: | ||
| targets = [_to_grid_qubit(q) for q in self.trajectory.qubits] | ||
| targets = self.trajectory.qubits | ||
| wait_gate = wg.WaitGateWithUnit( | ||
| freq_map.duration, qid_shape=cirq.qid_shape(targets) | ||
| ) | ||
|
|
@@ -119,7 +119,7 @@ def make_one_moment( | |
| q, prev_freq_map.couplings | ||
| ), | ||
| linear_rise=self.linear_qubit_ramp, | ||
| ).on(_to_grid_qubit(q)) | ||
| ).on(q) | ||
| ) | ||
| coupler_gates = [] | ||
| for p, g_max in freq_map.couplings.items(): | ||
|
|
@@ -138,7 +138,7 @@ def make_one_moment( | |
| neighbor_qubits_freq=_get_neighbor_freqs(p, freq_map.qubit_freqs), | ||
| prev_neighbor_qubits_freq=_get_neighbor_freqs(p, prev_freq_map.qubit_freqs), | ||
| interpolate_coupling_cal=self.interpolate_coupling_cal, | ||
| ).on(*sorted([_to_grid_qubit(p[0]), _to_grid_qubit(p[1])])) | ||
| ).on(p) | ||
| ) | ||
|
|
||
| return cirq.Moment(qubit_gates + coupler_gates) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call it
couplersinstead ofpairs?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, modified.