Skip to content

Cube embedding#280

Open
mahdiehmalekian wants to merge 1 commit into
dwavesystems:mainfrom
mahdiehmalekian:cube_embedding
Open

Cube embedding#280
mahdiehmalekian wants to merge 1 commit into
dwavesystems:mainfrom
mahdiehmalekian:cube_embedding

Conversation

@mahdiehmalekian

Copy link
Copy Markdown

This PR contains the cube embedder together with the needed tools.

cube_embedding contains perfect_cube_embedding.py which has the cube embedder function for graphs with Zephyr topology.
The rest of cube_embedding folder contains the necessary tools for performing the algorithm.

_lattice_utils contains some tools that can be used for finding the embedding of a variety of lattices (2d or 3d) on Zephyr. These tools are also used in cube_embedding.

@SebastianGitt SebastianGitt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, just did a first pass highlighting mostly minor issues before I take a deeper look. I did find what may be a couple of small bugs.

_fields = ("u", "w", "k", "j")

def to_tuple(self) -> tuple[int]:
"""Rerurns the tuple corresponding to the coordinate."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Rerurns the tuple corresponding to the coordinate."""
"""Returns the tuple corresponding to the coordinate."""

_fields = ("u", "w", "j")

def to_tuple(self) -> tuple[int]:
"""Rerurns the tuple corresponding to the coordinate."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Rerurns the tuple corresponding to the coordinate."""
"""Returns the tuple corresponding to the coordinate."""


Provides convenient representations and helpers for embedding-related algorithms.
Example:
>>> from burnaby.lattice_embedding.auxiliary_coordinates import UWKJ

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>>> from burnaby.lattice_embedding.auxiliary_coordinates import UWKJ
>>> from minorminer._lattice_utils.auxiliary_coordinates import UWKJ

It captures the full coordinate of a Zephyr node.

Example:
>>> from burnaby.lattice_embedding.auxiliary_coordinates import UWKJZ

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>>> from burnaby.lattice_embedding.auxiliary_coordinates import UWKJZ
>>> from minorminer._lattice_utils.auxiliary_coordinates import UWKJZ


# To make the node label consistent with ``G``'s
# (i.e. "int" or "coordinates")
if label == "coordinates":

@SebastianGitt SebastianGitt Jul 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be "coordinate" instead of "coordinates"? If so, should add a test using this branch since it wasn't caught, and update references to this in the comments here and elsewhere

if isinstance(val, int):
copied_dict[var] = val
elif isinstance(val, list):
copied_dict[var] = [k for k in val]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a shallow copy but the docstring says it returns a deep copy

Returns:
dict[Edge, int]: The dictionary after removing all items with value zero.
"""
return {chain: chain_freq for chain, chain_freq in chain_freq.items() if chain_freq != 0}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chain_freq is used for both the dictionary and the dictionary values, consider renaming one of them to make it more clear

from typing import Generator, NamedTuple

from minorminer.utils.zephyr.node_edge import Edge, NodeKind

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inconsistent spacing here and elsewhere, I recommend running a code formatter like Black if you haven't already

"""
A helper to represent some information of a path of chains of node indices (within a :class:`QuoTile`).
edge (Edge): Edge of node indices represnting the index-chain
pos (tuple[int, int]): pair of positions, the i-th element representing the number of occurence of i-th element of the index-chain when visiting the index-chain

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should break this up over two lines so it doesn't exceed 100 characters (here and elsewhere)

connectivity checks based on z-coupling.
4. A lattice survey module that provides utilities for embedding lattices
on partially-yielded Zephyr graphs.
5. A qoutient tile object to facilitate embedding lattice-type graphs on Zephyr.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
5. A qoutient tile object to facilitate embedding lattice-type graphs on Zephyr.
5. A quotient tile object to facilitate embedding lattice-type graphs on Zephyr.

@SebastianGitt SebastianGitt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did a more in-depth review and it's looking really good overall. I do think this PR would greatly benefit from having some more comprehensive docstrings. I also think there are some opportunities to use more clear/descriptive variable names. Also, make sure to include a release note.


Args:
tile_kind (TileKind): The kind of tile forming the floor.
sub_kind (Literal["main", "anti"]): The sub-kind of tile forming the floor.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the quotes here need to be fixed (and other occurrences of sub_kind)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, instead of fixing the types in docstrings, please remove them completely (here and elsewhere), since they're not needed when arguments are type-hinted. See the Documentation section in Ocean contributing guide (we follow Google Python Style for docstrings).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Radomir, I did mention that elsewhere but I missed that these ones should just be removed instead of fixed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I saw your comment later below, but only after I posted this comment 🙂


if z_coupling is ZCoupling.EITHER:
alt_edge_pos: dict[EdgePos, EdgePos] = {}
for i, ep_01 in enumerate(con_01):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using clearer variable names like edge_position instead of ep

Edge(5, 7),
Edge(0, 1),
Edge(1, 3),
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason "anti" is a set and "main" is a list?

Edge(4, 5),
Edge(0, 2),
Edge(6, 7),
Edge(2, 3),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a meaningful order to these edges?

},
}
"""A dictionary whose keys are the two subkinds of ``TileKind.LADDER``--"main", "anti".
The value is a dictionary whose

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this description should be updated since the values are not dictionaries

Returns:
int: The maximum number of times ``chain`` can be constructed given the current supply constraints.
"""
used_supply = used_supply or {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor, but I would go with
'if used_supply is None:
used_supply = {}'

list[ZEdge]: List of edges of the graph induced on the tile, when restricted by ``nbr_kind`` and ``where``.
"""
zns = self._zns
tile_coords = [zn.zcoord for zn in zns] if self.convert_to_z else [zn.ccoord for zn in zns]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convert_to_z should be defined as an attribute of QuoTile, this could raise an AttributeError

>>> print(len(emb))
576
"""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be worth adding some input validation here such as making sure z_periodic is a boolean, etc.

- Defaults to None.
- Note: Passing it saves computation time.

**kwargs: Optional arguments to specify the type of tiles or paths inside the tiles used for finding embedding.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My recommendation would be to make these explicit keyword arguments instead


def find_cube_embedding(
G: nx.Graph | DWaveSampler,
dim: tuple[int, int, int] | None=None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dim: tuple[int, int, int] | None=None,
dim: tuple[int, int, int] | None = None,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants