Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions dwave/graphs/topologies/common/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2016 D-Wave Systems Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from dwave.graphs.topologies.common.common import _add_compatible_edges, _add_compatible_nodes, _add_compatible_terms
from dwave.graphs.topologies.common.coord import *
from dwave.graphs.topologies.common.node_edge import *
from dwave.graphs.topologies.common.planeshift import *
from dwave.graphs.topologies.common.shape import *
from dwave.graphs.topologies.common.topology import *
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def _add_compatible_terms(
) -> None:
_add_compatible_edges(G, edge_list)
_add_compatible_nodes(G, node_list)
#Check node deletion hasn't caused edge deletion:
# Check node deletion hasn't caused edge deletion:
if edge_list is not None and len(edge_list) != G.number_of_edges():
raise ValueError('The edge_list contains nodes absent from the node_list')
raise ValueError(
'The edge_list contains nodes absent from the node_list')
151 changes: 151 additions & 0 deletions dwave/graphs/topologies/common/coord.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Copyright 2026 D-Wave
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# ================================================================================================


from __future__ import annotations

from enum import Enum, auto
from abc import ABC, abstractmethod
from functools import cached_property, total_ordering
from typing import Any, Iterator

from dwave.graphs.topologies.common.shape import TopologyShape

__all__ = ["Coord", "CoordKind"]


class CoordKind(Enum):
"""Kinds of coordinates of nodes in topologies."""
CARTESIAN = auto()
TOPOLOGY = auto()
LINEAR = auto()


@total_ordering
class Coord(ABC):
"""A class to represent the coordinate of a topology node."""

@classmethod
def topology_name(cls) -> str:
"""Returns the name of the topology associated with the class.

Returns:
str: The name of the topology the class is designed for.
"""
if hasattr(cls, "_topology_name"):
return cls._topology_name
raise NotImplementedError

@classmethod
@abstractmethod
def kind(cls) -> CoordKind:
"""Returns the kind of the coordinate associated with the class.

Returns:
CoordKind: The kind of class's coordinate.
"""

def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)

@abstractmethod
def _args_valid_topology(self, *args, **kwargs) -> None:
"""Verifies the given coordinate is a valid coordinate."""

@abstractmethod
def is_shape_consistent(self, shape: TopologyShape) -> bool:
"""Tells whether the coordinate is consistent with a topology shape.

Args:
shape: The shape to check the consistency of the coordinate with.

Returns:
bool: Whether the coordinate is consistent with the shape.
"""

@abstractmethod
def is_quotient(self) -> bool:
"""Whether the given coordinate is a quotient coordinate."""

@abstractmethod
def to_quotient(
self,
) -> Coord:
"""Converts the coordinate to its corresponding coordinate in a quotient graph."""

@abstractmethod
def to_non_quotient(
self,
shape: TopologyShape,
**kwargs,
) -> list[Coord]:
"""Expands the coordinate to a non-quotient shape; i.e. it gives
all coordinates in a non-quotient graph whose quotient is the coordinate.

Args:
shape: The non-quotient shape to expand the coordinate to.

Returns:
list[Coord]: The expansion of the coordinate into non-quotient.
"""

@abstractmethod
def convert(self, coord_kind: CoordKind) -> Coord:
"""Converts the coordinate to other kinds of coordinate in the same topology.

Args:
coord_kind (CoordKind): The coordinate kind to convert the coordinate to.

Returns:
Coord: The converted coordinate.
"""

@abstractmethod
def to_tuple(self) -> tuple:
"""Returns the tuple cooresponding to the coordinate."""

@cached_property
def _tuple_format(self) -> tuple[Any, ...]:
"""The tuple associated with the object."""
return self.to_tuple()

def __eq__(self, other: object) -> bool:
if (type(self) is not type(other)) or (self.is_quotient() != other.is_quotient()):
return NotImplemented
return self._tuple_format == other._tuple_format

def __lt__(self, other: object) -> bool:
if (type(self) is not type(other)) or (self.is_quotient() != other.is_quotient()):
return NotImplemented
return self._tuple_format < other._tuple_format

def __hash__(self) -> int:
return hash((type(self), self._tuple_format))

def __iter__(self) -> Iterator[Any]:
return iter(self._tuple_format)

def __len__(self) -> int:
return len(self._tuple_format)

def __getitem__(self, i: int) -> Any:
return self._tuple_format[i]

def __repr__(self) -> str:
return f"{type(self).__name__}{self._tuple_format}"

def __str__(self) -> str:
return f"{self._tuple_format}"
Loading