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

ABC for BooleanPolynomialRing #35240

Merged
merged 2 commits into from
Apr 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/sage/rings/polynomial/multi_polynomial_ring_base.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
cdef public dict _magma_cache

cdef _coerce_c_impl(self, x)


cdef class BooleanPolynomialRing_base(MPolynomialRing_base):
pass
22 changes: 22 additions & 0 deletions src/sage/rings/polynomial/multi_polynomial_ring_base.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,28 @@ cdef class MPolynomialRing_base(sage.rings.ring.CommutativeRing):
return DifferentialWeylAlgebra(self)


cdef class BooleanPolynomialRing_base(MPolynomialRing_base):
r"""
Abstract base class for :class:`~sage.rings.polynomial.pbori.pbori.BooleanPolynomialRing`.

This class is defined for the purpose of ``isinstance`` tests. It should not be
instantiated.

EXAMPLES::

sage: from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base
sage: R.<x, y, z> = BooleanPolynomialRing()
sage: isinstance(R, BooleanPolynomialRing_base)
True

By design, there is only one direct implementation subclass::

sage: len(BooleanPolynomialRing_base.__subclasses__()) <= 1
True
"""
pass


####################
# Leave *all* old versions!

Expand Down
22 changes: 14 additions & 8 deletions src/sage/rings/polynomial/multi_polynomial_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -1257,14 +1257,16 @@ def eliminate_linear_variables(self, maxlength=Infinity, skip=None, return_reduc

This is called "massaging" in [BCJ2007]_.
"""
from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing,gauss_on_polys
from sage.rings.polynomial.pbori.ll import eliminate,ll_encode,ll_red_nf_redsb
from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base

R = self.ring()

if not isinstance(R, BooleanPolynomialRing):
if not isinstance(R, BooleanPolynomialRing_base):
raise NotImplementedError("Only BooleanPolynomialRing's are supported.")

from sage.rings.polynomial.pbori.pbori import gauss_on_polys
from sage.rings.polynomial.pbori.ll import eliminate, ll_encode, ll_red_nf_redsb

F = self
reductors = []

Expand Down Expand Up @@ -1340,10 +1342,11 @@ def _groebner_strategy(self):
sage: F._groebner_strategy()
<sage.rings.polynomial.pbori.pbori.GroebnerStrategy object at 0x...>
"""
from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing
from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base

R = self.ring()

if not isinstance(R, BooleanPolynomialRing):
if not isinstance(R, BooleanPolynomialRing_base):
from sage.libs.singular.groebner_strategy import GroebnerStrategy
return GroebnerStrategy(self.ideal())
else:
Expand Down Expand Up @@ -1452,7 +1455,6 @@ def solve(self, algorithm='polybori', n=1, eliminate_linear_variables=True, ver
[]

"""
from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing
from sage.modules.free_module import VectorSpace

S = self
Expand All @@ -1462,6 +1464,8 @@ def solve(self, algorithm='polybori', n=1, eliminate_linear_variables=True, ver
if eliminate_linear_variables:
T, reductors = self.eliminate_linear_variables(return_reductors=True)
if T.variables() != ():
from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing

R_solving = BooleanPolynomialRing( T.nvariables(), [str(_) for _ in list(T.variables())] )
S = PolynomialSequence( R_solving, [ R_solving(f) for f in T] )

Expand Down Expand Up @@ -1543,11 +1547,13 @@ def reduced(self):
....: assert g[i].lt() not in t.divisors()
"""

from sage.rings.polynomial.pbori.pbori import BooleanPolynomialRing
from sage.rings.polynomial.multi_polynomial_ring_base import BooleanPolynomialRing_base

R = self.ring()

if isinstance(R, BooleanPolynomialRing):
if isinstance(R, BooleanPolynomialRing_base):
from sage.rings.polynomial.pbori.interred import interred as inter_red

l = [p for p in self if not p==0]
l = sorted(inter_red(l, completely=True), reverse=True)
return PolynomialSequence(l, R, immutable=True)
Expand Down
5 changes: 2 additions & 3 deletions src/sage/rings/polynomial/pbori/pbori.pxd
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from libcpp.memory cimport unique_ptr, shared_ptr, make_shared

from sage.rings.polynomial.multi_polynomial_ring_base cimport \
MPolynomialRing_base
from sage.rings.polynomial.multi_polynomial_ring_base cimport MPolynomialRing_base, BooleanPolynomialRing_base
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it still necessary to cimport MPolynomialRing_base? It is the only instance in this file. Do any file importing from sage.rings.polynomial.pbori.pbori expect it? If so, could they import it directly from sage.rings.polynomial.multi_polynomial_ring_base instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in pbori.pyx for an isinstance check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can of course move the cimport to the pyx file if you think that's better

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think it is particularly better. A cython expert would have to chime in on that. So, let's leave it as is.

from sage.rings.polynomial.multi_polynomial cimport MPolynomial
from sage.structure.element cimport MonoidElement

from sage.libs.polybori.decl cimport *


cdef class BooleanPolynomialRing(MPolynomialRing_base):
cdef class BooleanPolynomialRing(BooleanPolynomialRing_base):
cdef PBRing _pbring
cdef Py_ssize_t* pbind
cdef public _monom_monoid
Expand Down
6 changes: 3 additions & 3 deletions src/sage/rings/polynomial/pbori/pbori.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ block_dp_asc = int(pbblock_dp_asc)
rings = sage.misc.weak_dict.WeakValueDictionary()


cdef class BooleanPolynomialRing(MPolynomialRing_base):
cdef class BooleanPolynomialRing(BooleanPolynomialRing_base):
"""
Construct a boolean polynomial ring with the following parameters:

Expand Down Expand Up @@ -410,7 +410,7 @@ cdef class BooleanPolynomialRing(MPolynomialRing_base):
pbnames = tuple(names)
names = [name.replace('(', '').replace(')', '') for name in pbnames]

MPolynomialRing_base.__init__(self, GF((2,1)), n, names, order)
BooleanPolynomialRing_base.__init__(self, GF((2,1)), n, names, order)

counter = 0
for i in range(len(order.blocks()) - 1):
Expand Down Expand Up @@ -7645,7 +7645,7 @@ cdef BooleanPolynomialRing BooleanPolynomialRing_from_PBRing(PBRing _ring):

self._pbring = _ring

MPolynomialRing_base.__init__(self, GF(2), n, names, T)
BooleanPolynomialRing_base.__init__(self, GF(2), n, names, T)

self._zero_element = new_BP(self)
(<BooleanPolynomial>self._zero_element)._pbpoly = PBBoolePolynomial(0, self._pbring)
Expand Down