From 4b3977241526150f3198e6032167203e88dc573d Mon Sep 17 00:00:00 2001 From: Dave Bacon Date: Wed, 13 Jul 2022 11:36:25 -0700 Subject: [PATCH] Re-enable doctest (#5742) --- .../cirq/devices/grid_device_metadata.py | 15 ++-- cirq-core/cirq/ops/arithmetic_operation.py | 22 +++--- cirq-core/cirq/ops/linear_combinations.py | 20 ++--- cirq-core/cirq/ops/pauli_string.py | 18 ++--- cirq-core/cirq/ops/qid_util.py | 3 + .../stabilizer_simulation_state_test.py | 14 ++-- cirq-core/cirq/testing/repr_pretty_tester.py | 7 +- .../compilation_target_gateset.py | 31 ++++---- .../cirq/transformers/transformer_api.py | 76 +++++++++---------- .../cirq_google/devices/grid_device.py | 57 ++++++++++---- .../engine/calibration_to_noise_properties.py | 13 ++-- .../cirq_google/ops/fsim_gate_family.py | 10 +-- cirq-ionq/cirq_ionq/ionq_native_gates_test.py | 19 +++-- cirq-ionq/cirq_ionq/serializer.py | 2 +- cirq-ionq/cirq_ionq/serializer_test.py | 8 +- dev_tools/docs/run_doctest.py | 35 +++++++-- 16 files changed, 203 insertions(+), 147 deletions(-) diff --git a/cirq-core/cirq/devices/grid_device_metadata.py b/cirq-core/cirq/devices/grid_device_metadata.py index 5e52ef55246..70b9d22d9b0 100644 --- a/cirq-core/cirq/devices/grid_device_metadata.py +++ b/cirq-core/cirq/devices/grid_device_metadata.py @@ -153,16 +153,21 @@ def gate_durations(self) -> Optional[Mapping['cirq.GateFamily', 'cirq.Duration'] To look up the duration of a specific gate instance / gate type / operation which is part of the device's gateset, you can search for its corresponding GateFamily. For example: - >>> my_op = cirq.Z + >>> gateset = cirq.Gateset(cirq.ZPowGate) + >>> durations = {cirq.GateFamily(cirq.ZPowGate): cirq.Duration(nanos=1)} + >>> grid_device_metadata = cirq.GridDeviceMetadata((), gateset, durations) + >>> + >>> my_gate = cirq.Z >>> gate_durations = grid_device_metadata.gate_durations - >>> op_duration = None + >>> gate_duration = None >>> for gate_family in gate_durations: - ... if my_op in gate_family: - ... op_duration = gate_durations[gate_family] + ... if my_gate in gate_family: + ... gate_duration = gate_durations[gate_family] ... - >>> print(op_duration) + >>> print(gate_duration) 1 ns """ + return self._gate_durations def _value_equality_values_(self): diff --git a/cirq-core/cirq/ops/arithmetic_operation.py b/cirq-core/cirq/ops/arithmetic_operation.py index 4a89aae5727..29c859f4d59 100644 --- a/cirq-core/cirq/ops/arithmetic_operation.py +++ b/cirq-core/cirq/ops/arithmetic_operation.py @@ -45,19 +45,21 @@ class ArithmeticGate(Gate, metaclass=abc.ABCMeta): >>> class Add(cirq.ArithmeticGate): ... def __init__( ... self, - ... target_register: [int, Sequence[int]], - ... input_register: Union[int, Sequence[int]], + ... target_register: '[int, Sequence[int]]', + ... input_register: 'Union[int, Sequence[int]]', ... ): ... self.target_register = target_register ... self.input_register = input_register ... - ... def registers(self) -> Sequence[Union[int, Sequence[int]]]: + ... def registers(self) -> 'Sequence[Union[int, Sequence[int]]]': ... return self.target_register, self.input_register ... - ... def with_registers(self, *new_registers: Union[int, Sequence[int]]) -> TSelfGate: + ... def with_registers( + ... self, *new_registers: 'Union[int, Sequence[int]]' + ... ) -> 'TSelfGate': ... return Add(*new_registers) ... - ... def apply(self, *register_values: int) -> Union[int, Iterable[int]]: + ... def apply(self, *register_values: int) -> 'Union[int, Iterable[int]]': ... return sum(register_values) >>> cirq.unitary( ... Add(target_register=[2, 2], @@ -71,17 +73,17 @@ class ArithmeticGate(Gate, metaclass=abc.ABCMeta): ... cirq.X(cirq.LineQubit(3)), ... cirq.X(cirq.LineQubit(2)), ... cirq.X(cirq.LineQubit(6)), - ... cirq.measure(*cirq.LineQubit.range(4, 8), key='before:in'), - ... cirq.measure(*cirq.LineQubit.range(4), key='before:out'), + ... cirq.measure(*cirq.LineQubit.range(4, 8), key='before_in'), + ... cirq.measure(*cirq.LineQubit.range(4), key='before_out'), ... ... Add(target_register=[2] * 4, ... input_register=[2] * 4).on(*cirq.LineQubit.range(8)), ... - ... cirq.measure(*cirq.LineQubit.range(4, 8), key='after:in'), - ... cirq.measure(*cirq.LineQubit.range(4), key='after:out'), + ... cirq.measure(*cirq.LineQubit.range(4, 8), key='after_in'), + ... cirq.measure(*cirq.LineQubit.range(4), key='after_out'), ... ) >>> cirq.sample(c).data - before:in before:out after:in after:out + before_in before_out after_in after_out 0 2 3 2 5 ``` diff --git a/cirq-core/cirq/ops/linear_combinations.py b/cirq-core/cirq/ops/linear_combinations.py index e14fef5a55d..06f312752e0 100644 --- a/cirq-core/cirq/ops/linear_combinations.py +++ b/cirq-core/cirq/ops/linear_combinations.py @@ -379,7 +379,7 @@ class PauliSum: ... cirq.PauliString(0.5, cirq.Y(a), cirq.Y(b)) ... ]) >>> print(psum) - -1.000*X(q(0))*Y(q(1))+2.000*Z(q(0))*Z(q(1))+0.500*Y(q(0))*Y(q(1)) + -1.000*X(q(0, 0))*Y(q(0, 1))+2.000*Z(q(0, 0))*Z(q(0, 1))+0.500*Y(q(0, 0))*Y(q(0, 1)) or implicitly: @@ -387,16 +387,8 @@ class PauliSum: >>> a, b = cirq.GridQubit.rect(1, 2) >>> psum = cirq.X(a) * cirq.X(b) + 3.0 * cirq.Y(a) - >>> psum - cirq.PauliSum( - cirq.LinearDict({ - frozenset({ - (cirq.GridQubit(0, 0), cirq.X), (cirq.GridQubit(0, 1), cirq.X)}): (1+0j), - frozenset({ - (cirq.GridQubit(0, 0), cirq.Y)}): (3+0j)} - ) - ) - + >>> print(psum) + 1.000*X(q(0, 0))*X(q(0, 1))+3.000*Y(q(0, 0)) basic arithmetic and expectation operations are supported as well: @@ -413,10 +405,8 @@ class PauliSum: ... np.array([0.707106, 0, 0, 0.707106], dtype=complex), ... qubit_map={a: 0, b: 1} ... ) - >>> expectation - 4.0 - - + >>> print(f'{expectation:.1f}') + 4.0+0.0j """ def __init__(self, linear_dict: Optional[value.LinearDict[UnitPauliStringT]] = None): diff --git a/cirq-core/cirq/ops/pauli_string.py b/cirq-core/cirq/ops/pauli_string.py index 6f366dbbf84..73ed022f32f 100644 --- a/cirq-core/cirq/ops/pauli_string.py +++ b/cirq-core/cirq/ops/pauli_string.py @@ -146,20 +146,20 @@ class PauliString(raw_types.Operation, Generic[TKey]): I >>> print(cirq.PauliString(-1, cirq.X(a), cirq.Y(b), cirq.Z(c))) - -X(0)*Y(1)*Z(2) + -X(q(0))*Y(q(1))*Z(q(2)) - >>> -1 * cirq.X(a) * cirq.Y(b) * cirq.Z(c) - -X(0) * Y(1) * Z(2) + >>> print(-1 * cirq.X(a) * cirq.Y(b) * cirq.Z(c)) + -X(q(0))*Y(q(1))*Z(q(2)) >>> print(cirq.PauliString({a: cirq.X}, [-2, 3, cirq.Y(a)])) - -6j*Z(0) + -6j*Z(q(0)) >>> print(cirq.PauliString({a: cirq.I, b: cirq.X})) - X(1) + X(q(1)) >>> print(cirq.PauliString({a: cirq.Y}, ... qubit_pauli_map={a: cirq.X})) - 1j*Z(0) + 1j*Z(q(0)) Note that `cirq.PauliString`s are immutable objects. If you need a mutable version of pauli strings, see `cirq.MutablePauliString`. @@ -975,11 +975,11 @@ def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliString': Examples: >>> a, b = cirq.LineQubit.range(2) >>> print(cirq.X(a).conjugated_by(cirq.CZ(a, b))) - X(0)*Z(1) + X(q(0))*Z(q(1)) >>> print(cirq.X(a).conjugated_by(cirq.S(a))) - -Y(0) + -Y(q(0)) >>> print(cirq.X(a).conjugated_by([cirq.H(a), cirq.CNOT(a, b)])) - Z(0)*X(1) + Z(q(0))*X(q(1)) Returns: The Pauli string conjugated by the given Clifford operation. diff --git a/cirq-core/cirq/ops/qid_util.py b/cirq-core/cirq/ops/qid_util.py index eb024ac3836..dc0b1e8f74c 100644 --- a/cirq-core/cirq/ops/qid_util.py +++ b/cirq-core/cirq/ops/qid_util.py @@ -38,8 +38,11 @@ def q(*args: Union[int, str]) -> Union['cirq.LineQubit', 'cirq.GridQubit', 'cirq This is shorthand for constructing qubit ids of common types: >>> cirq.q(1) == cirq.LineQubit(1) + True >>> cirq.q(1, 2) == cirq.GridQubit(1, 2) + True >>> cirq.q("foo") == cirq.NamedQubit("foo") + True Note that arguments should be treated as positional only, even though this is only enforceable in python 3.8 or later. diff --git a/cirq-core/cirq/sim/clifford/stabilizer_simulation_state_test.py b/cirq-core/cirq/sim/clifford/stabilizer_simulation_state_test.py index 3098a5ffce5..2a8588182b4 100644 --- a/cirq-core/cirq/sim/clifford/stabilizer_simulation_state_test.py +++ b/cirq-core/cirq/sim/clifford/stabilizer_simulation_state_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from unittest.mock import Mock, call +import unittest.mock as mock import numpy as np import sympy @@ -22,7 +22,7 @@ def test_apply_gate(): q0, q1 = cirq.LineQubit.range(2) - state = Mock() + state = mock.Mock() args = cirq.StabilizerSimulationState(state=state, qubits=[q0, q1]) assert args._strat_apply_gate(cirq.X, [q0]) is True @@ -78,11 +78,11 @@ def test_apply_gate(): state.reset_mock() assert args._strat_apply_gate(cirq.SWAP, [q0, q1]) is True - state.apply_cx.assert_has_calls([call(0, 1), call(1, 0, 1.0, 0.0), call(0, 1)]) + state.apply_cx.assert_has_calls([mock.call(0, 1), mock.call(1, 0, 1.0, 0.0), mock.call(0, 1)]) state.reset_mock() assert args._strat_apply_gate(cirq.SwapPowGate(exponent=2, global_shift=1.3), [q0, q1]) is True - state.apply_cx.assert_has_calls([call(0, 1), call(1, 0, 2.0, 1.3), call(0, 1)]) + state.apply_cx.assert_has_calls([mock.call(0, 1), mock.call(1, 0, 2.0, 1.3), mock.call(0, 1)]) state.reset_mock() assert args._strat_apply_gate(cirq.BitFlipChannel(0.5), [q0]) == NotImplemented @@ -91,7 +91,7 @@ def test_apply_gate(): def test_apply_mixture(): q0 = cirq.LineQubit(0) - state = Mock() + state = mock.Mock() args = cirq.StabilizerSimulationState(state=state, qubits=[q0]) for _ in range(100): @@ -102,7 +102,7 @@ def test_apply_mixture(): def test_act_from_single_qubit_decompose(): q0 = cirq.LineQubit(0) - state = Mock() + state = mock.Mock() args = cirq.StabilizerSimulationState(state=state, qubits=[q0]) assert ( args._strat_act_from_single_qubit_decompose( @@ -122,7 +122,7 @@ def _qid_shape_(self): pass q0 = cirq.LineQubit(0) - state = Mock() + state = mock.Mock() args = cirq.StabilizerSimulationState(state=state, qubits=[q0]) assert args._strat_decompose(XContainer(), [q0]) is True state.apply_x.assert_called_with(0, 1.0, 0.0) diff --git a/cirq-core/cirq/testing/repr_pretty_tester.py b/cirq-core/cirq/testing/repr_pretty_tester.py index 7b25cf058ff..37832945a41 100644 --- a/cirq-core/cirq/testing/repr_pretty_tester.py +++ b/cirq-core/cirq/testing/repr_pretty_tester.py @@ -21,10 +21,11 @@ class FakePrinter: Can be used in tests to test a classes `_repr_pretty_` method: - >>> p = FakePrinter() - >>> s = object_under_test._repr_pretty(p, cycle=False) + >>> p = cirq.testing.FakePrinter() + >>> object_under_test = cirq.ResultDict(params=None, measurements={'x': np.array([[0, 1]] )}) + >>> s = object_under_test._repr_pretty_(p, cycle=False) >>> p.text_pretty - 'my pretty_text' + 'x=0, 1' Prefer to use `assert_repr_pretty` below. """ diff --git a/cirq-core/cirq/transformers/target_gatesets/compilation_target_gateset.py b/cirq-core/cirq/transformers/target_gatesets/compilation_target_gateset.py index 743ba3c303b..b96ea97f366 100644 --- a/cirq-core/cirq/transformers/target_gatesets/compilation_target_gateset.py +++ b/cirq-core/cirq/transformers/target_gatesets/compilation_target_gateset.py @@ -17,13 +17,10 @@ from typing import Optional, List, Hashable, TYPE_CHECKING import abc -from cirq import circuits, ops, protocols, _import +from cirq import circuits, ops, protocols, transformers from cirq.protocols.decompose_protocol import DecomposeResult from cirq.transformers import merge_k_qubit_gates, merge_single_qubit_gates -drop_empty_moments = _import.LazyLoader('drop_empty_moments', globals(), 'cirq.transformers') -drop_negligible = _import.LazyLoader('drop_negligible_operations', globals(), 'cirq.transformers') -expand_composite = _import.LazyLoader('expand_composite', globals(), 'cirq.transformers') if TYPE_CHECKING: import cirq @@ -37,16 +34,18 @@ def create_transformer_with_kwargs(transformer: 'cirq.TRANSFORMER', **kwargs) -> capture keyword arguments of a transformer before passing them as an argument to an API that expects `cirq.TRANSFORMER`. For example: - >>> def run_transformers(transformers: List[cirq.TRANSFORMER]): - >>> for transformer in transformers: - >>> transformer(circuit, context=context) - >>> - >>> transformers: List[cirq.TRANSFORMER] = [] + >>> def run_transformers(transformers: 'List[cirq.TRANSFORMER]'): + ... circuit = cirq.Circuit(cirq.X(cirq.q(0))) + ... context = cirq.TransformerContext() + ... for transformer in transformers: + ... transformer(circuit, context=context) + ... + >>> transformers: 'List[cirq.TRANSFORMER]' = [] >>> transformers.append( - >>> cirq.create_transformer_with_kwargs( - >>> cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= 2 - >>> ) - >>> ) + ... cirq.create_transformer_with_kwargs( + ... cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= 2 + ... ) + ... ) >>> transformers.append(cirq.create_transformer_with_kwargs(cirq.merge_k_qubit_unitaries, k=2)) >>> run_transformers(transformers) @@ -132,7 +131,7 @@ def preprocess_transformers(self) -> List['cirq.TRANSFORMER']: """List of transformers which should be run before decomposing individual operations.""" return [ create_transformer_with_kwargs( - expand_composite.expand_composite, + transformers.expand_composite, no_decomp=lambda op: protocols.num_qubits(op) <= self.num_qubits, ), create_transformer_with_kwargs( @@ -147,8 +146,8 @@ def postprocess_transformers(self) -> List['cirq.TRANSFORMER']: """List of transformers which should be run after decomposing individual operations.""" return [ merge_single_qubit_gates.merge_single_qubit_moments_to_phxz, - drop_negligible.drop_negligible_operations, - drop_empty_moments.drop_empty_moments, + transformers.drop_negligible_operations, + transformers.drop_empty_moments, ] diff --git a/cirq-core/cirq/transformers/transformer_api.py b/cirq-core/cirq/transformers/transformer_api.py index 3111ff00278..0526de4a1eb 100644 --- a/cirq-core/cirq/transformers/transformer_api.py +++ b/cirq-core/cirq/transformers/transformer_api.py @@ -239,25 +239,25 @@ class TRANSFORMER(Protocol): specified for each keyword argument. A transformer could be a function, for example: >>> def convert_to_cz( - >>> circuit: cirq.AbstractCircuit, - >>> *, - >>> context: Optional[cirq.TransformerContext] = None, - >>> atol: float = 1e-8, - >>> ) -> cirq.Circuit: - >>> ... + ... circuit: cirq.AbstractCircuit, + ... *, + ... context: 'Optional[cirq.TransformerContext]' = None, + ... atol: float = 1e-8, + ... ) -> cirq.Circuit: + ... ... Or it could be a class that implements `__call__` with the same API, for example: >>> class ConvertToSqrtISwaps: - >>> def __init__(self): - >>> ... - >>> def __call__( - >>> self, - >>> circuit: cirq.AbstractCircuit, - >>> *, - >>> context: Optional[cirq.TransformerContext] = None, - >>> ) -> cirq.AbstractCircuit: - >>> ... + ... def __init__(self): + ... ... + ... def __call__( + ... self, + ... circuit: cirq.AbstractCircuit, + ... *, + ... context: 'Optional[cirq.TransformerContext]' = None, + ... ) -> cirq.AbstractCircuit: + ... ... """ def __call__( @@ -300,38 +300,38 @@ def transformer(cls_or_func: Any = None, *, add_deep_support: bool = False) -> A modifying the input circuit. A transformer could be a function, for example: >>> @cirq.transformer - >>> def convert_to_cz( - >>> circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None - >>> ) -> cirq.Circuit: - >>> ... + ... def convert_to_cz( + ... circuit: cirq.AbstractCircuit, *, context: 'Optional[cirq.TransformerContext]' = None + ... ) -> cirq.Circuit: + ... ... Or it could be a class that implements `__call__` with the same API, for example: >>> @cirq.transformer - >>> class ConvertToSqrtISwaps: - >>> def __init__(self): - >>> ... - >>> def __call__( - >>> self, - >>> circuit: cirq.AbstractCircuit, - >>> *, - >>> context: Optional[cirq.TransformerContext] = None, - >>> ) -> cirq.Circuit: - >>> ... + ... class ConvertToSqrtISwaps: + ... def __init__(self): + ... ... + ... def __call__( + ... self, + ... circuit: cirq.AbstractCircuit, + ... *, + ... context: 'Optional[cirq.TransformerContext]' = None, + ... ) -> cirq.Circuit: + ... ... Note that transformers which take additional parameters as `**kwargs`, with default values specified for each keyword argument, are also supported. For example: >>> @cirq.transformer - >>> def convert_to_sqrt_iswap( - >>> circuit: cirq.AbstractCircuit, - >>> *, - >>> context: Optional[cirq.TransformerContext] = None, - >>> atol: float = 1e-8, - >>> sqrt_iswap_gate: cirq.ISwapPowGate = cirq.SQRT_ISWAP_INV, - >>> cleanup_operations: bool = True, - >>> ) -> cirq.Circuit: - >>> pass + ... def convert_to_sqrt_iswap( + ... circuit: cirq.AbstractCircuit, + ... *, + ... context: 'Optional[cirq.TransformerContext]' = None, + ... atol: float = 1e-8, + ... sqrt_iswap_gate: cirq.ISwapPowGate = cirq.SQRT_ISWAP_INV, + ... cleanup_operations: bool = True, + ... ) -> cirq.Circuit: + ... pass Args: cls_or_func: The callable class or function to be decorated. diff --git a/cirq-google/cirq_google/devices/grid_device.py b/cirq-google/cirq_google/devices/grid_device.py index 271e80a4cba..80a8a518bba 100644 --- a/cirq-google/cirq_google/devices/grid_device.py +++ b/cirq-google/cirq_google/devices/grid_device.py @@ -188,50 +188,81 @@ class GridDevice(cirq.Device): Example use cases: - * Get an instance of a Google grid device. - >>> device = cirq_google.get_engine().get_processor('processor_name').get_device() + Get an instance of a Google grid device. + >>> device = cirq_google.engine.create_device_from_processor_id("rainbow") - * Print the grid layout of the device. + Print the grid layout of the device. >>> print(device) - - * Determine whether a circuit can be run on the device. + (3, 2) + │ + │ + (4, 1)───(4, 2)───(4, 3) + │ │ │ + │ │ │ + (5, 0)───(5, 1)───(5, 2)───(5, 3)───(5, 4) + │ │ │ │ + │ │ │ │ + (6, 1)───(6, 2)───(6, 3)───(6, 4)───(6, 5) + │ │ │ │ + │ │ │ │ + (7, 2)───(7, 3)───(7, 4)───(7, 5)───(7, 6) + │ │ │ + │ │ │ + (8, 3)───(8, 4)───(8, 5) + │ + │ + (9, 4) + + Determine whether a circuit can be run on the device. + >>> circuit = cirq.Circuit(cirq.X(cirq.q(5, 1))) >>> device.validate_circuit(circuit) # Raises a ValueError if the circuit is invalid. - * Determine whether an operation can be run on the device. + Determine whether an operation can be run on the device. + >>> operation = cirq.X(cirq.q(5, 1)) >>> device.validate_operation(operation) # Raises a ValueError if the operation is invalid. - * Get the `cirq.Gateset` containing valid gates for the device, and inspect the full list - of valid gates. + Get the `cirq.Gateset` containing valid gates for the device, and inspect the full list + of valid gates. >>> gateset = device.metadata.gateset >>> print(gateset) + Gateset:... - * Determine whether a gate is available on the device. + Determine whether a gate is available on the device. + >>> gate = cirq.X >>> gate in device.metadata.gateset + True * Get a collection of valid qubits on the device. >>> device.metadata.qubit_set + frozenset({...cirq.GridQubit(6, 4)...}) * Get a collection of valid qubit pairs for two-qubit gates. >>> device.metadata.qubit_pairs + frozenset({...}) * Get a collection of isolated qubits, i.e. qubits which are not part of any qubit pair. >>> device.metadata.isolated_qubits + frozenset() * Get a collection of approximate gate durations for every gate supported by the device. >>> device.metadata.gate_durations + {...cirq.Duration...} * Get a collection of valid CompilationTargetGatesets for the device, which can be used to transform a circuit to one which only contains gates from a native target gateset supported by the device. >>> device.metadata.compilation_target_gatesets + (...cirq.CZTargetGateset...) * Assuming valid CompilationTargetGatesets exist for the device, select the first one and use it to transform a circuit to one which only contains gates from a native target gateset supported by the device. - >>> cirq.optimize_for_target_gateset( - circuit, - gateset=device.metadata.compilation_target_gatesets[0] - ) + >>> circuit = cirq.optimize_for_target_gateset( + ... circuit, + ... gateset=device.metadata.compilation_target_gatesets[0] + ... ) + >>> print(circuit) + (5, 1): ───PhXZ(a=0,x=1,z=0)─── A note about CompilationTargetGatesets: diff --git a/cirq-google/cirq_google/engine/calibration_to_noise_properties.py b/cirq-google/cirq_google/engine/calibration_to_noise_properties.py index 1263d00b82c..316fa2070a8 100644 --- a/cirq-google/cirq_google/engine/calibration_to_noise_properties.py +++ b/cirq-google/cirq_google/engine/calibration_to_noise_properties.py @@ -18,11 +18,12 @@ Given a Calibration "cal", a user can simulate noise approximating that calibration using the following pipeline: - >>> noise_props = cg.noise_properties_from_calibration(cal) - >>> noise_model = cg.NoiseModelFromGoogleNoiseProperties(noise_props) + >>> cal = cirq_google.engine.load_median_device_calibration("rainbow") + >>> noise_props = cirq_google.engine.noise_properties_from_calibration(cal) + >>> noise_model = cirq_google.NoiseModelFromGoogleNoiseProperties(noise_props) >>> simulator = cirq.Simulator(noise=noise_model) + >>> circuit = cirq.Circuit(cirq.X(cirq.GridQubit(5, 2))) >>> result = simulator.simulate(circuit) - # 'result' contains the simulation results """ from typing import Dict, Optional, Tuple, Type, TYPE_CHECKING @@ -98,8 +99,10 @@ def noise_properties_from_calibration( To manually override noise properties, call `with_params` on the output: - >>> noise_props = noise_properties_from_calibration(cal).with_params(gate_times_ns=37) - # noise_props with all gate durations set to 37ns. + >>> cal = cirq_google.engine.load_median_device_calibration("rainbow") + >>> # noise_props with all gate durations set to 37ns. + >>> noise_props = cirq_google.engine.noise_properties_from_calibration(cal).with_params( + ... gate_times_ns=37) See `cirq_google.GoogleNoiseProperties` for details. diff --git a/cirq-google/cirq_google/ops/fsim_gate_family.py b/cirq-google/cirq_google/ops/fsim_gate_family.py index d322569a754..65cb5f52b9d 100644 --- a/cirq-google/cirq_google/ops/fsim_gate_family.py +++ b/cirq-google/cirq_google/ops/fsim_gate_family.py @@ -93,17 +93,17 @@ class FSimGateFamily(cirq.GateFamily): gates in `gates_to_accept`, possibly accepting parameterized instances (assuming correct parameter value would be filled in during parameter resolution) based on `allow_symbols`: >>> gf = cirq_google.FSimGateFamily( - >>> gates_to_accept=[cirq.SQRT_ISWAP, cirq.CZPowGate, cirq_google.SYC], - >>> gate_types_to_check=[cirq.FSimGate], - >>> allow_symbols=True, - >>> ) + ... gates_to_accept=[cirq.SQRT_ISWAP, cirq.CZPowGate, cirq_google.SYC], + ... gate_types_to_check=[cirq.FSimGate], + ... allow_symbols=True, + ... ) >>> theta, phi = sympy.Symbol("theta"), sympy.Symbol("phi") >>> assert cirq.FSimGate(theta, phi) in gf # Assumes correct theta/phi will be substituted. >>> assert cirq_google.SYC in gf # SYC >>> assert cirq.FSimGate(0, np.pi / 2) in gf # CZPowGate >>> assert cirq.FSimGate(-np.pi / 4, phi) in gf # SQRT_ISWAP >>> assert cirq.FSimGate(-np.pi / 8, phi) not in gf # No value of `phi` would make it equal to - >>> # any gate/gate type in `gates_to_accept`. + ... # any gate/gate type in `gates_to_accept`. >>> assert cirq.CZ ** 0.25 not in gf # CZPowGate not in gate_types_to_check >>> assert cirq.SQRT_ISWAP not in gf # ISwapPowGate not in gate_types_to_check """ diff --git a/cirq-ionq/cirq_ionq/ionq_native_gates_test.py b/cirq-ionq/cirq_ionq/ionq_native_gates_test.py index 9697fa1db5f..bf6bb8d535c 100644 --- a/cirq-ionq/cirq_ionq/ionq_native_gates_test.py +++ b/cirq-ionq/cirq_ionq/ionq_native_gates_test.py @@ -17,15 +17,16 @@ import cirq import numpy import pytest -from .ionq_native_gates import GPIGate, GPI2Gate, MSGate + +import cirq_ionq as ionq @pytest.mark.parametrize( "gate,nqubits,diagram", [ - (GPIGate(phi=0.1), 1, "0: ───GPI(0.1)───"), - (GPI2Gate(phi=0.2), 1, "0: ───GPI2(0.2)───"), - (MSGate(phi0=0.1, phi1=0.2), 2, "0: ───MS(0.1)───\n │\n1: ───MS(0.2)───"), + (ionq.GPIGate(phi=0.1), 1, "0: ───GPI(0.1)───"), + (ionq.GPI2Gate(phi=0.2), 1, "0: ───GPI2(0.2)───"), + (ionq.MSGate(phi0=0.1, phi1=0.2), 2, "0: ───MS(0.1)───\n │\n1: ───MS(0.2)───"), ], ) def test_gate_methods(gate, nqubits, diagram): @@ -38,7 +39,9 @@ def test_gate_methods(gate, nqubits, diagram): assert c.to_text_diagram() == diagram -@pytest.mark.parametrize("gate", [GPIGate(phi=0.1), GPI2Gate(phi=0.2), MSGate(phi0=0.1, phi1=0.2)]) +@pytest.mark.parametrize( + "gate", [ionq.GPIGate(phi=0.1), ionq.GPI2Gate(phi=0.2), ionq.MSGate(phi0=0.1, phi1=0.2)] +) def test_gate_json(gate): g_json = cirq.to_json(gate) assert cirq.read_json(json_text=g_json) == gate @@ -47,7 +50,7 @@ def test_gate_json(gate): @pytest.mark.parametrize("phase", [0, 0.1, 0.4, math.pi / 2, math.pi, 2 * math.pi]) def test_gpi_unitary(phase): """Tests that the GPI gate is unitary.""" - gate = GPIGate(phi=phase) + gate = ionq.GPIGate(phi=phase) mat = cirq.protocols.unitary(gate) numpy.testing.assert_array_almost_equal(mat.dot(mat.conj().T), numpy.identity(2)) @@ -56,7 +59,7 @@ def test_gpi_unitary(phase): @pytest.mark.parametrize("phase", [0, 0.1, 0.4, math.pi / 2, math.pi, 2 * math.pi]) def test_gpi2_unitary(phase): """Tests that the GPI2 gate is unitary.""" - gate = GPI2Gate(phi=phase) + gate = ionq.GPI2Gate(phi=phase) mat = cirq.protocols.unitary(gate) numpy.testing.assert_array_almost_equal(mat.dot(mat.conj().T), numpy.identity(2)) @@ -67,7 +70,7 @@ def test_gpi2_unitary(phase): ) def test_ms_unitary(phases): """Tests that the MS gate is unitary.""" - gate = MSGate(phi0=phases[0], phi1=phases[1]) + gate = ionq.MSGate(phi0=phases[0], phi1=phases[1]) mat = cirq.protocols.unitary(gate) numpy.testing.assert_array_almost_equal(mat.dot(mat.conj().T), numpy.identity(4)) diff --git a/cirq-ionq/cirq_ionq/serializer.py b/cirq-ionq/cirq_ionq/serializer.py index 8ad7abb110a..fe7fdeace6f 100644 --- a/cirq-ionq/cirq_ionq/serializer.py +++ b/cirq-ionq/cirq_ionq/serializer.py @@ -21,7 +21,7 @@ import cirq from cirq.devices import line_qubit from cirq.ops import common_gates, parity_gates -from .ionq_native_gates import GPIGate, GPI2Gate, MSGate +from cirq_ionq.ionq_native_gates import GPIGate, GPI2Gate, MSGate _NATIVE_GATES = cirq.Gateset( GPIGate, GPI2Gate, MSGate, cirq.MeasurementGate, unroll_circuit_op=False diff --git a/cirq-ionq/cirq_ionq/serializer_test.py b/cirq-ionq/cirq_ionq/serializer_test.py index 826fca96011..6ccb811d5e9 100644 --- a/cirq-ionq/cirq_ionq/serializer_test.py +++ b/cirq-ionq/cirq_ionq/serializer_test.py @@ -19,8 +19,6 @@ import cirq import cirq_ionq as ionq -from .ionq_native_gates import GPIGate, GPI2Gate, MSGate - def test_serialize_empty_circuit_invalid(): empty = cirq.Circuit() @@ -256,9 +254,9 @@ def test_serialize_measurement_gate_split_across_dict(): def test_serialize_native_gates(): q0, q1, q2 = cirq.LineQubit.range(3) - gpi = GPIGate(phi=0.1).on(q0) - gpi2 = GPI2Gate(phi=0.2).on(q1) - ms = MSGate(phi0=0.3, phi1=0.4).on(q1, q2) + gpi = ionq.GPIGate(phi=0.1).on(q0) + gpi2 = ionq.GPI2Gate(phi=0.2).on(q1) + ms = ionq.MSGate(phi0=0.3, phi1=0.4).on(q1, q2) circuit = cirq.Circuit([gpi, gpi2, ms]) serializer = ionq.Serializer() result = serializer.serialize(circuit) diff --git a/dev_tools/docs/run_doctest.py b/dev_tools/docs/run_doctest.py index fd20a5330e1..2e424034c26 100755 --- a/dev_tools/docs/run_doctest.py +++ b/dev_tools/docs/run_doctest.py @@ -47,7 +47,13 @@ def __init__(self, file_name: str, mod: ModuleType, test_globals: Dict[str, Any] self.test_globals = test_globals def run(self) -> doctest.TestResults: - return doctest.testmod(self.mod, globs=self.test_globals, report=False, verbose=False) + return doctest.testmod( + self.mod, + globs=self.test_globals, + report=False, + verbose=False, + optionflags=doctest.ELLIPSIS, + ) def run_tests( @@ -112,11 +118,18 @@ def load_tests( try_print = lambda *args, **kwargs: None if include_modules: import cirq + import cirq_google import numpy import sympy import pandas - base_globals = {'cirq': cirq, 'np': numpy, 'sympy': sympy, 'pd': pandas} + base_globals = { + 'cirq': cirq, + 'cirq_google': cirq_google, + 'np': numpy, + 'pd': pandas, + 'sympy': sympy, + } else: base_globals = {} @@ -208,9 +221,19 @@ def import_file(file_path: str) -> ModuleType: def main(): quiet = len(sys.argv) >= 2 and sys.argv[1] == '-q' - file_names = glob.glob('cirq/**/*.py', recursive=True) + file_names = glob.glob('cirq**/cirq**/**/*.py', recursive=True) + assert file_names # Remove the engine client code. - file_names = [f for f in file_names if not f.startswith('cirq/google/engine/client/')] + excluded = [ + 'cirq-google/cirq_google/engine/client/', + 'cirq-google/cirq_google/cloud/', + 'cirq-google/cirq_google/api/', + ] + file_names = [ + f + for f in file_names + if not (any(f.startswith(x) for x in excluded) or f.endswith("_test.py")) + ] failed, attempted = run_tests( file_names, include_modules=True, include_local=False, quiet=quiet ) @@ -218,9 +241,7 @@ def main(): if failed != 0: print( shell_tools.highlight( - 'Failed: {} failed, {} passed, {} total'.format( - failed, attempted - failed, attempted - ), + f'Failed: {failed} failed, {attempted - failed} passed, {attempted} total', shell_tools.RED, ) )