multi_index#

This module contains numerical routines for manipulating multi-indices.

minterpy.utils.multi_index.get_poly_degree(exponents, lp_degree)[source]#

Get the polynomial degree from a multi-index set for a given lp-degree.

Parameters:
  • exponents (np.ndarray) – An array of exponents of a multi-index set.

  • lp_degree (float) – The lp-degree of the multi-index set.

Returns:

The polynomial degree from the multi-index set for the given lp-degree.

Return type:

int

minterpy.utils.multi_index.get_exponent_matrix(spatial_dimension, poly_degree, lp_degree)[source]#

Generate exponent matrix.

Parameters:
  • spatial_dimension (int) – Dimension of the domain space.

  • poly_degree (int) – Polynomial degree described by the resulting exponent matrix.

  • lp_degree (int or float) – Degree of the used lp-norm. This can be any integer bigger than one or np.inf.

Returns:

List of exponent arrays for all monomials, whose lp-norm of the exponents is smaller or equal to the given poly_degree. The list is given as a np.ndarray with the shape (number_of_monomials, spatial_dimension) and the list is lexicographically ordered.

Return type:

np.ndarray

minterpy.utils.multi_index.gen_backward_neighbors(index)[source]#

Yield the backward neighbors of a given multi-index set element.

Parameters:

index (numpy.ndarray) – Multi-index set element (i.e., a vector of multi-indices), a one-dimensional array of length m, where m is the spatial dimensions.

Returns:

A generator that yields all the backward neighbors (i.e., all vectors of multi-indices “smaller by 1”) of the given multi-index element.

Return type:

Iterable [numpy.ndarray]

Examples

>>> my_backward_neighbors = gen_backward_neighbors(np.array([1, 1, 2]))
>>> for my_backward_neighbor in my_backward_neighbors:
...     print(my_backward_neighbor)
[0 1 2]
[1 0 2]
[1 1 1]
minterpy.utils.multi_index.gen_missing_backward_neighbors(indices)[source]#

Yield all the missing backward neighbors for an array of multi-indices.

Parameters:

indices (numpy.ndarray) – Array of lexicographically sorted multi-indices, a two-dimensional non-negative integer array of shape (N, m), where N is the number of multi-indices and m is the number of spatial dimensions.

Returns:

A generator that yields all the missing backward neighbors (i.e., all the missing vectors of multi-indices “smaller by 1”) of the array of multi-indices.

Return type:

Iterable [numpy.ndarray]

Notes

  • This function strictly requires a lexicographically sorted array of multi-indices but, as a utility function, it does not check for them for efficiency reason. Higher-level functions that call this function must make sure that the array is sorted beforehand.

Examples

>>> my_missing_neighbors = gen_missing_backward_neighbors(np.array([[3]]))
>>> for missing_neighbor in my_missing_neighbors:
...     print(missing_neighbor)
[2]
>>> my_missing_neighbors = gen_missing_backward_neighbors(
...     np.array([[1, 1, 1]])
... )
>>> for missing_neighbor in my_missing_neighbors:
...     print(missing_neighbor)
[0 1 1]
[1 0 1]
[1 1 0]
minterpy.utils.multi_index.is_complete(indices, poly_degree, lp_degree)[source]#

Check if an array of multi-indices is complete w.r.t poly- & lp-degree.

Parameters:
  • indices (numpy.ndarray) – Array of lexicographically sorted multi-indices, a two-dimensional non-negative integer array of shape (N, m), where N is the number of multi-indices and m is the number of spatial dimensions.

  • poly_degree (int) – Polynomial degree supported by the multi-index set.

  • lp_degree (float) – \(p\) in the \(l_p\)-norm with respect to which the multi-index set is defined.

Returns:

True if the multi-index set is complete and False otherwise. The function also returns False if the array of multi-indices is not lexicographically sorted (including containing any duplicate entries).

Return type:

bool

Notes

  • For a definition of completeness, refer to the relevant section of the Minterpy Documentation.

Examples

>>> my_indices = np.array([
... [0, 0, 0],
... [1, 0, 0],
... [0, 1, 0],
... [1, 1, 0],
... [0, 0, 1],
... [1, 0, 1],
... [0, 1, 1],
... [1, 1, 1]])
>>> is_complete(my_indices, poly_degree=1, lp_degree=np.inf)
True
>>> is_complete(my_indices, poly_degree=1, lp_degree=2.0)
False
>>> is_complete(my_indices, poly_degree=2, lp_degree=1.0)
False
minterpy.utils.multi_index.is_disjoint(indices_1, indices_2, expand_dim_=False)[source]#

Check if an array of multi-indices is disjoint with another.

Parameters:
  • indices_1 (numpy.ndarray) – Two-dimensional integer array of shape (N1, m), where N1 is the number of multi-indices and m is the number of spatial dimensions.

  • indices_2 (numpy.ndarray) – Two-dimensional integer array of shape (N2, m), where N2 is the number of multi-indices and m is the number of spatial dimensions.

  • expand_dim (bool, optional) – Flag to allow the spatial dimension (i.e., the number of columns) of the indices to be expanded if there is a difference.

  • expand_dim_ (bool)

Returns:

True if the multi-index sets are disjoint and False otherwise. The function also returns True if the number of columns are different and expand_dim is set to False.

Return type:

bool

Examples

>>> my_indices_1 = np.array([
... [0, 0, 0],
... [1, 0, 0],
... [1, 1, 1]])
>>> my_indices_2 = np.array([
... [0, 0, 0],
... [1, 1, 1]])
>>> is_disjoint(my_indices_1, my_indices_2)
False
>>> my_indices_3 = np.array([
... [2, 0, 1],
... [1, 2, 1]])
>>> is_disjoint(my_indices_1, my_indices_3)
True
>>> my_indices_4 = np.array([
... [0, 0],
... [1, 0]])
>>> is_disjoint(my_indices_1, my_indices_4)
True
>>> is_disjoint(my_indices_1, my_indices_4, expand_dim_=True)
False
minterpy.utils.multi_index.is_downward_closed(indices)[source]#

Check if an array of multi-indices is downward-closed.

Parameters:

indices (numpy.ndarray) – Array of lexicographically sorted multi-indices, a two-dimensional non-negative integer array of shape (N, m), where N is the number of multi-indices and m is the number of spatial dimensions.

Returns:

True if the multi-index set is downward-closed and False otherwise. The function also returns False if the array of multi-indices is not lexicographically sorted (including containing any duplicate entries).

Return type:

bool

Notes

  • A multi-index is downward-closed if it does not contain “hole” across its spatial dimensions.

  • Some synonyms for a downward-closed multi-index set are: “monotonic”, “lower”, or “lexicographically complete”.

Examples

>>> my_indices = np.array([
... [0, 0, 0],
... [1, 0, 0],
... [0, 0, 1]])
>>> is_downward_closed(my_indices)
True
>>> my_indices = np.array([
... [0, 0, 0],
... [1, 0, 0],
... [0, 2, 0]])  # missing [0, 1, 0]
>>> is_downward_closed(my_indices)
False
minterpy.utils.multi_index.list_insert_single(list_of_indices, index2insert, check_for_inclusion=True)[source]#

inserts a single index into a given list of indices maintaining lexicographical ordering

Parameters:
  • list_of_indices (list[np.ndarray])

  • index2insert (np.ndarray)

  • check_for_inclusion (bool)

minterpy.utils.multi_index.insert_lexicographically(indices, indices2insert)[source]#

inserts possibly multiple index vectors into a given array of indices maintaining lexicographical ordering

exploits ordering for increased efficiency:

inserts one vector after another to maintain ordering

NOTE: is expected to return the same identical array instance

if all exponents are already contained!

Parameters:
Return type:

ndarray

minterpy.utils.multi_index.make_derivable(indices)[source]#

inserts all missing multi index vectors “smaller by one”

Parameters:

indices (ndarray)

Return type:

ndarray

minterpy.utils.multi_index.make_complete(exponents, lp_degree)[source]#

Create a complete exponents from a given array of exponents.

A complete set of exponents contains all monomials, whose \(l_p\)-norm of the exponents are smaller or equal to the polynomial degree of the set.

Parameters:
  • exponents (numpy.ndarray) – A given exponent array to be completed.

  • lp_degree (float) – A given \(l_p\) of the \(l_p\)-norm (i.e., the lp-degree) for the completion.

Returns:

The complete exponents with respect to the given exponents and lp_degree.

Return type:

numpy.ndarray

Notes

  • The polynomial degree is inferred from the given exponents with respect to the required lp_degree. It is the smallest polynomial degree with respect to the lp_degree to contain the given exponents.

Examples

>>> exponent = np.array([[2, 2]])
>>> lp_degree = 2.0
>>> make_complete(exponent, lp_degree)  # Complete w.r.t the lp_degree
array([[0, 0],
       [1, 0],
       [2, 0],
       [3, 0],
       [0, 1],
       [1, 1],
       [2, 1],
       [0, 2],
       [1, 2],
       [2, 2],
       [0, 3]])
minterpy.utils.multi_index.make_downward_closed(indices)[source]#

Make an array of multi-indices downward-closed.

Parameters:

indices (numpy.ndarray) – Array of lexicographically sorted multi-indices, a two-dimensional non-negative integer array of shape (N, m), where N is the number of multi-indices and m is the number of spatial dimensions.

Returns:

Array of downward-closed lexicographically sorted multi-indices, a two-dimensional array of shape (N1, m), where N1 is the number of multi-indices in the downward-closed set and m is the number of spatial dimensions.

Return type:

numpy.ndarray

Notes

  • This function strictly requires a lexicographically sorted array of multi-indices but, as a utility function, it does not check for them for efficiency reason. Higher-level functions that call this function must make sure that the array is sorted beforehand.

Examples

>>> my_indices = np.array([
... [0, 0],
... [2, 0],  # Jump from [1, 0]
... [0, 3],  # Jump from [0, 1] and [0, 2]
... ])
>>> make_downward_closed(my_indices)
array([[0, 0],
       [1, 0],
       [2, 0],
       [0, 1],
       [0, 2],
       [0, 3]])
>>> my_indices = np.array([[1, 1, 1]])  # must be two-dimensional
>>> make_downward_closed(my_indices)
array([[0, 0, 0],
       [1, 0, 0],
       [0, 1, 0],
       [1, 1, 0],
       [0, 0, 1],
       [1, 0, 1],
       [0, 1, 1],
       [1, 1, 1]])
minterpy.utils.multi_index.find_match_between(smaller_idx_set, larger_idx_set)[source]#

find the positions of each multi_index of the smaller set in the larger set

NOTE: both sets are required to be ordered lexicographically! NOTE: the smaller set is required to be a subset of the larger set NOTE: this function is required for ‘rebasing’ a polynomial onto complete multi indices (map the coefficients)

Parameters:
Return type:

ndarray

minterpy.utils.multi_index.lex_sort(indices)[source]#

Lexicographically sort an array of multi-indices.

Parameters:

indices (numpy.ndarray) – Two-dimensional array of multi-indices to be sorted.

Returns:

Lexicographically sorted array, having the same type as indices. Only unique entries are kept in the sorted array.

Return type:

numpy.ndarray

Examples

>>> xx = np.array([
... [0, 1, 2, 3],
... [0, 1, 0, 1],
... [0, 0, 0, 0],
... [0, 0, 1, 1],
... [0, 0, 0, 0],
... ])
>>> lex_sort(xx)  # Sort and remove duplicates
array([[0, 0, 0, 0],
       [0, 1, 0, 1],
       [0, 0, 1, 1],
       [0, 1, 2, 3]])
minterpy.utils.multi_index.multiply_indices(indices_1, indices_2)[source]#

Multiply an array of multi-indices with another array of multi-indices.

Parameters:
  • indices_1 (numpy.ndarray) – Two-dimensional array of multi-indices of shape (N1, m2) where N1 is the number of multi-indices and m2 is the number of dimensions of the first array.

  • indices_2 (numpy.ndarray) – Another two-dimensional array of multi-indices of shape (N2, m2) where N2 is the number of multi-indices and m2 is the number of dimensions of the second array.

Returns:

The product of indices_1 with indices_2 of shape (N3, m3) where m3 is the maximum between m1 and m2. The product array is lexicographically sorted.

Return type:

numpy.ndarray

Examples

>>> my_indices_1 = np.array([
... [0, 0],
... [1, 0],
... [0, 1],
... [1, 1],
... ])
>>> my_indices_2 = np.array([
... [0, 0],
... [1, 0],
... [0, 1],
... ])
>>> multiply_indices(my_indices_1, my_indices_2)
array([[0, 0],
       [1, 0],
       [2, 0],
       [0, 1],
       [1, 1],
       [2, 1],
       [0, 2],
       [1, 2]])
>>> my_indices_3 = np.array([
... [0],
... [1],
... [2],
... ])
>>> multiply_indices(my_indices_2, my_indices_3)  # Different dimension
array([[0, 0],
       [1, 0],
       [2, 0],
       [3, 0],
       [0, 1],
       [1, 1],
       [2, 1]])
>>> my_indices_4 = np.empty((0, 2), dtype=INT_DTYPE)
>>> multiply_indices(my_indices_3, my_indices_4)  # empty set
array([], shape=(0, 2), dtype=int64)
minterpy.utils.multi_index.union_indices(indices_1, indices_2)[source]#

Create a union between two arrays of multi-indices.

Parameters:
  • indices_1 (numpy.ndarray) – Two-dimensional array of multi-indices of shape (N1, m2) where N1 is the number of multi-indices and m2 is the number of dimensions of the first array.

  • indices_2 (numpy.ndarray) – Another two-dimensional array of multi-indices of shape (N2, m2) where N2 is the number of multi-indices and m2 is the number of dimensions of the second array.

Returns:

The union of indices_1 and indices_2 of shape (N3, m3) where m3 is the maximum between m1 and m2. The union is lexicographically sorted.

Return type:

numpy.ndarray

Examples

>>> my_indices_1 = np.array([
... [0, 0],
... [1, 0],
... [0, 1],
... [1, 1],
... ])
>>> my_indices_2 = np.array([
... [0, 0],
... [1, 0],
... [0, 1],
... ])
>>> union_indices(my_indices_1, my_indices_2)
array([[0, 0],
       [1, 0],
       [0, 1],
       [1, 1]])
>>> my_indices_3 = np.array([
... [0],
... [1],
... [2],
... ])
>>> union_indices(my_indices_1, my_indices_3)  # Different dimension
array([[0, 0],
       [1, 0],
       [2, 0],
       [0, 1],
       [1, 1]])
>>> my_indices_4 = np.empty((0, 1), dtype=int)
>>> union_indices(my_indices_3, my_indices_4)
array([[0],
       [1],
       [2]])