Skip to content

Commit e95013a

Browse files
committed
Add auto-reduction example to buchberger_naive. Reflow to 88 chars
1 parent 0907131 commit e95013a

File tree

1 file changed

+58
-28
lines changed

1 file changed

+58
-28
lines changed

src/flint/types/fmpz_mpoly.pyx

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -934,16 +934,15 @@ cdef class fmpz_mpoly(flint_mpoly):
934934

935935
def spoly(self, g):
936936
"""
937-
Compute the S-polynomial of `self` and `g`, scaled to an integer polynomial by computing the LCM of the
938-
leading coefficients.
937+
Compute the S-polynomial of `self` and `g`, scaled to an integer polynomial
938+
by computing the LCM of the leading coefficients.
939939
940940
>>> from flint import Ordering
941941
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
942942
>>> f = ctx.from_dict({(2, 0): 1, (0, 1): -1})
943943
>>> g = ctx.from_dict({(3, 0): 1, (1, 0): -1})
944944
>>> f.spoly(g)
945945
-x*y + x
946-
947946
"""
948947
cdef fmpz_mpoly res = create_fmpz_mpoly(self.ctx)
949948

@@ -956,8 +955,8 @@ cdef class fmpz_mpoly(flint_mpoly):
956955

957956
def reduction_primitive_part(self, vec):
958957
"""
959-
Compute the the primitive part of the reduction (remainder of multivariate quasi-division with remainder)
960-
with respect to the polynomials `vec`.
958+
Compute the the primitive part of the reduction (remainder of multivariate
959+
quasi-division with remainder) with respect to the polynomials `vec`.
961960
962961
>>> from flint import Ordering
963962
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
@@ -970,7 +969,6 @@ cdef class fmpz_mpoly(flint_mpoly):
970969
fmpz_mpoly_vec([x^2 + y^2 + 1, x*y - 2], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y')))
971970
>>> f.reduction_primitive_part(vec)
972971
x - y^3
973-
974972
"""
975973
cdef fmpz_mpoly res = create_fmpz_mpoly(self.ctx)
976974
if not typecheck(vec, fmpz_mpoly_vec):
@@ -986,7 +984,9 @@ cdef class fmpz_mpoly_vec:
986984
A class representing a vector of fmpz_mpolys.
987985
"""
988986

989-
def __cinit__(self, iterable_or_len, fmpz_mpoly_ctx ctx, bint double_indirect = False):
987+
def __cinit__(
988+
self, iterable_or_len, fmpz_mpoly_ctx ctx, bint double_indirect = False
989+
):
990990
if isinstance(iterable_or_len, int):
991991
length = iterable_or_len
992992
else:
@@ -996,7 +996,9 @@ cdef class fmpz_mpoly_vec:
996996
fmpz_mpoly_vec_init(self.val, length, self.ctx.val)
997997

998998
if double_indirect:
999-
self.double_indirect = <fmpz_mpoly_struct **> libc.stdlib.malloc(length * sizeof(fmpz_mpoly_struct *))
999+
self.double_indirect = <fmpz_mpoly_struct **> libc.stdlib.malloc(
1000+
length * sizeof(fmpz_mpoly_struct *)
1001+
)
10001002
if self.double_indirect is NULL:
10011003
raise MemoryError("malloc returned a null pointer") # pragma: no cover
10021004

@@ -1034,7 +1036,9 @@ cdef class fmpz_mpoly_vec:
10341036
elif (<fmpz_mpoly>y).ctx is not self.ctx:
10351037
raise IncompatibleContextError(f"{(<fmpz_mpoly>y).ctx} is not {self.ctx}")
10361038

1037-
fmpz_mpoly_set(fmpz_mpoly_vec_entry(self.val, x), (<fmpz_mpoly>y).val, self.ctx.val)
1039+
fmpz_mpoly_set(
1040+
fmpz_mpoly_vec_entry(self.val, x), (<fmpz_mpoly>y).val, self.ctx.val
1041+
)
10381042

10391043
def __len__(self):
10401044
return self.val.length
@@ -1054,7 +1058,10 @@ cdef class fmpz_mpoly_vec:
10541058
if not (op == Py_EQ or op == Py_NE):
10551059
return NotImplemented
10561060
elif typecheck(other, fmpz_mpoly_vec):
1057-
if (<fmpz_mpoly_vec>self).ctx is (<fmpz_mpoly_vec>other).ctx and len(self) == len(other):
1061+
if (
1062+
(<fmpz_mpoly_vec>self).ctx is (<fmpz_mpoly_vec>other).ctx
1063+
and len(self) == len(other)
1064+
):
10581065
return (op == Py_NE) ^ all(x == y for x, y in zip(self, other))
10591066
else:
10601067
return op == Py_NE
@@ -1066,7 +1073,8 @@ cdef class fmpz_mpoly_vec:
10661073

10671074
def is_groebner(self, other=None) -> bool:
10681075
"""
1069-
Check if self is a Gröbner basis. If `other` is not None then check if self is a Gröbner basis for `other`.
1076+
Check if self is a Gröbner basis. If `other` is not None then check if self
1077+
is a Gröbner basis for `other`.
10701078

10711079
>>> from flint import Ordering
10721080
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
@@ -1082,15 +1090,18 @@ cdef class fmpz_mpoly_vec:
10821090
True
10831091
>>> vec.is_groebner(fmpz_mpoly_vec([f, x**3], ctx))
10841092
False
1085-
10861093
"""
10871094
if other is None:
10881095
return <bint>fmpz_mpoly_vec_is_groebner(self.val, NULL, self.ctx.val)
10891096
elif typecheck(other, fmpz_mpoly_vec):
10901097
self.ctx.compatible_context_check((<fmpz_mpoly_vec>other).ctx)
1091-
return <bint>fmpz_mpoly_vec_is_groebner(self.val, (<fmpz_mpoly_vec>other).val, self.ctx.val)
1098+
return <bint>fmpz_mpoly_vec_is_groebner(
1099+
self.val, (<fmpz_mpoly_vec>other).val, self.ctx.val
1100+
)
10921101
else:
1093-
raise TypeError(f"expected either None or a fmpz_mpoly_vec, got {type(other)}")
1102+
raise TypeError(
1103+
f"expected either None or a fmpz_mpoly_vec, got {type(other)}"
1104+
)
10941105

10951106
def is_autoreduced(self) -> bool:
10961107
"""
@@ -1115,8 +1126,9 @@ cdef class fmpz_mpoly_vec:
11151126

11161127
def autoreduction(self, groebner=False) -> fmpz_mpoly_vec:
11171128
"""
1118-
Compute the autoreduction of `self`. If `groebner` is True and `self` is a Gröbner basis, compute the reduced
1119-
reduced Gröbner basis of `self`, throws an `RuntimeError` otherwise.
1129+
Compute the autoreduction of `self`. If `groebner` is True and `self` is a
1130+
Gröbner basis, compute the reduced reduced Gröbner basis of `self`, throws an
1131+
`RuntimeError` otherwise.
11201132

11211133
>>> from flint import Ordering
11221134
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
@@ -1132,14 +1144,16 @@ cdef class fmpz_mpoly_vec:
11321144
True
11331145
>>> vec2
11341146
fmpz_mpoly_vec([3*x^2 - y, x*y - x, y^2 - y], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y')))
1135-
11361147
"""
11371148

11381149
cdef fmpz_mpoly_vec h = fmpz_mpoly_vec(0, self.ctx)
11391150

11401151
if groebner:
11411152
if not self.is_groebner():
1142-
raise RuntimeError("reduced Gröbner basis construction requires that `self` is a Gröbner basis.")
1153+
raise RuntimeError(
1154+
"reduced Gröbner basis construction requires that `self` is a "
1155+
"Gröbner basis."
1156+
)
11431157
fmpz_mpoly_vec_autoreduction_groebner(h.val, self.val, self.ctx.val)
11441158
else:
11451159
fmpz_mpoly_vec_autoreduction(h.val, self.val, self.ctx.val)
@@ -1148,18 +1162,22 @@ cdef class fmpz_mpoly_vec:
11481162

11491163
def buchberger_naive(self, limits=None):
11501164
"""
1151-
Compute the Gröbner basis of `self` using a naive implementation of Buchberger’s algorithm.
1152-
1153-
Provide `limits` in the form of a tuple of `(ideal_len_limit, poly_len_limit, poly_bits_limit)` to halt
1154-
execution if the length of the ideal basis set exceeds `ideal_len_limit`, the length of any polynomial exceeds
1155-
`poly_len_limit`, or the size of the coefficients of any polynomial exceeds `poly_bits_limit`.
1165+
Compute the Gröbner basis of `self` using a naive implementation of
1166+
Buchberger’s algorithm.
11561167
1157-
If limits is provided return a tuple of `(result, success)`. If `success` is False then `result` is a valid
1158-
basis for `self`, but it may not be a Gröbner basis.
1168+
Provide `limits` in the form of a tuple of `(ideal_len_limit, poly_len_limit,
1169+
poly_bits_limit)` to halt execution if the length of the ideal basis set exceeds
1170+
`ideal_len_limit`, the length of any polynomial exceeds `poly_len_limit`, or the
1171+
size of the coefficients of any polynomial exceeds `poly_bits_limit`.
11591172
1160-
NOTE: This function is exposed only for convenience, it is a naive implementation and does not compute a reduced
1173+
If limits is provided return a tuple of `(result, success)`. If `success` is
1174+
False then `result` is a valid basis for `self`, but it may not be a Gröbner
11611175
basis.
11621176
1177+
NOTE: This function is exposed only for convenience, it is a naive
1178+
implementation and does not compute a reduced basis. To construct a reduced
1179+
basis use `autoreduce`.
1180+
11631181
>>> from flint import Ordering
11641182
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
11651183
>>> x, y = ctx.gens()
@@ -1168,10 +1186,15 @@ cdef class fmpz_mpoly_vec:
11681186
>>> vec = fmpz_mpoly_vec([f, g], ctx)
11691187
>>> vec.is_groebner()
11701188
False
1171-
>>> vec.buchberger_naive()
1189+
>>> vec2 = vec.buchberger_naive()
1190+
>>> vec2
11721191
fmpz_mpoly_vec([x^2 - y, x^3*y - x, x*y^2 - x, y^3 - y], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y')))
11731192
>>> vec.buchberger_naive(limits=(2, 2, 512))
11741193
(fmpz_mpoly_vec([x^2 - y, x^3*y - x], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y'))), False)
1194+
>>> vec2.is_autoreduced()
1195+
False
1196+
>>> vec2.autoreduction()
1197+
fmpz_mpoly_vec([x^2 - y, y^3 - y, x*y^2 - x], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y')))
11751198
"""
11761199

11771200
cdef:
@@ -1180,7 +1203,14 @@ cdef class fmpz_mpoly_vec:
11801203

11811204
if limits is not None:
11821205
ideal_len_limit, poly_len_limit, poly_bits_limit = limits
1183-
if fmpz_mpoly_buchberger_naive_with_limits(g.val, self.val, ideal_len_limit, poly_len_limit, poly_bits_limit, self.ctx.val):
1206+
if fmpz_mpoly_buchberger_naive_with_limits(
1207+
g.val,
1208+
self.val,
1209+
ideal_len_limit,
1210+
poly_len_limit,
1211+
poly_bits_limit,
1212+
self.ctx.val
1213+
):
11841214
return g, True
11851215
else:
11861216
return g, False

0 commit comments

Comments
 (0)