Difference polynomial rings

A difference polynomial ring over the commutative ring $R$ is an action polynomial ring $A$ whose action maps are (injective) endomorphisms of $A$. We also call them shift operators.

Construction

We provide the following methods to construct shift operators on the coefficient ring R. Using these is necessary, if one wants to use difference polynomial rings with nontrivial shift operators.

action_shift — Method
action_shift(R::Ring)

Construct the trivial shift, i.e. the identity map on the ring R.

Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source
action_shift — Method
action_shift(m::Map{D, D}) where {D <: Ring}

Wrap the map m into an ActionShift. This does not check whether m is actually a shift operator.

Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source

We provide the following methods to create difference polynomial rings where all shift operators are trivial, i.e. the identity map on the coefficient ring.

difference_polynomial_ring — Method
difference_polynomial_ring(R::Ring, action_indeterminates::Union{Vector{Symbol}, Int}, n_action_maps::Int) -> Tuple{DifferencePolyRing, Vector{DifferencePolyRingElem}}

Construct the difference polynomial ring over the coefficient ring R with the given action indeterminates that is equipped with n_action_maps-many trivial shift operators, i.e. they are the identity map on R.

  • If action_indeterminates is a vector of symbols, those names are used.
  • If it is an integer m, the symbols u1, …, um are generated automatically.

In both cases, the jet variables that are initially available are those with jet [0,…,0], one for each action indeterminate.

This method returns a tuple (dpr, gens) where dpr is the resulting difference polynomial ring and gens is the vector of initial jet variables.

This constructor also accepts all keyword arguments of set_ranking! to control the ranking.

Examples

julia> R, variablesR = difference_polynomial_ring(QQ, 3, 4)
(Difference polynomial ring in 3 action indeterminates over QQ, DifferencePolyRingElem{QQFieldElem}[u1[0,0,0,0], u2[0,0,0,0], u3[0,0,0,0]])

julia> R
Difference polynomial ring in 3 action indeterminates u1, u2, u3
with 4 commuting endomorphisms
  over rational field

julia> variablesR
3-element Vector{DifferencePolyRingElem{QQFieldElem}}:
 u1[0,0,0,0]
 u2[0,0,0,0]
 u3[0,0,0,0]

julia> S, variablesS = difference_polynomial_ring(QQ, [:a, :b, :c], 4)
(Difference polynomial ring in 3 action indeterminates over QQ, DifferencePolyRingElem{QQFieldElem}[a[0,0,0,0], b[0,0,0,0], c[0,0,0,0]])

julia> S
Difference polynomial ring in 3 action indeterminates a, b, c
with 4 commuting endomorphisms
  over rational field

julia> variablesS
3-element Vector{DifferencePolyRingElem{QQFieldElem}}:
 a[0,0,0,0]
 b[0,0,0,0]
 c[0,0,0,0]
Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source
difference_polynomial_ring — Method
difference_polynomial_ring(R::Ring, x::Symbol, n_action_maps::Int) -> Tuple{DifferencePolyRing, DifferencePolyRingElem}

This constructor behaves exactly like difference_polynomial_ring but only allows for one action indeterminate x instead of a vector of these. Consequently, this method returns the tuple (dpr, x[0,…,0]) where dpr is the resulting difference polynomial ring.

Examples

This constructor is preferred when one only wants to have one action indeterminate:

julia> R, x = difference_polynomial_ring(ZZ, :x, 2)
(Difference polynomial ring in 1 action indeterminates over ZZ, x[0,0])

julia> x
x[0,0]

If we instead construct this ring by passing the single action indeterminate as a vector, the variable x does not behave as intended:

julia> R, x = difference_polynomial_ring(ZZ, [:x], 2)
(Difference polynomial ring in 1 action indeterminates over ZZ, DifferencePolyRingElem{ZZRingElem}[x[0,0]])

julia> x
1-element Vector{DifferencePolyRingElem{ZZRingElem}}:
 x[0,0]
Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source

We provide the following constructors to create difference polynomial rings with arbitrary commuting shift operators. Note that commutativity is not actually checked and that ensuring it is left to the user.

difference_polynomial_ring — Method
difference_polynomial_ring(R::Ring, action_indeterminates::Union{Vector{Symbol}, Int}, action_maps::Vector{<:ActionShift}; kwargs...) -> Tuple{DifferencePolyRing, Vector{DifferencePolyRingElem}}

This constructor behaves exactly like and comes with the same features as difference_polynomial_ring but additionally allows the user to pass a custom vector of shift operators action_maps. In particular, this constructor allows for nontrivial shift operators.

Examples

julia> S, x = polynomial_ring(QQ, :x);

julia> nontrivial_shifts = action_shift.([hom(S, S, x + 1), hom(S, S, x + 2)])
2-element Vector{Oscar.NontrivialActionShift{QQPolyRing}}:
 Shift operator on S
 Shift operator on S

julia> dpr, (u, v) = difference_polynomial_ring(S, [:u, :v], nontrivial_shifts)
(Difference polynomial ring in 2 action indeterminates over S, DifferencePolyRingElem{QQPolyRingElem}[u[0,0], v[0,0]])
Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source
difference_polynomial_ring — Method
difference_polynomial_ring(R::Ring, action_indeterminate::Symbol, action_maps::Vector{<:ActionShift}; kwargs...) -> Tuple{DifferencePolyRing, DifferencePolyRingElem}

This constructor behaves exactly like difference_polynomial_ring in that only a single action indeterminate is passed as a symbol but additionally allows the user to pass a custom vector of shift operators action_maps. In particular, this constructor allows for nontrivial shift operators.

Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source

Applying shift operators

You can use the following methods to apply the shift operators of a difference polynomial ring to its elements:

apply_action — Method
apply_action(p::DifferencePolyRingElem, i::Int)

Apply the i-th shift operator to the difference polynomial p.

Examples

julia> dpr, (a,b,c) = difference_polynomial_ring(ZZ, [:a, :b, :c], 2); f = -2*a*b + 3*a*b^2;

julia> apply_action(3*a, 1)
3*a[1,0]

julia> apply_action(3*a, 2)
3*a[0,1]

julia> apply_action(f, 1)
(3*b[1,0]^2 - 2*b[1,0])*a[1,0]

julia> apply_action(f, 2)
(3*b[0,1]^2 - 2*b[0,1])*a[0,1]
Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source
apply_action — Method
apply_action(p::DifferencePolyRingElem, d::Vector{Int})

Successively apply the i-th shift operator d[i]-times to the difference polynomial p, where $i = 1, \ldots, \mathrm{length}(d)$.

Experimental

This function is part of the experimental code in Oscar. Please read here for more details.

source
Warning

After calling one of these methods, all jet variables that arise within their computation will be tracked afterwards.