Skip to content

fq_default_poly test fails sometimes #221

@oscarbenjamin

Description

@oscarbenjamin

I just tried running the test suite in parallel with pytest-xdist like:

$ spin test -- -n4
Invoking `build` prior to running tests:
$ meson compile -C build
INFO: autodetecting backend as ninja
INFO: calculating backend command to run: /home/oscar/.pyenv/versions/python-flint-3.12/bin/ninja -C /home/oscar/current/active/python-flint/build
ninja: Entering directory `/home/oscar/current/active/python-flint/build'
ninja: no work to do.
$ meson install --only-changed -C build --destdir ../build-install
$ export PYTHONPATH="/home/oscar/current/active/python-flint/build-install/usr/lib/python3.12/site-packages"
$ /home/oscar/.pyenv/versions/3.12.0/envs/python-flint-3.12/bin/python3.12 -P -c 'import flint'
$ cd /home/oscar/current/active/python-flint/build-install/usr/lib/python3.12/site-packages
$ /home/oscar/.pyenv/versions/3.12.0/envs/python-flint-3.12/bin/python3.12 -P -m pytest --import-mode=importlib --pyargs -n4
======================================== test session starts ========================================
platform linux -- Python 3.12.0, pytest-8.3.2, pluggy-1.5.0
rootdir: /home/oscar/current/active/python-flint
configfile: pyproject.toml
plugins: doctestplus-1.2.1, xdoctest-1.2.0, hypothesis-6.88.4, xdist-3.4.0, cov-5.0.0
4 workers [760 items]   
............................................................................................. [ 12%]
......F...................................................................................... [ 24%]
............................................................................................. [ 36%]
............................................................................................. [ 48%]
............................................................................................. [ 61%]
............................................................................................. [ 73%]
............................................................................................. [ 85%]
............................................................................................. [ 97%]
................                                                                              [100%]
============================================= FAILURES ==============================================
_______________________________________ test_fq_default_poly ________________________________________
...
            # series
            f_non_square = R_test([nqr, 1, 1, 1])
            f_zero = R_test([0, 1, 1, 1])
            assert raises(lambda: f_non_square.sqrt_trunc(1), ValueError)
            assert raises(lambda: f_zero.sqrt_trunc(1), ZeroDivisionError)
            assert raises(lambda: f_non_square.inv_sqrt_trunc(1), ValueError)
            assert raises(lambda: f_zero.inv_sqrt_trunc(1), ZeroDivisionError)
>           f_inv = f.inverse_series_trunc(2)

flint/test/test_all.py:4480: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   ZeroDivisionError: constant coefficient must be invertible

flint/types/fq_default_poly.pyx:1244: ZeroDivisionError
====================================== short test summary info ======================================
FAILED flint/test/test_all.py::test_fq_default_poly - ZeroDivisionError: constant coefficient must be invertible
=================================== 1 failed, 759 passed in 7.72s ===================================

This same test passes if I run the whole test suite normally or just run that particular test:

$ spin test -- -k test_fq_default_poly
Invoking `build` prior to running tests:
$ meson compile -C build
INFO: autodetecting backend as ninja
INFO: calculating backend command to run: /home/oscar/.pyenv/versions/python-flint-3.12/bin/ninja -C /home/oscar/current/active/python-flint/build
ninja: Entering directory `/home/oscar/current/active/python-flint/build'
ninja: no work to do.
$ meson install --only-changed -C build --destdir ../build-install
$ export PYTHONPATH="/home/oscar/current/active/python-flint/build-install/usr/lib/python3.12/site-packages"
$ /home/oscar/.pyenv/versions/3.12.0/envs/python-flint-3.12/bin/python3.12 -P -c 'import flint'
$ cd /home/oscar/current/active/python-flint/build-install/usr/lib/python3.12/site-packages
$ /home/oscar/.pyenv/versions/3.12.0/envs/python-flint-3.12/bin/python3.12 -P -m pytest --import-mode=importlib -k test_fq_default_poly
======================================== test session starts ========================================
platform linux -- Python 3.12.0, pytest-8.3.2, pluggy-1.5.0
rootdir: /home/oscar/current/active/python-flint
configfile: pyproject.toml
plugins: doctestplus-1.2.1, xdoctest-1.2.0, hypothesis-6.88.4, xdist-3.4.0, cov-5.0.0
collected 760 items / 759 deselected / 1 selected                                                   

flint/test/test_all.py .                                                                      [100%]

================================= 1 passed, 759 deselected in 0.50s =================================

Basically the operation somehow depends on the order of operations that take place before it when it should not. I think what this means is that there is some issue with fq_default_poly related either to caching (of contexts?) or some kind of invalid pointer usage or something.

Here is a deterministic way to reproduce this without using parallel processes:

$ spin test -- flint/test/test_all.py::test_matrices_rank flint/test/test_all.py::test_matrices_rref flint/test/test_all.py::test_matrices_solve flint/test/test_all.py::test_matrices_transpose flint/test/test_all.py::test_fq_default flint/test/test_all.py::test_fq_default_poly
...
            # inverse_mod
            f = R_test.random_element()
            while True:
                h = R_test.random_element()
                if f.gcd(h).is_one():
                    break
            g = f.inverse_mod(h)
            assert f.mul_mod(g, h).is_one()
            assert raises(lambda: f.inverse_mod(2*f), ValueError)
    
            # series
            f_non_square = R_test([nqr, 1, 1, 1])
            f_zero = R_test([0, 1, 1, 1])
            assert raises(lambda: f_non_square.sqrt_trunc(1), ValueError)
            assert raises(lambda: f_zero.sqrt_trunc(1), ZeroDivisionError)
            assert raises(lambda: f_non_square.inv_sqrt_trunc(1), ValueError)
            assert raises(lambda: f_zero.inv_sqrt_trunc(1), ZeroDivisionError)
>           f_inv = f.inverse_series_trunc(2)

flint/test/test_all.py:4480: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

>   ???
E   ZeroDivisionError: constant coefficient must be invertible

flint/types/fq_default_poly.pyx:1244: ZeroDivisionError

In the debugger I can see that f is not invertible:

> /home/oscar/current/active/python-flint/build-install/usr/lib/python3.12/site-packages/flint/test/test_all.py(4480)test_fq_default_poly()
-> f_inv = f.inverse_series_trunc(2)
(Pdb) p f
x

Ah, I see it is because we are using random_element but the seed is affected by which tests run before.

I think that the test needs to generate a random element that does not have a zero constant coefficient or otherwise should be checking for this like:

if ...
    assert func() == ...
else:
    assert raises(lambda func, ...)

Maybe if we are going to use random tests then we need to:

  • Make sure that they are actually random (with different seeds) each time.
  • Display the seed used for reproducibility.
  • Provide some way to set the seed...

CC @GiacomoPope

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions