From 483e78f7031a9cc6df1b52427946da205ece3995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 8 May 2024 20:27:12 +0200 Subject: [PATCH 1/2] some polishing for pbori (ruff and pep8 mostly) --- src/sage/rings/polynomial/pbori/blocks.py | 59 +++--- src/sage/rings/polynomial/pbori/cnf.py | 8 +- src/sage/rings/polynomial/pbori/gbcore.py | 171 +++++++++--------- src/sage/rings/polynomial/pbori/gbrefs.py | 3 +- .../rings/polynomial/pbori/interpolate.py | 2 +- src/sage/rings/polynomial/pbori/interred.py | 10 +- src/sage/rings/polynomial/pbori/ll.py | 44 ++--- src/sage/rings/polynomial/pbori/nf.py | 112 ++++++------ src/sage/rings/polynomial/pbori/parallel.py | 1 - src/sage/rings/polynomial/pbori/randompoly.py | 2 +- src/sage/rings/polynomial/pbori/rank.py | 2 +- .../rings/polynomial/pbori/specialsets.py | 6 +- src/sage/rings/polynomial/pbori/statistics.py | 2 +- 13 files changed, 211 insertions(+), 211 deletions(-) diff --git a/src/sage/rings/polynomial/pbori/blocks.py b/src/sage/rings/polynomial/pbori/blocks.py index ba6b9c7b493..8280fd7db81 100644 --- a/src/sage/rings/polynomial/pbori/blocks.py +++ b/src/sage/rings/polynomial/pbori/blocks.py @@ -5,7 +5,7 @@ from .PyPolyBoRi import (Ring, Polynomial, VariableFactory, Variable) -class Block(): +class Block: r""" The block class represents a block of variables (start_index,...,start_index+size-1), it is the preferred @@ -37,12 +37,12 @@ def register(self, start, context): ring = ring_context['r'] var_func = VariableBlock(self.size, self.start_index, start, self. - reverse, ring) + reverse, ring) var_func.__name__ = self.var_name context[self.var_name] = var_func -class AlternatingBlock(): +class AlternatingBlock: r""" The Alternating Block class is used for doing tricky variable schemes,where base names vary, e.g. @@ -74,7 +74,7 @@ def __getitem__(self, i): def register(self, start, context): def gen_var_func(var_pos): - class var_factory(): + class var_factory: def __init__(self, ring, index2pos, size): self.ring = ring self.index2pos = index2pos @@ -82,7 +82,7 @@ def __init__(self, ring, index2pos, size): def __call__(self, idx): return self.ring.variable(self.index2pos[idx] * self.size + - var_pos + start) + var_pos + start) ring_context = context while isinstance(ring_context, PrefixedDictProxy): ring_context = ring_context.wrapped @@ -107,7 +107,8 @@ class AdderBlock(AlternatingBlock): def __init__(self, adder_bits, sums="s", carries="c", input1="a", input2="b", start_index=0): AlternatingBlock.__init__(self, (sums, carries, input1, input2), - adder_bits, start_index=start_index, reverse=True) + adder_bits, start_index=start_index, + reverse=True) self.input1 = input1 self.input2 = input2 self.sums = sums @@ -124,13 +125,14 @@ def register(self, start, context): a = shift(a, self.start_index) b = shift(b, self.start_index) carries = [Polynomial(a(0).ring().zero())] + last = carries[0] for i in range(self.adder_bits): - c = 1 + (1 + a(i) * b(i)) * (1 + carries[-1] * a(i)) * (1 + - carries[-1] * b(i)) + c = 1 + (1 + a(i) * b(i)) * (1 + last * a(i)) * (1 + last * b(i)) carries.append(c) + last = c - self.add_results = [a(i) + b(i) + carries[i] for i in range(self. - adder_bits)] + self.add_results = [a(i) + b(i) + carries[i] + for i in range(self.adder_bits)] self.carries_polys = carries[1:] # def s(i): @@ -146,7 +148,7 @@ def implement(self, equations): equations.append(self.c(i) + self.carries_polys[i]) -class HigherOrderBlock(): +class HigherOrderBlock: r""" HigherOrderBlocks are multidimensional blocks of variables. @@ -192,14 +194,14 @@ def var_func(*indices): context[self.var_name] = var_func -class InOutBlock(): +class InOutBlock: def __init__(self, out_size, in_size, output="out", input="in", in_start_index=0, out_start_index=0, out_reverse=False, in_reverse=False): self.output = Block(var_name=output, start_index=out_start_index, - size=out_size, reverse=out_reverse) + size=out_size, reverse=out_reverse) self.input = Block(var_name=input, start_index=in_start_index, - size=in_size, reverse=in_reverse) + size=in_size, reverse=in_reverse) self.out_start_index = out_start_index self.in_start_index = in_start_index @@ -219,11 +221,11 @@ def register(self, start, context): self.output.register(start, context) self.input.register(start + len(self.output), context) self.out_vars = shift(context[self.output.var_name], self. - out_start_index) + out_start_index) self.in_vars = shift(context[self.input.var_name], self.in_start_index) -class MultiBlock(): +class MultiBlock: def __init__(self, sizes=None, var_names=["v"], start_indices=[], reverses=None): if reverses is None: @@ -236,8 +238,9 @@ def __init__(self, sizes=None, var_names=["v"], sizes += [1] * (len(var_names) - len(sizes)) self.blocks = [Block(var_name=var_names[idx], size=sizes[idx], - start_index=self.start_indices[idx], reverse=reverses[idx]) for - idx in range(len(var_names))] + start_index=self.start_indices[idx], + reverse=reverses[idx]) + for idx in range(len(var_names))] def __iter__(self): return chain(*self.blocks) @@ -247,7 +250,7 @@ def __getitem__(self, i): # sum([bl.names for bl in self.blocks])[i] def __len__(self): - return sum((len(bl) for bl in self.blocks)) + return sum(len(bl) for bl in self.blocks) def register(self, start, context): offset = 0 @@ -255,11 +258,12 @@ def register(self, start, context): bl.register(start + offset, context) offset += len(bl) - self.vars = [shift(context[self.blocks[idx].var_name], self. - start_indices[idx]) for idx in range(len(self.blocks))] + self.vars = [shift(context[self.blocks[idx].var_name], + self.start_indices[idx]) + for idx in range(len(self.blocks))] -class PrefixedDictProxy(): +class PrefixedDictProxy: """docstring for PrefixedDictProxy""" def __init__(self, wrapped, prefix): @@ -278,7 +282,7 @@ def __setitem__(self, k, v): self.wrapped[self.prefix + k] = v -class MacroBlock(): +class MacroBlock: def __init__(self, prefix): self.prefix = prefix @@ -299,7 +303,7 @@ def __getitem__(self, i): return self.prefix + "_" + next(islice(chain(*self.blocks), i, i + 1)) def __len__(self): - return sum((len(bl) for bl in self.blocks)) + return sum(len(bl) for bl in self.blocks) def resolve(self, localname): return self.prefix + "_" + localname @@ -324,7 +328,7 @@ def implement(self, equations): equations += self.connections -class IfThen(): +class IfThen: def __init__(self, ifpart, thenpart, supposed_to_be_valid=True): self.ifpart = [Polynomial(p) for p in ifpart] self.thenpart = [Polynomial(p) for p in thenpart] @@ -369,10 +373,7 @@ def canonicalize(blocks): n = 0 for b in blocks: - if isinstance(b, str): - n = n + 1 - else: - n = n + len(b) + n = n + 1 if isinstance(b, str) else n + len(b) r = Ring(n, names=canonicalize(blocks)) diff --git a/src/sage/rings/polynomial/pbori/cnf.py b/src/sage/rings/polynomial/pbori/cnf.py index 266a6f0f8a8..61d85866013 100644 --- a/src/sage/rings/polynomial/pbori/cnf.py +++ b/src/sage/rings/polynomial/pbori/cnf.py @@ -4,7 +4,7 @@ from .statistics import used_vars_set -class CNFEncoder(): +class CNFEncoder: def __init__(self, r, random_seed=16): self.random_generator = Random(random_seed) self.one_set = r.one().set() @@ -174,7 +174,7 @@ def dimacs_cnf(self, polynomial_system): res = ["c cnf generated by PolyBoRi"] r = polynomial_system[0].ring() n_variables = r.n_variables() - res.append("p cnf %s %s" % (n_variables, len(clauses_list))) + res.append(f"p cnf {n_variables} {len(clauses_list)}") res.extend(clauses_list) return "\n".join(res) @@ -213,7 +213,7 @@ def dimacs_encode_polynomial(self, p): indices.append(0) res = ["x" + " ".join(str(v) for v in indices)] self.group_counter = self.group_counter + 1 - group_comment = "\nc g %s %s" % (self.group_counter, str(p)[:30]) + group_comment = f"\nc g {self.group_counter} {str(p)[:30]}" return [c + group_comment for c in res] def dimacs_cnf(self, polynomial_system): @@ -234,6 +234,6 @@ def dimacs_cnf(self, polynomial_system): """ uv = list(used_vars_set(polynomial_system).variables()) res = super().dimacs_cnf(polynomial_system) - res += "\n" + "\n".join("c v %s %s" % (self.to_dimacs_index(v), v) + res += "\n" + "\n".join(f"c v {self.to_dimacs_index(v)} {v}" for v in uv) return res diff --git a/src/sage/rings/polynomial/pbori/gbcore.py b/src/sage/rings/polynomial/pbori/gbcore.py index 3eb6a73ff25..9c40c94c06c 100644 --- a/src/sage/rings/polynomial/pbori/gbcore.py +++ b/src/sage/rings/polynomial/pbori/gbcore.py @@ -12,6 +12,7 @@ from .easy_polynomials import easy_linear_polynomials from .interpolate import lex_groebner_basis_for_polynomial_via_variety from .fglm import _fglm +import contextlib def get_options_from_function(f): @@ -32,7 +33,7 @@ def filter_oldstyle_options(**options): def filter_newstyle_options(func, **options): allowed = get_options_from_function(func).keys() filtered = {} - for key in options.keys(): + for key in options: for prefix in ['', 'use_', 'opt_', 'opt_allow_']: if prefix + key in allowed: filtered[prefix + key] = options[key] @@ -80,7 +81,7 @@ def change_order_heuristic(d): if not I: return d switch_table = {OrderCode.lp: OrderCode.dp_asc, OrderCode.dlex: OrderCode. - dp_asc} + dp_asc} if "other_ordering_first" not in d: # TODO after ll situation might look much different, so heuristic is on # wrong place @@ -152,14 +153,12 @@ def trivial_heuristic(d): return d -class HeuristicalFunction(): +class HeuristicalFunction: def __call__(self, *args, **kwds): complete_dict = copy(kwds) heuristic = True - try: + with contextlib.suppress(KeyError): heuristic = complete_dict["heuristic"] - except KeyError: - pass for (k, v) in zip(self.argnames, args): complete_dict[k] = v if heuristic: @@ -172,7 +171,7 @@ def __init__(self, f, heuristic_function): self.options = f.options else: self.options = dict(zip(self.argnames[-len(self.defaults):], self. - defaults)) + defaults)) self.heuristicFunction = heuristic_function self.f = f self.__doc__ = f.__doc__ @@ -188,42 +187,40 @@ def make_wrapper(f): def clean_polys_pre(I): wrap = (Polynomial(p) for p in I) - return (list(set(p for p in wrap if not p.is_zero())), None) + return (list({p for p in wrap if not p.is_zero()}), None) def gb_with_pre_post_option(option, pre=None, - post=None, if_not_option=tuple(), + post=None, if_not_option=(), default=False): def make_wrapper(f): def wrapper(I, **kwds): prot = kwds.get("prot", False) for o in if_not_option: if (o in kwds and kwds[o]) or (o not in kwds and - groebner_basis.options[o]): + groebner_basis.options[o]): option_set = False if "option_set" not in locals(): option_set = kwds.get(option, default) - kwds = dict(((o, kwds[o]) for o in kwds if o != option)) + kwds = {o: kwds[o] for o in kwds if o != option} state = None - if option_set: - if pre: - pre_args = getargspec(pre)[0] - if prot: - print("preprocessing for option:", option) + if option_set and pre: + pre_args = getargspec(pre)[0] + if prot: + print("preprocessing for option:", option) - local_symbols = copy(locals()) - (I, state) = pre(**{k: v for (k, v) in local_symbols.items() - if k in pre_args}) + local_symbols = copy(locals()) + (I, state) = pre(**{k: v for (k, v) in local_symbols.items() + if k in pre_args}) I = f(I, **kwds) - if option_set: - if post: - post_args = getargspec(post)[0] - if prot: - print("postprocessing for option:", option) - local_symbols = copy(locals()) - I = post(**{k: v for (k, v) in local_symbols.items() - if k in post_args}) + if option_set and post: + post_args = getargspec(post)[0] + if prot: + print("postprocessing for option:", option) + local_symbols = copy(locals()) + I = post(**{k: v for (k, v) in local_symbols.items() + if k in post_args}) return I wrapper.__name__ = f.__name__ @@ -271,15 +268,15 @@ def llfirst_pre(I, prot): def ll_constants_pre(I): ll_res = [] - while len([p for p in I if p.lex_lead_deg() == 1 and - (p + p.lex_lead()).constant()]) > 0: + while any(p.lex_lead_deg() == 1 and (p + p.lex_lead()).constant() + for p in I): I_new = [] ll = [] leads = set() for p in I: if p.lex_lead_deg() == 1: l = p.lead() - if not (l in leads) and p.is_singleton_or_pair(): + if l not in leads and p.is_singleton_or_pair(): tail = p + l if tail.deg() <= 0: ll.append(p) @@ -289,9 +286,9 @@ def ll_constants_pre(I): encoded = ll_encode(ll) reduced = [] for p in I_new: - p = ll_red_nf_redsb(p, encoded) - if not p.is_zero(): - reduced.append(p) + rp = ll_red_nf_redsb(p, encoded) + if not rp.is_zero(): + reduced.append(rp) I = reduced ll_res.extend(ll) return (I, ll_res) @@ -418,12 +415,12 @@ def llfirst_post(I, state, prot, kwds): # redsb just for safety, as don't know how option is set kwds = copy(kwds) kwds.update( - dict(llfirst=False, - llfirstonthefly=False, - ll_constants=False, - deg_bound=False, - other_ordering_first=False, - eliminate_identical_variables=False, redsb=True)) + {'llfirst': False, + 'llfirstonthefly': False, + 'll_constants': False, + 'deg_bound': False, + 'other_ordering_first': False, + 'eliminate_identical_variables': False, 'redsb': True}) I = groebner_basis(I, **kwds) return I @@ -489,56 +486,63 @@ def eliminate_identical_variables_pre(I, prot): def my_sort_key(l): return l.navigation().value() - for (t, leads) in rules.items(): + for t, leads in rules.items(): if len(leads) > 1: changed = True - leads = sorted(leads, key=my_sort_key, reverse=True) - chosen = leads[0] - ll_system.extend(chosen + v for v in leads[1:]) + sleads = sorted(leads, key=my_sort_key, reverse=True) + chosen = sleads[0] + ll_system.extend(chosen + v for v in sleads[1:]) if ll_system: ll_encoded = ll_encode(ll_system, reduce=True) - I = set(ll_red_nf_redsb(p, ll_encoded) for p in I) + I = {ll_red_nf_redsb(p, ll_encoded) for p in I} return (I, ll_system) @gb_with_pre_post_option("clean_arguments", pre=clean_polys_pre, default=True) @gb_with_pre_post_option("easy_linear_polynomials", - pre=easy_linear_polynomials_pre, default=True) + pre=easy_linear_polynomials_pre, default=True) @gb_with_pre_post_option("result_to_list", post=result_to_list_post, - default=True) + default=True) @with_heuristic(interpolation_gb_heuristic) @gb_with_pre_post_option("invert", pre=invert_all_pre, - post=invert_all_post, default=False) + post=invert_all_post, default=False) @gb_with_pre_post_option("gauss_on_linear", pre=gauss_on_linear_pre, - default=True) + default=True) @gb_with_pre_post_option("ll_constants", pre=ll_constants_pre, - post=ll_constants_post, default=True) + post=ll_constants_post, default=True) @gb_with_pre_post_option("eliminate_identical_variables", - pre=eliminate_identical_variables_pre, post=llfirst_post, default=True) + pre=eliminate_identical_variables_pre, + post=llfirst_post, default=True) @with_heuristic(ll_heuristic) @gb_with_pre_post_option("llfirst", if_not_option=["llfirstonthefly"], - pre=llfirst_pre, post=llfirst_post, default=False) + pre=llfirst_pre, post=llfirst_post, default=False) @gb_with_pre_post_option("llfirstonthefly", pre=llfirstonthefly_pre, - post=llfirst_post, default=False) + post=llfirst_post, default=False) @gb_with_pre_post_option("incremental", pre=incremental_pre) @with_heuristic(change_order_heuristic) @gb_with_pre_post_option("other_ordering_first", if_not_option=[ "interpolation_gb"], pre=other_ordering_pre, default=False) @with_heuristic(linear_algebra_heuristic) @gb_with_pre_post_option("fix_deg_bound", if_not_option=["interpolation_gb"], - post=fix_deg_bound_post, default=True) -@gb_with_pre_post_option("minsb", post=minsb_post, if_not_option=["redsb", - "deg_bound", "interpolation_gb", "convert_with_fglm_from_ring"], - default=True) -@gb_with_pre_post_option("redsb", post=redsb_post, if_not_option=["deg_bound", - "interpolation_gb", "convert_with_fglm_from_ring"], default=True) + post=fix_deg_bound_post, default=True) +@gb_with_pre_post_option("minsb", post=minsb_post, + if_not_option=["redsb", "deg_bound", + "interpolation_gb", + "convert_with_fglm_from_ring"], + default=True) +@gb_with_pre_post_option("redsb", post=redsb_post, + if_not_option=["deg_bound", "interpolation_gb", + "convert_with_fglm_from_ring"], + default=True) def groebner_basis(I, heuristic=True, unique_ideal_generator=False, - interpolation_gb=False, clean_and_restart_algorithm=False, - convert_with_fglm_from_ring=None, convert_with_fglm_to_ring=None, - fglm_bound=40000, - modified_linear_algebra=True, preprocessor=None, deg_bound=False, - implementation="Python", full_prot=False, prot=False, - draw_matrices=False, preprocess_only=False, **impl_options): + interpolation_gb=False, clean_and_restart_algorithm=False, + convert_with_fglm_from_ring=None, + convert_with_fglm_to_ring=None, + fglm_bound=40000, + modified_linear_algebra=True, preprocessor=None, + deg_bound=False, + implementation="Python", full_prot=False, prot=False, + draw_matrices=False, preprocess_only=False, **impl_options): """Computes a Groebner basis of a given ideal I, w.r.t options.""" if not I: @@ -567,10 +571,7 @@ def groebner_basis(I, heuristic=True, unique_ideal_generator=False, prod = (p + 1) * prod I = [prod + 1] - if implementation == "Python": - implementation = symmGB_F2_python - else: - implementation = symmGB_F2_C + implementation = symmGB_F2_python if implementation == 'Python' else symmGB_F2_C # custom preprocessing if preprocessor: @@ -584,11 +585,13 @@ def groebner_basis(I, heuristic=True, unique_ideal_generator=False, def call_algorithm(I, max_generators=None): return implementation(I, - deg_bound=deg_bound, - full_prot=full_prot, - prot=prot, - max_generators=max_generators, draw_matrices=draw_matrices, - **filter_newstyle_options(implementation, **impl_options)) + deg_bound=deg_bound, + full_prot=full_prot, + prot=prot, + max_generators=max_generators, + draw_matrices=draw_matrices, + **filter_newstyle_options(implementation, + **impl_options)) if clean_and_restart_algorithm: for max_generators in [1000, 10000, 50000, 100000, 200000, 300000, @@ -606,22 +609,26 @@ def call_algorithm(I, max_generators=None): def build_groebner_basis_doc_string(): - additional_options_from_buchberger = filter_oldstyle_options(** - get_options_from_function(symmGB_F2_python)) + additional_options_from_buchberger = filter_oldstyle_options( + **get_options_from_function(symmGB_F2_python)) for k in list(additional_options_from_buchberger): if k in groebner_basis.options: del additional_options_from_buchberger[k] - groebner_basis.__doc__ = (groebner_basis.__doc__ + "\nOptions are:\n" + - "\n".join((k + " : " + repr(groebner_basis.options[k]) for k in - groebner_basis.options)) + """ + gdoc = groebner_basis.__doc__ + gdoc += "\nOptions are:\n" + gdoc += "\n".join(k + " : " + repr(groebner_basis.options[k]) + for k in groebner_basis.options) + gdoc += """ Turn off heuristic by setting heuristic=False Additional options come from the actual buchberger implementation. In case of our standard Python implementation these are the following: -""" + "\n".join((k + " : " + repr(additional_options_from_buchberger[k]) - for k in additional_options_from_buchberger))) +""" + gdoc += "\n".join(k + " : " + repr(additional_options_from_buchberger[k]) + for k in additional_options_from_buchberger) + groebner_basis.__doc__ = gdoc build_groebner_basis_doc_string() @@ -630,7 +637,3 @@ def build_groebner_basis_doc_string(): def _test(): import doctest doctest.testmod() - - -if __name__ == "__main__": - _test() diff --git a/src/sage/rings/polynomial/pbori/gbrefs.py b/src/sage/rings/polynomial/pbori/gbrefs.py index 70dc795cbab..0f5436c5b5f 100644 --- a/src/sage/rings/polynomial/pbori/gbrefs.py +++ b/src/sage/rings/polynomial/pbori/gbrefs.py @@ -74,7 +74,8 @@ def load_ref_gz_uu(s, o, b): def convert_refs(ref_file_orig): - content = open(ref_file_orig).read() + with open(ref_file_orig) as file: + content = file.read() buf_out = StringIO() zipped = gzip.GzipFile(filename=ref_file_orig, mode="w", fileobj=buf_out) zipped.write(content) diff --git a/src/sage/rings/polynomial/pbori/interpolate.py b/src/sage/rings/polynomial/pbori/interpolate.py index 68f25d57bb2..783e1209e2a 100644 --- a/src/sage/rings/polynomial/pbori/interpolate.py +++ b/src/sage/rings/polynomial/pbori/interpolate.py @@ -89,7 +89,7 @@ def lex_groebner_basis_points(points, variables): def lex_groebner_basis_for_polynomial_via_variety(p): variables = p.vars_as_monomial() return lex_groebner_basis_points(p.zeros_in(variables.divisors()), - variables) + variables) if __name__ == '__main__': diff --git a/src/sage/rings/polynomial/pbori/interred.py b/src/sage/rings/polynomial/pbori/interred.py index fe59be30896..9ecb705057f 100644 --- a/src/sage/rings/polynomial/pbori/interred.py +++ b/src/sage/rings/polynomial/pbori/interred.py @@ -13,7 +13,7 @@ def interred(l, completely=False): If completely is set to ``True``, then also terms in the tail are not reducible by other polynomials. """ - l = [Polynomial(p) for p in l if not p == 0] + l = [Polynomial(p) for p in l if p != 0] if not l: return [] ring = l[0].ring() @@ -26,8 +26,8 @@ def interred(l, completely=False): if completely: g.opt_red_tail = True for p in l: - p = g.nf(p) - if not p.is_zero(): - g.add_generator(p) + gp = g.nf(p) + if not gp.is_zero(): + g.add_generator(gp) l = tuple(e.p for e in g) - return list(l) + return l diff --git a/src/sage/rings/polynomial/pbori/ll.py b/src/sage/rings/polynomial/pbori/ll.py index 71a01bd3b50..5292050d6a7 100644 --- a/src/sage/rings/polynomial/pbori/ll.py +++ b/src/sage/rings/polynomial/pbori/ll.py @@ -20,16 +20,13 @@ def combine(reductors, p, reduce=None): def llredsb_Cudd_style(polys): - if polys: - reductors = Polynomial(polys[0].ring().one()).set() - else: - reductors = None + reductors = Polynomial(polys[0].ring().one()).set() if polys else None linear_lead = sorted(polys, key=lead_index, reverse=True) - assert len(set(p.lex_lead() for p in linear_lead)) == len(polys) + assert len({p.lex_lead() for p in linear_lead}) == len(polys) assert not any(p.constant() for p in polys) assert len([p for p in polys if p.lex_lead_deg() == 1]) == len(polys) - assert len(set(p.navigation().value() for p in polys)) == len(polys) + assert len({p.navigation().value() for p in polys}) == len(polys) for p in linear_lead: reductors = combine(reductors, p, reduce=ll_red_nf_redsb) return reductors @@ -38,26 +35,20 @@ def llredsb_Cudd_style(polys): def ll_encode(polys, reduce=False, prot=False, reduce_by_linear=True): polys = [Polynomial(p) for p in polys] linear_lead = sorted(polys, key=lead_index, reverse=True) - assert len(set(p.lex_lead() for p in linear_lead)) == len(polys) + assert len({p.lex_lead() for p in linear_lead}) == len(polys) assert not any(p.constant() for p in polys) assert len([p for p in polys if p.lex_lead_deg() == 1]) == len(polys) - assert len(set(p.navigation().value() for p in polys)) == len(polys) + assert len({p.navigation().value() for p in polys}) == len(polys) if (not reduce) and reduce_by_linear: linear_polys = [p for p in polys if p.deg() == 1] if linear_polys: linear_ll = ll_encode(linear_polys, reduce=True, - reduce_by_linear=False) + reduce_by_linear=False) polys = [p.lex_lead() + ll_red_nf_redsb(p + p.lex_lead(), - linear_ll) for p in polys] - if reduce: - reduce = ll_red_nf_redsb - else: - reduce = None + linear_ll) for p in polys] + reduce = ll_red_nf_redsb if reduce else None - if polys: - reductors = Polynomial(polys[0].ring().one()).set() - else: - reductors = None + reductors = Polynomial(polys[0].ring().one()).set() if polys else None last = None counter = 0 @@ -119,11 +110,11 @@ def llnf(p): reduced_list = [] reductors = ll_encode(linear_leads, reduce=(not on_the_fly), prot=prot) for p in rest: - p = reduction_function(p, reductors) - if p.is_one(): - reduced_list = [p] + rp = reduction_function(p, reductors) + if rp.is_one(): + reduced_list = [rp] break - reduced_list.append(p) + reduced_list.append(rp) return (linear_leads, llnf, reduced_list) @@ -145,7 +136,7 @@ def eliminate_ll_ranked(ll_system, to_reduce, ll_ranks = rank(ll_system) add_vars = set(used_vars_set(to_reduce).variables()).difference(ll_ranks. - keys()) + keys()) for v in add_vars: ll_ranks[v] = -1 @@ -182,10 +173,11 @@ def map_from(p): def map_back(p): return substitute_variables(from_ring, map_back_vec, p) + try: ll_opt_encoded = ll_encode([map_from(p) for p in ll_system], - prot=False, - reduce=reduce_ll_system) + prot=False, + reduce=reduce_ll_system) def llnf(p): return map_back(reduction_function(map_from(p), ll_opt_encoded)) @@ -195,7 +187,7 @@ def llnf(p): return (llnf, opt_eliminated) -class RingMap(): +class RingMap: r""" Define a mapping between two rings by common variable names. diff --git a/src/sage/rings/polynomial/pbori/nf.py b/src/sage/rings/polynomial/pbori/nf.py index ac6e447c525..0148826e033 100644 --- a/src/sage/rings/polynomial/pbori/nf.py +++ b/src/sage/rings/polynomial/pbori/nf.py @@ -33,21 +33,21 @@ def build_and_print_matrices(v, strat): """ treated = BooleSet() v = list(v) - rows = 0 - polys_in_mat = [] if not v: return + rows = 0 + polys_in_mat = [] while v: rows = rows + 1 p = v[0] v = v[1:] for m in list(p.terms()): - m = Monomial(m) - if m not in BooleSet(treated): - i = strat.select(m) + mom = Monomial(m) + if mom not in BooleSet(treated): + i = strat.select(mom) if i >= 0: p2 = strat[i] - p2 = p2 * (m // p2.lead()) + p2 = p2 * (mom // p2.lead()) v.append(p2) polys_in_mat.append(p) treated = treated.union(p.set()) @@ -63,12 +63,10 @@ def build_and_print_matrices(v, strat): rows = len(polys_in_mat) cols = len(m2i) im = Image.new("1", (cols, rows), "white") - for i in range(len(polys_in_mat)): - p = polys_in_mat[i] - for j in p: + for i, pi in enumerate(polys_in_mat): + for j in pi: assert i < rows assert j < cols - im.putpixel((j, i), 0) file_name = strat.matrix_prefix + str(mat_counter) + ".png" @@ -120,17 +118,17 @@ def build_and_print_matrices_deg_colored(v, strat): p = v[0] v = v[1:] for m in list(p.terms()): - m = Monomial(m) + mom = Monomial(m) if m not in BooleSet(treated): - i = strat.select(m) + i = strat.select(mom) if i >= 0: p2 = strat[i] - p2 = p2 * (m // p2.lead()) + p2 = p2 * (mom // p2.lead()) v.append(p2) polys_in_mat.append(p) treated = treated.union(p.set()) m2i = {v: k for k, v in enumerate(BooleSet(treated))} - max_deg = max([m.deg() for m in BooleSet(treated)]) + max_deg = max(m.deg() for m in BooleSet(treated)) if max_deg == 0: max_deg = 1 i2deg = {m2i[m]: m.deg() for m in BooleSet(treated)} @@ -149,8 +147,8 @@ def build_and_print_matrices_deg_colored(v, strat): for j in p: assert i < rows assert j < cols - im.putpixel((j, i), ImageColor.getrgb("hsl(" + str(270 - (270 * - i2deg[j]) / max_deg) + ",100%,50%)")) + hsl = str(270 - (270 * i2deg[j]) / max_deg) + im.putpixel((j, i), ImageColor.getrgb("hsl(" + hsl + ",100%,50%)")) file_name = strat.matrix_prefix + str(mat_counter) + ".png" if os.path.exists(file_name): os.remove(file_name) @@ -208,14 +206,17 @@ def high_probability_polynomials_trick(p, strat): def symmGB_F2_python(G, deg_bound=1000000000000, over_deg_bound=0, - use_faugere=False, use_noro=False, opt_lazy=True, opt_red_tail=True, - max_growth=2.0, step_factor=1.0, implications=False, prot=False, - full_prot=False, selection_size=1000, opt_exchange=True, - opt_allow_recursion=False, ll=False, - opt_linear_algebra_in_last_block=True, max_generators=None, - red_tail_deg_growth=True, matrix_prefix='mat', - modified_linear_algebra=True, draw_matrices=False, - easy_linear_polynomials=True): + use_faugere=False, use_noro=False, + opt_lazy=True, opt_red_tail=True, + max_growth=2.0, step_factor=1.0, + implications=False, prot=False, + full_prot=False, selection_size=1000, opt_exchange=True, + opt_allow_recursion=False, ll=False, + opt_linear_algebra_in_last_block=True, + max_generators=None, + red_tail_deg_growth=True, matrix_prefix='mat', + modified_linear_algebra=True, draw_matrices=False, + easy_linear_polynomials=True): if use_noro and use_faugere: raise ValueError('both use_noro and use_faugere specified') @@ -227,8 +228,8 @@ def add_to_basis(strat, p): if prot: if full_prot: print(p) - print("Result: ", "deg:", p.deg(), "lm: ", p.lead(), "el: ", p - .elength()) + print("Result: ", "deg:", p.deg(), "lm: ", + p.lead(), "el: ", p.elength()) if easy_linear_polynomials and p.lead_deg() > 2: lin = easy_linear_polynomials_func(p) for q in lin: @@ -291,7 +292,7 @@ def add_to_basis(strat, p): ps = [strat.reduction_strategy.cheap_reductions(p) for p in ps] ps = [p for p in ps if not p.is_zero()] if ps: - min_deg = min((p.deg() for p in ps)) + min_deg = min(p.deg() for p in ps) new_ps = [] for p in ps: if p.deg() <= min_deg: @@ -305,9 +306,9 @@ def add_to_basis(strat, p): if prot: print("start reducing") print("Chain Crit. : ", strat.chain_criterions, "VC:", strat. - variable_chain_criterions, "EASYP", strat. - easy_product_criterions, "EXTP", strat. - extended_product_criterions) + variable_chain_criterions, "EASYP", strat. + easy_product_criterions, "EXTP", strat. + extended_product_criterions) print(len(ps), "spolys added") if use_noro or use_faugere: @@ -316,18 +317,16 @@ def add_to_basis(strat, p): for p in ps: if not p.is_zero(): v.append(p) - if use_noro: - res = strat.noro_step(v) - else: - res = strat.faugere_step_dense(v) + res = strat.noro_step(v) if use_noro else strat.faugere_step_dense(v) else: v = BoolePolynomialVector() for p in ps: - p = Polynomial(mod_mon_set(BooleSet(p.set()), - strat.reduction_strategy.monomials)) - if not p.is_zero(): - v.append(p) + rp = Polynomial(mod_mon_set( + BooleSet(p.set()), + strat.reduction_strategy.monomials)) + if not rp.is_zero(): + v.append(rp) if len(v) > 100: res = parallel_reduce(v, strat, int(step_factor * 10), max_growth) @@ -382,7 +381,7 @@ def step(strat, trace, var, val): strat.add_generator_delayed(Polynomial( Monomial(Variable(var, strat.r)) + val)) strat = symmGB_F2_python(strat, prot=True, deg_bound=2, - over_deg_bound=10) + over_deg_bound=10) if var <= vars_start: strat = symmGB_F2_python(strat, prot=True, opt_lazy=False, opt_red_tail=False) @@ -428,7 +427,7 @@ def step(strat, trace, proof_path, pos, val): print("npairs", strat.npairs()) print("pos:", pos) strat = symmGB_F2_python(strat, deg_bound=deg_bound, opt_lazy=False, - over_deg_bound=over_deg_bound, prot=True) + over_deg_bound=over_deg_bound, prot=True) print("npairs", strat.npairs()) pos = pos + 1 if pos >= len(proof_path): @@ -472,7 +471,8 @@ def step(strat, trace, var, val): print("npairs", strat.npairs()) strat = symmGB_F2_python(strat, deg_bound=deg_bound, - opt_lazy=opt_lazy, over_deg_bound=over_deg_bound, prot=True) + opt_lazy=opt_lazy, + over_deg_bound=over_deg_bound, prot=True) if not strat.containsOne(): branch(strat, trace) @@ -483,8 +483,8 @@ def branch(strat, trace): if index < 0: uv = set(used_vars_set(strat)) - lv = set(next(iter(p.lead())).index() - for p in strat if p.lead_deg() == 1) + lv = {next(iter(p.lead())).index() + for p in strat if p.lead_deg() == 1} candidates = uv.difference(lv) if candidates: index = next(iter(candidates)).index() @@ -528,7 +528,9 @@ def sort_crit(p): strat.add_as_you_wish(g) if initial_bb: strat = symmGB_F2_python(strat, deg_bound=max(deg_bound, - first_deg_bound), opt_lazy=opt_lazy, over_deg_bound=0, prot=True) + first_deg_bound), + opt_lazy=opt_lazy, over_deg_bound=0, + prot=True) strat.opt_lazy = opt_lazy print("INITIALIZED") branch(strat, []) @@ -549,7 +551,7 @@ def step(strat, trace, proof_path, pos, choice): print("npairs", strat.npairs()) print("pos:", pos) strat = symmGB_F2_python(strat, deg_bound=deg_bound, - over_deg_bound=over_deg_bound, prot=True) + over_deg_bound=over_deg_bound, prot=True) print("npairs", strat.npairs()) pos = pos + 1 if pos >= len(proof_path): @@ -581,16 +583,16 @@ def branch(strat, trace, proof_path, pos): def symmGB_F2_C(G, opt_exchange=True, - deg_bound=1000000000000, opt_lazy=False, - over_deg_bound=0, opt_red_tail=True, - max_growth=2.0, step_factor=1.0, - implications=False, prot=False, - full_prot=False, selection_size=1000, - opt_allow_recursion=False, use_noro=False, use_faugere=False, - ll=False, opt_linear_algebra_in_last_block=True, - max_generators=None, red_tail_deg_growth=True, - modified_linear_algebra=True, matrix_prefix="", - draw_matrices=False): + deg_bound=1000000000000, opt_lazy=False, + over_deg_bound=0, opt_red_tail=True, + max_growth=2.0, step_factor=1.0, + implications=False, prot=False, + full_prot=False, selection_size=1000, + opt_allow_recursion=False, use_noro=False, use_faugere=False, + ll=False, opt_linear_algebra_in_last_block=True, + max_generators=None, red_tail_deg_growth=True, + modified_linear_algebra=True, matrix_prefix="", + draw_matrices=False): if use_noro: raise NotImplementedError("noro not implemented for symmgb") if isinstance(G, list): diff --git a/src/sage/rings/polynomial/pbori/parallel.py b/src/sage/rings/polynomial/pbori/parallel.py index be10865dd50..32eb3894312 100644 --- a/src/sage/rings/polynomial/pbori/parallel.py +++ b/src/sage/rings/polynomial/pbori/parallel.py @@ -1,4 +1,3 @@ -# coding=utf-8 r""" parallel.py PolyBoRi diff --git a/src/sage/rings/polynomial/pbori/randompoly.py b/src/sage/rings/polynomial/pbori/randompoly.py index 1e0dcd56189..34cc53d5dd4 100644 --- a/src/sage/rings/polynomial/pbori/randompoly.py +++ b/src/sage/rings/polynomial/pbori/randompoly.py @@ -99,5 +99,5 @@ def sparse_random_system_data_file_content(number_of_variables, **kwds): dummy_dict) polynomials = sparse_random_system(r, **kwds) polynomials = pformat(polynomials) - return "declare_ring(['x'+str(i) for in range(%s)])\nideal=\\\n%s\n\n" % ( + return "declare_ring(['x'+str(i) for in range({})])\nideal=\\\n{}\n\n".format( number_of_variables, polynomials) diff --git a/src/sage/rings/polynomial/pbori/rank.py b/src/sage/rings/polynomial/pbori/rank.py index bf16e6220ce..98d0a1727c9 100644 --- a/src/sage/rings/polynomial/pbori/rank.py +++ b/src/sage/rings/polynomial/pbori/rank.py @@ -18,7 +18,7 @@ def rank(data): def do_rank(v): if v in res: return res[v] - my_res = res[v] = max([do_rank(p) + 1 for p in parents[v]] + [0]) + my_res = res[v] = max((do_rank(p) + 1 for p in parents[v]), default=0) return my_res for v in parents: do_rank(v) diff --git a/src/sage/rings/polynomial/pbori/specialsets.py b/src/sage/rings/polynomial/pbori/specialsets.py index 74f56c2faf5..9c5b4bdefc8 100644 --- a/src/sage/rings/polynomial/pbori/specialsets.py +++ b/src/sage/rings/polynomial/pbori/specialsets.py @@ -89,7 +89,8 @@ def power_set(variables): print(list(power_set([Variable(i) for i in range(4)]))) print(list(power_set([]))) # every monomial in the first 8 var, which is at most linear in the first 5 - print(list(mod_mon_set(power_set([Variable(i) for i in range(8)]), + print(list(mod_mon_set( + power_set([Variable(i) for i in range(8)]), all_monomials_of_degree_d(2, [Variable(i) for i in range(5)])))) # specialized normal form computation @@ -97,7 +98,8 @@ def power_set(variables): mod_mon_set( (x(1) * x(2) + x(1) + 1).set(), all_monomials_of_degree_d(2, [Variable(i) for i in range(1000)])))) - print(list(mod_mon_set(power_set([Variable(i) for i in range(50)]), + print(list(mod_mon_set( + power_set([Variable(i) for i in range(50)]), all_monomials_of_degree_d(2, [Variable(i) for i in range(1000)])))) diff --git a/src/sage/rings/polynomial/pbori/statistics.py b/src/sage/rings/polynomial/pbori/statistics.py index 93cced307a7..efd49fcd005 100644 --- a/src/sage/rings/polynomial/pbori/statistics.py +++ b/src/sage/rings/polynomial/pbori/statistics.py @@ -21,7 +21,7 @@ def used_vars_set(l, bound=None): s.update(Polynomial(p).vars_as_monomial().variables()) if bound and len(s) > bound: break - sorted_s = sorted(list(s), key=top_index, reverse=True) + sorted_s = sorted(s, key=top_index, reverse=True) m = Monomial(next(iter(l)).ring()) for v in sorted_s: m = v * m From 22ed71b563e0bac93903b5b44fa1ac466b451874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 9 May 2024 11:50:09 +0200 Subject: [PATCH 2/2] suggested removal and minor import move --- src/sage/rings/polynomial/pbori/gbcore.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/sage/rings/polynomial/pbori/gbcore.py b/src/sage/rings/polynomial/pbori/gbcore.py index 9c40c94c06c..b5bc0a56192 100644 --- a/src/sage/rings/polynomial/pbori/gbcore.py +++ b/src/sage/rings/polynomial/pbori/gbcore.py @@ -1,3 +1,4 @@ +import contextlib from copy import copy from itertools import chain from inspect import getfullargspec as getargspec @@ -12,7 +13,6 @@ from .easy_polynomials import easy_linear_polynomials from .interpolate import lex_groebner_basis_for_polynomial_via_variety from .fglm import _fglm -import contextlib def get_options_from_function(f): @@ -632,8 +632,3 @@ def build_groebner_basis_doc_string(): build_groebner_basis_doc_string() - - -def _test(): - import doctest - doctest.testmod()