Skip to content

Conversation

@mahdiehmalekian
Copy link

@mahdiehmalekian mahdiehmalekian commented Mar 13, 2025

coordinate_systems.py : Contains namedtuples for Zephyr and Cartesian coordinates and the conversion functions between the two
plane_shift.py : Contains the class for displacement of nodes in the Cartesian plane.
node_edge.py: Contains the class for edge, edge of a Zephyr graph (which checks whether the edge exists in a perfect yield Zephyr graph), and the node of a Zephyr graph
qfloor.py: Contains the class for working with a tile (subset of nodes) in quotient Zephyr. Also contains the class for putting the tiles together in a number of rows and columns
survey.py: Contains the class for taking a survey of a Zephyr graph compared to a perfect-yield Zephyr graph on the same grid and tile size
The test suite contains the tests for these modules.

@mahdiehmalekian mahdiehmalekian changed the title Initial commit Zephyr utils Mar 13, 2025
Copy link
Contributor

@thisac thisac left a comment

Choose a reason for hiding this comment

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

Thanks for the hard work @mahdiehmalekian. Had a first pass through node_edge. Will come back to it again, and the other files, in a future review soon.

Copy link
Contributor

@thisac thisac left a comment

Choose a reason for hiding this comment

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

Had another review round. Haven't checked the tests yet (will do that next).

A couple of overall comments and suggestions:

  • qfloor.py contains a couple of methods without or with incomplete docstrings.
  • Code in docstrings should have double back-ticks (``), and wherever possible, it's nice (but not mandatory) to have cross-references to classes and methods, etc. See here.
  • A couple of places I'd recommend adding a new line after returns and around for-loop-blocks, try-excepts, after raises and after returns, to make it a bit more legible.

jackraymond and others added 29 commits November 14, 2025 11:31
randomir review implementation

Co-authored-by: Radomir Stevanovic <[email protected]>
thisac review code suggestions

Co-authored-by: Theodor Isacsson <[email protected]>
…anch with testing derived from TilingComposite
Co-authored-by: Radomir Stevanovic <[email protected]>
### New Features

- Allow lattice type and lattice dimensions to be passed as options for `find_sublattice_embeddings()`. See [\dwavesystems#266](dwavesystems#266).

### Bug Fixes

- Fix `find_sublattice_embeddings()` to not produce non-disjoint embeddings when `use_tile_embedding=True` is set. See [\dwavesystems#265](dwavesystems#265).
)

* Added support for colorings in Glasgow subgraph solver
* updated Glasgow to latest version (with patches for c++17 support)
* new parameters for subgraph.find_subgraph
  * as_embedding=True will produce a dict with tuple values
  * node_labels to be respected by GSS, node labels must match
  * edge_labels as with node_labels; directed edge labels match
* removed kwargs handling in favor for explicit arguments (issue dwavesystems#255)
* added injectivity parameter to support noninjective and locally-injective homomorphisms
* fix isolated nodes issue dwavesystems#254 and add injectivity options
* support random seeds (issue dwavesystems#243)
* added ability to interrupt find_subgraph via ctrl-c
Copy link
Member

@randomir randomir left a comment

Choose a reason for hiding this comment

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

Very well written code and super useful utils! Thank you, @mahdiehmalekian!

My feedback is mostly about code/docs style (for consistency with Ocean) and coding best practices.

In terms of interface/API, I would simplify ZNode by defining neighbor generators only, also removing membership test functions.

xyks = [(0, 1), (1, 0, None), (12, -3)]
ccoords = [CartesianCoord(*xyk) for xyk in xyks]
for ccoord in ccoords:
cartesian_to_zephyr(ccoord=ccoord)
Copy link
Member

Choose a reason for hiding this comment

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

I would fold the two *_runs tests with the parameterized ones, but if you want to keep them as smoke tests, I recommend at least testing the returned type:

Suggested change
cartesian_to_zephyr(ccoord=ccoord)
self.assertIsInstance(cartesian_to_zephyr(ccoord=ccoord), ZephyrCoord)

uwkjzs = [(0, 2, 4, 1, 5), (1, 3, 3, 0, 0), (1, 2, None, 1, 5)]
zcoords = [ZephyrCoord(*uwkjz) for uwkjz in uwkjzs]
for zcoord in zcoords:
zephyr_to_cartesian(zcoord=zcoord)
Copy link
Member

Choose a reason for hiding this comment

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

Same comment as above:

Suggested change
zephyr_to_cartesian(zcoord=zcoord)
self.assertIsInstance(zephyr_to_cartesian(zcoord=zcoord), CartesianCoord)

Comment on lines +29 to +30
x (int): The displacement in the x-direction of a Cartesian coordinate.
y (int): The displacement in the y-direction of a Cartesian coordinate.
Copy link
Member

Choose a reason for hiding this comment

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

In Ocean, we follow Google Python Style Guide, and omit types from docstrings when they are type-annotated. Here, and elsewhere in this PR.

Returns:
PlaneShift: The displacement in CartesianCoord by self followed by other.
"""
if type(self) != type(other):
Copy link
Member

Choose a reason for hiding this comment

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

By using isinstance, you support PlaneShift subclasses for other:

Suggested change
if type(self) != type(other):
if not isinstance(other, PlaneShift):


from __future__ import annotations

from typing import Iterator
Copy link
Member

Choose a reason for hiding this comment

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

Deprecated in favor of:

Suggested change
from typing import Iterator
from collections.abc import Iterator

for cc in self.odd_neighbors_generator(where=where):
yield cc

def neighbors(
Copy link
Member

Choose a reason for hiding this comment

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

What's the reason to include both the generators for all kinds of neighbors, and then redundant functions that return a set?

I would remove _generator suffix from the generators, and keep only those.

Comment on lines +616 to +619
for nbr in self.internal_neighbors_generator(where=where):
if other == nbr:
return True
return False
Copy link
Member

Choose a reason for hiding this comment

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

This, and the similar 3 other functions feel redundant as they can be replaced with:

Suggested change
for nbr in self.internal_neighbors_generator(where=where):
if other == nbr:
return True
return False
return other in self.internal_neighbors_generator(where=where)

self,
nbr_kind: EdgeKind | Iterable[EdgeKind] | None = None,
where: Callable[[CartesianCoord | ZephyrCoord], bool] = lambda coord: True,
) -> list[ZEdge]:
Copy link
Member

Choose a reason for hiding this comment

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

Why not make this function a generator?

return self._ccoord == other._ccoord


def __gt__(self, other: ZNode) -> bool:
Copy link
Member

Choose a reason for hiding this comment

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

Instead of manually defining all comparison methods, use @functools.total_ordering.

]
)
def test_degree(self, xy, m, nbr_kind, a, b) -> None:
for t in [None, 1, 4, 6]:
Copy link
Member

Choose a reason for hiding this comment

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

check indent

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.

6 participants