qoolqit.register
register
Section titled “
register
”Classes:
-
Register–A QoolQit register mapping qubit IDs to 2D coordinates.
Register
Section titled “
Register
”Register( qubits: Mapping[ str, Sequence[float] | NDArray[float64] | Tensor ] | Mapping[ int, Sequence[float] | NDArray[float64] | Tensor ],)A QoolQit register mapping qubit IDs to 2D coordinates.
Examples:
From a dictionary of qubit IDs and coordinates:
>>> reg = Register({"a": (0.0, 0.0), "b": (1.0, 0.0), "c": (0.0, 1.0)})>>> reg = Register({0: (0.0, 0.0), 1: (1.0, 0.0), 2: (0.0, 1.0)})From a list of coordinates (qubit IDs are assigned automatically as strings "0", "1", ...):
>>> reg = Register.from_coordinates([(0.0, 0.0), (1.0, 0.0), (0.0, 1.0)])Using numpy arrays as coordinates:
>>> import numpy as np>>> reg = Register({"a": np.array([0.0, 0.0]), "b": np.array([1.0, 0.0])})Using torch tensors as coordinates:
>>> import torch>>> reg = Register({"a": torch.tensor([0.0, 0.0]), "b": torch.tensor([1.0, 0.0])})Parameters:
-
qubits(Mapping[str, Sequence[float] | NDArray[float64] | Tensor] | Mapping[int, Sequence[float] | NDArray[float64] | Tensor]) –a dictionary of qubits and respective 2D coordinates {q: (x, y), ...}. Each coordinate must be castable to a numpy or torch array of shape (2,).
Raises:
-
TypeError–If
qubitsis not a Mapping. -
ValueError–If
qubitsdictionary is empty. -
ValueError–If a qubit coordinate cannot be converted to an array of floats, or if the converted coordinate is not a point in 2D.
- API reference
- API reference
Methods:
-
circle–Initializes a Register with qubits arranged in a circle.
-
distances–Distance between each qubit pair.
-
draw–Draw the register.
-
from_coordinates–Initializes a Register from a sequence or array of coordinates.
-
from_graph–Initializes a Register from a graph that has coordinates.
-
interaction_matrix–Interaction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).
-
interactions–Interaction 1/r^6 between each qubit pair.
-
line–Initializes a Register with qubits arranged in a line.
-
max_radial_distance–Maximum radial distance between all qubits.
-
min_distance–Minimum distance between all qubit pairs.
-
radial_distances–Radial distance of each qubit from the origin.
-
rectangular–Initializes a rectangular Register of qubits.
-
square–Initializes a square Register of qubits.
-
triangular–Initializes a triangular lattice Register of qubits.
Attributes:
-
n_qubits(int) –Number of qubits in the Register.
-
qubits(dict) –Returns a dictionary of qubits and respective coordinates.
-
qubits_ids(tuple[str | int, ...]) –Returns the qubit IDs.
Source code in qoolqit/register.py
def __init__( self, qubits: ( Mapping[str, Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] | Mapping[int, Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] ),) -> None: """Default constructor for the Register.
Args: qubits: a dictionary of qubits and respective 2D coordinates {q: (x, y), ...}. Each coordinate must be castable to a numpy or torch array of shape (2,).
Raises: TypeError: If `qubits` is not a Mapping. ValueError: If `qubits` dictionary is empty. ValueError: If a qubit coordinate cannot be converted to an array of floats, or if the converted coordinate is not a point in 2D. """ if not isinstance(qubits, Mapping): raise TypeError("`qubits` must be a Mapping of qubit ids to coordinates.") if not qubits: raise ValueError("Register cannot be empty.")
self._qubits_ids: tuple[str | int, ...] = tuple(qubits.keys()) validated_coords = [self._validate_coord(k, c) for k, c in qubits.items()] self._coords = self._stack_coords(validated_coords)
n_qubits
property
Section titled “
n_qubits
property
”n_qubits: intNumber of qubits in the Register.
qubits
property
Section titled “
qubits
property
”qubits: dictReturns a dictionary of qubits and respective coordinates.
qubits_ids
property
Section titled “
qubits_ids
property
”qubits_ids: tuple[str | int, ...]Returns the qubit IDs.
circle
classmethod
Section titled “
circle
classmethod
”circle(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a Register with qubits arranged in a circle.
Parameters:
-
n(int) –number of qubits to place in the circle.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef circle(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a Register with qubits arranged in a circle.
Args: n: number of qubits to place in the circle. spacing: distance between adjacent qubits. Defaults to 1.0. """ if n < 1: raise ValueError("Number of qubits must be at least 1.") if spacing <= 0: raise ValueError("Spacing must be positive.") if n == 1: return cls.from_coordinates([(0.0, 0.0)])
step = 2.0 * math.pi / n r = spacing / (2.0 * math.sin(math.pi / n)) coords = [(math.cos(step * i) * r, math.sin(step * i) * r) for i in range(n)]
return cls.from_coordinates(coords)
distances
Section titled “
distances
”distances() -> dictDistance between each qubit pair.
Source code in qoolqit/register.py
def distances(self) -> dict: """Distance between each qubit pair.""" pairs = all_node_pairs(self.qubits_ids) return distances(self.qubits, pairs)draw( ax: Axes | None = None, marker_size: int = 100, node_color: str = "tab:green",) -> NoneDraw the register.
Parameters:
-
ax(Axes | None, default:None) –an optional matplotlib Axes instance to draw on. If None, a new Axes will be created.
-
marker_size(int, default:100) –size of the qubit markers in points squared. Defaults to 100.
-
node_color(str, default:'tab:green') –color of the qubit markers. Defaults to "tab:green".
Source code in qoolqit/register.py
def draw( self, ax: Axes | None = None, marker_size: int = 100, node_color: str = "tab:green") -> None: """Draw the register.
Args: ax: an optional matplotlib Axes instance to draw on. If None, a new Axes will be created. marker_size: size of the qubit markers in points squared. Defaults to 100. node_color: color of the qubit markers. Defaults to "tab:green". """ if ax is None: _, ax = plt.subplots()
marker_radius = marker_size**0.5 / 2 # in points annotation_offset = 1.5 * marker_radius # place label just outside the marker
coords = self._coords.detach().cpu().numpy() if _is_torch(self._coords) else self._coords for xi, yi, qid in zip(coords[:, 0], coords[:, 1], self.qubits_ids): ax.scatter(xi, yi, s=marker_size, color=node_color) ax.annotate( str(qid), xy=(xi, yi), xytext=(annotation_offset, annotation_offset), textcoords="offset points", ha="center", va="center", )
ax.grid(True, color="lightgray", linestyle="--", linewidth=0.7) ax.set_axisbelow(True) ax.set_xlabel("x") ax.set_ylabel("y") ax.margins(0.1)
from_coordinates
classmethod
Section titled “
from_coordinates
classmethod
”from_coordinates( coords: Sequence[ Sequence[float] | NDArray[float64] | Tensor ] | NDArray[float64] | Tensor,) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a Register from a sequence or array of coordinates.
Qubit IDs are assigned as integers 0,1,...,N-1, where N is the number of coordinates.
Parameters:
-
coords(Sequence[Sequence[float] | NDArray[float64] | Tensor] | NDArray[float64] | Tensor) –a sequence of 2D coordinates, i.e. [(x, y), ...]. Each coordinate must be castable to a numpy or torch array of shape (2,). If
coordsis a numpy array or a torch tensor, it must be 2D and of shape (N, 2).
Raises:
-
TypeError–If
coordsis a Mapping.
Source code in qoolqit/register.py
@classmethoddef from_coordinates( cls, coords: ( Sequence[Sequence[float] | npt.NDArray[np.float64] | torch.Tensor] | npt.NDArray[np.float64] | torch.Tensor ),) -> Register: """Initializes a Register from a sequence or array of coordinates.
Qubit IDs are assigned as integers 0,1,...,N-1, where N is the number of coordinates.
Args: coords: a sequence of 2D coordinates, i.e. [(x, y), ...]. Each coordinate must be castable to a numpy or torch array of shape (2,). If `coords` is a numpy array or a torch tensor, it must be 2D and of shape (N, 2).
Raises: TypeError: If `coords` is a Mapping. """ if isinstance(coords, Mapping): raise TypeError( "Register.from_coordinates expects a sequence of coordinates [(x, y), ...]; " "pass an id-to-coordinate mapping to Register(...) directly." ) coords_dict = {i: pos for i, pos in enumerate(coords)} return cls(coords_dict)
from_graph
classmethod
Section titled “
from_graph
classmethod
”from_graph(graph: DataGraph (qoolqit.graphs.DataGraph)" href="../graphs/#qoolqit.graphs.DataGraph">DataGraph) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a Register from a graph that has coordinates.
Parameters:
-
graph(DataGraph) –a DataGraph instance.
Source code in qoolqit/register.py
@classmethoddef from_graph(cls, graph: DataGraph) -> Register: """Initializes a Register from a graph that has coordinates.
Args: graph: a DataGraph instance. """
if not graph.has_coords: raise ValueError("Initializing a register from a graph requires node coordinates.")
if len(graph.nodes) == 0: raise ValueError("Trying to initialize a register from an empty graph.")
return cls(graph.coords)
interaction_matrix
Section titled “
interaction_matrix
”interaction_matrix() -> NDArray[float64] | TensorInteraction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).
Source code in qoolqit/register.py
def interaction_matrix(self) -> npt.NDArray[np.float64] | torch.Tensor: """Interaction 1/r^6 between each qubit pair, as a matrix (0 on the diagonal).""" dist_matrix = _pdist(self._coords) interactions = _fill_diagonal(dist_matrix, 1.0) interactions **= -6 return _fill_diagonal(interactions, 0.0)
interactions
Section titled “
interactions
”interactions() -> dictInteraction 1/r^6 between each qubit pair.
Source code in qoolqit/register.py
def interactions(self) -> dict: """Interaction 1/r^6 between each qubit pair.""" return {p: 1.0 / (r**6) for p, r in self.distances().items()}
line
classmethod
Section titled “
line
classmethod
”line(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a Register with qubits arranged in a line.
Parameters:
-
n(int) –number of qubits to place in the line.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef line(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a Register with qubits arranged in a line.
Args: n: number of qubits to place in the line. spacing: distance between adjacent qubits. Defaults to 1.0. """ return cls.rectangular(n, 1, row_spacing=spacing)
max_radial_distance
Section titled “
max_radial_distance
”max_radial_distance() -> floatMaximum radial distance between all qubits.
Source code in qoolqit/register.py
def max_radial_distance(self) -> float: """Maximum radial distance between all qubits.""" max_radial_distance: float = max(self.radial_distances().values()) return max_radial_distance
min_distance
Section titled “
min_distance
”min_distance() -> floatMinimum distance between all qubit pairs.
Source code in qoolqit/register.py
def min_distance(self) -> float: """Minimum distance between all qubit pairs.""" distance: float = min(self.distances().values()) return distance
radial_distances
Section titled “
radial_distances
”radial_distances() -> dictRadial distance of each qubit from the origin.
Source code in qoolqit/register.py
def radial_distances(self) -> dict: """Radial distance of each qubit from the origin.""" return {qid: _norm(coord) for qid, coord in zip(self.qubits_ids, self._coords)}
rectangular
classmethod
Section titled “
rectangular
classmethod
”rectangular( rows: int, cols: int, row_spacing: float = 1.0, col_spacing: float = 1.0,) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a rectangular Register of qubits.
Parameters:
-
rows(int) –number of rows in the rectangle.
-
cols(int) –number of columns in the rectangle.
-
row_spacing(float, default:1.0) –distance between adjacent qubits in the row direction. Defaults to 1.0.
-
col_spacing(float, default:1.0) –distance between adjacent qubits in the column direction. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef rectangular( cls, rows: int, cols: int, row_spacing: float = 1.0, col_spacing: float = 1.0) -> Register: """Initializes a rectangular Register of qubits.
Args: rows: number of rows in the rectangle. cols: number of columns in the rectangle. row_spacing: distance between adjacent qubits in the row direction. Defaults to 1.0. col_spacing: distance between adjacent qubits in the column direction. Defaults to 1.0. """ if rows < 1 or cols < 1: raise ValueError("Number of rows and columns must be at least 1.") if row_spacing <= 0 or col_spacing <= 0: raise ValueError("Spacing must be positive.")
x_offset = (rows - 1) * row_spacing / 2.0 y_offset = (cols - 1) * col_spacing / 2.0 coords = [ (i * row_spacing - x_offset, j * col_spacing - y_offset) for i in range(rows) for j in range(cols) ]
return cls.from_coordinates(coords)
square
classmethod
Section titled “
square
classmethod
”square(n: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a square Register of qubits.
Parameters:
-
n(int) –number of qubits along each side of the square.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef square(cls, n: int, spacing: float = 1.0) -> Register: """Initializes a square Register of qubits.
Args: n: number of qubits along each side of the square. spacing: distance between adjacent qubits. Defaults to 1.0. """ return cls.rectangular(n, n, row_spacing=spacing, col_spacing=spacing)
triangular
classmethod
Section titled “
triangular
classmethod
”triangular( rows: int, atoms_per_row: int, spacing: float = 1.0) -> Register (qoolqit.register.Register)" href="#qoolqit.register.Register">RegisterInitializes a triangular lattice Register of qubits.
Parameters:
-
rows(int) –number of rows in the lattice.
-
atoms_per_row(int) –number of qubits per row.
-
spacing(float, default:1.0) –distance between adjacent qubits. Defaults to 1.0.
Source code in qoolqit/register.py
@classmethoddef triangular(cls, rows: int, atoms_per_row: int, spacing: float = 1.0) -> Register: """Initializes a triangular lattice Register of qubits.
Args: rows: number of rows in the lattice. atoms_per_row: number of qubits per row. spacing: distance between adjacent qubits. Defaults to 1.0. """ if rows < 1 or atoms_per_row < 1: raise ValueError("Number of rows and atoms per row must be at least 1.") if spacing <= 0: raise ValueError("Spacing must be positive.")
height = math.sqrt(3.0) / 2.0 x_offset = ((atoms_per_row - 1) / 2.0 + 0.5 * (rows // 2) / rows) * spacing y_offset = (rows - 1) * height * spacing / 2.0 coords = [ ((i + 0.5 * (j % 2)) * spacing - x_offset, j * height * spacing - y_offset) for j in range(rows) for i in range(atoms_per_row) ] return cls.from_coordinates(coords)