Skip to content

Commit

Permalink
Merge branch 'main' into mhucka-add-debug-workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
mhucka authored Jan 9, 2025
2 parents c817d11 + ecf9ed7 commit 5b22565
Show file tree
Hide file tree
Showing 25 changed files with 385 additions and 156 deletions.
50 changes: 44 additions & 6 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,57 @@
name: "Mark and close stale issues"
# Summary: perform stale issue & PR handling on a schedule
# For more info, see https://github.com/actions/stale/

name: "Label and close stale issues & PRs"

on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
inputs:
debug:
# Note: the job body sets `debug-only` to false by default. The value
# of inputs.debug is an empty string unless this workflow is invoked
# manually. When it's invoked manually, GitHub's GUI presents the user
# with a checkbox for this flag; we default that checkbox to true
# because the most likely reason for a manual run is debugging.
description: "Run in debug mode (dry run)"
type: boolean
default: true

jobs:
stale:
name: Label and/or close stale issues and PRs
runs-on: ubuntu-20.04
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days'
days-before-stale: 30
days-before-close: 30
close-issue-message: 'Issue closed due to inactivity.'
repo-token: ${{secrets.GITHUB_TOKEN}}
debug-only: ${{inputs.debug || false}}
days-before-stale: 90
days-before-close: 60
stale-issue-label: 'status/stale'
stale-pr-label: 'status/stale'
exempt-issue-labels: 'triage/accepted,triage/discuss,kind/design-issue,kind/health,kind/roadmap-item,kind/task'
stale-issue-message: >
This issue has been automatically labeled as stale because 90 days
have passed without comments or other activity. If no further
activity occurs and the `status/stale` label is not removed within
60 days, it will be closed. If you believe this is in error or would
like to discuss it further, please leave a comment here.
stale-pr-message: >
This pull request has been automatically labeled as stale because 90
days have passed without comments or other activity. If no further
activity occurs and the `status/stale` label is not removed within 60
days, it will be closed. If you believe this is in error or would
like to discuss it further, please leave a comment here.
close-issue-message: >
This issue has been closed due to inactivity for 60 days since the
time the stale label was applied. If you believe this is in error or
would like to discuss it further, please either open a new issue
(and reference this one in it, for continuity) or reach out to the
Cirq project maintainers at [email protected].
close-pr-message: >
This pull-request has been closed due to inactivity for 60 days
since the time the stale label was applied. If you believe this is
in error or would like to discuss it further, please reach out to
the Cirq project maintainers at [email protected].
18 changes: 18 additions & 0 deletions cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,24 @@ def transform_qubits(
) -> 'cirq.Circuit':
"""Returns the same circuit, but with different qubits.
This function will return a new `Circuit` with the same gates but
with qubits mapped according to the argument.
For example, the following will translate LineQubits to GridQubits:
>>> grid_qubits = cirq.GridQubit.square(2)
>>> line_qubits = cirq.LineQubit.range(4)
>>> circuit = cirq.Circuit([cirq.H(q) for q in line_qubits])
>>> circuit.transform_qubits(lambda q : grid_qubits[q.x])
cirq.Circuit([
cirq.Moment(
cirq.H(cirq.GridQubit(0, 0)),
cirq.H(cirq.GridQubit(0, 1)),
cirq.H(cirq.GridQubit(1, 0)),
cirq.H(cirq.GridQubit(1, 1)),
),
])
Args:
qubit_map: A function or a dict mapping each current qubit into a desired
new qubit.
Expand Down
49 changes: 32 additions & 17 deletions cirq-core/cirq/circuits/circuit_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def __init__(
repetition_ids: Optional[Sequence[str]] = None,
parent_path: Tuple[str, ...] = (),
extern_keys: FrozenSet['cirq.MeasurementKey'] = frozenset(),
use_repetition_ids: bool = True,
use_repetition_ids: Optional[bool] = None,
repeat_until: Optional['cirq.Condition'] = None,
):
"""Initializes a CircuitOperation.
Expand Down Expand Up @@ -120,7 +120,8 @@ def __init__(
use_repetition_ids: When True, any measurement key in the subcircuit
will have its path prepended with the repetition id for each
repetition. When False, this will not happen and the measurement
key will be repeated.
key will be repeated. When None, default to False unless the caller
passes `repetition_ids` explicitly.
repeat_until: A condition that will be tested after each iteration of
the subcircuit. The subcircuit will repeat until condition returns
True, but will always run at least once, and the measurement key
Expand Down Expand Up @@ -156,6 +157,8 @@ def __init__(
# Ensure that the circuit is invertible if the repetitions are negative.
self._repetitions = repetitions
self._repetition_ids = None if repetition_ids is None else list(repetition_ids)
if use_repetition_ids is None:
use_repetition_ids = repetition_ids is not None
self._use_repetition_ids = use_repetition_ids
if isinstance(self._repetitions, float):
if math.isclose(self._repetitions, round(self._repetitions)):
Expand Down Expand Up @@ -263,7 +266,7 @@ def replace(self, **changes) -> 'cirq.CircuitOperation':
'repetition_ids': self.repetition_ids,
'parent_path': self.parent_path,
'extern_keys': self._extern_keys,
'use_repetition_ids': self.use_repetition_ids,
'use_repetition_ids': True if 'repetition_ids' in changes else self.use_repetition_ids,
'repeat_until': self.repeat_until,
**changes,
}
Expand Down Expand Up @@ -448,11 +451,9 @@ def __repr__(self):
args += f'param_resolver={proper_repr(self.param_resolver)},\n'
if self.parent_path:
args += f'parent_path={proper_repr(self.parent_path)},\n'
if self.repetition_ids != self._default_repetition_ids():
if self.use_repetition_ids:
# Default repetition_ids need not be specified.
args += f'repetition_ids={proper_repr(self.repetition_ids)},\n'
if not self.use_repetition_ids:
args += 'use_repetition_ids=False,\n'
if self.repeat_until:
args += f'repeat_until={self.repeat_until!r},\n'
indented_args = args.replace('\n', '\n ')
Expand All @@ -477,14 +478,15 @@ def dict_str(d: Mapping) -> str:
args.append(f'params={self.param_resolver.param_dict}')
if self.parent_path:
args.append(f'parent_path={self.parent_path}')
if self.repetition_ids != self._default_repetition_ids():
# Default repetition_ids need not be specified.
args.append(f'repetition_ids={self.repetition_ids}')
if self.use_repetition_ids:
if self.repetition_ids != self._default_repetition_ids():
args.append(f'repetition_ids={self.repetition_ids}')
else:
# Default repetition_ids need not be specified.
args.append(f'loops={self.repetitions}, use_repetition_ids=True')
elif self.repetitions != 1:
# Only add loops if we haven't added repetition_ids.
# Add loops if not using repetition_ids.
args.append(f'loops={self.repetitions}')
if not self.use_repetition_ids:
args.append('no_rep_ids')
if self.repeat_until:
args.append(f'until={self.repeat_until}')
if not args:
Expand Down Expand Up @@ -529,10 +531,9 @@ def _json_dict_(self):
'measurement_key_map': self.measurement_key_map,
'param_resolver': self.param_resolver,
'repetition_ids': self.repetition_ids,
'use_repetition_ids': self.use_repetition_ids,
'parent_path': self.parent_path,
}
if not self.use_repetition_ids:
resp['use_repetition_ids'] = False
if self.repeat_until:
resp['repeat_until'] = self.repeat_until
return resp
Expand Down Expand Up @@ -566,7 +567,10 @@ def _from_json_dict_(
# Methods for constructing a similar object with one field modified.

def repeat(
self, repetitions: Optional[IntParam] = None, repetition_ids: Optional[Sequence[str]] = None
self,
repetitions: Optional[IntParam] = None,
repetition_ids: Optional[Sequence[str]] = None,
use_repetition_ids: Optional[bool] = None,
) -> 'CircuitOperation':
"""Returns a copy of this operation repeated 'repetitions' times.
Each repetition instance will be identified by a single repetition_id.
Expand All @@ -577,6 +581,10 @@ def repeat(
defaults to the length of `repetition_ids`.
repetition_ids: List of IDs, one for each repetition. If unset,
defaults to `default_repetition_ids(repetitions)`.
use_repetition_ids: If given, this specifies the value for `use_repetition_ids`
of the resulting circuit operation. If not given, we enable ids if
`repetition_ids` is not None, and otherwise fall back to
`self.use_repetition_ids`.
Returns:
A copy of this operation repeated `repetitions` times with the
Expand All @@ -591,6 +599,9 @@ def repeat(
ValueError: Unexpected length of `repetition_ids`.
ValueError: Both `repetitions` and `repetition_ids` are None.
"""
if use_repetition_ids is None:
use_repetition_ids = True if repetition_ids is not None else self.use_repetition_ids

if repetitions is None:
if repetition_ids is None:
raise ValueError('At least one of repetitions and repetition_ids must be set')
Expand All @@ -604,7 +615,7 @@ def repeat(
expected_repetition_id_length: int = np.abs(repetitions)

if repetition_ids is None:
if self.use_repetition_ids:
if use_repetition_ids:
repetition_ids = default_repetition_ids(expected_repetition_id_length)
elif len(repetition_ids) != expected_repetition_id_length:
raise ValueError(
Expand All @@ -617,7 +628,11 @@ def repeat(

# The eventual number of repetitions of the returned CircuitOperation.
final_repetitions = protocols.mul(self.repetitions, repetitions)
return self.replace(repetitions=final_repetitions, repetition_ids=repetition_ids)
return self.replace(
repetitions=final_repetitions,
repetition_ids=repetition_ids,
use_repetition_ids=use_repetition_ids,
)

def __pow__(self, power: IntParam) -> 'cirq.CircuitOperation':
return self.repeat(power)
Expand Down
Loading

0 comments on commit 5b22565

Please sign in to comment.