View on QuantumAI | Run in Google Colab | View source on GitHub | Download notebook |

The `IonDevice`

represents a trapped ion quantum computer with all-to-all qubit connectivity. The number of qubits as well as the duration of gates and measurements are specified by the user when creating an ion device.

Two-qubit gates are implemented by an Ising-type coupling known as the *Mølmer–Sørensen* gate. The Mølmer–Sørensen gate couples ions through the shared motional modes of the ion chain. The ion motion and internal state decouples at the end of each gate. The `IonDevice`

class assumes this decoupling is perfect and does not explicitly model the ion motion.

```
try:
import cirq
except ImportError:
print("installing cirq...")
!pip install cirq --quiet
print("installed cirq.")
import cirq
import numpy as np
```

## Defining an `IonDevice`

To define an `IonDevice`

, we specify

- The set of qubits in the device,
- The duration of single-qubit gates,
- The duration of two-qubit gates, and
- The duration of measurement gates.

The code below creates an `IonDevice`

with four qubits in a linear array. The durations we use for each type of gate are reasonable order-of-magnitude estimates, though they will differ for different trapped ion computers.

```
"""Create an IonDevice."""
ion_device = cirq.IonDevice(
qubits=cirq.LineQubit.range(4),
oneq_gates_duration=cirq.Duration(micros=10),
twoq_gates_duration=cirq.Duration(micros=200),
measurement_duration=cirq.Duration(micros=100)
)
```

We can view some properties of the `ion_device`

as shown below.

```
"""View some properties of the device."""
# Display the ion device.
print("Ion Device:\n", ion_device)
# Get all qubits in the device.
print("\nQubits in the IonDevice:\n", sorted(ion_device.qubits))
# Get a qubit at a certain position (if present).
pos = 2
print(f"\nQubit at position {pos}:\n", ion_device.at(pos))
```

Ion Device: 0───1───2───3 Qubits in the IonDevice: [cirq.LineQubit(0), cirq.LineQubit(1), cirq.LineQubit(2), cirq.LineQubit(3)] Qubit at position 2: 2

## Native Gate Set

An `IonDevice`

can implement single-qubit rotations about the \(X\), \(Y\), and \(Z\) axes of the Bloch sphere: namely, `cirq.rx`

, `cirq.ry`

, and `cirq.rz`

.

An `IonDevice`

can implement the two-qubit Mølmer–Sørensen gate, a rotation about the \(XX\) axis in the two-qubit Bloch sphere defined as

\begin{equation} \exp(-i t XX) = \left[ \begin{matrix} \cos t & 0 & 0 & -i \sin t \ 0 & \cos t & -i \sin t & 0 \ 0 & -i \sin t & \cos t & 0 \ -i \sin t & 0 & 0 & \cos t \end{matrix} \right] . \end{equation}

The Mølmer–Sørensen gate is defined in Cirq as `cirq.ms`

.

One can check if a given gate is valid with `IonDevice.validate_gate`

. This method raises an error if the gate is invalid (not supported by the device) and does nothing if the gate is valid (supported by the device).

```
"""Check if gates are valid. Invalid gates raise a ValueError."""
# Single-qubit X rotation of any angle is supported.
ion_device.validate_gate(cirq.rx(np.pi / 7))
# Single-qubit Z rotation of any angle is supported.
ion_device.validate_gate(cirq.rz(np.pi / 5))
# Mølmer–Sørensen gate of any angle is supported.
ion_device.validate_gate(cirq.ms(np.pi / 4))
```

One can also validate operations and circuits with `IonDevice.validate_operation`

and `IonDevice.validate_circuit`

, respectively.

We can get the duration of valid operations as follows.

```
"""Get the duration of valid operations."""
# Duration of a single-qubit operation.
ion_device.duration_of(cirq.ry(np.pi / 2).on(ion_device.at(0)))
```

cirq.Duration(micros=10)

## Decomposing Operations and Circuits

Operations which are not valid on the device can be decomposed into a set of valid operations. For example, a CNOT gate is not supported but can be implemented with the following decomposition.

```
"""Decompose a CNOT operation into valid IonDevice operations."""
# Get a CNOT operation.
op = cirq.CNOT(ion_device.at(0), ion_device.at(1))
# Decompose it for the IonDevice.
ion_device_ops = cirq.ConvertToIonGates().convert_one(op)
# Print the sequence of operations to implement a CNOT.
print("Sequence of IonDevice operations for a CNOT:\n")
print(cirq.Circuit(ion_device_ops))
```

Sequence of IonDevice operations for a CNOT: 0: ───Ry(0.5π)───MS(0.25π)───Rx(-0.5π)───Ry(-0.5π)─── │ 1: ──────────────MS(0.25π)───Rx(-0.5π)───────────────

Circuits can also be decomposed in a similar manner using `IonDevice.decompose_circuit`

.

```
"""Decompose a circuit into IonDevice operations."""
# Example circuit to decompose.
circuit = cirq.Circuit(
cirq.H(cirq.LineQubit(0)),
cirq.CNOT(cirq.LineQubit(0), cirq.LineQubit(1)),
cirq.CNOT(cirq.LineQubit(0), cirq.LineQubit(2))
)
# Display it.
print("Circuit to decompose:\n")
print(circuit)
# Decompose the circuit.
ion_device_circuit = ion_device.decompose_circuit(circuit)
# Display the decomposed circuit.
print("\nIonDevice circuit:\n")
print(ion_device_circuit)
```

Circuit to decompose: 0: ───H───@───@─── │ │ 1: ───────X───┼─── │ 2: ───────────X─── IonDevice circuit: 0: ───PhX(1)───────────MS(0.25π)───PhX(1)^0.5───────────MS(0.25π)───PhX(-0.5)^0.5───S^-1─── │ │ 1: ────────────────────MS(0.25π)───PhX(1)^0.5───────────┼────────────────────────────────── │ 2: ─────────────────────────────────────────────────────MS(0.25π)───PhX(1)^0.5─────────────