GRID_STAGGERED_PATTERN = ( GridInteractionLayer(col_offset=0, vertical=True, stagger=True), # A GridInteractionLayer(col_offset=1, vertical=True, stagger=True), # B GridInteractionLayer(col_offset=1, vertical=False, stagger=True), # C GridInteractionLayer(col_offset=0, vertical=False, stagger=True), # D GridInteractionLayer(col_offset=1, vertical=False, stagger=True), # C GridInteractionLayer(col_offset=0, vertical=False, stagger=True), # D GridInteractionLayer(col_offset=0, vertical=True, stagger=True), # A GridInteractionLayer(col_offset=1, vertical=True, stagger=True), # B ) document( GRID_STAGGERED_PATTERN, """A pattern of two-qubit gates that is hard to simulate. This pattern of gates was used in the paper https://www.nature.com/articles/s41586-019-1666-5 to demonstrate quantum supremacy. """, ) HALF_GRID_STAGGERED_PATTERN = ( GridInteractionLayer(col_offset=0, vertical=True, stagger=True), # A GridInteractionLayer(col_offset=1, vertical=True, stagger=True), # B GridInteractionLayer(col_offset=1, vertical=False, stagger=True), # C GridInteractionLayer(col_offset=0, vertical=False, stagger=True), # D ) document( HALF_GRID_STAGGERED_PATTERN, """A pattern that is half of GRID_STAGGERED_PATTERN.
from typing import List, Optional, Type, Union, cast, TYPE_CHECKING import numpy as np from cirq import circuits, protocols, study, devices, ops, value from cirq._doc import document from cirq.sim import sparse_simulator, density_matrix_simulator from cirq.sim.clifford import clifford_simulator if TYPE_CHECKING: import cirq CIRCUIT_LIKE = Union[circuits.Circuit, ops.Gate, ops.OP_TREE] document( CIRCUIT_LIKE, # type: ignore """A `circuits.Circuit` or a value that can be trivially converted into it: a gate, an operation, and a list or tree of operations. """, ) def _is_clifford_circuit(program: 'cirq.Circuit') -> bool: return all( clifford_simulator.CliffordSimulator.is_supported_operation(op) for op in program.all_operations() ) def sample( program: 'cirq.Circuit', *, noise: 'cirq.NOISE_MODEL_LIKE' = None,
import cirq DEFAULT_COMPLEX_DTYPE = np.complex64 STATE_VECTOR_LIKE = Union[ # Full big-endian computational basis state index. int, # Per-qudit computational basis values. Sequence[int], # Explicit state vector or state tensor. np.ndarray, Sequence[Union[int, float, complex]], # Product state object 'cirq.ProductState', ] document(STATE_VECTOR_LIKE, """An object representing a state vector.""") # type: ignore QUANTUM_STATE_LIKE = Union[ # state vector STATE_VECTOR_LIKE, # density matrix np.ndarray, # quantum state object 'cirq.QuantumState', ] document(QUANTUM_STATE_LIKE, """An object representing a quantum state.""") # type: ignore class QuantumState: """A quantum state.
def __new__(cls, qubits: Sequence['cirq.Qid']): return IdentityGate(qid_shape=protocols.qid_shape(qubits)).on(*qubits) @property def qubits(self) -> Tuple['cirq.Qid', ...]: raise NotImplementedError('deprecated') def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'cirq.Operation': raise NotImplementedError('deprecated') I = IdentityGate(num_qubits=1) document( I, """The one qubit identity gate. Matrix: [[1, 0], [0, 1]] """) def identity_each(*qubits: 'cirq.Qid') -> 'cirq.Operation': """Returns a single IdentityGate applied to all the given qubits. Args: *qubits: The qubits that the identity gate will apply to. Returns: An identity operation on the given qubits. Raises:
SYC_SERIALIZER, *SINGLE_QUBIT_SERIALIZERS, *SINGLE_QUBIT_HALF_PI_SERIALIZERS, MEASUREMENT_SERIALIZER, WAIT_GATE_SERIALIZER, ], deserializers=[ SYC_DESERIALIZER, *SINGLE_QUBIT_DESERIALIZERS, *SINGLE_QUBIT_HALF_PI_DESERIALIZERS, MEASUREMENT_DESERIALIZER, WAIT_GATE_DESERIALIZER, ], ) document( SYC_GATESET, """Gate set with fsim(pi/4, pi/6) as the core 2 qubit interaction.""") SQRT_ISWAP_GATESET = serializable_gate_set.SerializableGateSet( gate_set_name='sqrt_iswap', serializers=[ *SQRT_ISWAP_SERIALIZERS, *SINGLE_QUBIT_SERIALIZERS, MEASUREMENT_SERIALIZER, WAIT_GATE_SERIALIZER, ], deserializers=[ *SQRT_ISWAP_DESERIALIZERS, *SINGLE_QUBIT_DESERIALIZERS, MEASUREMENT_DESERIALIZER, WAIT_GATE_DESERIALIZER,
@property def keys(self) -> List[str]: return [] def __len__(self) -> int: return 1 def param_tuples(self) -> Iterator[Params]: yield () def __repr__(self): return 'cirq.UnitSweep' UnitSweep = _Unit() document(UnitSweep, """The singleton sweep with no parameters.""") class Product(Sweep): """Cartesian product of one or more sweeps. If one sweep assigns 'a' to the values 0, 1, 2, and the second sweep assigns 'b' to the values 2, 3, then the product is a sweep that assigns the tuple ('a','b') to all possible combinations of these assignments: (0, 2), (1, 2), (2, 2), (0, 3), (1, 3), (2, 3). """ def __init__(self, *factors: Sweep) -> None: _check_duplicate_keys(factors) self.factors = factors
@property def basis(self: '_PauliZ') -> Dict[int, '_ZEigenState']: from cirq.value.product_state import _ZEigenState return { +1: _ZEigenState(+1), -1: _ZEigenState(-1), } X = _PauliX() document( X, """The Pauli X gate. Matrix: [[0, 1], [1, 0]] """, ) Y = _PauliY() document( Y, """The Pauli Y gate. Matrix: [[0, -i], [i, 0]] """,
from typing import Dict, Tuple import numpy as np from cirq import value from cirq._doc import document PAULI_BASIS = { 'I': np.eye(2), 'X': np.array([[0., 1.], [1., 0.]]), 'Y': np.array([[0., -1j], [1j, 0.]]), 'Z': np.diag([1., -1]), } document( PAULI_BASIS, """The four Pauli matrices (including identity) keyed by character.""") def kron_bases(*bases: Dict[str, np.ndarray], repeat: int = 1) -> Dict[str, np.ndarray]: """Creates tensor product of bases.""" product_basis = {'': 1} for basis in bases * repeat: product_basis = { name1 + name2: np.kron(matrix1, matrix2) for name1, matrix1 in product_basis.items() for name2, matrix2 in basis.items() } return product_basis
from typing import Any, cast, Dict, NamedTuple, Optional, Sequence, Tuple, TYPE_CHECKING, Union import numpy as np from cirq import protocols, value, linalg from cirq._doc import document from cirq.ops import common_gates, gate_features, named_qubit, pauli_gates from cirq.ops.pauli_gates import Pauli from cirq.type_workarounds import NotImplementedType if TYPE_CHECKING: import cirq PauliTransform = NamedTuple('PauliTransform', [('to', Pauli), ('flip', bool)]) document(PauliTransform, """+X, -X, +Y, -Y, +Z, or -Z.""") def _to_pauli_transform(matrix: np.ndarray) -> Optional[PauliTransform]: """Converts matrix to PauliTransform. If matrix is not ±Pauli matrix, returns None. """ for pauli in Pauli._XYZ: p = protocols.unitary(pauli) if np.allclose(matrix, p): return PauliTransform(pauli, False) if np.allclose(matrix, -p): return PauliTransform(pauli, True) return None
# coverage: ignore raise ValueError("Bad eigenvalue: {}".format(self.eigenvalue)) def stabilized_by(self) -> Tuple[int, 'cirq.Pauli']: from cirq import ops return self.eigenvalue, ops.Z KET_PLUS = _XEigenState(eigenvalue=+1) document( KET_PLUS, """The |+⟩ State This is the state such that X|+⟩ = +1 |+⟩ Vector: [1, 1] / sqrt(2) """, ) KET_MINUS = _XEigenState(eigenvalue=-1) document( KET_MINUS, """The |-⟩ State This is the state such that X|-⟩ = -1 |-⟩ Vector:
from cirq import protocols from cirq._compat import proper_repr from cirq._doc import document if TYPE_CHECKING: import cirq DURATION_LIKE = Union[None, datetime.timedelta, 'cirq.Duration'] document( DURATION_LIKE, # type: ignore """A `cirq.Duration` or value that can trivially converted to one. A `datetime.timedelta` is a `cirq.DURATION_LIKE`. It is converted while preserving its duration. `None` is a `cirq.DURATION_LIKE` that converts into a zero-length duration. Note that 0 is a `DURATION_LIKE`, despite the fact that `int` is not listed, because 0 is the only integer where the physical unit doesn't matter. """, ) class Duration: """A time delta that supports symbols and picosecond accuracy.""" def __init__( self, value: DURATION_LIKE = None, *, # Force keyword args. picos: Union[int, float, sympy.Basic] = 0,
from cirq import protocols, value from cirq._doc import document from cirq.linalg import operator_spaces from cirq.ops import identity, raw_types, pauli_gates, pauli_string from cirq.ops.pauli_string import PauliString, _validate_qubit_mapping from cirq.value.linear_dict import _format_terms if TYPE_CHECKING: import cirq UnitPauliStringT = FrozenSet[Tuple[raw_types.Qid, pauli_gates.Pauli]] PauliSumLike = Union[int, float, complex, PauliString, 'PauliSum', pauli_string.SingleQubitPauliStringGateOperation] document( PauliSumLike, # type: ignore """Any value that can be easily translated into a sum of Pauli products. """) class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]): """Represents linear operator defined by a linear combination of gates. Suppose G1, G2, ..., Gn are gates and b1, b2, ..., bn are complex numbers. Then LinearCombinationOfGates({G1: b1, G2: b2, ..., Gn: bn}) represents the linear operator A = b1 G1 + b2 G2 + ... + bn Gn
moment, ops.Moment([ # TODO: Replace with "VirtualTag" class instance. self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits ]) ] def _json_dict_(self): return protocols.obj_to_dict_helper(self, ['qubit_noise_gate']) NO_NOISE: 'cirq.NoiseModel' = _NoNoiseModel() document( NO_NOISE, """The trivial noise model with no effects. This is the noise model used when a `NOISE_MODEL_LIKE` noise parameter is set to `None`. """) NOISE_MODEL_LIKE = Union[None, 'cirq.NoiseModel', 'cirq.SingleQubitGate'] document( NOISE_MODEL_LIKE, # type: ignore """A `cirq.NoiseModel` or a value that can be trivially converted into one. `None` is a `NOISE_MODEL_LIKE`. It will be replaced by the `cirq.NO_NOISE` noise model. A single qubit gate is a `NOISE_MODEL_LIKE`. It will be wrapped inside of a `cirq.ConstantQubitNoiseModel`. """)
from cirq.protocols import json_serializable_dataclass from cirq.work.observable_measurement_data import BitstringAccumulator from cirq.work.observable_settings import ( InitObsSetting, _MeasurementSpec, ) if TYPE_CHECKING: import cirq from cirq.value.product_state import _NamedOneQubitState MAX_REPETITIONS_PER_JOB = 3_000_000 document( MAX_REPETITIONS_PER_JOB, """The maximum repetitions allowed in a single batch job. This depends on the Sampler executing your batch job. It is set to be tens of minutes assuming ~kilosamples per second. """, ) def _with_parameterized_layers( circuit: 'cirq.Circuit', qubits: Sequence['cirq.Qid'], needs_init_layer: bool, ) -> 'cirq.Circuit': """Return a copy of the input circuit with parameterized single-qubit rotations. These rotations flank the circuit: the initial two layers of X and Y gates are given parameter names "{qubit}-Xi" and "{qubit}-Yi" and are used to set up the initial state. If `needs_init_layer` is False,
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Defines which types are Sweepable.""" from typing import Dict, Iterable, Iterator, List, Sequence, Union, cast import warnings from cirq._doc import document from cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType from cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep SweepLike = Union[ParamResolverOrSimilarType, Sweep] document(SweepLike, """An object similar to an iterable of parameter resolvers.""" ) # type: ignore Sweepable = Union[SweepLike, Iterable[SweepLike]] document( Sweepable, # type: ignore """An object or collection of objects representing a parameter sweep.""", ) def to_resolvers(sweepable: Sweepable) -> Iterator[ParamResolver]: """Convert a Sweepable to a list of ParamResolvers.""" for sweep in to_sweeps(sweepable): yield from sweep
def _value_equality_values_(self) -> Any: return self.phi def _circuit_diagram_info_( self, args: 'cirq.CircuitDiagramInfoArgs' ) -> Union[str, 'protocols.CircuitDiagramInfo']: return protocols.CircuitDiagramInfo( wire_symbols=(f'GPI({self.phase!r})', )) GPI = GPIGate(phi=0) document( GPI, r"""The GPI gate is a single qubit gate. The unitary of this gate is [[0, e^{-i*2*\pi*\phi}], [e^{-i*2*\pi*\phi}, 0]] It is driven by Rabi laser. https://ionq.com/best-practices """, ) @cirq.value.value_equality class GPI2Gate(cirq.Gate): r"""The GPI2 gate is a single qubit gate. The unitary of this gate is \frac{1}{/\sqrt{2}}[[1, -i*e^{-i\phi}], [-i*e^{-i\phi}, 1]] """ def __init__(self, *, phi): self.phi = phi
def riswap(rads: value.TParamVal) -> ISwapPowGate: """Returns gate with matrix exp(+i angle_rads (X⊗X + Y⊗Y) / 2).""" pi = sympy.pi if protocols.is_parameterized(rads) else np.pi return ISwapPowGate()**(2 * rads / pi) SWAP = SwapPowGate() document( SWAP, """The swap gate. Matrix: ``` [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]] ``` """, ) ISWAP = ISwapPowGate() document( ISWAP, """The iswap gate. Matrix: ``` [[1, 0, 0, 0],
def riswap(rads: value.TParamVal) -> ISwapPowGate: """Returns gate with matrix exp(+i angle_rads (X⊗X + Y⊗Y) / 2).""" pi = sympy.pi if protocols.is_parameterized(rads) else np.pi return ISwapPowGate()**(2 * rads / pi) SWAP = SwapPowGate() document( SWAP, r"""The swap gate. This gate will swap two qubits (in any basis). The unitary matrix of this gate is: $$ \begin{bmatrix} 1 & 0 & 0 & 0 \\ & 0 & 1 & 0 \\ & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} $$ """, ) ISWAP = ISwapPowGate() document( ISWAP, r"""The iswap gate. The unitary matrix of this gate is:
formatter: 'cirq.QuilFormatter') -> Optional[str]: return ''.join(formatter.format('I {0}\n', qubit) for qubit in qubits) @classmethod def _from_json_dict_(cls, num_qubits, qid_shape=None, **kwargs): return cls(num_qubits=num_qubits, qid_shape=None if qid_shape is None else tuple(qid_shape)) I = IdentityGate(num_qubits=1) document( I, """The one qubit identity gate. Matrix: ``` [[1, 0], [0, 1]] ``` """, ) def identity_each(*qubits: 'cirq.Qid') -> 'cirq.Operation': """Returns a single IdentityGate applied to all the given qubits. Args: *qubits: The qubits that the identity gate will apply to. Returns: An identity operation on the given qubits.
determines the behavior of the empty kron product. Returns: The kronecker product of all the inputs. """ product = np.ones(shape=(1, ) * shape_len) for m in factors: product = np.kron(product, m) return np.array(product) CONTROL_TAG = np.array([[float('nan'), 0], [0, 1]]) document( CONTROL_TAG, """A special indicator value for `cirq.kron_with_controls`. This value is a stand-in for "control operations on the other qubits based on the value of this qubit", which otherwise doesn't have a proper matrix. """, ) def kron_with_controls( *factors: Union[np.ndarray, complex, float]) -> np.ndarray: """Computes the kronecker product of a sequence of values and control tags. Use `cirq.CONTROL_TAG` to represent controls. Any entry of the output corresponding to a situation where the control is not satisfied will be overwritten by identity matrix elements. The control logic works by imbuing NaN with the meaning "failed to meet one or more controls". The normal kronecker product then spreads the per-item
pi = sympy.pi if protocols.is_parameterized(rads) else np.pi return ZPowGate(exponent=rads / pi, global_shift=-0.5) @deprecated(deadline='v0.8.0', fix='Use cirq.rz, instead.') def Rz(rads: value.TParamVal) -> ZPowGate: """Returns a gate with the matrix e^{-i Z rads / 2}.""" return rz(rads) H = HPowGate() document( H, """The Hadamard gate. The `exponent=1` instance of `cirq.HPowGate`. Matrix: [[s, s], [s, -s]] where s = sqrt(0.5). """) S = ZPowGate(exponent=0.5) document( S, """The Clifford S gate. The `exponent=0.5` instance of `cirq.ZPowGate`. Matrix: [[1, 0], [0, i]] """)
'constant': self._repr, } Foxtail = _NamedConstantXmonDevice( 'cirq_google.Foxtail', measurement_duration=cirq.Duration(nanos=4000), exp_w_duration=cirq.Duration(nanos=20), exp_11_duration=cirq.Duration(nanos=50), qubits=_parse_device(_FOXTAIL_GRID)[0], ) document( Foxtail, f"""72 xmon qubit device. **Qubit grid**: ``` {str(Foxtail)} ``` """, ) # Duration dict in picoseconds _DURATIONS_FOR_XMON = { 'cz': 45_000, 'xy': 15_000, 'z': 0, 'meas': 4_000_000, # 1000ns for readout, 3000ns for "ring down" } FOXTAIL_PROTO = create_device_proto_from_diagram(_FOXTAIL_GRID, [gate_sets.XMON],
qubits[0], qubits[1]) def riswap(rads: value.TParamVal) -> ISwapPowGate: """Returns gate with matrix exp(+i angle_rads (X⊗X + Y⊗Y) / 2).""" pi = sympy.pi if protocols.is_parameterized(rads) else np.pi return ISwapPowGate()**(2 * rads / pi) SWAP = SwapPowGate() document( SWAP, """The swap gate. Matrix: [[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]] """, ) ISWAP = ISwapPowGate() document( ISWAP, """The iswap gate. Matrix: [[1, 0, 0, 0], [0, 0, i, 0],
GRID_STAGGERED_PATTERN = ( GridInteractionLayer(col_offset=0, vertical=True, stagger=True), # A GridInteractionLayer(col_offset=1, vertical=True, stagger=True), # B GridInteractionLayer(col_offset=1, vertical=False, stagger=True), # C GridInteractionLayer(col_offset=0, vertical=False, stagger=True), # D GridInteractionLayer(col_offset=1, vertical=False, stagger=True), # C GridInteractionLayer(col_offset=0, vertical=False, stagger=True), # D GridInteractionLayer(col_offset=0, vertical=True, stagger=True), # A GridInteractionLayer(col_offset=1, vertical=True, stagger=True), # B ) document( GRID_STAGGERED_PATTERN, """A pattern of two-qubit gates that is hard to simulate. This pattern of gates was used in the paper https://www.nature.com/articles/s41586-019-1666-5 to demonstrate quantum supremacy. """) GRID_ALIGNED_PATTERN = ( GridInteractionLayer(col_offset=0, vertical=False, stagger=False), # E GridInteractionLayer(col_offset=1, vertical=False, stagger=False), # F GridInteractionLayer(col_offset=0, vertical=True, stagger=False), # G GridInteractionLayer(col_offset=1, vertical=True, stagger=False), # H ) document( GRID_ALIGNED_PATTERN, """A pattern of two-qubit gates that is easy to simulate. This pattern of gates was used in the paper
control_values=control_values, control_qid_shape=control_qid_shape, ) CCZ = CCZPowGate() document( CCZ, """The Controlled-Controlled-Z gate. The `exponent=1` instance of `cirq.CCZPowGate`. Matrix: ``` [[1 . . . . . . .], [. 1 . . . . . .], [. . 1 . . . . .], [. . . 1 . . . .], [. . . . 1 . . .], [. . . . . 1 . .], [. . . . . . 1 .], [. . . . . . . -1]] ``` """, ) CCNotPowGate = CCXPowGate CCX = TOFFOLI = CCNOT = CCXPowGate() document( CCX, """The TOFFOLI gate, also known as the Controlled-Controlled-X gate.
class Job: """A job created on the IonQ API. Note that this is mutable, when calls to get status or results are made the job updates itself to the results returned from the API. If a job is canceled or deleted, only the job id and the status remain valid. """ TERMINAL_STATES = ('completed', 'canceled', 'failed', 'deleted') document( TERMINAL_STATES, 'States of the IonQ API job from which the job cannot transition. ' 'Note that deleted can only exist in a return call from a delete ' '(subsequent calls will return not found).', ) NON_TERMINAL_STATES = ('ready', 'submitted', 'running') document( NON_TERMINAL_STATES, 'States of the IonQ API job which can transition to other states.') ALL_STATES = TERMINAL_STATES + NON_TERMINAL_STATES document(ALL_STATES, 'All states that an IonQ API job can exist in.') UNSUCCESSFUL_STATES = ('canceled', 'failed', 'deleted') document( UNSUCCESSFUL_STATES, 'States of the IonQ API job when it was not successful and so does not have any ' 'data associated with it beyond an id and a status.', ) def __init__(self, client: 'cirq_ionq.ionq_client._IonQClient', job_dict: dict): """Construct an IonQJob. Users should not call this themselves. If you only know the `job_id`, use `get_job` on `cirq_ionq.Service`. Args: client: The client used for calling the API. job: A dict representing the response from a call to get_job on the client. """ self._client = client self._job = job_dict def _refresh_job(self): """If the last fetched job is not terminal, gets the job from the API.""" if self._job['status'] not in self.TERMINAL_STATES: self._job = self._client.get_job(self.job_id()) def _check_if_unsuccessful(self): if self.status() in self.UNSUCCESSFUL_STATES: raise ionq_exceptions.IonQUnsuccessfulJobException( self.job_id(), self.status()) def job_id(self) -> str: """Returns the job id (UID) for the job. This is the id used for identifying the job by the API. """ return self._job['id'] def status(self) -> str: """Gets the current status of the job. This will get a new job if the status of the job previously was determined to not be in a terminal state. A full list of states is given in `cirq_ionq.IonQJob.ALL_STATES`. Raises: IonQException: If the API is not able to get the status of the job. Returns: The job status. """ self._refresh_job() return self._job['status'] def target(self) -> str: """Returns the target where the job is to be run, or was run. Returns: 'qpu' or 'simulator' depending on where the job was run or is running. Raises: IonQUnsuccessfulJob: If the job has failed, been canceled, or deleted. IonQException: If unable to get the status of the job from the API. """ self._check_if_unsuccessful() return self._job['target'] def name(self) -> str: """Returns the name of the job which was supplied during job creation. This is different than the `job_id`. Raises: IonQUnsuccessfulJob: If the job has failed, been canceled, or deleted. IonQException: If unable to get the status of the job from the API. """ self._check_if_unsuccessful() return self._job['name'] def num_qubits(self) -> int: """Returns the number of qubits for the job. Raises: IonQUnsuccessfulJob: If the job has failed, been canceled, or deleted. IonQException: If unable to get the status of the job from the API. """ self._check_if_unsuccessful() return int(self._job['qubits']) def repetitions(self) -> int: """Returns the number of repetitions for the job. Raises: IonQUnsuccessfulJob: If the job has failed, been canceled, or deleted. IonQException: If unable to get the status of the job from the API. """ self._check_if_unsuccessful() return int(self._job['metadata']['shots']) def measurement_dict(self) -> Dict[str, Sequence[int]]: """Returns a dictionary of measurement keys to target qubit index.""" measurement_dict: Dict[str, Sequence[int]] = {} if 'metadata' in self._job: full_str = ''.join(value for key, value in self._job['metadata'].items() if key.startswith('measurement')) if full_str == '': return measurement_dict for key_value in full_str.split(chr(30)): key, value = key_value.split(chr(31)) measurement_dict[key] = [int(t) for t in value.split(',')] return measurement_dict def results( self, timeout_seconds: int = 7200, polling_seconds: int = 1 ) -> Union[results.QPUResult, results.SimulatorResult]: """Polls the IonQ api for results. Args: timeout_seconds: The total number of seconds to poll for. polling_seconds: The interval with which to poll. Returns: Either a `cirq_ionq.QPUResults` or `cirq_ionq.SimulatorResults` depending on whether the job was running on an actual quantum processor or a simulator. Raises: IonQUnsuccessfulJob: If the job has failed, been canceled, or deleted. IonQException: If unable to get the results from the API. """ time_waited_seconds = 0 while time_waited_seconds < timeout_seconds: # Status does a refresh. if self.status() in self.TERMINAL_STATES: break time.sleep(polling_seconds) time_waited_seconds += polling_seconds if self.status() != 'completed': if 'failure' in self._job and 'error' in self._job['failure']: error = self._job['failure']['error'] raise RuntimeError(f'Job failed. Error message: {error}') raise RuntimeError( f'Job was not completed successful. Instead had status: {self.status()}' ) # IonQ returns results in little endian, Cirq prefers to use big endian, so we convert. if self.target() == 'qpu': repetitions = self.repetitions() counts = { _little_endian_to_big(int(k), self.num_qubits()): int(repetitions * float(v)) for k, v in self._job['data']['histogram'].items() } return results.QPUResult( counts=counts, num_qubits=self.num_qubits(), measurement_dict=self.measurement_dict(), ) else: probabilities = { _little_endian_to_big(int(k), self.num_qubits()): float(v) for k, v in self._job['data']['histogram'].items() } return results.SimulatorResult( probabilities=probabilities, num_qubits=self.num_qubits(), measurement_dict=self.measurement_dict(), repetitions=self.repetitions(), ) def cancel(self): """Cancel the given job. This mutates the job to only have a job id and status `canceled`. """ self._job = self._client.cancel_job(job_id=self.job_id()) def delete(self): """Delete the given job. This mutates the job to only have a job id and status `deleted`. Subsequence attempts to get the job with this job id will return not found. """ self._job = self._client.delete_job(job_id=self.job_id()) def __str__(self) -> str: return f'cirq_ionq.Job(job_id={self.job_id()})'
serializers=[ SYC_SERIALIZER, *SINGLE_QUBIT_SERIALIZERS, *SINGLE_QUBIT_HALF_PI_SERIALIZERS, MEASUREMENT_SERIALIZER, WAIT_GATE_SERIALIZER, ], deserializers=[ SYC_DESERIALIZER, *SINGLE_QUBIT_DESERIALIZERS, *SINGLE_QUBIT_HALF_PI_DESERIALIZERS, MEASUREMENT_DESERIALIZER, WAIT_GATE_DESERIALIZER, ], ) document(SYC_GATESET, """Gate set with fsim(pi/2, pi/6) as the core 2 qubit interaction.""") SQRT_ISWAP_GATESET = serializable_gate_set.SerializableGateSet( gate_set_name='sqrt_iswap', serializers=[ *SQRT_ISWAP_SERIALIZERS, *SINGLE_QUBIT_SERIALIZERS, MEASUREMENT_SERIALIZER, WAIT_GATE_SERIALIZER, ], deserializers=[ *SQRT_ISWAP_DESERIALIZERS, *SINGLE_QUBIT_DESERIALIZERS, MEASUREMENT_DESERIALIZER, WAIT_GATE_DESERIALIZER, ])
if TYPE_CHECKING: import cirq # A value that can be unambiguously converted into a `cirq.PauliString`. PAULI_STRING_LIKE = Union[ complex, 'cirq.OP_TREE', Mapping['cirq.Qid', 'cirq.PAULI_GATE_LIKE'], Iterable, # of PAULI_STRING_LIKE, but mypy doesn't do recursive types yet. ] document( PAULI_STRING_LIKE, # type: ignore """A `cirq.PauliString` or a value that can easily be converted into one. Complex numbers turn into the coefficient of an empty Pauli string. Dictionaries from qubit to Pauli operation are wrapped into a Pauli string. Each Pauli operation can be specified as a cirq object (e.g. `cirq.X`) or as a string (e.g. `"X"`) or as an integer where 0=I, 1=X, 2=Y, 3=Z. Collections of Pauli operations are recrusively multiplied into a single Pauli string. """) PAULI_GATE_LIKE = Union['cirq.Pauli', 'cirq.IdentityGate', str, int, ] document( PAULI_GATE_LIKE, # type: ignore """An object that can be interpreted as a Pauli gate. Allowed values are: 1. Cirq gates: `cirq.I`, `cirq.X`, `cirq.Y`, `cirq.Z`.
from typing import cast, Any import numpy as np from cirq._doc import document RANDOM_STATE_LIKE = Any document( RANDOM_STATE_LIKE, """A pseudorandom number generator or object that can be converted to one. If None, turns into the module `np.random`. If an integer, turns into a `np.random.RandomState` seeded with that integer. If none of the above, it is used unmodified. In this case, it is assumed that the object implements whatever methods are required for the use case at hand. For example, it might be an existing instance of `np.random.RandomState` or a custom pseudorandom number generator implementation. """) def parse_random_state(random_state: RANDOM_STATE_LIKE ) -> np.random.RandomState: """Interpret an object as a pseudorandom number generator. If `random_state` is None, returns the module `np.random`. If `random_state` is an integer, returns
return 'ZZ**{}'.format(self._exponent) def __repr__(self) -> str: if self._global_shift == 0: if self._exponent == 1: return 'cirq.ZZ' return '(cirq.ZZ**{})'.format(proper_repr(self._exponent)) return ('cirq.ZZPowGate(exponent={}, ' 'global_shift={!r})').format(proper_repr(self._exponent), self._global_shift) XX = XXPowGate() document( XX, """The tensor product of two X gates. The `exponent=1` instance of `cirq.XXPowGate`. """) YY = YYPowGate() document( YY, """The tensor product of two Y gates. The `exponent=1` instance of `cirq.YYPowGate`. """) ZZ = ZZPowGate() document( ZZ, """The tensor product of two Z gates. The `exponent=1` instance of `cirq.ZZPowGate`. """)