Skip to content

Commit 3108136

Browse files
committed
Merge branch 'main' into ci-daily-add-python-3.12
2 parents b6e7384 + 71c79da commit 3108136

File tree

139 files changed

+2356
-999
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+2356
-999
lines changed

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ P1 - I need this no later than the next release (end of quarter)
2727
P2 - we should do it in the next couple of quarters
2828
P3 - I'm not really blocked by it, it is an idea I'd like to discuss / suggestion based on principle
2929

30-
<!-- [optional] additional comment / context -->
30+
<!-- [optional] additional comment / context -->

.github/ISSUE_TEMPLATE/task.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: Project task
3-
about: Task to track larger efforts
3+
about: Task to track larger efforts
44
title: ''
55
labels: 'kind/task'
66
assignees: ''
@@ -16,4 +16,4 @@ assignees: ''
1616
<!-- optional, feel free to remove this section -->
1717
**Related**
1818

19-
Related issues: #abc, #xyz, ...
19+
Related issues: #abc, #xyz, ...

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ jobs:
107107
- name: Install requirements
108108
run: pip install -r dev_tools/requirements/dev.env.txt
109109
- name: RST check
110-
run: find . -type f -name "*.rst" | xargs rstcheck --report warning --ignore-directives autoclass,automodule
110+
run: find . -type f -name "*.rst" | xargs rstcheck
111111
- name: Doc check
112112
run: check/doctest -q
113113
nbformat:

CODE_OF_CONDUCT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,4 @@ harassment or threats to anyone's safety, we may take action without notice.
8989

9090
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
9191
available at
92-
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
92+
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

benchmarks/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ You can also pass arguments to the script, which would be forwarded to the `asv
1919
Please refer [Running Benchmarks guide by ASV](https://asv.readthedocs.io/en/stable/using.html#running-benchmarks) for more information.
2020

2121
## Results Database
22-
TODO([#3838](https://github.com/quantumlib/Cirq/issues/3838)): Add details regarding GCP setup.
22+
TODO([#3838](https://github.com/quantumlib/Cirq/issues/3838)): Add details regarding GCP setup.

check/all

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ cd "${topdir}" || exit $?
3838
errors=()
3939

4040
# Parse arguments.
41-
apply_arg=""
41+
apply_arg=( )
4242
only_changed=0
43-
rev=""
43+
rev=( )
4444
for arg in "$@"; do
4545
if [[ "${arg}" == "--only-changed-files" ]]; then
4646
only_changed=1
4747
elif [[ "${arg}" == "--apply-format-changes" ]]; then
48-
apply_arg="--apply"
49-
elif [ -z "${rev}" ]; then
48+
apply_arg=( "--apply" )
49+
elif [[ "${#rev[@]}" == 0 ]]; then
5050
if [ "$(git cat-file -t "${arg}" 2> /dev/null)" != "commit" ]; then
5151
echo -e "\033[31mNo revision '${arg}'.\033[0m" >&2
5252
exit 1
5353
fi
54-
rev="${arg}"
54+
rev=( "${arg}" )
5555
else
5656
echo -e "\033[31mInvalid arguments. Expected [BASE_REVISION] [--only-changed-files] [--apply-format].\033[0m" >&2
5757
exit 1
@@ -73,15 +73,16 @@ echo "Running mypy"
7373
check/mypy || errors+=( "check/mypy failed" )
7474

7575
echo "Running incremental format"
76-
check/format-incremental "${rev}" "${apply_arg}" || errors+=( "check/format-incremental failed" )
76+
check/format-incremental "${rev[@]}" "${apply_arg[@]}" ||
77+
errors+=( "check/format-incremental failed" )
7778

7879
if [ ${only_changed} -ne 0 ]; then
7980
echo "Running pytest and incremental coverage on changed files"
80-
check/pytest-changed-files-and-incremental-coverage "${rev}" ||
81+
check/pytest-changed-files-and-incremental-coverage "${rev[@]}" ||
8182
errors+=( "check/pytest-changed-files-and-incremental-coverage failed" )
8283
else
8384
echo "Running pytest and incremental coverage"
84-
check/pytest-and-incremental-coverage "${rev}" ||
85+
check/pytest-and-incremental-coverage "${rev[@]}" ||
8586
errors+=( "check/pytest-and-incremental-coverage failed" )
8687
fi
8788

check/build-changed-protos

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ cd "${topdir}" || exit $?
3232

3333
# Figure out which revision to compare against.
3434
if [ -n "$1" ] && [[ $1 != -* ]]; then
35-
if [ "$(git cat-file -t "$1" 2> /dev/null)" != "commit" ]; then
35+
if ! git rev-parse --verify --quiet --no-revs "$1^{commit}"; then
3636
echo -e "\033[31mNo revision '$1'.\033[0m" >&2
3737
exit 1
3838
fi
@@ -62,7 +62,7 @@ dev_tools/build-protos.sh
6262

6363
# Filenames with spaces will be ugly (each part will be listed separately)
6464
# but the error logic will still work.
65-
uncommitted=$(git status --porcelain 2>/dev/null | grep -E "^?? cirq-google" | cut -d " " -f 3)
65+
uncommitted=$(git status --porcelain 2>/dev/null | grep -E "^[?][?] cirq-google" | cut -d " " -f 3)
6666

6767
if [[ -n "$uncommitted" ]]; then
6868
echo -e "\033[31mERROR: Uncommitted generated files found! Please generate and commit these files using dev_tools/build-protos.sh:\033[0m"

check/format-incremental

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ for arg in "$@"; do
4646
elif [[ "${arg}" == "--all" ]]; then
4747
only_changed=0
4848
elif [ -z "${rev}" ]; then
49-
if [ "$(git cat-file -t "${arg}" 2> /dev/null)" != "commit" ]; then
49+
if ! git rev-parse --verify --quiet --no-revs "${arg}^{commit}"; then
5050
echo -e "\033[31mNo revision '${arg}'.\033[0m" >&2
5151
exit 1
5252
fi

check/pylint-changed-files

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ cd "${topdir}" || exit $?
3131

3232
# Figure out which revision to compare against.
3333
if [ -n "$1" ] && [[ $1 != -* ]]; then
34-
if [ "$(git cat-file -t "$1" 2> /dev/null)" != "commit" ]; then
34+
if ! git rev-parse --verify --quiet --no-revs "$1^{commit}"; then
3535
echo -e "\033[31mNo revision '$1'.\033[0m" >&2
3636
exit 1
3737
fi

check/pytest-and-incremental-coverage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ done
4545

4646
# Figure out which revision to compare against.
4747
if [ -n "${BASEREV}" ]; then
48-
if [ "$(git cat-file -t "${BASEREV}" 2> /dev/null)" != "commit" ]; then
48+
if ! git rev-parse --verify --quiet --no-revs "${BASEREV}^{commit}"; then
4949
echo -e "\033[31mNo revision '${BASEREV}'.\033[0m" >&2
5050
exit 1
5151
fi

check/pytest-changed-files

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ cd "${topdir}" || exit $?
3535
# Figure out which branch to compare against.
3636
rest=( "$@" )
3737
if [ -n "$1" ] && [[ $1 != -* ]]; then
38-
if [ "$(git cat-file -t "$1" 2> /dev/null)" != "commit" ]; then
38+
if ! git rev-parse --verify --quiet --no-revs "$1^{commit}"; then
3939
echo -e "\033[31mNo revision '$1'.\033[0m" >&2
4040
exit 1
4141
fi

check/pytest-changed-files-and-incremental-coverage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ cd "$(git rev-parse --show-toplevel)" || exit 1
3434

3535
# Figure out which revision to compare against.
3636
if [ -n "$1" ] && [[ $1 != -* ]]; then
37-
if [ "$(git cat-file -t "$1" 2> /dev/null)" != "commit" ]; then
37+
if ! git rev-parse --verify --quiet --no-revs "$1^{commit}"; then
3838
echo -e "\033[31mNo revision '$1'.\033[0m" >&2
3939
exit 1
4040
fi

cirq-aqt/cirq_aqt/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414

1515
"""Define version number here, read it from setup.py automatically"""
1616

17-
__version__ = "1.4.0.dev"
17+
__version__ = "1.5.0.dev"

cirq-aqt/cirq_aqt/_version_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44

55
def test_version():
6-
assert cirq_aqt.__version__ == "1.4.0.dev"
6+
assert cirq_aqt.__version__ == "1.5.0.dev"

cirq-aqt/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
requests~=2.18
1+
requests~=2.18

cirq-core/cirq/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@
332332
ZPowGate,
333333
ZZ,
334334
ZZPowGate,
335+
UniformSuperpositionGate,
335336
)
336337

337338
from cirq.transformers import (

cirq-core/cirq/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828
'of cirq (e.g. "python -m pip install cirq==1.1.*")'
2929
)
3030

31-
__version__ = "1.4.0.dev"
31+
__version__ = "1.5.0.dev"

cirq-core/cirq/_version_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44

55
def test_version():
6-
assert cirq.__version__ == "1.4.0.dev"
6+
assert cirq.__version__ == "1.5.0.dev"

cirq-core/cirq/circuits/circuit.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -145,29 +145,31 @@ class AbstractCircuit(abc.ABC):
145145
"""
146146

147147
@classmethod
148-
def from_moments(cls: Type[CIRCUIT_TYPE], *moments: 'cirq.OP_TREE') -> CIRCUIT_TYPE:
148+
def from_moments(cls: Type[CIRCUIT_TYPE], *moments: Optional['cirq.OP_TREE']) -> CIRCUIT_TYPE:
149149
"""Create a circuit from moment op trees.
150150
151151
Args:
152-
*moments: Op tree for each moment. If an op tree is a moment, it
153-
will be included directly in the new circuit. If an op tree is
154-
a circuit, it will be frozen, wrapped in a CircuitOperation, and
155-
included in its own moment in the new circuit. Otherwise, the
156-
op tree will be passed to `cirq.Moment` to create a new moment
157-
which is then included in the new circuit. Note that in the
158-
latter case we have the normal restriction that operations in a
159-
moment must be applied to disjoint sets of qubits.
152+
*moments: Op trees for each moment, which can be one of the following:
153+
- Moment: will be included directly in the new circuit.
154+
- AbstractCircuit: will be frozen, wrapped in a CircuitOperation,
155+
and included in its own moment in the new circuit.
156+
- None: will be skipped and omitted from the circuit. This can be
157+
used to include or skip a moment based on a conditional, for example.
158+
- Other OP_TREE: will be passed to `cirq.Moment` to create a new moment
159+
which is then included in the new circuit. Note that in this
160+
case we have the normal restriction that operations in a
161+
moment must be applied to disjoint sets of qubits.
160162
"""
161163
return cls._from_moments(cls._make_moments(moments))
162164

163165
@staticmethod
164-
def _make_moments(moments: Iterable['cirq.OP_TREE']) -> Iterator['cirq.Moment']:
166+
def _make_moments(moments: Iterable[Optional['cirq.OP_TREE']]) -> Iterator['cirq.Moment']:
165167
for m in moments:
166168
if isinstance(m, Moment):
167169
yield m
168170
elif isinstance(m, AbstractCircuit):
169171
yield Moment(m.freeze().to_op())
170-
else:
172+
elif m is not None:
171173
yield Moment(m)
172174

173175
@classmethod

cirq-core/cirq/circuits/circuit_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def test_from_moments():
8080
[cirq.X(c)],
8181
[],
8282
cirq.Z(d),
83+
None,
8384
[cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')],
8485
)
8586
assert circuit == cirq.Circuit(

cirq-core/cirq/contrib/svg/svg_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pylint: disable=wrong-or-nonexistent-copyright-notice
2-
import IPython.display # type: ignore
2+
import IPython.display
33
import numpy as np
44
import pytest
55

cirq-core/cirq/experiments/xeb_sampling.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
"""Estimation of fidelity associated with experimental circuit executions."""
15-
import concurrent
1615
import os
1716
import time
1817
import uuid
19-
from concurrent.futures.thread import ThreadPoolExecutor
2018
from dataclasses import dataclass
2119
from typing import (
2220
Callable,
@@ -276,18 +274,16 @@ def _execute_sample_2q_xeb_tasks_in_batches(
276274
run_batch = _SampleInBatches(
277275
sampler=sampler, repetitions=repetitions, combinations_by_layer=combinations_by_layer
278276
)
279-
with ThreadPoolExecutor(max_workers=2) as pool:
280-
futures = [pool.submit(run_batch, task_batch) for task_batch in batched_tasks]
281277

282-
records = []
283-
with progress_bar(total=len(batched_tasks) * batch_size) as progress:
284-
for future in concurrent.futures.as_completed(futures):
285-
new_records = future.result()
286-
if dataset_directory is not None:
287-
os.makedirs(f'{dataset_directory}', exist_ok=True)
288-
protocols.to_json(new_records, f'{dataset_directory}/xeb.{uuid.uuid4()}.json')
289-
records.extend(new_records)
290-
progress.update(batch_size)
278+
records = []
279+
with progress_bar(total=len(batched_tasks) * batch_size) as progress:
280+
for task in batched_tasks:
281+
new_records = run_batch(task)
282+
if dataset_directory is not None:
283+
os.makedirs(f'{dataset_directory}', exist_ok=True)
284+
protocols.to_json(new_records, f'{dataset_directory}/xeb.{uuid.uuid4()}.json')
285+
records.extend(new_records)
286+
progress.update(batch_size)
291287
return records
292288

293289

cirq-core/cirq/json_resolver_cache.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def _symmetricalqidpair(qids):
247247
'ZipLongest': cirq.ZipLongest,
248248
'ZPowGate': cirq.ZPowGate,
249249
'ZZPowGate': cirq.ZZPowGate,
250+
'UniformSuperpositionGate': cirq.UniformSuperpositionGate,
250251
# Old types, only supported for backwards-compatibility
251252
'BooleanHamiltonian': _boolean_hamiltonian_gate_op, # Removed in v0.15
252253
'CrossEntropyResult': _cross_entropy_result, # Removed in v0.16

cirq-core/cirq/ops/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,5 @@
217217
from cirq.ops.state_preparation_channel import StatePreparationChannel
218218

219219
from cirq.ops.control_values import AbstractControlValues, ProductOfSums, SumOfProducts
220+
221+
from cirq.ops.uniform_superposition_gate import UniformSuperpositionGate

cirq-core/cirq/ops/pauli_string.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,23 @@ def _validate_qubit_mapping(
11201120
)
11211121

11221122

1123+
def _try_interpret_as_pauli_string(op: Any):
1124+
"""Return a reprepresentation of an operation as a pauli string, if it is possible."""
1125+
if isinstance(op, gate_operation.GateOperation):
1126+
gates = {
1127+
common_gates.XPowGate: pauli_gates.X,
1128+
common_gates.YPowGate: pauli_gates.Y,
1129+
common_gates.ZPowGate: pauli_gates.Z,
1130+
}
1131+
if (pauli := gates.get(type(op.gate), None)) is not None:
1132+
exponent = op.gate.exponent # type: ignore
1133+
if exponent % 2 == 0:
1134+
return cirq.PauliString()
1135+
if exponent % 2 == 1:
1136+
return pauli.on(op.qubits[0])
1137+
return None
1138+
1139+
11231140
# Ignoring type because mypy believes `with_qubits` methods are incompatible.
11241141
class SingleQubitPauliStringGateOperation( # type: ignore
11251142
gate_operation.GateOperation, PauliString
@@ -1159,11 +1176,15 @@ def __mul__(self, other):
11591176
return self._as_pauli_string() * other._as_pauli_string()
11601177
if isinstance(other, (PauliString, complex, float, int)):
11611178
return self._as_pauli_string() * other
1179+
if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1180+
return self * as_pauli_string
11621181
return NotImplemented
11631182

11641183
def __rmul__(self, other):
11651184
if isinstance(other, (PauliString, complex, float, int)):
11661185
return other * self._as_pauli_string()
1186+
if (as_pauli_string := _try_interpret_as_pauli_string(other)) is not None:
1187+
return as_pauli_string * self
11671188
return NotImplemented
11681189

11691190
def __neg__(self):

cirq-core/cirq/ops/pauli_string_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,29 @@ def test_list_op_constructor_matches_mapping(pauli):
211211
assert cirq.PauliString([op]) == cirq.PauliString({q0: pauli})
212212

213213

214+
@pytest.mark.parametrize('pauli1', (cirq.X, cirq.Y, cirq.Z))
215+
@pytest.mark.parametrize('pauli2', (cirq.X, cirq.Y, cirq.Z))
216+
def test_exponent_mul_consistency(pauli1, pauli2):
217+
a, b = cirq.LineQubit.range(2)
218+
op_a, op_b = pauli1(a), pauli2(b)
219+
220+
assert op_a * op_a * op_a == op_a
221+
assert op_a * op_a**2 == op_a
222+
assert op_a**2 * op_a == op_a
223+
assert op_b * op_a * op_a == op_b
224+
assert op_b * op_a**2 == op_b
225+
assert op_a**2 * op_b == op_b
226+
assert op_a * op_a * op_a * op_a == cirq.PauliString()
227+
assert op_a * op_a**3 == cirq.PauliString()
228+
assert op_b * op_a * op_a * op_a == op_b * op_a
229+
assert op_b * op_a**3 == op_b * op_a
230+
231+
op_a, op_b = pauli1(a), pauli2(a)
232+
233+
assert op_a * op_b**3 == op_a * op_b * op_b * op_b
234+
assert op_b**3 * op_a == op_b * op_b * op_b * op_a
235+
236+
214237
def test_constructor_flexibility():
215238
a, b = cirq.LineQubit.range(2)
216239
with pytest.raises(TypeError, match='cirq.PAULI_STRING_LIKE'):

cirq-core/cirq/ops/phased_x_gate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
@value.value_equality(manual_cls=True, approximate=True)
3030
class PhasedXPowGate(raw_types.Gate):
31-
r"""A gate equivalent to $Z^{p} X^t Z^{-p}$.
31+
r"""A gate equivalent to $Z^{-p} X^t Z^{p}$ (in time order).
3232
3333
The unitary matrix of `cirq.PhasedXPowGate(exponent=t, phase_exponent=p)` is:
3434
$$

0 commit comments

Comments
 (0)