Skip to content

Commit

Permalink
Merge pull request #531 from Rosalbam1/dev
Browse files Browse the repository at this point in the history
tensor, vector, ring updates + linting
  • Loading branch information
avcopan authored Jul 11, 2024
2 parents 91a3377 + f3dec8d commit c4dde58
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 210 deletions.
2 changes: 1 addition & 1 deletion automol/util/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def move_items_to_front(lst: Sequence, items) -> tuple:
return tuple(lst)


def breakby(lst: Sequence, elem) -> tuple[tuple, tuple]:
def breakby(lst: Sequence, elem) -> tuple[tuple, ...]:
"""Break a list by element, dropping the element itself.
Analogous to '<char>'.split('<string>') for strings.
:param lst: The list
Expand Down
2 changes: 1 addition & 1 deletion automol/util/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def string(mat: Sequence[Sequence[float]], val_format="{0:>8.3f}") -> str:
"""Write a matrix to a string.
:param mat: matrix to form string with
:param mat: Matrix to form string with
:param val_format: A number-formatting string, such as "{:.3f}"
:return: Matrix as a string
"""
Expand Down
33 changes: 18 additions & 15 deletions automol/util/ring.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"""Functions for dealing with a list of items encoding a ring."""

import itertools
from collections.abc import Sequence

import more_itertools as mit


def normalize(items: list[object]) -> list[object]:
def normalize(items: Sequence[object]) -> tuple[object, ...]:
"""Normalize the ordering of items in a ring.
:param items: The ring items
Expand All @@ -20,7 +21,7 @@ def normalize(items: list[object]) -> list[object]:
return cycle(items, count=items.index(start_item))


def cycle(items: list[object], count: int = 1) -> list[object]:
def cycle(items: Sequence[object], count: int = 1) -> tuple[object]:
"""Cycle ring items once.
Example: (1, 2, 3, 4) -> (2, 3, 4, 1)
Expand All @@ -34,7 +35,7 @@ def cycle(items: list[object], count: int = 1) -> list[object]:
return tuple(itertools.islice(cycler, nitems))


def edges(items: list[object]) -> list[object]:
def edges(items: Sequence[object]) -> tuple[tuple[object, object], ...]:
"""Get the edge pairs of a ring.
Example: (1, 2, 3, 4) -> ((1, 2), (2, 3), (3, 4), (4, 1))
Expand All @@ -46,7 +47,7 @@ def edges(items: list[object]) -> list[object]:


def distance(
items: list[object], item1: object, item2: object, longest: bool = False
items: Sequence[object], item1: object, item2: object, longest: bool = False
) -> int:
"""Find the distance between two items in a ring.
Expand Down Expand Up @@ -82,8 +83,8 @@ def distance(


def cycle_item_to_front(
items: list[object], item: object, end_item: object = None
) -> list[object]:
items: Sequence[object], item: object, end_item: object = None
) -> tuple[object, ...]:
"""Cycle ring items until one is in front.
Optionally, request one adjacent item to be at the end, reversing the ring order if
Expand All @@ -107,8 +108,8 @@ def cycle_item_to_front(


def cycle_items_to_front(
items: list[object], front_items: list[object]
) -> list[object]:
items: Sequence[object], front_items: Sequence[object]
) -> tuple[object, ...]:
"""Cycle ring items until a group of adjacent items is at the front of the list.
:param items: The ring items
Expand All @@ -129,7 +130,9 @@ def cycle_items_to_front(
return tuple(itertools.islice(cycler, nitems))


def cycle_items_to_back(items: list[object], back_items: list[object]) -> list[object]:
def cycle_items_to_back(
items: Sequence[object], back_items: Sequence[object]
) -> tuple[object, ...]:
"""Cycle ring items until a group of adjacent items is at the end of the list.
:param items: The ring items
Expand All @@ -151,8 +154,8 @@ def cycle_items_to_back(items: list[object], back_items: list[object]) -> list[o


def cycle_to_split(
items: list[object], split_pair: tuple[object, object]
) -> list[object]:
items: Sequence[object], split_pair: tuple[object, object]
) -> tuple[object, ...]:
"""Cycle to split a pair of adjacent items, putting one on each end of the list.
:param items: The ring items
Expand Down Expand Up @@ -187,10 +190,10 @@ def cycle_to_split(


def cycle_to_optimal_split(
items: list[object],
split_pairs: list[tuple[object, object]],
back_items: list[object],
) -> list[object]:
items: Sequence[object],
split_pairs: Sequence[tuple[object, object]],
back_items: Sequence[object],
) -> tuple[object, ...]:
"""Cycle to find an "optimum split" that puts a subset of items as close as possible
to the end of the list.
Expand Down
65 changes: 31 additions & 34 deletions automol/util/tensor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
""" I/O operations for higher dimension matrices of 3 or higher
"""
"""I/O operations for higher dimension matrices of 3 or higher."""

import itertools

Expand All @@ -9,41 +8,42 @@


# I/O
def string(arr, include_zeros=False, include_perms=False, val_format="{0:>16.8f}"):
def string(
arr: np.ndarray, include_zeros=False, include_perms=False, val_format="{0:>16.8f}"
) -> str:
"""Write a higher dimensional array (3 or more) to a string.
:param arr: higher dimensions matrix
:type arr: numpy.ndarray
:rtpye: str
:return: Numbers in a string
Format of output string:
idx1 idx2 .. idxn val1
idx1 idx2 .. idxn valn
"""

def _chk_zero(val, include_zeros):
"""decide to write value"""
"""Decide to write value."""
iszero = np.isclose(val, 0.0)
return bool(not iszero or (iszero and include_zeros))

def _chk_idxs(arr):
"""decide if idxs
check if any permutation of idxs is already written
"""Decide if idxs
check if any permutation of idxs is already written.
"""
idxs_lst = tuple(idxs for idxs, _ in np.ndenumerate(arr))
if not include_perms:
idxs_lst = set(tuple(sorted(x)) for x in idxs_lst)
idxs_lst = {tuple(sorted(x)) for x in idxs_lst}
vals_lst = tuple(arr[idxs] for idxs in idxs_lst)

re_idxs = list(zip(idxs_lst, vals_lst))
re_idxs = list(zip(idxs_lst, vals_lst, strict=False))
fin_idxs = tuple(sorted(re_idxs, key=lambda x: x[0]))

return fin_idxs

arr_str = ""
for idxs, val in _chk_idxs(arr):
if _chk_zero(val, include_zeros):
val_str = "".join((f"{idx+1:<6d}" for idx in idxs))
val_str = "".join(f"{idx+1:<6d}" for idx in idxs)
val_str += val_format.format(val)
val_str += "\n"

Expand All @@ -54,18 +54,16 @@ def _chk_idxs(arr):
return arr_str


def from_string(arr_str, fill_perms=False):
def from_string(arr_str: str, fill_perms: bool = False) -> np.ndarray:
"""Write a higher dimensional array (3 or more) to a string.
:param arr_str: string containing higher dimensions matrix
:type arr_str: str
:rtype: numpy.ndarray
:return: Array of high dimension matrix
Format of input string:
idx1 idx2 .. idxn val1
idx1 idx2 .. idxn valn
"""

lines = arr_str.splitlines()

# Get the number of values in each array dimension; initialize array
Expand All @@ -87,17 +85,17 @@ def from_string(arr_str, fill_perms=False):
return arr


def string_submat_4d(arr):
"""Writes a 4-dimensional matrix to a unique string format
def string_submat_4d(arr: np.ndarray):
"""Writes a 4-dimensional matrix to a unique string format.
:param arr:higher dimensions matrix
:return: Numbers in a string
idx1
2d submat1
idx2
2d submat2
idxn
2d submatn
"""

2d submatn.
""" # noqa: D401
nd1, nd2, nd3, nd4 = arr.shape
idxs = tuple(val for val in range(nd1))

Expand All @@ -115,18 +113,18 @@ def string_submat_4d(arr):
return arr_str


def string_submat_3d(arr):
"""Writes a 3-dimensional matrix to a unique string format
def string_submat_3d(arr: np.ndarray):
"""Writes a 3-dimensional matrix to a unique string format.
:param arr:higher dimensions matrix
:return: Numbers in a string
idx1
2d submat1
idx2
2d submat2
idxn
2d submatn
"""
2d submatn.
""" # noqa: D401
nd1, nd2, nd3 = arr.shape
idxs = tuple(val for val in range(nd1))

Expand All @@ -149,14 +147,13 @@ def build_full_array(mat_idxs, mat_vals, fill_perms=False):
((idx1, idx2, ..., idxn), val1),
((idx1, idx2, ..., idxn), val2),
...,
((idx1, idx2, ..., idxn), valn),
"""
((idx1, idx2, ..., idxn), valn),.
""" # noqa: D401

def _gen_idxs(mat_idxs, mat_vals):
"""permute idxs"""

"""Permute idxs."""
full_idxs, full_vals = [], []
for idxs, val in zip(mat_idxs, mat_vals):
for idxs, val in zip(mat_idxs, mat_vals, strict=False):
idx_perms = tuple(itertools.permutations(idxs))
for perm in idx_perms:
full_idxs.append(perm)
Expand All @@ -169,7 +166,7 @@ def _gen_idxs(mat_idxs, mat_vals):
mat_idxs, mat_vals = _gen_idxs(mat_idxs, mat_vals)

# Get dimensionality of matrix (assumes 0 idx of mat)
ncoords = max((max(idxs) for idxs in mat_idxs)) + 1
ncoords = max(max(idxs) for idxs in mat_idxs) + 1
ndim = len(mat_idxs[0])

dims = tuple(ncoords for _ in range(ndim))
Expand All @@ -178,7 +175,7 @@ def _gen_idxs(mat_idxs, mat_vals):
mat = np.zeros(dims)
if fill_perms:
mat_idxs, mat_vals = _gen_idxs(mat_idxs, mat_vals)
for idxs, val in zip(mat_idxs, mat_vals):
for idxs, val in zip(mat_idxs, mat_vals, strict=False):
mat[idxs] = val

return mat
Loading

0 comments on commit c4dde58

Please sign in to comment.