Skip to content

Register

Quantum Registers

Register(support, spacing=1.0, device_specs=DEFAULT_DEVICE)

A register of qubits including 2D coordinates.

Instantiating the Register class directly is only recommended for building custom registers. For most uses where a predefined lattice is desired it is recommended to use the various class methods available, e.g. Register.triangular_lattice.

PARAMETER DESCRIPTION
support

A NetworkX graph or number of qubits. Nodes can include a "pos" attribute such that e.g.: graph.nodes = {0: {"pos": (2,3)}, 1: {"pos": (0,0)}, ...} which will be used in backends that need qubit coordinates. Passing a number of qubits calls Register.all_to_all(n_qubits).

TYPE: Graph | int

spacing

Value set as the distance between the two closest qubits. The spacing argument is also available for all the class method constructors.

TYPE: float | None DEFAULT: 1.0

Examples:

from qadence import Register

reg_all = Register.all_to_all(n_qubits = 4)
reg_line = Register.line(n_qubits = 4)
reg_circle = Register.circle(n_qubits = 4)
reg_squre = Register.square(qubits_side = 2)
reg_rect = Register.rectangular_lattice(qubits_row = 2, qubits_col = 2)
reg_triang = Register.triangular_lattice(n_cells_row = 2, n_cells_col = 2)
reg_honey = Register.honeycomb_lattice(n_cells_row = 2, n_cells_col = 2)

Source code in qadence/register.py
def __init__(
    self,
    support: nx.Graph | int,
    spacing: float | None = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
):
    """
    A register of qubits including 2D coordinates.

    Instantiating the Register class directly is only recommended for building custom registers.
    For most uses where a predefined lattice is desired it is recommended to use the various
    class methods available, e.g. `Register.triangular_lattice`.

    Arguments:
        support: A NetworkX graph or number of qubits. Nodes can include a `"pos"` attribute
            such that e.g.: `graph.nodes = {0: {"pos": (2,3)}, 1: {"pos": (0,0)}, ...}` which
            will be used in backends that need qubit coordinates. Passing a number of qubits
            calls `Register.all_to_all(n_qubits)`.
        spacing: Value set as the distance between the two closest qubits. The spacing
            argument is also available for all the class method constructors.

    Examples:
    ```python exec="on" source="material-block"
    from qadence import Register

    reg_all = Register.all_to_all(n_qubits = 4)
    reg_line = Register.line(n_qubits = 4)
    reg_circle = Register.circle(n_qubits = 4)
    reg_squre = Register.square(qubits_side = 2)
    reg_rect = Register.rectangular_lattice(qubits_row = 2, qubits_col = 2)
    reg_triang = Register.triangular_lattice(n_cells_row = 2, n_cells_col = 2)
    reg_honey = Register.honeycomb_lattice(n_cells_row = 2, n_cells_col = 2)
    ```
    """
    if device_specs is not None and not isinstance(device_specs, RydbergDevice):
        raise ValueError("Device specs are not valid. Please pass a `RydbergDevice` instance.")

    self.device_specs = device_specs

    self.graph = support if isinstance(support, nx.Graph) else alltoall_graph(support)

    if spacing is not None and self.min_distance != 0.0:
        _scale_node_positions(self.graph, self.min_distance, spacing)

all_node_pairs: EdgeView property

Return a list of all possible qubit pairs in the register.

coords: dict property

Return the dictionary of qubit coordinates.

distances: dict property

Return a dictionary of distances for all qubit pairs in the register.

edge_distances: dict property

Return a dictionary of distances for the qubit pairs that are.

connected by an edge in the underlying NetworkX graph.

edges: EdgeView property

Return the EdgeView of the underlying NetworkX graph.

min_distance: float property

Return the minimum distance between two qubts in the register.

n_qubits: int property

Total number of qubits in the register.

nodes: NodeView property

Return the NodeView of the underlying NetworkX graph.

support: set property

Return the set of qubits in the register.

all_to_all(n_qubits, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a register with an all-to-all connectivity graph.

The graph is projected onto a 2D space and the qubit coordinates are set using a spring layout algorithm.

PARAMETER DESCRIPTION
n_qubits

Total number of qubits.

TYPE: int

Source code in qadence/register.py
@classmethod
def all_to_all(
    cls,
    n_qubits: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a register with an all-to-all connectivity graph.

    The graph is projected
    onto a 2D space and the qubit coordinates are set using a spring layout algorithm.

    Arguments:
        n_qubits: Total number of qubits.
    """
    return cls(alltoall_graph(n_qubits), spacing, device_specs)

circle(n_qubits, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a circle register.

PARAMETER DESCRIPTION
n_qubits

Total number of qubits.

TYPE: int

Source code in qadence/register.py
@classmethod
def circle(
    cls,
    n_qubits: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a circle register.

    Arguments:
        n_qubits: Total number of qubits.
    """
    graph = nx.grid_2d_graph(n_qubits, 1, periodic=True)
    graph = nx.relabel_nodes(graph, {(i, 0): i for i in range(n_qubits)})
    coords = nx.circular_layout(graph)
    values = {i: {"pos": pos} for i, pos in coords.items()}
    nx.set_node_attributes(graph, values)
    return cls(graph, spacing, device_specs)

draw(show=True)

Draw the underlying NetworkX graph representing the register.

Source code in qadence/register.py
def draw(self, show: bool = True) -> None:
    """Draw the underlying NetworkX graph representing the register."""
    coords = {i: n["pos"] for i, n in self.graph.nodes.items()}
    nx.draw(self.graph, with_labels=True, pos=coords)
    if show:
        plt.gcf().show()

from_coordinates(coords, lattice=LatticeTopology.ARBITRARY, spacing=None, device_specs=DEFAULT_DEVICE) classmethod

Build a register from a list of qubit coordinates.

Each node is added to the underlying graph with the respective coordinates, but the edges are left empty.

PARAMETER DESCRIPTION
coords

List of qubit coordinate tuples.

TYPE: list[tuple]

Source code in qadence/register.py
@classmethod
def from_coordinates(
    cls,
    coords: list[tuple],
    lattice: LatticeTopology | str = LatticeTopology.ARBITRARY,
    spacing: float | None = None,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a register from a list of qubit coordinates.

    Each node is added to the underlying
    graph with the respective coordinates, but the edges are left empty.

    Arguments:
        coords: List of qubit coordinate tuples.
    """
    graph = nx.Graph()
    for i, pos in enumerate(coords):
        graph.add_node(i, pos=pos)
    return cls(graph, spacing, device_specs)

honeycomb_lattice(n_cells_row, n_cells_col, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a honeycomb lattice register.

Each cell is an hexagon made up of six qubits.

PARAMETER DESCRIPTION
n_cells_row

Number of cells in each row.

TYPE: int

n_cells_col

Number of cells in each column.

TYPE: int

Source code in qadence/register.py
@classmethod
def honeycomb_lattice(
    cls,
    n_cells_row: int,
    n_cells_col: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a honeycomb lattice register.

    Each cell is an hexagon made up of six qubits.

    Arguments:
        n_cells_row: Number of cells in each row.
        n_cells_col: Number of cells in each column.
    """
    graph = nx.hexagonal_lattice_graph(n_cells_row, n_cells_col)
    graph = nx.relabel_nodes(graph, {(i, j): k for k, (i, j) in enumerate(graph.nodes)})
    return cls(graph, spacing, device_specs)

line(n_qubits, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a line register.

PARAMETER DESCRIPTION
n_qubits

Total number of qubits.

TYPE: int

Source code in qadence/register.py
@classmethod
def line(
    cls,
    n_qubits: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a line register.

    Arguments:
        n_qubits: Total number of qubits.
    """
    return cls(line_graph(n_qubits), spacing, device_specs)

rescale_coords(scaling)

Rescale the coordinates of all qubits in the register.

PARAMETER DESCRIPTION
scaling

Scaling value.

TYPE: float

Source code in qadence/register.py
def rescale_coords(self, scaling: float) -> Register:
    """
    Rescale the coordinates of all qubits in the register.

    Arguments:
        scaling: Scaling value.
    """
    g = deepcopy(self.graph)
    _scale_node_positions(g, min_distance=1.0, spacing=scaling)
    return Register(g, spacing=None, device_specs=self.device_specs)

square(qubits_side, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a square register.

PARAMETER DESCRIPTION
qubits_side

Number of qubits on one side of the square.

TYPE: int

Source code in qadence/register.py
@classmethod
def square(
    cls,
    qubits_side: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a square register.

    Arguments:
        qubits_side: Number of qubits on one side of the square.
    """
    n_points = 4 * (qubits_side - 1)

    def gen_points() -> np.ndarray:
        rotate_left = np.array([[0.0, -1.0], [1.0, 0.0]])
        increment = np.array([0.0, 1.0])

        points = [np.array([0.0, 0.0])]
        counter = 1
        while len(points) < n_points:
            points.append(points[-1] + increment)

            counter = (counter + 1) % qubits_side
            if counter == 0:
                increment = rotate_left.dot(increment)
                counter = 1
        points = np.array(points)  # type: ignore[assignment]
        points -= np.mean(points, axis=0)

        return points  # type: ignore[return-value]

    graph = nx.grid_2d_graph(n_points, 1, periodic=True)
    graph = nx.relabel_nodes(graph, {(i, 0): i for i in range(n_points)})
    values = {i: {"pos": point} for i, point in zip(graph.nodes, gen_points())}
    nx.set_node_attributes(graph, values)
    return cls(graph, spacing, device_specs)

triangular_lattice(n_cells_row, n_cells_col, spacing=1.0, device_specs=DEFAULT_DEVICE) classmethod

Build a triangular lattice register.

Each cell is a triangle made up of three qubits.

PARAMETER DESCRIPTION
n_cells_row

Number of cells in each row.

TYPE: int

n_cells_col

Number of cells in each column.

TYPE: int

Source code in qadence/register.py
@classmethod
def triangular_lattice(
    cls,
    n_cells_row: int,
    n_cells_col: int,
    spacing: float = 1.0,
    device_specs: RydbergDevice = DEFAULT_DEVICE,
) -> Register:
    """
    Build a triangular lattice register.

    Each cell is a triangle made up of three qubits.

    Arguments:
        n_cells_row: Number of cells in each row.
        n_cells_col: Number of cells in each column.
    """
    return cls(triangular_lattice_graph(n_cells_row, n_cells_col), spacing, device_specs)