`in` for function fields produces false negatives
Consider the following computation:
gap> R := FunctionField(Integers, 2);
FunctionField(...,[ x_1, x_2 ])
gap> indet := IndeterminatesOfFunctionField(R);; x1 := indet[1];; x2 := indet[2];;
gap> left := 2*x1;; right := 1/(x1*x2);;
gap> left*right;
1/(1/2*x_2)
The representation of left*right with the coefficient 1/2 (which does not lie in the specified coefficient ring) is undesirable, but mathematically correct. However, this representation leads to mathematically incorrect behaviour: GAP claims that left*right does not lie in R even though left and right do.
gap> left in R; right in R; left*right in R;
true
true
false
I looked into what is happening. The multiplication left*right calls
https://github.com/gap-system/gap/blob/8c0b08cd9b029c711b742c36626915b3c56a3a14/lib/ratfun.gi#L1134-L1136
which produces the undesirable coefficient 1/2 in our example.
gap> fam := FamilyObj(left);;
gap> t:=TryGcdCancelExtRepPolynomials(fam,ExtRepPolynomialRatFun(left),ExtRepDenominatorRatFun(right));
[ [ [ ], 1 ], [ [ 2, 1 ], 1/2 ], [ [ 1, 1 ], 2 ] ]
The problem is essentially that TryGcdCancelExtRepPolynomials tries to use certain heuristics to cancel common factors, which may lead to coefficients outside the coefficient ring. Namely:
https://github.com/gap-system/gap/blob/8c0b08cd9b029c711b742c36626915b3c56a3a14/lib/ratfun1.gi#L1227-L1240
The coefficient 1/2 arises in line 1236 (example continued):
gap> num := ExtRepPolynomialRatFun(left);
[ [ 1, 1 ], 2 ]
gap> den := ExtRepDenominatorRatFun(right);
[ [ 1, 1, 2, 1 ], 1 ]
gap> q := QuotientPolynomialsExtRep(fam, den, num);
[ [ 2, 1 ], 1/2 ]
Clearly QuotientPolynomialsExtRep works as it should, because x_1*x_2/(2*x_2) = (1/2)*x_2.
I have no suggestion what should be done about this. Clearly a ring in GAP should be closed under multiplication, so it is problematic that left*right in R is false. However, I think it is complicated to fix without destroying the useful heuristics.
@hulpke is listed as one of the co-authors in the file.
Polynomials know about the Characteristics, not about a coefficient ring that is strictly smaller than its quotient field. That is, they behave in your example as if you had defined
R:=FunctionField(Rationals,2);
This cannot be changed easily, and such a change might cause subsequent problems with implicit embeddings of polynomial rings over a hierarchy of coefficient rings.
The inconsistency problem you observe is only with the in R test for the product. Since left*right=2/x_2 it does lie in R, and thus it is not suffiicent to just look at the coefficients of numerator and denominator separately.
Polynomials know about the Characteristics, not about a coefficient ring that is strictly smaller than its quotient field. That is, they behave in your example as if you had defined
R:=FunctionField(Rationals,2);This cannot be changed easily, and such a change might cause subsequent problems with implicit embeddings of polynomial rings over a hierarchy of coefficient rings.
The inconsistency problem you observe is only with the
in Rtest for the product. Sinceleft*right=2/x_2it does lie inR, and thus it is not suffiicent to just look at the coefficients of numerator and denominator separately.
Agreed.
I think it is true that if $R$ is an integral domain with field of fractions $S$, then the natural embedding of $R(x_1,...,x_n)$ into $S(x_1,...,x_n)$ is actually surjective because any $f \in S[x_1,...,x_n]$ can be written as $(1/r) *g$ for some $r \in R, g \in R[x_1,...,x_n]$. Hence the in test for $R(x_1,...,x_n)$ should check whether all coefficients lie in $S$, and then the problem should be solved.
However... does GAP not support fields of fractions for arbitrary integral domains? I cannot find them in the documentation.