Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conformance tests for is_unit and is_nilpotent #1941

Open
fingolfin opened this issue Dec 20, 2024 · 4 comments · May be fixed by #1947
Open

Add conformance tests for is_unit and is_nilpotent #1941

fingolfin opened this issue Dec 20, 2024 · 4 comments · May be fixed by #1947

Comments

@fingolfin
Copy link
Member

Some ideas (assuming we exclude zero rings at the start):

@test is_unit(one(R))
@test !is_unit(zero(R))
@test is_nilpotent(zero(R))
@test !is_nilpotent(one(R))

For a random element x:

@test !(is_unit(x) && is_nilpotent(x))
@test is_unit(x) == is_unit(x^2)
@test is_nilpotent(x) == is_nilpotent(x^2)
if characteristic(R) > 0 && is_nilpotent(x)
  @test is_unit(x+1)
end
if is_domain_type(typeof(x))
  @test is_nilpotent(x) == is_zero(x)
end

Then we have of course tests of polynomials rings over a ring -- those could also have some tests for specific polynomials, i.e. if the indeterminate is t then is_unit(1+t) == false, etc.

@fingolfin fingolfin linked a pull request Dec 22, 2024 that will close this issue
@JohnAAbbott
Copy link
Collaborator

I propose testing also minus one:

@test is_unit(-one(R))
@test !is_nilpotent(-one(R))

And perhaps also along similar lines:

@test is_unit(x) == is_unit(-x)
@test is_nilpotent(x) == is_nilpotent(-x)

@JohnAAbbott
Copy link
Collaborator

After talking to @fingolfin here is a simple function for generating a nilpotent element: it can be very slow (since it factorizes) and works only if the modulus is a single value.

function nilpotent(R::ResidueRing{T})  where {T}
  facs = factor(modulus(R))  # might take a long time!
  rad = prod([fac_pow[1]  for fac_pow in facs])  # radical of the modulus
  return R(rad)  # zero if modulus is square-free
end

Bother: it does not work for ZZModRing because that is not a ResidueRing. Must we duplicate the code?

@fingolfin
Copy link
Member Author

Regarding ZZModRing not being ResidueRing, see Nemocas/Nemo.jl#1819 (there are annoying technical issues with regards to rand which stalled this).

Regarding generating nilpotent elements and units for testing purposes: my idea was to have a pair of methods complementing test_elem, like so (untested code, just to demonstrate the idea):

function test_elem_nilpotent(R::Ring)
  return zero(R)
end

function test_elem_nilpotent(R::ResidueRing)
  error("TODO: factor modulus")
end

function test_elem_nilpotent(R::PolyRing)
  S = coefficient_ring(R)
  t = gen(R)
  return sum(test_elem_nilpotent(S)*t^i for i in 0:3)
end

function test_elem_nilpotent(R::MPolyRing)
  S = coefficient_ring(R)
  t = gen(R,1)
  # TODO: use all variables / generate random exponent vectors instead
  return sum(test_elem_nilpotent(S)*t^i for i in 0:3)
end

#
function test_elem_unit(R::Ring)
  if applicable(base_ring, R)
    S = base_ring(R)
    return R(test_elem_unit(S)) + test_elem_nilpotent(R)
  end
  return one(R) + test_elem_nilpotent(R)
end

BTW the function names are not great -- but I wanted something that riffs on test_elem. For better names I suggest we start by coming up with a better name for test_elem and then slowly migrate to that. But that's orthogonal to the core issue.

@fingolfin
Copy link
Member Author

Once more regarding ZZModRing versus ResidueRing: yes for now we'll have to duplicate the code, but we'll survive this for one 5-line function :-). Maybe add one more line:

# TODO: get rid of this once ZZModRing derives from ResidueRing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants