Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
25 changes: 0 additions & 25 deletions dpnp/linalg/dpnp_algo_linalg.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ cimport numpy
cimport dpnp.dpnp_utils as utils

__all__ = [
"dpnp_cond",
"dpnp_eig",
"dpnp_eigvals",
]
Expand All @@ -60,30 +59,6 @@ ctypedef c_dpctl.DPCTLSyclEventRef(*custom_linalg_2in_1out_func_ptr_t)(c_dpctl.D
const c_dpctl.DPCTLEventVectorRef)


cpdef object dpnp_cond(object input, object p):
if p in ('f', 'fro'):
# TODO: change order='K' when support is implemented
input = dpnp.ravel(input, order='C')
sqnorm = dpnp.dot(input, input)
res = dpnp.sqrt(sqnorm)
ret = dpnp.array([res])
elif p == dpnp.inf:
dpnp_sum_val = dpnp.sum(dpnp.abs(input), axis=1)
ret = dpnp.max(dpnp_sum_val)
elif p == -dpnp.inf:
dpnp_sum_val = dpnp.sum(dpnp.abs(input), axis=1)
ret = dpnp.min(dpnp_sum_val)
elif p == 1:
dpnp_sum_val = dpnp.sum(dpnp.abs(input), axis=0)
ret = dpnp.max(dpnp_sum_val)
elif p == -1:
dpnp_sum_val = dpnp.sum(dpnp.abs(input), axis=0)
ret = dpnp.min(dpnp_sum_val)
else:
ret = dpnp.array([input.item(0)])
return ret


cpdef tuple dpnp_eig(utils.dpnp_descriptor x1):
cdef shape_type_c x1_shape = x1.shape

Expand Down
57 changes: 43 additions & 14 deletions dpnp/linalg/dpnp_iface_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
check_stacked_2d,
check_stacked_square,
dpnp_cholesky,
dpnp_cond,
dpnp_det,
dpnp_eigh,
dpnp_inv,
Expand Down Expand Up @@ -144,32 +145,60 @@ def cholesky(a, upper=False):
return dpnp_cholesky(a, upper=upper)


def cond(input, p=None):
def cond(x, p=None):
"""
Compute the condition number of a matrix.

For full documentation refer to :obj:`numpy.linalg.cond`.

Limitations
-----------
Input array is supported as :obj:`dpnp.ndarray`.
Parameter p=[None, 1, -1, 2, -2, dpnp.inf, -dpnp.inf, 'fro'] is supported.
Parameters
----------
x : {dpnp.ndarray, usm_ndarray}
The matrix whose condition number is sought.
p : {None, 1, -1, 2, -2, inf, -inf, "fro"}, optional
Order of the norm used in the condition number computation.
inf means dpnp's `inf` object. The default is ``None``.
Comment thread
vtavana marked this conversation as resolved.
Outdated

Returns
-------
out : dpnp.ndarray
The condition number of the matrix. May be infinite.

See Also
--------
:obj:`dpnp.norm` : Matrix or vector norm.
Comment thread
vtavana marked this conversation as resolved.
Outdated
"""

if not use_origin_backend(input):
if p in [None, 1, -1, 2, -2, dpnp.inf, -dpnp.inf, "fro"]:
result_obj = dpnp_cond(input, p)
result = dpnp.convert_single_elem_array_to_scalar(result_obj)
Examples
--------
>>> import dpnp as np
>>> a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]])
>>> a
array([[ 1, 0, -1],
[ 0, 1, 0],
[ 1, 0, 1]])
>>> np.linalg.cond(a)
array(1.4142135623730951)
Comment thread
vtavana marked this conversation as resolved.
Outdated
>>> np.linalg.cond(a, 'fro')
array(3.1622776601683795)
Comment thread
vtavana marked this conversation as resolved.
Outdated
>>> np.linalg.cond(a, np.inf)
array(2.)
>>> np.linalg.cond(a, -np.inf)
array(1.)
>>> np.linalg.cond(a, 1)
array(2.)
>>> np.linalg.cond(a, -1)
array(1.)
>>> np.linalg.cond(a, 2)
array(1.4142135623730951)
Comment thread
vtavana marked this conversation as resolved.
Outdated
>>> np.linalg.cond(a, -2)
array(0.70710678118654746) # may vary
Comment thread
vtavana marked this conversation as resolved.
Outdated
>>> min(np.linalg.svd(a, compute_uv=False))*min(np.linalg.svd(np.linalg.inv(a), compute_uv=False))
array(0.70710678118654746) # may vary
Comment thread
vtavana marked this conversation as resolved.
Outdated

return result
else:
pass
"""

return call_origin(numpy.linalg.cond, input, p)
dpnp.check_supported_arrays_type(x)
return dpnp_cond(x, p)


def det(a):
Expand Down
46 changes: 43 additions & 3 deletions dpnp/linalg/dpnp_utils_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"check_stacked_2d",
"check_stacked_square",
"dpnp_cholesky",
"dpnp_cond",
"dpnp_det",
"dpnp_eigh",
"dpnp_inv",
Expand Down Expand Up @@ -199,6 +200,11 @@ def _common_inexact_type(default_dtype, *dtypes):
return dpnp.result_type(*inexact_dtypes)


def _is_empty_2d(arr):
Comment thread
vtavana marked this conversation as resolved.
# check size first for efficiency
return arr.size == 0 and prod(arr.shape[-2:]) == 0


def _lu_factor(a, res_type):
"""
Compute pivoted LU decomposition.
Expand Down Expand Up @@ -841,6 +847,40 @@ def dpnp_cholesky(a, upper):
return a_h


def dpnp_cond(x, p=None):
"""Compute the condition number of a matrix."""

if _is_empty_2d(x):
raise dpnp.linalg.LinAlgError("cond is not defined on empty arrays")
if p is None or p == 2 or p == -2:
s = dpnp.linalg.svd(x, compute_uv=False)
with numpy.errstate(all="ignore"):
Comment thread
vtavana marked this conversation as resolved.
Outdated
if p == -2:
r = s[..., -1] / s[..., 0]
else:
r = s[..., 0] / s[..., -1]
else:
# Call inv(x) ignoring errors. The result array will
# contain nans in the entries where inversion failed.
check_stacked_2d(x)
check_stacked_square(x)
Comment thread
vtavana marked this conversation as resolved.
Outdated
result_t = _common_type(x)
with numpy.errstate(all="ignore"):
invx = dpnp.linalg.inv(x)
r = dpnp.linalg.norm(x, p, axis=(-2, -1)) * dpnp.linalg.norm(
invx, p, axis=(-2, -1)
)
r = r.astype(result_t, copy=False)

# Convert nans to infs unless the original array had nan entries
nan_mask = dpnp.isnan(r)
if nan_mask.any():
nan_mask &= ~dpnp.isnan(x).any(axis=(-2, -1))
r[nan_mask] = dpnp.inf

return r


def dpnp_det(a):
"""
dpnp_det(a)
Expand Down Expand Up @@ -1222,18 +1262,18 @@ def dpnp_multi_dot(n, arrays, out=None):
"""Compute the dot product of two or more arrays in a single function call."""

if not arrays[0].ndim in [1, 2]:
raise numpy.linalg.LinAlgError(
raise dpnp.linalg.LinAlgError(
f"{arrays[0].ndim}-dimensional array given. First array must be 1-D or 2-D."
)

if not arrays[-1].ndim in [1, 2]:
raise numpy.linalg.LinAlgError(
raise dpnp.linalg.LinAlgError(
f"{arrays[-1].ndim}-dimensional array given. Last array must be 1-D or 2-D."
)

for arr in arrays[1:-1]:
if arr.ndim != 2:
raise numpy.linalg.LinAlgError(
raise dpnp.linalg.LinAlgError(
f"{arr.ndim}-dimensional array given. Inner arrays must be 2-D."
)

Expand Down
13 changes: 0 additions & 13 deletions tests/skipped_tests.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,6 @@ tests/third_party/cupy/fft_tests/test_fft.py::TestFftn_param_23_{axes=None, norm

tests/third_party/intel/test_zero_copy_test1.py::test_dpnp_interaction_with_dpctl_memory

tests/test_linalg.py::test_cond[-1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[-2-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[2-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[-2-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[2-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond["fro"-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond["fro"-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[None-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[None-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[-numpy.inf-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[numpy.inf-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]

tests/test_linalg.py::test_matrix_rank[None-[0, 1]-float64]
tests/test_linalg.py::test_matrix_rank[None-[0, 1]-float32]
tests/test_linalg.py::test_matrix_rank[None-[0, 1]-int64]
Expand Down
13 changes: 0 additions & 13 deletions tests/skipped_tests_gpu.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -158,19 +158,6 @@ tests/third_party/cupy/random_tests/test_distributions.py::TestDistributionsMult

tests/third_party/intel/test_zero_copy_test1.py::test_dpnp_interaction_with_dpctl_memory

tests/test_linalg.py::test_cond[-1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[1-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[-2-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[2-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[-2-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[2-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond["fro"-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond["fro"-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[None-[[1, 0, -1], [0, 1, 0], [1, 0, 1]]]
tests/test_linalg.py::test_cond[None-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[-numpy.inf-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]
tests/test_linalg.py::test_cond[numpy.inf-[[1, 2, 3], [4, 5, 6], [7, 8, 9]]]

tests/test_linalg.py::test_matrix_rank[None-[0, 1]-float64]
tests/test_linalg.py::test_matrix_rank[None-[0, 1]-float32]
tests/test_linalg.py::test_matrix_rank[None-[0, 1]-int64]
Expand Down
Loading