Skip to content

Commit 97cdd97

Browse files
author
Jake Moss
committed
Add tests, add note to buchberger_naive, add equality comparison
1 parent f379dc0 commit 97cdd97

File tree

3 files changed

+91
-10
lines changed

3 files changed

+91
-10
lines changed

src/flint/test/test_all.py

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,8 +3208,11 @@ def _all_mpoly_vecs():
32083208

32093209
def test_fmpz_mpoly_vec():
32103210
for context, mpoly_vec in _all_mpoly_vecs():
3211+
has_groebner_functions = mpoly_vec is flint.fmpz_mpoly_vec
3212+
32113213
ctx = context.get_context(nvars=2)
32123214
ctx1 = context.get_context(nvars=4)
3215+
x, y = ctx.gens()
32133216

32143217
vec = mpoly_vec(3, ctx)
32153218

@@ -3225,14 +3228,68 @@ def test_fmpz_mpoly_vec():
32253228
assert raises(lambda: vec[None], TypeError)
32263229
assert raises(lambda: vec[-1], IndexError)
32273230

3228-
vec[1] = ctx.from_dict({(1, 1): 1})
3229-
assert vec.to_tuple() == mpoly_vec([ctx.from_dict({}), ctx.from_dict({(1, 1): 1}), ctx.from_dict({})], ctx).to_tuple()
3231+
vec[1] = x * y
3232+
assert vec == mpoly_vec([ctx.from_dict({}), x * y, ctx.from_dict({})], ctx)
3233+
assert vec != mpoly_vec([x, x * y, ctx.from_dict({})], ctx)
3234+
assert vec != mpoly_vec([ctx.from_dict({})], ctx)
3235+
assert vec != mpoly_vec([ctx1.from_dict({})], ctx1)
3236+
assert vec.to_tuple() == mpoly_vec([ctx.from_dict({}), x * y, ctx.from_dict({})], ctx).to_tuple()
32303237
assert raises(lambda: vec.__setitem__(None, 0), TypeError)
32313238
assert raises(lambda: vec.__setitem__(-1, 0), IndexError)
32323239
assert raises(lambda: vec.__setitem__(0, 0), TypeError)
32333240
assert raises(lambda: vec.__setitem__(0, ctx1.from_dict({})), IncompatibleContextError)
32343241

32353242

3243+
if has_groebner_functions:
3244+
ctx = context.get_context(3, flint.Ordering.lex, nametup=('x', 'y', 'z'))
3245+
3246+
# Examples here cannibalised from
3247+
# https://en.wikipedia.org/wiki/Gr%C3%B6bner_basis#Example_and_counterexample
3248+
x, y, z = ctx.gens()
3249+
f = x**2 - y
3250+
f2 = 3 * x**2 - y
3251+
g = x**3 - x
3252+
g2 = x**3 * y - x
3253+
k = x * y - x
3254+
k2 = 3 * x * y - 3 * x
3255+
h = y**2 - y
3256+
3257+
vec = mpoly_vec([f, k, h], ctx)
3258+
assert vec.is_groebner()
3259+
assert vec.is_groebner(mpoly_vec([f, g], ctx))
3260+
assert not vec.is_groebner(mpoly_vec([f, x**3], ctx))
3261+
3262+
assert mpoly_vec([f2, k, h], ctx).is_autoreduced()
3263+
assert not mpoly_vec([f2, k2, h], ctx).is_autoreduced()
3264+
3265+
vec = mpoly_vec([f2, k2, h], ctx)
3266+
vec2 = vec.autoreduction()
3267+
assert not vec.is_autoreduced()
3268+
assert vec2.is_autoreduced()
3269+
assert vec2 == mpoly_vec([3 * x**2 - y, x * y - x, y**2 - y], ctx)
3270+
3271+
vec = mpoly_vec([f, g2], ctx)
3272+
assert not vec.is_groebner()
3273+
assert vec.buchberger_naive() == mpoly_vec([x**2 - y, x**3 * y - x, x * y**2 - x, y**3 - y], ctx)
3274+
assert vec.buchberger_naive(limits=(2, 2, 512)) == (mpoly_vec([x**2 - y, x**3 * y - x], ctx), False)
3275+
3276+
unreduced_basis = mpoly_vec([x**2 - 2, y**2 - 3, z - x - y], ctx).buchberger_naive()
3277+
assert list(unreduced_basis) == [
3278+
x**2 - 2,
3279+
y**2 - 3,
3280+
x + y - z,
3281+
2*y*z - z**2 - 1,
3282+
2*y + z**3 - 11*z,
3283+
z**4 - 10*z**2 + 1
3284+
]
3285+
3286+
assert list(unreduced_basis.autoreduction()) == [
3287+
z**4 - 10 * z**2 + 1,
3288+
2*y + z**3 - 11 * z,
3289+
2 * x - z**3 + 9 * z
3290+
]
3291+
3292+
32363293
def _all_matrices():
32373294
"""Return a list of matrix types and scalar types."""
32383295
R163 = flint.fmpz_mod_ctx(163)

src/flint/types/fmpq_mpoly.pyx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,5 +1112,16 @@ cdef class fmpq_mpoly_vec:
11121112
def __repr__(self):
11131113
return f"fmpq_mpoly_vec({self}, ctx={self.ctx})"
11141114

1115+
def __richcmp__(self, other, int op):
1116+
if not (op == Py_EQ or op == Py_NE):
1117+
return NotImplemented
1118+
elif typecheck(other, fmpq_mpoly_vec):
1119+
if (<fmpq_mpoly_vec>self).ctx is (<fmpq_mpoly_vec>other).ctx and len(self) == len(other):
1120+
return (op == Py_NE) ^ all(x == y for x, y in zip(self, other))
1121+
else:
1122+
return op == Py_NE
1123+
else:
1124+
return NotImplemented
1125+
11151126
def to_tuple(self):
11161127
return tuple(self[i] for i in range(self.length))

src/flint/types/fmpz_mpoly.pyx

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,17 @@ cdef class fmpz_mpoly_vec:
11741174
def __repr__(self):
11751175
return f"fmpz_mpoly_vec({self}, ctx={self.ctx})"
11761176

1177+
def __richcmp__(self, other, int op):
1178+
if not (op == Py_EQ or op == Py_NE):
1179+
return NotImplemented
1180+
elif typecheck(other, fmpz_mpoly_vec):
1181+
if (<fmpz_mpoly_vec>self).ctx is (<fmpz_mpoly_vec>other).ctx and len(self) == len(other):
1182+
return (op == Py_NE) ^ all(x == y for x, y in zip(self, other))
1183+
else:
1184+
return op == Py_NE
1185+
else:
1186+
return NotImplemented
1187+
11771188
def to_tuple(self):
11781189
return tuple(self[i] for i in range(self.val.length))
11791190

@@ -1193,7 +1204,7 @@ cdef class fmpz_mpoly_vec:
11931204
True
11941205
>>> vec.is_groebner(fmpz_mpoly_vec([f, g], ctx))
11951206
True
1196-
>>> vec.is_groebner(fmpz_mpoly_vec([f, ctx.from_dict({(3, 0): 1})], ctx))
1207+
>>> vec.is_groebner(fmpz_mpoly_vec([f, x**3], ctx))
11971208
False
11981209

11991210
"""
@@ -1212,14 +1223,14 @@ cdef class fmpz_mpoly_vec:
12121223
>>> from flint import Ordering
12131224
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
12141225
>>> x, y = ctx.gens()
1215-
>>> f = 3*x**2 - y
1216-
>>> k1 = x*y - x
1226+
>>> f2 = 3*x**2 - y
1227+
>>> k = x*y - x
12171228
>>> k2 = 3*x*y - 3*x
12181229
>>> h = y**2 - y
1219-
>>> vec = fmpz_mpoly_vec([f, k1, h], ctx)
1230+
>>> vec = fmpz_mpoly_vec([f2, k, h], ctx)
12201231
>>> vec.is_autoreduced()
12211232
True
1222-
>>> vec = fmpz_mpoly_vec([f, k2, h], ctx)
1233+
>>> vec = fmpz_mpoly_vec([f2, k2, h], ctx)
12231234
>>> vec.is_autoreduced()
12241235
False
12251236

@@ -1234,10 +1245,10 @@ cdef class fmpz_mpoly_vec:
12341245
>>> from flint import Ordering
12351246
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
12361247
>>> x, y = ctx.gens()
1237-
>>> f = 3*x**2 - y
1248+
>>> f2 = 3*x**2 - y
12381249
>>> k2 = 3*x*y - 3*x
12391250
>>> h = y**2 - y
1240-
>>> vec = fmpz_mpoly_vec([f, k2, h], ctx)
1251+
>>> vec = fmpz_mpoly_vec([f2, k2, h], ctx)
12411252
>>> vec.is_autoreduced()
12421253
False
12431254
>>> vec2 = vec.autoreduction()
@@ -1270,6 +1281,9 @@ cdef class fmpz_mpoly_vec:
12701281
If limits is provided return a tuple of `(result, success)`. If `success` is False then `result` is a valid
12711282
basis for `self`, but it may not be a Gröbner basis.
12721283
1284+
NOTE: This function is exposed only for convenience, it is a naive implementation and does not compute a reduced
1285+
basis.
1286+
12731287
>>> from flint import Ordering
12741288
>>> ctx = fmpz_mpoly_ctx.get_context(2, Ordering.lex, nametup=('x', 'y'))
12751289
>>> x, y = ctx.gens()
@@ -1282,7 +1296,6 @@ cdef class fmpz_mpoly_vec:
12821296
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')))
12831297
>>> vec.buchberger_naive(limits=(2, 2, 512))
12841298
(fmpz_mpoly_vec([x^2 - y, x^3*y - x], ctx=fmpz_mpoly_ctx(2, '<Ordering.lex: 0>', ('x', 'y'))), False)
1285-
12861299
"""
12871300

12881301
cdef:

0 commit comments

Comments
 (0)