ENH: Adding tests for tril and triu#442
Conversation
Signed-off-by: Pradyot Ranjan <99216956+pradyotRanjan@users.noreply.github.com>
tril and triu
Signed-off-by: Pradyot Ranjan <99216956+pradyotRanjan@users.noreply.github.com>
Signed-off-by: Pradyot Ranjan <99216956+pradyotRanjan@users.noreply.github.com>
Signed-off-by: Pradyot Ranjan <99216956+pradyotRanjan@users.noreply.github.com>
| expected_elements = [ | ||
| x[idx] if idx[-1] <= idx[-2] + k | ||
| else xp.asarray(0, dtype=out.dtype) | ||
| for idx in sh.ndindex(x.shape) | ||
| ] | ||
| if expected_elements: | ||
| expected = xp.stack(expected_elements) | ||
| else: | ||
| expected = xp.asarray([], dtype=out.dtype) | ||
| expected = xp.reshape(expected, x.shape) | ||
| ph.assert_array_elements( | ||
| "tril", | ||
| out=out, | ||
| expected=expected, | ||
| ) |
There was a problem hiding this comment.
I've moved the ph.assert_array_elements outside the loop and used idx entirely for one for loop. expected_elements contains a list of arrays which later gets stacked into one using stack. We then reshape it back to its original shape.
I think this brings us closer to how eye is tested.
There was a problem hiding this comment.
One thing that fails right now is running for jax.numpy with --max-examples=10_000 gives:
+ Exception Group Traceback (most recent call last):
| File "/Users/pradyotranjan/array-api-tests-1/array_api_tests/test_creation_functions.py", line 398, in test_tril
| def test_tril(x, data):
| ^^^
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 2274, in wrapped_test
| raise the_error_hypothesis_found
| hypothesis.errors.FlakyFailure: Hypothesis test_tril(x=Array([[[[ 2.5453735e+18-4.9889314e+16j]],
|
| [[ 1.5772956e+19+5.1305820e+16j]]],
|
|
| [[[ 2.8746495e+16+2.5450868e+16j]],
|
| [[ 1.8076227e+19+1.7226468e+19j]]],
|
|
| [[[-5.6867708e+16-4.8846053e+16j]],
|
| [[ 2.6559498e+16+7.6443090e+18j]]]], dtype=complex64), data=data(...)) produces unreliable results: Falsified on the first call but did not on a subsequent one (1 sub-exception)
| Falsifying example: test_tril(
| x=Array([[[[ 2.5453735e+18-4.9889314e+16j]],
|
| [[ 1.5772956e+19+5.1305820e+16j]]],
|
|
| [[[ 2.8746495e+16+2.5450868e+16j]],
|
| [[ 1.8076227e+19+1.7226468e+19j]]],
|
|
| [[[-5.6867708e+16-4.8846053e+16j]],
|
| [[ 2.6559498e+16+7.6443090e+18j]]]], dtype=complex64),
| data=data(...),
| )
| Draw 1 (k): 0
| Unreliable test timings! On an initial run, this test took 1058.55ms, which exceeded the deadline of 800.00ms, but on a subsequent run it took 4.21 ms, which did not. If you expect this sort of variability in your test timings, consider turning deadlines off for this test by setting deadline=None.
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 1212, in _execute_once_for_engine
| result = self.execute_once(data)
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 1150, in execute_once
| result = self.test_runner(data, run)
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 824, in default_executor
| return function(data)
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 1107, in run
| return test(*args, **kwargs)
| File "/Users/pradyotranjan/array-api-tests-1/array_api_tests/test_creation_functions.py", line 398, in test_tril
| def test_tril(x, data):
| ^^^^^^^^
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/hypothesis/core.py", line 1041, in test
| raise DeadlineExceeded(
| datetime.timedelta(seconds=runtime), self.settings.deadline
| )
| hypothesis.errors.DeadlineExceeded: Test took 1058.55ms, which exceeds the deadline of 800.00ms. If you expect test cases to take this long, you can use @settings(deadline=...) to either set a higher deadline, or to disable it with deadline=None.
+------------------------------------
===================================================================================================== short test summary info =====================================================================================================
FAILED array_api_tests/test_creation_functions.py::test_tril - DeadlineExceeded('Test took 1058.55ms, which exceeds the deadline of 800.00ms. If you expect test cases to take this long, you can use @settings(deadline=...) to either set a higher deadline, or to disable it with deadline...
There was a problem hiding this comment.
Does it still fail if you add --disable-deadline?
There was a problem hiding this comment.
Nope. It takes 13 min to complete the test on my machine.
| ph.assert_shape("tril", out_shape=out.shape, expected=x.shape) | ||
| expected_elements = [ | ||
| x[idx] if idx[-1] <= idx[-2] + k | ||
| else xp.asarray(0, dtype=out.dtype) |
There was a problem hiding this comment.
at a guess, this xp.asarray is not needed, since you xp.stack the result anyway.
There was a problem hiding this comment.
Actually, it's required. As 0 would be counted as a python integer. stack expects a sequence of arrays.
There was a problem hiding this comment.
see this failure when removed
| File "/opt/homebrew/Caskroom/miniconda/base/envs/array-api-tests/lib/python3.14/site-packages/array_api_strict/_manipulation_functions.py", line 172, in stack
| if len({a.device for a in arrays}) > 1:
| ^^^^^^^^
| AttributeError: 'int' object has no attribute 'device'
|
| ========== FAILING CODE SNIPPET:
| xp.tril(Array([[0, 0]], dtype=array_api_strict.uint8), k=0)
There was a problem hiding this comment.
Or it's because non-zero elements, x[idx] are arrays, and the spec prohibits xp.stack with a mix of OD arrays and python scalars? Then let's see of moving xp.asarray out of the loop helps the runtime.
EDIT: comments crossed. Value testing is hard :-(.
| if expected_elements: | ||
| expected = xp.stack(expected_elements) | ||
| else: | ||
| expected = xp.asarray([], dtype=out.dtype) |
There was a problem hiding this comment.
To double-check: this branching is needed even if if expected_elements is an empty list because 1) xp.stack does not accept an empty list, and even if it did, 2) it has no way to guess dtype=out.dtype. Would be nice to add a comment, since it's one of things which goes against numpy finger (and eye) memory.
| ph.assert_kw_dtype("asarray", kw_dtype=_dtype, out_dtype=out.dtype) | ||
| ph.assert_shape("asarray", out_shape=out.shape, expected=shape) | ||
| for idx, v_expect in zip(sh.ndindex(out.shape), _obj): | ||
| print(f"out.shape is : {out.shape} idx is: {idx}") |
There was a problem hiding this comment.
debug print, don't forget to remove before merging
|
Okay, with the runtime of Therefore, let's declare this being as good as it gets, cc #197. There's no point running with |
Mine just completed with the same diff in 15 min but for 10_000. Pushing changes now. |
Signed-off-by: Pradyot Ranjan <99216956+pradyotRanjan@users.noreply.github.com>
See: #441 (That PR has been split and tests for tril and triu are added here)
Towards: #439