From 45d36c5943071b0bcdc141892a310588d393117b Mon Sep 17 00:00:00 2001 From: "Lee, Kin Long Kelvin" Date: Mon, 2 Dec 2024 11:00:56 -0800 Subject: [PATCH 1/5] refactor: making str method return unsigned image --- matsciml/datasets/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matsciml/datasets/utils.py b/matsciml/datasets/utils.py index 909c988e..d9f77e98 100644 --- a/matsciml/datasets/utils.py +++ b/matsciml/datasets/utils.py @@ -644,7 +644,8 @@ def __eq__(self, other: Edge) -> bool: return all([index_eq, image_eq]) def __str__(self) -> str: - return f"Sorted src/dst: {self.sorted_index}, image: {self.image}" + """Represents the edge without phase or parity information. Mainly for hashing.""" + return f"Sorted src/dst: {self.sorted_index}, |image|: {self.image}" def __hash__(self) -> int: return hash(str(self)) From f5bb79f5074afd7a7b04b7bbcfaf25b769382f42 Mon Sep 17 00:00:00 2001 From: "Lee, Kin Long Kelvin" Date: Mon, 2 Dec 2024 11:04:56 -0800 Subject: [PATCH 2/5] feat: adding unsigned image property --- matsciml/datasets/utils.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/matsciml/datasets/utils.py b/matsciml/datasets/utils.py index d9f77e98..adc9711b 100644 --- a/matsciml/datasets/utils.py +++ b/matsciml/datasets/utils.py @@ -638,6 +638,22 @@ class Edge: def sorted_index(self) -> tuple[int, int]: return (min(self.src, self.dst), max(self.src, self.dst)) + @property + def unsigned_image(self) -> np.ndarray: + """ + Returns the absolute image indices. + + This is used when considering parity-inversion, + i.e. two edges are equivalent if they are in + in mirroring cell images. + + Returns + ------- + np.ndarray + Indices without parity + """ + return np.abs(self.image) + def __eq__(self, other: Edge) -> bool: index_eq = self.sorted_index == other.sorted_index image_eq = np.all(self.image == other.image) From e3df452303103c44bad7db7f9799b28b79cc3d80 Mon Sep 17 00:00:00 2001 From: "Lee, Kin Long Kelvin" Date: Mon, 2 Dec 2024 11:05:27 -0800 Subject: [PATCH 3/5] refactor: using unsigned image in str --- matsciml/datasets/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matsciml/datasets/utils.py b/matsciml/datasets/utils.py index adc9711b..97c0a374 100644 --- a/matsciml/datasets/utils.py +++ b/matsciml/datasets/utils.py @@ -661,7 +661,7 @@ def __eq__(self, other: Edge) -> bool: def __str__(self) -> str: """Represents the edge without phase or parity information. Mainly for hashing.""" - return f"Sorted src/dst: {self.sorted_index}, |image|: {self.image}" + return f"Sorted src/dst: {self.sorted_index}, |image|: {self.unsigned_image}" def __hash__(self) -> int: return hash(str(self)) From 9ab0222ac4d732aa7d1935c8fb657ff126ad4516 Mon Sep 17 00:00:00 2001 From: "Lee, Kin Long Kelvin" Date: Mon, 2 Dec 2024 11:06:21 -0800 Subject: [PATCH 4/5] refactor: making __eq__ also use unsigned image for comparison --- matsciml/datasets/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matsciml/datasets/utils.py b/matsciml/datasets/utils.py index 97c0a374..56a94838 100644 --- a/matsciml/datasets/utils.py +++ b/matsciml/datasets/utils.py @@ -656,7 +656,7 @@ def unsigned_image(self) -> np.ndarray: def __eq__(self, other: Edge) -> bool: index_eq = self.sorted_index == other.sorted_index - image_eq = np.all(self.image == other.image) + image_eq = np.all(self.unsigned_image == other.unsigned_image) return all([index_eq, image_eq]) def __str__(self) -> str: From 0b21f42acc97be4889d84a7bf38327d3fe7f2a1c Mon Sep 17 00:00:00 2001 From: "Lee, Kin Long Kelvin" Date: Mon, 2 Dec 2024 11:10:32 -0800 Subject: [PATCH 5/5] docs: added docstring to explain hash implementation --- matsciml/datasets/utils.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/matsciml/datasets/utils.py b/matsciml/datasets/utils.py index 56a94838..a580811d 100644 --- a/matsciml/datasets/utils.py +++ b/matsciml/datasets/utils.py @@ -664,6 +664,32 @@ def __str__(self) -> str: return f"Sorted src/dst: {self.sorted_index}, |image|: {self.unsigned_image}" def __hash__(self) -> int: + """ + This hash method is primarily intended for use in + ``set`` comparisons to check for uniqueness. + + The general idea for edge-uniqueness is assuming + the undirected case where ``src`` and ``dst`` + is exchangable, and when not considering phase + for image indices. + + As an example, the following two edges are + equivalent as they have interchangable ``src`` + and ``dst`` indices, **and** the displacement + owing to image offsets is the same - just in + opposite directions, + + ``` + Edge(src=1, dst=7, image=[-1, 0, 0]) + Edge(src=7, dst=1, image[1, 0, 0]) + ``` + + Returns + ------- + int + Permutation invariant hash of this edge. + """ + return hash(str(self))