diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index da6dd6c09dd..49c930ccb38 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -1355,10 +1355,10 @@ def BIBD_from_arc_in_desarguesian_projective_plane(n,k,existence=False): :doi:`10.1016/S0021-9800(69)80095-5` """ q = (n-1)//(k-1)-1 - if (k % 2 or - q % 2 or - q <= k or - n != (k-1)*(q+1)+1 or + if (k % 2 or + q % 2 or + q <= k or + n != (k-1)*(q+1)+1 or not is_prime_power(k) or not is_prime_power(q)): if existence: @@ -1391,12 +1391,10 @@ def BIBD_from_arc_in_desarguesian_projective_plane(n,k,existence=False): # [Denniston69] is the set of all elements of K of degree < log_n # (seeing elements of K as polynomials in 'a') - K_iter = list(K) # faster iterations - log_n = is_prime_power(n,get_data=True)[1] - C = [(x,y,one) - for x in K_iter - for y in K_iter - if Q(x,y).polynomial().degree() < log_n] + K_iter = list(K) # faster iterations + log_n = is_prime_power(n, get_data=True)[1] + C = [(x, y, one) for x in K_iter for y in K_iter + if Q(x, y).polynomial().degree() < log_n] from sage.combinat.designs.block_design import DesarguesianProjectivePlaneDesign return DesarguesianProjectivePlaneDesign(q).trace(C)._blocks diff --git a/src/sage/combinat/designs/block_design.py b/src/sage/combinat/designs/block_design.py index bdf37227019..0c8b5b3fd38 100644 --- a/src/sage/combinat/designs/block_design.py +++ b/src/sage/combinat/designs/block_design.py @@ -42,7 +42,7 @@ --------------------- """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 Peter Dobcsanyi # Copyright (C) 2007 David Joyner # @@ -51,7 +51,7 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# **************************************************************************** from sage.arith.misc import binomial, integer_floor, is_prime_power from sage.categories.sets_cat import EmptySetError from sage.misc.lazy_import import lazy_import @@ -69,7 +69,7 @@ BlockDesign = IncidenceStructure -### utility functions ------------------------------------------------------- +# utility functions ----------------------------------------------------- def tdesign_params(t, v, k, L): @@ -338,9 +338,10 @@ def DesarguesianProjectivePlaneDesign(n, point_coordinates=True, check=True): """ K = FiniteField(n, 'a') n2 = n**2 - relabel = {x:i for i,x in enumerate(K)} - Kiter = relabel # it is much faster to iterate through a dict than through - # the finite field K + relabel = {x: i for i, x in enumerate(K)} + Kiter = relabel + # it is much faster to iterate through a dict than through + # the finite field K # we decompose the (equivalence class) of points [x:y:z] of the projective # plane into an affine plane, an affine line and a point. At the same time, @@ -996,14 +997,14 @@ def HadamardDesign(n): """ from sage.combinat.matrices.hadamard_matrix import hadamard_matrix from sage.matrix.constructor import matrix - H = hadamard_matrix(n+1) #assumed to be normalised. + H = hadamard_matrix(n + 1) # assumed to be normalised. H1 = H.matrix_from_columns(range(1,n+1)) H2 = H1.matrix_from_rows(range(1,n+1)) J = matrix(ZZ,n,n,[1]*n*n) MS = J.parent() - A = MS((H2+J)/2) # convert -1's to 0's; coerce entries to ZZ + A = MS((H2+J)/2) # convert -1's to 0's; coerce entries to ZZ # A is the incidence matrix of the block design - return IncidenceStructure(incidence_matrix=A,name='HadamardDesign') + return IncidenceStructure(incidence_matrix=A, name='HadamardDesign') def Hadamard3Design(n): @@ -1060,10 +1061,10 @@ def Hadamard3Design(n): raise ValueError("The Hadamard design with n = %s does not extend to a three design." % n) from sage.combinat.matrices.hadamard_matrix import hadamard_matrix from sage.matrix.constructor import matrix, block_matrix - H = hadamard_matrix(n) #assumed to be normalised. + H = hadamard_matrix(n) # assumed to be normalised. H1 = H.matrix_from_columns(range(1, n)) J = matrix(ZZ, n, n-1, [1]*(n-1)*n) - A1 = (H1+J)/2 - A2 = (J-H1)/2 - A = block_matrix(1, 2, [A1, A2]) #the incidence matrix of the design. + A1 = (H1 + J) / 2 + A2 = (J - H1) / 2 + A = block_matrix(1, 2, [A1, A2]) # the incidence matrix of the design. return IncidenceStructure(incidence_matrix=A, name='HadamardThreeDesign') diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 7c797481773..dc614bd7b25 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -1109,7 +1109,7 @@ def OA_10_205(): baer_subplane_size = 4**2+4+1 B = [0, 1, 22, 33, 83, 122, 135, 141, 145, 159, 175, 200, 226, 229, 231, 238, 246] - pplane = [[(xx+i) % pplane_size for xx in B] for i in range(pplane_size)] + pplane = [[(xx+i) % pplane_size for xx in B] for i in range(pplane_size)] baer_subplane = set([i*pplane_size/baer_subplane_size for i in range(baer_subplane_size)]) p = list(baer_subplane)[0] @@ -1284,7 +1284,7 @@ def OA_11_254(): # Base block of a PG(2,19) B = (0,1,19,28,96,118,151,153,176,202,240,254,290,296,300,307,337,361,366,369) - BIBD = [[(x+i) % 381 for x in B] for i in range(381)] + BIBD = [[(x+i) % 381 for x in B] for i in range(381)] # We only keep points congruent to 0,1 mod 3 and relabel the PBD. The result is # a (254,{11,13,16})-PBD @@ -1708,7 +1708,7 @@ def OA_10_469(): 731,824,837,848,932,1002,1051,1055,1089,1105,1145,1165,1196,1217,1226, 1274,1281,1309,1405) - BIBD = [[(x+i) % 1407 for x in B] for i in range(1407)] + BIBD = [[(x+i) % 1407 for x in B] for i in range(1407)] # Only keep points v congruent to 0 mod 3 and relabel PBD = [[x//3 for x in B if x % 3 == 0] for B in BIBD] @@ -4171,7 +4171,7 @@ def RBIBD_120_8_1(): # A (precomputed) set that every block of the BIBD intersects on 0 or 2 points hyperoval = [128, 192, 194, 4, 262, 140, 175, 48, 81, 180, 245, 271, 119, 212, 249, 189, 62, 255] - #for B in BIBD: + # for B in BIBD: # len_trace = sum(x in hyperoval for x in B) # assert len_trace == 0 or len_trace == 2 @@ -4577,13 +4577,9 @@ def HigmanSimsDesign(): from sage.combinat.designs.block_design import WittDesign from .incidence_structures import IncidenceStructure W = WittDesign(24) - a,b = 0,1 - Wa = [set(B) for B in W - if (a in B and - b not in B)] - Wb = [set(B) for B in W - if (b in B and - a not in B)] + a, b = 0, 1 + Wa = [set(B) for B in W if a in B and b not in B] + Wb = [set(B) for B in W if b in B and a not in B] H = [[i for i, A in enumerate(Wa) if len(A & B) != 2] for B in Wb] diff --git a/src/sage/combinat/designs/difference_family.py b/src/sage/combinat/designs/difference_family.py index 789f5d9a281..2ec008f16db 100644 --- a/src/sage/combinat/designs/difference_family.py +++ b/src/sage/combinat/designs/difference_family.py @@ -123,8 +123,8 @@ def block_stabilizer(G, B): S = [] for b in B: # fun: if we replace +(-b) with -b it completely fails!! - bb0 = op(b,b0) # bb0 = b-B[0] - if all(op(bb0,c) in B for c in B): + bb0 = op(b, b0) # bb0 = b-B[0] + if all(op(bb0, c) in B for c in B): S.append(bb0) return S @@ -279,7 +279,7 @@ def is_difference_family(G, D, v=None, k=None, l=None, verbose=False): for c in d: if b == c: continue - gg = mul(b,inv(c)) # = b-c or bc^{-1} + gg = mul(b, inv(c)) # = b-c or bc^{-1} if gg not in tmp_counter: tmp_counter[gg] = 0 where[gg].add(i) @@ -319,7 +319,7 @@ def is_difference_family(G, D, v=None, k=None, l=None, verbose=False): g, counter[g], sorted(where[g]))) if too_much: print("Too much:") - for g in too_much: + for g in too_much: print(" {} is obtained {} times in blocks {}".format( g, counter[g], sorted(where[g]))) if too_few or too_much: @@ -388,9 +388,10 @@ def singer_difference_set(q,d): # build a polynomial c over GF(q) such that GF(q)[x] / (c(x)) is a # GF(q**(d+1)) and such that x is a multiplicative generator. p,e = q.factor()[0] - c = conway_polynomial(p,e*(d+1)) - if e != 1: # i.e. q is not a prime, so we factorize c over GF(q) and pick - # one of its factor + c = conway_polynomial(p, e*(d+1)) + if e != 1: + # i.e. q is not a prime, so we factorize c over GF(q) and pick + # one of its factor K = GF(q,'z') c = c.change_ring(K).factor()[0][0] else: @@ -454,7 +455,7 @@ def df_q_6_1(K, existence=False, check=True): xx = x**5 to_coset = {x**i * xx**j: i for i in range(5) for j in range((v-1)/5)} - for c in to_coset: # the loop runs through all nonzero elements of K + for c in to_coset: # the loop runs through all nonzero elements of K if c == one or c == r or c == r2: continue if len(set(to_coset[elt] for elt in (r-one, c*(r-one), c-one, c-r, c-r**2))) == 5: @@ -796,13 +797,13 @@ def one_radical_difference_family(K, k): A = [r**i - 1 for i in range(1,m+1)] else: m = k // 2 - r = x ** ((q-1) // (k-1)) # (k-1)-th root of unity + r = x ** ((q-1) // (k-1)) # (k-1)-th root of unity A = [r**i - 1 for i in range(1,m)] A.append(K.one()) # instead of the complicated multiplicative group K^*/(±C) we use the # discrete logarithm to convert everything into the additive group Z/cZ - c = m * (q-1) // e # cardinal of ±C + c = m * (q-1) // e # cardinal of ±C from sage.groups.generic import discrete_log logA = [discrete_log(a,x) % c for a in A] @@ -1036,18 +1037,18 @@ def are_mcfarland_1973_parameters(v, k, lmbda, return_parameters=False): 96 20 4 4 1 """ if v <= k or k <= lmbda: - return (False,None) if return_parameters else False + return (False, None) if return_parameters else False k = ZZ(k) lmbda = ZZ(lmbda) - qs,r = (k - lmbda).sqrtrem() # sqrt(k-l) should be q^s + qs, r = (k - lmbda).sqrtrem() # sqrt(k-l) should be q^s if r or (qs*(qs-1)) % lmbda: - return (False,None) if return_parameters else False + return (False, None) if return_parameters else False q = qs*(qs-1) // lmbda + 1 if (q <= 1 or - v * (q-1) != qs*q * (qs*q+q-2) or + v * (q-1) != qs*q * (qs*q+q-2) or k * (q-1) != qs * (qs*q-1)): - return (False,None) if return_parameters else False + return (False, None) if return_parameters else False # NOTE: below we compute the value of s so that qs = q^s. If the method # is_power_of of integers would be able to return the exponent, we could use @@ -1057,7 +1058,7 @@ def are_mcfarland_1973_parameters(v, k, lmbda, return_parameters=False): p2,a2 = q.is_prime_power(get_data=True) if a1 == 0 or a2 == 0 or p1 != p2 or a1 % a2: - return (False,None) if return_parameters else False + return (False, None) if return_parameters else False return (True, (q, a1//a2)) if return_parameters else True @@ -1265,10 +1266,10 @@ def turyn_1965_3x3xK(k=4): else: raise ValueError("k must be 2 or 4") - L = [[(0,1),(1,1),(2,1),(0,2),(1,2),(2,2)], # complement of y=0 - [(0,0),(1,1),(2,2)], # x-y=0 - [(0,0),(1,2),(2,1)], # x+y=0 - [(0,0),(0,1),(0,2)]] # x=0 + L = [[(0,1),(1,1),(2,1),(0,2),(1,2),(2,2)], # complement of y=0 + [(0,0),(1,1),(2,2)], # x-y=0 + [(0,0),(1,2),(2,1)], # x+y=0 + [(0,0),(0,1),(0,2)]] # x=0 return G, [[G(v + k) for l, k in zip(L, K) for v in l]] @@ -1835,7 +1836,7 @@ def supplementary_difference_set_from_rel_diff_set(q, existence=False, check=Tru from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing P = PolynomialRing(ZZ, 'x') - #Compute psi3, psi4 + # Compute psi3, psi4 hall = 0 for d in set1: hall += P.monomial(d[0]) diff --git a/src/sage/combinat/designs/ext_rep.py b/src/sage/combinat/designs/ext_rep.py index 5297ad3357a..93f55f6daed 100644 --- a/src/sage/combinat/designs/ext_rep.py +++ b/src/sage/combinat/designs/ext_rep.py @@ -869,11 +869,11 @@ def _start_element(self, name, attrs): check_dtrs_protocols('source', attrs['dtrs_protocol']) if self.list_of_designs_start_proc: self.list_of_designs_start_proc(attrs) - #self.outf.write('<%s' % name) - #pp_attributes(self.outf, attrs, indent='', precision_stack=[]) - #self.outf.write('>\n') + # self.outf.write('<%s' % name) + # pp_attributes(self.outf, attrs, indent='', precision_stack=[]) + # self.outf.write('>\n') elif name == 'designs': - pass # self.outf.write(' <%s>\n' % name) + pass # self.outf.write(' <%s>\n' % name) if self.in_item: for k, v in attrs.items(): attrs[k] = _encode_attribute(v) @@ -916,7 +916,7 @@ def _end_element(self, name): if name == 'block' or name == 'permutation' \ or name == 'preimage' or name == 'ksubset' \ or name == 'cycle_type' or name == 'row': - # these enclose lists of numbers + # these enclose lists of numbers children.append(ps) else: # the rest is a single number @@ -929,19 +929,19 @@ def _end_element(self, name): if self.save_designs: init_bd = XTree(self.current_node[2][0]) self.list_of_designs.append((init_bd.v, list(init_bd.blocks))) - #print_subxt(self.current_node[2][0], level=2, outf=self.outf) + # print_subxt(self.current_node[2][0], level=2, outf=self.outf) self._init() elif name == 'info': if self.info_proc: self.info_proc(self.current_node[2][0]) - #print_subxt(self.current_node[2][0], level=1, outf=self.outf) + # print_subxt(self.current_node[2][0], level=1, outf=self.outf) self._init() else: if name == 'designs': if self.designs_end_proc: self.designs_end_proc() - #self.outf.write(' ') - #self.outf.write('\n' % name) + # self.outf.write(' ') + # self.outf.write('\n' % name) def _char_data(self, data): """ @@ -962,9 +962,8 @@ def _char_data(self, data): {'b': 26, 'id': 't2-v13-b26-r6-k3-L1-0', 'v': 13}, ['[ DESIGN-1.1, GRAPE-4.2, GAPDoc-0.9999, GAP-4.4.3]']) """ - if self.in_item: - #@ this stripping may distort char data in the subtree + # @ this stripping may distort char data in the subtree # if they are not bracketed in some way. data = data.strip() if data: diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index 148cc11fdfa..e9964af900c 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -142,7 +142,7 @@ class IncidenceStructure: True """ def __init__(self, points=None, blocks=None, incidence_matrix=None, - name=None, check=True, copy=True): + name=None, check=True, copy=True): r""" TESTS:: @@ -271,7 +271,7 @@ def __repr__(self): Incidence structure with 7 points and 7 blocks """ return 'Incidence structure with {} points and {} blocks'.format( - self.num_points(), self.num_blocks()) + self.num_points(), self.num_blocks()) __str__ = __repr__ @@ -309,7 +309,7 @@ def __eq__(self, other): return self._blocks == other._blocks if (self.num_points() != other.num_points() or - self.num_blocks() != other.num_blocks()): + self.num_blocks() != other.num_blocks()): return False p_to_i = self._point_to_index if self._point_to_index else list(range(self.num_points())) @@ -409,12 +409,12 @@ def canonical_label(self): from sage.graphs.graph import Graph g = Graph() n = self.num_points() - g.add_edges((i+n,x) for i,b in enumerate(self._blocks) for x in b) - canonical_label = g.canonical_label([list(range(n)),list(range(n,n+self.num_blocks()))],certificate=True)[1] + g.add_edges((i+n, x) for i, b in enumerate(self._blocks) for x in b) + canonical_label = g.canonical_label([list(range(n)), list(range(n, n+self.num_blocks()))], certificate=True)[1] canonical_label = [canonical_label[x] for x in range(n)] self._canonical_label = canonical_label - return dict(zip(self._points,self._canonical_label)) + return dict(zip(self._points, self._canonical_label)) def is_isomorphic(self, other, certificate=False): r""" @@ -475,25 +475,25 @@ def is_isomorphic(self, other, certificate=False): """ if (self.num_points() != other.num_points() or self.num_blocks() != other.num_blocks() or - sorted(self.block_sizes()) != sorted(other.block_sizes())): + sorted(self.block_sizes()) != sorted(other.block_sizes())): return {} if certificate else False A_canon = self.canonical_label() B_canon = other.canonical_label() - A = self.relabel(A_canon,inplace=False) - B = other.relabel(B_canon,inplace=False) + A = self.relabel(A_canon, inplace=False) + B = other.relabel(B_canon, inplace=False) if A == B: if certificate: - B_canon_rev = {y:x for x,y in B_canon.items()} - return {x:B_canon_rev[xint] for x,xint in A_canon.items()} + B_canon_rev = {y: x for x, y in B_canon.items()} + return {x: B_canon_rev[xint] for x, xint in A_canon.items()} else: return True else: return {} if certificate else False - def isomorphic_substructures_iterator(self, H2,induced=False): + def isomorphic_substructures_iterator(self, H2, induced=False): r""" Iterate over all copies of ``H2`` contained in ``self``. @@ -560,7 +560,7 @@ def isomorphic_substructures_iterator(self, H2,induced=False): 5616 """ from sage.combinat.designs.subhypergraph_search import SubHypergraphSearch - return SubHypergraphSearch(self,H2,induced=induced) + return SubHypergraphSearch(self, H2, induced=induced) def copy(self): r""" @@ -581,7 +581,7 @@ def copy(self): IS = IncidenceStructure(self._blocks, name=self._name, check=False) - IS.relabel(dict(zip(range(self.num_points()),self._points))) + IS.relabel(dict(zip(range(self.num_points()), self._points))) IS._canonical_label = None if self._canonical_label is None else self._canonical_label[:] return IS @@ -723,7 +723,7 @@ def trace(self, points, min_size=1, multiset=True): if not multiset: blocks = set(blocks) IS = IncidenceStructure(blocks) - IS.relabel({i:self._points[i] for i in int_points}) + IS.relabel({i: self._points[i] for i in int_points}) return IS def ground_set(self): @@ -830,7 +830,7 @@ def degree(self, p=None, subset=False): # degree of a point if not subset: if self._point_to_index: - p = self._point_to_index.get(p,-1) + p = self._point_to_index.get(p, -1) else: p = p if (p >= 0 and p < len(self._points)) else -1 return sum((p in b) for b in self._blocks) if p != -1 else 0 @@ -838,7 +838,7 @@ def degree(self, p=None, subset=False): # degree of a set else: if self._point_to_index: - p = set(self._point_to_index.get(x,-1) for x in p) + p = set(self._point_to_index.get(x, -1) for x in p) else: p = set(p) if all(x >= 0 and x < len(self._points) for x in p) else set([-1]) @@ -888,12 +888,12 @@ def degrees(self, size=None): return {p: d[i] for i, p in enumerate(self._points)} else: from itertools import combinations - d = {t:0 for t in combinations(range(self.num_points()),size)} + d = {t: 0 for t in combinations(range(self.num_points()), size)} for b in self._blocks: - for s in combinations(b,size): + for s in combinations(b, size): d[s] += 1 if self._point_to_index: - return {tuple([self._points[x] for x in s]):v for s,v in d.items()} + return {tuple([self._points[x] for x in s]): v for s, v in d.items()} else: return d @@ -1112,8 +1112,8 @@ def intersection_graph(self, sizes=None): sizes = PositiveIntegers() elif sizes in PositiveIntegers(): sizes = (sizes,) - V = [Set(v) for v in self] - return Graph([V, lambda x,y: len(x & y) in sizes], loops=False) + V = [Set(v) for v in self] + return Graph([V, lambda x, y: len(x & y) in sizes], loops=False) def incidence_matrix(self): r""" @@ -1150,7 +1150,7 @@ def incidence_matrix(self): A[i, j] = 1 return A - def incidence_graph(self,labels=False): + def incidence_graph(self, labels=False): r""" Return the incidence graph of the incidence structure. @@ -1201,7 +1201,7 @@ def incidence_graph(self,labels=False): for b in self.blocks(): b = Set(b) G.add_vertex(b) - G.add_edges((b,x) for x in b) + G.add_edges((b, x) for x in b) return G else: @@ -1243,7 +1243,7 @@ def is_berge_cyclic(self): return not self.incidence_graph().is_forest() - def complement(self,uniform=False): + def complement(self, uniform=False): r""" Return the complement of the incidence structure. @@ -1303,7 +1303,7 @@ def complement(self,uniform=False): num_blocks = self.num_blocks() i = 0 from itertools import combinations - for B in combinations(range(self.num_points()),k): + for B in combinations(range(self.num_points()), k): B = list(B) while i < num_blocks and self._blocks[i] < B: i += 1 @@ -1311,12 +1311,12 @@ def complement(self,uniform=False): i += 1 continue blocks.append(B) - I = IncidenceStructure(blocks,copy=False) + I = IncidenceStructure(blocks, copy=False) else: X = set(range(self.num_points())) I = IncidenceStructure([X.difference(B) for B in self._blocks]) - I.relabel({i:self._points[i] for i in range(self.num_points())}) + I.relabel({i: self._points[i] for i in range(self.num_points())}) return I def relabel(self, perm=None, inplace=True): @@ -1387,7 +1387,7 @@ def relabel(self, perm=None, inplace=True): self._point_to_index = None return - if isinstance(perm, (list,tuple)): + if isinstance(perm, (list, tuple)): perm = dict(zip(self._points, perm)) if not isinstance(perm, dict): @@ -1608,32 +1608,32 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): b = self.num_blocks() # Trivial wrong answers - if (any(len(block) != k for block in self._blocks) or # non k-uniform - v != self.num_points()): - return (False, (0,0,0,0)) if return_parameters else False + if (any(len(block) != k for block in self._blocks) or # non k-uniform + v != self.num_points()): + return (False, (0, 0, 0, 0)) if return_parameters else False # Trivial case t>k if (t is not None and t > k): if (l is None or l == 0): - return (True, (t,v,k,0)) if return_parameters else True + return (True, (t, v, k, 0)) if return_parameters else True else: - return (False, (0,0,0,0)) if return_parameters else False + return (False, (0, 0, 0, 0)) if return_parameters else False # Trivial case k=0 if k == 0: if (l is None or l == 0): - return (True, (0,v,k,b)) if return_parameters else True + return (True, (0, v, k, b)) if return_parameters else True else: - return (False, (0,0,0,0)) if return_parameters else False + return (False, (0, 0, 0, 0)) if return_parameters else False # Trivial case k=v (includes v=0) if k == v: if t is None: t = v if l is None or b == l: - return (True, (t,v,k,b)) if return_parameters else True + return (True, (t, v, k, b)) if return_parameters else True else: - return (True, (0,0,0,0)) if return_parameters else False + return (True, (0, 0, 0, 0)) if return_parameters else False # Handbook of combinatorial design theorem II.4.8: # @@ -1642,30 +1642,30 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): # # We look for the largest t such that self is a t-design from itertools import combinations - for tt in (range(1,k+1) if t is None else [t]): + for tt in (range(1, k + 1) if t is None else [t]): # is lambda an integer? - if (b*binomial(k,tt)) % binomial(v,tt) != 0: + if (b * binomial(k, tt)) % binomial(v, tt): tt -= 1 break s = {} for block in self._blocks: - for i in combinations(block,tt): - s[i] = s.get(i,0) + 1 + for i in combinations(block, tt): + s[i] = s.get(i, 0) + 1 if len(set(s.values())) != 1: tt -= 1 break - ll = b*binomial(k,tt) // binomial(v,tt) + ll = (b * binomial(k, tt)) // binomial(v, tt) if ((t is not None and t != tt) or - (l is not None and l != ll)): - return (False, (0,0,0,0)) if return_parameters else False + (l is not None and l != ll)): + return (False, (0, 0, 0, 0)) if return_parameters else False else: if tt == 0: ll = b - return (True, (tt,v,k,ll)) if return_parameters else True + return (True, (tt, v, k, ll)) if return_parameters else True def is_generalized_quadrangle(self, verbose=False, parameters=False): r""" @@ -1758,9 +1758,9 @@ def is_generalized_quadrangle(self, verbose=False, parameters=False): if parameters: s = self.is_uniform() t = self.is_regular() - s = s-1 if (s is not False and s >= 2) else False - t = t-1 if (t is not False and t >= 2) else False - return (s,t) + s = s - 1 if (s is not False and s >= 2) else False + t = t - 1 if (t is not False and t >= 2) else False + return (s, t) else: return True @@ -1812,10 +1812,10 @@ def dual(self, algorithm=None): v = DD['v'].sage() gB = [[x - 1 for x in b] for b in DD['blocks'].sage()] return IncidenceStructure(list(range(v)), gB, name=None, check=False) - else: - return IncidenceStructure( - incidence_matrix=self.incidence_matrix().transpose(), - check=False) + + return IncidenceStructure( + incidence_matrix=self.incidence_matrix().transpose(), + check=False) def automorphism_group(self): r""" @@ -1856,9 +1856,9 @@ def automorphism_group(self): from sage.groups.perm_gps.permgroup import PermutationGroup g = Graph() n = self.num_points() - g.add_edges((i+n,x) for i,b in enumerate(self._blocks) for x in b) + g.add_edges((i + n, x) for i, b in enumerate(self._blocks) for x in b) ag = g.automorphism_group(partition=[list(range(n)), - list(range(n,n+self.num_blocks()))]) + list(range(n, n + self.num_blocks()))]) if self._point_to_index: gens = [[tuple([self._points[i] for i in cycle if (not cycle or cycle[0] < n)]) @@ -1971,18 +1971,18 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, # Lists of blocks containing i for every i dual = [[] for _ in domain] - for i,B in enumerate(self._blocks): + for i, B in enumerate(self._blocks): for x in B: dual[x].append(i) # Each class is a partition for t in range(n_classes): for x in domain: - p.add_constraint(p.sum(b[t,i] for i in dual[x]) == 1) + p.add_constraint(p.sum(b[t, i] for i in dual[x]) == 1) # Each set appears exactly once for i in range(len(self._blocks)): - p.add_constraint(p.sum(b[t,i] for t in range(n_classes)) == 1) + p.add_constraint(p.sum(b[t, i] for t in range(n_classes)) == 1) try: p.solve(log=verbose) @@ -1998,8 +1998,8 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, if check and self._classes is not False: assert sorted(id(c) for cls in self._classes for c in cls) == sorted(id(b) for b in self._blocks), "some set does not appear exactly once" domain = list(range(self.num_points())) - for i,c in enumerate(self._classes): - assert sorted(sum(c,[])) == domain, "class {} is not a partition".format(i) + for i, c in enumerate(self._classes): + assert sorted(sum(c, [])) == domain, "class {} is not a partition".format(i) if self._classes is False: return (False, []) if certificate else False @@ -2069,7 +2069,7 @@ def coloring(self, k=None, solver=None, verbose=0, 3 """ if k is None: - for k in range(self.num_points()+1): + for k in range(self.num_points() + 1): try: return self.coloring(k) except ValueError: @@ -2093,11 +2093,11 @@ def coloring(self, k=None, solver=None, verbose=0, b = p.new_variable(binary=True) for x in range(self.num_points()): - p.add_constraint(p.sum(b[x,i] for i in range(k)) == 1) + p.add_constraint(p.sum(b[x, i] for i in range(k)) == 1) for s in self._blocks: for i in range(k): - p.add_constraint(p.sum(b[x,i] for x in s) <= len(s)-1) + p.add_constraint(p.sum(b[x, i] for x in s) <= len(s) - 1) try: p.solve(log=verbose) @@ -2106,13 +2106,13 @@ def coloring(self, k=None, solver=None, verbose=0, col = [[] for _ in range(k)] - for (x,i),v in p.get_values(b, convert=bool, tolerance=integrality_tolerance).items(): + for (x, i), v in p.get_values(b, convert=bool, tolerance=integrality_tolerance).items(): if v: col[i].append(self._points[x]) return col - def edge_coloring(self): + def edge_coloring(self) -> list: r""" Compute a proper edge-coloring. @@ -2185,13 +2185,13 @@ def _spring_layout(self): for x in s: g.add_edge((0, s), (1, x)) - _ = g.plot(iterations=50000,save_pos=True) + _ = g.plot(iterations=50000, save_pos=True) # The values are rounded as TikZ does not like accuracy. return {k[1]: (round(x, 3), round(y, 3)) for k, (x, y) in g.get_pos().items()} - def _latex_(self): + def _latex_(self) -> str: r""" Return a TikZ representation of the incidence structure. @@ -2246,11 +2246,12 @@ def _latex_(self): pos = self._spring_layout() tex = "\\begin{tikzpicture}[scale=3]\n" - colors = ["black", "red", "green", "blue", "cyan", "magenta", "yellow","pink","brown"] - colored_sets = [(s,i) for i,S in enumerate(self.edge_coloring()) for s in S] + colors = ["black", "red", "green", "blue", "cyan", + "magenta", "yellow", "pink", "brown"] + colored_sets = [(s, i) for i, S in enumerate(self.edge_coloring()) for s in S] # Prints each set with its color - for s,i in colored_sets: + for s, i in colored_sets: current_color = colors[i % len(colors)] if len(s) == 2: @@ -2283,7 +2284,7 @@ def _latex_(self): tex += "\\end{tikzpicture}" return tex - def is_spread(self, spread): + def is_spread(self, spread) -> bool: r""" Check whether the input is a spread for ``self``. @@ -2340,10 +2341,7 @@ def is_spread(self, spread): points.difference_update(sblock) - if points: - return False - - return True + return not points from sage.misc.rest_index_of_methods import gen_rest_table_index diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index ae1d48388bb..daac0f322cf 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -955,12 +955,12 @@ def orthogonal_array(k,n,t=2,resolvable=False, check=True,existence=False,explai # Constructions from the database III (Quasi-difference matrices) elif (may_be_available and - (n,1) in QDM and + (n, 1) in QDM and any(kk >= k and mu <= lmbda and (orthogonal_array(k,u,existence=True) is True) for (_,lmbda,mu,u),(kk,_) in QDM[n,1].items())): _OA_cache_set(k,n,True) - for (nn,lmbda,mu,u),(kk,f) in QDM[n,1].items(): - if (kk >= k and + for (nn, lmbda, mu, u), (kk, f) in QDM[n,1].items(): + if (kk >= k and mu <= lmbda and (orthogonal_array(k,u,existence=True) is True)): if existence: @@ -1236,11 +1236,11 @@ def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): raise EmptySetError("The total size of holes must be smaller or equal than the size of the ground set") if (max_hole == 1 and - resolvable and + resolvable and sum_of_holes != n): if existence: return False - raise EmptySetError("There is no resolvable incomplete OA({},{}) whose holes' sizes sum to {} equivalent to OA(k+1,n) if max_hole == 1 and resolvable: @@ -1366,11 +1366,11 @@ def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): # Equal holes [h,h,...] with h>1 through OA product construction # # (i.e. OA(k,n1)-x.OA(k,1) and OA(k,n2) ==> OA(k,n1.n2)-x.OA(k,n2) ) - elif (min_hole > 1 and - max_hole == min_hole and - n % min_hole == 0 and # h divides n + elif (min_hole > 1 and + max_hole == min_hole and + n % min_hole == 0 and # h divides n orthogonal_array(k,min_hole,existence=True) and # OA(k,h) - incomplete_orthogonal_array(k,n//min_hole,[1]*number_of_holes,existence=True)): # OA(k,n/h)-x.OA(k,1) + incomplete_orthogonal_array(k,n//min_hole,[1]*number_of_holes,existence=True)): # OA(k,n/h)-x.OA(k,1) if existence: return True h = min_hole @@ -1540,7 +1540,7 @@ def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): """ if blocks: l = [] - for i,B in enumerate(zip(*blocks)): # the blocks are disjoint + for i, B in enumerate(zip(*blocks)): # the blocks are disjoint if len(B) != len(set(B)): raise RuntimeError("Two block have the same coordinate for one of the k dimensions") @@ -1941,7 +1941,7 @@ def QDM_from_Vmt(m,t,V): for e in V: L.append(e*wm**i) for ii in range(m+2): - M.append(L[-ii:]+L[:-ii]) # cyclic shift + M.append(L[-ii:]+L[:-ii]) # cyclic shift M.append([0]*(m+2)) diff --git a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py index edad950fc88..7366fb42a5a 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py +++ b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py @@ -537,9 +537,9 @@ def construction_q_x(k, q, x, check=True, explain_construction=False): # Add rows, extended with p1 and p2 p1 = q**2 - p2 = p1+1 - TD.extend([[ii*q+i for ii in range(q)]+[p1] for i in range(1,q)]) - TD.append( [ii*q for ii in range(q)]+[p1,p2]) + p2 = p1 + 1 + TD.extend(([ii*q + i for ii in range(q)] + [p1] for i in range(1, q))) + TD.append([ii*q for ii in range(q)] + [p1, p2]) # Add Columns. We do not add some columns which would have size 1 after we # delete points. @@ -1453,9 +1453,9 @@ def brouwer_separable_design(k,t,q,x,check=False,verbose=False,explain_construct else: partition_of_blocks_of_size_t[plane-t].append([relabel[xx] for xx in B if xx % m < t]) - ############################################################################### + ########################################################################### # Separable design built ! - #------------------------- + # ------------------------ # # At this point we have a PBD on t*(q**2+q+1) points. Its blocks are # split into: @@ -1466,7 +1466,7 @@ def brouwer_separable_design(k,t,q,x,check=False,verbose=False,explain_construct # - blocks_of_size_q_plus_t : contains all t*(q**2+q+1)blocks of size q+t, # covering the same number of points: it is a # symmetric design. - ############################################################################### + ########################################################################### ############################################## # Part 2: Build an OA on t(q^2+q+1)+x points # diff --git a/src/sage/combinat/designs/resolvable_bibd.py b/src/sage/combinat/designs/resolvable_bibd.py index 27a5bdcae32..ccc11176d54 100644 --- a/src/sage/combinat/designs/resolvable_bibd.py +++ b/src/sage/combinat/designs/resolvable_bibd.py @@ -311,14 +311,14 @@ def kirkman_triple_system(v,existence=False): b.remove(8) X = sum(X, []) + [8] gdd4.relabel({v:i for i,v in enumerate(X)}) - gdd4 = gdd4.is_resolvable(True)[1] # the relabeled classes + gdd4 = gdd4.is_resolvable(True)[1] # the relabeled classes X = [B for B in gdd7 if 14 in B] for b in X: b.remove(14) X = sum(X, []) + [14] gdd7.relabel({v:i for i,v in enumerate(X)}) - gdd7 = gdd7.is_resolvable(True)[1] # the relabeled classes + gdd7 = gdd7.is_resolvable(True)[1] # the relabeled classes # The first parallel class contains 01(n'-1), the second contains # 23(n'-1), etc.. @@ -573,7 +573,7 @@ def PBD_4_7(v,check=True, existence=False): # On these groups a (15+7,{4,7})-PBD is pasted, in such a way that the 7 # new points are a set of the final PBD PBD22 = PBD_4_7(15+7) - S = next(SS for SS in PBD22 if len(SS) == 7) # a set of size 7 + S = next(SS for SS in PBD22 if len(SS) == 7) # a set of size 7 PBD22.relabel({v:i for i,v in enumerate([i for i in range(15+7) if i not in S] + S)}) for B in PBD22: @@ -741,19 +741,19 @@ def PBD_4_7_from_Y(gdd,check=True): raise RuntimeError("A group has size {} but I do not know how to " "build a ({},[4,7])-PBD".format(gs,3*gs+1)) - GDD = {} # the GDD we will need + GDD = {} # the GDD we will need if 4 in block_sizes: - #GDD[4] = GDD_from_BIBD(3*4,4) + # GDD[4] = GDD_from_BIBD(3*4,4) GDD[4] = group_divisible_design(3*4,K=[4],G=[3]) if 5 in block_sizes: - #GDD[5] = GDD_from_BIBD(3*5,4) + # GDD[5] = GDD_from_BIBD(3*5,4) GDD[5] = group_divisible_design(3*5,K=[4],G=[3]) if 7 in block_sizes: # It is obtained from a PBD_4_7(22) by removing a point only contained # in sets of size 4 GDD[7] = PBD_4_7(22) x = set(range(22)).difference(*[S for S in GDD[7] if len(S) != 4]).pop() - relabel = sum((S for S in GDD[7] if x in S),[]) # the groups must be 012,345,... + relabel = sum((S for S in GDD[7] if x in S),[]) # the groups must be 012,345,... relabel = [xx for xx in relabel if xx != x]+[x] GDD[7].relabel({v:i for i,v in enumerate(relabel)}) GDD[7] = [S for S in GDD[7] if 21 not in S] diff --git a/src/sage/combinat/designs/twographs.py b/src/sage/combinat/designs/twographs.py index 281f4fac153..131916b89c9 100644 --- a/src/sage/combinat/designs/twographs.py +++ b/src/sage/combinat/designs/twographs.py @@ -70,7 +70,7 @@ class TwoGraph(IncidenceStructure): :mod:`~sage.combinat.designs.twographs` module. """ def __init__(self, points=None, blocks=None, incidence_matrix=None, - name=None, check=False, copy=True): + name=None, check=False, copy=True): r""" Constructor of the class.