From 5a4d10877a5c6414a20d23fcc217872d6287ba27 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Mon, 8 Aug 2022 13:24:45 -0400 Subject: [PATCH 001/225] This is the initial commit, the covering array class was created with a few initial methods: is_covering_array and the init method, as well as that give its size n and k, its parameters t and v, and an ordering based on the lexicographic ordering of each row. --- src/sage/combinat/designs/covering_arrays.py | 158 +++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/sage/combinat/designs/covering_arrays.py diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py new file mode 100644 index 00000000000..e77e6fd537d --- /dev/null +++ b/src/sage/combinat/designs/covering_arrays.py @@ -0,0 +1,158 @@ +''' +An implementation of a Covering Array (CA) class for sagemath. +The initial commit will include the definition of the Covering Array class +and some basic methods to check and return the parameters n,k,v,t of the CA, +as well as an ordering based on the lexicographic ordering of each row. + +Later commits will include methods to create CAs from Perfect Hash Families +and Covering Perfect Hash Families (CPHF) as well as recursive methods. + +The Covering Array class may be used as a basis for an Orthogonal Array class +which will be implemented afterwards + +''' + +import itertools +import copy + +def is_covering_array(Array,v ,t): + ''' + Check if the tuple of tuples 'Array' is a Covering Array CA(n,k,v,t). + + A CA(n,k,v,t) is an n by k array with entries from a set of v elements + with the property that in every selection of t columns, each row + contains every sequence of t-elements at least once. + + + ''' + + tupledict={} + a=[ttuple for ttuple in itertools.product(GF(v),repeat=t)] + for item in a: + tupledict.update({item:0}) + for comb in itertools.combinations(range(len(Array[0])),t): + wdict=copy.deepcopy(tupledict) + for row in Array: + wdict[tuple([row[ti] for ti in comb])]+=1 + if 0 in wdict.values(): + return False + return True + +class CoveringArray(): + def __init__(self, Array, t=None, v=None): + #From the array input, grab the dimensions of the array + n=len(Array) + self.__n=n + k=len(Array[0]) + self.__k=k + + #Array input is a tuple of tuples, the first thing to do is to sort + #the tuples lexicographically increasing + + L=list(Array) + L.sort() + SortedArray=tuple(L) + self.__array=SortedArray + + for row in Array: + assert len(row)==len(Array[0]), "Not all rows have same length" + + + #If v is not inputted then the symbol set may be assumed from what + #symbols are in the array by flattening the Array and counting the + #number of unique entries. + if v==None: + v = len({x for l in Array for x in l}) + self.__v=v + + #If t is not inputted then try all t in {1,2,3...} until the array is + #not a covering array for that t + if t==None: + finished=False + t=1 + while finished==False: + if is_covering_array(Array, v ,t): + t+=1 + else: + t-=1 + finished=True + + #If t is given, make sure that t is the highest strength of the given + #Covering Array, that is the Covering Array is not strength t+1 + else: + finished=False + while finished==False: + if is_covering_array(Array, v ,t): + t+=1 + else: + t-=1 + finished=True + self.__t=t + + def n(self): + return self.__n + + def k(self): + return self.__k + + def v(self): + return self.__v + + def t(self): + return self.__t + + def ArrayRepresentation(self): + return self.__array + + + def __repr__(self): + """ + A print method + + EXAMPLES:: + + sage: CA = CoveringArray(5,4,2,2,[[1 , 1 , 1 , 0],[1 , 1 , 0 , 1],[1 , 0 , 1 , 1],[0 , 1 , 1 , 1],[0 , 0 , 0 , 0]]) + sage: CA + A 5 by 4 Covering Array of strength 2 with 2 levels + """ + return 'A {} by {} Covering Array of strength {} with {} levels'.format( + self.nrows, self.ncols, self.strength, self.levels) + + __str__=__repr__ + + def __eq__(self, other): + if self.ArrayRepresentation() == other.ArrayRepresentation(): + return True + else: + return False + + def __neq__(self, other): + if self.ArrayRepresentation() != other.ArrayRepresentation(): + return True + else: + return False + + def __lt__(self, other): + if self.ArrayRepresentation() < other.ArrayRepresentation(): + return True + else: + return False + + def __le__(self, other): + if self.ArrayRepresentation() <= other.ArrayRepresentation(): + return True + else: + return False + + def __gt__(self, other): + if self.ArrayRepresentation() > other.ArrayRepresentation(): + return True + else: + return False + + def __ge__(self, other): + if self.ArrayRepresentation() >= other.ArrayRepresentation(): + return True + else: + return False + \ No newline at end of file From 07a90dab973b019d44eda3f3fa59417d09763d85 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Mon, 8 Aug 2022 13:24:45 -0400 Subject: [PATCH 002/225] This is the initial commit, the covering array class was created with a few initial methods: is_covering_array and the init method, as well as that give its size n and k, its parameters t and v, and an ordering based on the lexicographic ordering of each row. --- src/sage/combinat/designs/covering_arrays.py | 158 +++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 src/sage/combinat/designs/covering_arrays.py diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py new file mode 100644 index 00000000000..e77e6fd537d --- /dev/null +++ b/src/sage/combinat/designs/covering_arrays.py @@ -0,0 +1,158 @@ +''' +An implementation of a Covering Array (CA) class for sagemath. +The initial commit will include the definition of the Covering Array class +and some basic methods to check and return the parameters n,k,v,t of the CA, +as well as an ordering based on the lexicographic ordering of each row. + +Later commits will include methods to create CAs from Perfect Hash Families +and Covering Perfect Hash Families (CPHF) as well as recursive methods. + +The Covering Array class may be used as a basis for an Orthogonal Array class +which will be implemented afterwards + +''' + +import itertools +import copy + +def is_covering_array(Array,v ,t): + ''' + Check if the tuple of tuples 'Array' is a Covering Array CA(n,k,v,t). + + A CA(n,k,v,t) is an n by k array with entries from a set of v elements + with the property that in every selection of t columns, each row + contains every sequence of t-elements at least once. + + + ''' + + tupledict={} + a=[ttuple for ttuple in itertools.product(GF(v),repeat=t)] + for item in a: + tupledict.update({item:0}) + for comb in itertools.combinations(range(len(Array[0])),t): + wdict=copy.deepcopy(tupledict) + for row in Array: + wdict[tuple([row[ti] for ti in comb])]+=1 + if 0 in wdict.values(): + return False + return True + +class CoveringArray(): + def __init__(self, Array, t=None, v=None): + #From the array input, grab the dimensions of the array + n=len(Array) + self.__n=n + k=len(Array[0]) + self.__k=k + + #Array input is a tuple of tuples, the first thing to do is to sort + #the tuples lexicographically increasing + + L=list(Array) + L.sort() + SortedArray=tuple(L) + self.__array=SortedArray + + for row in Array: + assert len(row)==len(Array[0]), "Not all rows have same length" + + + #If v is not inputted then the symbol set may be assumed from what + #symbols are in the array by flattening the Array and counting the + #number of unique entries. + if v==None: + v = len({x for l in Array for x in l}) + self.__v=v + + #If t is not inputted then try all t in {1,2,3...} until the array is + #not a covering array for that t + if t==None: + finished=False + t=1 + while finished==False: + if is_covering_array(Array, v ,t): + t+=1 + else: + t-=1 + finished=True + + #If t is given, make sure that t is the highest strength of the given + #Covering Array, that is the Covering Array is not strength t+1 + else: + finished=False + while finished==False: + if is_covering_array(Array, v ,t): + t+=1 + else: + t-=1 + finished=True + self.__t=t + + def n(self): + return self.__n + + def k(self): + return self.__k + + def v(self): + return self.__v + + def t(self): + return self.__t + + def ArrayRepresentation(self): + return self.__array + + + def __repr__(self): + """ + A print method + + EXAMPLES:: + + sage: CA = CoveringArray(5,4,2,2,[[1 , 1 , 1 , 0],[1 , 1 , 0 , 1],[1 , 0 , 1 , 1],[0 , 1 , 1 , 1],[0 , 0 , 0 , 0]]) + sage: CA + A 5 by 4 Covering Array of strength 2 with 2 levels + """ + return 'A {} by {} Covering Array of strength {} with {} levels'.format( + self.nrows, self.ncols, self.strength, self.levels) + + __str__=__repr__ + + def __eq__(self, other): + if self.ArrayRepresentation() == other.ArrayRepresentation(): + return True + else: + return False + + def __neq__(self, other): + if self.ArrayRepresentation() != other.ArrayRepresentation(): + return True + else: + return False + + def __lt__(self, other): + if self.ArrayRepresentation() < other.ArrayRepresentation(): + return True + else: + return False + + def __le__(self, other): + if self.ArrayRepresentation() <= other.ArrayRepresentation(): + return True + else: + return False + + def __gt__(self, other): + if self.ArrayRepresentation() > other.ArrayRepresentation(): + return True + else: + return False + + def __ge__(self, other): + if self.ArrayRepresentation() >= other.ArrayRepresentation(): + return True + else: + return False + \ No newline at end of file From da2022ea7b817beec4d9b766e657bc87cbf457a3 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Mon, 10 Oct 2022 15:15:54 -0400 Subject: [PATCH 003/225] added comments to covering array file, still to add examples --- src/sage/combinat/designs/covering_arrays.py | 437 ++++++++++++++++--- 1 file changed, 383 insertions(+), 54 deletions(-) diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py index e77e6fd537d..6005388ad4b 100644 --- a/src/sage/combinat/designs/covering_arrays.py +++ b/src/sage/combinat/designs/covering_arrays.py @@ -1,8 +1,31 @@ -''' -An implementation of a Covering Array (CA) class for sagemath. -The initial commit will include the definition of the Covering Array class -and some basic methods to check and return the parameters n,k,v,t of the CA, -as well as an ordering based on the lexicographic ordering of each row. + +""" +Covering Arrays + +A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a +set of v elements with theproperty that in every selection of t columns, each +row contains every sequence of t-elements at least once. + +An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the property +that each row contains every sequence of t-elements exactly once + +REFERENCES: + +- reference 1 + +- reference 2 + +AUTHORS: + +- Aaron Dwyer and brett stevens + +.. NOTES:: + +This is a work in progress, it will be an implementation of a Covering Array (CA) +class for sagemath. The initial commit will include the definition of the +Covering Array class and some basic methods to check and return the parameters +N,k,v,t of the CA, as well as an ordering based on the lexicographic ordering +of each row. Later commits will include methods to create CAs from Perfect Hash Families and Covering Perfect Hash Families (CPHF) as well as recursive methods. @@ -10,39 +33,130 @@ The Covering Array class may be used as a basis for an Orthogonal Array class which will be implemented afterwards -''' +""" import itertools import copy -def is_covering_array(Array,v ,t): - ''' - Check if the tuple of tuples 'Array' is a Covering Array CA(n,k,v,t). - - A CA(n,k,v,t) is an n by k array with entries from a set of v elements - with the property that in every selection of t columns, each row - contains every sequence of t-elements at least once. - - - ''' - - tupledict={} - a=[ttuple for ttuple in itertools.product(GF(v),repeat=t)] - for item in a: - tupledict.update({item:0}) - for comb in itertools.combinations(range(len(Array[0])),t): - wdict=copy.deepcopy(tupledict) - for row in Array: - wdict[tuple([row[ti] for ti in comb])]+=1 - if 0 in wdict.values(): - return False - return True +def is_covering_array(Array,levels,strength): + """ + Input is a tuple of tuples called 'Array' that represents a N x k array, + and integers ``levels`` and ``strength`` which represent the desired + covering arrays values for v and t respectively. + + Checks if 'Array' with given parameters is a Covering Array CA(n,k,v,t) + and outputs True or False. + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: is_covering_array(C,2,2) + True + sage: is_covering_array(C,2,3) + False + + """ + tupledict={} + a=[ttuple for ttuple in itertools.product(GF(levels),repeat=strength)] + for item in a: + tupledict.update({item:0}) + for comb in itertools.combinations(range(len(Array[0])),strength): + wdict=copy.deepcopy(tupledict) + for row in Array: + wdict[tuple([row[ti] for ti in comb])]+=1 + if 0 in wdict.values(): + return False + return True class CoveringArray(): - def __init__(self, Array, t=None, v=None): + """ + A class for covering array objects. The objects will contain the array + itself and its paramters v, and t + + INPUT: + + -``Array`` -- The N x k array itself. This is stored as a tuple of tuples. + the N and k parameters are derived from this inputted array + + -``strength`` -- The parameter t, such that in any selection of t columns + of the array, every t tuple appears at least once. + + If a covering array has strength t, it also has strength t-1,t-2...1. So + we wish to only store the maximum strength of the given covering array, so + the class automatically checks if the CA(N,K,v,t) is a CA(N,k,v,t+1) until + it finds the maximum t + + -----------------all arrays are CA t=1??------ + + -``levels`` -- The paramter v, such that v is the size of the symbol set + of the array. + + If no such symbol set or size is given, then a v will be assumed by + counting how many unique elements appear in the array. + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C= ((0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,1), + (1,1,1,0,1,0,0,0,0,1), + (1,0,1,1,0,1,0,1,0,0), + (1,0,0,0,1,1,1,0,0,0), + (0,1,1,0,0,1,0,0,1,0), + (0,0,1,0,1,0,1,1,1,0), + (1,1,0,1,0,0,1,0,1,0), + (0,0,0,1,1,1,0,0,1,1), + (0,0,1,1,0,0,1,0,0,1), + (0,1,0,1,1,0,0,1,0,0), + (1,0,0,0,0,0,0,1,1,1), + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,2,3) + A 5 by 4 Covering Array of strength 3 with 2 levels + """ + def __init__(self, Array, strength=None, levels=None): + """ + Constructor function + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C= ((0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,1), + (1,1,1,0,1,0,0,0,0,1), + (1,0,1,1,0,1,0,1,0,0), + (1,0,0,0,1,1,1,0,0,0), + (0,1,1,0,0,1,0,0,1,0), + (0,0,1,0,1,0,1,1,1,0), + (1,1,0,1,0,0,1,0,1,0), + (0,0,0,1,1,1,0,0,1,1), + (0,0,1,1,0,0,1,0,0,1), + (0,1,0,1,1,0,0,1,0,0), + (1,0,0,0,0,0,0,1,1,1), + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,2,3) + A 5 by 4 Covering Array of strength 3 with 2 levels + """ #From the array input, grab the dimensions of the array - n=len(Array) - self.__n=n + N=len(Array) + self.__n=N k=len(Array[0]) self.__k=k @@ -61,20 +175,20 @@ def __init__(self, Array, t=None, v=None): #If v is not inputted then the symbol set may be assumed from what #symbols are in the array by flattening the Array and counting the #number of unique entries. - if v==None: - v = len({x for l in Array for x in l}) - self.__v=v + if levels==None: + levels = len({x for l in Array for x in l}) + self.__v=levels #If t is not inputted then try all t in {1,2,3...} until the array is #not a covering array for that t - if t==None: + if strength==None: finished=False - t=1 + strength=1 while finished==False: - if is_covering_array(Array, v ,t): - t+=1 + if is_covering_array(Array, levels ,strength): + strength+=1 else: - t-=1 + strength-=1 finished=True #If t is given, make sure that t is the highest strength of the given @@ -82,75 +196,290 @@ def __init__(self, Array, t=None, v=None): else: finished=False while finished==False: - if is_covering_array(Array, v ,t): - t+=1 + if is_covering_array(Array, levels ,strength): + strength+=1 else: - t-=1 + strength-=1 finished=True - self.__t=t + self.__t=strength - def n(self): + def numrows(self): + """ + Method that returns the number of rows, N, of the covering array + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CA=CoveringArray(C,2,2) + sage: CA.numrows() + 5 + """ return self.__n - def k(self): + def numcols(self): + """ + Method that returns the number of columns, k, of the covering array + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CA=CoveringArray(C,2,2) + sage: CA.numcols() + 4 + """ return self.__k - def v(self): + def levels(self): + """ + Method that returns the number of levels for the covering array, which + is the paramter v, such that v is the size of the symbol set of the + array. + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CA=CoveringArray(C,2,2) + sage: CA.levels() + 2 + """ return self.__v - def t(self): + def strength(self): + """ + Method that returns the strength of the covering array, which is the + paramter t, such that in any selection of t columns of the array, + every t tuple appears at least once. + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CA=CoveringArray(C,2,2) + sage: CA.strength() + 2 + """ return self.__t - def ArrayRepresentation(self): + def array_representation(self): + """ + Method that returns the covering array as a tuple of tuples, but where + the output is such that each row of the array is sorted in + lexicographic order + + EXAMPLES:: + + sage: C = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + sage: CA=CoveringArray(C,2,2) + sage: CA.array_representation() + ((0,0,0,0),(0,1,1,1),(1,0,1,1),(1,1,0,1),(1,1,1,0)) + + """ return self.__array def __repr__(self): """ - A print method - EXAMPLES:: - - sage: CA = CoveringArray(5,4,2,2,[[1 , 1 , 1 , 0],[1 , 1 , 0 , 1],[1 , 0 , 1 , 1],[0 , 1 , 1 , 1],[0 , 0 , 0 , 0]]) - sage: CA - A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C= ((0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,1), + (1,1,1,0,1,0,0,0,0,1), + (1,0,1,1,0,1,0,1,0,0), + (1,0,0,0,1,1,1,0,0,0), + (0,1,1,0,0,1,0,0,1,0), + (0,0,1,0,1,0,1,1,1,0), + (1,1,0,1,0,0,1,0,1,0), + (0,0,0,1,1,1,0,0,1,1), + (0,0,1,1,0,0,1,0,0,1), + (0,1,0,1,1,0,0,1,0,0), + (1,0,0,0,0,0,0,1,1,1), + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,2,3) + A 5 by 4 Covering Array of strength 3 with 2 levels """ return 'A {} by {} Covering Array of strength {} with {} levels'.format( self.nrows, self.ncols, self.strength, self.levels) __str__=__repr__ + def __eq__(self, other): + """ + A method that desrcibes whether two covering arrays are equal by + considering the array with rows sorted in lexicographic order + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + sage: C2 = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,1), + (1,1,1,0,1,0,0,0,0,1), + (1,0,1,1,0,1,0,1,0,0), + (1,0,0,0,1,1,1,0,0,0), + (0,1,1,0,0,1,0,0,1,0), + (0,0,1,0,1,0,1,1,1,0), + (1,1,0,1,0,0,1,0,1,0), + (0,0,0,1,1,1,0,0,1,1), + (0,0,1,1,0,0,1,0,0,1), + (0,1,0,1,1,0,0,1,0,0), + (1,0,0,0,0,0,0,1,1,1), + (0,1,0,0,0,1,1,1,0,1)) + sage: C1=C2 + True + sage: C1=C3 + False + """ if self.ArrayRepresentation() == other.ArrayRepresentation(): return True else: return False def __neq__(self, other): + """ + A method that desrcibes whether two covering arrays are not equal by + considering the array with rows sorted in lexicographic order + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + sage: C2 = ((1,1,1,0), + (1,1,0,1), + (1,0,1,1), + (0,1,1,1), + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0), + (1,1,1,1,1,1,1,1,1,1), + (1,1,1,0,1,0,0,0,0,1), + (1,0,1,1,0,1,0,1,0,0), + (1,0,0,0,1,1,1,0,0,0), + (0,1,1,0,0,1,0,0,1,0), + (0,0,1,0,1,0,1,1,1,0), + (1,1,0,1,0,0,1,0,1,0), + (0,0,0,1,1,1,0,0,1,1), + (0,0,1,1,0,0,1,0,0,1), + (0,1,0,1,1,0,0,1,0,0), + (1,0,0,0,0,0,0,1,1,1), + (0,1,0,0,0,1,1,1,0,1)) + sage: C1!=C2 + False + sage: C1!=C3 + True + """ if self.ArrayRepresentation() != other.ArrayRepresentation(): return True else: return False def __lt__(self, other): + """ + A method that desrcibes whether one covering array is less than another + based on the lexicographic order on the rows + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + + """ if self.ArrayRepresentation() < other.ArrayRepresentation(): return True else: return False def __le__(self, other): + """ + A method that desrcibes whether one covering array is less than or + equal to another based on the lexicographic order on the rows + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + + """ if self.ArrayRepresentation() <= other.ArrayRepresentation(): return True else: return False def __gt__(self, other): + """ + A method that desrcibes whether one covering array is greater than + another based on the lexicographic order on the rows + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + + """ if self.ArrayRepresentation() > other.ArrayRepresentation(): return True else: return False + + (0,1,0,0) + + (1,0) + def __ge__(self, other): + """ + A method that desrcibes whether one covering array is greater than or + equal to another based on the lexicographic order on the rows + + EXMAPLES:: + sage: C1 = ((1,1,1,0), + (0,0,0,0), + (1,0,1,1), + (1,1,0,1), + (0,1,1,1),) + + """ if self.ArrayRepresentation() >= other.ArrayRepresentation(): return True else: From 8e4aec57f2dd3164e347b55c036cbfa3432df953 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Mon, 10 Oct 2022 15:13:47 -0400 Subject: [PATCH 004/225] Created py file for basic CA generation methods, will not be used in first push so put it in new branch --- src/sage/combinat/designs/covering_array_methods.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/sage/combinat/designs/covering_array_methods.py diff --git a/src/sage/combinat/designs/covering_array_methods.py b/src/sage/combinat/designs/covering_array_methods.py new file mode 100644 index 00000000000..9daeafb9864 --- /dev/null +++ b/src/sage/combinat/designs/covering_array_methods.py @@ -0,0 +1 @@ +test From bb509f2a8f4f0fabb305241252af7bc845834b86 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 11 Oct 2022 14:45:37 -0400 Subject: [PATCH 005/225] finished the strength 2 construction --- .../designs/covering_array_methods.py | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_array_methods.py b/src/sage/combinat/designs/covering_array_methods.py index 9daeafb9864..4cd2492e783 100644 --- a/src/sage/combinat/designs/covering_array_methods.py +++ b/src/sage/combinat/designs/covering_array_methods.py @@ -1 +1,31 @@ -test +import itertools +import math + +def tuple_weight(t): + ''' + given a tuple t returns the integer sum of all of its values + ''' + ctr=0 + for i in t: + ctr+=i + return ctr + +def Strength2(n): + ''' + Given an integer n, returns a binary covering array with strength 2 + To do this we form a matrix represented as a tuple of tuples where the + columns are all binary n-tuples of weight ceiling(n/2) that have 0 + in 1st position + + Reference is Combinatorial aspects... + ''' + resulttupleT=() + x = [0,1] + for p in itertools.product(x, repeat=n-1): + if tuple_weight(p)==math.ceil(n/2): + column=(0,)+p + resulttupleT+=(column,) + M=Matrix(resulttupleT) + M1=M.transpose() + return(tuple(M1)) + From 8ec7c1d05624bab7e3719c94f70422f9a9af8dd2 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 29 Nov 2022 15:36:56 -0500 Subject: [PATCH 006/225] Added some methods namely pprint and __hash, edited/added doctests some of which are not yet working --- .../designs/covering_array_methods.py | 42 +- src/sage/combinat/designs/covering_arrays.py | 693 ++++++++++++------ 2 files changed, 491 insertions(+), 244 deletions(-) diff --git a/src/sage/combinat/designs/covering_array_methods.py b/src/sage/combinat/designs/covering_array_methods.py index 4cd2492e783..be9defbe7c6 100644 --- a/src/sage/combinat/designs/covering_array_methods.py +++ b/src/sage/combinat/designs/covering_array_methods.py @@ -10,8 +10,9 @@ def tuple_weight(t): ctr+=i return ctr -def Strength2(n): +def Kleitman_Specer_Katona(n): #Kleitman and Spencer [76] and Katona ''' + Given an integer n, returns a binary covering array with strength 2 To do this we form a matrix represented as a tuple of tuples where the columns are all binary n-tuples of weight ceiling(n/2) that have 0 @@ -29,3 +30,42 @@ def Strength2(n): M1=M.transpose() return(tuple(M1)) +def LFSR_for_strength3(n,p): + r""" + Returns a matrix that represents a CA() + + This method forms a sequence of entries of the ring GF(p) by using LFSR, + where the expression is given by the coeffients of the irreducible + polynomial of degree n with coefficients in GF(p). We form the circulant + matrix of the sequence and the reverse sequence, and remove the last + p^2+p+1 columns. The result is a covering array + """ + + R=PolynomialRing(GF(p),x) + #find the irreducible polynomial degree n + irr=R.irreducible_element(n) + #we want to use coefficients of irr poly and solve for the coeff for the + #highest order term, this is done by taking the inverse of everything and + #then dropping the first term + a=[j:=-i for i in irr] + a.pop() + #for use of sages LFSR we set the fill to be all 0s except the first term + fill=[0]*(n-1) + fill.insert(0,1) + #and the key is the expression from the coefficients found above + key=a + k=(p**n)-1 #the number of columns to be created + LSFRseq = lfsr_sequence(key,fill,k) + #We create a deep copy of this sequence so we can reverse it + LSFRrevseq = copy.deepcopy(L1) + LSFRrevseq.reverse() + #The array will be formed by the circ matrix of each sequence, plus the + #all zero row at the end + M=block_matrix(3,[matrix.circulant(LSFRseq),matrix.circulant(LSFRrevseq) + ,matrix(GF(3),[0]*k)]) + #We then delete the excess columns to obtain the CA + M=M.delete_columns([i for i in range (k-(p*p+p+1),k)]) + M2=[] + for i in M: + M2.append(tuple(i)) + return tuple(M2) \ No newline at end of file diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py index 6005388ad4b..5d24c8c6b19 100644 --- a/src/sage/combinat/designs/covering_arrays.py +++ b/src/sage/combinat/designs/covering_arrays.py @@ -1,64 +1,144 @@ - -""" -Covering Arrays +r""" +Covering Arrays (CA) A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a set of v elements with theproperty that in every selection of t columns, each row contains every sequence of t-elements at least once. -An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the property -that each row contains every sequence of t-elements exactly once +An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the +property that each row contains every sequence of t-elements exactly once REFERENCES: -- reference 1 +.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. + +.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. -- reference 2 +.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 AUTHORS: -- Aaron Dwyer and brett stevens +- Aaron Dwyer and brett stevens (2022): initial version .. NOTES:: -This is a work in progress, it will be an implementation of a Covering Array (CA) -class for sagemath. The initial commit will include the definition of the -Covering Array class and some basic methods to check and return the parameters -N,k,v,t of the CA, as well as an ordering based on the lexicographic ordering -of each row. +This is a work in progress, it will be an implementation of a Covering Array +(CA) class for sagemath. The initial commit will include the definition of +the Covering Array class and some basic methods to check and return the +parameters N,k,v,t of the CA, as well as an ordering based on the +lexicographic ordering of each row. -Later commits will include methods to create CAs from Perfect Hash Families -and Covering Perfect Hash Families (CPHF) as well as recursive methods. +Later commits will include methods to create CAs from Linear Feedback Shift +Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families +(CPHF) as well as recursive methods. The Covering Array class may be used as a basis for an Orthogonal Array class which will be implemented afterwards +Classes and methods +------------------- """ +# **************************************************************************** +# Copyright (C) 2022 Aaron Dwyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.rings.finite_rings.finite_field_constructor import GF import itertools import copy def is_covering_array(Array,levels,strength): - """ - Input is a tuple of tuples called 'Array' that represents a N x k array, - and integers ``levels`` and ``strength`` which represent the desired - covering arrays values for v and t respectively. + r""" + Check whether the tuple of tuples in ``Array`` forms a covering array. - Checks if 'Array' with given parameters is a Covering Array CA(n,k,v,t) - and outputs True or False. + INPUT: + + - ``Array`` - a tuple of tuples that represents a N x k array + - ``levels`` - positive integer representing the v value of the CA + - ``strength`` - positive integer representing the t value of the CA + + OUTPUT: + + A boolean representing if the input is a covering array or not EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), - (0,0,0,0)) + sage: from sage.combinat.designs.covering_arrays import is_covering_array + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: D = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) sage: is_covering_array(C,2,2) True sage: is_covering_array(C,2,3) False - + sage: is_covering_array(D,3,3) + True """ tupledict={} a=[ttuple for ttuple in itertools.product(GF(levels),repeat=strength)] @@ -73,87 +153,118 @@ def is_covering_array(Array,levels,strength): return True class CoveringArray(): - """ - A class for covering array objects. The objects will contain the array - itself and its paramters v, and t + r""" + Covering Array (CA) INPUT: - -``Array`` -- The N x k array itself. This is stored as a tuple of tuples. - the N and k parameters are derived from this inputted array - - -``strength`` -- The parameter t, such that in any selection of t columns - of the array, every t tuple appears at least once. - - If a covering array has strength t, it also has strength t-1,t-2...1. So - we wish to only store the maximum strength of the given covering array, so - the class automatically checks if the CA(N,K,v,t) is a CA(N,k,v,t+1) until - it finds the maximum t + - ``Array`` -- The N by k array itself stored as a tuple of tuples. + The N and k parameters are derived from this inputted array - -----------------all arrays are CA t=1??------ + - ``strength`` -- The parameter t, such that in any selection of t columns + of the array, every t tuple appears at least once. If ``None`` then the + maxiumum t is found by iterating from t=0 until array is not a CA with + strength t+1. - -``levels`` -- The paramter v, such that v is the size of the symbol set - of the array. - - If no such symbol set or size is given, then a v will be assumed by - counting how many unique elements appear in the array. + - ``levels`` -- The paramter v, such that v is the size of the symbol set + of the array. If ``None`` then a v will be assumed by counting number of + unique elements appear in the array. EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), - (0,0,0,0)) + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) sage: CoveringArray(C,strength=2) A 5 by 4 Covering Array of strength 2 with 2 levels - sage: C= ((0,0,0,0,0,0,0,0,0,0), - (1,1,1,1,1,1,1,1,1,1), - (1,1,1,0,1,0,0,0,0,1), - (1,0,1,1,0,1,0,1,0,0), - (1,0,0,0,1,1,1,0,0,0), - (0,1,1,0,0,1,0,0,1,0), - (0,0,1,0,1,0,1,1,1,0), - (1,1,0,1,0,0,1,0,1,0), - (0,0,0,1,1,1,0,0,1,1), - (0,0,1,1,0,0,1,0,0,1), - (0,1,0,1,1,0,0,1,0,0), - (1,0,0,0,0,0,0,1,1,1), - (0,1,0,0,0,1,1,1,0,1)) + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) sage: CoveringArray(C,2,3) A 5 by 4 Covering Array of strength 3 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + A 7 by 15 Covering Array of strength 2 with 2 levels + """ def __init__(self, Array, strength=None, levels=None): - """ + r""" Constructor function EXAMPLES:: - - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) sage: CoveringArray(C,strength=2) A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C= ((0,0,0,0,0,0,0,0,0,0), - (1,1,1,1,1,1,1,1,1,1), - (1,1,1,0,1,0,0,0,0,1), - (1,0,1,1,0,1,0,1,0,0), - (1,0,0,0,1,1,1,0,0,0), - (0,1,1,0,0,1,0,0,1,0), - (0,0,1,0,1,0,1,1,1,0), - (1,1,0,1,0,0,1,0,1,0), - (0,0,0,1,1,1,0,0,1,1), - (0,0,1,1,0,0,1,0,0,1), - (0,1,0,1,1,0,0,1,0,0), - (1,0,0,0,0,0,0,1,1,1), - (0,1,0,0,0,1,1,1,0,1)) + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) sage: CoveringArray(C,2,3) A 5 by 4 Covering Array of strength 3 with 2 levels - """ + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + A 7 by 15 Covering Array of strength 2 with 2 levels + + """ #From the array input, grab the dimensions of the array N=len(Array) self.__n=N @@ -204,91 +315,91 @@ def __init__(self, Array, strength=None, levels=None): self.__t=strength def numrows(self): - """ - Method that returns the number of rows, N, of the covering array + r""" + Return the number of rows, N, of the covering array EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: CA=CoveringArray(C,2,2) + sage: CA = CoveringArray(C,2,2) sage: CA.numrows() 5 """ return self.__n def numcols(self): - """ - Method that returns the number of columns, k, of the covering array + r""" + Returns the number of columns, k, of the covering array EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: CA=CoveringArray(C,2,2) + sage: CA = CoveringArray(C,2,2) sage: CA.numcols() 4 """ return self.__k def levels(self): - """ - Method that returns the number of levels for the covering array, which - is the paramter v, such that v is the size of the symbol set of the + r""" + Return the number of levels for the covering array, which is + the paramter v, such that v is the size of the symbol set of the array. EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: CA=CoveringArray(C,2,2) + sage: CA = CoveringArray(C,2,2) sage: CA.levels() 2 """ return self.__v def strength(self): - """ - Method that returns the strength of the covering array, which is the - paramter t, such that in any selection of t columns of the array, - every t tuple appears at least once. + r""" + Return the strength of the covering array, which is the paramter + t, such that in any selection of t columns of the array, every + t tuple appears at least once. EXAMPLES:: - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: CA=CoveringArray(C,2,2) + sage: CA = CoveringArray(C,2,2) sage: CA.strength() 2 """ return self.__t def array_representation(self): - """ - Method that returns the covering array as a tuple of tuples, but where + r""" + Return the covering array as a tuple of tuples, but where the output is such that each row of the array is sorted in lexicographic order EXAMPLES:: - sage: C = ((1,1,1,0), - (0,0,0,0), - (1,0,1,1), - (1,1,0,1), + sage: C = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ (0,1,1,1),) - sage: CA=CoveringArray(C,2,2) + sage: CA = CoveringArray(C,2,2) sage: CA.array_representation() ((0,0,0,0),(0,1,1,1),(1,0,1,1),(1,1,0,1),(1,1,1,0)) @@ -297,191 +408,287 @@ def array_representation(self): def __repr__(self): - """ + r""" + Returns a string that describes self + EXAMPLES:: - - sage: C = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) sage: CoveringArray(C,strength=2) A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C= ((0,0,0,0,0,0,0,0,0,0), - (1,1,1,1,1,1,1,1,1,1), - (1,1,1,0,1,0,0,0,0,1), - (1,0,1,1,0,1,0,1,0,0), - (1,0,0,0,1,1,1,0,0,0), - (0,1,1,0,0,1,0,0,1,0), - (0,0,1,0,1,0,1,1,1,0), - (1,1,0,1,0,0,1,0,1,0), - (0,0,0,1,1,1,0,0,1,1), - (0,0,1,1,0,0,1,0,0,1), - (0,1,0,1,1,0,0,1,0,0), - (1,0,0,0,0,0,0,1,1,1), - (0,1,0,0,0,1,1,1,0,1)) + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) sage: CoveringArray(C,2,3) A 5 by 4 Covering Array of strength 3 with 2 levels - """ + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + A 7 by 15 Covering Array of strength 2 with 2 levels + + """ return 'A {} by {} Covering Array of strength {} with {} levels'.format( - self.nrows, self.ncols, self.strength, self.levels) + self.numrows(), self.numcols(), self.strength(), self.levels()) __str__=__repr__ + def pprint(self): + r""" + Prints the covering array in a format easy for users to read + + EXAMPLES:: + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.pprint() + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) + """ + for i in self.__array: + print(str(i)) + + def __hash__(self): + r""" + Hashs the tuple of tuples and all tuples inside + + EXAMPLES:: - def __eq__(self, other): + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.pprint() + sage: hash(CA) + -2522140066511050633 """ - A method that desrcibes whether two covering arrays are equal by - considering the array with rows sorted in lexicographic order - - EXMAPLES:: - sage: C1 = ((1,1,1,0), - (0,0,0,0), - (1,0,1,1), - (1,1,0,1), - (0,1,1,1),) - sage: C2 = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + return hash((self.array_representation(),self.strength(),self.levels())) + + def __eq__(self, other): + r""" + Return whether two covering arrays are equal by considering the + array with rows sorted in lexicographic order + + EXAMPLES:: + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),\ + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0), - (1,1,1,1,1,1,1,1,1,1), - (1,1,1,0,1,0,0,0,0,1), - (1,0,1,1,0,1,0,1,0,0), - (1,0,0,0,1,1,1,0,0,0), - (0,1,1,0,0,1,0,0,1,0), - (0,0,1,0,1,0,1,1,1,0), - (1,1,0,1,0,0,1,0,1,0), - (0,0,0,1,1,1,0,0,1,1), - (0,0,1,1,0,0,1,0,0,1), - (0,1,0,1,1,0,0,1,0,0), - (1,0,0,0,0,0,0,1,1,1), + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: C1=C2 + sage: C1==C2 True - sage: C1=C3 + sage: C1==C3 False """ - if self.ArrayRepresentation() == other.ArrayRepresentation(): + if self.array_representation() == other.array_representation(): return True else: return False def __neq__(self, other): - """ - A method that desrcibes whether two covering arrays are not equal by - considering the array with rows sorted in lexicographic order - - EXMAPLES:: - sage: C1 = ((1,1,1,0), - (0,0,0,0), - (1,0,1,1), - (1,1,0,1), + r""" + Return whether two covering arrays are not equal by considering + the array with rows sorted in lexicographic order + + EXAMPLES:: + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ (0,1,1,1),) - sage: C2 = ((1,1,1,0), - (1,1,0,1), - (1,0,1,1), - (0,1,1,1), + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0), - (1,1,1,1,1,1,1,1,1,1), - (1,1,1,0,1,0,0,0,0,1), - (1,0,1,1,0,1,0,1,0,0), - (1,0,0,0,1,1,1,0,0,0), - (0,1,1,0,0,1,0,0,1,0), - (0,0,1,0,1,0,1,1,1,0), - (1,1,0,1,0,0,1,0,1,0), - (0,0,0,1,1,1,0,0,1,1), - (0,0,1,1,0,0,1,0,0,1), - (0,1,0,1,1,0,0,1,0,0), - (1,0,0,0,0,0,0,1,1,1), + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) sage: C1!=C2 False sage: C1!=C3 True """ - if self.ArrayRepresentation() != other.ArrayRepresentation(): + if self.array_representation() != other.array_representation(): return True else: return False def __lt__(self, other): - """ - A method that desrcibes whether one covering array is less than another + r""" + Return whether one covering array is less than another based on the lexicographic order on the rows - EXMAPLES:: - sage: C1 = ((1,1,1,0), - (0,0,0,0), - (1,0,1,1), - (1,1,0,1), + EXAMPLES:: + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ (0,1,1,1),) - + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1CA2 + False """ - if self.ArrayRepresentation() > other.ArrayRepresentation(): + if self.array_representation() > other.array_representation(): return True else: return False - - (0,1,0,0) - - (1,0) - def __ge__(self, other): - """ - A method that desrcibes whether one covering array is greater than or + r""" + Return whether one covering array is greater than or equal to another based on the lexicographic order on the rows - EXMAPLES:: - sage: C1 = ((1,1,1,0), - (0,0,0,0), - (1,0,1,1), - (1,1,0,1), + EXAMPLES:: + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ (0,1,1,1),) - + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1>=CA2 + False """ - if self.ArrayRepresentation() >= other.ArrayRepresentation(): + if self.array_representation() >= other.array_representation(): return True else: - return False - \ No newline at end of file + return False \ No newline at end of file From 514e3634d6971a1e70087ad28b16635561187a65 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Wed, 14 Dec 2022 23:49:17 -0500 Subject: [PATCH 007/225] Ensured all the doctests are working. --- src/sage/combinat/designs/covering_arrays.py | 62 +++++++++++++++----- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py index 5d24c8c6b19..93a56969f06 100644 --- a/src/sage/combinat/designs/covering_arrays.py +++ b/src/sage/combinat/designs/covering_arrays.py @@ -194,8 +194,8 @@ class CoveringArray(): (0,1,0,1,1,0,0,1,0,0),\ (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,2,3) - A 5 by 4 Covering Array of strength 3 with 2 levels + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -213,6 +213,7 @@ class CoveringArray(): (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) A 7 by 15 Covering Array of strength 2 with 2 levels """ @@ -222,6 +223,7 @@ def __init__(self, Array, strength=None, levels=None): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -243,8 +245,8 @@ def __init__(self, Array, strength=None, levels=None): (0,1,0,1,1,0,0,1,0,0),\ (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,2,3) - A 5 by 4 Covering Array of strength 3 with 2 levels + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -262,6 +264,7 @@ def __init__(self, Array, strength=None, levels=None): (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) A 7 by 15 Covering Array of strength 2 with 2 levels """ @@ -319,7 +322,8 @@ def numrows(self): Return the number of rows, N, of the covering array EXAMPLES:: - + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -336,7 +340,8 @@ def numcols(self): Returns the number of columns, k, of the covering array EXAMPLES:: - + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -356,6 +361,7 @@ def levels(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -375,6 +381,7 @@ def strength(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -394,6 +401,7 @@ def array_representation(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -401,7 +409,7 @@ def array_representation(self): (0,1,1,1),) sage: CA = CoveringArray(C,2,2) sage: CA.array_representation() - ((0,0,0,0),(0,1,1,1),(1,0,1,1),(1,1,0,1),(1,1,1,0)) + ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) """ return self.__array @@ -413,6 +421,7 @@ def __repr__(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -434,8 +443,8 @@ def __repr__(self): (0,1,0,1,1,0,0,1,0,0),\ (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,2,3) - A 5 by 4 Covering Array of strength 3 with 2 levels + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -453,8 +462,10 @@ def __repr__(self): (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) A 7 by 15 Covering Array of strength 2 with 2 levels + """ return 'A {} by {} Covering Array of strength {} with {} levels'.format( self.numrows(), self.numcols(), self.strength(), self.levels()) @@ -467,6 +478,7 @@ def pprint(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -493,6 +505,7 @@ def __hash__(self): EXAMPLES:: + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -501,7 +514,6 @@ def __hash__(self): (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA = CoveringArray(C,2,2) - sage: CA.pprint() sage: hash(CA) -2522140066511050633 """ @@ -513,11 +525,13 @@ def __eq__(self, other): array with rows sorted in lexicographic order EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ (1,1,0,1),\ - (0,1,1,1),\ + (0,1,1,1)) sage: C2 = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -536,9 +550,12 @@ def __eq__(self, other): (0,1,0,1,1,0,0,1,0,0),\ (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: C1==C2 + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1==CA2 True - sage: C1==C3 + sage: CA1==CA3 False """ if self.array_representation() == other.array_representation(): @@ -552,11 +569,13 @@ def __neq__(self, other): the array with rows sorted in lexicographic order EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ (1,1,0,1),\ - (0,1,1,1),) + (0,1,1,1)) sage: C2 = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -575,9 +594,12 @@ def __neq__(self, other): (0,1,0,1,1,0,0,1,0,0),\ (1,0,0,0,0,0,0,1,1,1),\ (0,1,0,0,0,1,1,1,0,1)) - sage: C1!=C2 + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1!=CA2 False - sage: C1!=C3 + sage: CA1!=CA3 True """ if self.array_representation() != other.array_representation(): @@ -591,6 +613,8 @@ def __lt__(self, other): based on the lexicographic order on the rows EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -618,6 +642,8 @@ def __le__(self, other): equal to another based on the lexicographic order on the rows EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -645,6 +671,8 @@ def __gt__(self, other): another based on the lexicographic order on the rows EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -672,6 +700,8 @@ def __ge__(self, other): equal to another based on the lexicographic order on the rows EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ From 337a825fa8cbf26b1282170e70e7338cefff82fb Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Thu, 15 Dec 2022 11:07:18 -0500 Subject: [PATCH 008/225] removed covering array file temporarily --- src/sage/combinat/designs/covering_arrays.py | 724 ------------------- 1 file changed, 724 deletions(-) delete mode 100644 src/sage/combinat/designs/covering_arrays.py diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py deleted file mode 100644 index 93a56969f06..00000000000 --- a/src/sage/combinat/designs/covering_arrays.py +++ /dev/null @@ -1,724 +0,0 @@ -r""" -Covering Arrays (CA) - -A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a -set of v elements with theproperty that in every selection of t columns, each -row contains every sequence of t-elements at least once. - -An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the -property that each row contains every sequence of t-elements exactly once - -REFERENCES: - -.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. - -.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. - Designs, 14 (2006) pp. 202-213. - -.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), - pp.125-150 - -AUTHORS: - -- Aaron Dwyer and brett stevens (2022): initial version - -.. NOTES:: - -This is a work in progress, it will be an implementation of a Covering Array -(CA) class for sagemath. The initial commit will include the definition of -the Covering Array class and some basic methods to check and return the -parameters N,k,v,t of the CA, as well as an ordering based on the -lexicographic ordering of each row. - -Later commits will include methods to create CAs from Linear Feedback Shift -Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families -(CPHF) as well as recursive methods. - -The Covering Array class may be used as a basis for an Orthogonal Array class -which will be implemented afterwards - -Classes and methods -------------------- -""" - -# **************************************************************************** -# Copyright (C) 2022 Aaron Dwyer -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.rings.finite_rings.finite_field_constructor import GF -import itertools -import copy - -def is_covering_array(Array,levels,strength): - r""" - Check whether the tuple of tuples in ``Array`` forms a covering array. - - INPUT: - - - ``Array`` - a tuple of tuples that represents a N x k array - - ``levels`` - positive integer representing the v value of the CA - - ``strength`` - positive integer representing the t value of the CA - - OUTPUT: - - A boolean representing if the input is a covering array or not - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import is_covering_array - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: D = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - sage: is_covering_array(C,2,2) - True - sage: is_covering_array(C,2,3) - False - sage: is_covering_array(D,3,3) - True - """ - tupledict={} - a=[ttuple for ttuple in itertools.product(GF(levels),repeat=strength)] - for item in a: - tupledict.update({item:0}) - for comb in itertools.combinations(range(len(Array[0])),strength): - wdict=copy.deepcopy(tupledict) - for row in Array: - wdict[tuple([row[ti] for ti in comb])]+=1 - if 0 in wdict.values(): - return False - return True - -class CoveringArray(): - r""" - Covering Array (CA) - - INPUT: - - - ``Array`` -- The N by k array itself stored as a tuple of tuples. - The N and k parameters are derived from this inputted array - - - ``strength`` -- The parameter t, such that in any selection of t columns - of the array, every t tuple appears at least once. If ``None`` then the - maxiumum t is found by iterating from t=0 until array is not a CA with - strength t+1. - - - ``levels`` -- The paramter v, such that v is the size of the symbol set - of the array. If ``None`` then a v will be assumed by counting number of - unique elements appear in the array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - """ - def __init__(self, Array, strength=None, levels=None): - r""" - Constructor function - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - """ - #From the array input, grab the dimensions of the array - N=len(Array) - self.__n=N - k=len(Array[0]) - self.__k=k - - #Array input is a tuple of tuples, the first thing to do is to sort - #the tuples lexicographically increasing - - L=list(Array) - L.sort() - SortedArray=tuple(L) - self.__array=SortedArray - - for row in Array: - assert len(row)==len(Array[0]), "Not all rows have same length" - - - #If v is not inputted then the symbol set may be assumed from what - #symbols are in the array by flattening the Array and counting the - #number of unique entries. - if levels==None: - levels = len({x for l in Array for x in l}) - self.__v=levels - - #If t is not inputted then try all t in {1,2,3...} until the array is - #not a covering array for that t - if strength==None: - finished=False - strength=1 - while finished==False: - if is_covering_array(Array, levels ,strength): - strength+=1 - else: - strength-=1 - finished=True - - #If t is given, make sure that t is the highest strength of the given - #Covering Array, that is the Covering Array is not strength t+1 - else: - finished=False - while finished==False: - if is_covering_array(Array, levels ,strength): - strength+=1 - else: - strength-=1 - finished=True - self.__t=strength - - def numrows(self): - r""" - Return the number of rows, N, of the covering array - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.numrows() - 5 - """ - return self.__n - - def numcols(self): - r""" - Returns the number of columns, k, of the covering array - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.numcols() - 4 - """ - return self.__k - - def levels(self): - r""" - Return the number of levels for the covering array, which is - the paramter v, such that v is the size of the symbol set of the - array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.levels() - 2 - """ - return self.__v - - def strength(self): - r""" - Return the strength of the covering array, which is the paramter - t, such that in any selection of t columns of the array, every - t tuple appears at least once. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.strength() - 2 - """ - return self.__t - - def array_representation(self): - r""" - Return the covering array as a tuple of tuples, but where - the output is such that each row of the array is sorted in - lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: CA = CoveringArray(C,2,2) - sage: CA.array_representation() - ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) - - """ - return self.__array - - - def __repr__(self): - r""" - Returns a string that describes self - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - - """ - return 'A {} by {} Covering Array of strength {} with {} levels'.format( - self.numrows(), self.numcols(), self.strength(), self.levels()) - - __str__=__repr__ - - def pprint(self): - r""" - Prints the covering array in a format easy for users to read - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.pprint() - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) - """ - for i in self.__array: - print(str(i)) - - def __hash__(self): - r""" - Hashs the tuple of tuples and all tuples inside - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C,2,2) - sage: hash(CA) - -2522140066511050633 - """ - return hash((self.array_representation(),self.strength(),self.levels())) - - def __eq__(self, other): - r""" - Return whether two covering arrays are equal by considering the - array with rows sorted in lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1==CA2 - True - sage: CA1==CA3 - False - """ - if self.array_representation() == other.array_representation(): - return True - else: - return False - - def __neq__(self, other): - r""" - Return whether two covering arrays are not equal by considering - the array with rows sorted in lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1!=CA2 - False - sage: CA1!=CA3 - True - """ - if self.array_representation() != other.array_representation(): - return True - else: - return False - - def __lt__(self, other): - r""" - Return whether one covering array is less than another - based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1,2,2) - sage: CA2 = CoveringArray(C2,2,2) - sage: CA1CA2 - False - """ - if self.array_representation() > other.array_representation(): - return True - else: - return False - - def __ge__(self, other): - r""" - Return whether one covering array is greater than or - equal to another based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1,2,2) - sage: CA2 = CoveringArray(C2,2,2) - sage: CA1>=CA2 - False - """ - if self.array_representation() >= other.array_representation(): - return True - else: - return False \ No newline at end of file From aeca574301f0c6f8fc55fe0a2da13c2ea2ee90ed Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Thu, 15 Dec 2022 11:09:25 -0500 Subject: [PATCH 009/225] The covering arrays file is now up to date --- src/sage/combinat/designs/covering_arrays.py | 698 ++++++++++++++++++- 1 file changed, 697 insertions(+), 1 deletion(-) mode change 100644 => 100755 src/sage/combinat/designs/covering_arrays.py diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py old mode 100644 new mode 100755 index e77e6fd537d..8db4c42c965 --- a/src/sage/combinat/designs/covering_arrays.py +++ b/src/sage/combinat/designs/covering_arrays.py @@ -1,3 +1,43 @@ +<<<<<<< HEAD +r""" +Covering Arrays (CA) + +A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a +set of v elements with theproperty that in every selection of t columns, each +row contains every sequence of t-elements at least once. + +An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the +property that each row contains every sequence of t-elements exactly once + +REFERENCES: + +.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. + +.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. + +.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 + +AUTHORS: + +- Aaron Dwyer and brett stevens (2022): initial version + +.. NOTES:: + +This is a work in progress, it will be an implementation of a Covering Array +(CA) class for sagemath. The initial commit will include the definition of +the Covering Array class and some basic methods to check and return the +parameters N,k,v,t of the CA, as well as an ordering based on the +lexicographic ordering of each row. + +Later commits will include methods to create CAs from Linear Feedback Shift +Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families +(CPHF) as well as recursive methods. +======= ''' An implementation of a Covering Array (CA) class for sagemath. The initial commit will include the definition of the Covering Array class @@ -6,10 +46,244 @@ Later commits will include methods to create CAs from Perfect Hash Families and Covering Perfect Hash Families (CPHF) as well as recursive methods. +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 The Covering Array class may be used as a basis for an Orthogonal Array class which will be implemented afterwards +<<<<<<< HEAD +Classes and methods +------------------- +""" + +# **************************************************************************** +# Copyright (C) 2022 Aaron Dwyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.rings.finite_rings.finite_field_constructor import GF +import itertools +import copy + +def is_covering_array(Array,levels,strength): + r""" + Check whether the tuple of tuples in ``Array`` forms a covering array. + + INPUT: + + - ``Array`` - a tuple of tuples that represents a N x k array + - ``levels`` - positive integer representing the v value of the CA + - ``strength`` - positive integer representing the t value of the CA + + OUTPUT: + + A boolean representing if the input is a covering array or not + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import is_covering_array + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: D = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: is_covering_array(C,2,2) + True + sage: is_covering_array(C,2,3) + False + sage: is_covering_array(D,3,3) + True + """ + tupledict={} + a=[ttuple for ttuple in itertools.product(GF(levels),repeat=strength)] + for item in a: + tupledict.update({item:0}) + for comb in itertools.combinations(range(len(Array[0])),strength): + wdict=copy.deepcopy(tupledict) + for row in Array: + wdict[tuple([row[ti] for ti in comb])]+=1 + if 0 in wdict.values(): + return False + return True + +class CoveringArray(): + r""" + Covering Array (CA) + + INPUT: + + - ``Array`` -- The N by k array itself stored as a tuple of tuples. + The N and k parameters are derived from this inputted array + + - ``strength`` -- The parameter t, such that in any selection of t columns + of the array, every t tuple appears at least once. If ``None`` then the + maxiumum t is found by iterating from t=0 until array is not a CA with + strength t+1. + + - ``levels`` -- The paramter v, such that v is the size of the symbol set + of the array. If ``None`` then a v will be assumed by counting number of + unique elements appear in the array. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array of strength 2 with 2 levels + + """ + def __init__(self, Array, strength=None, levels=None): + r""" + Constructor function + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array of strength 2 with 2 levels + + """ + #From the array input, grab the dimensions of the array + N=len(Array) + self.__n=N +======= ''' import itertools @@ -43,6 +317,7 @@ def __init__(self, Array, t=None, v=None): #From the array input, grab the dimensions of the array n=len(Array) self.__n=n +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 k=len(Array[0]) self.__k=k @@ -61,6 +336,22 @@ def __init__(self, Array, t=None, v=None): #If v is not inputted then the symbol set may be assumed from what #symbols are in the array by flattening the Array and counting the #number of unique entries. +<<<<<<< HEAD + if levels==None: + levels = len({x for l in Array for x in l}) + self.__v=levels + + #If t is not inputted then try all t in {1,2,3...} until the array is + #not a covering array for that t + if strength==None: + finished=False + strength=1 + while finished==False: + if is_covering_array(Array, levels ,strength): + strength+=1 + else: + strength-=1 +======= if v==None: v = len({x for l in Array for x in l}) self.__v=v @@ -75,6 +366,7 @@ def __init__(self, Array, t=None, v=None): t+=1 else: t-=1 +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 finished=True #If t is given, make sure that t is the highest strength of the given @@ -82,6 +374,110 @@ def __init__(self, Array, t=None, v=None): else: finished=False while finished==False: +<<<<<<< HEAD + if is_covering_array(Array, levels ,strength): + strength+=1 + else: + strength-=1 + finished=True + self.__t=strength + + def numrows(self): + r""" + Return the number of rows, N, of the covering array + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.numrows() + 5 + """ + return self.__n + + def numcols(self): + r""" + Returns the number of columns, k, of the covering array + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.numcols() + 4 + """ + return self.__k + + def levels(self): + r""" + Return the number of levels for the covering array, which is + the paramter v, such that v is the size of the symbol set of the + array. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.levels() + 2 + """ + return self.__v + + def strength(self): + r""" + Return the strength of the covering array, which is the paramter + t, such that in any selection of t columns of the array, every + t tuple appears at least once. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.strength() + 2 + """ + return self.__t + + def array_representation(self): + r""" + Return the covering array as a tuple of tuples, but where + the output is such that each row of the array is sorted in + lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: CA = CoveringArray(C,2,2) + sage: CA.array_representation() + ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) + + """ +======= if is_covering_array(Array, v ,t): t+=1 else: @@ -102,10 +498,156 @@ def t(self): return self.__t def ArrayRepresentation(self): +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return self.__array def __repr__(self): +<<<<<<< HEAD + r""" + Returns a string that describes self + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C,strength=2) + A 5 by 4 Covering Array of strength 2 with 2 levels + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,3,2) + A 13 by 10 Covering Array of strength 3 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 6 by 10 Covering Array of strength 2 with 2 levels + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array of strength 2 with 2 levels + + + """ + return 'A {} by {} Covering Array of strength {} with {} levels'.format( + self.numrows(), self.numcols(), self.strength(), self.levels()) + + __str__=__repr__ + + def pprint(self): + r""" + Prints the covering array in a format easy for users to read + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C,2,2) + sage: CA.pprint() + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) + """ + for i in self.__array: + print(str(i)) + + def __hash__(self): + r""" + Hashs the tuple of tuples and all tuples inside + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C,2,2) + sage: hash(CA) + -2522140066511050633 + """ + return hash((self.array_representation(),self.strength(),self.levels())) + + def __eq__(self, other): + r""" + Return whether two covering arrays are equal by considering the + array with rows sorted in lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1==CA2 + True + sage: CA1==CA3 + False + """ + if self.array_representation() == other.array_representation(): +======= """ A print method @@ -122,37 +664,191 @@ def __repr__(self): def __eq__(self, other): if self.ArrayRepresentation() == other.ArrayRepresentation(): +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __neq__(self, other): +<<<<<<< HEAD + r""" + Return whether two covering arrays are not equal by considering + the array with rows sorted in lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1!=CA2 + False + sage: CA1!=CA3 + True + """ + if self.array_representation() != other.array_representation(): +======= if self.ArrayRepresentation() != other.ArrayRepresentation(): +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __lt__(self, other): +<<<<<<< HEAD + r""" + Return whether one covering array is less than another + based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __le__(self, other): +<<<<<<< HEAD + r""" + Return whether one covering array is less than or + equal to another based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1<=CA2 + True + """ + if self.array_representation() <= other.array_representation(): +======= if self.ArrayRepresentation() <= other.ArrayRepresentation(): +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __gt__(self, other): +<<<<<<< HEAD + r""" + Return whether one covering array is greater than + another based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1>CA2 + False + """ + if self.array_representation() > other.array_representation(): +======= if self.ArrayRepresentation() > other.ArrayRepresentation(): +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __ge__(self, other): +<<<<<<< HEAD + r""" + Return whether one covering array is greater than or + equal to another based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1,2,2) + sage: CA2 = CoveringArray(C2,2,2) + sage: CA1>=CA2 + False + """ + if self.array_representation() >= other.array_representation(): + return True + else: + return False +======= if self.ArrayRepresentation() >= other.ArrayRepresentation(): return True else: return False - \ No newline at end of file + +>>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 From 42ba324efb6f3db8a4c0fecefbcee6bddfc57228 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Fri, 27 Jan 2023 11:47:01 -0500 Subject: [PATCH 010/225] Fixed the merge of the covering array file --- src/sage/combinat/designs/covering_arrays.py | 132 +------------------ 1 file changed, 1 insertion(+), 131 deletions(-) diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py index 8db4c42c965..93a56969f06 100755 --- a/src/sage/combinat/designs/covering_arrays.py +++ b/src/sage/combinat/designs/covering_arrays.py @@ -1,4 +1,3 @@ -<<<<<<< HEAD r""" Covering Arrays (CA) @@ -37,21 +36,10 @@ Later commits will include methods to create CAs from Linear Feedback Shift Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families (CPHF) as well as recursive methods. -======= -''' -An implementation of a Covering Array (CA) class for sagemath. -The initial commit will include the definition of the Covering Array class -and some basic methods to check and return the parameters n,k,v,t of the CA, -as well as an ordering based on the lexicographic ordering of each row. - -Later commits will include methods to create CAs from Perfect Hash Families -and Covering Perfect Hash Families (CPHF) as well as recursive methods. ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 The Covering Array class may be used as a basis for an Orthogonal Array class which will be implemented afterwards -<<<<<<< HEAD Classes and methods ------------------- """ @@ -283,41 +271,6 @@ def __init__(self, Array, strength=None, levels=None): #From the array input, grab the dimensions of the array N=len(Array) self.__n=N -======= -''' - -import itertools -import copy - -def is_covering_array(Array,v ,t): - ''' - Check if the tuple of tuples 'Array' is a Covering Array CA(n,k,v,t). - - A CA(n,k,v,t) is an n by k array with entries from a set of v elements - with the property that in every selection of t columns, each row - contains every sequence of t-elements at least once. - - - ''' - - tupledict={} - a=[ttuple for ttuple in itertools.product(GF(v),repeat=t)] - for item in a: - tupledict.update({item:0}) - for comb in itertools.combinations(range(len(Array[0])),t): - wdict=copy.deepcopy(tupledict) - for row in Array: - wdict[tuple([row[ti] for ti in comb])]+=1 - if 0 in wdict.values(): - return False - return True - -class CoveringArray(): - def __init__(self, Array, t=None, v=None): - #From the array input, grab the dimensions of the array - n=len(Array) - self.__n=n ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 k=len(Array[0]) self.__k=k @@ -336,7 +289,6 @@ def __init__(self, Array, t=None, v=None): #If v is not inputted then the symbol set may be assumed from what #symbols are in the array by flattening the Array and counting the #number of unique entries. -<<<<<<< HEAD if levels==None: levels = len({x for l in Array for x in l}) self.__v=levels @@ -351,22 +303,6 @@ def __init__(self, Array, t=None, v=None): strength+=1 else: strength-=1 -======= - if v==None: - v = len({x for l in Array for x in l}) - self.__v=v - - #If t is not inputted then try all t in {1,2,3...} until the array is - #not a covering array for that t - if t==None: - finished=False - t=1 - while finished==False: - if is_covering_array(Array, v ,t): - t+=1 - else: - t-=1 ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 finished=True #If t is given, make sure that t is the highest strength of the given @@ -374,7 +310,6 @@ def __init__(self, Array, t=None, v=None): else: finished=False while finished==False: -<<<<<<< HEAD if is_covering_array(Array, levels ,strength): strength+=1 else: @@ -477,33 +412,10 @@ def array_representation(self): ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) """ -======= - if is_covering_array(Array, v ,t): - t+=1 - else: - t-=1 - finished=True - self.__t=t - - def n(self): - return self.__n - - def k(self): - return self.__k - - def v(self): - return self.__v - - def t(self): - return self.__t - - def ArrayRepresentation(self): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return self.__array def __repr__(self): -<<<<<<< HEAD r""" Returns a string that describes self @@ -647,30 +559,11 @@ def __eq__(self, other): False """ if self.array_representation() == other.array_representation(): -======= - """ - A print method - - EXAMPLES:: - - sage: CA = CoveringArray(5,4,2,2,[[1 , 1 , 1 , 0],[1 , 1 , 0 , 1],[1 , 0 , 1 , 1],[0 , 1 , 1 , 1],[0 , 0 , 0 , 0]]) - sage: CA - A 5 by 4 Covering Array of strength 2 with 2 levels - """ - return 'A {} by {} Covering Array of strength {} with {} levels'.format( - self.nrows, self.ncols, self.strength, self.levels) - - __str__=__repr__ - - def __eq__(self, other): - if self.ArrayRepresentation() == other.ArrayRepresentation(): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __neq__(self, other): -<<<<<<< HEAD r""" Return whether two covering arrays are not equal by considering the array with rows sorted in lexicographic order @@ -710,15 +603,11 @@ def __neq__(self, other): True """ if self.array_representation() != other.array_representation(): -======= - if self.ArrayRepresentation() != other.ArrayRepresentation(): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __lt__(self, other): -<<<<<<< HEAD r""" Return whether one covering array is less than another based on the lexicographic order on the rows @@ -743,15 +632,11 @@ def __lt__(self, other): True """ if self.array_representation() < other.array_representation(): -======= - if self.ArrayRepresentation() < other.ArrayRepresentation(): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __le__(self, other): -<<<<<<< HEAD r""" Return whether one covering array is less than or equal to another based on the lexicographic order on the rows @@ -776,15 +661,11 @@ def __le__(self, other): True """ if self.array_representation() <= other.array_representation(): -======= - if self.ArrayRepresentation() <= other.ArrayRepresentation(): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __gt__(self, other): -<<<<<<< HEAD r""" Return whether one covering array is greater than another based on the lexicographic order on the rows @@ -809,15 +690,11 @@ def __gt__(self, other): False """ if self.array_representation() > other.array_representation(): -======= - if self.ArrayRepresentation() > other.ArrayRepresentation(): ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 return True else: return False def __ge__(self, other): -<<<<<<< HEAD r""" Return whether one covering array is greater than or equal to another based on the lexicographic order on the rows @@ -844,11 +721,4 @@ def __ge__(self, other): if self.array_representation() >= other.array_representation(): return True else: - return False -======= - if self.ArrayRepresentation() >= other.ArrayRepresentation(): - return True - else: - return False - ->>>>>>> 5a4d10877a5c6414a20d23fcc217872d6287ba27 + return False \ No newline at end of file From ec936ebc0aa49a837f0b4cc7b03429a0d16f5397 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 7 Feb 2023 12:01:52 -0500 Subject: [PATCH 011/225] Moved the is_covering_array function to be a class method. Allowed use of specific symbol sets for CAs instead of just their size. --- src/sage/combinat/designs/covering_array.py | 713 ++++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 src/sage/combinat/designs/covering_array.py diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py new file mode 100644 index 00000000000..af1e581eaf9 --- /dev/null +++ b/src/sage/combinat/designs/covering_array.py @@ -0,0 +1,713 @@ +r""" +Covering Arrays (CA) + +A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a +set of v elements with theproperty that in every selection of t columns, each +row contains every sequence of t-elements at least once. + +An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the +property that each row contains every sequence of t-elements exactly once + +REFERENCES: + +.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. + +.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. + +.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 + +AUTHORS: + +- Aaron Dwyer and brett stevens (2022): initial version + +.. NOTES:: + +This is a work in progress, it will be an implementation of a Covering Array +(CA) class for sagemath. The initial commit will include the definition of +the Covering Array class and some basic methods to check and return the +parameters N,k,v,t of the CA, as well as an ordering based on the +lexicographic ordering of each row. + +Later commits will include methods to create CAs from Linear Feedback Shift +Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families +(CPHF) among others. + +The Covering Array class may be used as a basis for an Orthogonal Array class +which will be implemented afterwards + +Classes and methods +------------------- +""" + +# **************************************************************************** +# Copyright (C) 2022 Aaron Dwyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.rings.finite_rings.finite_field_constructor import GF +import itertools +import copy + +class CoveringArray(): + r""" + Covering Array (CA) + + INPUT: + + - ``Array`` -- The N by k array itself stored as a tuple of tuples. + The N and k parameters are derived from this inputted array + + - ``SymbolSet`` -- The collection of symbols that is used in ``Array``. + If left blank, then a symbol set will be assumed by checking for each + unique entry in the given ``Array``. In such a case it will be stored + as a list of symbols but any appropriate object may be used as long as + it has `len()` as a method + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from [0, 1] + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] + + """ + def __init__(self, Array, SymbolSet=None): + r""" + Constructor function + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from [0, 1] + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] + + """ + #From the array input, grab the dimensions of the array + N=len(Array) + self.__n=N + k=len(Array[0]) + self.__k=k + + #Array input is a tuple of tuples, the first thing to do is to sort + #the tuples lexicographically increasing + L=list(Array) + L.sort() + SortedArray=tuple(L) + self.__array=SortedArray + + for row in Array: + assert len(row)==len(Array[0]), "Not all rows have same length" + + #If no symbol set is given, then it may be assumed from what + #symbols are in the array by flattening the array and counting the + #number of unique entries. + if SymbolSet==None: + SymbolSet = list({x for l in Array for x in l}) + self.__sset=SymbolSet + + def numrows(self): + r""" + Return the number of rows, N, of the covering array + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.numrows() + 5 + """ + return self.__n + + def numcols(self): + r""" + Returns the number of columns, k, of the covering array + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.numcols() + 4 + """ + return self.__k + + def symbolset(self): + r""" + Return the symbol set of the array. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.symbolset() + Finite Field of size 2 + """ + return self.__sset + + def is_covering_array(self,strength): + r""" + Check whether the tuple of tuples in ``Array`` forms a covering array + with the given strength. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA1 = CoveringArray(C1,GF(2)) + sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: CA2 = CoveringArray(C2,GF(3)) + sage: CA1.is_covering_array(2) + True + sage: CA1.is_covering_array(3) + False + sage: CA2.is_covering_array(3) + True + """ + tupledict={} + a=[ttuple for ttuple in itertools.product(self.symbolset(),repeat=strength)] + for item in a: + tupledict.update({item:0}) + for comb in itertools.combinations(range(self.numcols()),strength): + wdict=copy.deepcopy(tupledict) + for row in self.__array: + wdict[tuple([row[ti] for ti in comb])]+=1 + if 0 in wdict.values(): + return False + return True + + def strength(self): + r""" + Return the strength of the covering array, which is the paramter + t, such that in any selection of t columns of the array, every + t tuple appears at least once. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.strength() + 2 + """ + finished=False + strength=1 + while finished==False: + if self.is_covering_array(strength): + strength+=1 + else: + strength-=1 + finished=True + return strength + + def levels(self): + r""" + Return the number of levels for the covering array, which is + the paramter v, such that v is the size of the symbol set of the + array. + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.levels() + 2 + """ + return len(self.__sset) + + def array_representation(self): + r""" + Return the covering array as a tuple of tuples, but where + the output is such that each row of the array is sorted in + lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1),) + sage: CA = CoveringArray(C,GF(2)) + sage: CA.array_representation() + ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) + + """ + return self.__array + + + def __repr__(self): + r""" + Returns a string that describes self + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from [0, 1] + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] + + """ + return 'A {} by {} Covering Array with entries from {}'.format( + self.numrows(), self.numcols(), self.symbolset()) + + __str__=__repr__ + + def pprint(self): + r""" + Prints the covering array in a format easy for users to read + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C) + sage: CA.pprint() + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) + """ + for i in self.__array: + print(str(i)) + + def __hash__(self): + r""" + Hashs the tuple of tuples and all tuples inside + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA = CoveringArray(C) + sage: hash(CA) + 4367534393624660384 + """ + return hash((self.array_representation(),tuple(self.symbolset()))) + + def __eq__(self, other): + r""" + Return whether two covering arrays are equal by considering the + array with rows sorted in lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1==CA2 + True + sage: CA1==CA3 + False + """ + if self.array_representation() == other.array_representation(): + return True + else: + return False + + def __neq__(self, other): + r""" + Return whether two covering arrays are not equal by considering + the array with rows sorted in lexicographic order + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((1,1,1,0),\ + (1,1,0,1),\ + (1,0,1,1),\ + (0,1,1,1),\ + (0,0,0,0)) + sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA3 = CoveringArray(C3) + sage: CA1!=CA2 + False + sage: CA1!=CA3 + True + """ + if self.array_representation() != other.array_representation(): + return True + else: + return False + + def __lt__(self, other): + r""" + Return whether one covering array is less than another + based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA1CA2 + False + """ + if self.array_representation() > other.array_representation(): + return True + else: + return False + + def __ge__(self, other): + r""" + Return whether one covering array is greater than or + equal to another based on the lexicographic order on the rows + + EXAMPLES:: + + sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: C1 = ((1,1,1,0),\ + (0,0,0,0),\ + (1,0,1,1),\ + (1,1,0,1),\ + (0,1,1,1)) + sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CA1 = CoveringArray(C1) + sage: CA2 = CoveringArray(C2) + sage: CA1>=CA2 + False + """ + if self.array_representation() >= other.array_representation(): + return True + else: + return False From 5c52ce86e50ffcd776f969e368eef063ee2588d3 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 7 Feb 2023 13:50:57 -0500 Subject: [PATCH 012/225] Renamed file --- src/sage/combinat/designs/covering_arrays.py | 724 ------------------- 1 file changed, 724 deletions(-) delete mode 100755 src/sage/combinat/designs/covering_arrays.py diff --git a/src/sage/combinat/designs/covering_arrays.py b/src/sage/combinat/designs/covering_arrays.py deleted file mode 100755 index 93a56969f06..00000000000 --- a/src/sage/combinat/designs/covering_arrays.py +++ /dev/null @@ -1,724 +0,0 @@ -r""" -Covering Arrays (CA) - -A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a -set of v elements with theproperty that in every selection of t columns, each -row contains every sequence of t-elements at least once. - -An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the -property that each row contains every sequence of t-elements exactly once - -REFERENCES: - -.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. - -.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. - Designs, 14 (2006) pp. 202-213. - -.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), - pp.125-150 - -AUTHORS: - -- Aaron Dwyer and brett stevens (2022): initial version - -.. NOTES:: - -This is a work in progress, it will be an implementation of a Covering Array -(CA) class for sagemath. The initial commit will include the definition of -the Covering Array class and some basic methods to check and return the -parameters N,k,v,t of the CA, as well as an ordering based on the -lexicographic ordering of each row. - -Later commits will include methods to create CAs from Linear Feedback Shift -Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families -(CPHF) as well as recursive methods. - -The Covering Array class may be used as a basis for an Orthogonal Array class -which will be implemented afterwards - -Classes and methods -------------------- -""" - -# **************************************************************************** -# Copyright (C) 2022 Aaron Dwyer -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.rings.finite_rings.finite_field_constructor import GF -import itertools -import copy - -def is_covering_array(Array,levels,strength): - r""" - Check whether the tuple of tuples in ``Array`` forms a covering array. - - INPUT: - - - ``Array`` - a tuple of tuples that represents a N x k array - - ``levels`` - positive integer representing the v value of the CA - - ``strength`` - positive integer representing the t value of the CA - - OUTPUT: - - A boolean representing if the input is a covering array or not - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import is_covering_array - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: D = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - sage: is_covering_array(C,2,2) - True - sage: is_covering_array(C,2,3) - False - sage: is_covering_array(D,3,3) - True - """ - tupledict={} - a=[ttuple for ttuple in itertools.product(GF(levels),repeat=strength)] - for item in a: - tupledict.update({item:0}) - for comb in itertools.combinations(range(len(Array[0])),strength): - wdict=copy.deepcopy(tupledict) - for row in Array: - wdict[tuple([row[ti] for ti in comb])]+=1 - if 0 in wdict.values(): - return False - return True - -class CoveringArray(): - r""" - Covering Array (CA) - - INPUT: - - - ``Array`` -- The N by k array itself stored as a tuple of tuples. - The N and k parameters are derived from this inputted array - - - ``strength`` -- The parameter t, such that in any selection of t columns - of the array, every t tuple appears at least once. If ``None`` then the - maxiumum t is found by iterating from t=0 until array is not a CA with - strength t+1. - - - ``levels`` -- The paramter v, such that v is the size of the symbol set - of the array. If ``None`` then a v will be assumed by counting number of - unique elements appear in the array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - """ - def __init__(self, Array, strength=None, levels=None): - r""" - Constructor function - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - """ - #From the array input, grab the dimensions of the array - N=len(Array) - self.__n=N - k=len(Array[0]) - self.__k=k - - #Array input is a tuple of tuples, the first thing to do is to sort - #the tuples lexicographically increasing - - L=list(Array) - L.sort() - SortedArray=tuple(L) - self.__array=SortedArray - - for row in Array: - assert len(row)==len(Array[0]), "Not all rows have same length" - - - #If v is not inputted then the symbol set may be assumed from what - #symbols are in the array by flattening the Array and counting the - #number of unique entries. - if levels==None: - levels = len({x for l in Array for x in l}) - self.__v=levels - - #If t is not inputted then try all t in {1,2,3...} until the array is - #not a covering array for that t - if strength==None: - finished=False - strength=1 - while finished==False: - if is_covering_array(Array, levels ,strength): - strength+=1 - else: - strength-=1 - finished=True - - #If t is given, make sure that t is the highest strength of the given - #Covering Array, that is the Covering Array is not strength t+1 - else: - finished=False - while finished==False: - if is_covering_array(Array, levels ,strength): - strength+=1 - else: - strength-=1 - finished=True - self.__t=strength - - def numrows(self): - r""" - Return the number of rows, N, of the covering array - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.numrows() - 5 - """ - return self.__n - - def numcols(self): - r""" - Returns the number of columns, k, of the covering array - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.numcols() - 4 - """ - return self.__k - - def levels(self): - r""" - Return the number of levels for the covering array, which is - the paramter v, such that v is the size of the symbol set of the - array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.levels() - 2 - """ - return self.__v - - def strength(self): - r""" - Return the strength of the covering array, which is the paramter - t, such that in any selection of t columns of the array, every - t tuple appears at least once. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.strength() - 2 - """ - return self.__t - - def array_representation(self): - r""" - Return the covering array as a tuple of tuples, but where - the output is such that each row of the array is sorted in - lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: CA = CoveringArray(C,2,2) - sage: CA.array_representation() - ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) - - """ - return self.__array - - - def __repr__(self): - r""" - Returns a string that describes self - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: CoveringArray(C,strength=2) - A 5 by 4 Covering Array of strength 2 with 2 levels - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,3,2) - A 13 by 10 Covering Array of strength 3 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 6 by 10 Covering Array of strength 2 with 2 levels - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array of strength 2 with 2 levels - - - """ - return 'A {} by {} Covering Array of strength {} with {} levels'.format( - self.numrows(), self.numcols(), self.strength(), self.levels()) - - __str__=__repr__ - - def pprint(self): - r""" - Prints the covering array in a format easy for users to read - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C,2,2) - sage: CA.pprint() - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) - """ - for i in self.__array: - print(str(i)) - - def __hash__(self): - r""" - Hashs the tuple of tuples and all tuples inside - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C,2,2) - sage: hash(CA) - -2522140066511050633 - """ - return hash((self.array_representation(),self.strength(),self.levels())) - - def __eq__(self, other): - r""" - Return whether two covering arrays are equal by considering the - array with rows sorted in lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1==CA2 - True - sage: CA1==CA3 - False - """ - if self.array_representation() == other.array_representation(): - return True - else: - return False - - def __neq__(self, other): - r""" - Return whether two covering arrays are not equal by considering - the array with rows sorted in lexicographic order - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1!=CA2 - False - sage: CA1!=CA3 - True - """ - if self.array_representation() != other.array_representation(): - return True - else: - return False - - def __lt__(self, other): - r""" - Return whether one covering array is less than another - based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1,2,2) - sage: CA2 = CoveringArray(C2,2,2) - sage: CA1CA2 - False - """ - if self.array_representation() > other.array_representation(): - return True - else: - return False - - def __ge__(self, other): - r""" - Return whether one covering array is greater than or - equal to another based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1,2,2) - sage: CA2 = CoveringArray(C2,2,2) - sage: CA1>=CA2 - False - """ - if self.array_representation() >= other.array_representation(): - return True - else: - return False \ No newline at end of file From d2f339210044fd843db5a643f59c33adaf9fc8af Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 7 Feb 2023 13:52:51 -0500 Subject: [PATCH 013/225] added methods --- src/sage/combinat/designs/covering_array_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_array_methods.py b/src/sage/combinat/designs/covering_array_methods.py index be9defbe7c6..2c2e577b656 100644 --- a/src/sage/combinat/designs/covering_array_methods.py +++ b/src/sage/combinat/designs/covering_array_methods.py @@ -68,4 +68,4 @@ def LFSR_for_strength3(n,p): M2=[] for i in M: M2.append(tuple(i)) - return tuple(M2) \ No newline at end of file + return tuple(M2) From 2d85ecea3d51c334a7303106e38f915c941e2d1c Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 10 Feb 2023 23:53:37 +0800 Subject: [PATCH 014/225] Enable merge_group trigger for merge queues --- .github/workflows/build.yml | 4 ++++ .github/workflows/doc-build.yml | 4 ++++ .github/workflows/lint.yml | 8 +++++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 814e410d29f..fdb9f0cd5cb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,7 +2,11 @@ name: Build & Test on: pull_request: + merge_group: push: + branches: + - master + - develop workflow_dispatch: # Allow to run manually inputs: diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 0b17c199ac4..a278633a765 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -2,7 +2,11 @@ name: Build documentation on: pull_request: + merge_group: push: + branches: + - master + - develop workflow_dispatch: # Allow to run manually diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 883749e2bf7..6b3b8239053 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,12 @@ name: Lint -on: [push, pull_request] +on: + push: + branches: + - master + - develop + pull_request: + merge_group: concurrency: # Cancel previous runs of this workflow for the same branch From 7e96e8d40e978557115222958591d85198776986 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Sat, 18 Feb 2023 14:25:29 -0500 Subject: [PATCH 015/225] Fixed the name of the file in the doctests, and deleted a temporary file --- src/sage/combinat/designs/covering_array.py | 72 +++++++++---------- .../designs/covering_array_methods.py | 71 ------------------ 2 files changed, 36 insertions(+), 107 deletions(-) delete mode 100644 src/sage/combinat/designs/covering_array_methods.py diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index af1e581eaf9..af543b95bc6 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -75,14 +75,14 @@ class CoveringArray(): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a','a','a','b'),\ + ('a','a','b','a'),\ + ('a','b','a','a'),\ + ('b','a','a','a'),\ + ('b','b','b','b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from [0, 1] + A 5 by 4 Covering Array with entries from ['a', 'b'] sage: C = ((0,0,0,0,0,0,0,0,0,0),\ (1,1,1,1,1,1,1,1,1,1),\ @@ -126,14 +126,14 @@ def __init__(self, Array, SymbolSet=None): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a','a','a','b'),\ + ('a','a','b','a'),\ + ('a','b','a','a'),\ + ('b','a','a','a'),\ + ('b','b','b','b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from [0, 1] + A 5 by 4 Covering Array with entries from ['a', 'b'] sage: C = ((0,0,0,0,0,0,0,0,0,0),\ (1,1,1,1,1,1,1,1,1,1),\ @@ -200,7 +200,7 @@ def numrows(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -218,7 +218,7 @@ def numcols(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -236,7 +236,7 @@ def symbolset(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -255,7 +255,7 @@ def is_covering_array(self,strength): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -343,7 +343,7 @@ def strength(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -371,7 +371,7 @@ def levels(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ @@ -391,7 +391,7 @@ def array_representation(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -411,14 +411,14 @@ def __repr__(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a','a','a','b'),\ + ('a','a','b','a'),\ + ('a','b','a','a'),\ + ('b','a','a','a'),\ + ('b','b','b','b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from [0, 1] + A 5 by 4 Covering Array with entries from ['a', 'b'] sage: C = ((0,0,0,0,0,0,0,0,0,0),\ (1,1,1,1,1,1,1,1,1,1),\ @@ -467,7 +467,7 @@ def pprint(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -494,7 +494,7 @@ def __hash__(self): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ @@ -515,7 +515,7 @@ def __eq__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -559,7 +559,7 @@ def __neq__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -603,7 +603,7 @@ def __lt__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -632,7 +632,7 @@ def __le__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -661,7 +661,7 @@ def __gt__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ @@ -690,7 +690,7 @@ def __ge__(self, other): EXAMPLES:: - sage: from sage.combinat.designs.covering_arrays import CoveringArray + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ diff --git a/src/sage/combinat/designs/covering_array_methods.py b/src/sage/combinat/designs/covering_array_methods.py deleted file mode 100644 index 2c2e577b656..00000000000 --- a/src/sage/combinat/designs/covering_array_methods.py +++ /dev/null @@ -1,71 +0,0 @@ -import itertools -import math - -def tuple_weight(t): - ''' - given a tuple t returns the integer sum of all of its values - ''' - ctr=0 - for i in t: - ctr+=i - return ctr - -def Kleitman_Specer_Katona(n): #Kleitman and Spencer [76] and Katona - ''' - - Given an integer n, returns a binary covering array with strength 2 - To do this we form a matrix represented as a tuple of tuples where the - columns are all binary n-tuples of weight ceiling(n/2) that have 0 - in 1st position - - Reference is Combinatorial aspects... - ''' - resulttupleT=() - x = [0,1] - for p in itertools.product(x, repeat=n-1): - if tuple_weight(p)==math.ceil(n/2): - column=(0,)+p - resulttupleT+=(column,) - M=Matrix(resulttupleT) - M1=M.transpose() - return(tuple(M1)) - -def LFSR_for_strength3(n,p): - r""" - Returns a matrix that represents a CA() - - This method forms a sequence of entries of the ring GF(p) by using LFSR, - where the expression is given by the coeffients of the irreducible - polynomial of degree n with coefficients in GF(p). We form the circulant - matrix of the sequence and the reverse sequence, and remove the last - p^2+p+1 columns. The result is a covering array - """ - - R=PolynomialRing(GF(p),x) - #find the irreducible polynomial degree n - irr=R.irreducible_element(n) - #we want to use coefficients of irr poly and solve for the coeff for the - #highest order term, this is done by taking the inverse of everything and - #then dropping the first term - a=[j:=-i for i in irr] - a.pop() - #for use of sages LFSR we set the fill to be all 0s except the first term - fill=[0]*(n-1) - fill.insert(0,1) - #and the key is the expression from the coefficients found above - key=a - k=(p**n)-1 #the number of columns to be created - LSFRseq = lfsr_sequence(key,fill,k) - #We create a deep copy of this sequence so we can reverse it - LSFRrevseq = copy.deepcopy(L1) - LSFRrevseq.reverse() - #The array will be formed by the circ matrix of each sequence, plus the - #all zero row at the end - M=block_matrix(3,[matrix.circulant(LSFRseq),matrix.circulant(LSFRrevseq) - ,matrix(GF(3),[0]*k)]) - #We then delete the excess columns to obtain the CA - M=M.delete_columns([i for i in range (k-(p*p+p+1),k)]) - M2=[] - for i in M: - M2.append(tuple(i)) - return tuple(M2) From 3c1a2023649dfcd1dc8b3c630a9616eec8d675b0 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Fri, 24 Feb 2023 12:51:27 -0500 Subject: [PATCH 016/225] Edited file to fix unsuccessful checks --- src/sage/combinat/designs/covering_array.py | 289 ++++++++++---------- 1 file changed, 137 insertions(+), 152 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index af543b95bc6..75e5ae9b10e 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -1,44 +1,29 @@ r""" Covering Arrays (CA) -A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a -set of v elements with theproperty that in every selection of t columns, each +A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a +set of v elements with theproperty that in every selection of t columns, each row contains every sequence of t-elements at least once. -An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the +An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the property that each row contains every sequence of t-elements exactly once REFERENCES: - -.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. + +.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. Matematiche (Catania) 59 (2004), pp. 125–172. -.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. +.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. Designs, 14 (2006) pp. 202-213. -.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), +.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), pp.125-150 AUTHORS: - -- Aaron Dwyer and brett stevens (2022): initial version - -.. NOTES:: - -This is a work in progress, it will be an implementation of a Covering Array -(CA) class for sagemath. The initial commit will include the definition of -the Covering Array class and some basic methods to check and return the -parameters N,k,v,t of the CA, as well as an ordering based on the -lexicographic ordering of each row. - -Later commits will include methods to create CAs from Linear Feedback Shift -Register (LFSR), Perfect Hash Families and Covering Perfect Hash Families -(CPHF) among others. -The Covering Array class may be used as a basis for an Orthogonal Array class -which will be implemented afterwards +- Aaron Dwyer and brett stevens (2022): initial version Classes and methods ------------------- @@ -61,29 +46,29 @@ class CoveringArray(): r""" Covering Array (CA) - + INPUT: - + - ``Array`` -- The N by k array itself stored as a tuple of tuples. The N and k parameters are derived from this inputted array - + - ``SymbolSet`` -- The collection of symbols that is used in ``Array``. If left blank, then a symbol set will be assumed by checking for each unique entry in the given ``Array``. In such a case it will be stored as a list of symbols but any appropriate object may be used as long as it has `len()` as a method - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = (('a','a','a','b'),\ ('a','a','b','a'),\ ('a','b','a','a'),\ ('b','a','a','a'),\ - ('b','b','b','b')) + ('b','b','b','b')) sage: CoveringArray(C) A 5 by 4 Covering Array with entries from ['a', 'b'] - + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ (1,1,1,1,1,1,1,1,1,1),\ (1,1,1,0,1,0,0,0,0,1),\ @@ -99,7 +84,7 @@ class CoveringArray(): (0,1,0,0,0,1,1,1,0,1)) sage: CoveringArray(C,[0, 1]) A 13 by 10 Covering Array with entries from [0, 1] - + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ @@ -123,18 +108,18 @@ class CoveringArray(): def __init__(self, Array, SymbolSet=None): r""" Constructor function - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = (('a','a','a','b'),\ ('a','a','b','a'),\ ('a','b','a','a'),\ ('b','a','a','a'),\ - ('b','b','b','b')) + ('b','b','b','b')) sage: CoveringArray(C) A 5 by 4 Covering Array with entries from ['a', 'b'] - + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ (1,1,1,1,1,1,1,1,1,1),\ (1,1,1,0,1,0,0,0,0,1),\ @@ -150,7 +135,7 @@ def __init__(self, Array, SymbolSet=None): (0,1,0,0,0,1,1,1,0,1)) sage: CoveringArray(C,[0, 1]) A 13 by 10 Covering Array with entries from [0, 1] - + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ @@ -176,7 +161,7 @@ def __init__(self, Array, SymbolSet=None): self.__n=N k=len(Array[0]) self.__k=k - + #Array input is a tuple of tuples, the first thing to do is to sort #the tuples lexicographically increasing L=list(Array) @@ -186,75 +171,75 @@ def __init__(self, Array, SymbolSet=None): for row in Array: assert len(row)==len(Array[0]), "Not all rows have same length" - - #If no symbol set is given, then it may be assumed from what - #symbols are in the array by flattening the array and counting the + + #If no symbol set is given, then it may be assumed from what + #symbols are in the array by flattening the array and counting the #number of unique entries. - if SymbolSet==None: + if SymbolSet is None: SymbolSet = list({x for l in Array for x in l}) self.__sset=SymbolSet def numrows(self): r""" Return the number of rows, N, of the covering array - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ (0,1,1,1),\ - (0,0,0,0)) + (0,0,0,0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numrows() 5 """ return self.__n - + def numcols(self): r""" Returns the number of columns, k, of the covering array - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ (0,1,1,1),\ - (0,0,0,0)) + (0,0,0,0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numcols() 4 """ return self.__k - + def symbolset(self): r""" Return the symbol set of the array. - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ (0,1,1,1),\ - (0,0,0,0)) + (0,0,0,0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.symbolset() Finite Field of size 2 """ return self.__sset - def is_covering_array(self,strength): + def is_covering_array(self,strength): r""" - Check whether the tuple of tuples in ``Array`` forms a covering array + Check whether the tuple of tuples in ``Array`` forms a covering array with the given strength. EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (1,1,0,1),\ @@ -333,29 +318,29 @@ def is_covering_array(self,strength): wdict[tuple([row[ti] for ti in comb])]+=1 if 0 in wdict.values(): return False - return True + return True def strength(self): r""" - Return the strength of the covering array, which is the paramter - t, such that in any selection of t columns of the array, every - t tuple appears at least once. - + Return the strength of the covering array, which is the paramter + t, such that in any selection of t columns of the array, every + t tuple appears at least once. + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ (0,1,1,1),\ - (0,0,0,0)) + (0,0,0,0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.strength() 2 """ finished=False strength=1 - while finished==False: + while not finished: if self.is_covering_array(strength): strength+=1 else: @@ -365,18 +350,18 @@ def strength(self): def levels(self): r""" - Return the number of levels for the covering array, which is - the paramter v, such that v is the size of the symbol set of the + Return the number of levels for the covering array, which is + the paramter v, such that v is the size of the symbol set of the array. - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (1,1,0,1),\ (1,0,1,1),\ (0,1,1,1),\ - (0,0,0,0)) + (0,0,0,0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.levels() 2 @@ -386,87 +371,87 @@ def levels(self): def array_representation(self): r""" Return the covering array as a tuple of tuples, but where - the output is such that each row of the array is sorted in + the output is such that each row of the array is sorted in lexicographic order - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1,1,1,0),\ (0,0,0,0),\ (1,0,1,1),\ (1,1,0,1),\ - (0,1,1,1),) + (0,1,1,1),) sage: CA = CoveringArray(C,GF(2)) sage: CA.array_representation() ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) - + """ return self.__array - - + + def __repr__(self): r""" Returns a string that describes self - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a','a','a','b'),\ - ('a','a','b','a'),\ - ('a','b','a','a'),\ - ('b','a','a','a'),\ - ('b','b','b','b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + EXAMPLES:: + + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a','a','a','b'),\ + ('a','a','b','a'),\ + ('a','b','a','a'),\ + ('b','a','a','a'),\ + ('b','b','b','b')) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from ['a', 'b'] + + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] """ return 'A {} by {} Covering Array with entries from {}'.format( self.numrows(), self.numcols(), self.symbolset()) - + __str__=__repr__ - + def pprint(self): r""" Prints the covering array in a format easy for users to read - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ @@ -487,13 +472,13 @@ def pprint(self): """ for i in self.__array: print(str(i)) - + def __hash__(self): r""" Hashs the tuple of tuples and all tuples inside - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ @@ -507,14 +492,14 @@ def __hash__(self): 4367534393624660384 """ return hash((self.array_representation(),tuple(self.symbolset()))) - + def __eq__(self, other): r""" - Return whether two covering arrays are equal by considering the + Return whether two covering arrays are equal by considering the array with rows sorted in lexicographic order - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ @@ -551,14 +536,14 @@ def __eq__(self, other): return True else: return False - + def __neq__(self, other): r""" - Return whether two covering arrays are not equal by considering + Return whether two covering arrays are not equal by considering the array with rows sorted in lexicographic order - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ @@ -595,14 +580,14 @@ def __neq__(self, other): return True else: return False - + def __lt__(self, other): r""" Return whether one covering array is less than another based on the lexicographic order on the rows - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ @@ -624,14 +609,14 @@ def __lt__(self, other): return True else: return False - + def __le__(self, other): r""" - Return whether one covering array is less than or + Return whether one covering array is less than or equal to another based on the lexicographic order on the rows - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ @@ -653,14 +638,14 @@ def __le__(self, other): return True else: return False - + def __gt__(self, other): r""" - Return whether one covering array is greater than + Return whether one covering array is greater than another based on the lexicographic order on the rows - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ @@ -682,14 +667,14 @@ def __gt__(self, other): return True else: return False - + def __ge__(self, other): r""" - Return whether one covering array is greater than or + Return whether one covering array is greater than or equal to another based on the lexicographic order on the rows - + EXAMPLES:: - + sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1,1,1,0),\ (0,0,0,0),\ From d5940d701387839da647ebdc258fc69fa8c5c340 Mon Sep 17 00:00:00 2001 From: brett stevens Date: Tue, 28 Feb 2023 15:28:25 -0500 Subject: [PATCH 017/225] added two doctests: - in .symbolset if we don't specify symbols set on init - in .strength if we pass it strength 3 CA --- src/sage/combinat/designs/covering_array.py | 62 +++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 75e5ae9b10e..d59c2655aa0 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -177,6 +177,7 @@ def __init__(self, Array, SymbolSet=None): #number of unique entries. if SymbolSet is None: SymbolSet = list({x for l in Array for x in l}) + SymbolSet.sort() self.__sset=SymbolSet def numrows(self): @@ -230,6 +231,9 @@ def symbolset(self): sage: CA = CoveringArray(C,GF(2)) sage: CA.symbolset() Finite Field of size 2 + sage: CA = CoveringArray(C) + sage: CA.symbolset() + [0, 1] """ return self.__sset @@ -337,6 +341,64 @@ def strength(self): sage: CA = CoveringArray(C,GF(2)) sage: CA.strength() 2 + + + sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: CA2 = CoveringArray(C2,GF(3)) + sage: CA2.strength() + 3 """ finished=False strength=1 From b1488d50ccc2c2746f2da63e1b9f0411aeb6c183 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 3 Mar 2023 22:02:23 +0000 Subject: [PATCH 018/225] typo fixes --- src/sage/combinat/designs/covering_array.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index d59c2655aa0..a896764a8ac 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -326,7 +326,7 @@ def is_covering_array(self,strength): def strength(self): r""" - Return the strength of the covering array, which is the paramter + Return the strength of the covering array, which is the parameter t, such that in any selection of t columns of the array, every t tuple appears at least once. @@ -413,7 +413,7 @@ def strength(self): def levels(self): r""" Return the number of levels for the covering array, which is - the paramter v, such that v is the size of the symbol set of the + the parameter v, such that v is the size of the symbol set of the array. EXAMPLES:: From 36adf0763f2de81f80d69d03dd69c1bafee1edb9 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Sat, 4 Mar 2023 10:00:33 -0500 Subject: [PATCH 019/225] Added the covering array file to documentation, fixed a couple formatting typos in the covering array file --- src/doc/en/reference/combinat/module_list.rst | 1 + src/sage/combinat/designs/covering_array.py | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 3bfa10ed3f7..51ed68802b9 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -92,6 +92,7 @@ Comprehensive Module List sage/combinat/designs/resolvable_bibd sage/combinat/designs/group_divisible_designs sage/combinat/designs/block_design + sage/combinat/designs/covering_array sage/combinat/designs/covering_design sage/combinat/designs/database sage/combinat/designs/design_catalog diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index a896764a8ac..2ff7251d590 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -109,7 +109,7 @@ def __init__(self, Array, SymbolSet=None): r""" Constructor function - EXAMPLES:: + EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = (('a','a','a','b'),\ @@ -154,8 +154,7 @@ def __init__(self, Array, SymbolSet=None): (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) A 7 by 15 Covering Array with entries from [0, 1] - - """ + """ #From the array input, grab the dimensions of the array N=len(Array) self.__n=N @@ -341,8 +340,6 @@ def strength(self): sage: CA = CoveringArray(C,GF(2)) sage: CA.strength() 2 - - sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ @@ -447,7 +444,6 @@ def array_representation(self): sage: CA = CoveringArray(C,GF(2)) sage: CA.array_representation() ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) - """ return self.__array @@ -501,7 +497,6 @@ def __repr__(self): (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) A 7 by 15 Covering Array with entries from [0, 1] - """ return 'A {} by {} Covering Array with entries from {}'.format( self.numrows(), self.numcols(), self.symbolset()) From 496c071b02d85d1b72aa807f9e26f702ddbdc9ab Mon Sep 17 00:00:00 2001 From: Aaron-Dwyer <109538917+Aaron-Dwyer@users.noreply.github.com> Date: Sat, 4 Mar 2023 11:13:44 -0500 Subject: [PATCH 020/225] Update covering_array.py --- src/sage/combinat/designs/covering_array.py | 80 ++++++++++----------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 2ff7251d590..dd0aa57fdc0 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -111,49 +111,49 @@ def __init__(self, Array, SymbolSet=None): EXAMPLES:: - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a','a','a','b'),\ - ('a','a','b','a'),\ - ('a','b','a','a'),\ - ('b','a','a','a'),\ - ('b','b','b','b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a','a','a','b'),\ + ('a','a','b','a'),\ + ('a','b','a','a'),\ + ('b','a','a','a'),\ + ('b','b','b','b')) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from ['a', 'b'] - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + sage: C = ((0,0,0,0,0,0,0,0,0,0),\ + (1,1,1,1,1,1,1,1,1,1),\ + (1,1,1,0,1,0,0,0,0,1),\ + (1,0,1,1,0,1,0,1,0,0),\ + (1,0,0,0,1,1,1,0,0,0),\ + (0,1,1,0,0,1,0,0,1,0),\ + (0,0,1,0,1,0,1,1,1,0),\ + (1,1,0,1,0,0,1,0,1,0),\ + (0,0,0,1,1,1,0,0,1,1),\ + (0,0,1,1,0,0,1,0,0,1),\ + (0,1,0,1,1,0,0,1,0,0),\ + (1,0,0,0,0,0,0,1,1,1),\ + (0,1,0,0,0,1,1,1,0,1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] """ #From the array input, grab the dimensions of the array N=len(Array) From c8f62571021e1086778efc61f038947abc98e0de Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 7 Mar 2023 13:08:04 -0500 Subject: [PATCH 021/225] added covering array file to documentation, and made some changes to the file including richcmp and some formatting changes --- src/doc/en/reference/references/index.rst | 11 + src/sage/combinat/designs/covering_array.py | 857 ++++++++------------ 2 files changed, 361 insertions(+), 507 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 9f0c6c2b964..84f7737cba9 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1686,6 +1686,9 @@ REFERENCES: With an appendix by Ernst Kani. Canad. Math. Bull. 48 (2005), no. 1, 16--31. +.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. + .. [Col2004] Pierre Colmez, Invariant `\mathcal{L}` et derivees de valeurs propres de Frobenius, preprint, 2004. @@ -5433,6 +5436,10 @@ REFERENCES: Course material, 1997, ``_ +.. [Sher2006] G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. + .. [SHET2018] \O. Seker, P. Heggernes, T. Ekim, and Z. Caner Taskin. *Generation of random chordal graphs using subtrees of a tree*, :arxiv:`1810.13326v1`. @@ -6106,6 +6113,10 @@ REFERENCES: Math. Combin. Comput. **36** (2001), 95-118. http://www.info2.uqam.ca/~walsh_t/papers/Involutions%20paper.pdf +.. [Wal2007] R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 + .. [Walton1990] Mark A. Walton. *Fusion rules in Wess-Zumino-Witten models*. Nuclear Phys. B **340** (1990). diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 2ff7251d590..17cbd74ec1c 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -1,23 +1,26 @@ r""" Covering Arrays (CA) -A Covering Array, denoted CA(N,k,v,t), is an n by k array with entries from a -set of v elements with theproperty that in every selection of t columns, each -row contains every sequence of t-elements at least once. +A Covering Array, denoted CA`(N,k,v,t)`, is an `n` by `k` array with +entries from a set of `v` elements with the property that in every +selection of `t` columns, eachrow contains every sequence of +`t`-elements at least once. -An Orthogonal Array, denoted OA(N,k,v,t) is a covering array with the -property that each row contains every sequence of t-elements exactly once +An Orthogonal Array, denoted OA`(N,k,v,t)` is a covering array with the +property that each row contains every sequence of `t`-elements exactly +once REFERENCES: -.. [Col2004] \C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. +.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. -.. [Sher2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. - Designs, 14 (2006) pp. 202-213. -.. [Wal2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: +.. [Sher2006] G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, + "Covering arrays of higher strength from permutation + vectors". J. Combin. Designs, 14 (2006) pp. 202-213. + +.. [Wal2007] R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: Constructions and Existence". J. Math. Crypt. 1 (2007), pp.125-150 @@ -29,7 +32,7 @@ ------------------- """ -# **************************************************************************** +# ********************************************************************** # Copyright (C) 2022 Aaron Dwyer # # This program is free software: you can redistribute it and/or modify @@ -37,13 +40,17 @@ # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -# **************************************************************************** +# ********************************************************************** -from sage.rings.finite_rings.finite_field_constructor import GF import itertools import copy -class CoveringArray(): +from sage.rings.finite_rings.finite_field_constructor import GF +from sage.structure.sage_object import SageObject +from sage.structure.richcmp import richcmp + + +class CoveringArray(SageObject): r""" Covering Array (CA) @@ -52,128 +59,128 @@ class CoveringArray(): - ``Array`` -- The N by k array itself stored as a tuple of tuples. The N and k parameters are derived from this inputted array - - ``SymbolSet`` -- The collection of symbols that is used in ``Array``. - If left blank, then a symbol set will be assumed by checking for each - unique entry in the given ``Array``. In such a case it will be stored - as a list of symbols but any appropriate object may be used as long as - it has `len()` as a method + - ``SymbolSet`` -- The collection of symbols that is used in + ``Array``. If left blank, then a symbol set will be assumed by + checking for each unique entry in the given ``Array``. In such a + case it will be stored as a list of symbols but any appropriate + object may be used as long as it has `len()` as a method EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a','a','a','b'),\ - ('a','a','b','a'),\ - ('a','b','a','a'),\ - ('b','a','a','a'),\ - ('b','b','b','b')) + sage: C = (('a', 'a', 'a', 'b'), + ('a', 'a', 'b', 'a'), + ('a', 'b', 'a', 'a'), + ('b', 'a', 'a', 'a'), + ('b', 'b', 'b', 'b')) sage: CoveringArray(C) A 5 by 4 Covering Array with entries from ['a', 'b'] - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) sage: CoveringArray(C,[0, 1]) A 13 by 10 Covering Array with entries from [0, 1] - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C,GF(2)) A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) A 7 by 15 Covering Array with entries from [0, 1] - """ + def __init__(self, Array, SymbolSet=None): r""" Constructor function - EXAMPLES:: + EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a','a','a','b'),\ - ('a','a','b','a'),\ - ('a','b','a','a'),\ - ('b','a','a','a'),\ - ('b','b','b','b')) + sage: C = (('a', 'a', 'a', 'b'), + ('a', 'a', 'b', 'a'), + ('a', 'b', 'a', 'a'), + ('b', 'a', 'a', 'a'), + ('b', 'b', 'b', 'b')) sage: CoveringArray(C) A 5 by 4 Covering Array with entries from ['a', 'b'] - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) sage: CoveringArray(C,[0, 1]) A 13 by 10 Covering Array with entries from [0, 1] - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C,GF(2)) A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) A 7 by 15 Covering Array with entries from [0, 1] """ #From the array input, grab the dimensions of the array - N=len(Array) - self.__n=N - k=len(Array[0]) - self.__k=k - - #Array input is a tuple of tuples, the first thing to do is to sort - #the tuples lexicographically increasing - L=list(Array) + N = len(Array) + self.__n = N + k = len(Array[0]) + self.__k = k + + #Array input is a tuple of tuples, the first thing to do is to + #sort the tuples lexicographically increasing + L = list(Array) L.sort() - SortedArray=tuple(L) - self.__array=SortedArray + SortedArray = tuple(L) + self.__array = SortedArray for row in Array: - assert len(row)==len(Array[0]), "Not all rows have same length" + assert len(row) == len(Array[0]), "Not all rows have same length" #If no symbol set is given, then it may be assumed from what - #symbols are in the array by flattening the array and counting the - #number of unique entries. + #symbols are in the array by flattening the array and counting + #the number of unique entries. if SymbolSet is None: SymbolSet = list({x for l in Array for x in l}) SymbolSet.sort() @@ -181,16 +188,16 @@ def __init__(self, Array, SymbolSet=None): def numrows(self): r""" - Return the number of rows, N, of the covering array + Return the number of rows, `N`, of the covering array EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numrows() 5 @@ -199,16 +206,16 @@ def numrows(self): def numcols(self): r""" - Returns the number of columns, k, of the covering array + Returns the number of columns, `k`, of the covering array EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numcols() 4 @@ -222,11 +229,11 @@ def symbolset(self): EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.symbolset() Finite Field of size 2 @@ -238,71 +245,71 @@ def symbolset(self): def is_covering_array(self,strength): r""" - Check whether the tuple of tuples in ``Array`` forms a covering array - with the given strength. + Check whether the tuple of tuples in ``Array`` forms a covering + array with the given strength. EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C1 = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA1 = CoveringArray(C1,GF(2)) - sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) sage: CA2 = CoveringArray(C2,GF(3)) sage: CA1.is_covering_array(2) True @@ -311,116 +318,118 @@ def is_covering_array(self,strength): sage: CA2.is_covering_array(3) True """ - tupledict={} - a=[ttuple for ttuple in itertools.product(self.symbolset(),repeat=strength)] + tupledict = {} + a = [ttuple for ttuple in itertools.product(self.symbolset(), + repeat=strength)] for item in a: tupledict.update({item:0}) - for comb in itertools.combinations(range(self.numcols()),strength): + for comb in itertools.combinations(range(self.numcols()), + strength): wdict=copy.deepcopy(tupledict) for row in self.__array: - wdict[tuple([row[ti] for ti in comb])]+=1 + wdict[tuple([row[ti] for ti in comb])] += 1 if 0 in wdict.values(): return False return True def strength(self): r""" - Return the strength of the covering array, which is the parameter - t, such that in any selection of t columns of the array, every - t tuple appears at least once. + Return the strength of the covering array, which is the + parameter `t`, such that in any selection of `t` columns of the + array, every `t`-tuple appears at least once. EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.strength() 2 - sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2),\ - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2),\ - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0),\ - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1),\ - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2),\ - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2),\ - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1),\ - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2),\ - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0),\ - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2),\ - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0),\ - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0),\ - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1),\ - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1),\ - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1),\ - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0),\ - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2),\ - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1),\ - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1),\ - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2),\ - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1),\ - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0),\ - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1),\ - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0),\ - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0),\ - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2),\ - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2),\ - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0),\ - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0),\ - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1),\ - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0),\ - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1),\ - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2),\ - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1),\ - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1),\ - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2),\ - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0),\ - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1),\ - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1),\ - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1),\ - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0),\ - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0),\ - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2),\ - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0),\ - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2),\ - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1),\ - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2),\ - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2),\ - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1),\ - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0),\ - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2),\ - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2),\ - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), + (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) sage: CA2 = CoveringArray(C2,GF(3)) sage: CA2.strength() 3 """ - finished=False - strength=1 + finished = False + strength = 1 while not finished: if self.is_covering_array(strength): - strength+=1 + strength += 1 else: - strength-=1 - finished=True + strength -= 1 + finished = True return strength def levels(self): r""" Return the number of levels for the covering array, which is - the parameter v, such that v is the size of the symbol set of the - array. + the parameter `v`, such that `v` is the size of the symbol + set of the array. EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) + sage: C = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.levels() 2 @@ -429,93 +438,90 @@ def levels(self): def array_representation(self): r""" - Return the covering array as a tuple of tuples, but where - the output is such that each row of the array is sorted in - lexicographic order + Return the covering array as a tuple of tuples, the output is + such that each row of the array is sorted in lexicographic order EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1),) + sage: C = ((1, 1, 1, 0), + (0, 0, 0, 0), + (1, 0, 1, 1), + (1, 1, 0, 1), + (0, 1, 1, 1),) sage: CA = CoveringArray(C,GF(2)) sage: CA.array_representation() - ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) + ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), ... + (1, 1, 0, 1), (1, 1, 1, 0)) """ return self.__array - - def __repr__(self): + def _repr_(self): r""" Returns a string that describes self - EXAMPLES:: + EXAMPLES:: - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a','a','a','b'),\ - ('a','a','b','a'),\ - ('a','b','a','a'),\ - ('b','a','a','a'),\ - ('b','b','b','b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] - - sage: C = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a', 'a', 'a', 'b'), + ('a', 'a', 'b', 'a'), + ('a', 'b', 'a', 'a'), + ('b', 'a', 'a', 'a'), + ('b', 'b', 'b', 'b')) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from ['a', 'b'] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] """ return 'A {} by {} Covering Array with entries from {}'.format( self.numrows(), self.numcols(), self.symbolset()) - __str__=__repr__ - - def pprint(self): + def pp(self): r""" Prints the covering array in a format easy for users to read EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA = CoveringArray(C) sage: CA.pprint() @@ -537,219 +543,56 @@ def __hash__(self): EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA = CoveringArray(C) sage: hash(CA) 4367534393624660384 """ - return hash((self.array_representation(),tuple(self.symbolset()))) + return hash((self.array_representation(), tuple(self.symbolset()))) - def __eq__(self, other): + def _richcmp_(self, other, op): r""" - Return whether two covering arrays are equal by considering the - array with rows sorted in lexicographic order + Do the comparison. EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1==CA2 - True - sage: CA1==CA3 - False - """ - if self.array_representation() == other.array_representation(): - return True - else: - return False - - def __neq__(self, other): - r""" - Return whether two covering arrays are not equal by considering - the array with rows sorted in lexicographic order - - EXAMPLES:: + sage: C1 = ((1, 1, 1, 0), + (0, 0, 0, 0), + (1, 0, 1, 1), + (1, 1, 0, 1), + (0, 1, 1, 1)) + sage: C2 = ((1, 1, 1, 0), + (1, 1, 0, 1), + (1, 0, 1, 1), + (0, 1, 1, 1), + (0, 0, 0, 0)) + sage: C3 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((1,1,1,0),\ - (1,1,0,1),\ - (1,0,1,1),\ - (0,1,1,1),\ - (0,0,0,0)) - sage: C3 = ((0,0,0,0,0,0,0,0,0,0),\ - (1,1,1,1,1,1,1,1,1,1),\ - (1,1,1,0,1,0,0,0,0,1),\ - (1,0,1,1,0,1,0,1,0,0),\ - (1,0,0,0,1,1,1,0,0,0),\ - (0,1,1,0,0,1,0,0,1,0),\ - (0,0,1,0,1,0,1,1,1,0),\ - (1,1,0,1,0,0,1,0,1,0),\ - (0,0,0,1,1,1,0,0,1,1),\ - (0,0,1,1,0,0,1,0,0,1),\ - (0,1,0,1,1,0,0,1,0,0),\ - (1,0,0,0,0,0,0,1,1,1),\ - (0,1,0,0,0,1,1,1,0,1)) sage: CA1 = CoveringArray(C1) sage: CA2 = CoveringArray(C2) sage: CA3 = CoveringArray(C3) - sage: CA1!=CA2 - False - sage: CA1!=CA3 + sage: CA1 == CA2 True - """ - if self.array_representation() != other.array_representation(): - return True - else: - return False - - def __lt__(self, other): - r""" - Return whether one covering array is less than another - based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA1= CA1 True - """ - if self.array_representation() <= other.array_representation(): - return True - else: - return False - - def __gt__(self, other): - r""" - Return whether one covering array is greater than - another based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA1>CA2 - False - """ - if self.array_representation() > other.array_representation(): - return True - else: - return False - - def __ge__(self, other): - r""" - Return whether one covering array is greater than or - equal to another based on the lexicographic order on the rows - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1,1,1,0),\ - (0,0,0,0),\ - (1,0,1,1),\ - (1,1,0,1),\ - (0,1,1,1)) - sage: C2 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0),\ - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1),\ - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1),\ - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1),\ - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0),\ - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA1>=CA2 + sage: CA1 < CA2 False """ - if self.array_representation() >= other.array_representation(): - return True - else: - return False + return richcmp(self.array_representation(), + other.array_representation(), op) From 978415967b551dadbf12e8cad25c265d5bc67f7c Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Tue, 7 Mar 2023 23:54:32 -0500 Subject: [PATCH 022/225] Fixed some more formatting issues and doctests for CA file, richcmp is not yet working --- src/sage/combinat/designs/covering_array.py | 559 ++++++++++---------- 1 file changed, 280 insertions(+), 279 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 17cbd74ec1c..fb94f879b29 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -69,45 +69,45 @@ class CoveringArray(SageObject): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = (('a', 'a', 'a', 'b'), - ('a', 'a', 'b', 'a'), - ('a', 'b', 'a', 'a'), - ('b', 'a', 'a', 'a'), - ('b', 'b', 'b', 'b')) + ....: ('a', 'a', 'b', 'a'), + ....: ('a', 'b', 'a', 'a'), + ....: ('b', 'a', 'a', 'a'), + ....: ('b', 'b', 'b', 'b')) sage: CoveringArray(C) A 5 by 4 Covering Array with entries from ['a', 'b'] sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) + ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) sage: CoveringArray(C,[0, 1]) A 13 by 10 Covering Array with entries from [0, 1] sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C,GF(2)) A 6 by 10 Covering Array with entries from Finite Field of size 2 sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) A 7 by 15 Covering Array with entries from [0, 1] """ @@ -116,51 +116,51 @@ def __init__(self, Array, SymbolSet=None): r""" Constructor function - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a', 'a', 'a', 'b'), - ('a', 'a', 'b', 'a'), - ('a', 'b', 'a', 'a'), - ('b', 'a', 'a', 'a'), - ('b', 'b', 'b', 'b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + EXAMPLES:: - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a', 'a', 'a', 'b'), + ....: ('a', 'a', 'b', 'a'), + ....: ('a', 'b', 'a', 'a'), + ....: ('b', 'a', 'a', 'a'), + ....: ('b', 'b', 'b', 'b')) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from ['a', 'b'] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] """ #From the array input, grab the dimensions of the array N = len(Array) @@ -194,10 +194,10 @@ def numrows(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numrows() 5 @@ -212,10 +212,10 @@ def numcols(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.numcols() 4 @@ -230,10 +230,10 @@ def symbolset(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.symbolset() Finite Field of size 2 @@ -252,64 +252,64 @@ def is_covering_array(self,strength): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: CA1 = CoveringArray(C1,GF(2)) sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) sage: CA2 = CoveringArray(C2,GF(3)) sage: CA1.is_covering_array(2) True @@ -341,67 +341,67 @@ def strength(self): EXAMPLES:: sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) - sage: CA = CoveringArray(C,GF(2)) + sage: C1 = ((1, 1, 1, 0), + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) + sage: CA = CoveringArray(C1,GF(2)) sage: CA.strength() 2 sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) sage: CA2 = CoveringArray(C2,GF(3)) sage: CA2.strength() 3 @@ -426,10 +426,10 @@ def levels(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) sage: CA.levels() 2 @@ -445,14 +445,14 @@ def array_representation(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((1, 1, 1, 0), - (0, 0, 0, 0), - (1, 0, 1, 1), - (1, 1, 0, 1), - (0, 1, 1, 1),) + ....: (0, 0, 0, 0), + ....: (1, 0, 1, 1), + ....: (1, 1, 0, 1), + ....: (0, 1, 1, 1)) sage: CA = CoveringArray(C,GF(2)) sage: CA.array_representation() - ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), ... - (1, 1, 0, 1), (1, 1, 1, 0)) + ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), + (1, 1, 1, 0)) """ return self.__array @@ -460,52 +460,52 @@ def _repr_(self): r""" Returns a string that describes self - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a', 'a', 'a', 'b'), - ('a', 'a', 'b', 'a'), - ('a', 'b', 'a', 'a'), - ('b', 'a', 'a', 'a'), - ('b', 'b', 'b', 'b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + EXAMPLES:: - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 + sage: from sage.combinat.designs.covering_array import CoveringArray + sage: C = (('a', 'a', 'a', 'b'), + ....: ('a', 'a', 'b', 'a'), + ....: ('a', 'b', 'a', 'a'), + ....: ('b', 'a', 'a', 'a'), + ....: ('b', 'b', 'b', 'b')) + sage: CoveringArray(C) + A 5 by 4 Covering Array with entries from ['a', 'b'] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), + ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), + ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), + ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), + ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), + ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), + ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), + ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), + ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), + ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) + sage: CoveringArray(C,[0, 1]) + A 13 by 10 Covering Array with entries from [0, 1] + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C,GF(2)) + A 6 by 10 Covering Array with entries from Finite Field of size 2 - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] - """ + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + sage: CoveringArray(C) + A 7 by 15 Covering Array with entries from [0, 1] + """ return 'A {} by {} Covering Array with entries from {}'.format( self.numrows(), self.numcols(), self.symbolset()) @@ -517,14 +517,14 @@ def pp(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA = CoveringArray(C) - sage: CA.pprint() + sage: CA.pp() (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) @@ -544,18 +544,20 @@ def __hash__(self): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) + ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA = CoveringArray(C) sage: hash(CA) 4367534393624660384 """ return hash((self.array_representation(), tuple(self.symbolset()))) + + ''' def _richcmp_(self, other, op): r""" Do the comparison. @@ -564,22 +566,21 @@ def _richcmp_(self, other, op): sage: from sage.combinat.designs.covering_array import CoveringArray sage: C1 = ((1, 1, 1, 0), - (0, 0, 0, 0), - (1, 0, 1, 1), - (1, 1, 0, 1), - (0, 1, 1, 1)) + ....: (0, 0, 0, 0), + ....: (1, 0, 1, 1), + ....: (1, 1, 0, 1), + ....: (0, 1, 1, 1)) sage: C2 = ((1, 1, 1, 0), - (1, 1, 0, 1), - (1, 0, 1, 1), - (0, 1, 1, 1), - (0, 0, 0, 0)) + ....: (1, 1, 0, 1), + ....: (1, 0, 1, 1), + ....: (0, 1, 1, 1), + ....: (0, 0, 0, 0)) sage: C3 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CA1 = CoveringArray(C1) sage: CA2 = CoveringArray(C2) sage: CA3 = CoveringArray(C3) @@ -594,5 +595,5 @@ def _richcmp_(self, other, op): sage: CA1 < CA2 False """ - return richcmp(self.array_representation(), - other.array_representation(), op) + return richcmp(self.array_representation(), other.array_representation(), op) + ''' \ No newline at end of file From 4aa24acec21c6128d9310b523df0e4ab87c6cfd6 Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Thu, 9 Mar 2023 23:57:11 -0500 Subject: [PATCH 023/225] added decorator to richcmp method as needed, linked references --- src/sage/combinat/designs/covering_array.py | 27 +++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index fb94f879b29..5c833dd90d5 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -12,17 +12,17 @@ REFERENCES: -.. [Colb2004] C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. +.. [Colb2004]__ C.J. Colbourn. “Combinatorial aspects of covering arrays”. + Matematiche (Catania) 59 (2004), pp. 125–172. -.. [Sher2006] G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, - "Covering arrays of higher strength from permutation - vectors". J. Combin. Designs, 14 (2006) pp. 202-213. +.. [Sher2006]__ G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, + "Covering arrays of higher strength from permutation + vectors". J. Combin. Designs, 14 (2006) pp. 202-213. -.. [Wal2007] R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), - pp.125-150 +.. [Wal2007]__ R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 AUTHORS: @@ -47,9 +47,9 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.structure.sage_object import SageObject -from sage.structure.richcmp import richcmp - +from sage.structure.richcmp import richcmp, richcmp_method +@richcmp_method class CoveringArray(SageObject): r""" Covering Array (CA) @@ -556,9 +556,7 @@ def __hash__(self): """ return hash((self.array_representation(), tuple(self.symbolset()))) - - ''' - def _richcmp_(self, other, op): + def __richcmp__(self, other, op): r""" Do the comparison. @@ -595,5 +593,4 @@ def _richcmp_(self, other, op): sage: CA1 < CA2 False """ - return richcmp(self.array_representation(), other.array_representation(), op) - ''' \ No newline at end of file + return richcmp(self.array_representation(), other.array_representation(), op) \ No newline at end of file From bc1917a5211a6947ed66f6a005d0f2b96cc637af Mon Sep 17 00:00:00 2001 From: Aaron Dwyer Date: Fri, 10 Mar 2023 01:58:37 -0500 Subject: [PATCH 024/225] Added covering arrays to designs/design_catalog.py. Also edited CA file, changing some variable names and some doctest formatting, also sset is changed to a tuple and changed functions to use internal attributes --- src/sage/combinat/designs/covering_array.py | 138 ++++++++++---------- src/sage/combinat/designs/design_catalog.py | 2 + 2 files changed, 69 insertions(+), 71 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 5c833dd90d5..512903e609a 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -12,17 +12,11 @@ REFERENCES: -.. [Colb2004]__ C.J. Colbourn. “Combinatorial aspects of covering arrays”. - Matematiche (Catania) 59 (2004), pp. 125–172. +- [Colb2004]_ +- [Sher2006]_ -.. [Sher2006]__ G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, - "Covering arrays of higher strength from permutation - vectors". J. Combin. Designs, 14 (2006) pp. 202-213. - -.. [Wal2007]__ R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), - pp.125-150 +- [Wal2007]_ AUTHORS: @@ -56,14 +50,15 @@ class CoveringArray(SageObject): INPUT: - - ``Array`` -- The N by k array itself stored as a tuple of tuples. - The N and k parameters are derived from this inputted array + - ``array`` -- The `N` by `k` array itself stored as a tuple of + tuples. The `N` and `k` parameters are derived from this inputted + array. - - ``SymbolSet`` -- The collection of symbols that is used in - ``Array``. If left blank, then a symbol set will be assumed by - checking for each unique entry in the given ``Array``. In such a - case it will be stored as a list of symbols but any appropriate - object may be used as long as it has `len()` as a method + - ``symbol_set`` -- The collection of symbols that is used in + ``array``. If left blank, then a symbol set will be assumed by + checking for each unique entry in the given ``array``. In such a + case it will be stored as a tuple of symbols but any appropriate + object may be used as long as it has ``len()`` as a method. EXAMPLES:: @@ -74,7 +69,7 @@ class CoveringArray(SageObject): ....: ('b', 'a', 'a', 'a'), ....: ('b', 'b', 'b', 'b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] + A 5 by 4 Covering Array with entries from ('a', 'b') sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), @@ -89,8 +84,8 @@ class CoveringArray(SageObject): ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + sage: CoveringArray(C,(0, 1)) + A 13 by 10 Covering Array with entries from (0, 1) sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), @@ -109,12 +104,12 @@ class CoveringArray(SageObject): ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + A 7 by 15 Covering Array with entries from (0, 1) """ - def __init__(self, Array, SymbolSet=None): + def __init__(self, array, symbol_set=None): r""" - Constructor function + Constructor function. EXAMPLES:: @@ -125,7 +120,7 @@ def __init__(self, Array, SymbolSet=None): ....: ('b', 'a', 'a', 'a'), ....: ('b', 'b', 'b', 'b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] + A 5 by 4 Covering Array with entries from ('a', 'b') sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), @@ -140,8 +135,8 @@ def __init__(self, Array, SymbolSet=None): ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + sage: CoveringArray(C,(0, 1)) + A 13 by 10 Covering Array with entries from (0, 1) sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), @@ -160,35 +155,35 @@ def __init__(self, Array, SymbolSet=None): ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + A 7 by 15 Covering Array with entries from (0, 1) """ #From the array input, grab the dimensions of the array - N = len(Array) - self.__n = N - k = len(Array[0]) - self.__k = k + N = len(array) + self._n = N + k = len(array[0]) + self._k = k - #Array input is a tuple of tuples, the first thing to do is to + #array input is a tuple of tuples, the first thing to do is to #sort the tuples lexicographically increasing - L = list(Array) + L = list(array) L.sort() - SortedArray = tuple(L) - self.__array = SortedArray + self._array = tuple(L) - for row in Array: - assert len(row) == len(Array[0]), "Not all rows have same length" + for row in array: + assert len(row) == len(array[0]), "Not all rows have same length" #If no symbol set is given, then it may be assumed from what #symbols are in the array by flattening the array and counting #the number of unique entries. - if SymbolSet is None: - SymbolSet = list({x for l in Array for x in l}) - SymbolSet.sort() - self.__sset=SymbolSet + if symbol_set is None: + symbol_set = list({x for l in array for x in l}) + symbol_set.sort() + symbol_set = tuple(symbol_set) + self._sset = symbol_set - def numrows(self): + def number_rows(self): r""" - Return the number of rows, `N`, of the covering array + Return the number of rows, `N`, of the covering array. EXAMPLES:: @@ -199,14 +194,14 @@ def numrows(self): ....: (0, 1, 1, 1), ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) - sage: CA.numrows() + sage: CA.number_rows() 5 """ - return self.__n + return self._n - def numcols(self): + def number_columns(self): r""" - Returns the number of columns, `k`, of the covering array + Return the number of columns, `k`, of the covering array. EXAMPLES:: @@ -217,12 +212,12 @@ def numcols(self): ....: (0, 1, 1, 1), ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) - sage: CA.numcols() + sage: CA.number_columns() 4 """ - return self.__k + return self._k - def symbolset(self): + def symbol_set(self): r""" Return the symbol set of the array. @@ -235,13 +230,13 @@ def symbolset(self): ....: (0, 1, 1, 1), ....: (0, 0, 0, 0)) sage: CA = CoveringArray(C,GF(2)) - sage: CA.symbolset() + sage: CA.symbol_set() Finite Field of size 2 sage: CA = CoveringArray(C) - sage: CA.symbolset() - [0, 1] + sage: CA.symbol_set() + (0, 1) """ - return self.__sset + return self._sset def is_covering_array(self,strength): r""" @@ -319,14 +314,13 @@ def is_covering_array(self,strength): True """ tupledict = {} - a = [ttuple for ttuple in itertools.product(self.symbolset(), + a = [ttuple for ttuple in itertools.product(self._sset, repeat=strength)] for item in a: tupledict.update({item:0}) - for comb in itertools.combinations(range(self.numcols()), - strength): + for comb in itertools.combinations(range(self._k), strength): wdict=copy.deepcopy(tupledict) - for row in self.__array: + for row in self._array: wdict[tuple([row[ti] for ti in comb])] += 1 if 0 in wdict.values(): return False @@ -434,12 +428,12 @@ def levels(self): sage: CA.levels() 2 """ - return len(self.__sset) + return len(self._sset) def array_representation(self): r""" Return the covering array as a tuple of tuples, the output is - such that each row of the array is sorted in lexicographic order + such that each row of the array is sorted in lexicographic order. EXAMPLES:: @@ -454,11 +448,11 @@ def array_representation(self): ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)) """ - return self.__array + return self._array def _repr_(self): r""" - Returns a string that describes self + Return a string that describes self. EXAMPLES:: @@ -469,7 +463,7 @@ def _repr_(self): ....: ('b', 'a', 'a', 'a'), ....: ('b', 'b', 'b', 'b')) sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ['a', 'b'] + A 5 by 4 Covering Array with entries from ('a', 'b') sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), @@ -484,8 +478,8 @@ def _repr_(self): ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,[0, 1]) - A 13 by 10 Covering Array with entries from [0, 1] + sage: CoveringArray(C,(0, 1)) + A 13 by 10 Covering Array with entries from (0, 1) sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), @@ -504,14 +498,14 @@ def _repr_(self): ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from [0, 1] + A 7 by 15 Covering Array with entries from (0, 1) """ return 'A {} by {} Covering Array with entries from {}'.format( - self.numrows(), self.numcols(), self.symbolset()) + self._n, self._k, self._sset) def pp(self): r""" - Prints the covering array in a format easy for users to read + Prints the covering array in a format easy for users to read. EXAMPLES:: @@ -533,12 +527,12 @@ def pp(self): (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) """ - for i in self.__array: + for i in self._array: print(str(i)) def __hash__(self): r""" - Hashs the tuple of tuples and all tuples inside + Hashs the tuple of tuples and all tuples inside. EXAMPLES:: @@ -554,7 +548,8 @@ def __hash__(self): sage: hash(CA) 4367534393624660384 """ - return hash((self.array_representation(), tuple(self.symbolset()))) + return hash((self.array_representation(), + tuple(self.symbol_set()))) def __richcmp__(self, other, op): r""" @@ -593,4 +588,5 @@ def __richcmp__(self, other, op): sage: CA1 < CA2 False """ - return richcmp(self.array_representation(), other.array_representation(), op) \ No newline at end of file + return richcmp(self.array_representation(), + other.array_representation(), op) \ No newline at end of file diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index a9572e119c0..bd576df0749 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -119,3 +119,5 @@ lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) + +lazy_import('sage.combinat.designs.covering_array', 'CoveringArray') \ No newline at end of file From a25dfc653da9ecd52ad06a145592142f7a3ed785 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 18:43:03 -0400 Subject: [PATCH 025/225] Removed covering array file, instead put is_covering_array in designs_pyx to be consistent with is_orthogonal_array. Since covering array file is gone, removed links to it in module list and design catalogue. --- src/doc/en/reference/combinat/module_list.rst | 1 - src/sage/combinat/designs/covering_array.py | 592 ------------------ src/sage/combinat/designs/design_catalog.py | 2 - src/sage/combinat/designs/designs_pyx.pyx | 195 ++++++ 4 files changed, 195 insertions(+), 595 deletions(-) delete mode 100644 src/sage/combinat/designs/covering_array.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 51ed68802b9..3bfa10ed3f7 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -92,7 +92,6 @@ Comprehensive Module List sage/combinat/designs/resolvable_bibd sage/combinat/designs/group_divisible_designs sage/combinat/designs/block_design - sage/combinat/designs/covering_array sage/combinat/designs/covering_design sage/combinat/designs/database sage/combinat/designs/design_catalog diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py deleted file mode 100644 index 512903e609a..00000000000 --- a/src/sage/combinat/designs/covering_array.py +++ /dev/null @@ -1,592 +0,0 @@ -r""" -Covering Arrays (CA) - -A Covering Array, denoted CA`(N,k,v,t)`, is an `n` by `k` array with -entries from a set of `v` elements with the property that in every -selection of `t` columns, eachrow contains every sequence of -`t`-elements at least once. - -An Orthogonal Array, denoted OA`(N,k,v,t)` is a covering array with the -property that each row contains every sequence of `t`-elements exactly -once - -REFERENCES: - -- [Colb2004]_ - -- [Sher2006]_ - -- [Wal2007]_ - -AUTHORS: - -- Aaron Dwyer and brett stevens (2022): initial version - -Classes and methods -------------------- -""" - -# ********************************************************************** -# Copyright (C) 2022 Aaron Dwyer -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# https://www.gnu.org/licenses/ -# ********************************************************************** - -import itertools -import copy - -from sage.rings.finite_rings.finite_field_constructor import GF -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import richcmp, richcmp_method - -@richcmp_method -class CoveringArray(SageObject): - r""" - Covering Array (CA) - - INPUT: - - - ``array`` -- The `N` by `k` array itself stored as a tuple of - tuples. The `N` and `k` parameters are derived from this inputted - array. - - - ``symbol_set`` -- The collection of symbols that is used in - ``array``. If left blank, then a symbol set will be assumed by - checking for each unique entry in the given ``array``. In such a - case it will be stored as a tuple of symbols but any appropriate - object may be used as long as it has ``len()`` as a method. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a', 'a', 'a', 'b'), - ....: ('a', 'a', 'b', 'a'), - ....: ('a', 'b', 'a', 'a'), - ....: ('b', 'a', 'a', 'a'), - ....: ('b', 'b', 'b', 'b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ('a', 'b') - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,(0, 1)) - A 13 by 10 Covering Array with entries from (0, 1) - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from (0, 1) - """ - - def __init__(self, array, symbol_set=None): - r""" - Constructor function. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a', 'a', 'a', 'b'), - ....: ('a', 'a', 'b', 'a'), - ....: ('a', 'b', 'a', 'a'), - ....: ('b', 'a', 'a', 'a'), - ....: ('b', 'b', 'b', 'b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ('a', 'b') - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,(0, 1)) - A 13 by 10 Covering Array with entries from (0, 1) - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from (0, 1) - """ - #From the array input, grab the dimensions of the array - N = len(array) - self._n = N - k = len(array[0]) - self._k = k - - #array input is a tuple of tuples, the first thing to do is to - #sort the tuples lexicographically increasing - L = list(array) - L.sort() - self._array = tuple(L) - - for row in array: - assert len(row) == len(array[0]), "Not all rows have same length" - - #If no symbol set is given, then it may be assumed from what - #symbols are in the array by flattening the array and counting - #the number of unique entries. - if symbol_set is None: - symbol_set = list({x for l in array for x in l}) - symbol_set.sort() - symbol_set = tuple(symbol_set) - self._sset = symbol_set - - def number_rows(self): - r""" - Return the number of rows, `N`, of the covering array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA = CoveringArray(C,GF(2)) - sage: CA.number_rows() - 5 - """ - return self._n - - def number_columns(self): - r""" - Return the number of columns, `k`, of the covering array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA = CoveringArray(C,GF(2)) - sage: CA.number_columns() - 4 - """ - return self._k - - def symbol_set(self): - r""" - Return the symbol set of the array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA = CoveringArray(C,GF(2)) - sage: CA.symbol_set() - Finite Field of size 2 - sage: CA = CoveringArray(C) - sage: CA.symbol_set() - (0, 1) - """ - return self._sset - - def is_covering_array(self,strength): - r""" - Check whether the tuple of tuples in ``Array`` forms a covering - array with the given strength. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA1 = CoveringArray(C1,GF(2)) - sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - sage: CA2 = CoveringArray(C2,GF(3)) - sage: CA1.is_covering_array(2) - True - sage: CA1.is_covering_array(3) - False - sage: CA2.is_covering_array(3) - True - """ - tupledict = {} - a = [ttuple for ttuple in itertools.product(self._sset, - repeat=strength)] - for item in a: - tupledict.update({item:0}) - for comb in itertools.combinations(range(self._k), strength): - wdict=copy.deepcopy(tupledict) - for row in self._array: - wdict[tuple([row[ti] for ti in comb])] += 1 - if 0 in wdict.values(): - return False - return True - - def strength(self): - r""" - Return the strength of the covering array, which is the - parameter `t`, such that in any selection of `t` columns of the - array, every `t`-tuple appears at least once. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA = CoveringArray(C1,GF(2)) - sage: CA.strength() - 2 - sage: C2 = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - sage: CA2 = CoveringArray(C2,GF(3)) - sage: CA2.strength() - 3 - """ - finished = False - strength = 1 - while not finished: - if self.is_covering_array(strength): - strength += 1 - else: - strength -= 1 - finished = True - return strength - - def levels(self): - r""" - Return the number of levels for the covering array, which is - the parameter `v`, such that `v` is the size of the symbol - set of the array. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: CA = CoveringArray(C,GF(2)) - sage: CA.levels() - 2 - """ - return len(self._sset) - - def array_representation(self): - r""" - Return the covering array as a tuple of tuples, the output is - such that each row of the array is sorted in lexicographic order. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((1, 1, 1, 0), - ....: (0, 0, 0, 0), - ....: (1, 0, 1, 1), - ....: (1, 1, 0, 1), - ....: (0, 1, 1, 1)) - sage: CA = CoveringArray(C,GF(2)) - sage: CA.array_representation() - ((0, 0, 0, 0), (0, 1, 1, 1), (1, 0, 1, 1), (1, 1, 0, 1), - (1, 1, 1, 0)) - """ - return self._array - - def _repr_(self): - r""" - Return a string that describes self. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = (('a', 'a', 'a', 'b'), - ....: ('a', 'a', 'b', 'a'), - ....: ('a', 'b', 'a', 'a'), - ....: ('b', 'a', 'a', 'a'), - ....: ('b', 'b', 'b', 'b')) - sage: CoveringArray(C) - A 5 by 4 Covering Array with entries from ('a', 'b') - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (1, 1, 1, 0, 1, 0, 0, 0, 0, 1), - ....: (1, 0, 1, 1, 0, 1, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 1, 1, 1, 0, 0, 0), - ....: (0, 1, 1, 0, 0, 1, 0, 0, 1, 0), - ....: (0, 0, 1, 0, 1, 0, 1, 1, 1, 0), - ....: (1, 1, 0, 1, 0, 0, 1, 0, 1, 0), - ....: (0, 0, 0, 1, 1, 1, 0, 0, 1, 1), - ....: (0, 0, 1, 1, 0, 0, 1, 0, 0, 1), - ....: (0, 1, 0, 1, 1, 0, 0, 1, 0, 0), - ....: (1, 0, 0, 0, 0, 0, 0, 1, 1, 1), - ....: (0, 1, 0, 0, 0, 1, 1, 1, 0, 1)) - sage: CoveringArray(C,(0, 1)) - A 13 by 10 Covering Array with entries from (0, 1) - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C,GF(2)) - A 6 by 10 Covering Array with entries from Finite Field of size 2 - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CoveringArray(C) - A 7 by 15 Covering Array with entries from (0, 1) - """ - return 'A {} by {} Covering Array with entries from {}'.format( - self._n, self._k, self._sset) - - def pp(self): - r""" - Prints the covering array in a format easy for users to read. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C) - sage: CA.pp() - (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) - (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1) - (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1) - (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1) - (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0) - (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0) - """ - for i in self._array: - print(str(i)) - - def __hash__(self): - r""" - Hashs the tuple of tuples and all tuples inside. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA = CoveringArray(C) - sage: hash(CA) - 4367534393624660384 - """ - return hash((self.array_representation(), - tuple(self.symbol_set()))) - - def __richcmp__(self, other, op): - r""" - Do the comparison. - - EXAMPLES:: - - sage: from sage.combinat.designs.covering_array import CoveringArray - sage: C1 = ((1, 1, 1, 0), - ....: (0, 0, 0, 0), - ....: (1, 0, 1, 1), - ....: (1, 1, 0, 1), - ....: (0, 1, 1, 1)) - sage: C2 = ((1, 1, 1, 0), - ....: (1, 1, 0, 1), - ....: (1, 0, 1, 1), - ....: (0, 1, 1, 1), - ....: (0, 0, 0, 0)) - sage: C3 = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 0, 0)) - sage: CA1 = CoveringArray(C1) - sage: CA2 = CoveringArray(C2) - sage: CA3 = CoveringArray(C3) - sage: CA1 == CA2 - True - sage: CA1 == CA3 - False - sage: CA1 != CA3 - True - sage: CA3 >= CA1 - True - sage: CA1 < CA2 - False - """ - return richcmp(self.array_representation(), - other.array_representation(), op) \ No newline at end of file diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index bd576df0749..a9572e119c0 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -119,5 +119,3 @@ lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) - -lazy_import('sage.combinat.designs.covering_array', 'CoveringArray') \ No newline at end of file diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index c72baf64b6b..2de6cdf33b9 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -7,6 +7,201 @@ Functions --------- """ +def is_covering_array(array,strength=None,symbol_set=None,verbose=False,parameters=False): + r""" + Checks if the input is a covering array with given strength + + - ``array`` -- The Covering Array to be tested + + - ``strength`` (integer) -- The parameter `t` of the covering array, such that + in any selection of `t` columns of the array, every `t`-tuple appears + at least once. If set to None then all t>0 are tested to and the + maximal strength is used. + + - ``symbol_set`` -- The collection of symbols that is used in + ``array``. If set to None, then a symbol set will be assumed by + checking for each unique entry in the given ``array``. + + - ``verbose`` (boolean) -- whether to display some information about the + covering array + + - ``parameters`` (boolean) -- whether to return the parameters of + the Covering Array. If set to ``True``, the function returns a pair + ``(boolean_answer,(N,t,k,v))`` + + EXAMPLES:: + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = ((1, 1, 1, 0), + ....: (1, 1, 0, 0), + ....: (0, 0, 0)) + sage: is_covering_array(C) + Traceback (most recent call last): + ... + ValueError: Not all rows are the same length, row 2 is not the same length as row 0 + + sage: C = (('a', 'a', 'a', 'b'), + ....: ('a', 'a', 'b', 'a'), + ....: ('a', 'b', 'a', 'a'), + ....: ('b', 'a', 'a', 'a'), + ....: ('b', 'b', 'b', 'b')) + sage: is_covering_array(C,verbose=True) + A 5 by 4 Covering Array with strength 2 with entries from ['a', 'b'] + True + sage: is_covering_array(C,strength=3,verbose=True) + A 5 by 4 Covering Array with strength 0 with entries from ['a', 'b'] + False + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = ((0, 1, 0), + ....: (1, 1, 0), + ....: (1, 0, 0)) + sage: is_covering_array(C,verbose=True) + A 3 by 3 Covering Array with strength 0 with entries from [0, 1] + True + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 2, 0)) + sage: is_covering_array(C,symbol_set=(0,1)) + Traceback (most recent call last): + ... + ValueError: 2 appears in the array but not in the given symbol set + + sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), + ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: is_covering_array(C,parameters=True) + (True, (53, 3, 13, 3)) + + """ + from itertools import product, combinations + from copy import deepcopy + + number_rows=len(array) + number_columns=len(array[0]) + + for row in range(number_rows): + if len(array[row]) != number_columns: + raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(row)) + + if symbol_set is None: + symbol_set = list({x for l in array for x in l}) + symbol_set.sort() + else: + for l in array: + for x in l: + if x not in symbol_set: + raise ValueError("{} appears in the array but not in the given symbol set".format(x)) + + if strength is None: + wstrength = 1 + else: + wstrength = strength + finished = False + + # if no strength inputted, tries increasing values for t until one does not work + # if strength is inputted ends after one check + while finished == False: + # A dictionary to count how many times each t-tuple appears in the array + tupledict={} + a=[ttuple for ttuple in product(symbol_set,repeat=wstrength)] + for item in a: + tupledict.update({item:0}) + + # Iterates over every possible selections of t columns, and count the t-tuples appearing in each selection + for comb in combinations(range(number_columns),wstrength): + wdict=deepcopy(tupledict) + for row in array: + wdict[tuple([row[ti] for ti in comb])]+=1 + + # Checks if any t-tuple is not covered in current column selection + if 0 in wdict.values(): + if strength != None: + wstrength = 0 + result = False + finished = True + break + else: + wstrength -=1 + finished = True + break + + else: + if strength != None: + result = True + finished = True + break + if finished == False: + wstrength +=1 + + if verbose: + print('A {} by {} Covering Array with strength {} with entries from {}'.format(number_rows,number_columns,wstrength,symbol_set)) + + if strength is None: + if parameters: + return (True,(number_rows,wstrength,number_columns,len(symbol_set))) + else: + return True + + else: + if parameters: + return (result,(number_rows,wstrength,number_columns,len(symbol_set))) + else: + return result + from sage.data_structures.bitset_base cimport * from libc.string cimport memset From 17cc2ab53e7b3ed03cabc69be65e78a355068afd Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 19:54:10 -0400 Subject: [PATCH 026/225] Fixed some typos --- src/sage/combinat/designs/designs_pyx.pyx | 68 ++++++++++++----------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 2de6cdf33b9..c93ddf10fb3 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -10,25 +10,25 @@ Functions def is_covering_array(array,strength=None,symbol_set=None,verbose=False,parameters=False): r""" Checks if the input is a covering array with given strength - + - ``array`` -- The Covering Array to be tested - - - ``strength`` (integer) -- The parameter `t` of the covering array, such that - in any selection of `t` columns of the array, every `t`-tuple appears - at least once. If set to None then all t>0 are tested to and the - maximal strength is used. + + - ``strength`` (integer) -- The parameter `t` of the covering array, + such thatin any selection of `t` columns of the array, every `t` + -tuple appearsat least once. If set to None then all t>0 are + tested to and themaximal strength is used. - ``symbol_set`` -- The collection of symbols that is used in ``array``. If set to None, then a symbol set will be assumed by checking for each unique entry in the given ``array``. - - - ``verbose`` (boolean) -- whether to display some information about the - covering array - + + - ``verbose`` (boolean) -- whether to display some information about + the covering array + - ``parameters`` (boolean) -- whether to return the parameters of - the Covering Array. If set to ``True``, the function returns a pair - ``(boolean_answer,(N,t,k,v))`` - + the Covering Array. If set to ``True``, the function returns a + pair ``(boolean_answer,(N,t,k,v))`` + EXAMPLES:: sage: from sage.combinat.designs.designs_pyx import is_covering_array sage: C = ((1, 1, 1, 0), @@ -37,7 +37,7 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete sage: is_covering_array(C) Traceback (most recent call last): ... - ValueError: Not all rows are the same length, row 2 is not the same length as row 0 + ValueError: Not all rows are the same length, row 2i is not the same length as row 0 sage: C = (('a', 'a', 'a', 'b'), ....: ('a', 'a', 'b', 'a'), @@ -69,7 +69,7 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete Traceback (most recent call last): ... ValueError: 2 appears in the array but not in the given symbol set - + sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), @@ -129,14 +129,14 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete """ from itertools import product, combinations from copy import deepcopy - + number_rows=len(array) number_columns=len(array[0]) - + for row in range(number_rows): if len(array[row]) != number_columns: raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(row)) - + if symbol_set is None: symbol_set = list({x for l in array for x in l}) symbol_set.sort() @@ -145,29 +145,31 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete for x in l: if x not in symbol_set: raise ValueError("{} appears in the array but not in the given symbol set".format(x)) - + if strength is None: wstrength = 1 else: wstrength = strength finished = False - - # if no strength inputted, tries increasing values for t until one does not work - # if strength is inputted ends after one check - while finished == False: - # A dictionary to count how many times each t-tuple appears in the array + + # if no strength inputted, tries increasing values for t until one + does not work. If strength is inputted ends after one check + while finished is False: + # A dictionary to count how many times each t-tuple appears in + # the array tupledict={} a=[ttuple for ttuple in product(symbol_set,repeat=wstrength)] for item in a: tupledict.update({item:0}) - - # Iterates over every possible selections of t columns, and count the t-tuples appearing in each selection + + # Iterates over every possible selections of t columns, and + #count the t-tuples appearing in each selection for comb in combinations(range(number_columns),wstrength): wdict=deepcopy(tupledict) for row in array: wdict[tuple([row[ti] for ti in comb])]+=1 - - # Checks if any t-tuple is not covered in current column selection + + # Checks if any t-tuple is not covered in current columns if 0 in wdict.values(): if strength != None: wstrength = 0 @@ -178,24 +180,24 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete wstrength -=1 finished = True break - + else: if strength != None: result = True finished = True break - if finished == False: + if finished is False: wstrength +=1 - + if verbose: print('A {} by {} Covering Array with strength {} with entries from {}'.format(number_rows,number_columns,wstrength,symbol_set)) - + if strength is None: if parameters: return (True,(number_rows,wstrength,number_columns,len(symbol_set))) else: return True - + else: if parameters: return (result,(number_rows,wstrength,number_columns,len(symbol_set))) From bfb1ec56971b840c0361e2c6104ad6ed5d0def8b Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 20:13:25 -0400 Subject: [PATCH 027/225] fixed another typo --- src/sage/combinat/designs/designs_pyx.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index c93ddf10fb3..6d68eecb7b3 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -153,7 +153,7 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete finished = False # if no strength inputted, tries increasing values for t until one - does not work. If strength is inputted ends after one check + # does not work. If strength is inputted ends after one check while finished is False: # A dictionary to count how many times each t-tuple appears in # the array From 7c41349ba199ffc263426f791a8cebd155e9b1e3 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 20:41:56 -0400 Subject: [PATCH 028/225] fixing errors --- src/sage/combinat/designs/designs_pyx.pyx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 6d68eecb7b3..bb37e8cdd9e 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -7,6 +7,14 @@ Functions --------- """ +from sage.data_structures.bitset_base cimport * + +from libc.string cimport memset + +from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free + +from sage.misc.unknown import Unknown + def is_covering_array(array,strength=None,symbol_set=None,verbose=False,parameters=False): r""" Checks if the input is a covering array with given strength @@ -204,14 +212,6 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete else: return result -from sage.data_structures.bitset_base cimport * - -from libc.string cimport memset - -from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free - -from sage.misc.unknown import Unknown - def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology="OA"): r""" Check that the integer matrix `OA` is an `OA(k,n,t)`. From 6c34695b5a04f118855dcd025d1ae6c242080b98 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 21:05:57 -0400 Subject: [PATCH 029/225] fixed another typo again --- src/sage/combinat/designs/designs_pyx.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index bb37e8cdd9e..0fbbd8de54b 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -45,7 +45,7 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete sage: is_covering_array(C) Traceback (most recent call last): ... - ValueError: Not all rows are the same length, row 2i is not the same length as row 0 + ValueError: Not all rows are the same length, row 2 is not the same length as row 0 sage: C = (('a', 'a', 'a', 'b'), ....: ('a', 'a', 'b', 'a'), From 226011ff33e9833a66126e8b5dace99a3e7aed20 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 21:18:13 -0400 Subject: [PATCH 030/225] fixed another typo again --- src/sage/combinat/designs/designs_pyx.pyx | 204 +++++++++++----------- 1 file changed, 102 insertions(+), 102 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 0fbbd8de54b..8cdc1f6a4ac 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -17,122 +17,122 @@ from sage.misc.unknown import Unknown def is_covering_array(array,strength=None,symbol_set=None,verbose=False,parameters=False): r""" - Checks if the input is a covering array with given strength + Checks if the input is a covering array with given strength. - - ``array`` -- The Covering Array to be tested + - ``array`` -- The Covering Array to be tested. - ``strength`` (integer) -- The parameter `t` of the covering array, - such thatin any selection of `t` columns of the array, every `t` - -tuple appearsat least once. If set to None then all t>0 are - tested to and themaximal strength is used. + such thatin any selection of `t` columns of the array, every `t` + -tuple appearsat least once. If set to None then all t>0 are + tested to and themaximal strength is used. - ``symbol_set`` -- The collection of symbols that is used in ``array``. If set to None, then a symbol set will be assumed by checking for each unique entry in the given ``array``. - ``verbose`` (boolean) -- whether to display some information about - the covering array + the covering array. - ``parameters`` (boolean) -- whether to return the parameters of the Covering Array. If set to ``True``, the function returns a - pair ``(boolean_answer,(N,t,k,v))`` + pair ``(boolean_answer,(N,t,k,v))``. EXAMPLES:: - sage: from sage.combinat.designs.designs_pyx import is_covering_array - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 0), - ....: (0, 0, 0)) - sage: is_covering_array(C) - Traceback (most recent call last): - ... - ValueError: Not all rows are the same length, row 2 is not the same length as row 0 - - sage: C = (('a', 'a', 'a', 'b'), - ....: ('a', 'a', 'b', 'a'), - ....: ('a', 'b', 'a', 'a'), - ....: ('b', 'a', 'a', 'a'), - ....: ('b', 'b', 'b', 'b')) - sage: is_covering_array(C,verbose=True) - A 5 by 4 Covering Array with strength 2 with entries from ['a', 'b'] - True - sage: is_covering_array(C,strength=3,verbose=True) - A 5 by 4 Covering Array with strength 0 with entries from ['a', 'b'] - False - - sage: from sage.combinat.designs.designs_pyx import is_covering_array - sage: C = ((0, 1, 0), - ....: (1, 1, 0), - ....: (1, 0, 0)) - sage: is_covering_array(C,verbose=True) - A 3 by 3 Covering Array with strength 0 with entries from [0, 1] - True - - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 2, 0)) - sage: is_covering_array(C,symbol_set=(0,1)) - Traceback (most recent call last): - ... - ValueError: 2 appears in the array but not in the given symbol set - - sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) - sage: is_covering_array(C,parameters=True) - (True, (53, 3, 13, 3)) + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = ((1, 1, 1, 0), + ....: (1, 1, 0, 0), + ....: (0, 0, 0)) + sage: is_covering_array(C) + Traceback (most recent call last): + ... + ValueError: Not all rows are the same length, row 2 is not the same length as row 0 + + sage: C = (('a', 'a', 'a', 'b'), + ....: ('a', 'a', 'b', 'a'), + ....: ('a', 'b', 'a', 'a'), + ....: ('b', 'a', 'a', 'a'), + ....: ('b', 'b', 'b', 'b')) + sage: is_covering_array(C,verbose=True) + A 5 by 4 Covering Array with strength 2 with entries from ['a', 'b'] + True + sage: is_covering_array(C,strength=3,verbose=True) + A 5 by 4 Covering Array with strength 0 with entries from ['a', 'b'] + False + + sage: from sage.combinat.designs.designs_pyx import is_covering_array + sage: C = ((0, 1, 0), + ....: (1, 1, 0), + ....: (1, 0, 0)) + sage: is_covering_array(C,verbose=True) + A 3 by 3 Covering Array with strength 0 with entries from [0, 1] + True + + sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), + ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), + ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), + ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), + ....: (1, 1, 1, 0, 1, 1, 0, 1, 2, 0)) + sage: is_covering_array(C,symbol_set=(0,1)) + Traceback (most recent call last): + ... + ValueError: 2 appears in the array but not in the given symbol set + + sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), + ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), + ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), + ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), + ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), + ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), + ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), + ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), + ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), + ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), + ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), + ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), + ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), + ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), + ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), + ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), + ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), + ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), + ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), + ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), + ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), + ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), + ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), + ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), + ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), + ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), + ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), + ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), + ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), + ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), + ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), + ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), + ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), + ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), + ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), + ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), + ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), + ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), + ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), + ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), + ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), + ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), + ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), + ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), + ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), + ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), + ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), + ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), + ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), + ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), + ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), + ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), + ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + sage: is_covering_array(C,parameters=True) + (True, (53, 3, 13, 3)) """ from itertools import product, combinations From 546d474e62734718b124f513cf110d69ff996ec7 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 May 2023 22:22:37 -0400 Subject: [PATCH 031/225] Removed use of "copy" and condensed multiple lines to one --- src/sage/combinat/designs/designs_pyx.pyx | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 8cdc1f6a4ac..978a4417228 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -136,7 +136,6 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete """ from itertools import product, combinations - from copy import deepcopy number_rows=len(array) number_columns=len(array[0]) @@ -163,22 +162,15 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete # if no strength inputted, tries increasing values for t until one # does not work. If strength is inputted ends after one check while finished is False: - # A dictionary to count how many times each t-tuple appears in - # the array - tupledict={} - a=[ttuple for ttuple in product(symbol_set,repeat=wstrength)] - for item in a: - tupledict.update({item:0}) - # Iterates over every possible selections of t columns, and - #count the t-tuples appearing in each selection + # count the t-tuples appearing in each selection for comb in combinations(range(number_columns),wstrength): - wdict=deepcopy(tupledict) + tuple_dictionary = {item: 0 for item in product(symbol_set, repeat=wstrength)} for row in array: - wdict[tuple([row[ti] for ti in comb])]+=1 + tuple_dictionary[tuple([row[ti] for ti in comb])]+=1 # Checks if any t-tuple is not covered in current columns - if 0 in wdict.values(): + if 0 in tuple_dictionary.values(): if strength != None: wstrength = 0 result = False From 5d4c2fb7c6800360faf9263408d13537da46ae3a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 17 Jun 2023 06:27:40 -0700 Subject: [PATCH 032/225] build/pkgs/onetbb: Upgrade to 2021.9.0 --- build/pkgs/onetbb/checksums.ini | 6 +++--- build/pkgs/onetbb/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/onetbb/checksums.ini b/build/pkgs/onetbb/checksums.ini index 5ff81545b4b..69e7ed4d027 100644 --- a/build/pkgs/onetbb/checksums.ini +++ b/build/pkgs/onetbb/checksums.ini @@ -1,5 +1,5 @@ tarball=onetbb-VERSION.tar.gz -sha1=e4be99dc35948052296105d2ae7da6d34e01ba2d -md5=68e617448f71df02d8688c84d53778f6 -cksum=1573392748 +sha1=b991f5d882aba2182871cfe011614cc43b92aa3c +md5=ba4ecedc4949f673a34b35de738a72fc +cksum=211900655 upstream_url=https://github.com/oneapi-src/oneTBB/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/onetbb/package-version.txt b/build/pkgs/onetbb/package-version.txt index a489944aae9..a6513d2ae59 100644 --- a/build/pkgs/onetbb/package-version.txt +++ b/build/pkgs/onetbb/package-version.txt @@ -1 +1 @@ -2021.7.0 +2021.9.0 From 21dcab5916742089e75b9bdd62c95db3f4402d99 Mon Sep 17 00:00:00 2001 From: Aaron Date: Sat, 17 Jun 2023 11:33:52 -0400 Subject: [PATCH 033/225] Fixed and error with the main loop of is_covering_array that was terminating too early. Changed the function to only consider arrays with symbols 0...v for some input v. Changed doctests and sanity checks accordingly. --- src/sage/combinat/designs/designs_pyx.pyx | 119 ++++++++++------------ 1 file changed, 54 insertions(+), 65 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 978a4417228..106cf346ba6 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -15,20 +15,22 @@ from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free from sage.misc.unknown import Unknown -def is_covering_array(array,strength=None,symbol_set=None,verbose=False,parameters=False): +#Current Version +#***********************************************************# + +def is_covering_array(array, strength=None, levels=None, verbose=False, parameters=False): r""" - Checks if the input is a covering array with given strength. + Check if the input is a covering array with given strength. - ``array`` -- The Covering Array to be tested. - ``strength`` (integer) -- The parameter `t` of the covering array, - such thatin any selection of `t` columns of the array, every `t` - -tuple appearsat least once. If set to None then all t>0 are - tested to and themaximal strength is used. + such that in any selection of `t` columns of the array, every `t` + -tuple appears at least once. If set to None then all t > 0 are + tested to and the maximal strength is used. - - ``symbol_set`` -- The collection of symbols that is used in - ``array``. If set to None, then a symbol set will be assumed by - checking for each unique entry in the given ``array``. + - ``levels`` -- The number of symbols that appear in ``array``. + If set to None, then each unique entry in ``array`` is counted. - ``verbose`` (boolean) -- whether to display some information about the covering array. @@ -38,6 +40,7 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete pair ``(boolean_answer,(N,t,k,v))``. EXAMPLES:: + sage: from sage.combinat.designs.designs_pyx import is_covering_array sage: C = ((1, 1, 1, 0), ....: (1, 1, 0, 0), @@ -47,24 +50,12 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete ... ValueError: Not all rows are the same length, row 2 is not the same length as row 0 - sage: C = (('a', 'a', 'a', 'b'), - ....: ('a', 'a', 'b', 'a'), - ....: ('a', 'b', 'a', 'a'), - ....: ('b', 'a', 'a', 'a'), - ....: ('b', 'b', 'b', 'b')) - sage: is_covering_array(C,verbose=True) - A 5 by 4 Covering Array with strength 2 with entries from ['a', 'b'] - True - sage: is_covering_array(C,strength=3,verbose=True) - A 5 by 4 Covering Array with strength 0 with entries from ['a', 'b'] - False - sage: from sage.combinat.designs.designs_pyx import is_covering_array sage: C = ((0, 1, 0), ....: (1, 1, 0), ....: (1, 0, 0)) sage: is_covering_array(C,verbose=True) - A 3 by 3 Covering Array with strength 0 with entries from [0, 1] + A 3 by 3 Covering Array with strength 0 with entries from {0, 1} True sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), @@ -73,10 +64,10 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), ....: (1, 1, 1, 0, 1, 1, 0, 1, 2, 0)) - sage: is_covering_array(C,symbol_set=(0,1)) + sage: is_covering_array(C,levels=2) Traceback (most recent call last): ... - ValueError: 2 appears in the array but not in the given symbol set + ValueError: array should contain integer symbols from 0 to 1 sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), @@ -136,73 +127,71 @@ def is_covering_array(array,strength=None,symbol_set=None,verbose=False,paramete """ from itertools import product, combinations + from sage.rings.integer import Integer - number_rows=len(array) - number_columns=len(array[0]) - - for row in range(number_rows): - if len(array[row]) != number_columns: - raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(row)) - - if symbol_set is None: - symbol_set = list({x for l in array for x in l}) - symbol_set.sort() + if levels is None: + symbol_set = {x for l in array for x in l} + levels = len(symbol_set) else: - for l in array: - for x in l: - if x not in symbol_set: - raise ValueError("{} appears in the array but not in the given symbol set".format(x)) + symbol_set = {num for num in range(levels)} + + number_rows = len(array) + number_columns = len(array[0]) + # Set wstrength to be the current t value to be checked if strength is None: wstrength = 1 else: + if strength > number_columns: + raise ValueError("strength must be equal or less than number of columns") wstrength = strength - finished = False - # if no strength inputted, tries increasing values for t until one - # does not work. If strength is inputted ends after one check + for row in array: + if len(row) != number_columns: + raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(array.index(row))) + else: + for entry in row: + if type(entry) != Integer or entry < -1 or entry >= levels: + raise ValueError("array should contain integer symbols from 0 to {}".format(levels-1)) + + finished = False + # If no strength inputted, try increasing values for t until one + # does not work. If strength is inputted end after one check while finished is False: - # Iterates over every possible selections of t columns, and + # Iterate over every possible selections of t columns, and # count the t-tuples appearing in each selection - for comb in combinations(range(number_columns),wstrength): + for comb in combinations(range(number_columns), wstrength): tuple_dictionary = {item: 0 for item in product(symbol_set, repeat=wstrength)} for row in array: - tuple_dictionary[tuple([row[ti] for ti in comb])]+=1 + tuple_dictionary[tuple([row[ti] for ti in comb])] += 1 - # Checks if any t-tuple is not covered in current columns + # Check if any t-tuple is not covered in current columns if 0 in tuple_dictionary.values(): - if strength != None: - wstrength = 0 - result = False + if strength is None: + wstrength -= 1 finished = True break else: - wstrength -=1 + wstrength = 0 + result = False finished = True break - else: - if strength != None: - result = True - finished = True - break - if finished is False: - wstrength +=1 + if strength is None and finished is False and wstrength < number_columns: + wstrength += 1 + else: + result = True + finished = True + break if verbose: print('A {} by {} Covering Array with strength {} with entries from {}'.format(number_rows,number_columns,wstrength,symbol_set)) - if strength is None: - if parameters: - return (True,(number_rows,wstrength,number_columns,len(symbol_set))) - else: - return True - + if parameters: + return (result, (number_rows, wstrength, number_columns, levels)) else: - if parameters: - return (result,(number_rows,wstrength,number_columns,len(symbol_set))) - else: - return result + return result + def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology="OA"): r""" From d39809b98582775312493bc72bf68a3668be3a33 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 17 Jun 2023 10:07:50 -0700 Subject: [PATCH 034/225] build/pkgs/onetbb/patches: Add https://github.com/oneapi-src/oneTBB/commit/154cc73ca4d359621202399cc0c3c91058e56e79 --- ...c73ca4d359621202399cc0c3c91058e56e79.patch | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch diff --git a/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch b/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch new file mode 100644 index 00000000000..a2e4d939311 --- /dev/null +++ b/build/pkgs/onetbb/patches/gcc13-154cc73ca4d359621202399cc0c3c91058e56e79.patch @@ -0,0 +1,36 @@ +From 154cc73ca4d359621202399cc0c3c91058e56e79 Mon Sep 17 00:00:00 2001 +From: Sam James +Date: Wed, 22 Feb 2023 14:16:46 +0000 +Subject: [PATCH] test: common: include for abort() (fix build with + GCC 13) (#1031) + +GCC 13 (as usual for new compiler releases) shuffles around some +internal includes and so etc is no longer transitively included. + +See https://www.gnu.org/software/gcc/gcc-13/porting_to.html. + +Signed-off-by: Sam James +--- + test/common/utils_assert.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/test/common/utils_assert.h b/test/common/utils_assert.h +index 1df8ae72ac..0123ab881e 100644 +--- a/test/common/utils_assert.h ++++ b/test/common/utils_assert.h +@@ -1,5 +1,5 @@ + /* +- Copyright (c) 2005-2022 Intel Corporation ++ Copyright (c) 2005-2023 Intel Corporation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. +@@ -20,6 +20,8 @@ + #include "config.h" + #include "utils_report.h" + ++#include ++ + #define REPORT_FATAL_ERROR REPORT + + namespace utils { From 54b01723d4e8bda6c4ea9fe16d2669bbde9ec88d Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 26 Jun 2023 15:22:05 -0400 Subject: [PATCH 035/225] For efficiency made is_covering_array only consider the arrays where the symbols are 0,..,v-1. To allow for easy transitions between this "standard symbol set" and others, edits were made to the orthogonal arrays file to include functions that map symbol sets of arrays and these functions are imported to the file for covering array functions Because the covering array file was added back, documentation and links to it were added back as well --- src/doc/en/reference/combinat/module_list.rst | 1 + src/sage/combinat/designs/covering_array.py | 46 +++++ src/sage/combinat/designs/design_catalog.py | 2 + src/sage/combinat/designs/designs_pyx.pyx | 194 ++++++++++-------- .../combinat/designs/orthogonal_arrays.py | 46 ++++- 5 files changed, 200 insertions(+), 89 deletions(-) create mode 100644 src/sage/combinat/designs/covering_array.py diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 3bfa10ed3f7..51ed68802b9 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -92,6 +92,7 @@ Comprehensive Module List sage/combinat/designs/resolvable_bibd sage/combinat/designs/group_divisible_designs sage/combinat/designs/block_design + sage/combinat/designs/covering_array sage/combinat/designs/covering_design sage/combinat/designs/database sage/combinat/designs/design_catalog diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py new file mode 100644 index 00000000000..6c5ff677ef8 --- /dev/null +++ b/src/sage/combinat/designs/covering_array.py @@ -0,0 +1,46 @@ +r""" +Covering Arrays (CA) + +A Covering Array, denoted CA`(N,k,v,t)`, is an `n` by `k` array with +entries from a set of `v` elements with the property that in every +selection of `t` columns, eachrow contains every sequence of +`t`-elements at least once. + +An Orthogonal Array, denoted OA`(N,k,v,t)` is a covering array with the +property that each row contains every sequence of `t`-elements exactly +once + +REFERENCES: + +- [Colb2004]_ + +- [Sher2006]_ + +- [Wal2007]_ + +AUTHORS: + +- Aaron Dwyer and brett stevens (2022): initial version + +.. TODO:: + + Implement various construction methods for CAs + +Functions +--------- + +""" + +# ********************************************************************** +# Copyright (C) 2022 Aaron Dwyer +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# ********************************************************************** + +from .orthogonal_arrays import OA_relabel, OA_standard_label +CA_relabel = OA_relabel +CA_standard_label = OA_standard_label diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index a9572e119c0..bd576df0749 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -119,3 +119,5 @@ lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) + +lazy_import('sage.combinat.designs.covering_array', 'CoveringArray') \ No newline at end of file diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 106cf346ba6..ef85aaad5eb 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -22,14 +22,14 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete r""" Check if the input is a covering array with given strength. - - ``array`` -- The Covering Array to be tested. + - ``array`` -- the Covering Array to be tested. - - ``strength`` (integer) -- The parameter `t` of the covering array, + - ``strength`` (integer) -- the parameter `t` of the covering array, such that in any selection of `t` columns of the array, every `t` -tuple appears at least once. If set to None then all t > 0 are tested to and the maximal strength is used. - - ``levels`` -- The number of symbols that appear in ``array``. + - ``levels`` -- the number of symbols that appear in ``array``. If set to None, then each unique entry in ``array`` is counted. - ``verbose`` (boolean) -- whether to display some information about @@ -42,98 +42,116 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete EXAMPLES:: sage: from sage.combinat.designs.designs_pyx import is_covering_array - sage: C = ((1, 1, 1, 0), - ....: (1, 1, 0, 0), - ....: (0, 0, 0)) + sage: C = [[1, 1, 1, 0], + ....: [1, 1, 0, 0], + ....: [0, 0, 0]] sage: is_covering_array(C) Traceback (most recent call last): ... ValueError: Not all rows are the same length, row 2 is not the same length as row 0 - sage: from sage.combinat.designs.designs_pyx import is_covering_array - sage: C = ((0, 1, 0), - ....: (1, 1, 0), - ....: (1, 0, 0)) + sage: C = [[0, 1, 1], + ....: [1, 1, 0], + ....: [1, 0, 1], + ....: [0, 0, 0,]] + sage: is_covering_array(C,strength=4) + Traceback (most recent call last): + ... + ValueError: Strength must be equal or less than number of columns + + sage: C = [[0, 1, 1], + ....: [1, 1, 1], + ....: [1, 0, 1]] sage: is_covering_array(C,verbose=True) - A 3 by 3 Covering Array with strength 0 with entries from {0, 1} + A 3 by 3 Covering Array with strength 0 with entries from a symbol set of size 2 True - sage: C = ((0, 0, 0, 0, 0, 0, 0, 0, 0, 0), - ....: (0, 0, 0, 0, 1, 1, 1, 1, 1, 1), - ....: (0, 1, 1, 1, 0, 0, 0, 1, 1, 1), - ....: (1, 0, 1, 1, 0, 1, 1, 0, 0, 1), - ....: (1, 1, 0, 1, 1, 0, 1, 0, 1, 0), - ....: (1, 1, 1, 0, 1, 1, 0, 1, 2, 0)) + sage: C = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + ....: [0, 0, 0, 0, 1, 1, 1, 1, 1, 1], + ....: [0, 1, 1, 1, 0, 0, 0, 1, 1, 1], + ....: [1, 0, 1, 1, 0, 1, 1, 0, 0, 1], + ....: [1, 1, 0, 1, 1, 0, 1, 0, 1, 0], + ....: [1, 1, 1, 0, 1, 1, 0, 1, 2, 0]] sage: is_covering_array(C,levels=2) Traceback (most recent call last): ... - ValueError: array should contain integer symbols from 0 to 1 - - sage: C = ((1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2), - ....: (1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2), - ....: (1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0), - ....: (0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1), - ....: (2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2), - ....: (1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2), - ....: (1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1), - ....: (2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2), - ....: (1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0), - ....: (0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2), - ....: (1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0), - ....: (0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0), - ....: (0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1), - ....: (2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1), - ....: (2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1), - ....: (2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0), - ....: (0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2), - ....: (1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1), - ....: (2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1), - ....: (2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2), - ....: (1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1), - ....: (2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0), - ....: (0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1), - ....: (2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0), - ....: (0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0), - ....: (0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2), - ....: (1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2), - ....: (1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0), - ....: (0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0), - ....: (0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1), - ....: (2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0), - ....: (0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1), - ....: (2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2), - ....: (1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1), - ....: (2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1), - ....: (2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2), - ....: (1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0), - ....: (0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1), - ....: (2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1), - ....: (2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1), - ....: (2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0), - ....: (0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0), - ....: (0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2), - ....: (1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0), - ....: (0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2), - ....: (1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1), - ....: (2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2), - ....: (1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2), - ....: (1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1), - ....: (2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0), - ....: (0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2), - ....: (1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2), - ....: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + ValueError: Array should contain integer symbols from 0 to 1 + + sage: C = [[1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2], + ....: [1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2], + ....: [1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1, 0], + ....: [0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2, 1], + ....: [2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2, 2], + ....: [1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1, 2], + ....: [1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2, 1], + ....: [2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0, 2], + ....: [1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2, 0], + ....: [0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0, 2], + ....: [1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0, 0], + ....: [0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1, 0], + ....: [0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1, 1], + ....: [2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1, 1], + ....: [2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0, 1], + ....: [2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2, 0], + ....: [0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1, 2], + ....: [1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1, 1], + ....: [2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2, 1], + ....: [2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1, 2], + ....: [1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0, 1], + ....: [2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1, 0], + ....: [0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0, 1], + ....: [2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0, 0], + ....: [0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2, 0], + ....: [0, 0, 2, 0, 2, 1, 2, 2, 1, 0, 2, 2, 2], + ....: [1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2], + ....: [1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0], + ....: [0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 0], + ....: [0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1], + ....: [2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1, 0], + ....: [0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2, 1], + ....: [2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1, 2], + ....: [1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1, 1], + ....: [2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2, 1], + ....: [2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0, 2], + ....: [1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1, 0], + ....: [0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1, 1], + ....: [2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1, 1], + ....: [2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0, 1], + ....: [2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0, 0], + ....: [0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2, 0], + ....: [0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0, 2], + ....: [1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2, 0], + ....: [0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1, 2], + ....: [1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2, 1], + ....: [2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2, 2], + ....: [1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1, 2], + ....: [1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0, 1], + ....: [2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2, 0], + ....: [0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2, 2], + ....: [1, 0, 2, 1, 1, 2, 1, 0, 1, 0, 0, 2, 2], + ....: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] sage: is_covering_array(C,parameters=True) (True, (53, 3, 13, 3)) + sage: C = [[1, 0, 1, 1, 2, 0, 2, 2], + ....: [2, 1, 0, 1, 1, 2, 0, 2], + ....: [2, 2, 1, 0, 1, 1, 2, 0], + ....: [0, 2, 2, 1, 0, 1, 1, 2], + ....: [2, 0, 2, 2, 1, 0, 1, 1], + ....: [1, 2, 0, 2, 2, 1, 0, 1], + ....: [1, 1, 2, 0, 2, 2, 1, 0], + ....: [0, 1, 1, 2, 0, 2, 2, 1]] + sage: is_covering_array(C,strength=2,parameters=True) + (False, (8, 0, 8, 3)) + """ from itertools import product, combinations - from sage.rings.integer import Integer if levels is None: - symbol_set = {x for l in array for x in l} - levels = len(symbol_set) + symbol_list = list({x for l in array for x in l}) + levels = len(symbol_list) else: - symbol_set = {num for num in range(levels)} + symbol_list = [num for num in range(levels)] number_rows = len(array) number_columns = len(array[0]) @@ -143,7 +161,7 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete wstrength = 1 else: if strength > number_columns: - raise ValueError("strength must be equal or less than number of columns") + raise ValueError("Strength must be equal or less than number of columns") wstrength = strength for row in array: @@ -151,20 +169,20 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(array.index(row))) else: for entry in row: - if type(entry) != Integer or entry < -1 or entry >= levels: - raise ValueError("array should contain integer symbols from 0 to {}".format(levels-1)) + if int(entry) != entry or entry < -1 or entry >= levels: + raise ValueError("Array should contain integer symbols from 0 to {}".format(levels-1)) finished = False + result = True # If no strength inputted, try increasing values for t until one # does not work. If strength is inputted end after one check while finished is False: # Iterate over every possible selections of t columns, and # count the t-tuples appearing in each selection for comb in combinations(range(number_columns), wstrength): - tuple_dictionary = {item: 0 for item in product(symbol_set, repeat=wstrength)} + tuple_dictionary = {item: 0 for item in product(symbol_list, repeat=wstrength)} for row in array: tuple_dictionary[tuple([row[ti] for ti in comb])] += 1 - # Check if any t-tuple is not covered in current columns if 0 in tuple_dictionary.values(): if strength is None: @@ -177,15 +195,15 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete finished = True break - if strength is None and finished is False and wstrength < number_columns: - wstrength += 1 - else: - result = True - finished = True - break + if finished is False: + if strength is None and wstrength < number_columns: + wstrength += 1 + else: + finished = True + break if verbose: - print('A {} by {} Covering Array with strength {} with entries from {}'.format(number_rows,number_columns,wstrength,symbol_set)) + print('A {} by {} Covering Array with strength {} with entries from a symbol set of size {}'.format(number_rows,number_columns,wstrength,levels)) if parameters: return (result, (number_rows, wstrength, number_columns, levels)) diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index 388a3a777cc..b30d8de3b7a 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -34,6 +34,7 @@ :meth:`TD_product` | Return the product of two transversal designs. :meth:`OA_find_disjoint_blocks` | Return `x` disjoint blocks contained in a given `OA(k,n)`. :meth:`OA_relabel` | Return a relabelled version of the OA. + :meth:`OA_standard_label` | Return a version of the OA relabelled to symbols `(0,\dots,n-1)`. :meth:`OA_from_quasi_difference_matrix` | Return an Orthogonal Array from a Quasi-Difference matrix :meth:`OA_from_Vmt` | Return an Orthogonal Array from a `V(m,t)` :meth:`OA_from_PBD` | Return an `OA(k,n)` from a PBD @@ -1467,7 +1468,7 @@ def OA_find_disjoint_blocks(OA, k, n, x, independent_set = [OA[i] for i,v in b.items() if v] return independent_set -def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): +def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): r""" Return a relabelled version of the OA. @@ -1496,6 +1497,11 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): If set to ``None`` (default) no such relabelling is performed. + - ``symbol_list`` -- a list of the desired symbols for the + relabelled OA. If this is not ``None``, the same relabelling is + done on all blocks such that the index of an element in + symbol_list is its preimage in the relabelling map. + .. NOTE:: A ``None`` coordinate in one block remains a ``None`` @@ -1514,6 +1520,10 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): sage: is_transversal_design(TD,3,2) True + sage: OA = designs.orthogonal_arrays.build(3,2) + sage: OA_relabel(OA,3,2,symbol_list=['A','B']) + [['A', 'A', 'A'], ['A', 'B', 'B'], ['B', 'A', 'B'], ['B', 'B', 'A']] + Making sure that ``[2,2,2,2]`` is a block of `OA(4,3)`. We do this by relabelling block ``[0,0,0,0]`` which belongs to the design:: @@ -1543,8 +1553,42 @@ def OA_relabel(OA,k,n,blocks=tuple(),matrix=None): if matrix: OA = [[matrix[i][j] if j is not None else None for i,j in enumerate(R)] for R in OA] + if symbol_list: + result=[] + the_map = lambda x: symbol_list[x] + for row in OA: + result.append(list(map(the_map,row))) + OA = result return OA +def OA_standard_label(OA): + r""" + Return the inputted OA with entries relabelled as integers [0,...,n-1]. + + INPUT: + + - ``OA`` -- a list of lists with symbols as entries that are not + necessarily integers. + + EXAMPLES:: + + sage: from sage.combinat.designs.orthogonal_arrays import OA_standard_label + sage: C = [['a', 'a', 'a', 'b'], + ....: ['a', 'a', 'b', 'a'], + ....: ['a', 'b', 'a', 'a'], + ....: ['b', 'a', 'a', 'a'], + ....: ['b', 'b', 'b', 'b']] + sage: OA_standard_label(C) + [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0], [1, 1, 1, 1]] + + """ + symbol_list = sorted({x for l in OA for x in l}) + result = [] + the_map = lambda x: symbol_list.index(x) + for row in OA: + result.append(list(map(the_map,row))) + return result + def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): r""" Return an `OA(k, |G| \cdot 2^c)` from a constrained `(G,k-1,2)`-difference From c05d4832df383c6620f6445c9afd0529d3b70387 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 29 Jun 2023 15:50:04 -0400 Subject: [PATCH 036/225] Made the new relabelling functions in OA more efficient, removed an import of the CA class which no longer exists --- src/sage/combinat/designs/covering_array.py | 3 --- src/sage/combinat/designs/design_catalog.py | 4 +--- src/sage/combinat/designs/orthogonal_arrays.py | 14 ++++---------- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 6c5ff677ef8..ba6bbefb1ac 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -26,9 +26,6 @@ Implement various construction methods for CAs -Functions ---------- - """ # ********************************************************************** diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index bd576df0749..0415f573e4c 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -118,6 +118,4 @@ 'OAMainFunctions', as_='orthogonal_arrays') lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', - ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) - -lazy_import('sage.combinat.designs.covering_array', 'CoveringArray') \ No newline at end of file + ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) \ No newline at end of file diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index b30d8de3b7a..973fcc58417 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1554,11 +1554,8 @@ def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): OA = [[matrix[i][j] if j is not None else None for i,j in enumerate(R)] for R in OA] if symbol_list: - result=[] - the_map = lambda x: symbol_list[x] - for row in OA: - result.append(list(map(the_map,row))) - OA = result + mapping = {index : symbol for index, symbol in enumerate(symbol_list)} + OA = [[mapping.get(element) for element in row] for row in OA] return OA def OA_standard_label(OA): @@ -1583,11 +1580,8 @@ def OA_standard_label(OA): """ symbol_list = sorted({x for l in OA for x in l}) - result = [] - the_map = lambda x: symbol_list.index(x) - for row in OA: - result.append(list(map(the_map,row))) - return result + mapping = {symbol : index for index, symbol in enumerate(symbol_list)} + return [[mapping.get(element) for element in row] for row in OA] def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): r""" From d30539b7cb46ae0aff2fc2e2961fefb89f7007ee Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 19 Jul 2023 15:04:49 -0400 Subject: [PATCH 037/225] Fixed some formatting and improved the main loop of is_covering_array --- src/sage/combinat/designs/designs_pyx.pyx | 9 +++------ src/sage/combinat/designs/orthogonal_arrays.py | 10 +++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 39f18569bda..24f1394bc9b 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -178,13 +178,10 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete # does not work. If strength is inputted end after one check while finished is False: # Iterate over every possible selections of t columns, and - # count the t-tuples appearing in each selection + # ensure in those columns all unique t-tuples, are present for comb in combinations(range(number_columns), wstrength): - tuple_dictionary = {item: 0 for item in product(symbol_list, repeat=wstrength)} - for row in array: - tuple_dictionary[tuple([row[ti] for ti in comb])] += 1 - # Check if any t-tuple is not covered in current columns - if 0 in tuple_dictionary.values(): + existing_combinations = set(tuple([row[ti] for ti in comb]) for row in array) + if len(existing_combinations) != number_columns ** wstrength: if strength is None: wstrength -= 1 finished = True diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index 80aa1da702f..d8b629bfe7c 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1521,7 +1521,7 @@ def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): True sage: OA = designs.orthogonal_arrays.build(3,2) - sage: OA_relabel(OA,3,2,symbol_list=['A','B']) + sage: OA_relabel(OA, 3, 2, symbol_list=['A', 'B']) [['A', 'A', 'A'], ['A', 'B', 'B'], ['B', 'A', 'B'], ['B', 'B', 'A']] Making sure that ``[2,2,2,2]`` is a block of `OA(4,3)`. We do this @@ -1554,8 +1554,8 @@ def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): OA = [[matrix[i][j] if j is not None else None for i,j in enumerate(R)] for R in OA] if symbol_list: - mapping = {index : symbol for index, symbol in enumerate(symbol_list)} - OA = [[mapping.get(element) for element in row] for row in OA] + mapping = {index: symbol for index, symbol in enumerate(symbol_list)} + OA = [[mapping[element] for element in row] for row in OA] return OA def OA_standard_label(OA): @@ -1580,8 +1580,8 @@ def OA_standard_label(OA): """ symbol_list = sorted({x for l in OA for x in l}) - mapping = {symbol : index for index, symbol in enumerate(symbol_list)} - return [[mapping.get(element) for element in row] for row in OA] + mapping = {symbol: index for index, symbol in enumerate(symbol_list)} + return [[mapping[element] for element in row] for row in OA] def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): r""" From 5994edb665fd20802b688390c1756e66324f45fc Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 25 Jul 2023 17:17:40 -0400 Subject: [PATCH 038/225] Fixed some typos and formatting errors, fixed a doctest --- src/doc/en/reference/references/index.rst | 20 +++++++++---------- src/sage/combinat/designs/covering_array.py | 16 ++++++--------- src/sage/combinat/designs/designs_pyx.pyx | 13 ++++++------ .../combinat/designs/orthogonal_arrays.py | 13 ++++++++++++ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index e82e0a8d333..da6db42d57f 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -2727,9 +2727,9 @@ REFERENCES: doubles of finite groups*. PhD Thesis, University of California, Santa Cruz. 1999. -.. [GoMa2010] Christopher Goff and Geoffrey Mason, +.. [GoMa2010] Christopher Goff and Geoffrey Mason, *Generalized twisted quantum doubles and the McKay correspondence*, - J. Algebra 324 (2010), no. 11, 3007–3016. + J. Algebra 324 (2010), no. 11, 3007–3016. .. [GJ2016] Muddappa Seetharama Gowda and Juyoung Jeong. Spectral cones in Euclidean Jordan algebras. @@ -5558,10 +5558,6 @@ REFERENCES: Course material, 1997, ``_ -.. [Sher2006] G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering - arrays of higher strength from permutation vectors". J. Combin. - Designs, 14 (2006) pp. 202-213. - .. [SHET2018] \O. Seker, P. Heggernes, T. Ekim, and Z. Caner Taskin. *Generation of random chordal graphs using subtrees of a tree*, :arxiv:`1810.13326v1`. @@ -5626,6 +5622,10 @@ REFERENCES: .. [SloaHada] \N.J.A. Sloane's Library of Hadamard Matrices, at https://neilsloane.com/hadamard/ +.. [SMC2006] \G.B. Sherwood, S.S Martirosyan, and C.J. Colbourn, "Covering + arrays of higher strength from permutation vectors". J. Combin. + Designs, 14 (2006) pp. 202-213. + .. [SMMK2013] \T. Suzaki, K. Minematsu, S. Morioka, and E. Kobayashi, *TWINE: A lightweight block cipher for multiple platforms*; in SAC, (2012), pp. 338-354. @@ -6272,10 +6272,6 @@ REFERENCES: Math. Combin. Comput. **36** (2001), 95-118. http://www.info2.uqam.ca/~walsh_t/papers/Involutions%20paper.pdf -.. [Wal2007] R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: - Constructions and Existence". J. Math. Crypt. 1 (2007), - pp.125-150 - .. [Walton1990] Mark A. Walton. *Fusion rules in Wess-Zumino-Witten models*. Nuclear Phys. B **340** (1990). @@ -6309,6 +6305,10 @@ REFERENCES: .. [Wat2010] Watkins, David S. Fundamentals of Matrix Computations, Third Edition. Wiley, Hoboken, New Jersey, 2010. +.. [WC2007] \R.A. Walker II, and C.J. Colbourn, "Perfect Hash Families: + Constructions and Existence". J. Math. Crypt. 1 (2007), + pp.125-150 + .. [Web2007] James Webb. *Game theory: decisions, interaction and Evolution*. Springer Science & Business Media, 2007. diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index ba6bbefb1ac..5b19afbfdcb 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -1,14 +1,14 @@ r""" Covering Arrays (CA) -A Covering Array, denoted CA`(N,k,v,t)`, is an `n` by `k` array with +A Covering Array, denoted CA`(N;t,k,v)`, is an `N` by `k` array with entries from a set of `v` elements with the property that in every -selection of `t` columns, eachrow contains every sequence of -`t`-elements at least once. +selection of `t` columns, every sequence of `t` elements appears in at +least one row. -An Orthogonal Array, denoted OA`(N,k,v,t)` is a covering array with the -property that each row contains every sequence of `t`-elements exactly -once +An Orthogonal Array, denoted OA`(N;t,k,v)` is a covering array with the +property that every sequence of `t`-elements appears in exactly one row. +See :mod:`sage.combinat.designs.orthogonal_arrays.` REFERENCES: @@ -22,10 +22,6 @@ - Aaron Dwyer and brett stevens (2022): initial version -.. TODO:: - - Implement various construction methods for CAs - """ # ********************************************************************** diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 24f1394bc9b..51736f687e9 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -15,13 +15,14 @@ from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free from sage.misc.unknown import Unknown -#Current Version -#***********************************************************# - def is_covering_array(array, strength=None, levels=None, verbose=False, parameters=False): r""" Check if the input is a covering array with given strength. + See :mod:`sage.combinat.designs.covering_array` for a definition. + + INPUT: + - ``array`` -- the Covering Array to be tested. - ``strength`` (integer) -- the parameter `t` of the covering array, @@ -151,7 +152,7 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete symbol_list = list({x for l in array for x in l}) levels = len(symbol_list) else: - symbol_list = [num for num in range(levels)] + symbol_list = range(levels) number_rows = len(array) number_columns = len(array[0]) @@ -181,7 +182,7 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete # ensure in those columns all unique t-tuples, are present for comb in combinations(range(number_columns), wstrength): existing_combinations = set(tuple([row[ti] for ti in comb]) for row in array) - if len(existing_combinations) != number_columns ** wstrength: + if len(existing_combinations) != levels ** wstrength: if strength is None: wstrength -= 1 finished = True @@ -200,7 +201,7 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete break if verbose: - print('A {} by {} Covering Array with strength {} with entries from a symbol set of size {}'.format(number_rows,number_columns,wstrength,levels)) + print('A {} by {} Covering Array with strength {} with entries from a symbol set of size {}'.format(number_rows, number_columns, wstrength, levels)) if parameters: return (result, (number_rows, wstrength, number_columns, levels)) diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index d8b629bfe7c..91618e050fe 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -476,6 +476,7 @@ def is_transversal_design(B, k, n, verbose=False): """ return is_orthogonal_array([[x%n for x in R] for R in B],k,n,verbose=verbose) + def wilson_construction(OA,k,r,m,u,check=True,explain_construction=False): r""" Returns a `OA(k,rm+\sum_i u_i)` from a truncated `OA(k+s,r)` by Wilson's @@ -681,6 +682,7 @@ def wilson_construction(OA,k,r,m,u,check=True,explain_construction=False): return OA + def TD_product(k,TD1,n1,TD2,n2, check=True): r""" Return the product of two transversal designs. @@ -729,6 +731,7 @@ def TD_product(k,TD1,n1,TD2,n2, check=True): return TD + def orthogonal_array(k,n,t=2,resolvable=False, check=True,existence=False,explain_construction=False): r""" Return an orthogonal array of parameters `k,n,t`. @@ -1010,6 +1013,7 @@ def orthogonal_array(k,n,t=2,resolvable=False, check=True,existence=False,explai return OA + def largest_available_k(n,t=2): r""" Return the largest `k` such that Sage can build an `OA(k,n)`. @@ -1059,6 +1063,7 @@ def largest_available_k(n,t=2): k += 1 return k + def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): r""" Return an `OA(k,n)-\sum_{1\leq i\leq x} OA(k,s_i)`. @@ -1400,6 +1405,7 @@ def incomplete_orthogonal_array(k,n,holes,resolvable=False, existence=False): return OA + def OA_find_disjoint_blocks(OA, k, n, x, *, solver=None, integrality_tolerance=1e-3): r""" @@ -1468,6 +1474,7 @@ def OA_find_disjoint_blocks(OA, k, n, x, independent_set = [OA[i] for i,v in b.items() if v] return independent_set + def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): r""" Return a relabelled version of the OA. @@ -1558,6 +1565,7 @@ def OA_relabel(OA, k, n, blocks=tuple(), matrix=None, symbol_list=None): OA = [[mapping[element] for element in row] for row in OA] return OA + def OA_standard_label(OA): r""" Return the inputted OA with entries relabelled as integers [0,...,n-1]. @@ -1583,6 +1591,7 @@ def OA_standard_label(OA): mapping = {symbol: index for index, symbol in enumerate(symbol_list)} return [[mapping[element] for element in row] for row in OA] + def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): r""" Return an `OA(k, |G| \cdot 2^c)` from a constrained `(G,k-1,2)`-difference @@ -1741,6 +1750,7 @@ def OA_n_times_2_pow_c_from_matrix(k,c,G,A,Y,check=True): Mb = [[e+GG((G.zero(),x*v)) for v in H for e in R] for x, R in zip(Y, A)] return OA_from_quasi_difference_matrix(list(zip(*Mb)),GG,add_col=True) + def OA_from_quasi_difference_matrix(M,G,add_col=True,fill_hole=True): r""" Return an Orthogonal Array from a Quasi-Difference matrix @@ -1860,6 +1870,7 @@ def OA_from_quasi_difference_matrix(M,G,add_col=True,fill_hole=True): return new_M + def OA_from_Vmt(m,t,V): r""" Return an Orthogonal Array from a `V(m,t)` @@ -1947,6 +1958,7 @@ def QDM_from_Vmt(m,t,V): return Fq, M + def OA_from_PBD(k,n,PBD, check=True): r""" Return an `OA(k,n)` from a PBD @@ -2028,6 +2040,7 @@ def OA_from_PBD(k,n,PBD, check=True): return OA + def OA_from_wider_OA(OA,k): r""" Return the first `k` columns of `OA`. From 24128ae1bf7af424fa04b377ac72ef4d92d0f41e Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 25 Jul 2023 17:24:34 -0400 Subject: [PATCH 039/225] fixed typo --- src/sage/combinat/designs/covering_array.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 5b19afbfdcb..17cf88d5b9b 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -8,7 +8,7 @@ An Orthogonal Array, denoted OA`(N;t,k,v)` is a covering array with the property that every sequence of `t`-elements appears in exactly one row. -See :mod:`sage.combinat.designs.orthogonal_arrays.` +(See :mod:`sage.combinat.designs.orthogonal_arrays`). REFERENCES: From 8db0da25f91168711fcac4728df86be5ba1e8383 Mon Sep 17 00:00:00 2001 From: Aaron Date: Fri, 18 Aug 2023 19:30:17 -0400 Subject: [PATCH 040/225] Added to the documentation of covering_array.py and split the loop of the is_CA function into cases where t is inputted and is not, so to have better iteration and better stopping --- src/sage/combinat/designs/covering_array.py | 17 ++++++- src/sage/combinat/designs/designs_pyx.pyx | 55 +++++++++++---------- 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index 17cf88d5b9b..bffdd0bf6c4 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -10,13 +10,26 @@ property that every sequence of `t`-elements appears in exactly one row. (See :mod:`sage.combinat.designs.orthogonal_arrays`). +This module collects methods relating to covering arrays, some of which +are inherited from orthogonal array methods. This module defines the +following functions: + +.. csv-table:: + :class: contentstable + :widths: 30, 70 + :delim: | + + :meth:`~sage.combinat.designs.designs_pyx.is_covering_array` | Check that the list of lists `array` is an `CA(N;t,k,v)`. + :meth:`~sage.combinat.designs.orthogonal_arrays.OA_relabel` | Return a relabelled version of the CA. + :meth:`~sage.combinat.designs.orthogonal_arrays.OA_standard_label` | Return a version of the CA relabelled to symbols `(0,\dots,n-1)`. + REFERENCES: - [Colb2004]_ -- [Sher2006]_ +- [SMC2006]_ -- [Wal2007]_ +- [WC2007]_ AUTHORS: diff --git a/src/sage/combinat/designs/designs_pyx.pyx b/src/sage/combinat/designs/designs_pyx.pyx index 51736f687e9..347fde2157f 100644 --- a/src/sage/combinat/designs/designs_pyx.pyx +++ b/src/sage/combinat/designs/designs_pyx.pyx @@ -157,14 +157,6 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete number_rows = len(array) number_columns = len(array[0]) - # Set wstrength to be the current t value to be checked - if strength is None: - wstrength = 1 - else: - if strength > number_columns: - raise ValueError("Strength must be equal or less than number of columns") - wstrength = strength - for row in array: if len(row) != number_columns: raise ValueError("Not all rows are the same length, row {} is not the same length as row 0".format(array.index(row))) @@ -173,32 +165,41 @@ def is_covering_array(array, strength=None, levels=None, verbose=False, paramete if int(entry) != entry or entry < -1 or entry >= levels: raise ValueError("Array should contain integer symbols from 0 to {}".format(levels-1)) - finished = False result = True - # If no strength inputted, try increasing values for t until one - # does not work. If strength is inputted end after one check - while finished is False: - # Iterate over every possible selections of t columns, and - # ensure in those columns all unique t-tuples, are present + + # If strength t is inputted, check that for every selection of t + # columns, each v^t t-tuple is found in some row. + if strength: + if strength > number_columns: + raise ValueError("Strength must be equal or less than number of columns") + wstrength = strength for comb in combinations(range(number_columns), wstrength): - existing_combinations = set(tuple([row[ti] for ti in comb]) for row in array) - if len(existing_combinations) != levels ** wstrength: - if strength is None: + existing_ttuples = set(tuple([row[ti] for ti in comb]) for row in array) + if len(existing_ttuples) != levels ** wstrength: + wstrength = 0 + result = False + break + + # If no strength t is inputted, starting at t=1 check all t until + # one of the v^t t-tuples does not appear. + else: + wstrength = 1 + finished = False + do_iterate = True + while finished is False: + for comb in combinations(range(number_columns), wstrength): + tuple_dictionary = {item: 0 for item in product(symbol_list, repeat=wstrength)} + for row in array: + tuple_dictionary[tuple([row[ti] for ti in comb])] += 1 + if 0 in tuple_dictionary.values(): wstrength -= 1 finished = True break - else: - wstrength = 0 - result = False + elif do_iterate and any(value < levels for value in tuple_dictionary.values()): + do_iterate = False finished = True - break - - if finished is False: - if strength is None and wstrength < number_columns: + if finished is False and wstrength < number_columns and do_iterate: wstrength += 1 - else: - finished = True - break if verbose: print('A {} by {} Covering Array with strength {} with entries from a symbol set of size {}'.format(number_rows, number_columns, wstrength, levels)) From ad83ed9e715692c2ac2db903c9d126b736c7569e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 22 Aug 2023 11:29:47 -0700 Subject: [PATCH 041/225] build/pkgs/numpy: Update to 1.26.0b1 --- build/pkgs/numpy/checksums.ini | 6 +++--- build/pkgs/numpy/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/numpy/checksums.ini b/build/pkgs/numpy/checksums.ini index 70cc0ddaefd..5f6e6f3abec 100644 --- a/build/pkgs/numpy/checksums.ini +++ b/build/pkgs/numpy/checksums.ini @@ -1,5 +1,5 @@ tarball=numpy-VERSION.tar.gz -sha1=6c7f2278b4ddd113b30821e7e4d5f246dc3ee735 -md5=8b2692a511a3795f3af8af2cd7566a15 -cksum=3950457778 +sha1=7c36e75f2c063e51d1bb06cef7afb060d03b0dba +md5=3268568cee06327fa34175aa3805829d +cksum=2513117438 upstream_url=https://pypi.io/packages/source/n/numpy/numpy-VERSION.tar.gz diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index ca8ec414e78..47e51734ede 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.23.5 +1.26.0b1 From 2e652c0c45fceefaf970f842f0fec43340d8b500 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 22 Aug 2023 11:56:17 -0700 Subject: [PATCH 042/225] build/pkgs/numpy: Switch build system to meson_python, back out workarounds from #34110, #32746, #32423 --- build/pkgs/numpy/dependencies | 2 +- build/pkgs/numpy/lapack_conf.py | 37 ------------------ build/pkgs/numpy/patches/21891.patch | 31 --------------- build/pkgs/numpy/spkg-install.in | 58 +++++++--------------------- 4 files changed, 16 insertions(+), 112 deletions(-) delete mode 100644 build/pkgs/numpy/lapack_conf.py delete mode 100644 build/pkgs/numpy/patches/21891.patch diff --git a/build/pkgs/numpy/dependencies b/build/pkgs/numpy/dependencies index d3c0f0055e4..d4c75cbf47b 100644 --- a/build/pkgs/numpy/dependencies +++ b/build/pkgs/numpy/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) $(BLAS) gfortran | $(PYTHON_TOOLCHAIN) pkgconfig cython +$(PYTHON) $(BLAS) gfortran | $(PYTHON_TOOLCHAIN) pkgconfig cython meson_python ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/numpy/lapack_conf.py b/build/pkgs/numpy/lapack_conf.py deleted file mode 100644 index eeb9ffaf72c..00000000000 --- a/build/pkgs/numpy/lapack_conf.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 - -import pkgconfig, os - -conf_file=open('site.cfg', 'w') - -pc_blas = pkgconfig.parse('cblas blas') -pc_lapack = pkgconfig.parse('lapack') - -if os.environ['UNAME'] == 'Darwin': - # on macOS, if openblas is available (the default), use it instead of the - # macOS Accelerate framework - if 'openblas' in pc_blas.get('libraries', []): - conf_file.write('[openblas]\n') - conf_file.write('libraries = '+', '.join(pc_blas['libraries'])+'\n') - inc_dir = pc_blas['include_dirs'] - if len(inc_dir) > 0: - conf_file.write('include_dirs = '+ ':'.join(inc_dir)+'\n') - lib_dir = pc_blas['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') -else: - conf_file.write('[blas]\n') - inc_dir = pc_blas['include_dirs'] - if len(inc_dir) > 0: - conf_file.write('include_dirs = '+ ':'.join(inc_dir)+'\n') - lib_dir = pc_blas['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') - conf_file.write('blas_libs = '+', '.join(pc_blas['libraries'])+'\n') - conf_file.write('[lapack]\n') - lib_dir = pc_lapack['library_dirs'] - if len(lib_dir) > 0: - conf_file.write('library_dirs = '+ ':'.join(lib_dir)+'\n') - conf_file.write('lapack_libs = '+', '.join(pc_lapack['libraries'])+'\n') - -conf_file.close() diff --git a/build/pkgs/numpy/patches/21891.patch b/build/pkgs/numpy/patches/21891.patch deleted file mode 100644 index 095fa894ebb..00000000000 --- a/build/pkgs/numpy/patches/21891.patch +++ /dev/null @@ -1,31 +0,0 @@ -From c7894260aaf36c447dd091bf622c7c2bcdb15a28 Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Thu, 30 Jun 2022 13:18:46 -0700 -Subject: [PATCH] setup.py: Remove check for SETUPTOOLS_USE_DISTUTILS - ---- - setup.py | 11 ----------- - 1 file changed, 11 deletions(-) - -diff --git a/setup.py b/setup.py -index 353b6c09693..2bc70173eca 100755 ---- a/setup.py -+++ b/setup.py -@@ -85,17 +85,6 @@ - # so that it is in sys.modules - import numpy.distutils.command.sdist - import setuptools --if int(setuptools.__version__.split('.')[0]) >= 60: -- # setuptools >= 60 switches to vendored distutils by default; this -- # may break the numpy build, so make sure the stdlib version is used -- try: -- setuptools_use_distutils = os.environ['SETUPTOOLS_USE_DISTUTILS'] -- except KeyError: -- os.environ['SETUPTOOLS_USE_DISTUTILS'] = "stdlib" -- else: -- if setuptools_use_distutils != "stdlib": -- raise RuntimeError("setuptools versions >= '60.0.0' require " -- "SETUPTOOLS_USE_DISTUTILS=stdlib in the environment") - - # Initialize cmdclass from versioneer - from numpy.distutils.core import numpy_cmdclass diff --git a/build/pkgs/numpy/spkg-install.in b/build/pkgs/numpy/spkg-install.in index e28660f393f..20d2a2cef62 100644 --- a/build/pkgs/numpy/spkg-install.in +++ b/build/pkgs/numpy/spkg-install.in @@ -3,57 +3,29 @@ cd src set -e -if [ `uname` = "Darwin" ]; then - unset ATLAS - unset BLAS - unset LAPACK - # https://github.com/sagemath/sage/issues/34110#comment:35 - # The fix for "reciprocal" (affected by a clang compiler bug) in - # https://github.com/numpy/numpy/pull/19926 relies on -ftrapping-math - # being used when Apple clang v12+ is used. - # But numpy.distutils.ccompiler only sets this flag when - # $CC contains the string "clang" -- missing the case CC=/usr/bin/gcc. - # So we set it here explicitly if the compiler supports the flag. - export CFLAGS="$(testcflags.sh $CFLAGS -ftrapping-math)" -else - export {ATLAS,PTATLAS,OPENBLAS,MKL,MKLROOT}=None - export LDFLAGS="${LDFLAGS} -shared" -fi - if [ "$UNAME" = "CYGWIN" ]; then # Trac #30643 export CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE" fi -# Trac #32746: pkg-config omits -I and -L flags that refer to directories -# that are already on CPATH, LIBRARY_PATH. -# But our script tries to obtain the list of include_dirs and library_dirs -# from pkg-config! -(unset CPATH LIBRARY_PATH; python3 ../lapack_conf.py) - -# Make sure that the fortran objects are compiled with -fPIC -export FFLAGS="$FFLAGS -fPIC" -export FCFLAGS="$FCFLAGS -fPIC" - if [ "$SAGE_FAT_BINARY" = "yes" ]; then export NUMPY_FCONFIG="--cpu-baseline=NONE" else export NUMPY_FCONFIG="" fi -# Trac #32423: Fix 32-bit builds on x86_64 -ARCH=$($CC -dumpmachine 2>/dev/null || echo unknown) -case "$ARCH" in - *x86_64*) - ;; - *) - export NPY_DISABLE_SVML=1 - ;; -esac - -################################################ - -# Trac #33138: numpy is a PEP 517 package, so the crucial "--build-option"s would be ignored. -eval sdh_pip_install --no-use-pep517 \ - $(eval sdh_prefix_args "--build-option" build ${NUMPY_CONFIG} ${NUMPY_FCONFIG}) \ - . +### Per https://github.com/numpy/numpy/releases/tag/v1.26.0b1 +### "NumPy-specific build customization": +### +### The NPY_* environment variables which control BLAS/LAPACK, SIMD, +### threading, and other such options are no longer supported, nor is +### a site.cfg file to select BLAS and LAPACK. Instead, there are +### command-line flags that can be passed to the build via pip/build's +### config-settings interface. These flags are all listed in +### https://github.com/numpy/numpy/blob/main/meson_options.txt +### +### 1.26.0b1 temporarily vendors Meson and meson-python +### http://scipy.github.io/devdocs/building/index.html + + +sdh_pip_install . From 5db5acc9c6dfb649eea8070774b6ce83f81c4184 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 22 Aug 2023 12:04:35 -0700 Subject: [PATCH 043/225] build/pkgs/setuptools[_wheel]: Update from 63.4.3/65.6.3 to 68.1.2, sync versions --- build/pkgs/setuptools/SPKG.rst | 7 ------- build/pkgs/setuptools/checksums.ini | 6 +++--- build/pkgs/setuptools/package-version.txt | 2 +- build/pkgs/setuptools_wheel/SPKG.rst | 3 --- build/pkgs/setuptools_wheel/checksums.ini | 6 +----- build/pkgs/setuptools_wheel/package-version.txt | 2 +- 6 files changed, 6 insertions(+), 20 deletions(-) mode change 100644 => 120000 build/pkgs/setuptools_wheel/checksums.ini mode change 100644 => 120000 build/pkgs/setuptools_wheel/package-version.txt diff --git a/build/pkgs/setuptools/SPKG.rst b/build/pkgs/setuptools/SPKG.rst index a50e171a98d..bb69c65b66a 100644 --- a/build/pkgs/setuptools/SPKG.rst +++ b/build/pkgs/setuptools/SPKG.rst @@ -7,13 +7,6 @@ Description setuptools is the classical build system for Python packages, a collection of enhancements to the Python distutils. -This package represents version 63.x of ``setuptools``. -Sage installs this version to provide the build system -for non-PEP 517 packages. In particular, Sage uses it -for building ``numpy``, whose build system ``numpy.distutils`` -is not compatible with newer versions of ``setuptools``, -see https://github.com/numpy/numpy/pull/22154 - License ------- diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini index d47099a8019..e666bb16483 100644 --- a/build/pkgs/setuptools/checksums.ini +++ b/build/pkgs/setuptools/checksums.ini @@ -1,5 +1,5 @@ tarball=setuptools-VERSION.tar.gz -sha1=b14b8e2cf965fdb6870ebfccee50c751c056f757 -md5=02a0e4dc4fa13168904e8769a077aa26 -cksum=2734084418 +sha1=43e83ae0716615a7df123a5731412d1cd66dc81d +md5=222b8c1a7432457d8485f947a0e0fde6 +cksum=3076207771 upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt index fe3c6688881..c068d01a2ed 100644 --- a/build/pkgs/setuptools/package-version.txt +++ b/build/pkgs/setuptools/package-version.txt @@ -1 +1 @@ -63.4.3 +68.1.2 diff --git a/build/pkgs/setuptools_wheel/SPKG.rst b/build/pkgs/setuptools_wheel/SPKG.rst index b77a6679f8f..c78602a296a 100644 --- a/build/pkgs/setuptools_wheel/SPKG.rst +++ b/build/pkgs/setuptools_wheel/SPKG.rst @@ -3,6 +3,3 @@ setuptools_wheel: Build the setuptools package as a wheel After installing setuptools and wheel, we build a wheel of setuptools to complete the set of wheels stored in our wheelhouse. - -This version of setuptools is suitable for PEP 517/518/660 builds, -but it is not suitable for building ``numpy``. diff --git a/build/pkgs/setuptools_wheel/checksums.ini b/build/pkgs/setuptools_wheel/checksums.ini deleted file mode 100644 index 8db0d8c3016..00000000000 --- a/build/pkgs/setuptools_wheel/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=setuptools-VERSION.tar.gz -sha1=2875e8f9a12d8a971461b36e2d1bd64a3497e0f2 -md5=1fd8bd04b0bed95ad6c81f03b1c080bc -cksum=1462078737 -upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz diff --git a/build/pkgs/setuptools_wheel/checksums.ini b/build/pkgs/setuptools_wheel/checksums.ini new file mode 120000 index 00000000000..4f64d3ce107 --- /dev/null +++ b/build/pkgs/setuptools_wheel/checksums.ini @@ -0,0 +1 @@ +../setuptools/checksums.ini \ No newline at end of file diff --git a/build/pkgs/setuptools_wheel/package-version.txt b/build/pkgs/setuptools_wheel/package-version.txt deleted file mode 100644 index c1a8c8394ad..00000000000 --- a/build/pkgs/setuptools_wheel/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -65.6.3 diff --git a/build/pkgs/setuptools_wheel/package-version.txt b/build/pkgs/setuptools_wheel/package-version.txt new file mode 120000 index 00000000000..5268dbec8f6 --- /dev/null +++ b/build/pkgs/setuptools_wheel/package-version.txt @@ -0,0 +1 @@ +../setuptools/package-version.txt \ No newline at end of file From 009b4961365c7c65a9129c359a888c1a6a42cad5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 22 Aug 2023 12:12:17 -0700 Subject: [PATCH 044/225] build/pkgs/pip: Update to 23.2.1 --- build/pkgs/pip/checksums.ini | 6 +++--- build/pkgs/pip/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pip/checksums.ini b/build/pkgs/pip/checksums.ini index 1ae66fbc20a..9b6376d1abb 100644 --- a/build/pkgs/pip/checksums.ini +++ b/build/pkgs/pip/checksums.ini @@ -1,5 +1,5 @@ tarball=pip-VERSION.tar.gz -sha1=29167fffe19874a74247fe92f4fdba1bb1221c61 -md5=996f58a94fe0b8b82b6795c42bd171ba -cksum=537001443 +sha1=4bdfd8e976b5122cf55f4f4740f7305f1ffa4310 +md5=e9b1226701a56ee3fcc81aba60d25d75 +cksum=1940746834 upstream_url=https://pypi.io/packages/source/p/pip/pip-VERSION.tar.gz diff --git a/build/pkgs/pip/package-version.txt b/build/pkgs/pip/package-version.txt index 4c3dad97552..3f833b5b536 100644 --- a/build/pkgs/pip/package-version.txt +++ b/build/pkgs/pip/package-version.txt @@ -1 +1 @@ -22.3.1 +23.2.1 From 07e2648927b1d8949239f598e0eadb5166a6ab73 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 22 Aug 2023 12:22:55 -0700 Subject: [PATCH 045/225] build/pkgs/numpy/spkg-install.in: Remove incompatible -std=... from CXX --- build/pkgs/numpy/spkg-install.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build/pkgs/numpy/spkg-install.in b/build/pkgs/numpy/spkg-install.in index 20d2a2cef62..baebfd466a7 100644 --- a/build/pkgs/numpy/spkg-install.in +++ b/build/pkgs/numpy/spkg-install.in @@ -3,6 +3,10 @@ cd src set -e +# https://github.com/scipy/scipy/issues/16536 - meson breaks when CXX="g++ -std=gnu++11" +# -- this also affects numpy +export CXX=$(echo "$CXX" | sed 's/-std=[a-z0-9+]*//g') + if [ "$UNAME" = "CYGWIN" ]; then # Trac #30643 export CPPFLAGS="${CPPFLAGS} -D_GNU_SOURCE" From 708183aa49ebbb96ccb00aa7c03719091300bc72 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 22 Aug 2023 16:11:32 -0400 Subject: [PATCH 046/225] Fixed formatting in documentaton --- src/sage/combinat/designs/covering_array.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/designs/covering_array.py b/src/sage/combinat/designs/covering_array.py index bffdd0bf6c4..1596c708152 100644 --- a/src/sage/combinat/designs/covering_array.py +++ b/src/sage/combinat/designs/covering_array.py @@ -1,12 +1,12 @@ r""" Covering Arrays (CA) -A Covering Array, denoted CA`(N;t,k,v)`, is an `N` by `k` array with +A Covering Array, denoted `CA(N;t,k,v)`, is an `N` by `k` array with entries from a set of `v` elements with the property that in every selection of `t` columns, every sequence of `t` elements appears in at least one row. -An Orthogonal Array, denoted OA`(N;t,k,v)` is a covering array with the +An Orthogonal Array, denoted `OA(N;t,k,v)` is a covering array with the property that every sequence of `t`-elements appears in exactly one row. (See :mod:`sage.combinat.designs.orthogonal_arrays`). @@ -19,9 +19,9 @@ :widths: 30, 70 :delim: | - :meth:`~sage.combinat.designs.designs_pyx.is_covering_array` | Check that the list of lists `array` is an `CA(N;t,k,v)`. - :meth:`~sage.combinat.designs.orthogonal_arrays.OA_relabel` | Return a relabelled version of the CA. - :meth:`~sage.combinat.designs.orthogonal_arrays.OA_standard_label` | Return a version of the CA relabelled to symbols `(0,\dots,n-1)`. + :meth:`~sage.combinat.designs.designs_pyx.is_covering_array` | Check that an input list of lists is a `CA(N;t,k,v)`. + :meth:`~sage.combinat.designs.covering_array.CA_relabel` | Return a relabelled version of the CA. + :meth:`~sage.combinat.designs.covering_array.CA_standard_label` | Return a version of the CA relabelled to symbols `(0,\dots,n-1)`. REFERENCES: From 7ea4ee4b7400709531a7e3dfac45074528d3a748 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 23 Aug 2023 09:38:15 -0700 Subject: [PATCH 047/225] build/pkgs/numpy/patches: Add https://github.com/numpy/numpy/pull/24511 --- build/pkgs/numpy/patches/24511.patch | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 build/pkgs/numpy/patches/24511.patch diff --git a/build/pkgs/numpy/patches/24511.patch b/build/pkgs/numpy/patches/24511.patch new file mode 100644 index 00000000000..41e94f03241 --- /dev/null +++ b/build/pkgs/numpy/patches/24511.patch @@ -0,0 +1,30 @@ +From 31234832591b09e1982b386ff6811d348a129ec2 Mon Sep 17 00:00:00 2001 +From: mattip +Date: Wed, 23 Aug 2023 16:01:40 +0300 +Subject: [PATCH] use a default assignment for git_hash [skip ci] + +--- + numpy/_build_utils/gitversion.py | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/numpy/_build_utils/gitversion.py b/numpy/_build_utils/gitversion.py +index d910581a85d..6686ddb51fd 100644 +--- a/numpy/_build_utils/gitversion.py ++++ b/numpy/_build_utils/gitversion.py +@@ -24,6 +24,7 @@ def git_version(version): + import subprocess + import os.path + ++ git_hash = '' + try: + p = subprocess.Popen( + ['git', 'log', '-1', '--format="%H %aI"'], +@@ -48,8 +49,6 @@ def git_version(version): + # Only attach git tag to development versions + if 'dev' in version: + version += f'+git{git_date}.{git_hash[:7]}' +- else: +- git_hash = '' + + return version, git_hash + From 811ea7fe7dcc83ab435afbd808393ba2f78a7eff Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 23 Aug 2023 20:46:36 -0700 Subject: [PATCH 048/225] build/pkgs/numpy/patches: Add https://github.com/numpy/numpy/pull/24515 --- build/pkgs/numpy/patches/24515.patch | 66 ++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 build/pkgs/numpy/patches/24515.patch diff --git a/build/pkgs/numpy/patches/24515.patch b/build/pkgs/numpy/patches/24515.patch new file mode 100644 index 00000000000..08c99379d07 --- /dev/null +++ b/build/pkgs/numpy/patches/24515.patch @@ -0,0 +1,66 @@ +From e150c31194a3faff43791aa5ad3055db07f5e6e0 Mon Sep 17 00:00:00 2001 +From: Ralf Gommers +Date: Thu, 24 Aug 2023 05:18:55 +0200 +Subject: [PATCH] BUG: fix issue with git-version script, needs a shebang to + run + +Closes gh-24514 +--- + meson.build | 2 +- + numpy/_build_utils/gitversion.py | 1 + + numpy/meson.build | 13 +++++-------- + 3 files changed, 7 insertions(+), 9 deletions(-) + +diff --git a/meson.build b/meson.build +index a9e68c2eb94..0469f7f4590 100644 +--- a/meson.build ++++ b/meson.build +@@ -3,7 +3,7 @@ project( + 'c', 'cpp', 'cython', + version: run_command( + # This should become `numpy/_version.py` in NumPy 2.0 +- ['python', 'numpy/_build_utils/gitversion.py'], ++ ['numpy/_build_utils/gitversion.py'], + check: true).stdout().strip(), + license: 'BSD-3', + meson_version: '>=1.2.99', # version in vendored-meson is 1.2.99 +diff --git a/numpy/_build_utils/gitversion.py b/numpy/_build_utils/gitversion.py +index 6686ddb51fd..4ee6e00bbd6 100644 +--- a/numpy/_build_utils/gitversion.py ++++ b/numpy/_build_utils/gitversion.py +@@ -1,3 +1,4 @@ ++#!/usr/bin/env python3 + import os + import textwrap + +diff --git a/numpy/meson.build b/numpy/meson.build +index 9b9a3581a9c..40766081d14 100644 +--- a/numpy/meson.build ++++ b/numpy/meson.build +@@ -188,14 +188,6 @@ if not have_lapack and not allow_noblas + 'for some linear algebra operations).') + endif + +-# Generate version.py for sdist +-gitversion = files('_build_utils/gitversion.py')[0] +-python_bin = py.full_path() +-meson.add_dist_script( +- py, +- [gitversion, '--meson-dist', '--write', 'numpy/version.py'] +-) +- + # Copy the main __init__.py|pxd files to the build dir (needed for Cython) + __init__py = fs.copyfile('__init__.py') + __init__pxd = fs.copyfile('__init__.pxd') +@@ -257,6 +249,11 @@ endif + + np_dir = py.get_install_dir() / 'numpy' + ++# Generate version.py for sdist ++meson.add_dist_script( ++ ['_build_utils/gitversion.py', '--meson-dist', '--write', ++ 'numpy/version.py'] ++) + if not fs.exists('version.py') + generate_version = custom_target( + 'generate-version', From d7e818af166718305184864829feb14a964f05f4 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Fri, 21 Apr 2023 18:33:13 +0000 Subject: [PATCH 049/225] implement computation of traces for elliptic-curve endomorphisms --- src/sage/schemes/elliptic_curves/hom.py | 188 ++++++++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 58375d02a64..d622ba05b62 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -23,6 +23,8 @@ the common :class:`EllipticCurveHom` interface. - Lorenz Panny (2022): :meth:`~EllipticCurveHom.matrix_on_subgroup` + +- Lorenz Panny (2023): :meth:`~EllipticCurveHom.trace`, :meth:`~EllipticCurveHom.characteristic_polynomial` """ from sage.misc.cachefunc import cached_method from sage.structure.richcmp import richcmp_not_equal, richcmp, op_EQ, op_NE @@ -31,6 +33,7 @@ from sage.arith.misc import integer_floor +from sage.rings.integer_ring import ZZ from sage.rings.finite_rings import finite_field_base from sage.rings.number_field import number_field_base @@ -283,6 +286,83 @@ def degree(self): except AttributeError: raise NotImplementedError('children must implement') + @cached_method + def trace(self): + r""" + Return the trace of this elliptic-curve morphism, which must + be an endomorphism. + + ALGORITHM: :func:`compute_trace_generic` + + EXAMPLES:: + + sage: E = EllipticCurve(QQ, [42, 42]) + sage: m5 = E.scalar_multiplication(5) + sage: m5.trace() + 10 + + :: + + sage: E = EllipticCurve(GF(71^2), [45, 45]) + sage: P = E.lift_x(27) + sage: P.order() + 71 + sage: tau = E.isogeny(P, codomain=E) + sage: tau.trace() + -1 + + TESTS: + + It also works for more complicated :class:`EllipticCurveHom` + children:: + + sage: tau = E.isogeny(P, codomain=E, algorithm='velusqrt') + sage: tau.trace() + -1 + + Check that negation commutes with taking the trace:: + + sage: (-tau).trace() + 1 + """ + return compute_trace_generic(self) + + def characteristic_polynomial(self): + r""" + Return the characteristic polynomial of this elliptic-curve + morphism, which must be an endomorphism. + + .. SEEALSO:: + + - :meth:`degree` + - :meth:`trace` + + EXAMPLES:: + + sage: E = EllipticCurve(QQ, [42, 42]) + sage: m5 = E.scalar_multiplication(5) + sage: m5.characteristic_polynomial() + x^2 - 10*x + 25 + + :: + + sage: E = EllipticCurve(GF(71), [42, 42]) + sage: pi = E.frobenius_endomorphism() + sage: pi.characteristic_polynomial() + x^2 - 8*x + 71 + sage: E.frobenius().charpoly() + x^2 - 8*x + 71 + + TESTS:: + + sage: m5.characteristic_polynomial().parent() + Univariate Polynomial Ring in x over Integer Ring + sage: pi.characteristic_polynomial().parent() + Univariate Polynomial Ring in x over Integer Ring + """ + R = ZZ['x'] + return R([self.degree(), -self.trace(), 1]) + def kernel_polynomial(self): r""" Return the kernel polynomial of this elliptic-curve morphism. @@ -1006,3 +1086,111 @@ def find_post_isomorphism(phi, psi): # found no suitable isomorphism -- either doesn't exist or a bug raise ValueError('isogenies not equal up to post-isomorphism') + + +def compute_trace_generic(phi): + r""" + Compute the trace of the given elliptic-curve endomorphism `\varphi`. + + ALGORITHM: Simple variant of Schoof's algorithm. + + EXAMPLES: + + It works over finite fields:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(GF(31337), [1,1]) + sage: compute_trace_generic(E.frobenius_endomorphism()) + 314 + + It works over `\QQ`:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(QQ, [1,2,3,4,5]) + sage: m3 = E.scalar_multiplication(3) + sage: compute_trace_generic(m3) + 6 + + It works over number fields (for a CM curve):: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: x = polygen(QQ) + sage: K. = NumberField(5*x^2 - 2*x + 1) + sage: E = EllipticCurve(K, [1,0]) + sage: phi = E.isogeny([t,0,1], codomain=E) # phi = 1 + 2*i + sage: compute_trace_generic(phi) + 4 + + TESTS: + + Check on random elliptic curves over finite fields that + the result for Frobenius matches + :meth:`~sage.schemes.elliptic_curves.ell_finite_field.EllipticCurve_finite_field.trace_of_frobenius`:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: p = random_prime(10^3) + sage: e = randrange(1, ceil(log(10^5,p))) + sage: F. = GF((p, e)) + sage: E = choice(EllipticCurve(j=F.random_element()).twists()) + sage: pi = E.frobenius_endomorphism() + sage: compute_trace_generic(pi) == E.trace_of_frobenius() + True + + Check that the nonexistence of `p`-torsion for supersingular curves + does not cause trouble:: + + sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic + sage: E = EllipticCurve(GF(5), [0,1]) + sage: E.division_polynomial(5) + 4 + sage: m7 = E.scalar_multiplication(7) + sage: compute_trace_generic(-m7) + -14 + """ + from sage.rings.finite_rings.integer_mod import Mod + from sage.groups.generic import discrete_log + from sage.sets.primes import Primes + + E = phi.domain() + if phi.codomain() != E: + raise ValueError('trace only makes sense for endomorphisms') + + d = phi.degree() + + F = E.base_field() + S,X = F['X'].objgen() + + M = 4 * d.isqrt() + 1 # |trace| <= 2 sqrt(deg) + tr = Mod(0,1) + + for l in Primes(): + xpoly = E.division_polynomial(l) + if xpoly.degree() < 1: # supersingular and l == p + continue + mu = xpoly.factor()[0][0] + if isinstance(F, number_field_base.NumberField): + FF = F.extension(mu, 'X') + else: + FF = mu.splitting_field('X') + xx = mu.any_root(ring=FF, assume_squarefree=True) + T,Y = FF['Y'].objgen() + ypoly = E.defining_polynomial()(xx, Y, 1) + if ypoly.is_irreducible(): + if isinstance(F, number_field_base.NumberField): + FF = FF.extension(ypoly, 'Y') + else: + FF = ypoly.splitting_field('Y') + xx = FF(xx) + EE = E.change_ring(FF) + P = EE.lift_x(xx) + + Q = phi._eval(P) + R = phi._eval(Q) + t = discrete_log(R + d*P, Q, ord=l, operation='+') + assert not R - t*Q + d*P + + tr = tr.crt(Mod(t, l)) + if tr.modulus() >= M: + break + + return tr.lift_centered() From 494c943a9d32136b4050dc72bc53a8277799ee92 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sat, 22 Apr 2023 13:22:02 +0800 Subject: [PATCH 050/225] use deepcopy() instead of copy() to make sure @cached_method members are cleared --- src/sage/schemes/elliptic_curves/ell_curve_isogeny.py | 8 ++++---- src/sage/schemes/elliptic_curves/hom.py | 9 ++++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index e5e35f2a139..b419cb622a6 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -79,7 +79,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from copy import copy +from copy import copy, deepcopy from sage.structure.sequence import Sequence @@ -1442,7 +1442,7 @@ def __neg__(self): sage: negphi.rational_maps() # optional - sage.rings.number_field ((x^2 + (-a)*x - 2)/(x + (-a)), (-x^2*y + (2*a)*x*y - y)/(x^2 + (-2*a)*x - 1)) """ - output = copy(self) + output = deepcopy(self) output._set_post_isomorphism(negation_morphism(output._codomain)) return output @@ -3312,13 +3312,13 @@ def _composition_impl(left, right): NotImplemented """ if isinstance(left, WeierstrassIsomorphism) and isinstance(right, EllipticCurveIsogeny): - result = copy(right) + result = deepcopy(right) result._set_post_isomorphism(left) return result if isinstance(left, EllipticCurveIsogeny) and isinstance(right, WeierstrassIsomorphism): assert isinstance(left, EllipticCurveIsogeny) - result = copy(left) + result = deepcopy(left) result._set_pre_isomorphism(right) return result diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index d622ba05b62..0ec2b30b7bb 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -313,6 +313,13 @@ def trace(self): TESTS: + Make sure the cached value of the trace is not accidentally + copied on composition with automorphisms:: + + sage: aut = E.automorphisms()[1] # [-1] + sage: (aut * tau).trace() + 1 + It also works for more complicated :class:`EllipticCurveHom` children:: @@ -772,7 +779,7 @@ def __hash__(self): sage: EllipticCurveIsogeny(E,X^3-13*X^2-58*X+503,check=False) Isogeny of degree 7 from Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 107*x + 552 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 - x^2 - 5252*x - 178837 over Rational Field """ - return hash((self.domain(), self.codomain(), self.kernel_polynomial())) + return hash((self.domain(), self.codomain(), self.kernel_polynomial(), self.scaling_factor())) def as_morphism(self): r""" From ee64c2ad39f5011084975f38397e2f66c389893c Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sat, 22 Apr 2023 12:54:20 +0800 Subject: [PATCH 051/225] reviewer comments --- src/sage/schemes/elliptic_curves/hom.py | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 0ec2b30b7bb..7a4f377c2bb 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -1057,8 +1057,6 @@ def find_post_isomorphism(phi, psi): raise ValueError('codomains not isomorphic') F = E.base_ring() - from sage.rings.finite_rings import finite_field_base - from sage.rings.number_field import number_field_base if isinstance(F, finite_field_base.FiniteField): while len(isos) > 1: @@ -1100,6 +1098,12 @@ def compute_trace_generic(phi): Compute the trace of the given elliptic-curve endomorphism `\varphi`. ALGORITHM: Simple variant of Schoof's algorithm. + For enough small primes `\ell`, we find an order-`\ell` point `P` + on `E` and use a discrete-logarithm calculation to find the unique + scalar `t_\ell \in \{0,...,\ell-1\}` such that + `\varphi^2(P)+[\deg(\varphi)]P = [t_\ell]\varphi(P)`. + Then `t_\ell` equals the trace of `\varphi` modulo `\ell`, which + can therefore be recovered using the Chinese remainder theorem. EXAMPLES: @@ -1124,7 +1128,7 @@ def compute_trace_generic(phi): sage: x = polygen(QQ) sage: K. = NumberField(5*x^2 - 2*x + 1) sage: E = EllipticCurve(K, [1,0]) - sage: phi = E.isogeny([t,0,1], codomain=E) # phi = 1 + 2*i + sage: phi = E.isogeny([t,0,1], codomain=E) # phi = 2 + i sage: compute_trace_generic(phi) 4 @@ -1155,9 +1159,21 @@ def compute_trace_generic(phi): -14 """ from sage.rings.finite_rings.integer_mod import Mod + from sage.rings.polynomial.polynomial_ring import polygen from sage.groups.generic import discrete_log from sage.sets.primes import Primes + # Construct the field extension defined by the given polynomial, + # in such a way that the result is recognized by Sage as a field. + def ffext(poly): + rng = poly.parent() + fld = rng.base_ring() + if isinstance(fld, finite_field_base.FiniteField): + # Workaround: .extension() would return a PolynomialQuotientRing + # rather than another FiniteField. + return poly.splitting_field(rng.variable_name()) + return fld.extension(poly, rng.variable_name()) + E = phi.domain() if phi.codomain() != E: raise ValueError('trace only makes sense for endomorphisms') @@ -1165,7 +1181,7 @@ def compute_trace_generic(phi): d = phi.degree() F = E.base_field() - S,X = F['X'].objgen() + X = polygen(F, 'X') M = 4 * d.isqrt() + 1 # |trace| <= 2 sqrt(deg) tr = Mod(0,1) @@ -1175,18 +1191,12 @@ def compute_trace_generic(phi): if xpoly.degree() < 1: # supersingular and l == p continue mu = xpoly.factor()[0][0] - if isinstance(F, number_field_base.NumberField): - FF = F.extension(mu, 'X') - else: - FF = mu.splitting_field('X') + FF = ffext(mu) xx = mu.any_root(ring=FF, assume_squarefree=True) - T,Y = FF['Y'].objgen() + Y = polygen(FF, 'Y') ypoly = E.defining_polynomial()(xx, Y, 1) if ypoly.is_irreducible(): - if isinstance(F, number_field_base.NumberField): - FF = FF.extension(ypoly, 'Y') - else: - FF = ypoly.splitting_field('Y') + FF = ffext(ypoly) xx = FF(xx) EE = E.change_ring(FF) P = EE.lift_x(xx) From d522c0a6372b9b3aa36c1ef9e455450c6c43aaf9 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Tue, 9 May 2023 23:35:54 +0800 Subject: [PATCH 052/225] more reviewer comments --- src/sage/schemes/elliptic_curves/hom.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 7a4f377c2bb..c01cfb833cc 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -332,6 +332,11 @@ def trace(self): sage: (-tau).trace() 1 """ + F = self.domain().base_field() + if F.characteristic().is_zero(): + d = self.degree() + s = self.scaling_factor() + return ZZ(s + d/s) return compute_trace_generic(self) def characteristic_polynomial(self): @@ -1186,7 +1191,15 @@ def ffext(poly): M = 4 * d.isqrt() + 1 # |trace| <= 2 sqrt(deg) tr = Mod(0,1) + p = F.characteristic() + if p: + s = phi.scaling_factor() + if s: + tr = Mod(ZZ(s + d/s), p) + for l in Primes(): + if tr.modulus() >= M: + break xpoly = E.division_polynomial(l) if xpoly.degree() < 1: # supersingular and l == p continue @@ -1202,12 +1215,12 @@ def ffext(poly): P = EE.lift_x(xx) Q = phi._eval(P) + if not Q: # we learn nothing when P lies in the kernel + continue R = phi._eval(Q) t = discrete_log(R + d*P, Q, ord=l, operation='+') assert not R - t*Q + d*P tr = tr.crt(Mod(t, l)) - if tr.modulus() >= M: - break return tr.lift_centered() From f665235c9e0a7ee89afe99fd6f0d21a6a6b176d1 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 14 May 2023 15:56:04 +0800 Subject: [PATCH 053/225] use smaller scalar to make test (much) faster --- src/sage/schemes/elliptic_curves/hom.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index c01cfb833cc..829e6481d89 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -1123,9 +1123,9 @@ def compute_trace_generic(phi): sage: from sage.schemes.elliptic_curves.hom import compute_trace_generic sage: E = EllipticCurve(QQ, [1,2,3,4,5]) - sage: m3 = E.scalar_multiplication(3) - sage: compute_trace_generic(m3) - 6 + sage: dbl = E.scalar_multiplication(2) + sage: compute_trace_generic(dbl) + 4 It works over number fields (for a CM curve):: From 7503d40d9fc1742cb64f923f36d79f6e12ea6636 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Wed, 28 Jun 2023 16:24:35 +0800 Subject: [PATCH 054/225] factor out point_of_order() --- src/sage/schemes/elliptic_curves/ell_field.py | 69 +++++++++++++++++++ src/sage/schemes/elliptic_curves/hom.py | 38 +++------- 2 files changed, 77 insertions(+), 30 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 3c359e3de03..b6d74ac73e2 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -2034,3 +2034,72 @@ def compute_model(E, name): return E.montgomery_model() raise NotImplementedError(f'cannot compute {name} model') + +def point_of_order(E, l): + r""" + Given an elliptic curve `E` over a finite field or a number field + and an integer `\ell \geq 1`, construct a point of order `\ell` on `E`, + possibly defined over an extension of the base field of `E`. + + Currently only prime values of `\ell` are supported. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.ell_field import point_of_order + sage: E = EllipticCurve(GF(101), [1,2,3,4,5]) + sage: P = point_of_order(E, 5); P + (50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1) + sage: P.base_ring() + Finite Field in Y of size 101^6 + sage: P.order() + 5 + sage: P.curve().a_invariants() + (1, 2, 3, 4, 5) + + :: + + sage: from sage.schemes.elliptic_curves.ell_field import point_of_order + sage: E = EllipticCurve(QQ, [7,7]) + sage: P = point_of_order(E, 3); P + (x : -Y : 1) + sage: P.base_ring() + Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field + sage: P.order() + 3 + sage: P.curve().a_invariants() + (0, 0, 0, 7, 7) + """ + # Construct the field extension defined by the given polynomial, + # in such a way that the result is recognized by Sage as a field. + def ffext(poly): + rng = poly.parent() + fld = rng.base_ring() + if fld in FiniteFields(): + # Workaround: .extension() would return a PolynomialQuotientRing + # rather than another FiniteField. + return poly.splitting_field(rng.variable_name()) + return fld.extension(poly, rng.variable_name()) + + l = ZZ(l) + if l == 1: + return E(0) + + if not l.is_prime(): + raise NotImplementedError('composite orders are currently unsupported') + + xpoly = E.division_polynomial(l) + if xpoly.degree() < 1: # supersingular and l == p + raise ValueError('curve does not have any points of the specified order') + + mu = xpoly.factor()[0][0] + FF = ffext(mu) + xx = mu.any_root(ring=FF, assume_squarefree=True) + + Y = polygen(FF, 'Y') + ypoly = E.defining_polynomial()(xx, Y, 1) + if ypoly.is_irreducible(): + FF = ffext(ypoly) + xx = FF(xx) + + EE = E.change_ring(FF) + return EE.lift_x(xx) diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 829e6481d89..995420ae438 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -1100,7 +1100,7 @@ def find_post_isomorphism(phi, psi): def compute_trace_generic(phi): r""" - Compute the trace of the given elliptic-curve endomorphism `\varphi`. + Compute the trace of the given elliptic-curve endomorphism. ALGORITHM: Simple variant of Schoof's algorithm. For enough small primes `\ell`, we find an order-`\ell` point `P` @@ -1164,20 +1164,9 @@ def compute_trace_generic(phi): -14 """ from sage.rings.finite_rings.integer_mod import Mod - from sage.rings.polynomial.polynomial_ring import polygen from sage.groups.generic import discrete_log from sage.sets.primes import Primes - - # Construct the field extension defined by the given polynomial, - # in such a way that the result is recognized by Sage as a field. - def ffext(poly): - rng = poly.parent() - fld = rng.base_ring() - if isinstance(fld, finite_field_base.FiniteField): - # Workaround: .extension() would return a PolynomialQuotientRing - # rather than another FiniteField. - return poly.splitting_field(rng.variable_name()) - return fld.extension(poly, rng.variable_name()) + from sage.schemes.elliptic_curves.ell_field import point_of_order E = phi.domain() if phi.codomain() != E: @@ -1185,12 +1174,10 @@ def ffext(poly): d = phi.degree() - F = E.base_field() - X = polygen(F, 'X') - M = 4 * d.isqrt() + 1 # |trace| <= 2 sqrt(deg) tr = Mod(0,1) + F = E.base_field() p = F.characteristic() if p: s = phi.scaling_factor() @@ -1200,26 +1187,17 @@ def ffext(poly): for l in Primes(): if tr.modulus() >= M: break - xpoly = E.division_polynomial(l) - if xpoly.degree() < 1: # supersingular and l == p - continue - mu = xpoly.factor()[0][0] - FF = ffext(mu) - xx = mu.any_root(ring=FF, assume_squarefree=True) - Y = polygen(FF, 'Y') - ypoly = E.defining_polynomial()(xx, Y, 1) - if ypoly.is_irreducible(): - FF = ffext(ypoly) - xx = FF(xx) - EE = E.change_ring(FF) - P = EE.lift_x(xx) + try: + P = point_of_order(E, l) + except ValueError: + continue # supersingular and l == p Q = phi._eval(P) if not Q: # we learn nothing when P lies in the kernel continue R = phi._eval(Q) t = discrete_log(R + d*P, Q, ord=l, operation='+') - assert not R - t*Q + d*P +# assert not R - t*Q + d*P tr = tr.crt(Mod(t, l)) From c0398097dcaf29ea4042a1f7d65f886ad29d4edb Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Mon, 4 Sep 2023 11:59:34 +0200 Subject: [PATCH 055/225] mark doctest output as random --- src/sage/schemes/elliptic_curves/ell_field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index b6d74ac73e2..6738bfc2cef 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -2060,7 +2060,7 @@ def point_of_order(E, l): sage: from sage.schemes.elliptic_curves.ell_field import point_of_order sage: E = EllipticCurve(QQ, [7,7]) - sage: P = point_of_order(E, 3); P + sage: P = point_of_order(E, 3); P # random (x : -Y : 1) sage: P.base_ring() Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field From 057823f9d246703a4c7a673dc43e646e89c74797 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 7 Sep 2023 09:12:17 -0700 Subject: [PATCH 056/225] build/pkgs/numpy: Update to 1.26.0rc1, remove patches --- build/pkgs/numpy/checksums.ini | 6 +-- build/pkgs/numpy/package-version.txt | 2 +- build/pkgs/numpy/patches/24511.patch | 30 ------------- build/pkgs/numpy/patches/24515.patch | 66 ---------------------------- 4 files changed, 4 insertions(+), 100 deletions(-) delete mode 100644 build/pkgs/numpy/patches/24511.patch delete mode 100644 build/pkgs/numpy/patches/24515.patch diff --git a/build/pkgs/numpy/checksums.ini b/build/pkgs/numpy/checksums.ini index 5f6e6f3abec..b71fbb37b7e 100644 --- a/build/pkgs/numpy/checksums.ini +++ b/build/pkgs/numpy/checksums.ini @@ -1,5 +1,5 @@ tarball=numpy-VERSION.tar.gz -sha1=7c36e75f2c063e51d1bb06cef7afb060d03b0dba -md5=3268568cee06327fa34175aa3805829d -cksum=2513117438 +sha1=514f9201d6c3ba0f7e88400e72bb3fb179aa31fc +md5=23bf7c39807a9cce5c8ea0ba293b7dd9 +cksum=3121934199 upstream_url=https://pypi.io/packages/source/n/numpy/numpy-VERSION.tar.gz diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index 47e51734ede..0635ee2cc52 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.26.0b1 +1.26.0rc1 diff --git a/build/pkgs/numpy/patches/24511.patch b/build/pkgs/numpy/patches/24511.patch deleted file mode 100644 index 41e94f03241..00000000000 --- a/build/pkgs/numpy/patches/24511.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 31234832591b09e1982b386ff6811d348a129ec2 Mon Sep 17 00:00:00 2001 -From: mattip -Date: Wed, 23 Aug 2023 16:01:40 +0300 -Subject: [PATCH] use a default assignment for git_hash [skip ci] - ---- - numpy/_build_utils/gitversion.py | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/numpy/_build_utils/gitversion.py b/numpy/_build_utils/gitversion.py -index d910581a85d..6686ddb51fd 100644 ---- a/numpy/_build_utils/gitversion.py -+++ b/numpy/_build_utils/gitversion.py -@@ -24,6 +24,7 @@ def git_version(version): - import subprocess - import os.path - -+ git_hash = '' - try: - p = subprocess.Popen( - ['git', 'log', '-1', '--format="%H %aI"'], -@@ -48,8 +49,6 @@ def git_version(version): - # Only attach git tag to development versions - if 'dev' in version: - version += f'+git{git_date}.{git_hash[:7]}' -- else: -- git_hash = '' - - return version, git_hash - diff --git a/build/pkgs/numpy/patches/24515.patch b/build/pkgs/numpy/patches/24515.patch deleted file mode 100644 index 08c99379d07..00000000000 --- a/build/pkgs/numpy/patches/24515.patch +++ /dev/null @@ -1,66 +0,0 @@ -From e150c31194a3faff43791aa5ad3055db07f5e6e0 Mon Sep 17 00:00:00 2001 -From: Ralf Gommers -Date: Thu, 24 Aug 2023 05:18:55 +0200 -Subject: [PATCH] BUG: fix issue with git-version script, needs a shebang to - run - -Closes gh-24514 ---- - meson.build | 2 +- - numpy/_build_utils/gitversion.py | 1 + - numpy/meson.build | 13 +++++-------- - 3 files changed, 7 insertions(+), 9 deletions(-) - -diff --git a/meson.build b/meson.build -index a9e68c2eb94..0469f7f4590 100644 ---- a/meson.build -+++ b/meson.build -@@ -3,7 +3,7 @@ project( - 'c', 'cpp', 'cython', - version: run_command( - # This should become `numpy/_version.py` in NumPy 2.0 -- ['python', 'numpy/_build_utils/gitversion.py'], -+ ['numpy/_build_utils/gitversion.py'], - check: true).stdout().strip(), - license: 'BSD-3', - meson_version: '>=1.2.99', # version in vendored-meson is 1.2.99 -diff --git a/numpy/_build_utils/gitversion.py b/numpy/_build_utils/gitversion.py -index 6686ddb51fd..4ee6e00bbd6 100644 ---- a/numpy/_build_utils/gitversion.py -+++ b/numpy/_build_utils/gitversion.py -@@ -1,3 +1,4 @@ -+#!/usr/bin/env python3 - import os - import textwrap - -diff --git a/numpy/meson.build b/numpy/meson.build -index 9b9a3581a9c..40766081d14 100644 ---- a/numpy/meson.build -+++ b/numpy/meson.build -@@ -188,14 +188,6 @@ if not have_lapack and not allow_noblas - 'for some linear algebra operations).') - endif - --# Generate version.py for sdist --gitversion = files('_build_utils/gitversion.py')[0] --python_bin = py.full_path() --meson.add_dist_script( -- py, -- [gitversion, '--meson-dist', '--write', 'numpy/version.py'] --) -- - # Copy the main __init__.py|pxd files to the build dir (needed for Cython) - __init__py = fs.copyfile('__init__.py') - __init__pxd = fs.copyfile('__init__.pxd') -@@ -257,6 +249,11 @@ endif - - np_dir = py.get_install_dir() / 'numpy' - -+# Generate version.py for sdist -+meson.add_dist_script( -+ ['_build_utils/gitversion.py', '--meson-dist', '--write', -+ 'numpy/version.py'] -+) - if not fs.exists('version.py') - generate_version = custom_target( - 'generate-version', From e4034863d87efb20e3a8d632c4e515353aac270b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 7 Sep 2023 12:02:23 -0700 Subject: [PATCH 057/225] build/pkgs/numpy/patches/cython3-legacy.patch: Remove --- build/pkgs/numpy/patches/cython3-legacy.patch | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 build/pkgs/numpy/patches/cython3-legacy.patch diff --git a/build/pkgs/numpy/patches/cython3-legacy.patch b/build/pkgs/numpy/patches/cython3-legacy.patch deleted file mode 100644 index dfcb9c4a69c..00000000000 --- a/build/pkgs/numpy/patches/cython3-legacy.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/tools/cythonize.py b/tools/cythonize.py -index 002b2fa..c04422e 100755 ---- a/tools/cythonize.py -+++ b/tools/cythonize.py -@@ -47,6 +47,7 @@ def process_pyx(fromfile, tofile): - flags = ['-3', '--fast-fail'] - if tofile.endswith('.cxx'): - flags.append('--cplus') -+ flags += ['--directive', 'legacy_implicit_noexcept=true'] - - subprocess.check_call( - [sys.executable, '-m', 'cython'] + flags + ["-o", tofile, fromfile]) From 6e950daa6c2042d1ad1f4f1650684d65a0760379 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 16 Sep 2023 15:44:22 +0200 Subject: [PATCH 058/225] some care in graph.py --- src/sage/graphs/graph.py | 200 +++++++++++++++++---------------------- 1 file changed, 88 insertions(+), 112 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index fe02be46c77..f4485c2d47f 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1322,8 +1322,7 @@ def graph6_string(self): raise ValueError('graph6 format supports graphs on 0 to 262143 vertices only.') elif self.has_loops() or self.has_multiple_edges(): raise ValueError('graph6 format supports only simple graphs (no loops, no multiple edges)') - else: - return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) + return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) @doc_index("Basic methods") def sparse6_string(self): @@ -1626,8 +1625,7 @@ def vertices_to_edges(x): stack.append((v, w)) seen[v] = u - else: - return self.order() == self.size() + 1 + return self.order() == self.size() + 1 @doc_index("Graph properties") def is_forest(self, certificate=False, output='vertex'): @@ -1667,20 +1665,17 @@ def is_forest(self, certificate=False, output='vertex'): if not certificate: return isit - else: - if isit: - return (True, None) - # The graph contains a cycle, and the user wants to see it. - - # No need to copy the graph - if number_of_connected_components == 1: - return self.is_tree(certificate=True, output=output) + if isit: + return (True, None) - # We try to find a cycle in each connected component - for cc in connected_components: - isit, cycle = self.subgraph(cc).is_tree(certificate=True, output=output) - if not isit: - return (False, cycle) + # The graph contains a cycle, and the user wants to see it. + if number_of_connected_components == 1: + return self.is_tree(certificate=True, output=output) + # We try to find a cycle in each connected component + for cc in connected_components: + isit, cycle = self.subgraph(cc).is_tree(certificate=True, output=output) + if not isit: + return (False, cycle) @doc_index("Graph properties") def is_cactus(self): @@ -2072,12 +2067,12 @@ def apex_vertices(self, k=None): return [next(it) for _ in range(k)] elif len(P) > 1: return [] + + # We proceed with the non planar component + if P[0].is_immutable(): + H = Graph(P[0].edges(labels=0, sort=False), immutable=False, loops=False, multiedges=False) else: - # We proceed with the non planar component - if P[0].is_immutable(): - H = Graph(P[0].edges(labels=0, sort=False), immutable=False, loops=False, multiedges=False) - else: - H = P[0] + H = P[0] elif self.is_planar(): # A planar graph is apex. @@ -2319,8 +2314,7 @@ def is_even_hole_free(self, certificate=False): if subgraph is not None: if certificate: return subgraph - else: - return False + return False start += 2 @@ -2391,8 +2385,7 @@ def is_odd_hole_free(self, certificate=False): if subgraph is not None: if certificate: return subgraph - else: - return False + return False start += 2 @@ -2518,8 +2511,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): return True return (self.adjacency_matrix()**3).trace() == 0 - else: - raise ValueError("Algorithm '%s' not yet implemented. Please contribute." % (algorithm)) + raise ValueError("Algorithm '%s' not yet implemented. Please contribute." % (algorithm)) @doc_index("Graph properties") def is_split(self): @@ -3578,8 +3570,7 @@ def bipartite_color(self): if isit: return certificate - else: - raise RuntimeError("Graph is not bipartite.") + raise RuntimeError("Graph is not bipartite.") @doc_index("Basic methods") def bipartite_sets(self): @@ -3827,8 +3818,8 @@ def func(alg): for input, output in func(algorithms): return output return use_all(['DLX', 'MILP', 'CP']) - else: - raise ValueError("the 'algorithm' keyword must be set to either 'DLX', 'MILP', 'CP' or 'parallel'") + + raise ValueError("the 'algorithm' keyword must be set to either 'DLX', 'MILP', 'CP' or 'parallel'") @doc_index("Coloring") def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, @@ -3914,8 +3905,8 @@ def coloring(self, algorithm="DLX", hex_colors=False, solver=None, verbose=0, elif algorithm == "DLX": from sage.graphs.graph_coloring import first_coloring return first_coloring(self, hex_colors=hex_colors) - else: - raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.") + + raise ValueError("The 'algorithm' keyword must be set to either 'DLX' or 'MILP'.") @doc_index("Coloring") def chromatic_symmetric_function(self, R=None): @@ -4248,10 +4239,10 @@ def weight(x): if value_only: if use_edge_labels: return sum(W[frozenset(e)] for e in d) - else: - return Integer(len(d)) - else: - return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in d], format='list_of_edges')) + return Integer(len(d)) + + return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in d], + format='list_of_edges')) elif algorithm == "LP": g = self @@ -4275,13 +4266,13 @@ def weight(x): if value_only: if use_edge_labels: return sum(w for fe, w in W.items() if b[fe]) - else: - return Integer(sum(1 for fe in L if b[fe])) - else: - return EdgesView(Graph([(u, v, L[frozenset((u, v))]) for u, v in L if b[frozenset((u, v))]], format='list_of_edges')) + return Integer(sum(1 for fe in L if b[fe])) - else: - raise ValueError('algorithm must be set to either "Edmonds" or "LP"') + return EdgesView(Graph([(u, v, L[frozenset((u, v))]) + for u, v in L if b[frozenset((u, v))]], + format='list_of_edges')) + + raise ValueError('algorithm must be set to either "Edmonds" or "LP"') @doc_index("Leftovers") def is_factor_critical(self, matching=None, algorithm='Edmonds', solver=None, verbose=0, @@ -4775,8 +4766,7 @@ def maximum_average_degree(self, value_only=True, solver=None, verbose=0): if value_only: return g_mad.average_degree() - else: - return g_mad + return g_mad @doc_index("Algorithmically hard stuff") def independent_set_of_representatives(self, family, solver=None, verbose=0, @@ -5156,8 +5146,7 @@ def centrality_degree(self, v=None): "on graphs with only one vertex") if v is None: return {v: self.degree(v)/n_minus_one for v in self} - else: - return self.degree(v)/n_minus_one + return self.degree(v)/n_minus_one # Distances @@ -5356,8 +5345,7 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, algo = 'bounds' if with_labels: return dict(zip(v, eccentricity(self, algorithm=algo, vertex_list=v))) - else: - return eccentricity(self, algorithm=algo, vertex_list=v) + return eccentricity(self, algorithm=algo, vertex_list=v) if algorithm == 'DHV': if by_weight: @@ -5366,17 +5354,15 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, return dict(zip(v, eccentricity_DHV(self, vertex_list=v, weight_function=weight_function, check_weight=check_weight))) - else: - return eccentricity_DHV(self, vertex_list=v, - weight_function=weight_function, - check_weight=check_weight) - else: - from sage.graphs.distances_all_pairs import eccentricity - if with_labels: - return dict(zip(v, eccentricity(self, algorithm=algorithm, - vertex_list=v))) - else: - return eccentricity(self, algorithm=algorithm, vertex_list=v) + return eccentricity_DHV(self, vertex_list=v, + weight_function=weight_function, + check_weight=check_weight) + + from sage.graphs.distances_all_pairs import eccentricity + if with_labels: + return dict(zip(v, eccentricity(self, algorithm=algorithm, + vertex_list=v))) + return eccentricity(self, algorithm=algorithm, vertex_list=v) if algorithm in ['Floyd-Warshall-Python', 'Floyd-Warshall-Cython', 'Johnson_Boost']: dist_dict = self.shortest_path_all_pairs(by_weight, algorithm, @@ -5410,12 +5396,11 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, if with_labels: return ecc - else: - if len(ecc) == 1: - # return single value - v, = ecc.values() - return v - return [ecc[u] for u in v] + if len(ecc) == 1: + # return single value + v, = ecc.values() + return v + return [ecc[u] for u in v] @doc_index("Distances") def radius(self, by_weight=False, algorithm='DHV', weight_function=None, @@ -5493,9 +5478,9 @@ def radius(self, by_weight=False, algorithm='DHV', weight_function=None, from sage.graphs.base.boost_graph import radius_DHV return radius_DHV(self, weight_function=weight_function, check_weight=False) - else: - from sage.graphs.distances_all_pairs import radius_DHV - return radius_DHV(self) + + from sage.graphs.distances_all_pairs import radius_DHV + return radius_DHV(self) return min(self.eccentricity(v=None, by_weight=by_weight, weight_function=weight_function, @@ -5625,9 +5610,8 @@ def diameter(self, by_weight=False, algorithm=None, weight_function=None, from sage.graphs.base.boost_graph import diameter_DHV return diameter_DHV(self, weight_function=weight_function, check_weight=False) - else: - from sage.graphs.distances_all_pairs import diameter - return diameter(self, algorithm=algorithm) + from sage.graphs.distances_all_pairs import diameter + return diameter(self, algorithm=algorithm) if algorithm in ['standard', '2sweep', 'multi-sweep', 'iFUB']: if by_weight: @@ -6606,8 +6590,7 @@ def cliques_maximal(self, algorithm="native"): elif algorithm == "NetworkX": import networkx return list(networkx.find_cliques(self.networkx_graph())) - else: - raise ValueError("Algorithm must be equal to 'native' or to 'NetworkX'.") + raise ValueError("Algorithm must be equal to 'native' or to 'NetworkX'.") @doc_index("Clique-related methods") def clique_maximum(self, algorithm="Cliquer", solver=None, verbose=0, @@ -6693,8 +6676,7 @@ def clique_maximum(self, algorithm="Cliquer", solver=None, verbose=0, integrality_tolerance=integrality_tolerance) elif algorithm == "mcqd": return mcqd(self) - else: - raise NotImplementedError("Only 'MILP', 'Cliquer' and 'mcqd' are supported.") + raise NotImplementedError("Only 'MILP', 'Cliquer' and 'mcqd' are supported.") @doc_index("Clique-related methods") def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose=0, @@ -6799,8 +6781,7 @@ def clique_number(self, algorithm="Cliquer", cliques=None, solver=None, verbose= integrality_tolerance=integrality_tolerance)) elif algorithm == "mcqd": return len(mcqd(self)) - else: - raise NotImplementedError("Only 'networkx' 'MILP' 'Cliquer' and 'mcqd' are supported.") + raise NotImplementedError("Only 'networkx' 'MILP' 'Cliquer' and 'mcqd' are supported.") @doc_index("Clique-related methods") def cliques_number_of(self, vertices=None, cliques=None): @@ -7007,9 +6988,8 @@ def independent_set(self, algorithm="Cliquer", value_only=False, reduction_rules integrality_tolerance=integrality_tolerance) if value_only: return self.order() - my_cover - else: - my_cover = set(my_cover) - return [u for u in self if u not in my_cover] + my_cover = set(my_cover) + return [u for u in self if u not in my_cover] @doc_index("Algorithmically hard stuff") def vertex_cover(self, algorithm="Cliquer", value_only=False, @@ -7294,19 +7274,19 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, # We finally reconstruct the solution according the reduction rules if value_only: return len(ppset) + len(folded_vertices) + size_cover_g - else: - # RULES 2 and 3: - cover_g.update(ppset) - # RULE 4: - folded_vertices.reverse() - for u, v, w in folded_vertices: - if u in cover_g: - cover_g.discard(u) - cover_g.add(v) - cover_g.add(w) - else: - cover_g.add(u) - return list(cover_g) + + # RULES 2 and 3: + cover_g.update(ppset) + # RULE 4: + folded_vertices.reverse() + for u, v, w in folded_vertices: + if u in cover_g: + cover_g.discard(u) + cover_g.add(v) + cover_g.add(w) + else: + cover_g.add(u) + return list(cover_g) @doc_index("Connectivity, orientations, trees") def ear_decomposition(self): @@ -7530,8 +7510,7 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, elif algorithm == "networkx": import networkx return dict(networkx.node_clique_number(self.networkx_graph(), vertices, cliques)) - else: - raise NotImplementedError("Only 'networkx' and 'cliquer' are supported.") + raise NotImplementedError("Only 'networkx' and 'cliquer' are supported.") @doc_index("Clique-related methods") def cliques_containing_vertex(self, vertices=None, cliques=None): @@ -7881,8 +7860,7 @@ def cores(self, k=None, with_labels=False): if with_labels: return core - else: - return list(core.values()) + return list(core.values()) @doc_index("Leftovers") def modular_decomposition(self, algorithm=None, style='tuple'): @@ -8076,9 +8054,10 @@ def modular_decomposition(self, algorithm=None, style='tuple'): def relabel(x): if x.node_type == NodeType.NORMAL: return x.children[0] - else: - return x.node_type, [relabel(y) for y in x.children] + return x.node_type, [relabel(y) for y in x.children] + return relabel(D) + elif style == 'tree': from sage.combinat.rooted_tree import LabelledRootedTree if D is None: @@ -8087,11 +8066,11 @@ def relabel(x): def to_tree(x): if x.node_type == NodeType.NORMAL: return LabelledRootedTree([], label=x.children[0]) - else: - return LabelledRootedTree([to_tree(y) for y in x.children], label=x.node_type) + return LabelledRootedTree([to_tree(y) for y in x.children], label=x.node_type) + return to_tree(D) - else: - raise ValueError("style must be 'tuple' or 'tree'") + + raise ValueError("style must be 'tuple' or 'tree'") @doc_index("Graph properties") def is_polyhedral(self): @@ -9104,8 +9083,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, return True except MIPSolverException: return False - else: - raise ValueError('algorithm must be set to "Edmonds", "LP_matching" or "LP"') + raise ValueError('algorithm must be set to "Edmonds", "LP_matching" or "LP"') @doc_index("Leftovers") def effective_resistance(self, i, j, *, base_ring=None): @@ -9216,9 +9194,8 @@ def effective_resistance(self, i, j, *, base_ring=None): if j in connected_i: component = self.subgraph(connected_i) return component.effective_resistance(i, j) - else: - from sage.rings.infinity import Infinity - return Infinity + from sage.rings.infinity import Infinity + return Infinity vert = list(self) i1 = vert.index(i) @@ -9754,8 +9731,7 @@ def arboricity(self, certificate=False): P = Matroid(self).partition() if certificate: return (len(P), [self.subgraph(edges=forest) for forest in P]) - else: - return len(P) + return len(P) @doc_index("Graph properties") def is_antipodal(self): From 0ade83a3d633ffa552c7e6411562360303db625a Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 16 Sep 2023 15:57:51 +0200 Subject: [PATCH 059/225] some care in digraph.py --- src/sage/graphs/digraph.py | 52 +++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index d30d5e63efa..aca8e530c6d 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -905,8 +905,7 @@ def dig6_string(self): raise ValueError('dig6 format supports graphs on 0 to 262143 vertices only') elif self.has_multiple_edges(): raise ValueError('dig6 format does not support multiple edges') - else: - return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) + return generic_graph_pyx.small_integer_to_graph6(n) + generic_graph_pyx.binary_string_to_graph6(self._bit_vector()) # Attributes @@ -1641,8 +1640,7 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, integrality_tolerance=integrality_tolerance) if value_only: return FAS + len(loops) - else: - return FAS + loops + return FAS + loops if not self.is_strongly_connected(): # If the digraph is not strongly connected, we solve the problem on @@ -1719,29 +1717,28 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, ###################################### # Ordering-based MILP Implementation # ###################################### - else: - p = MixedIntegerLinearProgram(maximization=False, solver=solver) + p = MixedIntegerLinearProgram(maximization=False, solver=solver) - b = p.new_variable(binary=True) - d = p.new_variable(integer=True, nonnegative=True) + b = p.new_variable(binary=True) + d = p.new_variable(integer=True, nonnegative=True) - n = self.order() + n = self.order() - for u, v in self.edge_iterator(labels=None): - p.add_constraint(d[u] - d[v] + n * b[u, v], min=1) + for u, v in self.edge_iterator(labels=None): + p.add_constraint(d[u] - d[v] + n * b[u, v], min=1) - for v in self: - p.add_constraint(d[v] <= n) + for v in self: + p.add_constraint(d[v] <= n) - p.set_objective(p.sum(b[e] for e in self.edge_iterator(labels=False))) + p.set_objective(p.sum(b[e] for e in self.edge_iterator(labels=False))) - p.solve(log=verbose) + p.solve(log=verbose) - b_sol = p.get_values(b, convert=bool, tolerance=integrality_tolerance) + b_sol = p.get_values(b, convert=bool, tolerance=integrality_tolerance) - if value_only: - return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e]) - return [e for e in self.edge_iterator(labels=False) if b_sol[e]] + if value_only: + return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e]) + return [e for e in self.edge_iterator(labels=False) if b_sol[e]] # Construction @@ -2366,12 +2363,11 @@ def eccentricity(self, v=None, by_weight=False, algorithm=None, if with_labels: return ecc - else: - if len(ecc) == 1: - # return single value - v, = ecc.values() - return v - return [ecc[u] for u in v] + if len(ecc) == 1: + # return single value + v, = ecc.values() + return v + return [ecc[u] for u in v] def radius(self, by_weight=False, algorithm=None, weight_function=None, check_weight=True): @@ -3264,8 +3260,7 @@ def topological_sort(self, implementation="default"): else: return S - else: - raise ValueError("implementation must be set to one of \"default\" or \"NetworkX\"") + raise ValueError("implementation must be set to one of \"default\" or \"NetworkX\"") def topological_sort_generator(self): """ @@ -3365,8 +3360,7 @@ def layout_acyclic(self, rankdir="up", **options): """ if have_dot2tex(): return self.layout_graphviz(rankdir=rankdir, **options) - else: - return self.layout_acyclic_dummy(rankdir=rankdir, **options) + return self.layout_acyclic_dummy(rankdir=rankdir, **options) def layout_acyclic_dummy(self, heights=None, rankdir='up', **options): """ From 1ec283253b73cff728880ff73e6da6b951016b05 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sat, 16 Sep 2023 16:08:10 +0200 Subject: [PATCH 060/225] some care in bipartite_graph.py --- src/sage/graphs/bipartite_graph.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index f707ee2a968..0b14a70de02 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -651,8 +651,7 @@ def __repr__(self): s = Graph._repr_(self).lower() if "bipartite" in s: return s.capitalize() - else: - return "".join(["Bipartite ", s]) + return "".join(["Bipartite ", s]) def add_vertex(self, name=None, left=False, right=False): """ @@ -734,8 +733,7 @@ def add_vertex(self, name=None, left=False, right=False): if ((left and name in self.left) or (right and name in self.right)): return - else: - raise RuntimeError("cannot add duplicate vertex to other partition") + raise RuntimeError("cannot add duplicate vertex to other partition") # add the vertex retval = Graph.add_vertex(self, name) @@ -1311,8 +1309,7 @@ def is_bipartite(self, certificate=False): color = {u: 0 for u in self.left} color.update({u: 1 for u in self.right}) return True, color - else: - return True + return True def complement(self): r""" @@ -1558,8 +1555,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): K = PolynomialRing(A.base_ring(), name) p = K(b) return p - else: - raise ValueError('algorithm must be one of "Godsil" or "rook"') + raise ValueError('algorithm must be one of "Godsil" or "rook"') def perfect_matchings(self, labels=False): r""" @@ -2212,8 +2208,7 @@ class :class:`MixedIntegerLinearProgram if value_only: return Integer(len(d)) - else: - return d + return d elif algorithm == "Edmonds" or algorithm == "LP": return Graph.matching(self, value_only=value_only, @@ -2221,9 +2216,8 @@ class :class:`MixedIntegerLinearProgram use_edge_labels=use_edge_labels, solver=solver, verbose=verbose, integrality_tolerance=integrality_tolerance) - else: - raise ValueError('algorithm must be "Hopcroft-Karp", ' - '"Eppstein", "Edmonds" or "LP"') + raise ValueError('algorithm must be "Hopcroft-Karp", ' + '"Eppstein", "Edmonds" or "LP"') def vertex_cover(self, algorithm="Konig", value_only=False, reduction_rules=True, solver=None, verbose=0, @@ -2687,5 +2681,4 @@ class by some canonization function `c`. If `G` and `H` are graphs, if certificate: return C, cert - else: - return C + return C From af3d2b7cc2cef0e4cd1de4f47d51cd6fb577805b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 10 Sep 2023 23:23:21 -0700 Subject: [PATCH 061/225] sage.rings.padics: Modularization fixes --- .../rings/padics/padic_extension_generic.py | 5 +++-- .../rings/padics/padic_extension_leaves.py | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/sage/rings/padics/padic_extension_generic.py b/src/sage/rings/padics/padic_extension_generic.py index 88027e19439..83557a951c9 100644 --- a/src/sage/rings/padics/padic_extension_generic.py +++ b/src/sage/rings/padics/padic_extension_generic.py @@ -19,10 +19,11 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +import sage.rings.abc + from .padic_generic import pAdicGeneric, ResidueLiftingMap from .padic_base_generic import pAdicBaseGeneric from sage.rings.number_field.number_field_base import NumberField -from sage.rings.number_field.order import Order from sage.rings.rational_field import QQ from sage.rings.infinity import Infinity from sage.structure.richcmp import op_EQ @@ -223,7 +224,7 @@ def _convert_map_from_(self, R): cat = R.category() else: cat = EuclideanDomains() & MetricSpaces().Complete() - elif isinstance(R, Order) and R.number_field().defining_polynomial() == self.defining_polynomial(): + elif isinstance(R, sage.rings.abc.Order) and R.number_field().defining_polynomial() == self.defining_polynomial(): cat = IntegralDomains() elif isinstance(R, NumberField) and R.defining_polynomial() == self.defining_polynomial(): if self.is_field(): diff --git a/src/sage/rings/padics/padic_extension_leaves.py b/src/sage/rings/padics/padic_extension_leaves.py index ed171e833e4..0e9f3b2ee86 100644 --- a/src/sage/rings/padics/padic_extension_leaves.py +++ b/src/sage/rings/padics/padic_extension_leaves.py @@ -20,11 +20,13 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import Zmod -from .pow_computer_ext import PowComputer_ext_maker -from .pow_computer_flint import PowComputer_flint_maker -from sage.libs.ntl.ntl_ZZ_pX import ntl_ZZ_pX + +lazy_import('sage.rings.padics.pow_computer_ext', 'PowComputer_ext_maker') +lazy_import('sage.rings.padics.pow_computer_flint', 'PowComputer_flint_maker') +lazy_import('sage.libs.ntl.ntl_ZZ_pX', 'ntl_ZZ_pX') from .unramified_extension_generic import UnramifiedExtensionGeneric from .eisenstein_extension_generic import EisensteinExtensionGeneric @@ -47,13 +49,13 @@ #from padic_general_extension_capped_relative_element import pAdicGeneralExtensionCappedRelativeElement #from padic_general_extension_lazy_element import pAdicGeneralExtensionRelaxedElement -from .padic_ZZ_pX_FM_element import pAdicZZpXFMElement -from .padic_ZZ_pX_CR_element import pAdicZZpXCRElement -from .padic_ZZ_pX_CA_element import pAdicZZpXCAElement -from .qadic_flint_CR import qAdicCappedRelativeElement -from .qadic_flint_CA import qAdicCappedAbsoluteElement -from .qadic_flint_FM import qAdicFixedModElement -from .qadic_flint_FP import qAdicFloatingPointElement +lazy_import('sage.rings.padics.padic_ZZ_pX_FM_element', 'pAdicZZpXFMElement') +lazy_import('sage.rings.padics.padic_ZZ_pX_CR_element', 'pAdicZZpXCRElement') +lazy_import('sage.rings.padics.padic_ZZ_pX_CA_element', 'pAdicZZpXCAElement') +lazy_import('sage.rings.padics.qadic_flint_CR', 'qAdicCappedRelativeElement') +lazy_import('sage.rings.padics.qadic_flint_CA', 'qAdicCappedAbsoluteElement') +lazy_import('sage.rings.padics.qadic_flint_FM', 'qAdicFixedModElement') +lazy_import('sage.rings.padics.qadic_flint_FP', 'qAdicFloatingPointElement') def _make_integral_poly(exact_modulus, p, prec): """ From 9d8036b01db185760ccb59b473d2d11dbdfc22b9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Sep 2023 00:08:19 -0700 Subject: [PATCH 062/225] sage.rings.padics: Fix up import, update # needs --- src/sage/rings/padics/factory.py | 5 ++--- .../rings/padics/padic_extension_leaves.py | 22 +++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index d8d7c7e3c3b..cea226d80c9 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -3231,10 +3231,9 @@ class pAdicExtension_class(UniqueFactory): sage: R = Zp(5,3) sage: S. = ZZ[] - sage: W. = pAdicExtension(R, x^4 - 15) - sage: W + sage: W. = pAdicExtension(R, x^4 - 15); W # needs sage.libs.ntl 5-adic Eisenstein Extension Ring in w defined by x^4 - 15 - sage: W.precision_cap() + sage: W.precision_cap() # needs sage.libs.ntl 12 """ def create_key_and_extra_args(self, base, modulus, prec=None, print_mode=None, diff --git a/src/sage/rings/padics/padic_extension_leaves.py b/src/sage/rings/padics/padic_extension_leaves.py index 0e9f3b2ee86..bf5599f7c59 100644 --- a/src/sage/rings/padics/padic_extension_leaves.py +++ b/src/sage/rings/padics/padic_extension_leaves.py @@ -49,13 +49,21 @@ #from padic_general_extension_capped_relative_element import pAdicGeneralExtensionCappedRelativeElement #from padic_general_extension_lazy_element import pAdicGeneralExtensionRelaxedElement -lazy_import('sage.rings.padics.padic_ZZ_pX_FM_element', 'pAdicZZpXFMElement') -lazy_import('sage.rings.padics.padic_ZZ_pX_CR_element', 'pAdicZZpXCRElement') -lazy_import('sage.rings.padics.padic_ZZ_pX_CA_element', 'pAdicZZpXCAElement') -lazy_import('sage.rings.padics.qadic_flint_CR', 'qAdicCappedRelativeElement') -lazy_import('sage.rings.padics.qadic_flint_CA', 'qAdicCappedAbsoluteElement') -lazy_import('sage.rings.padics.qadic_flint_FM', 'qAdicFixedModElement') -lazy_import('sage.rings.padics.qadic_flint_FP', 'qAdicFloatingPointElement') +try: + from .padic_ZZ_pX_FM_element import pAdicZZpXFMElement + from .padic_ZZ_pX_CR_element import pAdicZZpXCRElement + from .padic_ZZ_pX_CA_element import pAdicZZpXCAElement +except ImportError: + pass + +try: + from .qadic_flint_CR import qAdicCappedRelativeElement + from .qadic_flint_CA import qAdicCappedAbsoluteElement + from .qadic_flint_FM import qAdicFixedModElement + from .qadic_flint_FP import qAdicFloatingPointElement +except ImportError: + pass + def _make_integral_poly(exact_modulus, p, prec): """ From d03dd0c3305dd8fa05560f3c880a763ba8d140aa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 22 Feb 2023 20:33:27 -0800 Subject: [PATCH 063/225] src/sage/sets: Add # optional --- src/sage/sets/cartesian_product.py | 24 ++-- src/sage/sets/set.py | 194 +++++++++++++++-------------- 2 files changed, 110 insertions(+), 108 deletions(-) diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index f110f55cfc9..dac1cef42c0 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -37,14 +37,14 @@ class CartesianProduct(UniqueRepresentation, Parent): EXAMPLES:: - sage: G = cartesian_product([GF(5), Permutations(10)]) - sage: G.cartesian_factors() + sage: G = cartesian_product([GF(5), Permutations(10)]) # optional - sage.libs.pari + sage: G.cartesian_factors() # optional - sage.libs.pari (Finite Field of size 5, Standard permutations of 10) - sage: G.cardinality() + sage: G.cardinality() # optional - sage.libs.pari 18144000 - sage: G.random_element() # random + sage: G.random_element() # random # optional - sage.libs.pari (1, [4, 7, 6, 5, 10, 1, 3, 2, 8, 9]) - sage: G.category() + sage: G.category() # optional - sage.libs.pari Join of Category of finite monoids and Category of Cartesian products of monoids and Category of Cartesian products of finite enumerated sets @@ -93,24 +93,24 @@ def _element_constructor_(self, x): EXAMPLES:: - sage: C = cartesian_product([GF(5), GF(3)]) - sage: x = C((1,3)); x + sage: C = cartesian_product([GF(5), GF(3)]) # optional - sage.libs.pari + sage: x = C((1,3)); x # optional - sage.libs.pari (1, 0) - sage: x.parent() + sage: x.parent() # optional - sage.libs.pari The Cartesian product of (Finite Field of size 5, Finite Field of size 3) - sage: x[0].parent() + sage: x[0].parent() # optional - sage.libs.pari Finite Field of size 5 - sage: x[1].parent() + sage: x[1].parent() # optional - sage.libs.pari Finite Field of size 3 An iterable is also accepted as input:: - sage: C(i for i in range(2)) + sage: C(i for i in range(2)) # optional - sage.libs.pari (0, 1) TESTS:: - sage: C((1,3,4)) + sage: C((1,3,4)) # optional - sage.libs.pari Traceback (most recent call last): ... ValueError: (1, 3, 4) should be of length 2 diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index a1789c61300..dab3cf749f7 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -71,7 +71,7 @@ def has_finite_length(obj): True sage: has_finite_length(iter(range(10))) False - sage: has_finite_length(GF(17^127)) + sage: has_finite_length(GF(17^127)) # optional - sage.libs.pari True sage: has_finite_length(ZZ) False @@ -100,7 +100,7 @@ def Set(X=None, category=None): EXAMPLES:: - sage: X = Set(GF(9,'a')) + sage: X = Set(GF(9, 'a')) # optional - sage.libs.pari sage: X {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} sage: type(X) @@ -218,18 +218,24 @@ def union(self, X): EXAMPLES:: sage: Set(QQ).union(Set(ZZ)) - Set-theoretic union of Set of elements of Rational Field and Set of elements of Integer Ring + Set-theoretic union of + Set of elements of Rational Field and + Set of elements of Integer Ring sage: Set(QQ) + Set(ZZ) - Set-theoretic union of Set of elements of Rational Field and Set of elements of Integer Ring - sage: X = Set(QQ).union(Set(GF(3))); X - Set-theoretic union of Set of elements of Rational Field and {0, 1, 2} - sage: 2/3 in X + Set-theoretic union of + Set of elements of Rational Field and + Set of elements of Integer Ring + sage: X = Set(QQ).union(Set(GF(3))); X # optional - sage.libs.pari + Set-theoretic union of + Set of elements of Rational Field and + {0, 1, 2} + sage: 2/3 in X # optional - sage.libs.pari True - sage: GF(3)(2) in X + sage: GF(3)(2) in X # optional - sage.libs.pari True - sage: GF(5)(2) in X + sage: GF(5)(2) in X # optional - sage.libs.pari False - sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) + sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) # optional - sage.libs.pari [0, 0, 1, 1, 2, 2, 3, 4, 5, 6] """ if isinstance(X, (Set_generic, Set_base)): @@ -253,12 +259,10 @@ def intersection(self, X): sage: 2/1 in X True - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))) - sage: X + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))); X # optional - sage.libs.pari {} - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))) - sage: X + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))); X # optional - sage.libs.pari {} """ if isinstance(X, (Set_generic, Set_base)): @@ -282,12 +286,10 @@ def difference(self, X): sage: 4/1 in X True - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))) - sage: X + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))); X # optional - sage.libs.pari {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))) - sage: X + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))); X # optional - sage.libs.pari {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} """ if isinstance(X, (Set_generic, Set_base)): @@ -411,11 +413,11 @@ def __add__(self, X): Set-theoretic union of Set of elements of Real Field with 53 bits of precision and Set of elements of Vector space of dimension 5 over Rational Field - sage: Set(GF(3)) + Set(GF(2)) + sage: Set(GF(3)) + Set(GF(2)) # optional - sage.libs.pari {0, 1, 2, 0, 1} - sage: Set(GF(2)) + Set(GF(4,'a')) + sage: Set(GF(2)) + Set(GF(4,'a')) # optional - sage.libs.pari {0, 1, a, a + 1} - sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) + sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) # optional - sage.libs.pari [0, 0, 1, 1, a, a + 1, b, b + 1, b^2, b^2 + 1, b^2 + b, b^2 + b + 1] """ return self.union(X) @@ -441,14 +443,14 @@ class Set_object(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_opera EXAMPLES:: - sage: K = GF(19) - sage: Set(K) + sage: K = GF(19) # optional - sage.libs.pari + sage: Set(K) # optional - sage.libs.pari {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} - sage: S = Set(K) + sage: S = Set(K) # optional - sage.libs.pari - sage: latex(S) + sage: latex(S) # optional - sage.libs.pari \left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\} - sage: TestSuite(S).run() + sage: TestSuite(S).run() # optional - sage.libs.pari sage: latex(Set(ZZ)) \Bold{Z} @@ -606,7 +608,7 @@ def __contains__(self, x): sage: X = Set(ZZ) sage: 5 in X True - sage: GF(7)(3) in X + sage: GF(7)(3) in X # optional - sage.libs.pari True sage: 2/1 in X True @@ -618,16 +620,16 @@ def __contains__(self, x): Finite fields better illustrate the difference between ``__contains__`` for objects and their underlying sets:: - sage: X = Set(GF(7)) - sage: X + sage: X = Set(GF(7)) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, 2, 3, 4, 5, 6} - sage: 5/3 in X + sage: 5/3 in X # optional - sage.libs.pari False - sage: 5/3 in GF(7) + sage: 5/3 in GF(7) # optional - sage.libs.pari False - sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) + sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) # optional - sage.libs.pari [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6] - sage: Set(GF(7)).intersection(Set(GF(5))) + sage: Set(GF(7)).intersection(Set(GF(5))) # optional - sage.libs.pari {} """ return x in self.__object @@ -671,9 +673,9 @@ def cardinality(self): +Infinity sage: Primes().cardinality() +Infinity - sage: Set(GF(5)).cardinality() + sage: Set(GF(5)).cardinality() # optional - sage.libs.pari 5 - sage: Set(GF(5^2,'a')).cardinality() + sage: Set(GF(5^2,'a')).cardinality() # optional - sage.libs.pari 25 """ if self in Sets().Infinite(): @@ -739,7 +741,7 @@ def is_finite(self): sage: Set(QQ).is_finite() False - sage: Set(GF(250037)).is_finite() + sage: Set(GF(250037)).is_finite() # optional - sage.libs.pari True sage: Set(Integers(2^1000000)).is_finite() True @@ -853,13 +855,13 @@ def __init__(self, X, category=None): EXAMPLES:: - sage: S = Set(GF(19)); S + sage: S = Set(GF(19)); S # optional - sage.libs.pari {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} - sage: S.category() + sage: S.category() # optional - sage.libs.pari Category of finite enumerated sets - sage: print(latex(S)) + sage: print(latex(S)) # optional - sage.libs.pari \left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\} - sage: TestSuite(S).run() + sage: TestSuite(S).run() # optional - sage.libs.pari """ Set_object.__init__(self, X, category=FiniteEnumeratedSets().or_subcategory(category)) @@ -884,7 +886,7 @@ def is_finite(self): EXAMPLES:: - sage: Set(GF(19)).is_finite() + sage: Set(GF(19)).is_finite() # optional - sage.libs.pari True """ return True @@ -916,15 +918,15 @@ def __iter__(self): EXAMPLES:: - sage: S = Set(GF(19)) - sage: I = iter(S) - sage: next(I) + sage: S = Set(GF(19)) # optional - sage.libs.pari + sage: I = iter(S) # optional - sage.libs.pari + sage: next(I) # optional - sage.libs.pari 0 - sage: next(I) + sage: next(I) # optional - sage.libs.pari 1 - sage: next(I) + sage: next(I) # optional - sage.libs.pari 2 - sage: next(I) + sage: next(I) # optional - sage.libs.pari 3 """ return iter(self.set()) @@ -935,8 +937,8 @@ def _latex_(self): EXAMPLES:: - sage: S = Set(GF(2)) - sage: latex(S) + sage: S = Set(GF(2)) # optional - sage.libs.pari + sage: latex(S) # optional - sage.libs.pari \left\{0, 1\right\} """ return '\\left\\{' + ', '.join(latex(x) for x in self.set()) + '\\right\\}' @@ -947,8 +949,8 @@ def _repr_(self): EXAMPLES:: - sage: S = Set(GF(2)) - sage: S + sage: S = Set(GF(2)) # optional - sage.libs.pari + sage: S # optional - sage.libs.pari {0, 1} TESTS:: @@ -967,12 +969,12 @@ def list(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: X + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: X.list() + sage: X.list() # optional - sage.libs.pari [0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1] - sage: type(X.list()) + sage: type(X.list()) # optional - sage.libs.pari <... 'list'> .. TODO:: @@ -995,14 +997,14 @@ def set(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: X + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: X.set() + sage: X.set() # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: type(X.set()) + sage: type(X.set()) # optional - sage.libs.pari <... 'set'> - sage: type(X) + sage: type(X) # optional - sage.libs.pari """ return set(self.object()) @@ -1014,22 +1016,22 @@ def frozenset(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: X + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: s = X.set(); s + sage: s = X.set(); s # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: hash(s) + sage: hash(s) # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: unhashable type: 'set' - sage: s = X.frozenset(); s + sage: s = X.frozenset(); s # optional - sage.libs.pari frozenset({0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1}) - sage: hash(s) != hash(tuple(X.set())) + sage: hash(s) != hash(tuple(X.set())) # optional - sage.libs.pari True - sage: type(s) + sage: type(s) # optional - sage.libs.pari <... 'frozenset'> """ return frozenset(self.object()) @@ -1040,8 +1042,8 @@ def __hash__(self): EXAMPLES:: - sage: s = Set(GF(8,'c')) - sage: hash(s) == hash(s) + sage: s = Set(GF(8,'c')) # optional - sage.libs.pari + sage: hash(s) == hash(s) # optional - sage.libs.pari True """ return hash(self.frozenset()) @@ -1052,10 +1054,10 @@ def __richcmp__(self, other, op): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: X == Set(GF(8,'c')) + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: X == Set(GF(8,'c')) # optional - sage.libs.pari True - sage: X == Set(GF(4,'a')) + sage: X == Set(GF(4,'a')) # optional - sage.libs.pari False sage: Set(QQ) == Set(ZZ) False @@ -1142,13 +1144,13 @@ def union(self, other): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: Y = Set([GF(8,'c').0, 1, 2, 3]) - sage: X + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: sorted(Y) + sage: sorted(Y) # optional - sage.libs.pari [1, 2, 3, c] - sage: sorted(X.union(Y), key=str) + sage: sorted(X.union(Y), key=str) # optional - sage.libs.pari [0, 1, 2, 3, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1] """ if not isinstance(other, Set_object_enumerated): @@ -1161,9 +1163,9 @@ def intersection(self, other): EXAMPLES:: - sage: X = Set(GF(8,'c')) - sage: Y = Set([GF(8,'c').0, 1, 2, 3]) - sage: X.intersection(Y) + sage: X = Set(GF(8,'c')) # optional - sage.libs.pari + sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # optional - sage.libs.pari + sage: X.intersection(Y) # optional - sage.libs.pari {1, c} """ if not isinstance(other, Set_object_enumerated): @@ -1319,7 +1321,7 @@ def _repr_(self): EXAMPLES:: - sage: Set(ZZ).union(Set(GF(5))) + sage: Set(ZZ).union(Set(GF(5))) # optional - sage.libs.pari Set-theoretic union of Set of elements of Integer Ring and {0, 1, 2, 3, 4} """ return "Set-theoretic {} of {} and {}".format(self._op, self._X, self._Y) @@ -1330,7 +1332,7 @@ def _latex_(self): EXAMPLES:: - sage: latex(Set(ZZ).union(Set(GF(5)))) + sage: latex(Set(ZZ).union(Set(GF(5)))) # optional - sage.libs.pari \Bold{Z} \cup \left\{0, 1, 2, 3, 4\right\} """ return latex(self._X) + self._latex_op + latex(self._Y) @@ -1344,9 +1346,9 @@ def __hash__(self): The hash values of equal sets are in general not equal since it is not decidable whether two sets are equal:: - sage: X = Set(GF(13)).intersection(Set(ZZ)) - sage: Y = Set(ZZ).intersection(Set(GF(13))) - sage: hash(X) == hash(Y) + sage: X = Set(GF(13)).intersection(Set(ZZ)) # optional - sage.libs.pari + sage: Y = Set(ZZ).intersection(Set(GF(13))) # optional - sage.libs.pari + sage: hash(X) == hash(Y) # optional - sage.libs.pari False TESTS: @@ -1452,7 +1454,7 @@ def __iter__(self): EXAMPLES:: - sage: [x for x in Set(GF(3)).union(Set(GF(2)))] + sage: [x for x in Set(GF(3)).union(Set(GF(2)))] # optional - sage.libs.pari [0, 1, 2, 0, 1] """ for x in self._X: @@ -1466,14 +1468,14 @@ def __contains__(self, x): EXAMPLES:: - sage: X = Set(GF(3)).union(Set(GF(2))) - sage: GF(5)(1) in X + sage: X = Set(GF(3)).union(Set(GF(2))) # optional - sage.libs.pari + sage: GF(5)(1) in X # optional - sage.libs.pari False - sage: GF(3)(2) in X + sage: GF(3)(2) in X # optional - sage.libs.pari True - sage: GF(2)(0) in X + sage: GF(2)(0) in X # optional - sage.libs.pari True - sage: GF(5)(0) in X + sage: GF(5)(0) in X # optional - sage.libs.pari False """ return x in self._X or x in self._Y @@ -1484,14 +1486,14 @@ def cardinality(self): EXAMPLES:: - sage: X = Set(GF(3)).union(Set(GF(2))) - sage: X + sage: X = Set(GF(3)).union(Set(GF(2))) # optional - sage.libs.pari + sage: X # optional - sage.libs.pari {0, 1, 2, 0, 1} - sage: X.cardinality() + sage: X.cardinality() # optional - sage.libs.pari 5 - sage: X = Set(GF(3)).union(Set(ZZ)) - sage: X.cardinality() + sage: X = Set(GF(3)).union(Set(ZZ)) # optional - sage.libs.pari + sage: X.cardinality() # optional - sage.libs.pari +Infinity """ return self._X.cardinality() + self._Y.cardinality() From 6c4478ad0d45a6b0cbf814cc3798ac60cb1984ed Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Feb 2023 08:50:53 -0800 Subject: [PATCH 064/225] src/sage/sets/set.py: Fix # optional --- src/sage/sets/set.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index dab3cf749f7..1015cdf3b3e 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -101,14 +101,16 @@ def Set(X=None, category=None): EXAMPLES:: sage: X = Set(GF(9, 'a')) # optional - sage.libs.pari - sage: X + sage: X # optional - sage.libs.pari {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} - sage: type(X) + sage: type(X) # optional - sage.libs.pari - sage: Y = X.union(Set(QQ)) - sage: Y - Set-theoretic union of {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} and Set of elements of Rational Field - sage: type(Y) + sage: Y = X.union(Set(QQ)) # optional - sage.libs.pari + sage: Y # optional - sage.libs.pari + Set-theoretic union of + {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} and + Set of elements of Rational Field + sage: type(Y) # optional - sage.libs.pari Usually sets can be used as dictionary keys. From 37cac272ad7d33f913dbd475786176cc8f9e1c55 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 23 Feb 2023 22:11:36 -0800 Subject: [PATCH 065/225] sage.sets: Add more # optional --- src/sage/sets/non_negative_integers.py | 8 ++++---- src/sage/sets/set.py | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index c7b3fd27a2d..8e013eec8ad 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -102,15 +102,15 @@ def __contains__(self, elt): True sage: -1 in NN False - sage: x in NN + sage: x in NN # optional - sage.symbolic False sage: None in NN False - sage: QQbar(sqrt(2)) in NN + sage: QQbar(sqrt(2)) in NN # optional - sage.symbolic, sage.rings.number_field False sage: RIF(1,2) in NN False - sage: QQbar(2) in NN + sage: QQbar(2) in NN # optional - sage.rings.number_field True sage: RIF(2) in NN True @@ -135,7 +135,7 @@ def _element_constructor_(self, i): Traceback (most recent call last): ... ValueError: Value -5 in not in Non negative integers. - sage: NN._element_constructor_(x) + sage: NN._element_constructor_(x) # optional - sage.symbolic Traceback (most recent call last): ... ValueError: Value x in not in Non negative integers. diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 1015cdf3b3e..d21ef863293 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -329,7 +329,7 @@ def _test_as_set_object(self, tester=None, **options): Instances of other subclasses of :class:`Set_base` run this method:: - sage: Polyhedron()._test_as_set_object(verbose=True) + sage: Polyhedron()._test_as_set_object(verbose=True) # optional - sage.geometry.polyhedron Running the test suite of Set(self) running ._test_an_element() . . . pass ... @@ -715,7 +715,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(SymmetricGroup(2).list()).is_empty() + sage: Set(SymmetricGroup(2).list()).is_empty() # optional - sage.groups False sage: Set(ZZ).is_empty() False @@ -728,7 +728,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(DihedralGroup(4).list()).is_empty() + sage: Set(DihedralGroup(4).list()).is_empty() # optional - sage.groups False sage: Set(QQ).is_empty() False @@ -800,10 +800,10 @@ def subsets_lattice(self): EXAMPLES:: sage: X = Set([1,2,3]) - sage: X.subsets_lattice() + sage: X.subsets_lattice() # optional - sage.combinat Finite lattice containing 8 elements sage: Y = Set() - sage: Y.subsets_lattice() + sage: Y.subsets_lattice() # optional - sage.combinat Finite lattice containing 1 elements """ @@ -1105,7 +1105,7 @@ def issubset(self, other): TESTS:: - sage: len([Z for Z in Y.subsets() if Z.issubset(X)]) + sage: len([Z for Z in Y.subsets() if Z.issubset(X)]) # optional - sage.combinat 8 """ if not isinstance(other, Set_object_enumerated): @@ -1133,7 +1133,7 @@ def issuperset(self, other): TESTS:: - sage: len([Z for Z in Y.subsets() if Z.issuperset(X)]) + sage: len([Z for Z in Y.subsets() if Z.issuperset(X)]) # optional - sage.combinat 4 """ if not isinstance(other, Set_object_enumerated): From a2b8381d4ab795f2fa4b3925adf3b4ce76a6dc3d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 3 Mar 2023 15:40:01 -0800 Subject: [PATCH 066/225] sage.sets: More # optional --- src/sage/sets/image_set.py | 52 +++++++++++++++++++------------------- src/sage/sets/set.py | 44 +++++++++++++++++--------------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/sage/sets/image_set.py b/src/sage/sets/image_set.py index 54b78eede7a..74a99c65641 100644 --- a/src/sage/sets/image_set.py +++ b/src/sage/sets/image_set.py @@ -73,12 +73,12 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None, inve EXAMPLES:: - sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) + sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) # optional - sage.modules sage: R. = QQ[] - sage: H = Hom(M, R, category=Sets()) - sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) - sage: Im = f.image() - sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', + sage: H = Hom(M, R, category=Sets()) # optional - sage.modules + sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) # optional - sage.modules + sage: Im = f.image() # optional - sage.modules + sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', # optional - sage.modules ....: '_test_some_elements', '_test_elements']) """ if not is_Parent(domain_subset): @@ -173,12 +173,12 @@ def ambient(self): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) - sage: R. = ZZ[] - sage: H = Hom(M, R, category=Sets()) - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) - sage: Im = f.image() - sage: Im.ambient() is R + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules + sage: R. = ZZ[] # optional - sage.modules + sage: H = Hom(M, R, category=Sets()) # optional - sage.modules + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules + sage: Im = f.image() # optional - sage.modules + sage: Im.ambient() is R # optional - sage.modules True sage: P = Partitions(3).map(attrcall('conjugate')) @@ -197,14 +197,14 @@ def lift(self, x): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules sage: R. = ZZ[] - sage: H = Hom(M, R, category=Sets()) - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) - sage: Im = f.image() - sage: p = Im.lift(Im.an_element()); p + sage: H = Hom(M, R, category=Sets()) # optional - sage.modules + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules + sage: Im = f.image() # optional - sage.modules + sage: p = Im.lift(Im.an_element()); p # optional - sage.modules 2*x - 4 - sage: p.parent() is R + sage: p.parent() is R # optional - sage.modules True """ return x @@ -219,13 +219,13 @@ def retract(self, x): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) - sage: R. = ZZ[] - sage: H = Hom(M, R, category=Sets()) - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) - sage: Im = f.image() - sage: p = 2 * x - 4 - sage: Im.retract(p).parent() + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules + sage: R. = ZZ[] # optional - sage.modules + sage: H = Hom(M, R, category=Sets()) # optional - sage.modules + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules + sage: Im = f.image() # optional - sage.modules + sage: p = 2 * x - 4 # optional - sage.modules + sage: Im.retract(p).parent() # optional - sage.modules Multivariate Polynomial Ring in x, y over Integer Ring """ return x @@ -251,8 +251,8 @@ def cardinality(self) -> Integer: :meth:`~sage.categories.enumerated_sets.EnumeratedSets.ParentMethods.map` defaults to ``is_injective=True``): - sage: R = Permutations(10).map(attrcall('reduced_word')) - sage: R.cardinality() + sage: R = Permutations(10).map(attrcall('reduced_word')) # optional - sage.combinat + sage: R.cardinality() # optional - sage.combinat 3628800 sage: Evens = ZZ.map(lambda x: 2 * x) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index d21ef863293..69a81546bb4 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -411,7 +411,7 @@ def __add__(self, X): EXAMPLES:: - sage: Set(RealField()) + Set(QQ^5) + sage: Set(RealField()) + Set(QQ^5) # optional - sage.modules Set-theoretic union of Set of elements of Real Field with 53 bits of precision and Set of elements of Vector space of dimension 5 over Rational Field @@ -785,9 +785,9 @@ def subsets(self, size=None): EXAMPLES:: sage: X = Set([1, 2, 3]) - sage: list(X.subsets()) + sage: list(X.subsets()) # optional - sage.combinat [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}] - sage: list(X.subsets(2)) + sage: list(X.subsets(2)) # optional - sage.combinat [{1, 2}, {1, 3}, {2, 3}] """ from sage.combinat.subset import Subsets @@ -1268,10 +1268,10 @@ class Set_object_binary(Set_object, metaclass=ClasscallMetaclass): EXAMPLES:: - sage: X = Set(QQ^2) + sage: X = Set(QQ^2) # optional - sage.modules sage: Y = Set(ZZ) sage: from sage.sets.set import Set_object_binary - sage: S = Set_object_binary(X, Y, "union", "\\cup"); S + sage: S = Set_object_binary(X, Y, "union", "\\cup"); S # optional - sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1285,9 +1285,9 @@ def __classcall__(cls, X, Y, *args, **kwds): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = QQ^2 + sage: X = QQ^2 # optional - sage.modules sage: Y = ZZ - sage: Set_object_binary(X, Y, "union", "\\cup") + sage: Set_object_binary(X, Y, "union", "\\cup") # optional - sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1305,10 +1305,10 @@ def __init__(self, X, Y, op, latex_op, category=None): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = Set(QQ^2) + sage: X = Set(QQ^2) # optional - sage.modules sage: Y = Set(ZZ) - sage: S = Set_object_binary(X, Y, "union", "\\cup") - sage: type(S) + sage: S = Set_object_binary(X, Y, "union", "\\cup") # optional - sage.modules + sage: type(S) # optional - sage.modules """ self._X = X @@ -1375,17 +1375,17 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) + sage: S = Set(QQ^2) # optional - sage.modules sage: T = Set(ZZ) - sage: X = S.union(T); X + sage: X = S.union(T); X # optional - sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() + sage: X.category() # optional - sage.modules Category of infinite sets - sage: latex(X) + sage: latex(X) # optional - sage.modules \Bold{Q}^{2} \cup \Bold{Z} - sage: TestSuite(X).run() + sage: TestSuite(X).run() # optional - sage.modules """ if category is None: category = Sets() @@ -1528,13 +1528,15 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) - sage: T = Set(ZZ) - sage: X = S.intersection(T); X - Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() + sage: S = Set(QQ^2) # optional - sage.modules + sage: T = Set(ZZ) # optional - sage.modules + sage: X = S.intersection(T); X # optional - sage.modules + Set-theoretic intersection of + Set of elements of Vector space of dimension 2 over Rational Field and + Set of elements of Integer Ring + sage: X.category() # optional - sage.modules Category of enumerated sets - sage: latex(X) + sage: latex(X) # optional - sage.modules \Bold{Q}^{2} \cap \Bold{Z} sage: X = Set(IntegerRange(100)).intersection(Primes()) From dcc4c1cab1efeafb2236f6dc240c6f85d7c4e0c9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 4 Mar 2023 01:14:56 -0800 Subject: [PATCH 067/225] sage.sets: More # optional --- src/sage/sets/set.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 69a81546bb4..ccdbef457ad 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -1426,11 +1426,11 @@ def __richcmp__(self, right, op): EXAMPLES:: - sage: Y = Set(ZZ^2).union(Set(ZZ^3)) - sage: X = Set(ZZ^3).union(Set(ZZ^2)) - sage: X == Y + sage: Y = Set(ZZ^2).union(Set(ZZ^3)) # optional - sage.modules + sage: X = Set(ZZ^3).union(Set(ZZ^2)) # optional - sage.modules + sage: X == Y # optional - sage.modules True - sage: Y == X + sage: Y == X # optional - sage.modules True This illustrates that equality testing for formal unions From 62ab33aa726f1532792ca77f7156fadece73768b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 5 Mar 2023 21:38:40 -0800 Subject: [PATCH 068/225] Add # optional - numpy etc. --- src/sage/sets/non_negative_integers.py | 2 +- src/sage/sets/positive_integers.py | 2 +- src/sage/sets/real_set.py | 14 +++++++------- src/sage/sets/set.py | 20 ++++++++++---------- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 8e013eec8ad..0f632c0cd88 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -231,7 +231,7 @@ def _sympy_(self): EXAMPLES:: sage: NN = NonNegativeIntegers() - sage: NN._sympy_() + sage: NN._sympy_() # optional - sympy Naturals0 """ from sympy import Naturals0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index aae3c5a031f..26bf71a9cae 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -83,7 +83,7 @@ def _sympy_(self): EXAMPLES:: - sage: PositiveIntegers()._sympy_() + sage: PositiveIntegers()._sympy_() # optional - sympy Naturals """ from sympy import Naturals diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index 47a0505de6b..b4e1d5ca266 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -2806,21 +2806,21 @@ def _sympy_(self): EXAMPLES:: - sage: RealSet()._sympy_() + sage: RealSet()._sympy_() # optional - sympy EmptySet - sage: RealSet.point(5)._sympy_() # random - this output format is sympy >= 1.9 + sage: RealSet.point(5)._sympy_() # random - this output format is sympy >= 1.9 # optional - sympy {5} - sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random + sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random # optional - sympy {1, 2} - sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_() + sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_() # optional - sympy Union(Interval.open(1, 2), Interval(3, 4)) - sage: RealSet(-oo, oo)._sympy_() + sage: RealSet(-oo, oo)._sympy_() # optional - sympy Reals Infinities are not elements:: - sage: import sympy - sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) + sage: import sympy # optional - sympy + sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) # optional - sympy False """ from sympy import Reals, Union diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index ccdbef457ad..875ab3765f7 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -839,7 +839,7 @@ def _sympy_(self): sage: X = Set(ZZ); X Set of elements of Integer Ring - sage: X._sympy_() + sage: X._sympy_() # optional - sympy Integers """ from sage.interfaces.sympy import sympy_init @@ -1231,16 +1231,16 @@ def _sympy_(self): sage: X = Set({1, 2, 3}); X {1, 2, 3} - sage: sX = X._sympy_(); sX + sage: sX = X._sympy_(); sX # optional - sympy Set(1, 2, 3) - sage: sX.is_empty is None + sage: sX.is_empty is None # optional - sympy True sage: Empty = Set([]); Empty {} - sage: sEmpty = Empty._sympy_(); sEmpty + sage: sEmpty = Empty._sympy_(); sEmpty # optional - sympy EmptySet - sage: sEmpty.is_empty + sage: sEmpty.is_empty # optional - sympy True """ from sympy import Set, EmptySet @@ -1509,7 +1509,7 @@ def _sympy_(self): sage: X = Set(ZZ).union(Set([1/2])); X Set-theoretic union of Set of elements of Integer Ring and {1/2} - sage: X._sympy_() + sage: X._sympy_() # optional - sympy Union(Integers, Set(1/2)) """ from sympy import Union @@ -1690,7 +1690,7 @@ def _sympy_(self): Set-theoretic intersection of Set of elements of Integer Ring and Set of elements of [3/2, 11/2] - sage: X._sympy_() + sage: X._sympy_() # optional - sympy Range(2, 6, 1) """ from sympy import Intersection @@ -1859,7 +1859,7 @@ def _sympy_(self): Set of elements of Integer Ring sage: X.category() Category of sets - sage: X._sympy_() + sage: X._sympy_() # optional - sympy Complement(Rationals, Integers) sage: X = Set(ZZ).difference(Set(QQ)); X @@ -1868,7 +1868,7 @@ def _sympy_(self): Set of elements of Rational Field sage: X.category() Category of enumerated sets - sage: X._sympy_() + sage: X._sympy_() # optional - sympy EmptySet """ from sympy import Complement @@ -2035,7 +2035,7 @@ def _sympy_(self): Set-theoretic symmetric difference of Set of elements of Integer Ring and {0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3} - sage: X._sympy_() + sage: X._sympy_() # optional - sympy Union(Complement(Integers, Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3)), Complement(Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3), Integers)) """ From 4500966434c647580ddadb4c14d304018f5872ee Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 7 Mar 2023 19:13:14 -0800 Subject: [PATCH 069/225] sage.sets: More # optional --- src/sage/sets/primes.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/sets/primes.py b/src/sage/sets/primes.py index df64c2efbbf..b95ed278e45 100644 --- a/src/sage/sets/primes.py +++ b/src/sage/sets/primes.py @@ -66,18 +66,18 @@ def __init__(self, proof): sage: P = Primes(); P Set of all prime numbers: 2, 3, 5, 7, ... - sage: Q = Primes(proof = False); Q + sage: Q = Primes(proof=False); Q Set of all prime numbers: 2, 3, 5, 7, ... TESTS:: sage: P.category() Category of facade infinite enumerated sets - sage: TestSuite(P).run() + sage: TestSuite(P).run() # optional - sage.libs.pari sage: Q.category() Category of facade infinite enumerated sets - sage: TestSuite(Q).run() + sage: TestSuite(Q).run() # optional - sage.libs.pari The set of primes can be compared to various things, but is only equal to itself:: @@ -123,7 +123,7 @@ def __contains__(self, x): False sage: 1.5 in P False - sage: e in P + sage: e in P # optional - sage.symbolic False """ try: @@ -164,7 +164,7 @@ def next(self, pr): EXAMPLES:: sage: P = Primes() - sage: P.next(5) + sage: P.next(5) # optional - sage.libs.pari 7 """ pr = pr.next_prime(self.__proof) @@ -177,11 +177,11 @@ def unrank(self, n): EXAMPLES:: sage: P = Primes() - sage: P.unrank(0) + sage: P.unrank(0) # optional - sage.libs.pari 2 - sage: P.unrank(5) + sage: P.unrank(5) # optional - sage.libs.pari 13 - sage: P.unrank(42) + sage: P.unrank(42) # optional - sage.libs.pari 191 """ return nth_prime(n + 1) From 76ddcc09afb8fae53920bc5bf247cd820b97b5a3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Mar 2023 00:08:19 -0800 Subject: [PATCH 070/225] sage.sets: More # optional --- src/sage/sets/condition_set.py | 22 +-- .../sets/disjoint_union_enumerated_sets.py | 186 +++++++++--------- 2 files changed, 108 insertions(+), 100 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 92f17647315..b4d6f8e84ec 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -104,24 +104,24 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope Using ``ConditionSet`` without predicates provides a way of attaching variable names to a set:: - sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 + sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 # optional - sage.modules { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring } - sage: Z3.variable_names() + sage: Z3.variable_names() # optional - sage.modules ('x', 'y', 'z') - sage: Z3.arguments() + sage: Z3.arguments() # optional - sage.modules (x, y, z) - sage: Q4. = ConditionSet(QQ^4); Q4 + sage: Q4. = ConditionSet(QQ^4); Q4 # optional - sage.modules { (a, b, c, d) ∈ Vector space of dimension 4 over Rational Field } - sage: Q4.variable_names() + sage: Q4.variable_names() # optional - sage.modules ('a', 'b', 'c', 'd') - sage: Q4.arguments() + sage: Q4.arguments() # optional - sage.modules (a, b, c, d) TESTS:: - sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas - sage: TestSuite(P_inter_B_again).run() + sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # optional - sage.geometry.polyhedron + sage: TestSuite(P_inter_B_again).run() # optional - sage.geometry.polyhedron, sage.symbolic """ @staticmethod def __classcall_private__(cls, universe, *predicates, vars=None, names=None, category=None): @@ -345,9 +345,9 @@ def _call_predicate(self, predicate, element): sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: predicate = SmallTriples._predicates[0] - sage: element = TripleDigits((1, 2, 3)) - sage: SmallTriples._call_predicate(predicate, element) + sage: predicate = SmallTriples._predicates[0] # optional - sage.symbolic + sage: element = TripleDigits((1, 2, 3)) # optional - sage.symbolic + sage: SmallTriples._call_predicate(predicate, element) # optional - sage.symbolic sqrt(14) < 12 sage: var('t') diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 3dea567a779..6b21beda837 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -90,30 +90,32 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): In general the input can be any family:: - sage: U3 = DisjointUnionEnumeratedSets( + sage: U3 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([2,3,4], Permutations, lazy=True)) - sage: U3 - Disjoint union of Lazy family ((i))_{i in [2, 3, 4]} - sage: U3.cardinality() + sage: U3 # optional - sage.combinat + Disjoint union of Lazy family + ((i))_{i in [2, 3, 4]} + sage: U3.cardinality() # optional - sage.combinat 32 - sage: it = iter(U3) - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] + sage: it = iter(U3) # optional - sage.combinat + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat [[1, 2], [2, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1]] - sage: U3.unrank(18) + sage: U3.unrank(18) # optional - sage.combinat [2, 4, 1, 3] This allows for infinite unions:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Permutations)) - sage: U4 - Disjoint union of Lazy family ((i))_{i in Non negative integers} - sage: U4.cardinality() + sage: U4 # optional - sage.combinat + Disjoint union of Lazy family + ((i))_{i in Non negative integers} + sage: U4.cardinality() # optional - sage.combinat +Infinity - sage: it = iter(U4) - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] + sage: it = iter(U4) # optional - sage.combinat + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: U4.unrank(18) + sage: U4.unrank(18) # optional - sage.combinat [2, 3, 1, 4] .. WARNING:: @@ -126,41 +128,41 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): We demonstrate the ``keepkey`` option:: - sage: Ukeep = DisjointUnionEnumeratedSets( + sage: Ukeep = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(list(range(4)), Permutations), keepkey=True) - sage: it = iter(Ukeep) - sage: [next(it) for i in range(6)] + sage: it = iter(Ukeep) # optional - sage.combinat + sage: [next(it) for i in range(6)] # optional - sage.combinat [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: type(next(it)[1]) + sage: type(next(it)[1]) # optional - sage.combinat We now demonstrate the ``facade`` option:: - sage: UNoFacade = DisjointUnionEnumeratedSets( + sage: UNoFacade = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(list(range(4)), Permutations), facade=False) - sage: it = iter(UNoFacade) - sage: [next(it) for i in range(6)] + sage: it = iter(UNoFacade) # optional - sage.combinat + sage: [next(it) for i in range(6)] # optional - sage.combinat [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: el = next(it); el + sage: el = next(it); el # optional - sage.combinat [2, 1, 3] - sage: type(el) + sage: type(el) # optional - sage.combinat <... 'sage.structure.element_wrapper.ElementWrapper'> - sage: el.parent() == UNoFacade + sage: el.parent() == UNoFacade # optional - sage.combinat True - sage: elv = el.value; elv + sage: elv = el.value; elv # optional - sage.combinat [2, 1, 3] - sage: type(elv) + sage: type(elv) # optional - sage.combinat The elements ``el`` of the disjoint union are simple wrapped elements. So to access the methods, you need to do ``el.value``:: - sage: el[0] + sage: el[0] # optional - sage.combinat Traceback (most recent call last): ... TypeError: 'sage.structure.element_wrapper.ElementWrapper' object is not subscriptable - sage: el.value[0] + sage: el.value[0] # optional - sage.combinat 2 Possible extensions: the current enumeration order is not suitable @@ -182,12 +184,12 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): :class:`DisjointUnionEnumeratedSets`. Then, one simply writes the ``__init__`` method as usual:: - sage: class MyUnion(DisjointUnionEnumeratedSets): + sage: class MyUnion(DisjointUnionEnumeratedSets): # optional - sage.combinat ....: def __init__(self): ....: DisjointUnionEnumeratedSets.__init__(self, ....: Family([1,2], Permutations)) - sage: pp = MyUnion() - sage: pp.list() + sage: pp = MyUnion() # optional - sage.combinat + sage: pp.list() # optional - sage.combinat [[1], [1, 2], [2, 1]] In case the :meth:`__init__` method takes optional arguments, @@ -202,19 +204,21 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: class UnionOfSpecialSets(DisjointUnionEnumeratedSets): ....: __classcall_private__ = staticmethod(DisjointUnionEnumeratedSets.__classcall_private__) - sage: psp = UnionOfSpecialSets(Family([1,2], Permutations)) - sage: psp.list() + sage: psp = UnionOfSpecialSets(Family([1,2], Permutations)) # optional - sage.combinat + sage: psp.list() # optional - sage.combinat [[1], [1, 2], [2, 1]] TESTS:: sage: TestSuite(U1).run() sage: TestSuite(U2).run() - sage: TestSuite(U3).run() - sage: TestSuite(U4).run() - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + sage: TestSuite(U3).run() # optional - sage.combinat + sage: TestSuite(U4).run() # optional - sage.combinat + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. - sage: TestSuite(UNoFacade).run() + sage: TestSuite(UNoFacade).run() # optional - sage.combinat We skip ``_test_an_element`` because the coercion framework does not currently allow a tuple to be returned for facade parents:: @@ -226,11 +230,11 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): been defined interactively:: sage: import __main__ - sage: __main__.MyUnion = MyUnion + sage: __main__.MyUnion = MyUnion # optional - sage.combinat sage: __main__.UnionOfSpecialSets = UnionOfSpecialSets - sage: TestSuite(pp).run() - sage: TestSuite(psp).run() + sage: TestSuite(pp).run() # optional - sage.combinat + sage: TestSuite(psp).run() # optional - sage.combinat """ @@ -323,10 +327,12 @@ def _is_a(self, x): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Compositions)) - sage: U4._is_a(Composition([3,2,1,1])) - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + sage: U4._is_a(Composition([3,2,1,1])) # optional - sage.combinat + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. True """ @@ -352,17 +358,19 @@ def __contains__(self, x): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Partitions)) - sage: Partition([]) in U4 - doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union + sage: Partition([]) in U4 # optional - sage.combinat + doctest:...: UserWarning: Disjoint union of Lazy family + ((i))_{i in Non negative integers} + is an infinite union The default implementation of __contains__ can loop forever. Please overload it. True Note: one has to use a different family from the previous one in this file otherwise the warning is not re-issued:: - sage: Partition([3,2,1,1]) in U4 + sage: Partition([3,2,1,1]) in U4 # optional - sage.combinat True The following call will loop forever:: @@ -381,21 +389,21 @@ def __iter__(self): """ TESTS:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Permutations)) - sage: it = iter(U4) - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] + sage: it = iter(U4) # optional - sage.combinat + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Permutations), ....: keepkey=True, facade=False) - sage: it = iter(U4) - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] + sage: it = iter(U4) # optional - sage.combinat + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: el = next(it); el.parent() == U4 + sage: el = next(it); el.parent() == U4 # optional - sage.combinat True - sage: el.value == (3, Permutation([2,1,3])) + sage: el.value == (3, Permutation([2,1,3])) # optional - sage.combinat True """ for k in self._family.keys(): @@ -414,7 +422,7 @@ def an_element(self): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( + sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([3, 5, 7], Permutations)) sage: U4.an_element() [1, 2, 3] @@ -431,16 +439,16 @@ def cardinality(self): For finite disjoint unions, the cardinality is computed by summing the cardinalities of the enumerated sets:: - sage: U = DisjointUnionEnumeratedSets(Family([0,1,2,3], Permutations)) - sage: U.cardinality() + sage: U = DisjointUnionEnumeratedSets(Family([0,1,2,3], Permutations)) # optional - sage.combinat + sage: U.cardinality() # optional - sage.combinat 10 For infinite disjoint unions, this makes the assumption that the result is infinite:: - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family(NonNegativeIntegers(), Permutations)) - sage: U.cardinality() + sage: U.cardinality() # optional - sage.combinat +Infinity .. WARNING:: @@ -463,14 +471,14 @@ def _element_constructor_(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), facade=False) - sage: U._element_constructor_ + sage: U._element_constructor_ # optional - sage.combinat - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), facade=True) - sage: U._element_constructor_ + sage: U._element_constructor_ # optional - sage.combinat """ @@ -483,13 +491,13 @@ def _element_constructor_default(self, el): r""" TESTS:: - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), facade=False) - sage: U([1]) # indirect doctest + sage: U([1]) # indirect doctest # optional - sage.combinat [1] - sage: U([2,1]) # indirect doctest + sage: U([2,1]) # indirect doctest # optional - sage.combinat [2, 1] - sage: U([1,3,2]) # indirect doctest + sage: U([1,3,2]) # indirect doctest # optional - sage.combinat Traceback (most recent call last): ... ValueError: value [1, 3, 2] does not belong to Disjoint union of @@ -497,13 +505,13 @@ def _element_constructor_default(self, el): 2: Partitions of the integer 2, 3: Partitions of the integer 3} - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), keepkey=True, facade=False) - sage: U((1, [1])) # indirect doctest + sage: U((1, [1])) # indirect doctest # optional - sage.combinat (1, [1]) - sage: U((3,[2,1])) # indirect doctest + sage: U((3,[2,1])) # indirect doctest # optional - sage.combinat (3, [2, 1]) - sage: U((4,[2,1])) # indirect doctest + sage: U((4,[2,1])) # indirect doctest # optional - sage.combinat Traceback (most recent call last): ... ValueError: value (4, [2, 1]) does not belong to Disjoint union of @@ -522,12 +530,12 @@ def _element_constructor_facade(self, el): """ TESTS:: - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) - sage: X([1]).parent() + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat + sage: X([1]).parent() # optional - sage.combinat Partitions of the integer 1 - sage: X([2,1,1]).parent() # indirect doctest + sage: X([2,1,1]).parent() # indirect doctest # optional - sage.combinat Partitions of the integer 4 - sage: X([6]) + sage: X([6]) # optional - sage.combinat Traceback (most recent call last): ... ValueError: cannot coerce `[6]` in any parent in `Finite family {...}` @@ -536,23 +544,23 @@ def _element_constructor_facade(self, el): because this returns a `tuple`, where the coercion framework requires an :class:`Element` be returned. - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}, + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}, # optional - sage.combinat ....: keepkey=True) - sage: p = X._element_constructor_((0, [])) # indirect doctest - sage: p[1].parent() + sage: p = X._element_constructor_((0, [])) # indirect doctest # optional - sage.combinat + sage: p[1].parent() # optional - sage.combinat Partitions of the integer 0 Test that facade parents can create and properly access elements that are tuples (fixed by :trac:`22382`):: - sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), + sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), # optional - sage.combinat ....: mu.standard_tableaux()]) - sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) - sage: s = StandardTableau([[1,3],[2,4]]) - sage: (s,s) in tabs + sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) # optional - sage.combinat + sage: s = StandardTableau([[1,3],[2,4]]) # optional - sage.combinat + sage: (s,s) in tabs # optional - sage.combinat True - sage: ss = tabs( (s,s) ) - sage: ss[0] + sage: ss = tabs( (s,s) ) # optional - sage.combinat + sage: ss[0] # optional - sage.combinat [[1, 3], [2, 4]] We do not coerce when one of the elements is already in the set:: @@ -588,13 +596,13 @@ def Element(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), facade=False) - sage: U.Element + sage: U.Element # optional - sage.combinat <... 'sage.structure.element_wrapper.ElementWrapper'> - sage: U = DisjointUnionEnumeratedSets( + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([1,2,3], Partitions), facade=True) - sage: U.Element + sage: U.Element # optional - sage.combinat Traceback (most recent call last): ... AttributeError: 'DisjointUnionEnumeratedSets_with_category' object has no attribute 'Element' From 4c8c2adfbb003bb4e21ed8eaedc060db48c58033 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Mar 2023 01:08:07 -0800 Subject: [PATCH 071/225] More # optional --- src/sage/sets/disjoint_union_enumerated_sets.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 6b21beda837..5ad8546c99b 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -223,7 +223,7 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): We skip ``_test_an_element`` because the coercion framework does not currently allow a tuple to be returned for facade parents:: - sage: TestSuite(Ukeep).run(skip="_test_an_element") + sage: TestSuite(Ukeep).run(skip="_test_an_element") # optional - sage.combinat The following three lines are required for the pickling tests, because the classes ``MyUnion`` and ``UnionOfSpecialSets`` have @@ -277,8 +277,8 @@ def __init__(self, family, facade=True, keepkey=False, category=None): ....: 2: FiniteEnumeratedSet([4,5,6])}) sage: TestSuite(U).run() - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) - sage: TestSuite(X).run() + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat + sage: TestSuite(X).run() # optional - sage.combinat """ self._family = family self._facade = facade @@ -424,7 +424,7 @@ def an_element(self): sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat ....: Family([3, 5, 7], Permutations)) - sage: U4.an_element() + sage: U4.an_element() # optional - sage.combinat [1, 2, 3] """ return self._an_element_from_iterator() From 0e0387d656d136d85b58269759322161dd46ff88 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 8 Mar 2023 10:25:42 -0800 Subject: [PATCH 072/225] In # optional, no commas between tags --- src/sage/sets/condition_set.py | 8 ++++---- src/sage/sets/non_negative_integers.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index b4d6f8e84ec..2e8a1de78bb 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -79,11 +79,11 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 1.2; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 1.20000000000000 - sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again + sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic { (x, y, z) ∈ P : sqrt(x^2 + y^2 + z^2) < 1.20000000000000 } - sage: vector([1, 0, 0]) in P_inter_B_again + sage: vector([1, 0, 0]) in P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic True - sage: vector([1, 1, 1]) in P_inter_B_again + sage: vector([1, 1, 1]) in P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic False Iterating over subsets determined by predicates:: @@ -121,7 +121,7 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope TESTS:: sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # optional - sage.geometry.polyhedron - sage: TestSuite(P_inter_B_again).run() # optional - sage.geometry.polyhedron, sage.symbolic + sage: TestSuite(P_inter_B_again).run() # optional - sage.geometry.polyhedron sage.symbolic """ @staticmethod def __classcall_private__(cls, universe, *predicates, vars=None, names=None, category=None): diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 0f632c0cd88..72601250a97 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -106,7 +106,7 @@ def __contains__(self, elt): False sage: None in NN False - sage: QQbar(sqrt(2)) in NN # optional - sage.symbolic, sage.rings.number_field + sage: QQbar(sqrt(2)) in NN # optional - sage.symbolic sage.rings.number_field False sage: RIF(1,2) in NN False From bb9a561170da7378187e34685bece61372ca4128 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 11:41:11 -0700 Subject: [PATCH 073/225] More # optional --- src/sage/sets/family.py | 70 ++++---- src/sage/sets/recursively_enumerated_set.pyx | 8 +- src/sage/sets/set_from_iterator.py | 176 ++++++++++--------- 3 files changed, 128 insertions(+), 126 deletions(-) diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index a630ef51e24..eb08c87a12d 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -17,8 +17,8 @@ Check :trac:`12482` (shall be run in a fresh session):: - sage: P = Partitions(3) - sage: Family(P, lambda x: x).category() + sage: P = Partitions(3) # optional - sage.combinat + sage: Family(P, lambda x: x).category() # optional - sage.combinat Category of finite enumerated sets """ @@ -185,10 +185,10 @@ def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=Fa Beware that for those kind of families len(f) is not supposed to work. As a replacement, use the .cardinality() method:: - sage: f = Family(Permutations(3), attrcall("to_lehmer_code")) - sage: list(f) + sage: f = Family(Permutations(3), attrcall("to_lehmer_code")) # optional - sage.combinat + sage: list(f) # optional - sage.combinat [[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0], [2, 0, 0], [2, 1, 0]] - sage: f.cardinality() + sage: f.cardinality() # optional - sage.combinat 6 Caveat: Only certain families with lazy behavior can be pickled. In @@ -196,14 +196,14 @@ def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=Fa and unpickle_function (in sage.misc.fpickle) will correctly unpickle. The following two work:: - sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f + sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f # optional - sage.combinat Lazy family ((i))_{i in Standard permutations of 3} - sage: f == loads(dumps(f)) + sage: f == loads(dumps(f)) # optional - sage.combinat True - sage: f = Family(Permutations(3), attrcall("to_lehmer_code")); f + sage: f = Family(Permutations(3), attrcall("to_lehmer_code")); f # optional - sage.combinat Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3} - sage: f == loads(dumps(f)) + sage: f == loads(dumps(f)) # optional - sage.combinat True But this one does not:: @@ -1187,12 +1187,12 @@ def __getstate__(self): sage: d['set'] [3, 4, 7] - sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()) - sage: f == loads(dumps(f)) + sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()) # optional - sage.combinat + sage: f == loads(dumps(f)) # optional - sage.combinat True - sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) - sage: f == loads(dumps(f)) + sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) # optional - sage.combinat + sage: f == loads(dumps(f)) # optional - sage.combinat True """ f = self.function @@ -1417,8 +1417,8 @@ def __init__(self, enumset): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) - sage: TestSuite(f).run() + sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat + sage: TestSuite(f).run() # optional - sage.combinat sage: f = Family(NonNegativeIntegers()) sage: TestSuite(f).run() @@ -1428,12 +1428,12 @@ def __init__(self, enumset): Check that category and keys are set correctly (:trac:`28274`):: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(4)) - sage: f.category() + sage: f = EnumeratedFamily(Permutations(4)) # optional - sage.combinat + sage: f.category() # optional - sage.combinat Category of finite enumerated sets - sage: list(f.keys()) == list(range(f.cardinality())) + sage: list(f.keys()) == list(range(f.cardinality())) # optional - sage.combinat True - sage: Family(Permutations()).keys() + sage: Family(Permutations()).keys() # optional - sage.combinat Non negative integers sage: type(Family(NN)) @@ -1449,8 +1449,8 @@ def __eq__(self, other): """ EXAMPLES:: - sage: f = Family(Permutations(3)) - sage: g = Family(Permutations(3)) + sage: f = Family(Permutations(3)) # optional - sage.combinat + sage: g = Family(Permutations(3)) # optional - sage.combinat sage: f == g True """ @@ -1461,7 +1461,7 @@ def __repr__(self): """ EXAMPLES:: - sage: f = Family(Permutations(3)); f # indirect doctest + sage: f = Family(Permutations(3)); f # indirect doctest # optional - sage.combinat Family (Standard permutations of 3) sage: f = Family(NonNegativeIntegers()); f @@ -1476,7 +1476,7 @@ def __contains__(self, x): """ EXAMPLES:: - sage: f = Family(Permutations(3)) + sage: f = Family(Permutations(3)) # optional - sage.combinat sage: [2,1,3] in f True """ @@ -1489,8 +1489,8 @@ def cardinality(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) - sage: f.cardinality() + sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat + sage: f.cardinality() # optional - sage.combinat 6 sage: f = Family(NonNegativeIntegers()) @@ -1504,8 +1504,8 @@ def __iter__(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) - sage: [i for i in f] + sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat + sage: [i for i in f] # optional - sage.combinat [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ for i in self.enumset: @@ -1516,8 +1516,8 @@ def __getitem__(self, i): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) - sage: f[1] + sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat + sage: f[1] # optional - sage.combinat [1, 3, 2] """ return self.enumset.unrank(i) @@ -1527,10 +1527,10 @@ def __getstate__(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) - sage: f.__getstate__() + sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat + sage: f.__getstate__() # optional - sage.combinat {'enumset': Standard permutations of 3} - sage: loads(dumps(f)) == f + sage: loads(dumps(f)) == f # optional - sage.combinat True """ return {'enumset': self.enumset} @@ -1540,9 +1540,9 @@ def __setstate__(self, state): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(0)) - sage: f.__setstate__({'enumset': Permutations(3)}) - sage: f + sage: f = EnumeratedFamily(Permutations(0)) # optional - sage.combinat + sage: f.__setstate__({'enumset': Permutations(3)}) # optional - sage.combinat + sage: f # optional - sage.combinat Family (Standard permutations of 3) """ self.__init__(state['enumset']) diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index a8b21530946..50bcd6ad9fb 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -880,10 +880,10 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): We compute all the permutations of 3:: - sage: seeds = [Permutation([1,2,3])] - sage: succ = attrcall("permutohedron_succ") - sage: R = RecursivelyEnumeratedSet(seeds, succ) - sage: sorted(R.naive_search_iterator()) + sage: seeds = [Permutation([1,2,3])] # optional - sage.combinat + sage: succ = attrcall("permutohedron_succ") # optional - sage.combinat + sage: R = RecursivelyEnumeratedSet(seeds, succ) # optional - sage.combinat + sage: sorted(R.naive_search_iterator()) # optional - sage.combinat [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ cdef set known, todo diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index 4c92deb5d52..fa67e99fa25 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -7,20 +7,20 @@ representative for each isomorphism class of graphs:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator( + sage: E = EnumeratedSetFromIterator( # optional - sage.graphs ....: graphs, - ....: name = "Graphs", - ....: category = InfiniteEnumeratedSets(), - ....: cache = True) - sage: E + ....: name="Graphs", + ....: category=InfiniteEnumeratedSets(), + ....: cache=True) + sage: E # optional - sage.graphs Graphs - sage: E.unrank(0) + sage: E.unrank(0) # optional - sage.graphs Graph on 0 vertices - sage: E.unrank(4) + sage: E.unrank(4) # optional - sage.graphs Graph on 3 vertices - sage: E.cardinality() + sage: E.cardinality() # optional - sage.graphs +Infinity - sage: E.category() + sage: E.category() # optional - sage.graphs Category of facade infinite enumerated sets The module also provides decorator for functions and methods:: @@ -97,25 +97,26 @@ class EnumeratedSetFromIterator(Parent): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args = (7,)) - sage: E - {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} - sage: E.category() + sage: E = EnumeratedSetFromIterator(graphs, args = (7,)) # optional - sage.graphs + sage: E # optional - sage.graphs + {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, + Graph on 7 vertices, Graph on 7 vertices, ...} + sage: E.category() # optional - sage.graphs Category of facade enumerated sets The same example with a cache and a custom name:: - sage: E = EnumeratedSetFromIterator( + sage: E = EnumeratedSetFromIterator( # optional - sage.graphs ....: graphs, ....: args = (8,), ....: category = FiniteEnumeratedSets(), ....: name = "Graphs with 8 vertices", ....: cache = True) - sage: E + sage: E # optional - sage.graphs Graphs with 8 vertices - sage: E.unrank(3) + sage: E.unrank(3) # optional - sage.graphs Graph on 8 vertices - sage: E.category() + sage: E.category() # optional - sage.graphs Category of facade finite enumerated sets TESTS: @@ -154,7 +155,7 @@ def __init__(self, f, args=None, kwds=None, name=None, category=None, cache=Fals TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: S = EnumeratedSetFromIterator(xsrange, (1,200,-1), category=FiniteEnumeratedSets()) + sage: S = EnumeratedSetFromIterator(xsrange, (1, 200, -1), category=FiniteEnumeratedSets()) sage: TestSuite(S).run() """ if category is not None: @@ -184,7 +185,7 @@ def __hash__(self): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(xsrange, (1,200)) + sage: E = EnumeratedSetFromIterator(xsrange, (1, 200)) sage: hash(E) == hash(tuple(range(1, 14))) True """ @@ -201,16 +202,16 @@ def __reduce__(self): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: from sage.graphs.graph_generators import graphs - sage: E = EnumeratedSetFromIterator(graphs, + sage: from sage.graphs.graph_generators import graphs # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, # optional - sage.graphs ....: args=(3,), ....: category=FiniteEnumeratedSets(), ....: name="Graphs on 3 vertices") - sage: E + sage: E # optional - sage.graphs Graphs on 3 vertices - sage: F = loads(dumps(E)); F + sage: F = loads(dumps(E)); F # optional - sage.graphs Graphs on 3 vertices - sage: E == F + sage: E == F # optional - sage.graphs True """ return (EnumeratedSetFromIterator, @@ -229,14 +230,15 @@ def _repr_(self): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(Partitions(7,min_part=2).__iter__) - sage: repr(E) # indirect doctest + sage: E = EnumeratedSetFromIterator(Partitions(7, min_part=2).__iter__) # optional - sage.combinat + sage: repr(E) # indirect doctest # optional - sage.combinat '{[7], [5, 2], [4, 3], [3, 2, 2]}' - sage: E = EnumeratedSetFromIterator(Partitions(9,min_part=2).__iter__) - sage: repr(E) # indirect doctest + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__) # optional - sage.combinat + sage: repr(E) # indirect doctest # optional - sage.combinat '{[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], ...}' - sage: E = EnumeratedSetFromIterator(Partitions(9,min_part=2).__iter__, name="Some partitions") - sage: repr(E) # indirect doctest + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__, # optional - sage.combinat + ....: name="Some partitions") + sage: repr(E) # indirect doctest # optional - sage.combinat 'Some partitions' """ l = [] @@ -260,10 +262,10 @@ def __contains__(self, x): EXAMPLES:: - sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: P = Partitions(12,min_part=2,max_part=5) - sage: E = EnumeratedSetFromIterator(P.__iter__) - sage: P([5,5,2]) in E + sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator # optional - sage.combinat + sage: P = Partitions(12, min_part=2, max_part=5) # optional - sage.combinat + sage: E = EnumeratedSetFromIterator(P.__iter__) # optional - sage.combinat + sage: P([5,5,2]) in E # optional - sage.combinat True """ return any(x == y for y in self) @@ -281,18 +283,18 @@ def __eq__(self, other): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) - sage: E4 == E4 + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: E4 == E4 # optional - sage.graphs True - sage: E4 == F4 + sage: E4 == F4 # optional - sage.graphs True - sage: E4 == E5 + sage: E4 == E5 # optional - sage.graphs False - sage: E5 == E4 + sage: E5 == E4 # optional - sage.graphs False - sage: E5 == E5 + sage: E5 == E5 # optional - sage.graphs True """ if isinstance(other, EnumeratedSetFromIterator): @@ -336,18 +338,18 @@ def __ne__(self, other): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) - sage: E4 != E4 + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) # optional - sage.graphs + sage: E4 != E4 # optional - sage.graphs False - sage: E4 != F4 + sage: E4 != F4 # optional - sage.graphs False - sage: E4 != E5 + sage: E4 != E5 # optional - sage.graphs True - sage: E5 != E4 + sage: E5 != E4 # optional - sage.graphs True - sage: E5 != E5 + sage: E5 != E5 # optional - sage.graphs False """ return not self == other @@ -359,13 +361,13 @@ def __iter__(self): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) - sage: g1 = next(iter(E)); g1 + sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) # optional - sage.graphs + sage: g1 = next(iter(E)); g1 # optional - sage.graphs Graph on 8 vertices - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) - sage: g2 = next(iter(E)); g2 + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs + sage: g2 = next(iter(E)); g2 # optional - sage.graphs Graph on 8 vertices - sage: g1 == g2 + sage: g1 == g2 # optional - sage.graphs True """ if hasattr(self, '_cache'): @@ -379,11 +381,11 @@ def unrank(self, i): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) - sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) - sage: E.unrank(2) + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs + sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) # optional - sage.graphs + sage: E.unrank(2) # optional - sage.graphs Graph on 8 vertices - sage: E.unrank(2) == F.unrank(2) + sage: E.unrank(2) == F.unrank(2) # optional - sage.graphs True """ if hasattr(self, '_cache'): @@ -504,11 +506,11 @@ def _sage_src_lines_(self): sage: from sage.misc.sageinspect import sage_getsourcelines sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = MathieuGroup.order - sage: S = sage_getsourcelines(d) # indirect doctest - sage: S[0][2] + sage: d.f = MathieuGroup.order # optional - sage.groups + sage: S = sage_getsourcelines(d) # indirect doctest # optional - sage.groups + sage: S[0][2] # optional - sage.groups ' Return the number of elements of this group.\n' - sage: S[0][25] + sage: S[0][25] # optional - sage.groups ' if not gens:\n' """ from sage.misc.sageinspect import sage_getsourcelines @@ -593,8 +595,8 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): A simple example with many options:: sage: @set_from_function( - ....: name = "From %(m)d to %(n)d", - ....: category = FiniteEnumeratedSets()) + ....: name="From %(m)d to %(n)d", + ....: category=FiniteEnumeratedSets()) ....: def f(m, n): return xsrange(m,n+1) sage: E = f(3,10); E From 3 to 10 @@ -612,30 +614,30 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): sage: @cached_function ....: @set_from_function( - ....: name = "Graphs on %(n)d vertices", - ....: category = FiniteEnumeratedSets(), - ....: cache = True) + ....: name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), + ....: cache=True) ....: def Graphs(n): return graphs(n) - sage: Graphs(10) + sage: Graphs(10) # optional - sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) + sage: Graphs(10).unrank(0) # optional - sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) + sage: Graphs(10) is Graphs(10) # optional - sage.graphs True The ``cached_function`` must go first:: sage: @set_from_function( - ....: name = "Graphs on %(n)d vertices", - ....: category = FiniteEnumeratedSets(), - ....: cache = True) + ....: name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), + ....: cache=True) ....: @cached_function ....: def Graphs(n): return graphs(n) - sage: Graphs(10) + sage: Graphs(10) # optional - sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) + sage: Graphs(10).unrank(0) # optional - sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) + sage: Graphs(10) is Graphs(10) # optional - sage.graphs False """ def __init__(self, f=None, name=None, **options): @@ -865,18 +867,18 @@ class EnumeratedSetFromIterator_method_decorator(): sage: class B(): ....: @set_from_method( - ....: name = "Graphs(%(n)d)", - ....: category = FiniteEnumeratedSets()) + ....: name="Graphs(%(n)d)", + ....: category=FiniteEnumeratedSets()) ....: def graphs(self, n): return graphs(n) sage: b = B() sage: G3 = b.graphs(3) sage: G3 Graphs(3) - sage: G3.cardinality() + sage: G3.cardinality() # optional - sage.graphs 4 sage: G3.category() Category of facade finite enumerated sets - sage: B.graphs(b,3) + sage: B.graphs(b, 3) Graphs(3) And a last example with a name parametrized by a function:: @@ -885,8 +887,8 @@ class EnumeratedSetFromIterator_method_decorator(): ....: def __init__(self, name): self.name = str(name) ....: def __str__(self): return self.name ....: @set_from_method( - ....: name = lambda self,n: str(self)*n, - ....: category = FiniteEnumeratedSets()) + ....: name=lambda self, n: str(self) * n, + ....: category=FiniteEnumeratedSets()) ....: def subset(self, n): ....: return xsrange(n) sage: d = D('a') @@ -914,11 +916,11 @@ def __init__(self, f=None, **options): :mod:`sage.combinat.permutation`) because its method ``bruhat_succ`` and ``bruhat_pred`` are decorated with ``set_from_method``:: - sage: from sage.combinat.permutation import Permutation - sage: loads(dumps(Permutation)) + sage: from sage.combinat.permutation import Permutation # optional - sage.combinat + sage: loads(dumps(Permutation)) # optional - sage.combinat - sage: p = Permutation([3,2,1]) - sage: loads(dumps(p)) == p + sage: p = Permutation([3,2,1]) # optional - sage.combinat + sage: loads(dumps(p)) == p # optional - sage.combinat True """ if f is not None: From 49a927b30069d1d9d779fe46b10525dc57aa3ee3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 13 Mar 2023 01:27:57 -0700 Subject: [PATCH 074/225] sage.sets: More # optional --- src/sage/sets/family.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index eb08c87a12d..bf4ecb47f97 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -1056,7 +1056,7 @@ def _repr_(self): sage: f = LazyFamily([3,4,7], fun); f Lazy family (fun(i))_{i in [3, 4, 7]} - sage: f = Family(Permutations(3), attrcall("to_lehmer_code"), lazy=True); f + sage: f = Family(Permutations(3), attrcall("to_lehmer_code"), lazy=True); f # optional - sage.combinat Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3} sage: f = LazyFamily([3,4,7], lambda i: 2*i); f @@ -1451,7 +1451,7 @@ def __eq__(self, other): sage: f = Family(Permutations(3)) # optional - sage.combinat sage: g = Family(Permutations(3)) # optional - sage.combinat - sage: f == g + sage: f == g # optional - sage.combinat True """ return (isinstance(other, self.__class__) and @@ -1477,7 +1477,7 @@ def __contains__(self, x): EXAMPLES:: sage: f = Family(Permutations(3)) # optional - sage.combinat - sage: [2,1,3] in f + sage: [2,1,3] in f # optional - sage.combinat True """ return x in self.enumset From d703a91804cf68e7fa2cff7d5461b7a47fd682a4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 17 Mar 2023 20:32:46 -0700 Subject: [PATCH 075/225] sage.sets: More # optional --- src/sage/sets/family.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index bf4ecb47f97..3e3676c2d03 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -1069,7 +1069,7 @@ def _repr_(self): Check that using a class as the function is correctly handled:: - sage: Family(NonNegativeIntegers(), PerfectMatchings) + sage: Family(NonNegativeIntegers(), PerfectMatchings) # optional - sage.combinat Lazy family ((i))_{i in Non negative integers} """ if self.function_name is not None: From bbed2e0127b42480bedd68d6d3166b985ed9a828 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 25 Apr 2023 23:10:36 -0700 Subject: [PATCH 076/225] sage.{sets,structure}: More # optional --- src/sage/sets/condition_set.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 2e8a1de78bb..49ddcf26cd0 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -419,16 +419,17 @@ def _sympy_(self): sage: (5, 7, 9) in ST False - sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval + sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval # optional - sage.symbolic { x ∈ Real Field with 53 bits of precision : x >= -7, x <= 4 } - sage: Interval._sympy_() - ConditionSet(x, (x >= -7) & (x <= 4), SageSet(Real Field with 53 bits of precision)) + sage: Interval._sympy_() # optional - sage.symbolic sympy + ConditionSet(x, (x >= -7) & (x <= 4), + SageSet(Real Field with 53 bits of precision)) If a predicate is not symbolic, we fall back to creating a wrapper:: sage: Evens = ConditionSet(ZZ, is_even); Evens { x ∈ Integer Ring : (x) } - sage: Evens._sympy_() + sage: Evens._sympy_() # optional - sympy SageSet({ x ∈ Integer Ring : (x) }) """ from sage.interfaces.sympy import sympy_init From 3f549138b9121fb8e7ad8c16b446a6034d80c872 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 28 Apr 2023 12:01:47 -0700 Subject: [PATCH 077/225] sage.{geometry,matrix,modules,repl,sets}: More # optional --- src/sage/sets/condition_set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 49ddcf26cd0..e58d68bfa12 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -74,7 +74,7 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope { x ∈ P : at 0x...>(x) } sage: vector([1, 0, 0]) in P_inter_B True - sage: vector([1, 1, 1]) in P_inter_B + sage: vector([1, 1, 1]) in P_inter_B # optional - sage.geometry.polyhedron sage.symbolic False sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 1.2; predicate From 4b16bd5c965f165b305e0da195194fd16a4fef29 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 11:41:46 -0700 Subject: [PATCH 078/225] Doctest cosmetics --- src/sage/sets/set_from_iterator.py | 205 ++++++++++++++--------------- 1 file changed, 99 insertions(+), 106 deletions(-) diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index fa67e99fa25..fc1a8f5dc1a 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -3,7 +3,7 @@ EXAMPLES: -We build a set from the iterator ``graphs`` that returns a canonical +We build a set from the iterator :obj:`graphs` that returns a canonical representative for each isomorphism class of graphs:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator @@ -37,9 +37,9 @@ sage: from sage.sets.set_from_iterator import set_from_method sage: class A: - ....: @set_from_method - ....: def f(self,n): - ....: return xsrange(n) + ....: @set_from_method + ....: def f(self,n): + ....: return xsrange(n) sage: a = A() sage: a.f(3) {0, 1, 2} @@ -97,8 +97,7 @@ class EnumeratedSetFromIterator(Parent): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args = (7,)) # optional - sage.graphs - sage: E # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(7,)); E # optional - sage.graphs {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} sage: E.category() # optional - sage.graphs @@ -106,13 +105,9 @@ class EnumeratedSetFromIterator(Parent): The same example with a cache and a custom name:: - sage: E = EnumeratedSetFromIterator( # optional - sage.graphs - ....: graphs, - ....: args = (8,), - ....: category = FiniteEnumeratedSets(), - ....: name = "Graphs with 8 vertices", - ....: cache = True) - sage: E # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True, # optional - sage.graphs + ....: name="Graphs with 8 vertices", + ....: category=FiniteEnumeratedSets()); E Graphs with 8 vertices sage: E.unrank(3) # optional - sage.graphs Graph on 8 vertices @@ -283,18 +278,21 @@ def __eq__(self, other): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: E4 == E4 # optional - sage.graphs + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: E4 == E4 # optional - sage.graphs True - sage: E4 == F4 # optional - sage.graphs + sage: E4 == F4 # optional - sage.graphs True - sage: E4 == E5 # optional - sage.graphs + sage: E4 == E5 # optional - sage.graphs False - sage: E5 == E4 # optional - sage.graphs + sage: E5 == E4 # optional - sage.graphs False - sage: E5 == E5 # optional - sage.graphs + sage: E5 == E5 # optional - sage.graphs True """ if isinstance(other, EnumeratedSetFromIterator): @@ -338,18 +336,21 @@ def __ne__(self, other): TESTS:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), category=FiniteEnumeratedSets()) # optional - sage.graphs - sage: E4 != E4 # optional - sage.graphs + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), # optional - sage.graphs + ....: category=FiniteEnumeratedSets()) + sage: E4 != E4 # optional - sage.graphs False - sage: E4 != F4 # optional - sage.graphs + sage: E4 != F4 # optional - sage.graphs False - sage: E4 != E5 # optional - sage.graphs + sage: E4 != E5 # optional - sage.graphs True - sage: E5 != E4 # optional - sage.graphs + sage: E5 != E4 # optional - sage.graphs True - sage: E5 != E5 # optional - sage.graphs + sage: E5 != E5 # optional - sage.graphs False """ return not self == other @@ -361,13 +362,13 @@ def __iter__(self): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) # optional - sage.graphs - sage: g1 = next(iter(E)); g1 # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) # optional - sage.graphs + sage: g1 = next(iter(E)); g1 # optional - sage.graphs Graph on 8 vertices - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs - sage: g2 = next(iter(E)); g2 # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs + sage: g2 = next(iter(E)); g2 # optional - sage.graphs Graph on 8 vertices - sage: g1 == g2 # optional - sage.graphs + sage: g1 == g2 # optional - sage.graphs True """ if hasattr(self, '_cache'): @@ -381,11 +382,11 @@ def unrank(self, i): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs - sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) # optional - sage.graphs - sage: E.unrank(2) # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs + sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) # optional - sage.graphs + sage: E.unrank(2) # optional - sage.graphs Graph on 8 vertices - sage: E.unrank(2) == F.unrank(2) # optional - sage.graphs + sage: E.unrank(2) == F.unrank(2) # optional - sage.graphs True """ if hasattr(self, '_cache'): @@ -402,7 +403,8 @@ def _element_constructor_(self, el): sage: S = EnumeratedSetFromIterator(range, args=(1,4)) sage: S(1) - doctest:...: UserWarning: Testing equality of infinite sets which will not end in case of equality + doctest:...: UserWarning: Testing equality of infinite sets + which will not end in case of equality 1 sage: S(0) # indirect doctest Traceback (most recent call last): @@ -422,8 +424,7 @@ def clear_cache(self): sage: from itertools import count sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator sage: E = EnumeratedSetFromIterator(count, args=(1,), cache=True) - sage: e1 = E._cache - sage: e1 + sage: e1 = E._cache; e1 lazy list [1, 2, 3, ...] sage: E.clear_cache() sage: E._cache @@ -506,11 +507,11 @@ def _sage_src_lines_(self): sage: from sage.misc.sageinspect import sage_getsourcelines sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = MathieuGroup.order # optional - sage.groups - sage: S = sage_getsourcelines(d) # indirect doctest # optional - sage.groups - sage: S[0][2] # optional - sage.groups + sage: d.f = MathieuGroup.order # optional - sage.groups + sage: S = sage_getsourcelines(d) # indirect doctest # optional - sage.groups + sage: S[0][2] # optional - sage.groups ' Return the number of elements of this group.\n' - sage: S[0][25] # optional - sage.groups + sage: S[0][25] # optional - sage.groups ' if not gens:\n' """ from sage.misc.sageinspect import sage_getsourcelines @@ -526,7 +527,7 @@ def _sage_argspec_(self): sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() sage: d.f = find_local_minimum - sage: sage_getargspec(d) # indirect doctest + sage: sage_getargspec(d) # indirect doctest FullArgSpec(args=['f', 'a', 'b', 'tol', 'maxfun'], varargs=None, varkw=None, defaults=(1.48e-08, 500), kwonlyargs=[], kwonlydefaults=None, annotations={}) @@ -557,12 +558,12 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): r""" Decorator for :class:`EnumeratedSetFromIterator`. - Name could be string or a function ``(args,kwds) -> string``. + Name could be string or a function ``(args, kwds) -> string``. .. WARNING:: - If you are going to use this with the decorator ``cached_function``, - you must place the ``cached_function`` first. See the example below. + If you are going to use this with the decorator :func:`cached_function`, + you must place the ``@cached_function`` first. See the example below. EXAMPLES:: @@ -586,18 +587,16 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): ....: while True: ....: yield a ....: a, b = b, a + b - sage: F = Fibonacci() - sage: F + sage: F = Fibonacci(); F {1, 2, 3, 5, 8, ...} sage: F.cardinality() +Infinity A simple example with many options:: - sage: @set_from_function( - ....: name="From %(m)d to %(n)d", - ....: category=FiniteEnumeratedSets()) - ....: def f(m, n): return xsrange(m,n+1) + sage: @set_from_function(name="From %(m)d to %(n)d", + ....: category=FiniteEnumeratedSets()) + ....: def f(m, n): return xsrange(m, n + 1) sage: E = f(3,10); E From 3 to 10 sage: E.list() @@ -606,38 +605,34 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): From 1 to 100 sage: E.cardinality() 100 - sage: f(n=100,m=1) == E + sage: f(n=100, m=1) == E True - An example which mixes together ``set_from_function`` and - ``cached_method``:: + An example which mixes together :func:`set_from_function` and + :func:`cached_method`:: sage: @cached_function - ....: @set_from_function( - ....: name="Graphs on %(n)d vertices", - ....: category=FiniteEnumeratedSets(), - ....: cache=True) + ....: @set_from_function(name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), cache=True) ....: def Graphs(n): return graphs(n) - sage: Graphs(10) # optional - sage.graphs + sage: Graphs(10) # optional - sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) # optional - sage.graphs + sage: Graphs(10).unrank(0) # optional - sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) # optional - sage.graphs + sage: Graphs(10) is Graphs(10) # optional - sage.graphs True - The ``cached_function`` must go first:: + The ``@cached_function`` must go first:: - sage: @set_from_function( - ....: name="Graphs on %(n)d vertices", - ....: category=FiniteEnumeratedSets(), - ....: cache=True) + sage: @set_from_function(name="Graphs on %(n)d vertices", + ....: category=FiniteEnumeratedSets(), cache=True) ....: @cached_function ....: def Graphs(n): return graphs(n) - sage: Graphs(10) # optional - sage.graphs + sage: Graphs(10) # optional - sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) # optional - sage.graphs + sage: Graphs(10).unrank(0) # optional - sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) # optional - sage.graphs + sage: Graphs(10) is Graphs(10) # optional - sage.graphs False """ def __init__(self, f=None, name=None, **options): @@ -721,7 +716,7 @@ class EnumeratedSetFromIterator_method_caller(Decorator): - ``f`` -- a method of a class of ``inst`` (and not of the instance itself) - ``name`` -- optional -- either a string (which may contains substitution - rules from argument or a function args,kwds -> string. + rules from argument or a function ``args, kwds -> string``. - ``options`` -- any option accepted by :class:`EnumeratedSetFromIterator` """ @@ -748,7 +743,8 @@ def __init__(self, inst, f, name=None, **options): sage: loads(dumps(d.f())) Traceback (most recent call last): ... - _pickle.PicklingError: Can't pickle : it's not the same object as sage.sets.set_from_iterator.DummyExampleForPicklingTest.f + _pickle.PicklingError: Can't pickle : + it's not the same object as sage.sets.set_from_iterator.DummyExampleForPicklingTest.f """ self.inst = inst self.f = f @@ -813,8 +809,8 @@ def __get__(self, inst, cls): sage: class A: ....: stop = 10000 ....: @set_from_method - ....: def f(self,start): - ....: return xsrange(start,self.stop) + ....: def f(self, start): + ....: return xsrange(start, self.stop) sage: a = A() sage: A.f(a,4) {4, 5, 6, 7, 8, ...} @@ -822,8 +818,8 @@ def __get__(self, inst, cls): sage: class B: ....: stop = 10000 ....: @set_from_method(category=FiniteEnumeratedSets()) - ....: def f(self,start): - ....: return xsrange(start,self.stop) + ....: def f(self, start): + ....: return xsrange(start, self.stop) sage: b = B() sage: B.f(b,2) {2, 3, 4, 5, 6, ...} @@ -852,9 +848,9 @@ class EnumeratedSetFromIterator_method_decorator(): sage: from sage.sets.set_from_iterator import set_from_method sage: class A(): - ....: def n(self): return 12 - ....: @set_from_method - ....: def f(self): return xsrange(self.n()) + ....: def n(self): return 12 + ....: @set_from_method + ....: def f(self): return xsrange(self.n()) sage: a = A() sage: print(a.f.__class__) @@ -866,15 +862,13 @@ class EnumeratedSetFromIterator_method_decorator(): A more complicated example with a parametrized name:: sage: class B(): - ....: @set_from_method( - ....: name="Graphs(%(n)d)", - ....: category=FiniteEnumeratedSets()) - ....: def graphs(self, n): return graphs(n) + ....: @set_from_method(name="Graphs(%(n)d)", + ....: category=FiniteEnumeratedSets()) + ....: def graphs(self, n): return graphs(n) sage: b = B() - sage: G3 = b.graphs(3) - sage: G3 + sage: G3 = b.graphs(3); G3 Graphs(3) - sage: G3.cardinality() # optional - sage.graphs + sage: G3.cardinality() # optional - sage.graphs 4 sage: G3.category() Category of facade finite enumerated sets @@ -884,13 +878,12 @@ class EnumeratedSetFromIterator_method_decorator(): And a last example with a name parametrized by a function:: sage: class D(): - ....: def __init__(self, name): self.name = str(name) - ....: def __str__(self): return self.name - ....: @set_from_method( - ....: name=lambda self, n: str(self) * n, - ....: category=FiniteEnumeratedSets()) - ....: def subset(self, n): - ....: return xsrange(n) + ....: def __init__(self, name): self.name = str(name) + ....: def __str__(self): return self.name + ....: @set_from_method(name=lambda self, n: str(self) * n, + ....: category=FiniteEnumeratedSets()) + ....: def subset(self, n): + ....: return xsrange(n) sage: d = D('a') sage: E = d.subset(3); E aaa @@ -916,11 +909,11 @@ def __init__(self, f=None, **options): :mod:`sage.combinat.permutation`) because its method ``bruhat_succ`` and ``bruhat_pred`` are decorated with ``set_from_method``:: - sage: from sage.combinat.permutation import Permutation # optional - sage.combinat - sage: loads(dumps(Permutation)) # optional - sage.combinat + sage: from sage.combinat.permutation import Permutation # optional - sage.combinat + sage: loads(dumps(Permutation)) # optional - sage.combinat - sage: p = Permutation([3,2,1]) # optional - sage.combinat - sage: loads(dumps(p)) == p # optional - sage.combinat + sage: p = Permutation([3,2,1]) # optional - sage.combinat + sage: loads(dumps(p)) == p # optional - sage.combinat True """ if f is not None: @@ -950,9 +943,9 @@ def __call__(self, f): sage: from sage.sets.set_from_iterator import set_from_method sage: class A: # indirect doctest - ....: @set_from_method() - ....: def f(self): - ....: return xsrange(3) + ....: @set_from_method() + ....: def f(self): + ....: return xsrange(3) sage: a = A() sage: a.f() {0, 1, 2} @@ -965,9 +958,9 @@ def __get__(self, inst, cls): sage: from sage.sets.set_from_iterator import set_from_method sage: class A(): - ....: def n(self): return 12 - ....: @set_from_method - ....: def f(self): return xsrange(self.n()) + ....: def n(self): return 12 + ....: @set_from_method + ....: def f(self): return xsrange(self.n()) sage: a = A() sage: print(A.f.__class__) From 71cc773a6dbe657938a98f5c22a57b4105b1ce5d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 12 May 2023 20:01:52 -0700 Subject: [PATCH 079/225] Fix # optional --- src/sage/sets/condition_set.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index e58d68bfa12..7d66f59300c 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -345,18 +345,18 @@ def _call_predicate(self, predicate, element): sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: predicate = SmallTriples._predicates[0] # optional - sage.symbolic - sage: element = TripleDigits((1, 2, 3)) # optional - sage.symbolic - sage: SmallTriples._call_predicate(predicate, element) # optional - sage.symbolic + sage: predicate = SmallTriples._predicates[0] # optional - sage.symbolic + sage: element = TripleDigits((1, 2, 3)) # optional - sage.modules + sage: SmallTriples._call_predicate(predicate, element) # optional - sage.modules sage.symbolic sqrt(14) < 12 sage: var('t') t - sage: TinyUniverse = ZZ^0 - sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) - sage: predicate = Nullary._predicates[0] - sage: element = TinyUniverse(0) - sage: Nullary._call_predicate(predicate, element) + sage: TinyUniverse = ZZ^0 # optional - sage.modules + sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) # optional - sage.modules sage.symbolic + sage: predicate = Nullary._predicates[0] # optional - sage.modules sage.symbolic + sage: element = TinyUniverse(0) # optional - sage.modules + sage: Nullary._call_predicate(predicate, element) # optional - sage.modules sage.symbolic t > 0 """ if isinstance(predicate, Expression) and predicate.is_callable(): From 6dd822522ab497128897926993efda0f1c0e1842 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 17 May 2023 13:20:30 -0700 Subject: [PATCH 080/225] Massive modularization fixes --- src/sage/sets/condition_set.py | 10 +++++----- src/sage/sets/real_set.py | 15 ++++++++------- src/sage/sets/set.py | 10 +++++----- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 7d66f59300c..18b88e2b809 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -108,14 +108,14 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring } sage: Z3.variable_names() # optional - sage.modules ('x', 'y', 'z') - sage: Z3.arguments() # optional - sage.modules + sage: Z3.arguments() # optional - sage.modules sage.symbolic (x, y, z) - sage: Q4. = ConditionSet(QQ^4); Q4 # optional - sage.modules + sage: Q4. = ConditionSet(QQ^4); Q4 # optional - sage.modules sage.symbolic { (a, b, c, d) ∈ Vector space of dimension 4 over Rational Field } - sage: Q4.variable_names() # optional - sage.modules + sage: Q4.variable_names() # optional - sage.modules sage.symbolic ('a', 'b', 'c', 'd') - sage: Q4.arguments() # optional - sage.modules + sage: Q4.arguments() # optional - sage.modules sage.symbolic (a, b, c, d) TESTS:: @@ -429,7 +429,7 @@ def _sympy_(self): sage: Evens = ConditionSet(ZZ, is_even); Evens { x ∈ Integer Ring : (x) } - sage: Evens._sympy_() # optional - sympy + sage: Evens._sympy_() # optional - sage.symbolic sympy SageSet({ x ∈ Integer Ring : (x) }) """ from sage.interfaces.sympy import sympy_init diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index b4e1d5ca266..d341d09eba9 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -464,17 +464,17 @@ def _sympy_(self): EXAMPLES:: - sage: RealSet.open_closed(0, 1)[0]._sympy_() + sage: RealSet.open_closed(0, 1)[0]._sympy_() # optional - sympy Interval.Lopen(0, 1) - sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9 + sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9 # optional - sympy {0} - sage: type(_) + sage: type(_) # optional - sympy - sage: RealSet.open(0,1)[0]._sympy_() + sage: RealSet.open(0,1)[0]._sympy_() # optional - sympy Interval.open(0, 1) - sage: RealSet.open(-oo,1)[0]._sympy_() + sage: RealSet.open(-oo,1)[0]._sympy_() # optional - sympy Interval.open(-oo, 1) - sage: RealSet.open(0, oo)[0]._sympy_() + sage: RealSet.open(0, oo)[0]._sympy_() # optional - sympy Interval.open(0, oo) """ from sympy import Interval @@ -2107,7 +2107,8 @@ def union(self, *real_set_collection): (-oo, +oo) sage: s = RealSet().union([1, 2], (2, 3)); s [1, 3) - sage: RealSet().union((-oo, 0), x > 6, s[0], RealSet.point(5.0), RealSet.closed_open(2, 4)) + sage: RealSet().union((-oo, 0), x > 6, s[0], # optional - sage.symbolic + ....: RealSet.point(5.0), RealSet.closed_open(2, 4)) (-oo, 0) ∪ [1, 4) ∪ {5} ∪ (6, +oo) """ sets = [self] diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 875ab3765f7..943efee47be 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -1669,12 +1669,12 @@ def __contains__(self, x): Any specific floating-point number in Sage is to finite precision, hence it is rational:: - sage: RR(sqrt(2)) in X + sage: RR(sqrt(2)) in X # optional - sage.symbolic True Real constants are not rational:: - sage: pi in X + sage: pi in X # optional - sage.symbolic False """ return x in self._X and x in self._Y @@ -1837,9 +1837,9 @@ def __contains__(self, x): False sage: ComplexField().0 in X False - sage: sqrt(2) in X # since sqrt(2) is not a numerical approx + sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # optional - sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # optional - sage.symbolic True sage: 5/2 in X True @@ -2010,7 +2010,7 @@ def __contains__(self, x): True sage: ComplexField().0 in X False - sage: sqrt(2) in X # since sqrt(2) is currently symbolic + sage: sqrt(2) in X # since sqrt(2) is currently symbolic # optional - sage.symbolic False sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated True From 370ae890f73e4a105e53d776055037dbfca0cbba Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 27 May 2023 20:18:26 -0700 Subject: [PATCH 081/225] Add # optional --- src/sage/sets/disjoint_set.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 0dc2f93c20b..602bcdd3aa4 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -561,7 +561,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(4,1) sage: e = d.element_to_root_dict(); e {0: 0, 1: 4, 2: 2, 3: 2, 4: 4} - sage: WordMorphism(e) + sage: WordMorphism(e) # optional - sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} @@ -849,7 +849,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: e = d.element_to_root_dict() sage: sorted(e.items()) [(0, 0), (1, 4), (2, 2), (3, 2), (4, 4)] - sage: WordMorphism(e) + sage: WordMorphism(e) # optional - sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} From 05a77d9b43ec21ba29aace9ab3020207ce703840 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 31 May 2023 14:51:31 -0700 Subject: [PATCH 082/225] src/sage/sets/disjoint_set.pyx: Add # optional --- src/sage/sets/disjoint_set.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 602bcdd3aa4..5b291c9eb97 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -583,9 +583,9 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g + sage: g = d.to_digraph(); g # optional - sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) + sage: g.edges(sort=True) # optional - sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: @@ -596,7 +596,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) + sage: d.to_digraph().edges(sort=True) # optional - sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {i: [self._nodes.parent[i]] for i in range(self.cardinality())} @@ -870,7 +870,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g + sage: g = d.to_digraph(); g # optional - sage.graphs Looped digraph on 5 vertices sage: g.edges(sort=True) [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] @@ -883,7 +883,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) + sage: d.to_digraph().edges(sort=True) # optional - sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {} From d8c5aa6d450d2c9d2ce457298ea28c0337c0a774 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 31 May 2023 23:18:40 -0700 Subject: [PATCH 083/225] sage.sets: More # optional --- src/sage/sets/disjoint_set.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 5b291c9eb97..edaf98ad5ae 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -872,7 +872,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): {{0}, {1, 2, 3, 4}} sage: g = d.to_digraph(); g # optional - sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) + sage: g.edges(sort=True) # optional - sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: From dd5bc38005e3dc11b8910b01973a21063308ab9f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 9 Jun 2023 00:55:41 -0700 Subject: [PATCH 084/225] More # optional --- src/sage/sets/real_set.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index d341d09eba9..ec57b00236f 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.rings.real_mpfr """ Subsets of the Real Line From f8ad1e3fc6fde900f305953e1ef08456fc5f1508 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 10 Jun 2023 17:49:30 -0700 Subject: [PATCH 085/225] More # optional --- .../sets/disjoint_union_enumerated_sets.py | 67 ++++++++++--------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 5ad8546c99b..aa51ebe7fd0 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -277,8 +277,8 @@ def __init__(self, family, facade=True, keepkey=False, category=None): ....: 2: FiniteEnumeratedSet([4,5,6])}) sage: TestSuite(U).run() - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat - sage: TestSuite(X).run() # optional - sage.combinat + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat sage.libs.flint + sage: TestSuite(X).run() # optional - sage.combinat sage.libs.flint """ self._family = family self._facade = facade @@ -471,14 +471,14 @@ def _element_constructor_(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), facade=False) - sage: U._element_constructor_ # optional - sage.combinat + sage: U._element_constructor_ # optional - sage.combinat sage.libs.flint - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), facade=True) - sage: U._element_constructor_ # optional - sage.combinat + sage: U._element_constructor_ # optional - sage.combinat sage.libs.flint """ @@ -491,13 +491,13 @@ def _element_constructor_default(self, el): r""" TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), facade=False) - sage: U([1]) # indirect doctest # optional - sage.combinat + sage: U([1]) # indirect doctest # optional - sage.combinat sage.libs.flint [1] - sage: U([2,1]) # indirect doctest # optional - sage.combinat + sage: U([2,1]) # indirect doctest # optional - sage.combinat sage.libs.flint [2, 1] - sage: U([1,3,2]) # indirect doctest # optional - sage.combinat + sage: U([1,3,2]) # indirect doctest # optional - sage.combinat sage.libs.flint Traceback (most recent call last): ... ValueError: value [1, 3, 2] does not belong to Disjoint union of @@ -505,13 +505,13 @@ def _element_constructor_default(self, el): 2: Partitions of the integer 2, 3: Partitions of the integer 3} - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), keepkey=True, facade=False) - sage: U((1, [1])) # indirect doctest # optional - sage.combinat + sage: U((1, [1])) # indirect doctest # optional - sage.combinat sage.libs.flint (1, [1]) - sage: U((3,[2,1])) # indirect doctest # optional - sage.combinat + sage: U((3,[2,1])) # indirect doctest # optional - sage.combinat sage.libs.flint (3, [2, 1]) - sage: U((4,[2,1])) # indirect doctest # optional - sage.combinat + sage: U((4,[2,1])) # indirect doctest # optional - sage.combinat sage.libs.flint Traceback (most recent call last): ... ValueError: value (4, [2, 1]) does not belong to Disjoint union of @@ -530,12 +530,13 @@ def _element_constructor_facade(self, el): """ TESTS:: - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat - sage: X([1]).parent() # optional - sage.combinat + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # optional - sage.combinat sage.libs.flint + ....: for i in range(5)}) + sage: X([1]).parent() # optional - sage.combinat sage.libs.flint Partitions of the integer 1 - sage: X([2,1,1]).parent() # indirect doctest # optional - sage.combinat + sage: X([2,1,1]).parent() # indirect doctest # optional - sage.combinat sage.libs.flint Partitions of the integer 4 - sage: X([6]) # optional - sage.combinat + sage: X([6]) # optional - sage.combinat sage.libs.flint Traceback (most recent call last): ... ValueError: cannot coerce `[6]` in any parent in `Finite family {...}` @@ -544,23 +545,24 @@ def _element_constructor_facade(self, el): because this returns a `tuple`, where the coercion framework requires an :class:`Element` be returned. - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}, # optional - sage.combinat + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # optional - sage.combinat sage.libs.flint + ....: for i in range(5)}, ....: keepkey=True) - sage: p = X._element_constructor_((0, [])) # indirect doctest # optional - sage.combinat - sage: p[1].parent() # optional - sage.combinat + sage: p = X._element_constructor_((0, [])) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: p[1].parent() # optional - sage.combinat sage.libs.flint Partitions of the integer 0 Test that facade parents can create and properly access elements that are tuples (fixed by :trac:`22382`):: - sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), # optional - sage.combinat + sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), # optional - sage.combinat sage.libs.flint ....: mu.standard_tableaux()]) - sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) # optional - sage.combinat - sage: s = StandardTableau([[1,3],[2,4]]) # optional - sage.combinat - sage: (s,s) in tabs # optional - sage.combinat + sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) # optional - sage.combinat sage.libs.flint + sage: s = StandardTableau([[1,3],[2,4]]) # optional - sage.combinat sage.libs.flint + sage: (s,s) in tabs # optional - sage.combinat sage.libs.flint True - sage: ss = tabs( (s,s) ) # optional - sage.combinat - sage: ss[0] # optional - sage.combinat + sage: ss = tabs( (s,s) ) # optional - sage.combinat sage.libs.flint + sage: ss[0] # optional - sage.combinat sage.libs.flint [[1, 3], [2, 4]] We do not coerce when one of the elements is already in the set:: @@ -596,16 +598,17 @@ def Element(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), facade=False) - sage: U.Element # optional - sage.combinat + sage: U.Element # optional - sage.combinat sage.libs.flint <... 'sage.structure.element_wrapper.ElementWrapper'> - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint ....: Family([1,2,3], Partitions), facade=True) - sage: U.Element # optional - sage.combinat + sage: U.Element # optional - sage.combinat sage.libs.flint Traceback (most recent call last): ... - AttributeError: 'DisjointUnionEnumeratedSets_with_category' object has no attribute 'Element' + AttributeError: 'DisjointUnionEnumeratedSets_with_category' object + has no attribute 'Element' """ if not self._facade: return ElementWrapper From 5cf167b0c8b5db016664c2306255e6d7e17439f7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 11 Jun 2023 23:47:37 -0700 Subject: [PATCH 086/225] More # optional --- src/sage/sets/set.py | 4 ++-- src/sage/sets/set_from_iterator.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 943efee47be..8ad86411222 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -800,10 +800,10 @@ def subsets_lattice(self): EXAMPLES:: sage: X = Set([1,2,3]) - sage: X.subsets_lattice() # optional - sage.combinat + sage: X.subsets_lattice() # optional - sage.combinat sage.graphs sage.modules Finite lattice containing 8 elements sage: Y = Set() - sage: Y.subsets_lattice() # optional - sage.combinat + sage: Y.subsets_lattice() # optional - sage.combinat sage.graphs sage.modules Finite lattice containing 1 elements """ diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index fc1a8f5dc1a..0c7e4f35aa4 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -526,8 +526,8 @@ def _sage_argspec_(self): sage: from sage.misc.sageinspect import sage_getargspec sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = find_local_minimum - sage: sage_getargspec(d) # indirect doctest + sage: d.f = find_local_minimum # optional - scipy + sage: sage_getargspec(d) # indirect doctest # optional - scipy FullArgSpec(args=['f', 'a', 'b', 'tol', 'maxfun'], varargs=None, varkw=None, defaults=(1.48e-08, 500), kwonlyargs=[], kwonlydefaults=None, annotations={}) From 3d0d2f1161011cf6909aee39cfcb6560ef54da40 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 15 Jun 2023 21:40:28 -0700 Subject: [PATCH 087/225] sage.sets: More # optional --- src/sage/sets/cartesian_product.py | 12 ++++++------ src/sage/sets/set.py | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index dac1cef42c0..e4c15f778bd 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -354,9 +354,9 @@ def __len__(self): EXAMPLES:: - sage: C = cartesian_product([ZZ, QQ, CC]) - sage: e = C.random_element() - sage: len(e) + sage: C = cartesian_product([ZZ, QQ, CC]) # optional - sage.rings.real_mpfr + sage: e = C.random_element() # optional - sage.rings.real_mpfr + sage: len(e) # optional - sage.rings.real_mpfr 3 """ return len(self.value) @@ -367,10 +367,10 @@ def cartesian_factors(self): EXAMPLES:: - sage: A = cartesian_product([ZZ, RR]) - sage: A((1, 1.23)).cartesian_factors() + sage: A = cartesian_product([ZZ, RR]) # optional - sage.rings.real_mpfr + sage: A((1, 1.23)).cartesian_factors() # optional - sage.rings.real_mpfr (1, 1.23000000000000) - sage: type(_) + sage: type(_) # optional - sage.rings.real_mpfr <... 'tuple'> """ return self.value diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 8ad86411222..fe5f97d9133 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -1663,13 +1663,13 @@ def __contains__(self, x): sage: X = Set(QQ).intersection(Set(RR)) sage: 5 in X True - sage: ComplexField().0 in X + sage: ComplexField().0 in X # optional - sage.rings.real_mpfr False Any specific floating-point number in Sage is to finite precision, hence it is rational:: - sage: RR(sqrt(2)) in X # optional - sage.symbolic + sage: RR(sqrt(2)) in X # optional - sage.rings.real_mpfr sage.symbolic True Real constants are not rational:: @@ -1835,11 +1835,11 @@ def __contains__(self, x): sage: X = Set(QQ).difference(Set(ZZ)) sage: 5 in X False - sage: ComplexField().0 in X + sage: ComplexField().0 in X # optional - sage.rings.real_mpfr False sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # optional - sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # optional - sage.symbolic + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # optional - sage.rings.real_mpfr sage.symbolic True sage: 5/2 in X True @@ -2008,13 +2008,13 @@ def __contains__(self, x): sage: X = Set(QQ).symmetric_difference(Primes()) sage: 4 in X True - sage: ComplexField().0 in X + sage: ComplexField().0 in X # optional - sage.rings.real_mpfr False sage: sqrt(2) in X # since sqrt(2) is currently symbolic # optional - sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated # optional - sage.rings.real_mpfr True - sage: pi in X + sage: pi in X # optional - sage.symbolic False sage: 5/2 in X True From 5918b0bd6c79be399587885bffd84a0e83fc2332 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Jun 2023 09:35:21 -0700 Subject: [PATCH 088/225] sage.sets: Remove '# optional - sage.rings.finite_rings' that are now unnecessary --- src/sage/sets/cartesian_product.py | 24 ++++----- src/sage/sets/set.py | 82 +++++++++++++++--------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index e4c15f778bd..87157bc9256 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -37,14 +37,14 @@ class CartesianProduct(UniqueRepresentation, Parent): EXAMPLES:: - sage: G = cartesian_product([GF(5), Permutations(10)]) # optional - sage.libs.pari - sage: G.cartesian_factors() # optional - sage.libs.pari + sage: G = cartesian_product([GF(5), Permutations(10)]) + sage: G.cartesian_factors() (Finite Field of size 5, Standard permutations of 10) - sage: G.cardinality() # optional - sage.libs.pari + sage: G.cardinality() 18144000 - sage: G.random_element() # random # optional - sage.libs.pari + sage: G.random_element() (1, [4, 7, 6, 5, 10, 1, 3, 2, 8, 9]) - sage: G.category() # optional - sage.libs.pari + sage: G.category() Join of Category of finite monoids and Category of Cartesian products of monoids and Category of Cartesian products of finite enumerated sets @@ -93,24 +93,24 @@ def _element_constructor_(self, x): EXAMPLES:: - sage: C = cartesian_product([GF(5), GF(3)]) # optional - sage.libs.pari - sage: x = C((1,3)); x # optional - sage.libs.pari + sage: C = cartesian_product([GF(5), GF(3)]) + sage: x = C((1,3)); x (1, 0) - sage: x.parent() # optional - sage.libs.pari + sage: x.parent() The Cartesian product of (Finite Field of size 5, Finite Field of size 3) - sage: x[0].parent() # optional - sage.libs.pari + sage: x[0].parent() Finite Field of size 5 - sage: x[1].parent() # optional - sage.libs.pari + sage: x[1].parent() Finite Field of size 3 An iterable is also accepted as input:: - sage: C(i for i in range(2)) # optional - sage.libs.pari + sage: C(i for i in range(2)) (0, 1) TESTS:: - sage: C((1,3,4)) # optional - sage.libs.pari + sage: C((1,3,4)) Traceback (most recent call last): ... ValueError: (1, 3, 4) should be of length 2 diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index fe5f97d9133..11a99a33a7e 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -227,11 +227,11 @@ def union(self, X): Set-theoretic union of Set of elements of Rational Field and Set of elements of Integer Ring - sage: X = Set(QQ).union(Set(GF(3))); X # optional - sage.libs.pari + sage: X = Set(QQ).union(Set(GF(3))); X Set-theoretic union of Set of elements of Rational Field and {0, 1, 2} - sage: 2/3 in X # optional - sage.libs.pari + sage: 2/3 in X True sage: GF(3)(2) in X # optional - sage.libs.pari True @@ -445,14 +445,14 @@ class Set_object(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_opera EXAMPLES:: - sage: K = GF(19) # optional - sage.libs.pari - sage: Set(K) # optional - sage.libs.pari + sage: K = GF(19) + sage: Set(K) {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} - sage: S = Set(K) # optional - sage.libs.pari + sage: S = Set(K) - sage: latex(S) # optional - sage.libs.pari + sage: latex(S) \left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\} - sage: TestSuite(S).run() # optional - sage.libs.pari + sage: TestSuite(S).run() sage: latex(Set(ZZ)) \Bold{Z} @@ -622,12 +622,12 @@ def __contains__(self, x): Finite fields better illustrate the difference between ``__contains__`` for objects and their underlying sets:: - sage: X = Set(GF(7)) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: X = Set(GF(7)) + sage: X {0, 1, 2, 3, 4, 5, 6} - sage: 5/3 in X # optional - sage.libs.pari + sage: 5/3 in X False - sage: 5/3 in GF(7) # optional - sage.libs.pari + sage: 5/3 in GF(7) False sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) # optional - sage.libs.pari [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6] @@ -675,7 +675,7 @@ def cardinality(self): +Infinity sage: Primes().cardinality() +Infinity - sage: Set(GF(5)).cardinality() # optional - sage.libs.pari + sage: Set(GF(5)).cardinality() 5 sage: Set(GF(5^2,'a')).cardinality() # optional - sage.libs.pari 25 @@ -785,9 +785,9 @@ def subsets(self, size=None): EXAMPLES:: sage: X = Set([1, 2, 3]) - sage: list(X.subsets()) # optional - sage.combinat + sage: list(X.subsets()) [{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}] - sage: list(X.subsets(2)) # optional - sage.combinat + sage: list(X.subsets(2)) [{1, 2}, {1, 3}, {2, 3}] """ from sage.combinat.subset import Subsets @@ -857,13 +857,13 @@ def __init__(self, X, category=None): EXAMPLES:: - sage: S = Set(GF(19)); S # optional - sage.libs.pari + sage: S = Set(GF(19)); S {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} - sage: S.category() # optional - sage.libs.pari + sage: S.category() Category of finite enumerated sets - sage: print(latex(S)) # optional - sage.libs.pari + sage: print(latex(S)) \left\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18\right\} - sage: TestSuite(S).run() # optional - sage.libs.pari + sage: TestSuite(S).run() """ Set_object.__init__(self, X, category=FiniteEnumeratedSets().or_subcategory(category)) @@ -888,7 +888,7 @@ def is_finite(self): EXAMPLES:: - sage: Set(GF(19)).is_finite() # optional - sage.libs.pari + sage: Set(GF(19)).is_finite() True """ return True @@ -920,15 +920,15 @@ def __iter__(self): EXAMPLES:: - sage: S = Set(GF(19)) # optional - sage.libs.pari - sage: I = iter(S) # optional - sage.libs.pari - sage: next(I) # optional - sage.libs.pari + sage: S = Set(GF(19)) + sage: I = iter(S) + sage: next(I) 0 - sage: next(I) # optional - sage.libs.pari + sage: next(I) 1 - sage: next(I) # optional - sage.libs.pari + sage: next(I) 2 - sage: next(I) # optional - sage.libs.pari + sage: next(I) 3 """ return iter(self.set()) @@ -939,8 +939,8 @@ def _latex_(self): EXAMPLES:: - sage: S = Set(GF(2)) # optional - sage.libs.pari - sage: latex(S) # optional - sage.libs.pari + sage: S = Set(GF(2)) + sage: latex(S) \left\{0, 1\right\} """ return '\\left\\{' + ', '.join(latex(x) for x in self.set()) + '\\right\\}' @@ -951,8 +951,8 @@ def _repr_(self): EXAMPLES:: - sage: S = Set(GF(2)) # optional - sage.libs.pari - sage: S # optional - sage.libs.pari + sage: S = Set(GF(2)) + sage: S {0, 1} TESTS:: @@ -1105,7 +1105,7 @@ def issubset(self, other): TESTS:: - sage: len([Z for Z in Y.subsets() if Z.issubset(X)]) # optional - sage.combinat + sage: len([Z for Z in Y.subsets() if Z.issubset(X)]) 8 """ if not isinstance(other, Set_object_enumerated): @@ -1133,7 +1133,7 @@ def issuperset(self, other): TESTS:: - sage: len([Z for Z in Y.subsets() if Z.issuperset(X)]) # optional - sage.combinat + sage: len([Z for Z in Y.subsets() if Z.issuperset(X)]) 4 """ if not isinstance(other, Set_object_enumerated): @@ -1323,7 +1323,7 @@ def _repr_(self): EXAMPLES:: - sage: Set(ZZ).union(Set(GF(5))) # optional - sage.libs.pari + sage: Set(ZZ).union(Set(GF(5))) Set-theoretic union of Set of elements of Integer Ring and {0, 1, 2, 3, 4} """ return "Set-theoretic {} of {} and {}".format(self._op, self._X, self._Y) @@ -1334,7 +1334,7 @@ def _latex_(self): EXAMPLES:: - sage: latex(Set(ZZ).union(Set(GF(5)))) # optional - sage.libs.pari + sage: latex(Set(ZZ).union(Set(GF(5)))) \Bold{Z} \cup \left\{0, 1, 2, 3, 4\right\} """ return latex(self._X) + self._latex_op + latex(self._Y) @@ -1348,9 +1348,9 @@ def __hash__(self): The hash values of equal sets are in general not equal since it is not decidable whether two sets are equal:: - sage: X = Set(GF(13)).intersection(Set(ZZ)) # optional - sage.libs.pari - sage: Y = Set(ZZ).intersection(Set(GF(13))) # optional - sage.libs.pari - sage: hash(X) == hash(Y) # optional - sage.libs.pari + sage: X = Set(GF(13)).intersection(Set(ZZ)) + sage: Y = Set(ZZ).intersection(Set(GF(13))) + sage: hash(X) == hash(Y) False TESTS: @@ -1494,8 +1494,8 @@ def cardinality(self): sage: X.cardinality() # optional - sage.libs.pari 5 - sage: X = Set(GF(3)).union(Set(ZZ)) # optional - sage.libs.pari - sage: X.cardinality() # optional - sage.libs.pari + sage: X = Set(GF(3)).union(Set(ZZ)) + sage: X.cardinality() +Infinity """ return self._X.cardinality() + self._Y.cardinality() @@ -1528,9 +1528,9 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) # optional - sage.modules - sage: T = Set(ZZ) # optional - sage.modules - sage: X = S.intersection(T); X # optional - sage.modules + sage: S = Set(QQ^2) # optional - sage.modules + sage: T = Set(ZZ) + sage: X = S.intersection(T); X # optional - sage.modules Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring From fbd72eb35aea08f7059d2265a882a8e3f712308e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 27 Jun 2023 13:54:02 -0700 Subject: [PATCH 089/225] src/sage/sets/cartesian_product.py: Restore # random --- src/sage/sets/cartesian_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index 87157bc9256..0afdd88ef1a 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -42,7 +42,7 @@ class CartesianProduct(UniqueRepresentation, Parent): (Finite Field of size 5, Standard permutations of 10) sage: G.cardinality() 18144000 - sage: G.random_element() + sage: G.random_element() # random (1, [4, 7, 6, 5, 10, 1, 3, 2, 8, 9]) sage: G.category() Join of Category of finite monoids From cff77b01e1b7f05e38bb0ea7f92d047d155fae35 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 1 Jul 2023 15:42:59 -0700 Subject: [PATCH 090/225] Update # optional / # needs --- src/sage/sets/recursively_enumerated_set.pyx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index 50bcd6ad9fb..094b1d852de 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -394,9 +394,10 @@ def RecursivelyEnumeratedSet(seeds, successors, structure=None, A recursive set given by a graded relation:: - sage: f = lambda a: [a+1, a+I] - sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') - sage: C + sage: # optional - sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] + sage: C = RecursivelyEnumeratedSet([0], f, structure='graded'); C A recursively enumerated set with a graded structure (breadth first search) sage: it = iter(C) sage: [next(it) for _ in range(7)] @@ -1125,7 +1126,9 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Gaussian integers:: - sage: f = lambda a: [a+1, a+I] + sage: # optional - sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] sage: S = RecursivelyEnumeratedSet([0], f, structure='symmetric') sage: it = S.graded_component_iterator() sage: [sorted(next(it)) for _ in range(7)] @@ -1142,6 +1145,7 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Note that interrupting the computation (``KeyboardInterrupt`` for instance) breaks the iterator:: + sage: # optional - sage.symbolic sage: def f(a): ....: sleep(0.05r) ....: return [a-1,a+1] @@ -1411,7 +1415,9 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): EXAMPLES:: - sage: f = lambda a: [a+1, a+I] + sage: # optional - sage.symbolic + sage: def f(a): + ....: return [a + 1, a + I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') sage: for i in range(5): sorted(C.graded_component(i)) [0] @@ -1424,6 +1430,7 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): We make sure that :trac:`21312` is fixed:: + sage: # optional - sage.symbolic sage: def f(a): ....: sleep(0.1r) ....: return [a+1, a+I] From dccc19f9ad53a106d372309fbcc5d926cb4072a6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 2 Jul 2023 01:06:19 -0700 Subject: [PATCH 091/225] Update # optional / # needs --- src/sage/sets/disjoint_set.pyx | 2 +- src/sage/sets/integer_range.py | 2 +- src/sage/sets/set.py | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index edaf98ad5ae..11a17542910 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -122,7 +122,7 @@ def DisjointSet(arg): or an iterable:: - sage: DisjointSet(4.3) + sage: DisjointSet(4.3) # optional - sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: 'sage.rings.real_mpfr.RealLiteral' object is not iterable diff --git a/src/sage/sets/integer_range.py b/src/sage/sets/integer_range.py index 1eeb9681527..984b3edf045 100644 --- a/src/sage/sets/integer_range.py +++ b/src/sage/sets/integer_range.py @@ -217,7 +217,7 @@ def __classcall_private__(cls, begin, end=None, step=Integer(1), middle_point=No ValueError: IntegerRange() step argument must not be zero sage: IntegerRange(2) is IntegerRange(0, 2) True - sage: IntegerRange(1.0) + sage: IntegerRange(1.0) # optional - sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: end must be Integer or Infinity, not <... 'sage.rings.real_mpfr.RealLiteral'> diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 11a99a33a7e..cadbb7fe461 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -117,7 +117,8 @@ def Set(X=None, category=None): :: - sage: d={Set([2*I,1+I]):10} + sage: # needs sage.symbolic + sage: d = {Set([2*I, 1 + I]): 10} sage: d # key is randomly ordered {{I + 1, 2*I}: 10} sage: d[Set([1+I,2*I])] @@ -586,8 +587,8 @@ def _an_element_(self): EXAMPLES:: - sage: R = Set(RR) - sage: R.an_element() # indirect doctest + sage: R = Set(RR) # optional - sage.rings.real_mpfr + sage: R.an_element() # indirect doctest # optional - sage.rings.real_mpfr 1.00000000000000 sage: F = Set([1, 2, 3]) @@ -1185,8 +1186,8 @@ def difference(self, other): sage: X.difference(Y) {3, 4} sage: Z = Set(ZZ) - sage: W = Set([2.5, 4, 5, 6]) - sage: W.difference(Z) + sage: W = Set([2.5, 4, 5, 6]) # optional - sage.rings.real_mpfr + sage: W.difference(Z) # optional - sage.rings.real_mpfr {2.50000000000000} """ if not isinstance(other, Set_object_enumerated): From f752918b2af296151e25b1321e8d1cc240cad9b5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 11:42:30 -0700 Subject: [PATCH 092/225] ./sage -fixdoctests --distribution sagemath-categories --probe all --only-tags src/sage/sets --- src/sage/sets/cartesian_product.py | 12 +- src/sage/sets/condition_set.py | 113 +++++---- src/sage/sets/disjoint_set.pyx | 18 +- .../sets/disjoint_union_enumerated_sets.py | 187 +++++++------- src/sage/sets/family.py | 78 +++--- src/sage/sets/image_set.py | 74 +++--- src/sage/sets/integer_range.py | 2 +- src/sage/sets/non_negative_integers.py | 10 +- src/sage/sets/positive_integers.py | 2 +- src/sage/sets/primes.py | 14 +- src/sage/sets/real_set.py | 93 +++---- src/sage/sets/recursively_enumerated_set.pyx | 36 +-- src/sage/sets/set.py | 229 +++++++++--------- src/sage/sets/set_from_iterator.py | 143 +++++------ src/sage/sets/totally_ordered_finite_set.py | 4 +- 15 files changed, 535 insertions(+), 480 deletions(-) diff --git a/src/sage/sets/cartesian_product.py b/src/sage/sets/cartesian_product.py index 0afdd88ef1a..9d0bb024a12 100644 --- a/src/sage/sets/cartesian_product.py +++ b/src/sage/sets/cartesian_product.py @@ -354,9 +354,9 @@ def __len__(self): EXAMPLES:: - sage: C = cartesian_product([ZZ, QQ, CC]) # optional - sage.rings.real_mpfr - sage: e = C.random_element() # optional - sage.rings.real_mpfr - sage: len(e) # optional - sage.rings.real_mpfr + sage: C = cartesian_product([ZZ, QQ, CC]) # needs sage.rings.real_mpfr + sage: e = C.random_element() # needs sage.rings.real_mpfr + sage: len(e) # needs sage.rings.real_mpfr 3 """ return len(self.value) @@ -367,10 +367,10 @@ def cartesian_factors(self): EXAMPLES:: - sage: A = cartesian_product([ZZ, RR]) # optional - sage.rings.real_mpfr - sage: A((1, 1.23)).cartesian_factors() # optional - sage.rings.real_mpfr + sage: A = cartesian_product([ZZ, RR]) + sage: A((1, 1.23)).cartesian_factors() # needs sage.rings.real_mpfr (1, 1.23000000000000) - sage: type(_) # optional - sage.rings.real_mpfr + sage: type(_) <... 'tuple'> """ return self.value diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 18b88e2b809..ad8c2a8d512 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -62,11 +62,12 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope sage: 7/2 in EvensAndOdds False - sage: var('y') + sage: var('y') # needs sage.symbolic y - sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds + sage: SmallOdds = ConditionSet(ZZ, is_odd, abs(y) <= 11, vars=[y]); SmallOdds # needs sage.symbolic { y ∈ Integer Ring : abs(y) <= 11, (y) } + sage: # needs sage.geometry.polyhedron sage: P = polytopes.cube(); P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices sage: P.rename("P") @@ -74,16 +75,17 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope { x ∈ P : at 0x...>(x) } sage: vector([1, 0, 0]) in P_inter_B True - sage: vector([1, 1, 1]) in P_inter_B # optional - sage.geometry.polyhedron sage.symbolic + sage: vector([1, 1, 1]) in P_inter_B # needs sage.symbolic False + sage: # needs sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 1.2; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 1.20000000000000 - sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic + sage: P_inter_B_again = ConditionSet(P, predicate); P_inter_B_again # needs sage.geometry.polyhedron { (x, y, z) ∈ P : sqrt(x^2 + y^2 + z^2) < 1.20000000000000 } - sage: vector([1, 0, 0]) in P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic + sage: vector([1, 0, 0]) in P_inter_B_again # needs sage.geometry.polyhedron True - sage: vector([1, 1, 1]) in P_inter_B_again # optional - sage.geometry.polyhedron sage.symbolic + sage: vector([1, 1, 1]) in P_inter_B_again # needs sage.geometry.polyhedron False Iterating over subsets determined by predicates:: @@ -104,24 +106,25 @@ class ConditionSet(Set_generic, Set_base, Set_boolean_operators, Set_add_sub_ope Using ``ConditionSet`` without predicates provides a way of attaching variable names to a set:: - sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 # optional - sage.modules - { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring } - sage: Z3.variable_names() # optional - sage.modules + sage: Z3 = ConditionSet(ZZ^3, vars=['x', 'y', 'z']); Z3 # needs sage.modules + { (x, y, z) ∈ Ambient free module of rank 3 + over the principal ideal domain Integer Ring } + sage: Z3.variable_names() # needs sage.modules ('x', 'y', 'z') - sage: Z3.arguments() # optional - sage.modules sage.symbolic + sage: Z3.arguments() # needs sage.modules sage.symbolic (x, y, z) - sage: Q4. = ConditionSet(QQ^4); Q4 # optional - sage.modules sage.symbolic + sage: Q4. = ConditionSet(QQ^4); Q4 # needs sage.modules sage.symbolic { (a, b, c, d) ∈ Vector space of dimension 4 over Rational Field } - sage: Q4.variable_names() # optional - sage.modules sage.symbolic + sage: Q4.variable_names() # needs sage.modules sage.symbolic ('a', 'b', 'c', 'd') - sage: Q4.arguments() # optional - sage.modules sage.symbolic + sage: Q4.arguments() # needs sage.modules sage.symbolic (a, b, c, d) TESTS:: - sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # optional - sage.geometry.polyhedron - sage: TestSuite(P_inter_B_again).run() # optional - sage.geometry.polyhedron sage.symbolic + sage: TestSuite(P_inter_B).run(skip='_test_pickling') # cannot pickle lambdas # needs sage.geometry.polyhedron + sage: TestSuite(P_inter_B_again).run() # needs sage.geometry.polyhedron sage.symbolic """ @staticmethod def __classcall_private__(cls, universe, *predicates, vars=None, names=None, category=None): @@ -130,9 +133,9 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat TESTS:: - sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x) + sage: ConditionSet(ZZ, names=["x"]) is ConditionSet(ZZ, names=x) # needs sage.symbolic True - sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x)) + sage: ConditionSet(RR, x > 0, names=x) is ConditionSet(RR, (x > 0).function(x)) # needs sage.symbolic True """ if category is None: @@ -224,10 +227,10 @@ def _repr_(self): EXAMPLES:: - sage: var('t') # parameter + sage: var('t') # parameter # needs sage.symbolic t - sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) - sage: ZeroDimButNotNullary._repr_() + sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) # needs sage.symbolic + sage: ZeroDimButNotNullary._repr_() # needs sage.symbolic '{ q ∈ Ambient free module of rank 0 over the principal ideal domain Integer Ring : t > 0 }' """ @@ -257,13 +260,13 @@ def _repr_condition(self, predicate): sage: Evens = ConditionSet(ZZ, is_even) sage: Evens._repr_condition(is_even) '(x)' - sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x]) - sage: BigSin._repr_condition(BigSin._predicates[0]) + sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x]) # needs sage.symbolic + sage: BigSin._repr_condition(BigSin._predicates[0]) # needs sage.symbolic 'sin(x) > 0.900000000000000' - sage: var('t') # parameter + sage: var('t') # parameter # needs sage.symbolic t - sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) - sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0]) + sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) # needs sage.symbolic + sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0]) # needs sage.symbolic 't > 0' """ if isinstance(predicate, Expression) and predicate.is_callable(): @@ -285,9 +288,9 @@ def arguments(self): sage: Odds = ConditionSet(ZZ, is_odd); Odds { x ∈ Integer Ring : (x) } - sage: args = Odds.arguments(); args + sage: args = Odds.arguments(); args # needs sage.symbolic (x,) - sage: args[0].parent() + sage: args[0].parent() # needs sage.symbolic Symbolic Ring """ from sage.symbolic.ring import SR @@ -339,24 +342,24 @@ def _call_predicate(self, predicate, element): TESTS:: - sage: TripleDigits = ZZ^3 - sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate + sage: TripleDigits = ZZ^3 # needs sage.modules + sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate # needs sage.symbolic (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 - sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples + sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples # needs sage.symbolic { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: predicate = SmallTriples._predicates[0] # optional - sage.symbolic - sage: element = TripleDigits((1, 2, 3)) # optional - sage.modules - sage: SmallTriples._call_predicate(predicate, element) # optional - sage.modules sage.symbolic + sage: predicate = SmallTriples._predicates[0] # needs sage.symbolic + sage: element = TripleDigits((1, 2, 3)) # needs sage.modules + sage: SmallTriples._call_predicate(predicate, element) # needs sage.modules sage.symbolic sqrt(14) < 12 - sage: var('t') + sage: var('t') # needs sage.symbolic t - sage: TinyUniverse = ZZ^0 # optional - sage.modules - sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) # optional - sage.modules sage.symbolic - sage: predicate = Nullary._predicates[0] # optional - sage.modules sage.symbolic - sage: element = TinyUniverse(0) # optional - sage.modules - sage: Nullary._call_predicate(predicate, element) # optional - sage.modules sage.symbolic + sage: TinyUniverse = ZZ^0 # needs sage.modules + sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) # needs sage.modules sage.symbolic + sage: predicate = Nullary._predicates[0] # needs sage.modules sage.symbolic + sage: element = TinyUniverse(0) # needs sage.modules + sage: Nullary._call_predicate(predicate, element) # needs sage.modules sage.symbolic t > 0 """ if isinstance(predicate, Expression) and predicate.is_callable(): @@ -372,13 +375,13 @@ def _an_element_(self): TESTS:: - sage: TripleDigits = ZZ^3 - sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate + sage: TripleDigits = ZZ^3 # needs sage.modules + sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate # needs sage.symbolic (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 - sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples + sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples # needs sage.symbolic { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: SmallTriples.an_element() # indirect doctest + sage: SmallTriples.an_element() # indirect doctest # needs sage.symbolic (1, 0, 0) """ for element in self._universe.some_elements(): @@ -406,6 +409,7 @@ def _sympy_(self): EXAMPLES:: + sage: # needs sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples @@ -419,9 +423,9 @@ def _sympy_(self): sage: (5, 7, 9) in ST False - sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval # optional - sage.symbolic + sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval # needs sage.symbolic { x ∈ Real Field with 53 bits of precision : x >= -7, x <= 4 } - sage: Interval._sympy_() # optional - sage.symbolic sympy + sage: Interval._sympy_() # needs sympy sage.symbolic ConditionSet(x, (x >= -7) & (x <= 4), SageSet(Real Field with 53 bits of precision)) @@ -429,7 +433,7 @@ def _sympy_(self): sage: Evens = ConditionSet(ZZ, is_even); Evens { x ∈ Integer Ring : (x) } - sage: Evens._sympy_() # optional - sage.symbolic sympy + sage: Evens._sympy_() # needs sympy sage.symbolic SageSet({ x ∈ Integer Ring : (x) }) """ from sage.interfaces.sympy import sympy_init @@ -464,10 +468,12 @@ def intersection(self, X): EXAMPLES:: + sage: # needs sage.symbolic sage: in_small_oblong(x, y) = x^2 + 3 * y^2 <= 42 sage: SmallOblongUniverse = ConditionSet(QQ^2, in_small_oblong) sage: SmallOblongUniverse - { (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 } + { (x, y) ∈ Vector space of dimension 2 + over Rational Field : x^2 + 3*y^2 <= 42 } sage: parity_check(x, y) = abs(sin(pi/2*(x + y))) < 1/1000 sage: EvenUniverse = ConditionSet(ZZ^2, parity_check); EvenUniverse { (x, y) ∈ Ambient free module of rank 2 over the principal ideal @@ -481,13 +487,18 @@ def intersection(self, X): Combining two ``ConditionSet``s with different formal variables works correctly. The formal variables of the intersection are taken from ``self``:: - sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, vars=(y, x)) + sage: # needs sage.symbolic + sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, + ....: vars=(y, x)) sage: SmallMirrorUniverse - { (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 } + { (y, x) ∈ Vector space of dimension 2 + over Rational Field : 3*x^2 + y^2 <= 42 } sage: SmallOblongUniverse & SmallMirrorUniverse - { (x, y) ∈ Vector space of dimension 2 over Rational Field : x^2 + 3*y^2 <= 42 } + { (x, y) ∈ Vector space of dimension 2 + over Rational Field : x^2 + 3*y^2 <= 42 } sage: SmallMirrorUniverse & SmallOblongUniverse - { (y, x) ∈ Vector space of dimension 2 over Rational Field : 3*x^2 + y^2 <= 42 } + { (y, x) ∈ Vector space of dimension 2 + over Rational Field : 3*x^2 + y^2 <= 42 } """ if isinstance(X, ConditionSet): return ConditionSet(self.ambient().intersection(X.ambient()), diff --git a/src/sage/sets/disjoint_set.pyx b/src/sage/sets/disjoint_set.pyx index 11a17542910..4db91f4f058 100644 --- a/src/sage/sets/disjoint_set.pyx +++ b/src/sage/sets/disjoint_set.pyx @@ -122,7 +122,7 @@ def DisjointSet(arg): or an iterable:: - sage: DisjointSet(4.3) # optional - sage.rings.real_mpfr + sage: DisjointSet(4.3) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: 'sage.rings.real_mpfr.RealLiteral' object is not iterable @@ -561,7 +561,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(4,1) sage: e = d.element_to_root_dict(); e {0: 0, 1: 4, 2: 2, 3: 2, 4: 4} - sage: WordMorphism(e) # optional - sage.combinat + sage: WordMorphism(e) # needs sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} @@ -583,9 +583,9 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g # optional - sage.graphs + sage: g = d.to_digraph(); g # needs sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: @@ -596,7 +596,7 @@ cdef class DisjointSet_of_integers(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) # optional - sage.graphs + sage: d.to_digraph().edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {i: [self._nodes.parent[i]] for i in range(self.cardinality())} @@ -849,7 +849,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: e = d.element_to_root_dict() sage: sorted(e.items()) [(0, 0), (1, 4), (2, 2), (3, 2), (4, 4)] - sage: WordMorphism(e) # optional - sage.combinat + sage: WordMorphism(e) # needs sage.combinat WordMorphism: 0->0, 1->4, 2->2, 3->2, 4->4 """ d = {} @@ -870,9 +870,9 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(3,4) sage: d {{0}, {1, 2, 3, 4}} - sage: g = d.to_digraph(); g # optional - sage.graphs + sage: g = d.to_digraph(); g # needs sage.graphs Looped digraph on 5 vertices - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 2, None), (2, 2, None), (3, 2, None), (4, 2, None)] The result depends on the ordering of the union:: @@ -883,7 +883,7 @@ cdef class DisjointSet_of_hashables(DisjointSet_class): sage: d.union(1,4) sage: d {{0}, {1, 2, 3, 4}} - sage: d.to_digraph().edges(sort=True) # optional - sage.graphs + sage: d.to_digraph().edges(sort=True) # needs sage.graphs [(0, 0, None), (1, 1, None), (2, 1, None), (3, 1, None), (4, 1, None)] """ d = {} diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index aa51ebe7fd0..2375f4d191a 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -90,32 +90,34 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): In general the input can be any family:: - sage: U3 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: # needs sage.combinat + sage: U3 = DisjointUnionEnumeratedSets( ....: Family([2,3,4], Permutations, lazy=True)) - sage: U3 # optional - sage.combinat + sage: U3 Disjoint union of Lazy family ((i))_{i in [2, 3, 4]} - sage: U3.cardinality() # optional - sage.combinat + sage: U3.cardinality() 32 - sage: it = iter(U3) # optional - sage.combinat - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat + sage: it = iter(U3) + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[1, 2], [2, 1], [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1]] - sage: U3.unrank(18) # optional - sage.combinat + sage: U3.unrank(18) [2, 4, 1, 3] This allows for infinite unions:: - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: # needs sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations)) - sage: U4 # optional - sage.combinat + sage: U4 Disjoint union of Lazy family ((i))_{i in Non negative integers} - sage: U4.cardinality() # optional - sage.combinat + sage: U4.cardinality() +Infinity - sage: it = iter(U4) # optional - sage.combinat - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat + sage: it = iter(U4) + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: U4.unrank(18) # optional - sage.combinat + sage: U4.unrank(18) [2, 3, 1, 4] .. WARNING:: @@ -128,41 +130,43 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): We demonstrate the ``keepkey`` option:: - sage: Ukeep = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: # needs sage.combinat + sage: Ukeep = DisjointUnionEnumeratedSets( ....: Family(list(range(4)), Permutations), keepkey=True) - sage: it = iter(Ukeep) # optional - sage.combinat - sage: [next(it) for i in range(6)] # optional - sage.combinat + sage: it = iter(Ukeep) + sage: [next(it) for i in range(6)] [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: type(next(it)[1]) # optional - sage.combinat + sage: type(next(it)[1]) We now demonstrate the ``facade`` option:: - sage: UNoFacade = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: # needs sage.combinat + sage: UNoFacade = DisjointUnionEnumeratedSets( ....: Family(list(range(4)), Permutations), facade=False) - sage: it = iter(UNoFacade) # optional - sage.combinat - sage: [next(it) for i in range(6)] # optional - sage.combinat + sage: it = iter(UNoFacade) + sage: [next(it) for i in range(6)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: el = next(it); el # optional - sage.combinat + sage: el = next(it); el [2, 1, 3] - sage: type(el) # optional - sage.combinat + sage: type(el) <... 'sage.structure.element_wrapper.ElementWrapper'> - sage: el.parent() == UNoFacade # optional - sage.combinat + sage: el.parent() == UNoFacade True - sage: elv = el.value; elv # optional - sage.combinat + sage: elv = el.value; elv [2, 1, 3] - sage: type(elv) # optional - sage.combinat + sage: type(elv) The elements ``el`` of the disjoint union are simple wrapped elements. So to access the methods, you need to do ``el.value``:: - sage: el[0] # optional - sage.combinat + sage: el[0] # needs sage.combinat Traceback (most recent call last): ... TypeError: 'sage.structure.element_wrapper.ElementWrapper' object is not subscriptable - sage: el.value[0] # optional - sage.combinat + sage: el.value[0] # needs sage.combinat 2 Possible extensions: the current enumeration order is not suitable @@ -184,12 +188,12 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): :class:`DisjointUnionEnumeratedSets`. Then, one simply writes the ``__init__`` method as usual:: - sage: class MyUnion(DisjointUnionEnumeratedSets): # optional - sage.combinat + sage: class MyUnion(DisjointUnionEnumeratedSets): ....: def __init__(self): ....: DisjointUnionEnumeratedSets.__init__(self, ....: Family([1,2], Permutations)) - sage: pp = MyUnion() # optional - sage.combinat - sage: pp.list() # optional - sage.combinat + sage: pp = MyUnion() + sage: pp.list() [[1], [1, 2], [2, 1]] In case the :meth:`__init__` method takes optional arguments, @@ -204,37 +208,37 @@ class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): sage: class UnionOfSpecialSets(DisjointUnionEnumeratedSets): ....: __classcall_private__ = staticmethod(DisjointUnionEnumeratedSets.__classcall_private__) - sage: psp = UnionOfSpecialSets(Family([1,2], Permutations)) # optional - sage.combinat - sage: psp.list() # optional - sage.combinat + sage: psp = UnionOfSpecialSets(Family([1,2], Permutations)) + sage: psp.list() [[1], [1, 2], [2, 1]] TESTS:: sage: TestSuite(U1).run() sage: TestSuite(U2).run() - sage: TestSuite(U3).run() # optional - sage.combinat - sage: TestSuite(U4).run() # optional - sage.combinat + sage: TestSuite(U3).run() # needs sage.combinat + sage: TestSuite(U4).run() # needs sage.combinat doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union The default implementation of __contains__ can loop forever. Please overload it. - sage: TestSuite(UNoFacade).run() # optional - sage.combinat + sage: TestSuite(UNoFacade).run() # needs sage.combinat We skip ``_test_an_element`` because the coercion framework does not currently allow a tuple to be returned for facade parents:: - sage: TestSuite(Ukeep).run(skip="_test_an_element") # optional - sage.combinat + sage: TestSuite(Ukeep).run(skip="_test_an_element") # needs sage.combinat The following three lines are required for the pickling tests, because the classes ``MyUnion`` and ``UnionOfSpecialSets`` have been defined interactively:: sage: import __main__ - sage: __main__.MyUnion = MyUnion # optional - sage.combinat + sage: __main__.MyUnion = MyUnion sage: __main__.UnionOfSpecialSets = UnionOfSpecialSets - sage: TestSuite(pp).run() # optional - sage.combinat - sage: TestSuite(psp).run() # optional - sage.combinat + sage: TestSuite(pp).run() + sage: TestSuite(psp).run() """ @@ -277,8 +281,8 @@ def __init__(self, family, facade=True, keepkey=False, category=None): ....: 2: FiniteEnumeratedSet([4,5,6])}) sage: TestSuite(U).run() - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # optional - sage.combinat sage.libs.flint - sage: TestSuite(X).run() # optional - sage.combinat sage.libs.flint + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) for i in range(5)}) # needs sage.combinat sage.libs.flint + sage: TestSuite(X).run() # needs sage.combinat sage.libs.flint """ self._family = family self._facade = facade @@ -327,9 +331,9 @@ def _is_a(self, x): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Compositions)) - sage: U4._is_a(Composition([3,2,1,1])) # optional - sage.combinat + sage: U4._is_a(Composition([3,2,1,1])) doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union @@ -358,9 +362,9 @@ def __contains__(self, x): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( # needs sage.combinat ....: Family(NonNegativeIntegers(), Partitions)) - sage: Partition([]) in U4 # optional - sage.combinat + sage: Partition([]) in U4 # needs sage.combinat doctest:...: UserWarning: Disjoint union of Lazy family ((i))_{i in Non negative integers} is an infinite union @@ -370,7 +374,7 @@ def __contains__(self, x): Note: one has to use a different family from the previous one in this file otherwise the warning is not re-issued:: - sage: Partition([3,2,1,1]) in U4 # optional - sage.combinat + sage: Partition([3,2,1,1]) in U4 # needs sage.combinat True The following call will loop forever:: @@ -389,21 +393,22 @@ def __iter__(self): """ TESTS:: - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations)) - sage: it = iter(U4) # optional - sage.combinat - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat + sage: it = iter(U4) + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [[], [1], [1, 2], [2, 1], [1, 2, 3], [1, 3, 2]] - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: # needs sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations), ....: keepkey=True, facade=False) - sage: it = iter(U4) # optional - sage.combinat - sage: [next(it), next(it), next(it), next(it), next(it), next(it)] # optional - sage.combinat + sage: it = iter(U4) + sage: [next(it), next(it), next(it), next(it), next(it), next(it)] [(0, []), (1, [1]), (2, [1, 2]), (2, [2, 1]), (3, [1, 2, 3]), (3, [1, 3, 2])] - sage: el = next(it); el.parent() == U4 # optional - sage.combinat + sage: el = next(it); el.parent() == U4 True - sage: el.value == (3, Permutation([2,1,3])) # optional - sage.combinat + sage: el.value == (3, Permutation([2,1,3])) True """ for k in self._family.keys(): @@ -422,9 +427,9 @@ def an_element(self): EXAMPLES:: - sage: U4 = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U4 = DisjointUnionEnumeratedSets( ....: Family([3, 5, 7], Permutations)) - sage: U4.an_element() # optional - sage.combinat + sage: U4.an_element() [1, 2, 3] """ return self._an_element_from_iterator() @@ -439,16 +444,16 @@ def cardinality(self): For finite disjoint unions, the cardinality is computed by summing the cardinalities of the enumerated sets:: - sage: U = DisjointUnionEnumeratedSets(Family([0,1,2,3], Permutations)) # optional - sage.combinat - sage: U.cardinality() # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets(Family([0,1,2,3], Permutations)) + sage: U.cardinality() 10 For infinite disjoint unions, this makes the assumption that the result is infinite:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat + sage: U = DisjointUnionEnumeratedSets( ....: Family(NonNegativeIntegers(), Permutations)) - sage: U.cardinality() # optional - sage.combinat + sage: U.cardinality() +Infinity .. WARNING:: @@ -471,14 +476,15 @@ def _element_constructor_(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) - sage: U._element_constructor_ # optional - sage.combinat sage.libs.flint + sage: U._element_constructor_ - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=True) - sage: U._element_constructor_ # optional - sage.combinat sage.libs.flint + sage: U._element_constructor_ """ @@ -491,13 +497,14 @@ def _element_constructor_default(self, el): r""" TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) - sage: U([1]) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U([1]) # indirect doctest [1] - sage: U([2,1]) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U([2,1]) # indirect doctest [2, 1] - sage: U([1,3,2]) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U([1,3,2]) # indirect doctest Traceback (most recent call last): ... ValueError: value [1, 3, 2] does not belong to Disjoint union of @@ -505,13 +512,14 @@ def _element_constructor_default(self, el): 2: Partitions of the integer 2, 3: Partitions of the integer 3} - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), keepkey=True, facade=False) - sage: U((1, [1])) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U((1, [1])) # indirect doctest (1, [1]) - sage: U((3,[2,1])) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U((3,[2,1])) # indirect doctest (3, [2, 1]) - sage: U((4,[2,1])) # indirect doctest # optional - sage.combinat sage.libs.flint + sage: U((4,[2,1])) # indirect doctest Traceback (most recent call last): ... ValueError: value (4, [2, 1]) does not belong to Disjoint union of @@ -530,13 +538,14 @@ def _element_constructor_facade(self, el): """ TESTS:: - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) ....: for i in range(5)}) - sage: X([1]).parent() # optional - sage.combinat sage.libs.flint + sage: X([1]).parent() Partitions of the integer 1 - sage: X([2,1,1]).parent() # indirect doctest # optional - sage.combinat sage.libs.flint + sage: X([2,1,1]).parent() # indirect doctest Partitions of the integer 4 - sage: X([6]) # optional - sage.combinat sage.libs.flint + sage: X([6]) Traceback (most recent call last): ... ValueError: cannot coerce `[6]` in any parent in `Finite family {...}` @@ -545,24 +554,25 @@ def _element_constructor_facade(self, el): because this returns a `tuple`, where the coercion framework requires an :class:`Element` be returned. - sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # optional - sage.combinat sage.libs.flint + sage: X = DisjointUnionEnumeratedSets({i: Partitions(i) # needs sage.combinat sage.libs.flint ....: for i in range(5)}, ....: keepkey=True) - sage: p = X._element_constructor_((0, [])) # indirect doctest # optional - sage.combinat sage.libs.flint - sage: p[1].parent() # optional - sage.combinat sage.libs.flint + sage: p = X._element_constructor_((0, [])) # indirect doctest # needs sage.combinat sage.libs.flint + sage: p[1].parent() # needs sage.combinat sage.libs.flint Partitions of the integer 0 Test that facade parents can create and properly access elements that are tuples (fixed by :trac:`22382`):: - sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: f = lambda mu: cartesian_product([mu.standard_tableaux(), ....: mu.standard_tableaux()]) - sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) # optional - sage.combinat sage.libs.flint - sage: s = StandardTableau([[1,3],[2,4]]) # optional - sage.combinat sage.libs.flint - sage: (s,s) in tabs # optional - sage.combinat sage.libs.flint + sage: tabs = DisjointUnionEnumeratedSets(Family(Partitions(4), f)) + sage: s = StandardTableau([[1,3],[2,4]]) + sage: (s,s) in tabs True - sage: ss = tabs( (s,s) ) # optional - sage.combinat sage.libs.flint - sage: ss[0] # optional - sage.combinat sage.libs.flint + sage: ss = tabs( (s,s) ) + sage: ss[0] [[1, 3], [2, 4]] We do not coerce when one of the elements is already in the set:: @@ -598,13 +608,14 @@ def Element(self): """ TESTS:: - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: # needs sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) - sage: U.Element # optional - sage.combinat sage.libs.flint + sage: U.Element <... 'sage.structure.element_wrapper.ElementWrapper'> - sage: U = DisjointUnionEnumeratedSets( # optional - sage.combinat sage.libs.flint + sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=True) - sage: U.Element # optional - sage.combinat sage.libs.flint + sage: U.Element Traceback (most recent call last): ... AttributeError: 'DisjointUnionEnumeratedSets_with_category' object diff --git a/src/sage/sets/family.py b/src/sage/sets/family.py index 3e3676c2d03..6c007a96835 100644 --- a/src/sage/sets/family.py +++ b/src/sage/sets/family.py @@ -17,8 +17,8 @@ Check :trac:`12482` (shall be run in a fresh session):: - sage: P = Partitions(3) # optional - sage.combinat - sage: Family(P, lambda x: x).category() # optional - sage.combinat + sage: P = Partitions(3) # needs sage.combinat + sage: Family(P, lambda x: x).category() # needs sage.combinat Category of finite enumerated sets """ @@ -185,10 +185,10 @@ def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=Fa Beware that for those kind of families len(f) is not supposed to work. As a replacement, use the .cardinality() method:: - sage: f = Family(Permutations(3), attrcall("to_lehmer_code")) # optional - sage.combinat - sage: list(f) # optional - sage.combinat + sage: f = Family(Permutations(3), attrcall("to_lehmer_code")) + sage: list(f) [[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0], [2, 0, 0], [2, 1, 0]] - sage: f.cardinality() # optional - sage.combinat + sage: f.cardinality() 6 Caveat: Only certain families with lazy behavior can be pickled. In @@ -196,14 +196,14 @@ def Family(indices, function=None, hidden_keys=[], hidden_function=None, lazy=Fa and unpickle_function (in sage.misc.fpickle) will correctly unpickle. The following two work:: - sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f # optional - sage.combinat + sage: f = Family(Permutations(3), lambda p: p.to_lehmer_code()); f Lazy family ((i))_{i in Standard permutations of 3} - sage: f == loads(dumps(f)) # optional - sage.combinat + sage: f == loads(dumps(f)) True - sage: f = Family(Permutations(3), attrcall("to_lehmer_code")); f # optional - sage.combinat + sage: f = Family(Permutations(3), attrcall("to_lehmer_code")); f Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3} - sage: f == loads(dumps(f)) # optional - sage.combinat + sage: f == loads(dumps(f)) True But this one does not:: @@ -1056,7 +1056,7 @@ def _repr_(self): sage: f = LazyFamily([3,4,7], fun); f Lazy family (fun(i))_{i in [3, 4, 7]} - sage: f = Family(Permutations(3), attrcall("to_lehmer_code"), lazy=True); f # optional - sage.combinat + sage: f = Family(Permutations(3), attrcall("to_lehmer_code"), lazy=True); f Lazy family (i.to_lehmer_code())_{i in Standard permutations of 3} sage: f = LazyFamily([3,4,7], lambda i: 2*i); f @@ -1069,7 +1069,7 @@ def _repr_(self): Check that using a class as the function is correctly handled:: - sage: Family(NonNegativeIntegers(), PerfectMatchings) # optional - sage.combinat + sage: Family(NonNegativeIntegers(), PerfectMatchings) # needs sage.combinat Lazy family ((i))_{i in Non negative integers} """ if self.function_name is not None: @@ -1187,12 +1187,12 @@ def __getstate__(self): sage: d['set'] [3, 4, 7] - sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()) # optional - sage.combinat - sage: f == loads(dumps(f)) # optional - sage.combinat + sage: f = LazyFamily(Permutations(3), lambda p: p.to_lehmer_code()) + sage: f == loads(dumps(f)) True - sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) # optional - sage.combinat - sage: f == loads(dumps(f)) # optional - sage.combinat + sage: f = LazyFamily(Permutations(3), attrcall("to_lehmer_code")) + sage: f == loads(dumps(f)) True """ f = self.function @@ -1417,8 +1417,8 @@ def __init__(self, enumset): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat - sage: TestSuite(f).run() # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(3)) + sage: TestSuite(f).run() sage: f = Family(NonNegativeIntegers()) sage: TestSuite(f).run() @@ -1428,12 +1428,12 @@ def __init__(self, enumset): Check that category and keys are set correctly (:trac:`28274`):: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(4)) # optional - sage.combinat - sage: f.category() # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(4)) + sage: f.category() Category of finite enumerated sets - sage: list(f.keys()) == list(range(f.cardinality())) # optional - sage.combinat + sage: list(f.keys()) == list(range(f.cardinality())) True - sage: Family(Permutations()).keys() # optional - sage.combinat + sage: Family(Permutations()).keys() Non negative integers sage: type(Family(NN)) @@ -1449,9 +1449,9 @@ def __eq__(self, other): """ EXAMPLES:: - sage: f = Family(Permutations(3)) # optional - sage.combinat - sage: g = Family(Permutations(3)) # optional - sage.combinat - sage: f == g # optional - sage.combinat + sage: f = Family(Permutations(3)) + sage: g = Family(Permutations(3)) + sage: f == g True """ return (isinstance(other, self.__class__) and @@ -1461,7 +1461,7 @@ def __repr__(self): """ EXAMPLES:: - sage: f = Family(Permutations(3)); f # indirect doctest # optional - sage.combinat + sage: f = Family(Permutations(3)); f # indirect doctest Family (Standard permutations of 3) sage: f = Family(NonNegativeIntegers()); f @@ -1476,8 +1476,8 @@ def __contains__(self, x): """ EXAMPLES:: - sage: f = Family(Permutations(3)) # optional - sage.combinat - sage: [2,1,3] in f # optional - sage.combinat + sage: f = Family(Permutations(3)) + sage: [2,1,3] in f True """ return x in self.enumset @@ -1489,8 +1489,8 @@ def cardinality(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat - sage: f.cardinality() # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(3)) + sage: f.cardinality() 6 sage: f = Family(NonNegativeIntegers()) @@ -1504,8 +1504,8 @@ def __iter__(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat - sage: [i for i in f] # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(3)) + sage: [i for i in f] [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ for i in self.enumset: @@ -1516,8 +1516,8 @@ def __getitem__(self, i): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat - sage: f[1] # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(3)) + sage: f[1] [1, 3, 2] """ return self.enumset.unrank(i) @@ -1527,10 +1527,10 @@ def __getstate__(self): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(3)) # optional - sage.combinat - sage: f.__getstate__() # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(3)) + sage: f.__getstate__() {'enumset': Standard permutations of 3} - sage: loads(dumps(f)) == f # optional - sage.combinat + sage: loads(dumps(f)) == f True """ return {'enumset': self.enumset} @@ -1540,9 +1540,9 @@ def __setstate__(self, state): EXAMPLES:: sage: from sage.sets.family import EnumeratedFamily - sage: f = EnumeratedFamily(Permutations(0)) # optional - sage.combinat - sage: f.__setstate__({'enumset': Permutations(3)}) # optional - sage.combinat - sage: f # optional - sage.combinat + sage: f = EnumeratedFamily(Permutations(0)) + sage: f.__setstate__({'enumset': Permutations(3)}) + sage: f Family (Standard permutations of 3) """ self.__init__(state['enumset']) diff --git a/src/sage/sets/image_set.py b/src/sage/sets/image_set.py index 74a99c65641..4ad2d76a0a3 100644 --- a/src/sage/sets/image_set.py +++ b/src/sage/sets/image_set.py @@ -73,12 +73,12 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None, inve EXAMPLES:: - sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) # optional - sage.modules + sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) # needs sage.modules sage: R. = QQ[] - sage: H = Hom(M, R, category=Sets()) # optional - sage.modules - sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) # optional - sage.modules - sage: Im = f.image() # optional - sage.modules - sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', # optional - sage.modules + sage: H = Hom(M, R, category=Sets()) # needs sage.modules + sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) # needs sage.modules + sage: Im = f.image() # needs sage.modules + sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', # needs sage.modules ....: '_test_some_elements', '_test_elements']) """ if not is_Parent(domain_subset): @@ -173,16 +173,17 @@ def ambient(self): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules - sage: R. = ZZ[] # optional - sage.modules - sage: H = Hom(M, R, category=Sets()) # optional - sage.modules - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules - sage: Im = f.image() # optional - sage.modules - sage: Im.ambient() is R # optional - sage.modules + sage: # needs sage.modules + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) + sage: R. = ZZ[] + sage: H = Hom(M, R, category=Sets()) + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) + sage: Im = f.image() + sage: Im.ambient() is R True - sage: P = Partitions(3).map(attrcall('conjugate')) - sage: P.ambient() is None + sage: P = Partitions(3).map(attrcall('conjugate')) # needs sage.combinat + sage: P.ambient() is None # needs sage.combinat True sage: R = Permutations(10).map(attrcall('reduced_word')) @@ -197,14 +198,14 @@ def lift(self, x): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # needs sage.modules sage: R. = ZZ[] - sage: H = Hom(M, R, category=Sets()) # optional - sage.modules - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules - sage: Im = f.image() # optional - sage.modules - sage: p = Im.lift(Im.an_element()); p # optional - sage.modules + sage: H = Hom(M, R, category=Sets()) # needs sage.modules + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # needs sage.modules + sage: Im = f.image() # needs sage.modules + sage: p = Im.lift(Im.an_element()); p # needs sage.modules 2*x - 4 - sage: p.parent() is R # optional - sage.modules + sage: p.parent() is R # needs sage.modules True """ return x @@ -219,13 +220,14 @@ def retract(self, x): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # optional - sage.modules - sage: R. = ZZ[] # optional - sage.modules - sage: H = Hom(M, R, category=Sets()) # optional - sage.modules - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # optional - sage.modules - sage: Im = f.image() # optional - sage.modules - sage: p = 2 * x - 4 # optional - sage.modules - sage: Im.retract(p).parent() # optional - sage.modules + sage: # needs sage.modules + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) + sage: R. = ZZ[] + sage: H = Hom(M, R, category=Sets()) + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) + sage: Im = f.image() + sage: p = 2 * x - 4 + sage: Im.retract(p).parent() Multivariate Polynomial Ring in x, y over Integer Ring """ return x @@ -234,7 +236,7 @@ def _repr_(self) -> str: r""" TESTS:: - sage: Partitions(3).map(attrcall('conjugate')) + sage: Partitions(3).map(attrcall('conjugate')) # needs sage.combinat Image of Partitions of the integer 3 by The map *.conjugate() from Partitions of the integer 3 """ @@ -251,8 +253,8 @@ def cardinality(self) -> Integer: :meth:`~sage.categories.enumerated_sets.EnumeratedSets.ParentMethods.map` defaults to ``is_injective=True``): - sage: R = Permutations(10).map(attrcall('reduced_word')) # optional - sage.combinat - sage: R.cardinality() # optional - sage.combinat + sage: R = Permutations(10).map(attrcall('reduced_word')) + sage: R.cardinality() 3628800 sage: Evens = ZZ.map(lambda x: 2 * x) @@ -294,6 +296,7 @@ def __iter__(self) -> Iterator: EXAMPLES:: + sage: # needs sage.combinat sage: P = Partitions() sage: H = Hom(P, ZZ) sage: f = H(ZZ.sum) @@ -322,8 +325,8 @@ def _an_element_(self): EXAMPLES:: - sage: R = SymmetricGroup(10).map(attrcall('reduced_word')) - sage: R.an_element() + sage: R = SymmetricGroup(10).map(attrcall('reduced_word')) # needs sage.groups + sage: R.an_element() # needs sage.groups [9, 8, 7, 6, 5, 4, 3, 2] """ domain_element = self._domain_subset.an_element() @@ -336,9 +339,9 @@ def _sympy_(self): EXAMPLES:: sage: from sage.sets.image_set import ImageSet - sage: S = ImageSet(sin, RealSet.open(0, pi/4)); S + sage: S = ImageSet(sin, RealSet.open(0, pi/4)); S # needs sage.symbolic Image of (0, 1/4*pi) by The map sin from (0, 1/4*pi) - sage: S._sympy_() + sage: S._sympy_() # needs sage.symbolic ImageSet(Lambda(x, sin(x)), Interval.open(0, pi/4)) """ from sympy import imageset @@ -360,11 +363,12 @@ class ImageSet(ImageSubobject, Set_base, Set_add_sub_operators, Set_boolean_oper Symbolics:: - sage: ImageSet(sin, RealSet.open(0, pi/4)) + sage: ImageSet(sin, RealSet.open(0, pi/4)) # needs sage.symbolic Image of (0, 1/4*pi) by The map sin from (0, 1/4*pi) - sage: _.an_element() + sage: _.an_element() # needs sage.symbolic 1/2*sqrt(-sqrt(2) + 2) + sage: # needs sage.symbolic sage: sos(x,y) = x^2 + y^2; sos (x, y) |--> x^2 + y^2 sage: ImageSet(sos, ZZ^2) diff --git a/src/sage/sets/integer_range.py b/src/sage/sets/integer_range.py index 984b3edf045..d42f77a5307 100644 --- a/src/sage/sets/integer_range.py +++ b/src/sage/sets/integer_range.py @@ -217,7 +217,7 @@ def __classcall_private__(cls, begin, end=None, step=Integer(1), middle_point=No ValueError: IntegerRange() step argument must not be zero sage: IntegerRange(2) is IntegerRange(0, 2) True - sage: IntegerRange(1.0) # optional - sage.rings.real_mpfr + sage: IntegerRange(1.0) # needs sage.rings.real_mpfr Traceback (most recent call last): ... TypeError: end must be Integer or Infinity, not <... 'sage.rings.real_mpfr.RealLiteral'> diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 72601250a97..8eb83f3dfc1 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -102,15 +102,15 @@ def __contains__(self, elt): True sage: -1 in NN False - sage: x in NN # optional - sage.symbolic + sage: x in NN # needs sage.symbolic False sage: None in NN False - sage: QQbar(sqrt(2)) in NN # optional - sage.symbolic sage.rings.number_field + sage: QQbar(sqrt(2)) in NN # needs sage.rings.number_field sage.symbolic False sage: RIF(1,2) in NN False - sage: QQbar(2) in NN # optional - sage.rings.number_field + sage: QQbar(2) in NN # needs sage.rings.number_field True sage: RIF(2) in NN True @@ -135,7 +135,7 @@ def _element_constructor_(self, i): Traceback (most recent call last): ... ValueError: Value -5 in not in Non negative integers. - sage: NN._element_constructor_(x) # optional - sage.symbolic + sage: NN._element_constructor_(x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: Value x in not in Non negative integers. @@ -231,7 +231,7 @@ def _sympy_(self): EXAMPLES:: sage: NN = NonNegativeIntegers() - sage: NN._sympy_() # optional - sympy + sage: NN._sympy_() # needs sympy Naturals0 """ from sympy import Naturals0 diff --git a/src/sage/sets/positive_integers.py b/src/sage/sets/positive_integers.py index 26bf71a9cae..70625fb53b7 100644 --- a/src/sage/sets/positive_integers.py +++ b/src/sage/sets/positive_integers.py @@ -83,7 +83,7 @@ def _sympy_(self): EXAMPLES:: - sage: PositiveIntegers()._sympy_() # optional - sympy + sage: PositiveIntegers()._sympy_() # needs sympy Naturals """ from sympy import Naturals diff --git a/src/sage/sets/primes.py b/src/sage/sets/primes.py index b95ed278e45..ac33901a73b 100644 --- a/src/sage/sets/primes.py +++ b/src/sage/sets/primes.py @@ -73,11 +73,11 @@ def __init__(self, proof): sage: P.category() Category of facade infinite enumerated sets - sage: TestSuite(P).run() # optional - sage.libs.pari + sage: TestSuite(P).run() # needs sage.libs.pari sage: Q.category() Category of facade infinite enumerated sets - sage: TestSuite(Q).run() # optional - sage.libs.pari + sage: TestSuite(Q).run() # needs sage.libs.pari The set of primes can be compared to various things, but is only equal to itself:: @@ -123,7 +123,7 @@ def __contains__(self, x): False sage: 1.5 in P False - sage: e in P # optional - sage.symbolic + sage: e in P # needs sage.symbolic False """ try: @@ -164,7 +164,7 @@ def next(self, pr): EXAMPLES:: sage: P = Primes() - sage: P.next(5) # optional - sage.libs.pari + sage: P.next(5) # needs sage.libs.pari 7 """ pr = pr.next_prime(self.__proof) @@ -177,11 +177,11 @@ def unrank(self, n): EXAMPLES:: sage: P = Primes() - sage: P.unrank(0) # optional - sage.libs.pari + sage: P.unrank(0) # needs sage.libs.pari 2 - sage: P.unrank(5) # optional - sage.libs.pari + sage: P.unrank(5) # needs sage.libs.pari 13 - sage: P.unrank(42) # optional - sage.libs.pari + sage: P.unrank(42) # needs sage.libs.pari 191 """ return nth_prime(n + 1) diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index ec57b00236f..df54230cc07 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -48,6 +48,7 @@ Relations containing symbols and numeric values or constants:: + sage: # needs sage.symbolic sage: RealSet(x != 0) (-oo, 0) ∪ (0, +oo) sage: RealSet(x == pi) @@ -61,11 +62,11 @@ Note that multiple arguments are combined as union:: - sage: RealSet(x >= 0, x < 1) + sage: RealSet(x >= 0, x < 1) # needs sage.symbolic (-oo, +oo) - sage: RealSet(x >= 0, x > 1) + sage: RealSet(x >= 0, x > 1) # needs sage.symbolic [0, +oo) - sage: RealSet(x >= 0, x > -1) + sage: RealSet(x >= 0, x > -1) # needs sage.symbolic (-1, +oo) AUTHORS: @@ -406,9 +407,9 @@ def _latex_(self): EXAMPLES:: - sage: RealSet.open_closed(1/2, pi)._latex_() + sage: RealSet.open_closed(1/2, pi)._latex_() # needs sage.symbolic '(\\frac{1}{2}, \\pi]' - sage: (RealSet.point(sqrt(2)))._latex_() + sage: (RealSet.point(sqrt(2)))._latex_() # needs sage.symbolic '\\{\\sqrt{2}\\}' """ from sage.misc.latex import latex @@ -435,7 +436,7 @@ def _sympy_condition_(self, variable): EXAMPLES:: - sage: RealSet(0, 4)._sympy_condition_(x) + sage: RealSet(0, 4)._sympy_condition_(x) # needs sage.symbolic (0 < x) & (x < 4) """ x = variable @@ -464,17 +465,18 @@ def _sympy_(self): EXAMPLES:: - sage: RealSet.open_closed(0, 1)[0]._sympy_() # optional - sympy + sage: # needs sympy + sage: RealSet.open_closed(0, 1)[0]._sympy_() Interval.Lopen(0, 1) - sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9 # optional - sympy + sage: RealSet.point(0)[0]._sympy_() # random - this output format is sympy >= 1.9 {0} - sage: type(_) # optional - sympy + sage: type(_) - sage: RealSet.open(0,1)[0]._sympy_() # optional - sympy + sage: RealSet.open(0,1)[0]._sympy_() Interval.open(0, 1) - sage: RealSet.open(-oo,1)[0]._sympy_() # optional - sympy + sage: RealSet.open(-oo,1)[0]._sympy_() Interval.open(-oo, 1) - sage: RealSet.open(0, oo)[0]._sympy_() # optional - sympy + sage: RealSet.open(0, oo)[0]._sympy_() Interval.open(0, oo) """ from sympy import Interval @@ -494,7 +496,7 @@ def _giac_condition_(self, variable): EXAMPLES:: - sage: RealSet(0, 4)._giac_condition_(x) + sage: RealSet(0, 4)._giac_condition_(x) # needs sage.symbolic '((0 < sageVARx) and (sageVARx < 4))' """ x = variable @@ -985,11 +987,13 @@ class RealSet(UniqueRepresentation, Parent, Set_base, sage: i1, i2 = s1[0], s2[0] sage: RealSet(i2, i1) # union of intervals (1, 2) ∪ [3, 4] - sage: RealSet((-oo, 0), x > 6, i1, RealSet.point(5), RealSet.closed_open(4, 3)) + sage: RealSet((-oo, 0), x > 6, i1, RealSet.point(5), # needs sage.symbolic + ....: RealSet.closed_open(4, 3)) (-oo, 0) ∪ (1, 2) ∪ [3, 4) ∪ {5} ∪ (6, +oo) Initialization from manifold objects:: + sage: # needs sage.symbolic sage: R = manifolds.RealLine(); R Real number line ℝ sage: RealSet(R) @@ -1004,7 +1008,8 @@ class RealSet(UniqueRepresentation, Parent, Set_base, (0, 1) sage: RealSet(I01_of_R.closure()) [0, 1] - sage: I01_of_I02 = manifolds.OpenInterval(0, 1, ambient_interval=I02); I01_of_I02 + sage: I01_of_I02 = manifolds.OpenInterval(0, 1, + ....: ambient_interval=I02); I01_of_I02 Real interval (0, 1) sage: RealSet(I01_of_I02) (0, 1) @@ -1038,23 +1043,23 @@ class RealSet(UniqueRepresentation, Parent, Set_base, Constructing real sets as manifolds or manifold subsets by passing ``structure='differentiable'``:: - sage: RealSet(-oo, oo, structure='differentiable') + sage: RealSet(-oo, oo, structure='differentiable') # needs sage.symbolic Real number line ℝ - sage: RealSet([0, 1], structure='differentiable') + sage: RealSet([0, 1], structure='differentiable') # needs sage.symbolic Subset [0, 1] of the Real number line ℝ - sage: _.category() + sage: _.category() # needs sage.symbolic Category of subobjects of sets - sage: RealSet.open_closed(0, 5, structure='differentiable') + sage: RealSet.open_closed(0, 5, structure='differentiable') # needs sage.symbolic Subset (0, 5] of the Real number line ℝ This is implied when a coordinate name is given using the keywords ``coordinate`` or ``names``:: - sage: RealSet(0, 1, coordinate='λ') + sage: RealSet(0, 1, coordinate='λ') # needs sage.symbolic Open subset (0, 1) of the Real number line ℝ - sage: _.category() + sage: _.category() # needs sage.symbolic Join of Category of smooth manifolds over Real Field with 53 bits of precision and Category of connected manifolds over Real Field with 53 bits of precision and @@ -1062,14 +1067,15 @@ class RealSet(UniqueRepresentation, Parent, Set_base, It is also implied by assigning a coordinate name using generator notation:: - sage: R_xi.<ξ> = RealSet.real_line(); R_xi + sage: R_xi.<ξ> = RealSet.real_line(); R_xi # needs sage.symbolic Real number line ℝ - sage: R_xi.canonical_chart() + sage: R_xi.canonical_chart() # needs sage.symbolic Chart (ℝ, (ξ,)) With the keyword ``ambient``, we can construct a subset of a previously constructed manifold:: + sage: # needs sage.symbolic sage: P_xi = RealSet(0, oo, ambient=R_xi); P_xi Open subset (0, +oo) of the Real number line ℝ sage: P_xi.default_chart() @@ -1083,13 +1089,14 @@ class RealSet(UniqueRepresentation, Parent, Set_base, sage: F = RealSet.point(0).union(RealSet.point(1)).union(RealSet.point(2)); F {0} ∪ {1} ∪ {2} - sage: F_tau = RealSet(F, names="τ"); F_tau + sage: F_tau = RealSet(F, names="τ"); F_tau # needs sage.symbolic Subset {0} ∪ {1} ∪ {2} of the Real number line ℝ - sage: F_tau.manifold().canonical_chart() + sage: F_tau.manifold().canonical_chart() # needs sage.symbolic Chart (ℝ, (τ,)) TESTS:: + sage: # needs sage.symbolic sage: TestSuite(R_xi).run() sage: TestSuite(P_xi).run() sage: R_xi.point((1,)) in P_xi @@ -1123,6 +1130,7 @@ def __classcall__(cls, *args, **kwds): TESTS:: + sage: # needs sage.symbolic sage: RealSet(x != 0) (-oo, 0) ∪ (0, +oo) sage: RealSet(x == pi) @@ -1628,6 +1636,7 @@ def _sympy_condition_(self, variable): EXAMPLES:: + sage: # needs sage.symbolic sage: RealSet(0, 1)._sympy_condition_(x) (0 < x) & (x < 1) sage: RealSet((0,1), [2,3])._sympy_condition_(x) @@ -1639,9 +1648,9 @@ def _sympy_condition_(self, variable): TESTS:: - sage: RealSet(6,6)._sympy_condition_(x) + sage: RealSet(6,6)._sympy_condition_(x) # needs sage.symbolic False - sage: RealSet([6,6])._sympy_condition_(x) + sage: RealSet([6,6])._sympy_condition_(x) # needs sage.symbolic Eq(x, 6) """ x = variable @@ -1664,6 +1673,7 @@ def _giac_condition_(self, variable): EXAMPLES:: + sage: # needs sage.symbolic sage: RealSet(0, 1)._giac_condition_(x) '((0 < sageVARx) and (sageVARx < 1))' sage: RealSet((0,1), [2,3])._giac_condition_(x) @@ -1675,9 +1685,9 @@ def _giac_condition_(self, variable): TESTS:: - sage: RealSet(6,6)._giac_condition_(x) + sage: RealSet(6,6)._giac_condition_(x) # needs sage.symbolic 'false' - sage: RealSet([6,6])._giac_condition_(x) + sage: RealSet([6,6])._giac_condition_(x) # needs sage.symbolic 'sageVARx == 6' """ x = variable @@ -2107,7 +2117,7 @@ def union(self, *real_set_collection): (-oo, +oo) sage: s = RealSet().union([1, 2], (2, 3)); s [1, 3) - sage: RealSet().union((-oo, 0), x > 6, s[0], # optional - sage.symbolic + sage: RealSet().union((-oo, 0), x > 6, s[0], # needs sage.symbolic ....: RealSet.point(5.0), RealSet.closed_open(2, 4)) (-oo, 0) ∪ [1, 4) ∪ {5} ∪ (6, +oo) """ @@ -2171,7 +2181,7 @@ def intersection(self, *real_set_collection): [1, 10) sage: s5.intersection(-oo, +oo) [1, 10) - sage: s5.intersection(x != 2, (-oo, 3), RealSet.real_line()[0]) + sage: s5.intersection(x != 2, (-oo, 3), RealSet.real_line()[0]) # needs sage.symbolic [1, 2) ∪ (2, 3) TESTS:: @@ -2285,7 +2295,7 @@ def complement(self): TESTS:: - sage: RealSet(x != 0).complement() + sage: RealSet(x != 0).complement() # needs sage.symbolic {0} sage: RealSet.real_line().complement() {} @@ -2639,7 +2649,7 @@ def is_connected(self): (-oo, -10] ∪ (1, 3) sage: s3.is_connected() False - sage: RealSet(x != 0).is_connected() + sage: RealSet(x != 0).is_connected() # needs sage.symbolic False sage: RealSet(-oo, oo).is_connected() True @@ -2796,7 +2806,7 @@ def __rmul__(self, other): sage: A = RealSet([0, 1/2], RealSet.unbounded_above_closed(2)); A [0, 1/2] ∪ [2, +oo) - sage: pi * A + sage: pi * A # needs sage.symbolic [0, 1/2*pi] ∪ [2*pi, +oo) """ return self * other @@ -2807,21 +2817,22 @@ def _sympy_(self): EXAMPLES:: - sage: RealSet()._sympy_() # optional - sympy + sage: # needs sympy + sage: RealSet()._sympy_() EmptySet - sage: RealSet.point(5)._sympy_() # random - this output format is sympy >= 1.9 # optional - sympy + sage: RealSet.point(5)._sympy_() # random - this format is sympy >= 1.9 {5} - sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random # optional - sympy + sage: (RealSet.point(1).union(RealSet.point(2)))._sympy_() # random {1, 2} - sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_() # optional - sympy + sage: (RealSet(1, 2).union(RealSet.closed(3, 4)))._sympy_() Union(Interval.open(1, 2), Interval(3, 4)) - sage: RealSet(-oo, oo)._sympy_() # optional - sympy + sage: RealSet(-oo, oo)._sympy_() Reals Infinities are not elements:: - sage: import sympy # optional - sympy - sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) # optional - sympy + sage: import sympy # needs sympy + sage: RealSet(-oo, oo)._sympy_().contains(sympy.oo) # needs sympy False """ from sympy import Reals, Union diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index 094b1d852de..7a072820514 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -127,6 +127,7 @@ Elements of given depth iterator:: Graded components (set of elements of the same depth):: + sage: # needs sage.combinat sage: sorted(R.graded_component(0)) [[1, 2, 3, 4, 5]] sage: sorted(R.graded_component(1)) @@ -394,7 +395,7 @@ def RecursivelyEnumeratedSet(seeds, successors, structure=None, A recursive set given by a graded relation:: - sage: # optional - sage.symbolic + sage: # needs sage.symbolic sage: def f(a): ....: return [a + 1, a + I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded'); C @@ -881,10 +882,11 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): We compute all the permutations of 3:: - sage: seeds = [Permutation([1,2,3])] # optional - sage.combinat - sage: succ = attrcall("permutohedron_succ") # optional - sage.combinat - sage: R = RecursivelyEnumeratedSet(seeds, succ) # optional - sage.combinat - sage: sorted(R.naive_search_iterator()) # optional - sage.combinat + sage: # needs sage.combinat + sage: seeds = [Permutation([1,2,3])] + sage: succ = attrcall("permutohedron_succ") + sage: R = RecursivelyEnumeratedSet(seeds, succ) + sage: sorted(R.naive_search_iterator()) [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ cdef set known, todo @@ -955,7 +957,7 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): sage: child = lambda i: [(i+3) % 10, (i+8) % 10] sage: R = RecursivelyEnumeratedSet([0], child) - sage: R.to_digraph() + sage: R.to_digraph() # needs sage.graphs Looped multi-digraph on 10 vertices Digraph of an recursively enumerated set with a symmetric structure of @@ -964,20 +966,21 @@ cdef class RecursivelyEnumeratedSet_generic(Parent): sage: succ = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)] sage: seeds = [(0,0)] sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric') - sage: C.to_digraph(max_depth=3) + sage: C.to_digraph(max_depth=3) # needs sage.graphs Looped multi-digraph on 41 vertices The ``max_depth`` argument can be given at the creation of the set:: - sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric', max_depth=2) - sage: C.to_digraph() + sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric', + ....: max_depth=2) + sage: C.to_digraph() # needs sage.graphs Looped multi-digraph on 25 vertices Digraph of an recursively enumerated set with a graded structure:: sage: f = lambda a: [a+1, a+I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') - sage: C.to_digraph(max_depth=4) + sage: C.to_digraph(max_depth=4) # needs sage.graphs Looped multi-digraph on 21 vertices """ successors = self.successors @@ -1126,7 +1129,7 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Gaussian integers:: - sage: # optional - sage.symbolic + sage: # needs sage.symbolic sage: def f(a): ....: return [a + 1, a + I] sage: S = RecursivelyEnumeratedSet([0], f, structure='symmetric') @@ -1145,7 +1148,7 @@ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic): Note that interrupting the computation (``KeyboardInterrupt`` for instance) breaks the iterator:: - sage: # optional - sage.symbolic + sage: # needs sage.symbolic sage: def f(a): ....: sleep(0.05r) ....: return [a-1,a+1] @@ -1415,7 +1418,7 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): EXAMPLES:: - sage: # optional - sage.symbolic + sage: # needs sage.symbolic sage: def f(a): ....: return [a + 1, a + I] sage: C = RecursivelyEnumeratedSet([0], f, structure='graded') @@ -1430,7 +1433,7 @@ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic): We make sure that :trac:`21312` is fixed:: - sage: # optional - sage.symbolic + sage: # needs sage.symbolic sage: def f(a): ....: sleep(0.1r) ....: return [a+1, a+I] @@ -2095,14 +2098,13 @@ class RecursivelyEnumeratedSet_forest(Parent): sage: F = RecursivelyEnumeratedSet(seeds, succ, ....: structure='forest', enumeration='depth') - sage: # needs sage.symbolic - sage: y = var('y') + sage: y = var('y') # needs sage.symbolic sage: def map_function(t): ....: li, sum, _ = t ....: return y ^ sum sage: def reduce_function(x, y): ....: return x + y - sage: F.map_reduce(map_function, reduce_function, 0) + sage: F.map_reduce(map_function, reduce_function, 0) # needs sage.symbolic y^45 + y^44 + y^43 + 2*y^42 + 2*y^41 + 3*y^40 + 4*y^39 + 5*y^38 + 6*y^37 + 8*y^36 + 9*y^35 + 10*y^34 + 12*y^33 + 13*y^32 + 15*y^31 + 17*y^30 + 18*y^29 + 19*y^28 + 21*y^27 + 21*y^26 + 22*y^25 + 23*y^24 + 23*y^23 diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index cadbb7fe461..304d37ba1f1 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -71,7 +71,7 @@ def has_finite_length(obj): True sage: has_finite_length(iter(range(10))) False - sage: has_finite_length(GF(17^127)) # optional - sage.libs.pari + sage: has_finite_length(GF(17^127)) # needs sage.rings.finite_rings True sage: has_finite_length(ZZ) False @@ -100,17 +100,18 @@ def Set(X=None, category=None): EXAMPLES:: - sage: X = Set(GF(9, 'a')) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(9, 'a')) + sage: X {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} - sage: type(X) # optional - sage.libs.pari + sage: type(X) - sage: Y = X.union(Set(QQ)) # optional - sage.libs.pari - sage: Y # optional - sage.libs.pari + sage: Y = X.union(Set(QQ)) + sage: Y Set-theoretic union of {0, 1, 2, a, a + 1, a + 2, 2*a, 2*a + 1, 2*a + 2} and Set of elements of Rational Field - sage: type(Y) # optional - sage.libs.pari + sage: type(Y) Usually sets can be used as dictionary keys. @@ -152,7 +153,7 @@ def Set(X=None, category=None): We can also create sets from different types:: - sage: sorted(Set([Sequence([3,1], immutable=True), 5, QQ, Partition([3,1,1])]), key=str) + sage: sorted(Set([Sequence([3,1], immutable=True), 5, QQ, Partition([3,1,1])]), key=str) # needs sage.combinat [5, Rational Field, [3, 1, 1], [3, 1]] Sets with unhashable objects work, but with less functionality:: @@ -236,9 +237,9 @@ def union(self, X): True sage: GF(3)(2) in X # optional - sage.libs.pari True - sage: GF(5)(2) in X # optional - sage.libs.pari + sage: GF(5)(2) in X # needs sage.rings.finite_rings False - sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) # optional - sage.libs.pari + sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) # needs sage.rings.finite_rings [0, 0, 1, 1, 2, 2, 3, 4, 5, 6] """ if isinstance(X, (Set_generic, Set_base)): @@ -262,10 +263,10 @@ def intersection(self, X): sage: 2/1 in X True - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))); X # optional - sage.libs.pari + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'c'))); X # needs sage.rings.finite_rings {} - sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))); X # optional - sage.libs.pari + sage: X = Set(GF(9,'b')).intersection(Set(GF(27,'b'))); X # needs sage.rings.finite_rings {} """ if isinstance(X, (Set_generic, Set_base)): @@ -289,10 +290,10 @@ def difference(self, X): sage: 4/1 in X True - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))); X # optional - sage.libs.pari + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'c'))); X # needs sage.rings.finite_rings {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} - sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))); X # optional - sage.libs.pari + sage: X = Set(GF(9,'b')).difference(Set(GF(27,'b'))); X # needs sage.rings.finite_rings {0, 1, 2, b, b + 1, b + 2, 2*b, 2*b + 1, 2*b + 2} """ if isinstance(X, (Set_generic, Set_base)): @@ -330,7 +331,7 @@ def _test_as_set_object(self, tester=None, **options): Instances of other subclasses of :class:`Set_base` run this method:: - sage: Polyhedron()._test_as_set_object(verbose=True) # optional - sage.geometry.polyhedron + sage: Polyhedron()._test_as_set_object(verbose=True) # needs sage.geometry.polyhedron Running the test suite of Set(self) running ._test_an_element() . . . pass ... @@ -412,15 +413,15 @@ def __add__(self, X): EXAMPLES:: - sage: Set(RealField()) + Set(QQ^5) # optional - sage.modules + sage: Set(RealField()) + Set(QQ^5) # needs sage.modules Set-theoretic union of Set of elements of Real Field with 53 bits of precision and Set of elements of Vector space of dimension 5 over Rational Field - sage: Set(GF(3)) + Set(GF(2)) # optional - sage.libs.pari + sage: Set(GF(3)) + Set(GF(2)) # needs sage.rings.finite_rings {0, 1, 2, 0, 1} - sage: Set(GF(2)) + Set(GF(4,'a')) # optional - sage.libs.pari + sage: Set(GF(2)) + Set(GF(4,'a')) # needs sage.rings.finite_rings {0, 1, a, a + 1} - sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) # optional - sage.libs.pari + sage: sorted(Set(GF(8,'b')) + Set(GF(4,'a')), key=str) # needs sage.rings.finite_rings [0, 0, 1, 1, a, a + 1, b, b + 1, b^2, b^2 + 1, b^2 + b, b^2 + b + 1] """ return self.union(X) @@ -587,8 +588,8 @@ def _an_element_(self): EXAMPLES:: - sage: R = Set(RR) # optional - sage.rings.real_mpfr - sage: R.an_element() # indirect doctest # optional - sage.rings.real_mpfr + sage: R = Set(RR) + sage: R.an_element() # indirect doctest # needs sage.rings.real_mpfr 1.00000000000000 sage: F = Set([1, 2, 3]) @@ -630,9 +631,9 @@ def __contains__(self, x): False sage: 5/3 in GF(7) False - sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) # optional - sage.libs.pari + sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) # needs sage.rings.finite_rings [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6] - sage: Set(GF(7)).intersection(Set(GF(5))) # optional - sage.libs.pari + sage: Set(GF(7)).intersection(Set(GF(5))) # needs sage.rings.finite_rings {} """ return x in self.__object @@ -678,7 +679,7 @@ def cardinality(self): +Infinity sage: Set(GF(5)).cardinality() 5 - sage: Set(GF(5^2,'a')).cardinality() # optional - sage.libs.pari + sage: Set(GF(5^2,'a')).cardinality() # needs sage.rings.finite_rings 25 """ if self in Sets().Infinite(): @@ -716,7 +717,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(SymmetricGroup(2).list()).is_empty() # optional - sage.groups + sage: Set(SymmetricGroup(2).list()).is_empty() # needs sage.groups False sage: Set(ZZ).is_empty() False @@ -729,7 +730,7 @@ def is_empty(self): False sage: Set([1..100]).is_empty() False - sage: Set(DihedralGroup(4).list()).is_empty() # optional - sage.groups + sage: Set(DihedralGroup(4).list()).is_empty() # needs sage.groups False sage: Set(QQ).is_empty() False @@ -744,7 +745,7 @@ def is_finite(self): sage: Set(QQ).is_finite() False - sage: Set(GF(250037)).is_finite() # optional - sage.libs.pari + sage: Set(GF(250037)).is_finite() # needs sage.rings.finite_rings True sage: Set(Integers(2^1000000)).is_finite() True @@ -801,10 +802,10 @@ def subsets_lattice(self): EXAMPLES:: sage: X = Set([1,2,3]) - sage: X.subsets_lattice() # optional - sage.combinat sage.graphs sage.modules + sage: X.subsets_lattice() # needs sage.combinat sage.graphs sage.modules Finite lattice containing 8 elements sage: Y = Set() - sage: Y.subsets_lattice() # optional - sage.combinat sage.graphs sage.modules + sage: Y.subsets_lattice() # needs sage.combinat sage.graphs sage.modules Finite lattice containing 1 elements """ @@ -840,7 +841,7 @@ def _sympy_(self): sage: X = Set(ZZ); X Set of elements of Integer Ring - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy Integers """ from sage.interfaces.sympy import sympy_init @@ -972,12 +973,13 @@ def list(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(8,'c')) + sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: X.list() # optional - sage.libs.pari + sage: X.list() [0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1] - sage: type(X.list()) # optional - sage.libs.pari + sage: type(X.list()) <... 'list'> .. TODO:: @@ -1000,14 +1002,15 @@ def set(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(8,'c')) + sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: X.set() # optional - sage.libs.pari + sage: X.set() {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: type(X.set()) # optional - sage.libs.pari + sage: type(X.set()) <... 'set'> - sage: type(X) # optional - sage.libs.pari + sage: type(X) """ return set(self.object()) @@ -1019,22 +1022,23 @@ def frozenset(self): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(8,'c')) + sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: s = X.set(); s # optional - sage.libs.pari + sage: s = X.set(); s {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: hash(s) # optional - sage.libs.pari + sage: hash(s) Traceback (most recent call last): ... TypeError: unhashable type: 'set' - sage: s = X.frozenset(); s # optional - sage.libs.pari + sage: s = X.frozenset(); s frozenset({0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1}) - sage: hash(s) != hash(tuple(X.set())) # optional - sage.libs.pari + sage: hash(s) != hash(tuple(X.set())) # needs sage.rings.finite_rings True - sage: type(s) # optional - sage.libs.pari + sage: type(s) # needs sage.rings.finite_rings <... 'frozenset'> """ return frozenset(self.object()) @@ -1045,8 +1049,8 @@ def __hash__(self): EXAMPLES:: - sage: s = Set(GF(8,'c')) # optional - sage.libs.pari - sage: hash(s) == hash(s) # optional - sage.libs.pari + sage: s = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: hash(s) == hash(s) # needs sage.rings.finite_rings True """ return hash(self.frozenset()) @@ -1057,10 +1061,10 @@ def __richcmp__(self, other, op): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: X == Set(GF(8,'c')) # optional - sage.libs.pari + sage: X = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: X == Set(GF(8,'c')) # needs sage.rings.finite_rings True - sage: X == Set(GF(4,'a')) # optional - sage.libs.pari + sage: X == Set(GF(4,'a')) # needs sage.rings.finite_rings False sage: Set(QQ) == Set(ZZ) False @@ -1147,13 +1151,14 @@ def union(self, other): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(8,'c')) + sage: Y = Set([GF(8,'c').0, 1, 2, 3]) + sage: X {0, 1, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1} - sage: sorted(Y) # optional - sage.libs.pari + sage: sorted(Y) [1, 2, 3, c] - sage: sorted(X.union(Y), key=str) # optional - sage.libs.pari + sage: sorted(X.union(Y), key=str) [0, 1, 2, 3, c, c + 1, c^2, c^2 + 1, c^2 + c, c^2 + c + 1] """ if not isinstance(other, Set_object_enumerated): @@ -1166,9 +1171,9 @@ def intersection(self, other): EXAMPLES:: - sage: X = Set(GF(8,'c')) # optional - sage.libs.pari - sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # optional - sage.libs.pari - sage: X.intersection(Y) # optional - sage.libs.pari + sage: X = Set(GF(8,'c')) # needs sage.rings.finite_rings + sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # needs sage.rings.finite_rings + sage: X.intersection(Y) # needs sage.rings.finite_rings {1, c} """ if not isinstance(other, Set_object_enumerated): @@ -1186,8 +1191,8 @@ def difference(self, other): sage: X.difference(Y) {3, 4} sage: Z = Set(ZZ) - sage: W = Set([2.5, 4, 5, 6]) # optional - sage.rings.real_mpfr - sage: W.difference(Z) # optional - sage.rings.real_mpfr + sage: W = Set([2.5, 4, 5, 6]) + sage: W.difference(Z) # needs sage.rings.real_mpfr {2.50000000000000} """ if not isinstance(other, Set_object_enumerated): @@ -1232,16 +1237,16 @@ def _sympy_(self): sage: X = Set({1, 2, 3}); X {1, 2, 3} - sage: sX = X._sympy_(); sX # optional - sympy + sage: sX = X._sympy_(); sX # needs sympy Set(1, 2, 3) - sage: sX.is_empty is None # optional - sympy + sage: sX.is_empty is None # needs sympy True sage: Empty = Set([]); Empty {} - sage: sEmpty = Empty._sympy_(); sEmpty # optional - sympy + sage: sEmpty = Empty._sympy_(); sEmpty # needs sympy EmptySet - sage: sEmpty.is_empty # optional - sympy + sage: sEmpty.is_empty # needs sympy True """ from sympy import Set, EmptySet @@ -1269,10 +1274,10 @@ class Set_object_binary(Set_object, metaclass=ClasscallMetaclass): EXAMPLES:: - sage: X = Set(QQ^2) # optional - sage.modules + sage: X = Set(QQ^2) # needs sage.modules sage: Y = Set(ZZ) sage: from sage.sets.set import Set_object_binary - sage: S = Set_object_binary(X, Y, "union", "\\cup"); S # optional - sage.modules + sage: S = Set_object_binary(X, Y, "union", "\\cup"); S # needs sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1286,9 +1291,9 @@ def __classcall__(cls, X, Y, *args, **kwds): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = QQ^2 # optional - sage.modules + sage: X = QQ^2 # needs sage.modules sage: Y = ZZ - sage: Set_object_binary(X, Y, "union", "\\cup") # optional - sage.modules + sage: Set_object_binary(X, Y, "union", "\\cup") # needs sage.modules Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring @@ -1306,10 +1311,10 @@ def __init__(self, X, Y, op, latex_op, category=None): TESTS:: sage: from sage.sets.set import Set_object_binary - sage: X = Set(QQ^2) # optional - sage.modules + sage: X = Set(QQ^2) # needs sage.modules sage: Y = Set(ZZ) - sage: S = Set_object_binary(X, Y, "union", "\\cup") # optional - sage.modules - sage: type(S) # optional - sage.modules + sage: S = Set_object_binary(X, Y, "union", "\\cup") # needs sage.modules + sage: type(S) # needs sage.modules """ self._X = X @@ -1376,17 +1381,19 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) # optional - sage.modules + sage: S = Set(QQ^2) # needs sage.modules sage: T = Set(ZZ) - sage: X = S.union(T); X # optional - sage.modules - Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() # optional - sage.modules + sage: X = S.union(T); X # needs sage.modules + Set-theoretic union of + Set of elements of Vector space of dimension 2 over Rational Field and + Set of elements of Integer Ring + sage: X.category() # needs sage.modules Category of infinite sets - sage: latex(X) # optional - sage.modules + sage: latex(X) # needs sage.modules \Bold{Q}^{2} \cup \Bold{Z} - sage: TestSuite(X).run() # optional - sage.modules + sage: TestSuite(X).run() # needs sage.modules """ if category is None: category = Sets() @@ -1427,11 +1434,12 @@ def __richcmp__(self, right, op): EXAMPLES:: - sage: Y = Set(ZZ^2).union(Set(ZZ^3)) # optional - sage.modules - sage: X = Set(ZZ^3).union(Set(ZZ^2)) # optional - sage.modules - sage: X == Y # optional - sage.modules + sage: # needs sage.modules + sage: Y = Set(ZZ^2).union(Set(ZZ^3)) + sage: X = Set(ZZ^3).union(Set(ZZ^2)) + sage: X == Y True - sage: Y == X # optional - sage.modules + sage: Y == X True This illustrates that equality testing for formal unions @@ -1457,7 +1465,7 @@ def __iter__(self): EXAMPLES:: - sage: [x for x in Set(GF(3)).union(Set(GF(2)))] # optional - sage.libs.pari + sage: [x for x in Set(GF(3)).union(Set(GF(2)))] # needs sage.rings.finite_rings [0, 1, 2, 0, 1] """ for x in self._X: @@ -1471,14 +1479,15 @@ def __contains__(self, x): EXAMPLES:: - sage: X = Set(GF(3)).union(Set(GF(2))) # optional - sage.libs.pari - sage: GF(5)(1) in X # optional - sage.libs.pari + sage: # needs sage.rings.finite_rings + sage: X = Set(GF(3)).union(Set(GF(2))) + sage: GF(5)(1) in X False - sage: GF(3)(2) in X # optional - sage.libs.pari + sage: GF(3)(2) in X True - sage: GF(2)(0) in X # optional - sage.libs.pari + sage: GF(2)(0) in X True - sage: GF(5)(0) in X # optional - sage.libs.pari + sage: GF(5)(0) in X False """ return x in self._X or x in self._Y @@ -1489,10 +1498,10 @@ def cardinality(self): EXAMPLES:: - sage: X = Set(GF(3)).union(Set(GF(2))) # optional - sage.libs.pari - sage: X # optional - sage.libs.pari + sage: X = Set(GF(3)).union(Set(GF(2))) # needs sage.rings.finite_rings + sage: X # needs sage.rings.finite_rings {0, 1, 2, 0, 1} - sage: X.cardinality() # optional - sage.libs.pari + sage: X.cardinality() # needs sage.rings.finite_rings 5 sage: X = Set(GF(3)).union(Set(ZZ)) @@ -1510,7 +1519,7 @@ def _sympy_(self): sage: X = Set(ZZ).union(Set([1/2])); X Set-theoretic union of Set of elements of Integer Ring and {1/2} - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy Union(Integers, Set(1/2)) """ from sympy import Union @@ -1529,15 +1538,15 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) # optional - sage.modules + sage: S = Set(QQ^2) # needs sage.modules sage: T = Set(ZZ) - sage: X = S.intersection(T); X # optional - sage.modules + sage: X = S.intersection(T); X # needs sage.modules Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() # optional - sage.modules + sage: X.category() # needs sage.modules Category of enumerated sets - sage: latex(X) # optional - sage.modules + sage: latex(X) # needs sage.modules \Bold{Q}^{2} \cap \Bold{Z} sage: X = Set(IntegerRange(100)).intersection(Primes()) @@ -1664,18 +1673,18 @@ def __contains__(self, x): sage: X = Set(QQ).intersection(Set(RR)) sage: 5 in X True - sage: ComplexField().0 in X # optional - sage.rings.real_mpfr + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False Any specific floating-point number in Sage is to finite precision, hence it is rational:: - sage: RR(sqrt(2)) in X # optional - sage.rings.real_mpfr sage.symbolic + sage: RR(sqrt(2)) in X # needs sage.rings.real_mpfr sage.symbolic True Real constants are not rational:: - sage: pi in X # optional - sage.symbolic + sage: pi in X # needs sage.symbolic False """ return x in self._X and x in self._Y @@ -1691,7 +1700,7 @@ def _sympy_(self): Set-theoretic intersection of Set of elements of Integer Ring and Set of elements of [3/2, 11/2] - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy Range(2, 6, 1) """ from sympy import Intersection @@ -1836,11 +1845,11 @@ def __contains__(self, x): sage: X = Set(QQ).difference(Set(ZZ)) sage: 5 in X False - sage: ComplexField().0 in X # optional - sage.rings.real_mpfr + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False - sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # optional - sage.symbolic + sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # optional - sage.rings.real_mpfr sage.symbolic + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx True sage: 5/2 in X True @@ -1860,7 +1869,7 @@ def _sympy_(self): Set of elements of Integer Ring sage: X.category() Category of sets - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy Complement(Rationals, Integers) sage: X = Set(ZZ).difference(Set(QQ)); X @@ -1869,7 +1878,7 @@ def _sympy_(self): Set of elements of Rational Field sage: X.category() Category of enumerated sets - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy EmptySet """ from sympy import Complement @@ -2009,13 +2018,13 @@ def __contains__(self, x): sage: X = Set(QQ).symmetric_difference(Primes()) sage: 4 in X True - sage: ComplexField().0 in X # optional - sage.rings.real_mpfr + sage: ComplexField().0 in X # needs sage.rings.real_mpfr False - sage: sqrt(2) in X # since sqrt(2) is currently symbolic # optional - sage.symbolic + sage: sqrt(2) in X # since sqrt(2) is currently symbolic # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated # optional - sage.rings.real_mpfr + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated True - sage: pi in X # optional - sage.symbolic + sage: pi in X # needs sage.symbolic False sage: 5/2 in X True @@ -2036,7 +2045,7 @@ def _sympy_(self): Set-theoretic symmetric difference of Set of elements of Integer Ring and {0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3} - sage: X._sympy_() # optional - sympy + sage: X._sympy_() # needs sympy Union(Complement(Integers, Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3)), Complement(Set(0, 1, 2, 1/3, 2/3, 4/3, 5/3, 7/3, 8/3), Integers)) """ diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index 0c7e4f35aa4..7d97cfc4064 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -6,21 +6,22 @@ We build a set from the iterator :obj:`graphs` that returns a canonical representative for each isomorphism class of graphs:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator( # optional - sage.graphs + sage: E = EnumeratedSetFromIterator( ....: graphs, ....: name="Graphs", ....: category=InfiniteEnumeratedSets(), ....: cache=True) - sage: E # optional - sage.graphs + sage: E Graphs - sage: E.unrank(0) # optional - sage.graphs + sage: E.unrank(0) Graph on 0 vertices - sage: E.unrank(4) # optional - sage.graphs + sage: E.unrank(4) Graph on 3 vertices - sage: E.cardinality() # optional - sage.graphs + sage: E.cardinality() +Infinity - sage: E.category() # optional - sage.graphs + sage: E.category() Category of facade infinite enumerated sets The module also provides decorator for functions and methods:: @@ -97,21 +98,21 @@ class EnumeratedSetFromIterator(Parent): EXAMPLES:: sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(7,)); E # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(7,)); E # needs sage.graphs {Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, Graph on 7 vertices, ...} - sage: E.category() # optional - sage.graphs + sage: E.category() # needs sage.graphs Category of facade enumerated sets The same example with a cache and a custom name:: - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True, # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True, # needs sage.graphs ....: name="Graphs with 8 vertices", ....: category=FiniteEnumeratedSets()); E Graphs with 8 vertices - sage: E.unrank(3) # optional - sage.graphs + sage: E.unrank(3) # needs sage.graphs Graph on 8 vertices - sage: E.category() # optional - sage.graphs + sage: E.category() # needs sage.graphs Category of facade finite enumerated sets TESTS: @@ -196,17 +197,18 @@ def __reduce__(self): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: from sage.graphs.graph_generators import graphs # optional - sage.graphs - sage: E = EnumeratedSetFromIterator(graphs, # optional - sage.graphs + sage: from sage.graphs.graph_generators import graphs + sage: E = EnumeratedSetFromIterator(graphs, ....: args=(3,), ....: category=FiniteEnumeratedSets(), ....: name="Graphs on 3 vertices") - sage: E # optional - sage.graphs + sage: E Graphs on 3 vertices - sage: F = loads(dumps(E)); F # optional - sage.graphs + sage: F = loads(dumps(E)); F Graphs on 3 vertices - sage: E == F # optional - sage.graphs + sage: E == F True """ return (EnumeratedSetFromIterator, @@ -224,16 +226,17 @@ def _repr_(self): TESTS:: + sage: # needs sage.combinat sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(Partitions(7, min_part=2).__iter__) # optional - sage.combinat - sage: repr(E) # indirect doctest # optional - sage.combinat + sage: E = EnumeratedSetFromIterator(Partitions(7, min_part=2).__iter__) + sage: repr(E) # indirect doctest '{[7], [5, 2], [4, 3], [3, 2, 2]}' - sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__) # optional - sage.combinat - sage: repr(E) # indirect doctest # optional - sage.combinat + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__) + sage: repr(E) # indirect doctest '{[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], ...}' - sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__, # optional - sage.combinat + sage: E = EnumeratedSetFromIterator(Partitions(9, min_part=2).__iter__, ....: name="Some partitions") - sage: repr(E) # indirect doctest # optional - sage.combinat + sage: repr(E) # indirect doctest 'Some partitions' """ l = [] @@ -257,10 +260,10 @@ def __contains__(self, x): EXAMPLES:: - sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator # optional - sage.combinat - sage: P = Partitions(12, min_part=2, max_part=5) # optional - sage.combinat - sage: E = EnumeratedSetFromIterator(P.__iter__) # optional - sage.combinat - sage: P([5,5,2]) in E # optional - sage.combinat + sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator + sage: P = Partitions(12, min_part=2, max_part=5) # needs sage.combinat + sage: E = EnumeratedSetFromIterator(P.__iter__) # needs sage.combinat + sage: P([5,5,2]) in E # needs sage.combinat True """ return any(x == y for y in self) @@ -277,22 +280,23 @@ def __eq__(self, other): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), ....: category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), ....: category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), # optional - sage.graphs + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), ....: category=FiniteEnumeratedSets()) - sage: E4 == E4 # optional - sage.graphs + sage: E4 == E4 True - sage: E4 == F4 # optional - sage.graphs + sage: E4 == F4 True - sage: E4 == E5 # optional - sage.graphs + sage: E4 == E5 False - sage: E5 == E4 # optional - sage.graphs + sage: E5 == E4 False - sage: E5 == E5 # optional - sage.graphs + sage: E5 == E5 True """ if isinstance(other, EnumeratedSetFromIterator): @@ -335,22 +339,23 @@ def __ne__(self, other): TESTS:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + sage: E4 = EnumeratedSetFromIterator(graphs, args=(4,), ....: category=FiniteEnumeratedSets()) - sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), # optional - sage.graphs + sage: F4 = EnumeratedSetFromIterator(graphs, args=(4,), ....: category=FiniteEnumeratedSets()) - sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), # optional - sage.graphs + sage: E5 = EnumeratedSetFromIterator(graphs, args=(5,), ....: category=FiniteEnumeratedSets()) - sage: E4 != E4 # optional - sage.graphs + sage: E4 != E4 False - sage: E4 != F4 # optional - sage.graphs + sage: E4 != F4 False - sage: E4 != E5 # optional - sage.graphs + sage: E4 != E5 True - sage: E5 != E4 # optional - sage.graphs + sage: E5 != E4 True - sage: E5 != E5 # optional - sage.graphs + sage: E5 != E5 False """ return not self == other @@ -361,14 +366,15 @@ def __iter__(self): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) # optional - sage.graphs - sage: g1 = next(iter(E)); g1 # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,)) + sage: g1 = next(iter(E)); g1 Graph on 8 vertices - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs - sage: g2 = next(iter(E)); g2 # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) + sage: g2 = next(iter(E)); g2 Graph on 8 vertices - sage: g1 == g2 # optional - sage.graphs + sage: g1 == g2 True """ if hasattr(self, '_cache'): @@ -381,12 +387,13 @@ def unrank(self, i): EXAMPLES:: + sage: # needs sage.graphs sage: from sage.sets.set_from_iterator import EnumeratedSetFromIterator - sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) # optional - sage.graphs - sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) # optional - sage.graphs - sage: E.unrank(2) # optional - sage.graphs + sage: E = EnumeratedSetFromIterator(graphs, args=(8,), cache=True) + sage: F = EnumeratedSetFromIterator(graphs, args=(8,), cache=False) + sage: E.unrank(2) Graph on 8 vertices - sage: E.unrank(2) == F.unrank(2) # optional - sage.graphs + sage: E.unrank(2) == F.unrank(2) True """ if hasattr(self, '_cache'): @@ -507,11 +514,11 @@ def _sage_src_lines_(self): sage: from sage.misc.sageinspect import sage_getsourcelines sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = MathieuGroup.order # optional - sage.groups - sage: S = sage_getsourcelines(d) # indirect doctest # optional - sage.groups - sage: S[0][2] # optional - sage.groups + sage: d.f = MathieuGroup.order # needs sage.groups + sage: S = sage_getsourcelines(d) # indirect doctest # needs sage.groups + sage: S[0][2] # needs sage.groups ' Return the number of elements of this group.\n' - sage: S[0][25] # optional - sage.groups + sage: S[0][25] # needs sage.groups ' if not gens:\n' """ from sage.misc.sageinspect import sage_getsourcelines @@ -526,8 +533,8 @@ def _sage_argspec_(self): sage: from sage.misc.sageinspect import sage_getargspec sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = find_local_minimum # optional - scipy - sage: sage_getargspec(d) # indirect doctest # optional - scipy + sage: d.f = find_local_minimum # needs scipy + sage: sage_getargspec(d) # indirect doctest # needs scipy FullArgSpec(args=['f', 'a', 'b', 'tol', 'maxfun'], varargs=None, varkw=None, defaults=(1.48e-08, 500), kwonlyargs=[], kwonlydefaults=None, annotations={}) @@ -615,11 +622,11 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): ....: @set_from_function(name="Graphs on %(n)d vertices", ....: category=FiniteEnumeratedSets(), cache=True) ....: def Graphs(n): return graphs(n) - sage: Graphs(10) # optional - sage.graphs + sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) # optional - sage.graphs + sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) # optional - sage.graphs + sage: Graphs(10) is Graphs(10) # needs sage.graphs True The ``@cached_function`` must go first:: @@ -628,11 +635,11 @@ class EnumeratedSetFromIterator_function_decorator(Decorator): ....: category=FiniteEnumeratedSets(), cache=True) ....: @cached_function ....: def Graphs(n): return graphs(n) - sage: Graphs(10) # optional - sage.graphs + sage: Graphs(10) # needs sage.graphs Graphs on 10 vertices - sage: Graphs(10).unrank(0) # optional - sage.graphs + sage: Graphs(10).unrank(0) # needs sage.graphs Graph on 10 vertices - sage: Graphs(10) is Graphs(10) # optional - sage.graphs + sage: Graphs(10) is Graphs(10) # needs sage.graphs False """ def __init__(self, f=None, name=None, **options): @@ -868,7 +875,7 @@ class EnumeratedSetFromIterator_method_decorator(): sage: b = B() sage: G3 = b.graphs(3); G3 Graphs(3) - sage: G3.cardinality() # optional - sage.graphs + sage: G3.cardinality() # needs sage.graphs 4 sage: G3.category() Category of facade finite enumerated sets @@ -909,11 +916,11 @@ def __init__(self, f=None, **options): :mod:`sage.combinat.permutation`) because its method ``bruhat_succ`` and ``bruhat_pred`` are decorated with ``set_from_method``:: - sage: from sage.combinat.permutation import Permutation # optional - sage.combinat - sage: loads(dumps(Permutation)) # optional - sage.combinat + sage: from sage.combinat.permutation import Permutation + sage: loads(dumps(Permutation)) - sage: p = Permutation([3,2,1]) # optional - sage.combinat - sage: loads(dumps(p)) == p # optional - sage.combinat + sage: p = Permutation([3,2,1]) + sage: loads(dumps(p)) == p True """ if f is not None: diff --git a/src/sage/sets/totally_ordered_finite_set.py b/src/sage/sets/totally_ordered_finite_set.py index fde8984b501..f28840c81f7 100644 --- a/src/sage/sets/totally_ordered_finite_set.py +++ b/src/sage/sets/totally_ordered_finite_set.py @@ -173,8 +173,8 @@ class TotallyOrderedFiniteSet(FiniteEnumeratedSet): sage: T1 = TotallyOrderedFiniteSet([3,2,5,1]) sage: T1(3) < T1(1) False - sage: T2 = TotallyOrderedFiniteSet([3,var('x')]) - sage: T2(3) < T2(var('x')) + sage: T2 = TotallyOrderedFiniteSet([3, x]) # needs sage.symbolic + sage: T2(3) < T2(x) # needs sage.symbolic 3 < x To make the above example work, you should set the argument facade to From 726c3cf00494a382cc694b448f790616ac565c07 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 13 Jul 2023 22:33:35 -0700 Subject: [PATCH 093/225] sage.parallel, sage.sets: Update # needs --- src/sage/sets/recursively_enumerated_set.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/sets/recursively_enumerated_set.pyx b/src/sage/sets/recursively_enumerated_set.pyx index 7a072820514..26bcd769b44 100644 --- a/src/sage/sets/recursively_enumerated_set.pyx +++ b/src/sage/sets/recursively_enumerated_set.pyx @@ -2098,13 +2098,14 @@ class RecursivelyEnumeratedSet_forest(Parent): sage: F = RecursivelyEnumeratedSet(seeds, succ, ....: structure='forest', enumeration='depth') - sage: y = var('y') # needs sage.symbolic + sage: # needs sage.symbolic + sage: y = var('y') sage: def map_function(t): ....: li, sum, _ = t ....: return y ^ sum sage: def reduce_function(x, y): ....: return x + y - sage: F.map_reduce(map_function, reduce_function, 0) # needs sage.symbolic + sage: F.map_reduce(map_function, reduce_function, 0) y^45 + y^44 + y^43 + 2*y^42 + 2*y^41 + 3*y^40 + 4*y^39 + 5*y^38 + 6*y^37 + 8*y^36 + 9*y^35 + 10*y^34 + 12*y^33 + 13*y^32 + 15*y^31 + 17*y^30 + 18*y^29 + 19*y^28 + 21*y^27 + 21*y^26 + 22*y^25 + 23*y^24 + 23*y^23 From 783ea1547a3b21cfb4323c199b62d656e9e9a8e6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 6 Aug 2023 18:30:46 -0700 Subject: [PATCH 094/225] sage.sets: Update # needs --- src/sage/sets/non_negative_integers.py | 4 ++-- src/sage/sets/set.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/non_negative_integers.py b/src/sage/sets/non_negative_integers.py index 8eb83f3dfc1..a7995ff3e1e 100644 --- a/src/sage/sets/non_negative_integers.py +++ b/src/sage/sets/non_negative_integers.py @@ -108,11 +108,11 @@ def __contains__(self, elt): False sage: QQbar(sqrt(2)) in NN # needs sage.rings.number_field sage.symbolic False - sage: RIF(1,2) in NN + sage: RIF(1,2) in NN # needs sage.rings.real_interval_field False sage: QQbar(2) in NN # needs sage.rings.number_field True - sage: RIF(2) in NN + sage: RIF(2) in NN # needs sage.rings.real_interval_field True """ try: diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 304d37ba1f1..f650fa7674b 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -1173,8 +1173,8 @@ def intersection(self, other): sage: X = Set(GF(8,'c')) # needs sage.rings.finite_rings sage: Y = Set([GF(8,'c').0, 1, 2, 3]) # needs sage.rings.finite_rings - sage: X.intersection(Y) # needs sage.rings.finite_rings - {1, c} + sage: sorted(X.intersection(Y), key=str) # needs sage.rings.finite_rings + [1, c] """ if not isinstance(other, Set_object_enumerated): return Set_object.intersection(self, other) From 0a5857108f41c49a5a836ae8aa2f4f5e2c304eb6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Sep 2023 09:47:44 -0700 Subject: [PATCH 095/225] sage.sets: Update # needs --- src/sage/sets/real_set.py | 22 ++++++++++------------ src/sage/sets/set.py | 26 +++++++++++++------------- src/sage/sets/set_from_iterator.py | 4 ++-- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/sage/sets/real_set.py b/src/sage/sets/real_set.py index df54230cc07..45394cba23c 100644 --- a/src/sage/sets/real_set.py +++ b/src/sage/sets/real_set.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.rings.real_mpfr +# sage.doctest: needs sage.rings.real_interval_field sage.rings.real_mpfr """ Subsets of the Real Line @@ -1043,15 +1043,14 @@ class RealSet(UniqueRepresentation, Parent, Set_base, Constructing real sets as manifolds or manifold subsets by passing ``structure='differentiable'``:: - sage: RealSet(-oo, oo, structure='differentiable') # needs sage.symbolic + sage: # needs sage.symbolic + sage: RealSet(-oo, oo, structure='differentiable') Real number line ℝ - - sage: RealSet([0, 1], structure='differentiable') # needs sage.symbolic + sage: RealSet([0, 1], structure='differentiable') Subset [0, 1] of the Real number line ℝ - sage: _.category() # needs sage.symbolic + sage: _.category() Category of subobjects of sets - - sage: RealSet.open_closed(0, 5, structure='differentiable') # needs sage.symbolic + sage: RealSet.open_closed(0, 5, structure='differentiable') Subset (0, 5] of the Real number line ℝ This is implied when a coordinate name is given using the keywords ``coordinate`` @@ -1086,12 +1085,11 @@ class RealSet(UniqueRepresentation, Parent, Set_base, Chart ((0, 1), (ξ,)) sage: R_xi.subset_family() Set {(0, +oo), (0, 1), ℝ} of open subsets of the Real number line ℝ - sage: F = RealSet.point(0).union(RealSet.point(1)).union(RealSet.point(2)); F {0} ∪ {1} ∪ {2} - sage: F_tau = RealSet(F, names="τ"); F_tau # needs sage.symbolic + sage: F_tau = RealSet(F, names="τ"); F_tau Subset {0} ∪ {1} ∪ {2} of the Real number line ℝ - sage: F_tau.manifold().canonical_chart() # needs sage.symbolic + sage: F_tau.manifold().canonical_chart() Chart (ℝ, (τ,)) TESTS:: @@ -1648,9 +1646,9 @@ def _sympy_condition_(self, variable): TESTS:: - sage: RealSet(6,6)._sympy_condition_(x) # needs sage.symbolic + sage: RealSet(6,6)._sympy_condition_(x) # needs sympy sage.symbolic False - sage: RealSet([6,6])._sympy_condition_(x) # needs sage.symbolic + sage: RealSet([6,6])._sympy_condition_(x) # needs sympy sage.symbolic Eq(x, 6) """ x = variable diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index f650fa7674b..a8854d0df2b 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -237,9 +237,9 @@ def union(self, X): True sage: GF(3)(2) in X # optional - sage.libs.pari True - sage: GF(5)(2) in X # needs sage.rings.finite_rings + sage: GF(5)(2) in X False - sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) # needs sage.rings.finite_rings + sage: sorted(Set(GF(7)) + Set(GF(3)), key=int) [0, 0, 1, 1, 2, 2, 3, 4, 5, 6] """ if isinstance(X, (Set_generic, Set_base)): @@ -417,7 +417,7 @@ def __add__(self, X): Set-theoretic union of Set of elements of Real Field with 53 bits of precision and Set of elements of Vector space of dimension 5 over Rational Field - sage: Set(GF(3)) + Set(GF(2)) # needs sage.rings.finite_rings + sage: Set(GF(3)) + Set(GF(2)) {0, 1, 2, 0, 1} sage: Set(GF(2)) + Set(GF(4,'a')) # needs sage.rings.finite_rings {0, 1, a, a + 1} @@ -631,9 +631,9 @@ def __contains__(self, x): False sage: 5/3 in GF(7) False - sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) # needs sage.rings.finite_rings + sage: sorted(Set(GF(7)).union(Set(GF(5))), key=int) [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6] - sage: Set(GF(7)).intersection(Set(GF(5))) # needs sage.rings.finite_rings + sage: Set(GF(7)).intersection(Set(GF(5))) {} """ return x in self.__object @@ -802,10 +802,10 @@ def subsets_lattice(self): EXAMPLES:: sage: X = Set([1,2,3]) - sage: X.subsets_lattice() # needs sage.combinat sage.graphs sage.modules + sage: X.subsets_lattice() # needs sage.graphs Finite lattice containing 8 elements sage: Y = Set() - sage: Y.subsets_lattice() # needs sage.combinat sage.graphs sage.modules + sage: Y.subsets_lattice() # needs sage.graphs Finite lattice containing 1 elements """ @@ -1465,7 +1465,7 @@ def __iter__(self): EXAMPLES:: - sage: [x for x in Set(GF(3)).union(Set(GF(2)))] # needs sage.rings.finite_rings + sage: [x for x in Set(GF(3)).union(Set(GF(2)))] [0, 1, 2, 0, 1] """ for x in self._X: @@ -1498,10 +1498,10 @@ def cardinality(self): EXAMPLES:: - sage: X = Set(GF(3)).union(Set(GF(2))) # needs sage.rings.finite_rings - sage: X # needs sage.rings.finite_rings + sage: X = Set(GF(3)).union(Set(GF(2))) + sage: X {0, 1, 2, 0, 1} - sage: X.cardinality() # needs sage.rings.finite_rings + sage: X.cardinality() 5 sage: X = Set(GF(3)).union(Set(ZZ)) @@ -1849,7 +1849,7 @@ def __contains__(self, x): False sage: sqrt(2) in X # since sqrt(2) is not a numerical approx # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is a numerical approx # needs sage.rings.real_interval_field True sage: 5/2 in X True @@ -2022,7 +2022,7 @@ def __contains__(self, x): False sage: sqrt(2) in X # since sqrt(2) is currently symbolic # needs sage.symbolic False - sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated + sage: sqrt(RR(2)) in X # since sqrt(RR(2)) is currently approximated # needs sage.rings.real_interval_field True sage: pi in X # needs sage.symbolic False diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index 7d97cfc4064..ef3e479c26c 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -533,8 +533,8 @@ def _sage_argspec_(self): sage: from sage.misc.sageinspect import sage_getargspec sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = find_local_minimum # needs scipy - sage: sage_getargspec(d) # indirect doctest # needs scipy + sage: d.f = find_local_minimum + sage: sage_getargspec(d) # indirect doctest FullArgSpec(args=['f', 'a', 'b', 'tol', 'maxfun'], varargs=None, varkw=None, defaults=(1.48e-08, 500), kwonlyargs=[], kwonlydefaults=None, annotations={}) From 0a28f0c09eec718b8a2950dc4f95775ae0e14979 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Sep 2023 09:10:49 -0700 Subject: [PATCH 096/225] src/sage/sets/set_from_iterator.py: Fix # needs --- src/sage/sets/set_from_iterator.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index ef3e479c26c..4b78c2cb59e 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -511,12 +511,13 @@ def _sage_src_lines_(self): TESTS:: + sage: # needs sage.groups sage: from sage.misc.sageinspect import sage_getsourcelines sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() - sage: d.f = MathieuGroup.order # needs sage.groups - sage: S = sage_getsourcelines(d) # indirect doctest # needs sage.groups - sage: S[0][2] # needs sage.groups + sage: d.f = MathieuGroup.order + sage: S = sage_getsourcelines(d) # indirect doctest + sage: S[0][2] ' Return the number of elements of this group.\n' sage: S[0][25] # needs sage.groups ' if not gens:\n' @@ -530,6 +531,7 @@ def _sage_argspec_(self): TESTS:: + sage: # needs sage.modules sage: from sage.misc.sageinspect import sage_getargspec sage: from sage.sets.set_from_iterator import Decorator sage: d = Decorator() From eac6dc37687f56481adcb8a564734b7a7275c4fa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 11:42:48 -0700 Subject: [PATCH 097/225] sage -fixdoctests --no-test --only-tags src/sage/sets --- src/sage/sets/set.py | 4 ++-- src/sage/sets/set_from_iterator.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index a8854d0df2b..117b830621a 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -235,7 +235,7 @@ def union(self, X): {0, 1, 2} sage: 2/3 in X True - sage: GF(3)(2) in X # optional - sage.libs.pari + sage: GF(3)(2) in X # needs sage.libs.pari True sage: GF(5)(2) in X False @@ -612,7 +612,7 @@ def __contains__(self, x): sage: X = Set(ZZ) sage: 5 in X True - sage: GF(7)(3) in X # optional - sage.libs.pari + sage: GF(7)(3) in X # needs sage.libs.pari True sage: 2/1 in X True diff --git a/src/sage/sets/set_from_iterator.py b/src/sage/sets/set_from_iterator.py index 4b78c2cb59e..5123879673a 100644 --- a/src/sage/sets/set_from_iterator.py +++ b/src/sage/sets/set_from_iterator.py @@ -519,7 +519,7 @@ def _sage_src_lines_(self): sage: S = sage_getsourcelines(d) # indirect doctest sage: S[0][2] ' Return the number of elements of this group.\n' - sage: S[0][25] # needs sage.groups + sage: S[0][25] ' if not gens:\n' """ from sage.misc.sageinspect import sage_getsourcelines From 795932fe4bed897b3e938b2a0ae47563b746d6c3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 4 Jul 2023 19:08:26 -0700 Subject: [PATCH 098/225] src/sage/combinat/designs/block_design.py: Style fixes --- src/sage/combinat/designs/block_design.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/designs/block_design.py b/src/sage/combinat/designs/block_design.py index 057af5c969c..69f73dc92a0 100644 --- a/src/sage/combinat/designs/block_design.py +++ b/src/sage/combinat/designs/block_design.py @@ -934,12 +934,13 @@ def WittDesign(n): EXAMPLES:: - sage: BD = designs.WittDesign(9) # optional - gap_package_design - sage: BD.is_t_design(return_parameters=True) # optional - gap_package_design + sage: # optional - gap_packages (design package) + sage: BD = designs.WittDesign(9) + sage: BD.is_t_design(return_parameters=True) (True, (2, 9, 3, 1)) - sage: BD # optional - gap_package_design + sage: BD Incidence structure with 9 points and 12 blocks - sage: print(BD) # optional - gap_package_design + sage: print(BD) Incidence structure with 9 points and 12 blocks """ libgap.load_package("design") From ddde9f23a76a77957cc7fa59edfdd4ad342ea09f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 6 Aug 2023 20:45:03 -0700 Subject: [PATCH 099/225] src/sage/combinat: Update file-level doctest tag --- src/sage/combinat/affine_permutation.py | 1 + src/sage/combinat/alternating_sign_matrix.py | 2 +- src/sage/combinat/bijectionist.py | 1 + src/sage/combinat/binary_recurrence_sequences.py | 1 + src/sage/combinat/blob_algebra.py | 2 +- src/sage/combinat/chas/fsym.py | 1 + src/sage/combinat/chas/wqsym.py | 2 +- src/sage/combinat/cluster_complex.py | 1 + src/sage/combinat/constellation.py | 2 +- src/sage/combinat/crystals/affine.py | 1 + src/sage/combinat/crystals/affine_factorization.py | 1 + src/sage/combinat/crystals/affinization.py | 1 + src/sage/combinat/crystals/alcove_path.py | 1 + src/sage/combinat/crystals/bkk_crystals.py | 1 + src/sage/combinat/crystals/crystals.py | 1 + src/sage/combinat/crystals/direct_sum.py | 1 + src/sage/combinat/crystals/elementary_crystals.py | 1 + src/sage/combinat/crystals/fast_crystals.py | 1 + .../combinat/crystals/fully_commutative_stable_grothendieck.py | 1 + src/sage/combinat/crystals/generalized_young_walls.py | 2 +- src/sage/combinat/crystals/highest_weight_crystals.py | 1 + src/sage/combinat/crystals/induced_structure.py | 1 + src/sage/combinat/crystals/infinity_crystals.py | 1 + src/sage/combinat/crystals/kac_modules.py | 1 + src/sage/combinat/crystals/kirillov_reshetikhin.py | 1 + src/sage/combinat/crystals/kyoto_path_model.py | 1 + src/sage/combinat/crystals/letters.pyx | 2 +- src/sage/combinat/crystals/littelmann_path.py | 1 + src/sage/combinat/crystals/monomial_crystals.py | 1 + src/sage/combinat/crystals/multisegments.py | 1 + src/sage/combinat/crystals/mv_polytopes.py | 2 +- src/sage/combinat/crystals/pbw_crystal.py | 2 +- src/sage/combinat/crystals/pbw_datum.pyx | 2 +- src/sage/combinat/crystals/polyhedral_realization.py | 1 + src/sage/combinat/crystals/spins.pyx | 2 +- src/sage/combinat/crystals/star_crystal.py | 1 + src/sage/combinat/crystals/subcrystal.py | 1 + src/sage/combinat/crystals/tensor_product.py | 1 + src/sage/combinat/crystals/tensor_product_element.pyx | 2 +- src/sage/combinat/crystals/virtual_crystal.py | 1 + src/sage/combinat/descent_algebra.py | 1 + src/sage/combinat/diagram_algebras.py | 2 +- src/sage/combinat/e_one_star.py | 1 + src/sage/combinat/finite_state_machine.py | 2 +- src/sage/combinat/finite_state_machine_generators.py | 2 +- src/sage/combinat/fqsym.py | 2 +- src/sage/combinat/free_dendriform_algebra.py | 2 +- src/sage/combinat/free_prelie_algebra.py | 2 +- src/sage/combinat/fully_commutative_elements.py | 1 + src/sage/combinat/fully_packed_loop.py | 1 + src/sage/combinat/grossman_larson_algebras.py | 2 +- src/sage/combinat/growth.py | 2 +- src/sage/combinat/hall_polynomial.py | 1 + src/sage/combinat/integer_matrices.py | 1 + src/sage/combinat/integer_vectors_mod_permgroup.py | 2 +- src/sage/combinat/k_tableau.py | 1 + src/sage/combinat/kazhdan_lusztig.py | 1 + src/sage/combinat/key_polynomial.py | 1 + src/sage/combinat/matrices/hadamard_matrix.py | 1 + src/sage/combinat/matrices/latin.py | 1 + src/sage/combinat/ncsf_qsym/generic_basis_code.py | 1 + src/sage/combinat/ncsf_qsym/ncsf.py | 2 +- src/sage/combinat/ncsf_qsym/qsym.py | 2 +- src/sage/combinat/ncsf_qsym/tutorial.py | 2 +- src/sage/combinat/ncsym/bases.py | 1 + src/sage/combinat/ncsym/dual.py | 1 + src/sage/combinat/ncsym/ncsym.py | 1 + src/sage/combinat/nu_dyck_word.py | 2 +- src/sage/combinat/nu_tamari_lattice.py | 2 +- src/sage/combinat/parallelogram_polyomino.py | 2 +- src/sage/combinat/partition_algebra.py | 1 + src/sage/combinat/partition_kleshchev.py | 1 + src/sage/combinat/partition_shifting_algebras.py | 2 +- src/sage/combinat/posets/d_complete.py | 1 + src/sage/combinat/posets/incidence_algebras.py | 2 +- src/sage/combinat/posets/lattices.py | 2 +- src/sage/combinat/posets/moebius_algebra.py | 2 +- src/sage/combinat/recognizable_series.py | 2 +- src/sage/combinat/regular_sequence.py | 2 +- src/sage/combinat/rigged_configurations/bij_abstract_class.py | 1 + src/sage/combinat/rigged_configurations/bij_infinity.py | 1 + src/sage/combinat/rigged_configurations/bij_type_A.py | 1 + src/sage/combinat/rigged_configurations/bij_type_A2_dual.py | 1 + src/sage/combinat/rigged_configurations/bij_type_A2_even.py | 1 + src/sage/combinat/rigged_configurations/bij_type_A2_odd.py | 1 + src/sage/combinat/rigged_configurations/bij_type_B.py | 1 + src/sage/combinat/rigged_configurations/bij_type_C.py | 1 + src/sage/combinat/rigged_configurations/bij_type_D.py | 1 + src/sage/combinat/rigged_configurations/bij_type_D_tri.py | 1 + src/sage/combinat/rigged_configurations/bij_type_D_twisted.py | 1 + src/sage/combinat/rigged_configurations/bij_type_E67.py | 1 + src/sage/combinat/rigged_configurations/bijection.py | 1 + src/sage/combinat/rigged_configurations/kleber_tree.py | 1 + src/sage/combinat/rigged_configurations/kr_tableaux.py | 2 +- src/sage/combinat/rigged_configurations/rc_crystal.py | 1 + src/sage/combinat/rigged_configurations/rc_infinity.py | 1 + .../rigged_configurations/rigged_configuration_element.py | 1 + .../combinat/rigged_configurations/rigged_configurations.py | 1 + src/sage/combinat/rigged_configurations/rigged_partition.pyx | 1 + .../rigged_configurations/tensor_product_kr_tableaux.py | 1 + .../rigged_configurations/tensor_product_kr_tableaux_element.py | 1 + src/sage/combinat/rsk.py | 1 + src/sage/combinat/schubert_polynomial.py | 1 + src/sage/combinat/sf/character.py | 1 + src/sage/combinat/sf/classical.py | 1 + src/sage/combinat/sf/dual.py | 1 + src/sage/combinat/sf/elementary.py | 1 + src/sage/combinat/sf/hall_littlewood.py | 1 + src/sage/combinat/sf/hecke.py | 1 + src/sage/combinat/sf/homogeneous.py | 1 + src/sage/combinat/sf/jack.py | 1 + src/sage/combinat/sf/k_dual.py | 1 + src/sage/combinat/sf/kfpoly.py | 1 + src/sage/combinat/sf/llt.py | 1 + src/sage/combinat/sf/macdonald.py | 1 + src/sage/combinat/sf/monomial.py | 1 + src/sage/combinat/sf/multiplicative.py | 1 + src/sage/combinat/sf/new_kschur.py | 1 + src/sage/combinat/sf/ns_macdonald.py | 1 + src/sage/combinat/sf/orthogonal.py | 1 + src/sage/combinat/sf/orthotriang.py | 1 + src/sage/combinat/sf/powersum.py | 1 + src/sage/combinat/sf/schur.py | 1 + src/sage/combinat/sf/sf.py | 1 + src/sage/combinat/sf/sfa.py | 1 + src/sage/combinat/sf/symplectic.py | 1 + src/sage/combinat/sf/witt.py | 1 + src/sage/combinat/shifted_primed_tableau.py | 2 +- src/sage/combinat/similarity_class_type.py | 1 + src/sage/combinat/sloane_functions.py | 2 +- src/sage/combinat/specht_module.py | 1 + src/sage/combinat/species/misc.py | 1 + src/sage/combinat/species/partition_species.py | 1 + src/sage/combinat/species/permutation_species.py | 1 + src/sage/combinat/subword_complex.py | 1 + src/sage/combinat/subword_complex_c.pyx | 2 ++ src/sage/combinat/symmetric_group_algebra.py | 2 +- src/sage/combinat/symmetric_group_representations.py | 1 + src/sage/combinat/tamari_lattices.py | 2 +- src/sage/combinat/tiling.py | 2 +- src/sage/combinat/words/paths.py | 2 +- 141 files changed, 142 insertions(+), 39 deletions(-) diff --git a/src/sage/combinat/affine_permutation.py b/src/sage/combinat/affine_permutation.py index 13144414cb9..abf9017119b 100644 --- a/src/sage/combinat/affine_permutation.py +++ b/src/sage/combinat/affine_permutation.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups r""" Affine Permutations """ diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index 80d4ab301b7..a42b7a2898c 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Alternating Sign Matrices diff --git a/src/sage/combinat/bijectionist.py b/src/sage/combinat/bijectionist.py index 68d1f322e9f..00053209d4e 100644 --- a/src/sage/combinat/bijectionist.py +++ b/src/sage/combinat/bijectionist.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.numerical.mip r""" A bijectionist's toolkit diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index 9527c512360..04223d9975a 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Binary Recurrence Sequences diff --git a/src/sage/combinat/blob_algebra.py b/src/sage/combinat/blob_algebra.py index 657c70a5c0e..595063a69fd 100644 --- a/src/sage/combinat/blob_algebra.py +++ b/src/sage/combinat/blob_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Blob Algebras diff --git a/src/sage/combinat/chas/fsym.py b/src/sage/combinat/chas/fsym.py index a2dfd12f621..f1c149c66f1 100644 --- a/src/sage/combinat/chas/fsym.py +++ b/src/sage/combinat/chas/fsym.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Poirier-Reutenauer Hopf algebra of standard tableaux diff --git a/src/sage/combinat/chas/wqsym.py b/src/sage/combinat/chas/wqsym.py index 99659ab154a..57b90761c88 100644 --- a/src/sage/combinat/chas/wqsym.py +++ b/src/sage/combinat/chas/wqsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Word Quasi-symmetric functions diff --git a/src/sage/combinat/cluster_complex.py b/src/sage/combinat/cluster_complex.py index e263d983887..a1f7489f1ad 100644 --- a/src/sage/combinat/cluster_complex.py +++ b/src/sage/combinat/cluster_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs r""" Cluster complex (or generalized dual associahedron) diff --git a/src/sage/combinat/constellation.py b/src/sage/combinat/constellation.py index 8f7274cc256..6ab7c474a24 100644 --- a/src/sage/combinat/constellation.py +++ b/src/sage/combinat/constellation.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.groups r""" Constellations diff --git a/src/sage/combinat/crystals/affine.py b/src/sage/combinat/crystals/affine.py index c33fe853152..186d2ea373e 100644 --- a/src/sage/combinat/crystals/affine.py +++ b/src/sage/combinat/crystals/affine.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affine Crystals """ diff --git a/src/sage/combinat/crystals/affine_factorization.py b/src/sage/combinat/crystals/affine_factorization.py index eca08c2f3bd..ced7de7ed17 100644 --- a/src/sage/combinat/crystals/affine_factorization.py +++ b/src/sage/combinat/crystals/affine_factorization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affine factorization crystal of type `A` """ diff --git a/src/sage/combinat/crystals/affinization.py b/src/sage/combinat/crystals/affinization.py index 2a58d8ab609..d849e407c3f 100644 --- a/src/sage/combinat/crystals/affinization.py +++ b/src/sage/combinat/crystals/affinization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affinization Crystals """ diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index ef1ad7a9c75..045ff0a4fa4 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Alcove paths diff --git a/src/sage/combinat/crystals/bkk_crystals.py b/src/sage/combinat/crystals/bkk_crystals.py index 15e795ca484..b3658fd28a4 100644 --- a/src/sage/combinat/crystals/bkk_crystals.py +++ b/src/sage/combinat/crystals/bkk_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Benkart-Kang-Kashiwara crystals for the general-linear Lie superalgebra """ diff --git a/src/sage/combinat/crystals/crystals.py b/src/sage/combinat/crystals/crystals.py index dbc2e9a211f..b68469ce8ba 100644 --- a/src/sage/combinat/crystals/crystals.py +++ b/src/sage/combinat/crystals/crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" An introduction to crystals =========================== diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index e66ea6e9ef5..f94570091d8 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Direct Sum of Crystals """ diff --git a/src/sage/combinat/crystals/elementary_crystals.py b/src/sage/combinat/crystals/elementary_crystals.py index 2aa68d0279e..c89dd7504fd 100644 --- a/src/sage/combinat/crystals/elementary_crystals.py +++ b/src/sage/combinat/crystals/elementary_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Elementary Crystals diff --git a/src/sage/combinat/crystals/fast_crystals.py b/src/sage/combinat/crystals/fast_crystals.py index d12812f8bce..a989c296599 100644 --- a/src/sage/combinat/crystals/fast_crystals.py +++ b/src/sage/combinat/crystals/fast_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fast Rank Two Crystals """ diff --git a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py index caa2c52fdbc..930cb718143 100644 --- a/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py +++ b/src/sage/combinat/crystals/fully_commutative_stable_grothendieck.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully commutative stable Grothendieck crystal diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index 0ff8a9d3805..cac42b0c33c 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of Generalized Young Walls diff --git a/src/sage/combinat/crystals/highest_weight_crystals.py b/src/sage/combinat/crystals/highest_weight_crystals.py index 1b1d7f315e8..96d7377c029 100644 --- a/src/sage/combinat/crystals/highest_weight_crystals.py +++ b/src/sage/combinat/crystals/highest_weight_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Highest weight crystals """ diff --git a/src/sage/combinat/crystals/induced_structure.py b/src/sage/combinat/crystals/induced_structure.py index 2920fb67b7c..95ed85bf5f8 100644 --- a/src/sage/combinat/crystals/induced_structure.py +++ b/src/sage/combinat/crystals/induced_structure.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Induced Crystals diff --git a/src/sage/combinat/crystals/infinity_crystals.py b/src/sage/combinat/crystals/infinity_crystals.py index 32536d9de60..6219da38391 100644 --- a/src/sage/combinat/crystals/infinity_crystals.py +++ b/src/sage/combinat/crystals/infinity_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" `\mathcal{B}(\infty)` Crystals of Tableaux in Nonexceptional Types and `G_2` diff --git a/src/sage/combinat/crystals/kac_modules.py b/src/sage/combinat/crystals/kac_modules.py index d9da3fd8bff..79d753ac9ae 100644 --- a/src/sage/combinat/crystals/kac_modules.py +++ b/src/sage/combinat/crystals/kac_modules.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Crystals of Kac modules of the general-linear Lie superalgebra """ diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 5f79d8e1898..f06a91740e7 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kirillov-Reshetikhin Crystals """ diff --git a/src/sage/combinat/crystals/kyoto_path_model.py b/src/sage/combinat/crystals/kyoto_path_model.py index ff4c69e9ff9..e7ae0b47275 100644 --- a/src/sage/combinat/crystals/kyoto_path_model.py +++ b/src/sage/combinat/crystals/kyoto_path_model.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kyoto Path Model for Affine Highest Weight Crystals """ diff --git a/src/sage/combinat/crystals/letters.pyx b/src/sage/combinat/crystals/letters.pyx index 921be80c434..d204a979563 100644 --- a/src/sage/combinat/crystals/letters.pyx +++ b/src/sage/combinat/crystals/letters.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of letters """ diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index c384a818e56..a90a61cb4c9 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Littelmann paths diff --git a/src/sage/combinat/crystals/monomial_crystals.py b/src/sage/combinat/crystals/monomial_crystals.py index 44d0c1cb4bd..95657cba3f4 100644 --- a/src/sage/combinat/crystals/monomial_crystals.py +++ b/src/sage/combinat/crystals/monomial_crystals.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystals of Modified Nakajima Monomials diff --git a/src/sage/combinat/crystals/multisegments.py b/src/sage/combinat/crystals/multisegments.py index a3d0d661015..6f63d4562a3 100644 --- a/src/sage/combinat/crystals/multisegments.py +++ b/src/sage/combinat/crystals/multisegments.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystal of Bernstein-Zelevinsky Multisegments """ diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index cd6a4497d8e..67967f88bd0 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Crystal Of Mirković-Vilonen (MV) Polytopes diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index b03ace896b4..0b07bd01c6b 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" `\mathcal{B}(\infty)` Crystal Of PBW Monomials diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index dd27d91294a..2adcb09d902 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" PBW Data diff --git a/src/sage/combinat/crystals/polyhedral_realization.py b/src/sage/combinat/crystals/polyhedral_realization.py index f4f20fe84f7..c4193b44655 100644 --- a/src/sage/combinat/crystals/polyhedral_realization.py +++ b/src/sage/combinat/crystals/polyhedral_realization.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Polyhedral Realization of `B(\infty)` """ diff --git a/src/sage/combinat/crystals/spins.pyx b/src/sage/combinat/crystals/spins.pyx index 0798a534077..7548b7b695e 100644 --- a/src/sage/combinat/crystals/spins.pyx +++ b/src/sage/combinat/crystals/spins.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Spin Crystals diff --git a/src/sage/combinat/crystals/star_crystal.py b/src/sage/combinat/crystals/star_crystal.py index 2b4ac9c90a8..02427149ed4 100644 --- a/src/sage/combinat/crystals/star_crystal.py +++ b/src/sage/combinat/crystals/star_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Star-Crystal Structure On `B(\infty)` diff --git a/src/sage/combinat/crystals/subcrystal.py b/src/sage/combinat/crystals/subcrystal.py index b1221b51e88..e712abd38c8 100644 --- a/src/sage/combinat/crystals/subcrystal.py +++ b/src/sage/combinat/crystals/subcrystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Subcrystals diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index 0318f6528ae..b88405a083c 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Tensor Products of Crystals diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index a95d2060b4b..bafdb5e175a 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Tensor Products of Crystal Elements diff --git a/src/sage/combinat/crystals/virtual_crystal.py b/src/sage/combinat/crystals/virtual_crystal.py index f14bf59dd42..a4cdc8b4ee8 100644 --- a/src/sage/combinat/crystals/virtual_crystal.py +++ b/src/sage/combinat/crystals/virtual_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Virtual Crystals diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index 8945c697c1e..3468d80b4b7 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Descent Algebras diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 693b8dfe269..11d96acced8 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Diagram and Partition Algebras diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index cb6e5607931..a41e116d068 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Substitutions over unit cube faces (Rauzy fractals) diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 494e8154c80..4c75a15305c 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.modules r""" Finite state machines, automata, transducers diff --git a/src/sage/combinat/finite_state_machine_generators.py b/src/sage/combinat/finite_state_machine_generators.py index b5b8abbbd9e..24d027c03d0 100644 --- a/src/sage/combinat/finite_state_machine_generators.py +++ b/src/sage/combinat/finite_state_machine_generators.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.graphs sage.modules r""" Common Automata and Transducers (Finite State Machines Generators) diff --git a/src/sage/combinat/fqsym.py b/src/sage/combinat/fqsym.py index 03c53e6520b..48780725faa 100644 --- a/src/sage/combinat/fqsym.py +++ b/src/sage/combinat/fqsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Free Quasi-symmetric functions diff --git a/src/sage/combinat/free_dendriform_algebra.py b/src/sage/combinat/free_dendriform_algebra.py index 1bdcd1dbe31..fb1cb498c79 100644 --- a/src/sage/combinat/free_dendriform_algebra.py +++ b/src/sage/combinat/free_dendriform_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Free Dendriform Algebras diff --git a/src/sage/combinat/free_prelie_algebra.py b/src/sage/combinat/free_prelie_algebra.py index 2354cbbe576..965c459720c 100644 --- a/src/sage/combinat/free_prelie_algebra.py +++ b/src/sage/combinat/free_prelie_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Free Pre-Lie Algebras diff --git a/src/sage/combinat/fully_commutative_elements.py b/src/sage/combinat/fully_commutative_elements.py index 79237fefe42..200b98b2f36 100644 --- a/src/sage/combinat/fully_commutative_elements.py +++ b/src/sage/combinat/fully_commutative_elements.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully commutative elements of Coxeter groups diff --git a/src/sage/combinat/fully_packed_loop.py b/src/sage/combinat/fully_packed_loop.py index de1bf3e5269..ca4bf09b1b0 100644 --- a/src/sage/combinat/fully_packed_loop.py +++ b/src/sage/combinat/fully_packed_loop.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fully packed loops diff --git a/src/sage/combinat/grossman_larson_algebras.py b/src/sage/combinat/grossman_larson_algebras.py index 8fcf8a2e5ec..db2f1de5eca 100644 --- a/src/sage/combinat/grossman_larson_algebras.py +++ b/src/sage/combinat/grossman_larson_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Grossman-Larson Hopf Algebras diff --git a/src/sage/combinat/growth.py b/src/sage/combinat/growth.py index cf8d18c1764..86d5070a590 100644 --- a/src/sage/combinat/growth.py +++ b/src/sage/combinat/growth.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs r""" Growth diagrams and dual graded graphs diff --git a/src/sage/combinat/hall_polynomial.py b/src/sage/combinat/hall_polynomial.py index 19d65bc2263..9d2326e60f8 100644 --- a/src/sage/combinat/hall_polynomial.py +++ b/src/sage/combinat/hall_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hall Polynomials """ diff --git a/src/sage/combinat/integer_matrices.py b/src/sage/combinat/integer_matrices.py index 75e8e896db8..8d737c64349 100644 --- a/src/sage/combinat/integer_matrices.py +++ b/src/sage/combinat/integer_matrices.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Counting, generating, and manipulating non-negative integer matrices diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 46365a26eeb..21d36fbc425 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -1,4 +1,4 @@ -# optional - sage.combinat sage.groups +# sage.doctest: needs sage.combinat sage.groups r""" Integer vectors modulo the action of a permutation group """ diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 77264231908..aafa4eb3618 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Strong and weak tableaux diff --git a/src/sage/combinat/kazhdan_lusztig.py b/src/sage/combinat/kazhdan_lusztig.py index 0c213ea9013..11e50379d1d 100644 --- a/src/sage/combinat/kazhdan_lusztig.py +++ b/src/sage/combinat/kazhdan_lusztig.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kazhdan-Lusztig Polynomials diff --git a/src/sage/combinat/key_polynomial.py b/src/sage/combinat/key_polynomial.py index d132b037de3..43db18cc72f 100644 --- a/src/sage/combinat/key_polynomial.py +++ b/src/sage/combinat/key_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Key polynomials diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 6174fe3df50..308721707fe 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs sage.modules r""" Hadamard matrices diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py index e36edf0fc82..29d4ce3adaf 100644 --- a/src/sage/combinat/matrices/latin.py +++ b/src/sage/combinat/matrices/latin.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups sage.modules r""" Latin Squares diff --git a/src/sage/combinat/ncsf_qsym/generic_basis_code.py b/src/sage/combinat/ncsf_qsym/generic_basis_code.py index 012f8bd7ce1..ec64af20164 100644 --- a/src/sage/combinat/ncsf_qsym/generic_basis_code.py +++ b/src/sage/combinat/ncsf_qsym/generic_basis_code.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Generic code for bases diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f9aafb014aa..b1bf18c4ae6 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Non-Commutative Symmetric Functions """ diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index fe4e58277b1..c4f6b1ff0f3 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Quasisymmetric functions diff --git a/src/sage/combinat/ncsf_qsym/tutorial.py b/src/sage/combinat/ncsf_qsym/tutorial.py index 78978507cb3..4b7f1d199ae 100644 --- a/src/sage/combinat/ncsf_qsym/tutorial.py +++ b/src/sage/combinat/ncsf_qsym/tutorial.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Introduction to Quasisymmetric Functions diff --git a/src/sage/combinat/ncsym/bases.py b/src/sage/combinat/ncsym/bases.py index 8b703487547..9d4aac2cdf1 100644 --- a/src/sage/combinat/ncsym/bases.py +++ b/src/sage/combinat/ncsym/bases.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bases for `NCSym` diff --git a/src/sage/combinat/ncsym/dual.py b/src/sage/combinat/ncsym/dual.py index 5acd9c8f176..4b2ca62f86d 100644 --- a/src/sage/combinat/ncsym/dual.py +++ b/src/sage/combinat/ncsym/dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Dual Symmetric Functions in Non-Commuting Variables diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 64772ade2d7..dfc77b9b7bc 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric Functions in Non-Commuting Variables diff --git a/src/sage/combinat/nu_dyck_word.py b/src/sage/combinat/nu_dyck_word.py index efb0af7f572..654b9a4c2a3 100644 --- a/src/sage/combinat/nu_dyck_word.py +++ b/src/sage/combinat/nu_dyck_word.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" `\nu`-Dyck Words diff --git a/src/sage/combinat/nu_tamari_lattice.py b/src/sage/combinat/nu_tamari_lattice.py index 0d6b391aa8b..433b7058cf5 100644 --- a/src/sage/combinat/nu_tamari_lattice.py +++ b/src/sage/combinat/nu_tamari_lattice.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat r""" `\nu`-Tamari lattice diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index 9c4ceedfd19..9aea6a3aaf5 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Parallelogram Polyominoes ========================= diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 0b7eb06c3a5..cca9b164aec 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Partition/Diagram Algebras """ diff --git a/src/sage/combinat/partition_kleshchev.py b/src/sage/combinat/partition_kleshchev.py index 18db4ff3424..bdc24c64ca8 100644 --- a/src/sage/combinat/partition_kleshchev.py +++ b/src/sage/combinat/partition_kleshchev.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kleshchev partitions ==================== diff --git a/src/sage/combinat/partition_shifting_algebras.py b/src/sage/combinat/partition_shifting_algebras.py index 7dfee4fa460..e8f22589eb3 100644 --- a/src/sage/combinat/partition_shifting_algebras.py +++ b/src/sage/combinat/partition_shifting_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Partition Shifting Algebras diff --git a/src/sage/combinat/posets/d_complete.py b/src/sage/combinat/posets/d_complete.py index 6bfe6eca61e..aa3c527ef8f 100644 --- a/src/sage/combinat/posets/d_complete.py +++ b/src/sage/combinat/posets/d_complete.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" D-Complete Posets diff --git a/src/sage/combinat/posets/incidence_algebras.py b/src/sage/combinat/posets/incidence_algebras.py index 204c4661b3b..dfd18f8c338 100644 --- a/src/sage/combinat/posets/incidence_algebras.py +++ b/src/sage/combinat/posets/incidence_algebras.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Incidence Algebras """ diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 99e403765f8..45f5715f0e7 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Finite lattices and semilattices diff --git a/src/sage/combinat/posets/moebius_algebra.py b/src/sage/combinat/posets/moebius_algebra.py index aada2725078..00691051587 100644 --- a/src/sage/combinat/posets/moebius_algebra.py +++ b/src/sage/combinat/posets/moebius_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Möbius Algebras """ diff --git a/src/sage/combinat/recognizable_series.py b/src/sage/combinat/recognizable_series.py index ca2f11bd6ff..698dd959619 100644 --- a/src/sage/combinat/recognizable_series.py +++ b/src/sage/combinat/recognizable_series.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.modules +# sage.doctest: needs sage.combinat sage.modules r""" Recognizable Series diff --git a/src/sage/combinat/regular_sequence.py b/src/sage/combinat/regular_sequence.py index afb83bed6f7..a10ceb7cf17 100644 --- a/src/sage/combinat/regular_sequence.py +++ b/src/sage/combinat/regular_sequence.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - sage.combinat sage.modules sage.symbolic +# sage.doctest: needs sage.combinat sage.modules sage.symbolic r""" `k`-regular sequences diff --git a/src/sage/combinat/rigged_configurations/bij_abstract_class.py b/src/sage/combinat/rigged_configurations/bij_abstract_class.py index 66ad0ac37ce..520ce241d57 100644 --- a/src/sage/combinat/rigged_configurations/bij_abstract_class.py +++ b/src/sage/combinat/rigged_configurations/bij_abstract_class.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Abstract classes for the rigged configuration bijections diff --git a/src/sage/combinat/rigged_configurations/bij_infinity.py b/src/sage/combinat/rigged_configurations/bij_infinity.py index 8d9700e168a..0fd8ee7fdc9 100644 --- a/src/sage/combinat/rigged_configurations/bij_infinity.py +++ b/src/sage/combinat/rigged_configurations/bij_infinity.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection between rigged configurations for `B(\infty)` and marginally large tableaux diff --git a/src/sage/combinat/rigged_configurations/bij_type_A.py b/src/sage/combinat/rigged_configurations/bij_type_A.py index 198ba0fc433..2a623f322da 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py b/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py index dee72713e12..ceb6ad8f1b8 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n}^{(2)\dagger}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_even.py b/src/sage/combinat/rigged_configurations/bij_type_A2_even.py index 1c0d587139a..8fa552a1077 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_even.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_even.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n}^{(2)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py b/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py index 42a8cf956fb..ea7862ef3ef 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py +++ b/src/sage/combinat/rigged_configurations/bij_type_A2_odd.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `A_{2n-1}^{(2)}`. diff --git a/src/sage/combinat/rigged_configurations/bij_type_B.py b/src/sage/combinat/rigged_configurations/bij_type_B.py index fd924150380..299f9e2e94c 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_B.py +++ b/src/sage/combinat/rigged_configurations/bij_type_B.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `B_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_C.py b/src/sage/combinat/rigged_configurations/bij_type_C.py index d04267b5569..9e0997e1479 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_C.py +++ b/src/sage/combinat/rigged_configurations/bij_type_C.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `C_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D.py b/src/sage/combinat/rigged_configurations/bij_type_D.py index 12fb6c6be2c..ab9b41b89bd 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_n^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D_tri.py b/src/sage/combinat/rigged_configurations/bij_type_D_tri.py index f143b3ce38a..b82ff955642 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D_tri.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D_tri.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_4^{(3)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py b/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py index dbc049d6ae0..ce177ffb468 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py +++ b/src/sage/combinat/rigged_configurations/bij_type_D_twisted.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `D_{n+1}^{(2)}` diff --git a/src/sage/combinat/rigged_configurations/bij_type_E67.py b/src/sage/combinat/rigged_configurations/bij_type_E67.py index 3d258443276..af59d3048f5 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_E67.py +++ b/src/sage/combinat/rigged_configurations/bij_type_E67.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection classes for type `E_{6,7}^{(1)}` diff --git a/src/sage/combinat/rigged_configurations/bijection.py b/src/sage/combinat/rigged_configurations/bijection.py index f312f12930c..850270930a6 100644 --- a/src/sage/combinat/rigged_configurations/bijection.py +++ b/src/sage/combinat/rigged_configurations/bijection.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bijection between rigged configurations and KR tableaux diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index 405adcdb71a..568c6f465f2 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Kleber Trees diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 84e3db6640c..3addee9e2e5 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Kirillov-Reshetikhin Tableaux diff --git a/src/sage/combinat/rigged_configurations/rc_crystal.py b/src/sage/combinat/rigged_configurations/rc_crystal.py index dbd7fd047fe..647d3c6eb0d 100644 --- a/src/sage/combinat/rigged_configurations/rc_crystal.py +++ b/src/sage/combinat/rigged_configurations/rc_crystal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Crystal of Rigged Configurations diff --git a/src/sage/combinat/rigged_configurations/rc_infinity.py b/src/sage/combinat/rigged_configurations/rc_infinity.py index b988c5a6ff2..e592f9b3656 100644 --- a/src/sage/combinat/rigged_configurations/rc_infinity.py +++ b/src/sage/combinat/rigged_configurations/rc_infinity.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configurations of `\mathcal{B}(\infty)` diff --git a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py index 542649cf9dd..088dd64f20f 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py +++ b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configuration Elements diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index a7073a700bb..b822a668612 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Configurations diff --git a/src/sage/combinat/rigged_configurations/rigged_partition.pyx b/src/sage/combinat/rigged_configurations/rigged_partition.pyx index d5ecb7c778d..694b3dd5977 100644 --- a/src/sage/combinat/rigged_configurations/rigged_partition.pyx +++ b/src/sage/combinat/rigged_configurations/rigged_partition.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Rigged Partitions diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index ce4c2ad2ab4..3314986004f 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tensor Product of Kirillov-Reshetikhin Tableaux diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py index c816d2140a6..8db94443af2 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tensor Product of Kirillov-Reshetikhin Tableaux Elements diff --git a/src/sage/combinat/rsk.py b/src/sage/combinat/rsk.py index 1a4ae2e548f..2c787878768 100644 --- a/src/sage/combinat/rsk.py +++ b/src/sage/combinat/rsk.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Robinson-Schensted-Knuth correspondence diff --git a/src/sage/combinat/schubert_polynomial.py b/src/sage/combinat/schubert_polynomial.py index 441dbbe3317..e4611fcdc55 100644 --- a/src/sage/combinat/schubert_polynomial.py +++ b/src/sage/combinat/schubert_polynomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Schubert Polynomials diff --git a/src/sage/combinat/sf/character.py b/src/sage/combinat/sf/character.py index eda80d2d1c3..3bd8ab5e0a1 100644 --- a/src/sage/combinat/sf/character.py +++ b/src/sage/combinat/sf/character.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Characters of the symmetric group as bases of the symmetric functions diff --git a/src/sage/combinat/sf/classical.py b/src/sage/combinat/sf/classical.py index 73bf285c14f..3151566ed6d 100644 --- a/src/sage/combinat/sf/classical.py +++ b/src/sage/combinat/sf/classical.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Classical symmetric functions """ diff --git a/src/sage/combinat/sf/dual.py b/src/sage/combinat/sf/dual.py index 90ed7f7ac8c..6a68eb7dfe6 100644 --- a/src/sage/combinat/sf/dual.py +++ b/src/sage/combinat/sf/dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Generic dual bases symmetric functions """ diff --git a/src/sage/combinat/sf/elementary.py b/src/sage/combinat/sf/elementary.py index a7e5d9cf44c..ce9cae6cdc8 100644 --- a/src/sage/combinat/sf/elementary.py +++ b/src/sage/combinat/sf/elementary.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Elementary symmetric functions """ diff --git a/src/sage/combinat/sf/hall_littlewood.py b/src/sage/combinat/sf/hall_littlewood.py index 9cb70465fe8..0520780c0b1 100644 --- a/src/sage/combinat/sf/hall_littlewood.py +++ b/src/sage/combinat/sf/hall_littlewood.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hall-Littlewood Polynomials diff --git a/src/sage/combinat/sf/hecke.py b/src/sage/combinat/sf/hecke.py index 2fda46380a3..4ed4acf510c 100644 --- a/src/sage/combinat/sf/hecke.py +++ b/src/sage/combinat/sf/hecke.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hecke Character Basis diff --git a/src/sage/combinat/sf/homogeneous.py b/src/sage/combinat/sf/homogeneous.py index da55fef0426..e83dd16861e 100644 --- a/src/sage/combinat/sf/homogeneous.py +++ b/src/sage/combinat/sf/homogeneous.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Homogeneous symmetric functions diff --git a/src/sage/combinat/sf/jack.py b/src/sage/combinat/sf/jack.py index 7c067bcdf03..7956a5ce94a 100644 --- a/src/sage/combinat/sf/jack.py +++ b/src/sage/combinat/sf/jack.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Jack Symmetric Functions diff --git a/src/sage/combinat/sf/k_dual.py b/src/sage/combinat/sf/k_dual.py index 391fb488943..0ccac0de589 100644 --- a/src/sage/combinat/sf/k_dual.py +++ b/src/sage/combinat/sf/k_dual.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Quotient of symmetric function space by ideal generated by Hall-Littlewood symmetric functions diff --git a/src/sage/combinat/sf/kfpoly.py b/src/sage/combinat/sf/kfpoly.py index 88eb77485e8..09283745aa5 100644 --- a/src/sage/combinat/sf/kfpoly.py +++ b/src/sage/combinat/sf/kfpoly.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Kostka-Foulkes Polynomials diff --git a/src/sage/combinat/sf/llt.py b/src/sage/combinat/sf/llt.py index 7c26b9905cd..5c01a9b5798 100644 --- a/src/sage/combinat/sf/llt.py +++ b/src/sage/combinat/sf/llt.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" LLT symmetric functions diff --git a/src/sage/combinat/sf/macdonald.py b/src/sage/combinat/sf/macdonald.py index 99c9a00ca5b..648d08410ee 100644 --- a/src/sage/combinat/sf/macdonald.py +++ b/src/sage/combinat/sf/macdonald.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Macdonald Polynomials diff --git a/src/sage/combinat/sf/monomial.py b/src/sage/combinat/sf/monomial.py index 588d8154add..3af845888f3 100644 --- a/src/sage/combinat/sf/monomial.py +++ b/src/sage/combinat/sf/monomial.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Monomial symmetric functions """ diff --git a/src/sage/combinat/sf/multiplicative.py b/src/sage/combinat/sf/multiplicative.py index 4e6c57ffffa..7ff9797f81a 100644 --- a/src/sage/combinat/sf/multiplicative.py +++ b/src/sage/combinat/sf/multiplicative.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Multiplicative symmetric functions diff --git a/src/sage/combinat/sf/new_kschur.py b/src/sage/combinat/sf/new_kschur.py index 551e776ebb6..e4c2abcc75a 100644 --- a/src/sage/combinat/sf/new_kschur.py +++ b/src/sage/combinat/sf/new_kschur.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ `k`-Schur Functions """ diff --git a/src/sage/combinat/sf/ns_macdonald.py b/src/sage/combinat/sf/ns_macdonald.py index 44075c054cf..8807bd95b87 100644 --- a/src/sage/combinat/sf/ns_macdonald.py +++ b/src/sage/combinat/sf/ns_macdonald.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Non-symmetric Macdonald Polynomials """ diff --git a/src/sage/combinat/sf/orthogonal.py b/src/sage/combinat/sf/orthogonal.py index 0e9e2053d51..3ab5f56debc 100644 --- a/src/sage/combinat/sf/orthogonal.py +++ b/src/sage/combinat/sf/orthogonal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Orthogonal Symmetric Functions diff --git a/src/sage/combinat/sf/orthotriang.py b/src/sage/combinat/sf/orthotriang.py index 96cae8e7384..2e1650e57a7 100644 --- a/src/sage/combinat/sf/orthotriang.py +++ b/src/sage/combinat/sf/orthotriang.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric functions defined by orthogonality and triangularity diff --git a/src/sage/combinat/sf/powersum.py b/src/sage/combinat/sf/powersum.py index fb9ecb31e91..bb20adf9941 100644 --- a/src/sage/combinat/sf/powersum.py +++ b/src/sage/combinat/sf/powersum.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Power sum symmetric functions """ diff --git a/src/sage/combinat/sf/schur.py b/src/sage/combinat/sf/schur.py index 202c31d7cee..299cf28da99 100644 --- a/src/sage/combinat/sf/schur.py +++ b/src/sage/combinat/sf/schur.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Schur symmetric functions """ diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index 56b3b96f279..aba6c941430 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symmetric functions, with their multiple realizations """ diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index d32397c2879..3144a081144 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Symmetric Functions diff --git a/src/sage/combinat/sf/symplectic.py b/src/sage/combinat/sf/symplectic.py index 7ee859ce6db..f6db1782489 100644 --- a/src/sage/combinat/sf/symplectic.py +++ b/src/sage/combinat/sf/symplectic.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Symplectic Symmetric Functions diff --git a/src/sage/combinat/sf/witt.py b/src/sage/combinat/sf/witt.py index cceebed7889..138b2647826 100644 --- a/src/sage/combinat/sf/witt.py +++ b/src/sage/combinat/sf/witt.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Witt symmetric functions """ diff --git a/src/sage/combinat/shifted_primed_tableau.py b/src/sage/combinat/shifted_primed_tableau.py index 2ca02da12da..e9a320cd0ea 100644 --- a/src/sage/combinat/shifted_primed_tableau.py +++ b/src/sage/combinat/shifted_primed_tableau.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Shifted primed tableaux diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 94e87115ea3..01c0ea3aac5 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Similarity class types of matrices with entries in a finite field diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index c3cf9299093..b94af845645 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.libs.gap sage.libs.flint sage.libs.pari sage.modules r""" Functions that compute some of the sequences in Sloane's tables diff --git a/src/sage/combinat/specht_module.py b/src/sage/combinat/specht_module.py index 678933d78fb..9db20d0b184 100644 --- a/src/sage/combinat/specht_module.py +++ b/src/sage/combinat/specht_module.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Specht Modules diff --git a/src/sage/combinat/species/misc.py b/src/sage/combinat/species/misc.py index 7296c77e54d..a516beb56ae 100644 --- a/src/sage/combinat/species/misc.py +++ b/src/sage/combinat/species/misc.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups """ Miscellaneous Functions """ diff --git a/src/sage/combinat/species/partition_species.py b/src/sage/combinat/species/partition_species.py index c9b08f1b4bb..3ed00b45ca4 100644 --- a/src/sage/combinat/species/partition_species.py +++ b/src/sage/combinat/species/partition_species.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.flint """ Partition Species """ diff --git a/src/sage/combinat/species/permutation_species.py b/src/sage/combinat/species/permutation_species.py index aeb7ad3ca3b..4549e0354ff 100644 --- a/src/sage/combinat/species/permutation_species.py +++ b/src/sage/combinat/species/permutation_species.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups sage.libs.flint """ Permutation species """ diff --git a/src/sage/combinat/subword_complex.py b/src/sage/combinat/subword_complex.py index de7eefe946e..1a1b05dbf17 100644 --- a/src/sage/combinat/subword_complex.py +++ b/src/sage/combinat/subword_complex.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Subword complex diff --git a/src/sage/combinat/subword_complex_c.pyx b/src/sage/combinat/subword_complex_c.pyx index 39200e0c339..66da5184356 100644 --- a/src/sage/combinat/subword_complex_c.pyx +++ b/src/sage/combinat/subword_complex_c.pyx @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.modules + cpdef int _flip_c(W, set positions, list extended_root_conf_indices, int i, side="both"): r""" diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py index 3884747f825..3e8b27e9210 100644 --- a/src/sage/combinat/symmetric_group_algebra.py +++ b/src/sage/combinat/symmetric_group_algebra.py @@ -1,4 +1,4 @@ -# optional - sage.combinat sage.modules sage.groups +# sage.doctest: needs sage.combinat sage.modules sage.groups r""" Symmetric Group Algebra """ diff --git a/src/sage/combinat/symmetric_group_representations.py b/src/sage/combinat/symmetric_group_representations.py index ee518756525..4eae56f9e0a 100644 --- a/src/sage/combinat/symmetric_group_representations.py +++ b/src/sage/combinat/symmetric_group_representations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules sage.groups r""" Representations of the Symmetric Group diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 6ef7dd06cdc..e074e8efc8b 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Generalized Tamari lattices diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index 676a4846b23..aaa9a7227b8 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Tiling Solver diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index 9789faae487..04e28b5c6e8 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Word paths From 70a52845c87b4a443183a4d562969445410c404c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 7 Aug 2023 22:44:15 -0700 Subject: [PATCH 100/225] src/sage/graphs: sage -fixdoctests --only-tags --- src/sage/graphs/generators/families.py | 11 ++++++----- .../graphs/graph_decompositions/graph_products.pyx | 4 ++-- src/sage/graphs/strongly_regular_db.pyx | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index a5916a13b5c..54ea6c2d9d2 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2693,14 +2693,15 @@ def SwitchedSquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) # needs sage.modules - sage: g.is_strongly_regular(parameters=True) # needs sage.modules + sage: # needs sage.modules + sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) + sage: g.is_strongly_regular(parameters=True) (226, 105, 48, 49) sage: from sage.combinat.designs.twographs import twograph_descendant - sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True) # needs sage.modules + sage: twograph_descendant(g, 0).is_strongly_regular(parameters=True) (225, 112, 55, 56) - sage: gc = g.complement() # needs sage.modules - sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True) # needs sage.modules + sage: gc = g.complement() + sage: twograph_descendant(gc, 0).is_strongly_regular(parameters=True) (225, 112, 55, 56) TESTS:: diff --git a/src/sage/graphs/graph_decompositions/graph_products.pyx b/src/sage/graphs/graph_decompositions/graph_products.pyx index 31f49206586..cd4f0b04c7d 100644 --- a/src/sage/graphs/graph_decompositions/graph_products.pyx +++ b/src/sage/graphs/graph_decompositions/graph_products.pyx @@ -397,12 +397,12 @@ def rooted_product(G, H, root=None): sage: G = graphs.RandomGNP(20, .3) sage: P = graphs.PathGraph(2) sage: R = G.rooted_product(P) - sage: len(R.dominating_set()) == G.order() + sage: len(R.dominating_set()) == G.order() # needs sage.numerical.mip True sage: G = digraphs.RandomDirectedGNP(20, .3) sage: P = digraphs.Path(2) sage: R = G.rooted_product(P) - sage: len(R.dominating_set()) == G.order() + sage: len(R.dominating_set()) == G.order() # needs sage.numerical.mip True The rooted product of two graphs is a subgraph of the cartesian product of diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index 25e803cc5d8..e90e51e0c87 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -2435,8 +2435,8 @@ def SRG_560_208_72_80(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_560_208_72_80 - sage: g = SRG_560_208_72_80() # not tested (~2s) - sage: g.is_strongly_regular(parameters=True) # not tested (~2s) + sage: g = SRG_560_208_72_80() # not tested (~2s) # needs sage.libs.gap + sage: g.is_strongly_regular(parameters=True) # not tested (~2s) # needs sage.libs.gap (560, 208, 72, 80) """ from sage.libs.gap.libgap import libgap From fc5b2dae164042eef55d017f0d4217c61ef8d882 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 7 Aug 2023 22:44:22 -0700 Subject: [PATCH 101/225] src/sage/sandpiles: sage -fixdoctests --only-tags --- src/sage/sandpiles/sandpile.py | 42 +++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index c8e15e06f05..eae4d844b59 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -83,7 +83,7 @@ A picture of the graph:: - sage: S.show() # long time + sage: S.show() # long time # needs sage.plot The relevant Laplacian matrices:: @@ -250,10 +250,11 @@ ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i+1),log(a.count(i))] for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)','log(D(N))']) - sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) - sage: show(p+t,axes_labels=['log(N)','log(D(N))']) # long time + sage: p = list_plot([[log(i + 1), log(a.count(i))] # needs sage.plot + ....: for i in [0..max(a)] if a.count(i)]) + sage: p.axes_labels(['log(N)', 'log(D(N))']) # needs sage.plot + sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) # needs sage.plot + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time # needs sage.plot Working with sandpile divisors:: @@ -792,8 +793,8 @@ def show(self, **kwds): EXAMPLES:: sage: S = Sandpile({0:[], 1:[0,3,4], 2:[0,3,5], 3:[2,5], 4:[1,1], 5:[2,4]}) - sage: S.show() - sage: S.show(graph_border=True, edge_labels=True) + sage: S.show() # needs sage.plot + sage: S.show(graph_border=True, edge_labels=True) # needs sage.plot """ if self.is_undirected(): @@ -812,7 +813,7 @@ def show3d(self, **kwds): EXAMPLES:: sage: S = sandpiles.House() - sage: S.show3d() # long time + sage: S.show3d() # long time # needs sage.plot """ if self.is_undirected(): @@ -3763,10 +3764,11 @@ def add_random(self, distrib=None): ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i+1),log(a.count(i))] for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)','log(D(N))']) - sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) - sage: show(p+t,axes_labels=['log(N)','log(D(N))']) # long time + sage: p = list_plot([[log(i + 1), log(a.count(i))] # needs sage.plot + ....: for i in [0..max(a)] if a.count(i)]) + sage: p.axes_labels(['log(N)', 'log(D(N))']) # needs sage.plot + sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) # needs sage.plot + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time, needs sage.plot .. NOTE:: @@ -4145,9 +4147,9 @@ def show(self, sink=True, colors=True, heights=False, directed=None, **kwds): sage: S = sandpiles.Diamond() sage: c = S.identity() - sage: c.show() - sage: c.show(directed=False) - sage: c.show(sink=False,colors=False,heights=True) + sage: c.show() # needs sage.plot + sage: c.show(directed=False) # needs sage.plot + sage: c.show(sink=False, colors=False, heights=True) # needs sage.plot """ if directed: T = DiGraph(self.sandpile()) @@ -6045,8 +6047,8 @@ def show(self, heights=True, directed=None, **kwds): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: D = SandpileDivisor(S,[1,-2,0,2]) - sage: D.show(graph_border=True,vertex_size=700,directed=False) + sage: D = SandpileDivisor(S, [1,-2,0,2]) + sage: D.show(graph_border=True, vertex_size=700, directed=False) # needs sage.plot """ if directed: T = DiGraph(self.sandpile()) @@ -6362,7 +6364,8 @@ def firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) sage: eff = D.effective_div() - sage: firing_graph(S,eff).show3d(edge_size=.005,vertex_size=0.01) # long time + sage: firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.plot + ....: vertex_size=0.01) """ g = DiGraph() g.add_vertices(range(len(eff))) @@ -6398,7 +6401,8 @@ def parallel_firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) sage: eff = D.effective_div() - sage: parallel_firing_graph(S,eff).show3d(edge_size=.005,vertex_size=0.01) # long time + sage: parallel_firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.plot + ....: vertex_size=0.01) """ g = DiGraph() g.add_vertices(range(len(eff))) From 9a65f92831b364fa367e74909623990e66a12ab2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 12 Aug 2023 22:54:33 -0700 Subject: [PATCH 102/225] sage.sandpiles: Add # needs --- src/sage/sandpiles/examples.py | 4 +- src/sage/sandpiles/sandpile.py | 235 ++++++++++++++++++--------------- 2 files changed, 134 insertions(+), 105 deletions(-) diff --git a/src/sage/sandpiles/examples.py b/src/sage/sandpiles/examples.py index a902a156318..265e72c546b 100644 --- a/src/sage/sandpiles/examples.py +++ b/src/sage/sandpiles/examples.py @@ -156,10 +156,10 @@ def Fan(self, n, deg_three_verts=False): EXAMPLES:: sage: f = sandpiles.Fan(10) - sage: f.group_order() == fibonacci(18) + sage: f.group_order() == fibonacci(18) # needs sage.libs.pari True sage: f = sandpiles.Fan(10,True) # all nonsink vertices have deg 3 - sage: f.group_order() == fibonacci(20) + sage: f.group_order() == fibonacci(20) # needs sage.libs.pari True """ f = graphs.WheelGraph(n) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index eae4d844b59..e6cba3195ca 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -205,17 +205,19 @@ the saturated homogeneous toppling ideal:: - sage: S.ideal() - Ideal (x1 - x0, x3*x2 - x0^2, x4^2 - x0^2, x2^3 - x4*x3*x0, x4*x2^2 - x3^2*x0, x3^3 - x4*x2*x0, x4*x3^2 - x2^2*x0) of Multivariate Polynomial Ring in x4, x3, x2, x1, x0 over Rational Field + sage: S.ideal() # needs sage.libs.singular + Ideal (x1 - x0, x3*x2 - x0^2, x4^2 - x0^2, x2^3 - x4*x3*x0, + x4*x2^2 - x3^2*x0, x3^3 - x4*x2*x0, x4*x3^2 - x2^2*x0) of + Multivariate Polynomial Ring in x4, x3, x2, x1, x0 over Rational Field its minimal free resolution:: - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^7 <-- R^15 <-- R^13 <-- R^4' and its Betti numbers:: - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 4 ------------------------------------ 0: 1 1 - - - @@ -250,11 +252,13 @@ ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i + 1), log(a.count(i))] # needs sage.plot + + sage: # needs sage.plot + sage: p = list_plot([[log(i + 1), log(a.count(i))] ....: for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)', 'log(D(N))']) # needs sage.plot - sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) # needs sage.plot - sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time # needs sage.plot + sage: p.axes_labels(['log(N)', 'log(D(N))']) + sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time Working with sandpile divisors:: @@ -276,6 +280,8 @@ {0: 4, 1: 0, 2: 0, 3: 1} sage: D.rank() 2 + + sage: # needs sage.geometry.polyhedron sage: sorted(D.effective_div(), key=str) [{0: 0, 1: 0, 2: 0, 3: 5}, {0: 0, 1: 0, 2: 4, 3: 1}, @@ -297,6 +303,7 @@ -1 sage: (D - E).effective_div() [] + sage: D.weierstrass_pts() (0, 1, 2, 3) sage: D.weierstrass_rank_seq(0) @@ -1376,7 +1383,7 @@ def recurrents(self, verbose=True): sage: r = Sandpile(graphs.HouseXGraph(),0).recurrents() sage: r[:3] [{1: 2, 2: 3, 3: 3, 4: 1}, {1: 1, 2: 3, 3: 3, 4: 0}, {1: 1, 2: 3, 3: 3, 4: 1}] - sage: sandpiles.Complete(4).recurrents(False) + sage: sandpiles.Complete(4).recurrents(False) # needs sage.combinat [[2, 2, 2], [2, 2, 1], [2, 1, 2], @@ -1435,7 +1442,7 @@ def superstables(self, verbose=True): sage: sp = Sandpile(graphs.HouseXGraph(),0).superstables() sage: sp[:3] [{1: 0, 2: 0, 3: 0, 4: 0}, {1: 1, 2: 0, 3: 0, 4: 1}, {1: 1, 2: 0, 3: 0, 4: 0}] - sage: sandpiles.Complete(4).superstables(False) + sage: sandpiles.Complete(4).superstables(False) # needs sage.combinat [[0, 0, 0], [0, 0, 1], [0, 1, 0], @@ -1556,8 +1563,8 @@ def _set_min_recurrents(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s._set_min_recurrents() - sage: '_min_recurrents' in s.__dict__ + sage: s._set_min_recurrents() # needs sage.combinat + sage: '_min_recurrents' in s.__dict__ # needs sage.combinat True """ if self.is_undirected(): @@ -1661,7 +1668,7 @@ def tutte_polynomial(self): x^3 + y^3 + 3*x^2 + 4*x*y + 3*y^2 + 2*x + 2*y sage: s.tutte_polynomial().subs(x=1) y^3 + 3*y^2 + 6*y + 6 - sage: s.tutte_polynomial().subs(x=1).coefficients() == s.h_vector() + sage: s.tutte_polynomial().subs(x=1).coefficients() == s.h_vector() # needs sage.combinat True """ if self.is_undirected(): @@ -1676,8 +1683,8 @@ def _set_avalanche_polynomial(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s._set_avalanche_polynomial() - sage: '_avalanche_polynomial' in s.__dict__ + sage: s._set_avalanche_polynomial() # needs sage.combinat + sage: '_avalanche_polynomial' in s.__dict__ # needs sage.combinat True """ n = self.num_verts() - 1 @@ -1709,9 +1716,9 @@ def avalanche_polynomial(self, multivariable=True): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s.avalanche_polynomial() + sage: s.avalanche_polynomial() # needs sage.combinat 9*x0*x1*x2 + 2*x0*x1 + 2*x0*x2 + 2*x1*x2 + 3*x0 + 3*x1 + 3*x2 + 24 - sage: s.avalanche_polynomial(False) + sage: s.avalanche_polynomial(False) # needs sage.combinat 9*x0^3 + 6*x0^2 + 9*x0 + 24 .. NOTE:: @@ -1748,12 +1755,13 @@ def nonspecial_divisors(self, verbose=True): EXAMPLES:: + sage: # needs sage.combinat sage: S = sandpiles.Complete(4) sage: ns = S.nonspecial_divisors() sage: D = ns[0] - sage: D.values() + sage: D.values() # needs sage.symbolic [-1, 0, 1, 2] - sage: D.deg() + sage: D.deg() # needs sage.symbolic 2 sage: [i.effective_div() for i in ns] [[], [], [], [], [], []] @@ -1915,7 +1923,7 @@ def postulation(self): EXAMPLES:: sage: s = sandpiles.Complete(4) - sage: s.postulation() + sage: s.postulation() # needs sage.combinat 3 """ return self._postulation @@ -2001,8 +2009,8 @@ def _set_jacobian_representatives(self): EXAMPLES:: sage: s = sandpiles.Complete(3) - sage: s._set_jacobian_representatives() - sage: '_jacobian_representatives' in s.__dict__ + sage: s._set_jacobian_representatives() # needs sage.combinat + sage: '_jacobian_representatives' in s.__dict__ # needs sage.combinat True """ if self.is_undirected(): @@ -2056,9 +2064,9 @@ def jacobian_representatives(self, verbose=True): representatives for the Jacobian group.:: sage: s = sandpiles.Complete(3) - sage: s.superstables(False) + sage: s.superstables(False) # needs sage.combinat [[0, 0], [0, 1], [1, 0]] - sage: s.jacobian_representatives(False) + sage: s.jacobian_representatives(False) # needs sage.combinat [[0, 0, 0], [-1, 0, 1], [-1, 1, 0]] If the graph is directed, the representatives described above may by @@ -2067,7 +2075,7 @@ def jacobian_representatives(self, verbose=True): sage: s = Sandpile({0: {1: 1, 2: 2}, 1: {0: 2, 2: 4}, 2: {0: 4, 1: 2}},0) sage: s.group_order() 28 - sage: s.jacobian_representatives() + sage: s.jacobian_representatives() # needs sage.symbolic [{0: -5, 1: 3, 2: 2}, {0: -4, 1: 3, 2: 1}] Let `\tau` be the nonnegative generator of the kernel of the transpose of @@ -2108,11 +2116,11 @@ def picard_representatives(self, d, verbose=True): EXAMPLES:: sage: s = sandpiles.Complete(3) - sage: s.superstables(False) + sage: s.superstables(False) # needs sage.combinat [[0, 0], [0, 1], [1, 0]] - sage: s.jacobian_representatives(False) + sage: s.jacobian_representatives(False) # needs sage.combinat [[0, 0, 0], [-1, 0, 1], [-1, 1, 0]] - sage: s.picard_representatives(3,False) + sage: s.picard_representatives(3,False) # needs sage.combinat [[3, 0, 0], [2, 0, 1], [2, 1, 0]] """ D = self.zero_div() @@ -2143,12 +2151,12 @@ def stable_configs(self, smax=None): sage: s = sandpiles.Complete(3) sage: a = s.stable_configs() - sage: next(a) + sage: next(a) # needs sage.combinat {1: 0, 2: 0} - sage: [i.values() for i in a] + sage: [i.values() for i in a] # needs sage.combinat [[0, 1], [1, 0], [1, 1]] sage: b = s.stable_configs([1,0]) - sage: list(b) + sage: list(b) # needs sage.combinat [{1: 0, 2: 0}, {1: 1, 2: 0}] """ if smax is None: @@ -2318,6 +2326,8 @@ def stationary_density(self): sage: s = sandpiles.Complete(3) sage: s.stationary_density() 10/9 + + sage: # needs sage.combinat sage: s = Sandpile(digraphs.DeBruijn(2,2),'00') sage: s.stationary_density() 9/8 @@ -2379,8 +2389,8 @@ def _set_betti_complexes(self): EXAMPLES:: sage: S = Sandpile({0:{},1:{0: 1, 2: 1, 3: 4},2:{3: 5},3:{1: 1, 2: 1}},0) - sage: S._set_betti_complexes() - sage: '_betti_complexes' in S.__dict__ + sage: S._set_betti_complexes() # needs sage.geometry.polyhedron + sage: '_betti_complexes' in S.__dict__ # needs sage.geometry.polyhedron True """ results = [] @@ -2413,13 +2423,15 @@ def betti_complexes(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = Sandpile({0:{},1:{0: 1, 2: 1, 3: 4},2:{3: 5},3:{1: 1, 2: 1}},0) sage: p = S.betti_complexes() sage: p[0] - [{0: -8, 1: 5, 2: 4, 3: 1}, Simplicial complex with vertex set (1, 2, 3) and facets {(3,), (1, 2)}] + [{0: -8, 1: 5, 2: 4, 3: 1}, + Simplicial complex with vertex set (1, 2, 3) and facets {(3,), (1, 2)}] sage: S.resolution() 'R^1 <-- R^5 <-- R^5 <-- R^1' - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -2490,8 +2502,8 @@ def _set_ideal(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_ideal() - sage: '_ideal' in S.__dict__ + sage: S._set_ideal() # needs sage.libs.singular + sage: '_ideal' in S.__dict__ # needs sage.libs.singular True """ from sage.libs.singular.function_factory import ff @@ -2517,8 +2529,9 @@ def unsaturated_ideal(self): sage: S = sandpiles.Diamond() sage: S.unsaturated_ideal().gens() [x1^3 - x3*x2*x0, x2^3 - x3*x1*x0, x3^2 - x2*x1] - sage: S.ideal().gens() - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal().gens() # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] """ return self._unsaturated_ideal @@ -2538,12 +2551,16 @@ def ideal(self, gens=False): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.ideal() - Ideal (x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0) of Multivariate Polynomial Ring in x3, x2, x1, x0 over Rational Field - sage: S.ideal(True) - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] - sage: S.ideal().gens() # another way to get the generators - [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal() # needs sage.libs.singular + Ideal (x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0) + of Multivariate Polynomial Ring in x3, x2, x1, x0 over Rational Field + sage: S.ideal(True) # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] + sage: S.ideal().gens() # another way to get the generators # needs sage.libs.singular + [x2*x1 - x0^2, x3^2 - x0^2, x1^3 - x3*x2*x0, + x3*x1^2 - x2^2*x0, x2^3 - x3*x1*x0, x3*x2^2 - x1^2*x0] """ if gens: return self._ideal.gens() @@ -2582,8 +2599,8 @@ def _set_resolution(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_resolution() - sage: '_resolution' in S.__dict__ + sage: S._set_resolution() # needs sage.libs.singular + sage: '_resolution' in S.__dict__ # needs sage.libs.singular True """ # get the resolution in singular form @@ -2625,6 +2642,7 @@ def resolution(self, verbose=False): EXAMPLES:: + sage: # needs sage.libs.singular sage: S = Sandpile({0: {}, 1: {0: 1, 2: 1, 3: 4}, 2: {3: 5}, 3: {1: 1, 2: 1}},0) sage: S.resolution() # a Gorenstein sandpile graph 'R^1 <-- R^5 <-- R^5 <-- R^1' @@ -2662,8 +2680,8 @@ def _set_groebner(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_groebner() - sage: '_groebner' in S.__dict__ + sage: S._set_groebner() # needs sage.libs.singular + sage: '_groebner' in S.__dict__ # needs sage.libs.singular True """ self._groebner = self._ideal.groebner_basis() @@ -2680,8 +2698,9 @@ def groebner(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.groebner() - [x3*x2^2 - x1^2*x0, x2^3 - x3*x1*x0, x3*x1^2 - x2^2*x0, x1^3 - x3*x2*x0, x3^2 - x0^2, x2*x1 - x0^2] + sage: S.groebner() # needs sage.libs.singular + [x3*x2^2 - x1^2*x0, x2^3 - x3*x1*x0, x3*x1^2 - x2^2*x0, + x1^3 - x3*x2*x0, x3^2 - x0^2, x2*x1 - x0^2] """ return self._groebner @@ -2703,7 +2722,7 @@ def betti(self, verbose=True): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -2711,7 +2730,7 @@ def betti(self, verbose=True): 2: - 4 9 4 ------------------------------ total: 1 6 9 4 - sage: S.betti(False) + sage: S.betti(False) # needs sage.libs.singular [1, 6, 9, 4] """ if verbose: @@ -2732,7 +2751,7 @@ def solve(self): EXAMPLES:: sage: S = Sandpile({0: {}, 1: {2: 2}, 2: {0: 4, 1: 1}}, 0) - sage: S.solve() + sage: Z = S.solve() # needs sage.libs.singular [[-0.707107000000000 + 0.707107000000000*I, 0.707107000000000 - 0.707107000000000*I], [-0.707107000000000 - 0.707107000000000*I, @@ -2745,7 +2764,7 @@ def solve(self): -0.707107000000000 + 0.707107000000000*I], [1, 1], [-1, -1]] - sage: len(_) + sage: len(Z) # needs sage.libs.singular 8 sage: S.group_order() 8 @@ -2780,8 +2799,8 @@ def _set_points(self): EXAMPLES:: sage: S = sandpiles.Diamond() - sage: S._set_points() - sage: '_points' in S.__dict__ + sage: S._set_points() # needs sage.symbolic + sage: '_points' in S.__dict__ # needs sage.symbolic True """ L = self._reduced_laplacian.transpose().dense_matrix() @@ -2812,7 +2831,7 @@ def points(self): :: sage: S = sandpiles.Complete(4) - sage: S.points() + sage: S.points() # needs sage.symbolic [[-I, I, 1], [-I, 1, I]] """ return self._points @@ -3764,11 +3783,13 @@ def add_random(self, distrib=None): ....: m = m.add_random() ....: m, f = m.stabilize(True) ....: a.append(sum(f.values())) - sage: p = list_plot([[log(i + 1), log(a.count(i))] # needs sage.plot + + sage: # needs sage.plot + sage: p = list_plot([[log(i + 1), log(a.count(i))] ....: for i in [0..max(a)] if a.count(i)]) - sage: p.axes_labels(['log(N)', 'log(D(N))']) # needs sage.plot - sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) # needs sage.plot - sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time, needs sage.plot + sage: p.axes_labels(['log(N)', 'log(D(N))']) + sage: t = text("Distribution of avalanche sizes", (2,2), rgbcolor=(1,0,0)) + sage: show(p + t, axes_labels=['log(N)', 'log(D(N))']) # long time .. NOTE:: @@ -4327,8 +4348,8 @@ def __setitem__(self, key, item): sage: S = sandpiles.Cycle(3) sage: D = SandpileDivisor(S,[0,1,1]) - sage: eff = D.effective_div() - sage: D.__dict__ + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: D.__dict__ # needs sage.geometry.polyhedron {'_effective_div': [{0: 0, 1: 1, 2: 1}, {0: 2, 1: 0, 2: 0}], '_polytope': A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, '_polytope_integer_pts': ((0, 0), (1, 1)), @@ -5199,8 +5220,8 @@ def _set_polytope(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_polytope() - sage: '_polytope' in D.__dict__ + sage: D._set_polytope() # needs sage.geometry.polyhedron + sage: '_polytope' in D.__dict__ # needs sage.geometry.polyhedron True """ S = self.sandpile() @@ -5218,6 +5239,7 @@ def polytope(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) sage: p = D.polytope() @@ -5250,8 +5272,8 @@ def _set_polytope_integer_pts(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_polytope_integer_pts() - sage: '_polytope_integer_pts' in D.__dict__ + sage: D._set_polytope_integer_pts() # needs sage.geometry.polyhedron + sage: '_polytope_integer_pts' in D.__dict__ # needs sage.geometry.polyhedron True """ self._polytope_integer_pts = self._polytope.integral_points() @@ -5270,7 +5292,7 @@ def polytope_integer_pts(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: sorted(D.polytope_integer_pts()) + sage: sorted(D.polytope_integer_pts()) # needs sage.geometry.polyhedron [(-2, -1, -1), (-1, -2, -1), (-1, -1, -2), @@ -5278,7 +5300,7 @@ def polytope_integer_pts(self): (0, -1, -1), (0, 0, 0)] sage: D = SandpileDivisor(s,[-1,0,0,0]) - sage: D.polytope_integer_pts() + sage: D.polytope_integer_pts() # needs sage.geometry.polyhedron () """ return deepcopy(self._polytope_integer_pts) @@ -5291,8 +5313,8 @@ def _set_effective_div(self): sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) - sage: D._set_effective_div() - sage: '_effective_div' in D.__dict__ + sage: D._set_effective_div() # needs sage.geometry.polyhedron + sage: '_effective_div' in D.__dict__ # needs sage.geometry.polyhedron True """ S = self.sandpile() @@ -5321,6 +5343,7 @@ def effective_div(self, verbose=True, with_firing_vectors=False): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Complete(4) sage: D = SandpileDivisor(s,[4,2,0,0]) sage: sorted(D.effective_div(), key=str) @@ -5394,8 +5417,8 @@ def _set_rank(self, set_witness=False): True sage: '_rank_witness' in D.__dict__ False - sage: D._set_rank(True) - sage: '_rank_witness' in D.__dict__ + sage: D._set_rank(True) # needs sage.geometry.polyhedron + sage: '_rank_witness' in D.__dict__ # needs sage.geometry.polyhedron True sage: D = SandpileDivisor(s,[1,0,0,0]) sage: D._set_rank() @@ -5462,6 +5485,7 @@ def rank(self, with_witness=False): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = sandpiles.Complete(4) sage: D = SandpileDivisor(S,[4,2,0,0]) sage: D.rank() @@ -5469,19 +5493,21 @@ def rank(self, with_witness=False): sage: D.rank(True) (3, {0: 3, 1: 0, 2: 1, 3: 0}) sage: E = _[1] - sage: (D - E).rank() + sage: (D - E).rank() # needs sage.rings.number_field -1 Riemann-Roch theorem:: + sage: # needs sage.geometry.polyhedron sage: D.rank() - (S.canonical_divisor()-D).rank() == D.deg() + 1 - S.genus() True Riemann-Roch theorem:: + sage: # needs sage.geometry.polyhedron sage: D.rank() - (S.canonical_divisor()-D).rank() == D.deg() + 1 - S.genus() True - sage: S = Sandpile({0:[1,1,1,2],1:[0,0,0,1,1,1,2,2],2:[2,2,1,1,0]},0) # multigraph with loops + sage: S = Sandpile({0:[1,1,1,2],1:[0,0,0,1,1,1,2,2],2:[2,2,1,1,0]},0) # multigraph with loops sage: D = SandpileDivisor(S,[4,2,0]) sage: D.rank(True) (2, {0: 1, 1: 1, 2: 1}) @@ -5494,7 +5520,7 @@ def rank(self, with_witness=False): sage: D.rank(True) (0, {0: 0, 1: 0, 2: 1}) sage: E = D.rank(True)[1] - sage: (D - E).effective_div() + sage: (D - E).effective_div() # needs sage.rings.number_field [] .. NOTE:: @@ -5521,8 +5547,8 @@ def _set_r_of_D(self, verbose=False): EXAMPLES:: sage: S = sandpiles.Cycle(6) - sage: D = SandpileDivisor(S, [0,0,0,0,0,4]) # optional - 4ti2 - sage: D._set_r_of_D() # optional - 4ti2 + sage: D = SandpileDivisor(S, [0,0,0,0,0,4]) # optional - 4ti2 + sage: D._set_r_of_D() # optional - 4ti2 """ eff = self.effective_div() n = self._sandpile.num_verts() @@ -5575,7 +5601,7 @@ def weierstrass_rank_seq(self, v='sink'): sage: s = sandpiles.House() sage: K = s.canonical_divisor() - sage: [K.weierstrass_rank_seq(v) for v in s.vertices(sort=True)] + sage: [K.weierstrass_rank_seq(v) for v in s.vertices(sort=True)] # needs sage.geometry.polyhedron [(1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, -1), (1, 0, 0, -1)] """ s = self.sandpile() @@ -5615,13 +5641,14 @@ def weierstrass_gap_seq(self, v='sink', weight=True): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.Cycle(4) sage: D = SandpileDivisor(s,[2,0,0,0]) sage: [D.weierstrass_gap_seq(v,False) for v in s.vertices(sort=True)] [(1, 3), (1, 2), (1, 3), (1, 2)] sage: [D.weierstrass_gap_seq(v) for v in s.vertices(sort=True)] [((1, 3), 1), ((1, 2), 0), ((1, 3), 1), ((1, 2), 0)] - sage: D.weierstrass_gap_seq() # gap sequence at sink vertex, 0 + sage: D.weierstrass_gap_seq() # gap sequence at sink vertex, 0 ((1, 3), 1) sage: D.weierstrass_rank_seq() # rank sequence at the sink vertex (1, 0, 0, -1) @@ -5657,6 +5684,7 @@ def is_weierstrass_pt(self, v='sink'): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: s = sandpiles.House() sage: K = s.canonical_divisor() sage: K.weierstrass_rank_seq() # sequence at the sink vertex, 0 @@ -5684,8 +5712,8 @@ def _set_weierstrass_pts(self): sage: s = sandpiles.Diamond() sage: D = SandpileDivisor(s, [2,1,0,0]) - sage: D._set_weierstrass_pts() - sage: '_weierstrass_pts' in D.__dict__ + sage: D._set_weierstrass_pts() # needs sage.geometry.polyhedron + sage: '_weierstrass_pts' in D.__dict__ # needs sage.geometry.polyhedron True """ self._weierstrass_pts = tuple([v for v in self.sandpile().vertices(sort=True) @@ -5707,9 +5735,9 @@ def weierstrass_pts(self, with_rank_seq=False): sage: s = sandpiles.House() sage: K = s.canonical_divisor() - sage: K.weierstrass_pts() + sage: K.weierstrass_pts() # needs sage.geometry.polyhedron (4,) - sage: K.weierstrass_pts(True) + sage: K.weierstrass_pts(True) # needs sage.geometry.polyhedron [(4, (1, 0, 0, -1))] .. NOTE:: @@ -5741,12 +5769,12 @@ def weierstrass_div(self, verbose=True): sage: s = sandpiles.Diamond() sage: D = SandpileDivisor(s,[4,2,1,0]) - sage: [D.weierstrass_rank_seq(v) for v in s] + sage: [D.weierstrass_rank_seq(v) for v in s] # needs sage.geometry.polyhedron [(5, 4, 3, 2, 1, 0, 0, -1), (5, 4, 3, 2, 1, 0, -1), (5, 4, 3, 2, 1, 0, 0, 0, -1), (5, 4, 3, 2, 1, 0, 0, -1)] - sage: D.weierstrass_div() + sage: D.weierstrass_div() # needs sage.geometry.polyhedron {0: 1, 1: 0, 2: 2, 3: 1} sage: k5 = sandpiles.Complete(5) sage: K = k5.canonical_divisor() @@ -5789,8 +5817,8 @@ def _set_Dcomplex(self): sage: S = sandpiles.Complete(4) sage: D = SandpileDivisor(S, [0,0,1,1]) - sage: D._set_Dcomplex() - sage: '_Dcomplex' in D.__dict__ + sage: D._set_Dcomplex() # needs sage.geometry.polyhedron + sage: '_Dcomplex' in D.__dict__ # needs sage.geometry.polyhedron True """ simp = [] @@ -5826,6 +5854,7 @@ def Dcomplex(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: S = sandpiles.House() sage: p = SandpileDivisor(S, [1,2,1,0,0]).Dcomplex() sage: p.homology() @@ -5854,7 +5883,7 @@ def betti(self): sage: S = sandpiles.Cycle(3) sage: D = SandpileDivisor(S, [2,0,1]) - sage: D.betti() + sage: D.betti() # needs sage.geometry.polyhedron {0: 1, 1: 1} .. NOTE:: @@ -6099,7 +6128,7 @@ def sandlib(selector=None): riemann-roch1 : directed graph with postulation 9 and 3 maximal weight superstables riemann-roch2 : directed graph with a superstable not majorized by a maximal superstable sage: S = sandlib('gor') - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^5 <-- R^5 <-- R^1' """ # The convention is for the sink to be zero. @@ -6291,7 +6320,7 @@ def glue_graphs(g, h, glue_g, glue_h): sage: S = Sandpile(z,'sink') sage: S.h_vector() [1, 6, 17, 31, 41, 41, 31, 17, 6, 1] - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^7 <-- R^21 <-- R^35 <-- R^35 <-- R^21 <-- R^7 <-- R^1' .. NOTE:: @@ -6363,8 +6392,8 @@ def firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) - sage: eff = D.effective_div() - sage: firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.plot + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.geometry.polyhedron sage.plot ....: vertex_size=0.01) """ g = DiGraph() @@ -6400,8 +6429,8 @@ def parallel_firing_graph(S, eff): sage: S = sandpiles.Cycle(6) sage: D = SandpileDivisor(S, [1,1,1,1,2,0]) - sage: eff = D.effective_div() - sage: parallel_firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.plot + sage: eff = D.effective_div() # needs sage.geometry.polyhedron + sage: parallel_firing_graph(S, eff).show3d(edge_size=.005, # long time, needs sage.geometry.polyhedron sage.plot ....: vertex_size=0.01) """ g = DiGraph() @@ -6440,8 +6469,8 @@ def admissible_partitions(S, k): sage: from sage.sandpiles.sandpile import admissible_partitions sage: from sage.sandpiles.sandpile import partition_sandpile sage: S = sandpiles.Cycle(4) - sage: P = [admissible_partitions(S, i) for i in [2,3,4]] - sage: P + sage: P = [admissible_partitions(S, i) for i in [2,3,4]] # needs sage.combinat + sage: P # needs sage.combinat [[{{0, 2, 3}, {1}}, {{0, 3}, {1, 2}}, {{0, 1, 3}, {2}}, @@ -6453,12 +6482,12 @@ def admissible_partitions(S, k): {{0}, {1, 2}, {3}}, {{0, 1}, {2}, {3}}], [{{0}, {1}, {2}, {3}}]] - sage: for p in P: + sage: for p in P: # needs sage.combinat ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) 6 8 3 - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - @@ -6498,13 +6527,13 @@ def partition_sandpile(S, p): sage: from sage.sandpiles.sandpile import admissible_partitions, partition_sandpile sage: S = sandpiles.Cycle(4) - sage: P = [admissible_partitions(S, i) for i in [2,3,4]] - sage: for p in P: + sage: P = [admissible_partitions(S, i) for i in [2,3,4]] # needs sage.combinat + sage: for p in P: # needs sage.combinat ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) 6 8 3 - sage: S.betti() + sage: S.betti() # needs sage.libs.singular 0 1 2 3 ------------------------------ 0: 1 - - - From f9b4c6ae581f2bfebedb50bb4b915405a810ba9a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 13 Aug 2023 11:27:21 -0700 Subject: [PATCH 103/225] sage -fixdoctests --long --only-tags --distribution 'sagemath_graphs[modules]' --overwrite src/sage/graphs --- src/sage/graphs/base/static_dense_graph.pyx | 2 +- src/sage/graphs/base/static_sparse_graph.pyx | 14 ++-- src/sage/graphs/bipartite_graph.py | 8 +-- src/sage/graphs/connectivity.pyx | 6 +- src/sage/graphs/digraph_generators.py | 10 +-- src/sage/graphs/distances_all_pairs.pyx | 2 +- src/sage/graphs/generators/basic.py | 56 +++++++-------- src/sage/graphs/generators/degree_sequence.py | 8 +-- .../graphs/generators/distance_regular.pyx | 12 ++-- src/sage/graphs/generators/families.py | 30 ++++---- src/sage/graphs/generators/intersection.py | 8 +-- src/sage/graphs/generators/platonic_solids.py | 2 +- src/sage/graphs/generators/random.py | 4 +- src/sage/graphs/generators/smallgraphs.py | 28 ++++---- src/sage/graphs/generators/world_map.py | 2 +- src/sage/graphs/generic_graph.py | 70 ++++++++++--------- src/sage/graphs/graph.py | 66 ++++++++--------- src/sage/graphs/graph_coloring.pyx | 6 +- src/sage/graphs/graph_database.py | 6 +- .../graphs/graph_decompositions/cutwidth.pyx | 2 +- src/sage/graphs/graph_generators.py | 6 +- src/sage/graphs/hyperbolicity.pyx | 4 +- src/sage/graphs/independent_sets.pyx | 4 +- src/sage/graphs/strongly_regular_db.pyx | 18 ++--- src/sage/graphs/tutte_polynomial.py | 2 +- 25 files changed, 190 insertions(+), 186 deletions(-) diff --git a/src/sage/graphs/base/static_dense_graph.pyx b/src/sage/graphs/base/static_dense_graph.pyx index 2014289457d..78711fae2f1 100644 --- a/src/sage/graphs/base/static_dense_graph.pyx +++ b/src/sage/graphs/base/static_dense_graph.pyx @@ -344,7 +344,7 @@ def triangles_count(G): sage: from sage.graphs.base.static_dense_graph import triangles_count sage: triangles_count(graphs.PetersenGraph()) {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} - sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3 * binomial(15, 3) + sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3 * binomial(15, 3) # needs sage.symbolic True """ from sage.rings.integer import Integer diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index b5462299058..4b98ff027a3 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -925,7 +925,7 @@ def triangles_count(G): sage: from sage.graphs.base.static_sparse_graph import triangles_count sage: triangles_count(graphs.PetersenGraph()) {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0} - sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3*binomial(15,3) + sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3*binomial(15,3) # needs sage.symbolic True """ from sage.rings.integer import Integer @@ -1023,8 +1023,8 @@ def spectral_radius(G, prec=1e-10): sage: G = Graph([(0,1),(0,2),(1,2),(1,3),(2,4),(3,4)]) sage: e_min, e_max = spectral_radius(G, 1e-14) - sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) # needs sage.modules - sage: e_min < e < e_max # needs sage.modules + sage: e = max(G.adjacency_matrix().charpoly().roots(AA, multiplicities=False)) # needs sage.modules sage.rings.number_field + sage: e_min < e < e_max # needs sage.modules sage.rings.number_field sage.symbolic True sage: G.spectral_radius() # abs tol 1e-9 @@ -1041,8 +1041,8 @@ def spectral_radius(G, prec=1e-10): sage: p = G.adjacency_matrix(sparse=True).charpoly() sage: p x^201 - x^199 - 1 - sage: r = p.roots(AA, multiplicities=False)[0] - sage: e_min < r < e_max + sage: r = p.roots(AA, multiplicities=False)[0] # needs sage.rings.number_field + sage: e_min < r < e_max # needs sage.rings.number_field True A much larger example:: @@ -1061,7 +1061,7 @@ def spectral_radius(G, prec=1e-10): sage: G.add_edges([(0,0),(0,0),(0,1),(1,0)]) sage: spectral_radius(G, 1e-14) # abs tol 1e-14 (2.414213562373094, 2.414213562373095) - sage: max(G.adjacency_matrix().eigenvalues(AA)) # needs sage.modules + sage: max(G.adjacency_matrix().eigenvalues(AA)) # needs sage.modules sage.rings.number_field 2.414213562373095? Some bipartite graphs:: @@ -1092,7 +1092,7 @@ def spectral_radius(G, prec=1e-10): ... ValueError: precision (=1.00000000000000e-20) is too small - sage: for _ in range(100): # needs sage.modules + sage: for _ in range(100): # needs sage.modules sage.rings.number_field ....: G = digraphs.RandomDirectedGNM(10,35) ....: if not G.is_strongly_connected(): ....: continue diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index f707ee2a968..ee63977a071 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -1507,7 +1507,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): EXAMPLES:: - sage: BipartiteGraph(graphs.CubeGraph(3)).matching_polynomial() + sage: BipartiteGraph(graphs.CubeGraph(3)).matching_polynomial() # needs sage.libs.flint x^8 - 12*x^6 + 42*x^4 - 44*x^2 + 9 :: @@ -1537,7 +1537,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): TESTS:: sage: g = BipartiteGraph(matrix.ones(4, 3)) - sage: g.matching_polynomial() + sage: g.matching_polynomial() # needs sage.libs.flint x^7 - 12*x^5 + 36*x^3 - 24*x sage: g.matching_polynomial(algorithm="rook") x^7 - 12*x^5 + 36*x^3 - 24*x @@ -2138,7 +2138,7 @@ class :class:`MixedIntegerLinearProgram 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') # needs networkx 4 - sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') # needs sage.numerical.mip 4 sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Eppstein') Traceback (most recent call last): @@ -2156,7 +2156,7 @@ class :class:`MixedIntegerLinearProgram 2 sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') # needs networkx 2 - sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') # needs sage.numerical.mip 2 With multiedges enabled:: diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index ff0cabb8f37..a1f1815743a 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -1078,8 +1078,8 @@ def edge_connectivity(G, sage: for u,v in tree.edge_iterator(labels=None): ....: tree.set_edge_label(u, v, random()) sage: minimum = min(tree.edge_labels()) - sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, use_edge_labels=True) - sage: l == minimum + sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, use_edge_labels=True) # needs sage.numerical.mip + sage: l == minimum # needs sage.numerical.mip True When ``value_only=True`` and ``implementation="sage"``, this function is @@ -1128,7 +1128,7 @@ def edge_connectivity(G, Checking that the two implementations agree:: - sage: for i in range(10): + sage: for i in range(10): # needs sage.numerical.mip ....: g = graphs.RandomGNP(30, 0.3) ....: e1 = edge_connectivity(g, implementation="boost") ....: e2 = edge_connectivity(g, implementation="sage") diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index 3070cb2f37f..ec2f608e28c 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -182,7 +182,7 @@ class DiGraphGenerators(): sage: L = list(digraphs(4, lambda G: G.size() <= 3)) sage: len(L) 20 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all digraphs with degree at most 2, up to 5 vertices:: @@ -371,7 +371,7 @@ def StronglyRegular(self, n): A Strongly Regular digraph satisfies the condition `AJ = JA = kJ` where `A` is the adjacency matrix:: - sage: # needs sage.modules + sage: # needs sage.combinat sage.modules sage: g = digraphs.StronglyRegular(7); g Strongly regular digraph: Digraph on 7 vertices sage: A = g.adjacency_matrix()*ones_matrix(7) @@ -383,7 +383,7 @@ def StronglyRegular(self, n): Wrong parameter:: - sage: digraphs.StronglyRegular(73) # needs sage.modules + sage: digraphs.StronglyRegular(73) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: strongly regular digraph with 73 vertices not yet implemented @@ -516,7 +516,7 @@ def RandomTournament(self, n): sage: T = digraphs.RandomTournament(10); T Random Tournament: Digraph on 10 vertices - sage: T.size() == binomial(10, 2) + sage: T.size() == binomial(10, 2) # needs sage.symbolic True sage: T.is_tournament() True @@ -1635,7 +1635,7 @@ def RandomSemiComplete(self, n): sage: SC = digraphs.RandomSemiComplete(10); SC Random Semi-Complete digraph: Digraph on 10 vertices - sage: SC.size() >= binomial(10, 2) + sage: SC.size() >= binomial(10, 2) # needs sage.symbolic True sage: digraphs.RandomSemiComplete(-1) Traceback (most recent call last): diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index a5a90cc0c0c..865a0cea140 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -2297,7 +2297,7 @@ def szeged_index(G, algorithm=None): Check that both algorithms return same value:: sage: # long time - sage: G = graphs.RandomBarabasiAlbert(100, 2) + sage: G = graphs.RandomBarabasiAlbert(100, 2) # needs networkx sage: a = szeged_index(G, algorithm='low') sage: b = szeged_index(G, algorithm='high') sage: a == b diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 314d66aef43..11083069adc 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -43,7 +43,7 @@ def BullGraph(): sage: g = graphs.BullGraph(); g Bull graph: Graph on 5 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot The bull graph has 5 vertices and 5 edges. Its radius is 2, its diameter 3, and its girth 3. The bull graph is planar with chromatic @@ -66,9 +66,9 @@ def BullGraph(): `x` is a variable, `A` the adjacency matrix of the graph, and `I` the identity matrix of the same dimensions as `A`:: - sage: chrompoly = g.chromatic_polynomial() - sage: x = chrompoly.parent()('x') - sage: x * (x - 2) * (x - 1)^3 == chrompoly + sage: chrompoly = g.chromatic_polynomial() # needs sage.libs.flint + sage: x = chrompoly.parent()('x') # needs sage.libs.flint + sage: x * (x - 2) * (x - 1)^3 == chrompoly # needs sage.libs.flint True sage: charpoly = g.characteristic_polynomial() sage: M = g.adjacency_matrix(); M @@ -78,10 +78,10 @@ def BullGraph(): [0 1 0 0 0] [0 0 1 0 0] sage: Id = identity_matrix(ZZ, M.nrows()) - sage: D = x*Id - M - sage: D.determinant() == charpoly + sage: D = x*Id - M # needs sage.libs.flint + sage: D.determinant() == charpoly # needs sage.libs.flint sage.symbolic True - sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly + sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly # needs sage.libs.flint True """ edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)] @@ -108,7 +108,7 @@ def ButterflyGraph(): sage: G = graphs.ButterflyGraph(); G Butterfly graph: Graph on 5 vertices - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot sage: G.is_planar() True sage: G.order() @@ -170,7 +170,7 @@ def CircularLadderGraph(n): Construct and show a circular ladder graph with 26 nodes:: sage: g = graphs.CircularLadderGraph(13) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several circular ladder graphs in a Sage graphics array:: @@ -212,7 +212,7 @@ def ClawGraph(): Show a Claw graph:: - sage: (graphs.ClawGraph()).show() # long time + sage: (graphs.ClawGraph()).show() # long time # needs sage.plot Inspect a Claw graph:: @@ -500,7 +500,7 @@ def CompleteBipartiteGraph(p, q, set_position=True): Notice here how the spring-layout tends to center the nodes of `n1`:: sage: spring_med.show() # long time # needs networkx - sage: posdict_med.show() # long time + sage: posdict_med.show() # long time # needs sage.plot View many complete bipartite graphs with a Sage Graphics Array, with this constructor (i.e., the position dictionary filled):: @@ -659,7 +659,7 @@ def DiamondGraph(): Construct and show a diamond graph:: sage: g = graphs.DiamondGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1)} edges = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)] @@ -681,7 +681,7 @@ def GemGraph(): Construct and show a gem graph:: sage: g = graphs.GemGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0.5, 0), 1: (0, 0.75), 2: (0.25, 1), 3: (0.75, 1), 4: (1, 0.75)} edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (3, 4)] @@ -703,7 +703,7 @@ def ForkGraph(): Construct and show a fork graph:: sage: g = graphs.ForkGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 2), (2, 3), (3, 1), (2, 4)] @@ -723,7 +723,7 @@ def DartGraph(): Construct and show a dart graph:: sage: g = graphs.DartGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 0)} edges = [(0, 1), (0, 2), (1, 4), (2, 4), (0, 4), (3, 4)] @@ -748,7 +748,7 @@ def EmptyGraph(): sage: empty1 = graphs.EmptyGraph() sage: empty1.add_vertex() 0 - sage: empty1.show() # long time + sage: empty1.show() # long time # needs sage.plot Use for loops to build a graph from an empty graph:: @@ -764,7 +764,7 @@ def EmptyGraph(): ....: empty2.add_edge(i,i+1) # add edges {[0:1],[1:2],[2:3]} sage: for i in range(1, 4): ....: empty2.add_edge(4,i) # add edges {[1:4],[2:4],[3:4]} - sage: empty2.show() # long time + sage: empty2.show() # long time # needs sage.plot """ return Graph(sparse=True) @@ -896,7 +896,7 @@ def Grid2dGraph(p, q, set_positions=True): Construct and show a grid 2d graph Rows = `5`, Columns = `7`:: sage: g = graphs.Grid2dGraph(5,7) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS: @@ -950,14 +950,14 @@ def GridGraph(dim_list): EXAMPLES:: sage: G = graphs.GridGraph([2,3,4]) - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot :: sage: C = graphs.CubeGraph(4) sage: G = graphs.GridGraph([2,2,2,2]) - sage: C.show() # long time - sage: G.show() # long time + sage: C.show() # long time # needs sage.plot + sage: G.show() # long time # needs sage.plot TESTS: @@ -1064,7 +1064,7 @@ def HouseGraph(): Construct and show a house graph:: sage: g = graphs.HouseGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)] @@ -1092,7 +1092,7 @@ def HouseXGraph(): Construct and show a house X graph:: sage: g = graphs.HouseXGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] @@ -1116,7 +1116,7 @@ def LadderGraph(n): Construct and show a ladder graph with 14 nodes:: sage: g = graphs.LadderGraph(7) - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several ladder graphs in a Sage graphics array:: @@ -1179,26 +1179,26 @@ def PathGraph(n, pos=None): :: sage: p = graphs.PathGraph(10) - sage: p.show() # long time + sage: p.show() # long time # needs sage.plot 'circle': `10 < n < 41` :: sage: q = graphs.PathGraph(25) - sage: q.show() # long time + sage: q.show() # long time # needs sage.plot 'line': `n \geq 41` :: sage: r = graphs.PathGraph(55) - sage: r.show() # long time + sage: r.show() # long time # needs sage.plot Override the default drawing:: sage: s = graphs.PathGraph(5,'circle') - sage: s.show() # long time + sage: s.show() # long time # needs sage.plot """ G = Graph(n, name="Path graph") diff --git a/src/sage/graphs/generators/degree_sequence.py b/src/sage/graphs/generators/degree_sequence.py index ed89ce43abc..f5e68d89c79 100644 --- a/src/sage/graphs/generators/degree_sequence.py +++ b/src/sage/graphs/generators/degree_sequence.py @@ -93,15 +93,15 @@ def DegreeSequenceBipartite(s1, s2): If we are given as sequences ``[2,2,2,2,2]`` and ``[5,5]`` we are given as expected the complete bipartite graph `K_{2,5}`:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # needs sage.modules - sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # needs sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]) # needs sage.combinat sage.modules + sage: g.is_isomorphic(graphs.CompleteBipartiteGraph(5,2)) # needs sage.combinat sage.modules True Some sequences being incompatible if, for example, their sums are different, the functions raises a ``ValueError`` when no graph corresponding to the degree sequences exists:: - sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs sage.modules + sage: g = graphs.DegreeSequenceBipartite([2,2,2,2,1],[5,5]) # needs sage.combinat sage.modules Traceback (most recent call last): ... ValueError: there exists no bipartite graph corresponding to the given degree sequences @@ -110,7 +110,7 @@ def DegreeSequenceBipartite(s1, s2): :trac:`12155`:: - sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # needs sage.modules + sage: graphs.DegreeSequenceBipartite([2,2,2,2,2],[5,5]).complement() # needs sage.combinat sage.modules Graph on 7 vertices """ from sage.combinat.integer_vector import gale_ryser_theorem diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index b90795b86a1..7a476b192dc 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -321,8 +321,8 @@ def LargeWittGraph(): EXAMPLES:: - sage: g = graphs.LargeWittGraph() # needs sage.modules - sage: g.is_distance_regular(True) # needs sage.modules + sage: g = graphs.LargeWittGraph() # needs sage.libs.pari sage.modules + sage: g.is_distance_regular(True) # needs sage.libs.pari sage.modules ([30, 28, 24, None], [None, 1, 3, 15]) REFERENCES: @@ -359,7 +359,7 @@ def TruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.TruncatedWittGraph() # long time # needs sage.modules + sage: G = graphs.TruncatedWittGraph() # long time # needs sage.libs.pari sage.modules sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules ([15, 14, 12, None], [None, 1, 1, 9]) @@ -388,8 +388,8 @@ def DoublyTruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.modules - sage: G.is_distance_regular(True) # needs sage.modules + sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.libs.pari sage.modules + sage: G.is_distance_regular(True) # needs sage.libs.pari sage.modules ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) REFERENCES: @@ -2143,7 +2143,7 @@ def graph_with_classical_parameters(int d, int b, alpha_in, beta_in, int gamma): Half 4 Cube: Graph on 8 vertices sage: graph_with_classical_parameters(3, 2, 0, 2, 9) # needs sage.libs.gap Symplectic Dual Polar Graph DSp(6, 2): Graph on 135 vertices - sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time + sage: graph_with_classical_parameters(3, 2, 2, 14, 7) # long time # needs sage.symbolic Grassmann graph J_2(6, 3): Graph on 1395 vertices sage: graph_with_classical_parameters(3, -2, -2, 6, 6) # optional - gap_package_atlasrep internet Generalised hexagon of order (2, 8): Graph on 819 vertices diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 54ea6c2d9d2..ecc626f2451 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -614,7 +614,7 @@ def BarbellGraph(n1, n2): sage: g = graphs.BarbellGraph(9, 4); g Barbell graph: Graph on 22 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot An ``n1 >= 2``, ``n2 >= 0`` barbell graph has order ``2*n1 + n2``. It has the complete graph on ``n1`` vertices as a subgraph. It also has @@ -712,7 +712,7 @@ def LollipopGraph(n1, n2): sage: g = graphs.LollipopGraph(13,4); g Lollipop graph: Graph on 17 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -785,7 +785,7 @@ def TadpoleGraph(n1, n2): sage: g = graphs.TadpoleGraph(13, 4); g Tadpole graph: Graph on 17 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -877,7 +877,7 @@ def DipoleGraph(n): sage: g = graphs.DipoleGraph(13); g Dipole graph: Multi-graph on 2 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -935,7 +935,7 @@ def BubbleSortGraph(n): sage: g = graphs.BubbleSortGraph(4); g Bubble sort: Graph on 24 vertices - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 61 graphics primitives The bubble sort graph on `n = 1` symbol is the trivial graph `K_1`:: @@ -1313,9 +1313,9 @@ def GoethalsSeidelGraph(k, r): EXAMPLES:: - sage: graphs.GoethalsSeidelGraph(3,3) # needs sage.modules + sage: graphs.GoethalsSeidelGraph(3,3) # needs sage.combinat sage.modules Graph on 28 vertices - sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) # needs sage.modules + sage: graphs.GoethalsSeidelGraph(3,3).is_strongly_regular(parameters=True) # needs sage.combinat sage.modules (28, 15, 6, 10) """ from sage.combinat.designs.bibd import balanced_incomplete_block_design @@ -2137,7 +2137,7 @@ def HyperStarGraph(n, k): sage: g = graphs.HyperStarGraph(6,3) sage: sorted(g.neighbors('011100')) ['101100', '110100', '111000'] - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 51 graphics primitives TESTS:: @@ -2406,7 +2406,7 @@ def NKStarGraph(n, k): EXAMPLES:: sage: g = graphs.NKStarGraph(4,2) - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 31 graphics primitives REFERENCES: @@ -2465,7 +2465,7 @@ def NStarGraph(n): EXAMPLES:: sage: g = graphs.NStarGraph(4) - sage: g.plot() # long time + sage: g.plot() # long time # needs sage.plot Graphics object consisting of 61 graphics primitives REFERENCES: @@ -2639,7 +2639,7 @@ def SquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: # needs sage.modules + sage: # needs sage.combinat sage.modules sage: G = graphs.SquaredSkewHadamardMatrixGraph(4) sage: G.is_strongly_regular(parameters=True) (225, 112, 55, 56) @@ -2693,7 +2693,7 @@ def SwitchedSquaredSkewHadamardMatrixGraph(n): EXAMPLES:: - sage: # needs sage.modules + sage: # needs sage.combinat sage.modules sage: g = graphs.SwitchedSquaredSkewHadamardMatrixGraph(4) sage: g.is_strongly_regular(parameters=True) (226, 105, 48, 49) @@ -3841,13 +3841,13 @@ def MathonPseudocyclicMergingGraph(M, t): sage: from sage.graphs.generators.families import MathonPseudocyclicMergingGraph as mer sage: from sage.graphs.generators.smallgraphs import _EllipticLinesProjectivePlaneScheme as ES - sage: G = mer(ES(3), 0) # long time + sage: G = mer(ES(3), 0) # long time # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) # long time (784, 243, 82, 72) - sage: G = mer(ES(3), 1) # long time + sage: G = mer(ES(3), 1) # long time # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) # long time (784, 270, 98, 90) - sage: G = mer(ES(3), 2) # long time + sage: G = mer(ES(3), 2) # long time # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) # long time (784, 297, 116, 110) sage: G = mer(ES(2), 2) # needs sage.libs.gap diff --git a/src/sage/graphs/generators/intersection.py b/src/sage/graphs/generators/intersection.py index 0de3715e0e1..0d19d30f9ea 100644 --- a/src/sage/graphs/generators/intersection.py +++ b/src/sage/graphs/generators/intersection.py @@ -464,20 +464,20 @@ def OrthogonalArrayBlockGraph(k, n, OA=None): But nevertheless isospectral:: - sage: g0.spectrum() # needs sage.modules + sage: g0.spectrum() # needs sage.modules sage.rings.number_field [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] - sage: g1.spectrum() # needs sage.modules + sage: g1.spectrum() # needs sage.modules sage.rings.number_field [9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3] Note that the graph ``g0`` is actually isomorphic to the affine polar graph `VO^+(4,2)`:: - sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.modules + sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.libs.gap sage.modules True TESTS:: - sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules + sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules sage.schemes Traceback (most recent call last): ... NotImplementedError: I don't know how to build an OA(4,6)! diff --git a/src/sage/graphs/generators/platonic_solids.py b/src/sage/graphs/generators/platonic_solids.py index 38e070a054a..d3bc60a9974 100644 --- a/src/sage/graphs/generators/platonic_solids.py +++ b/src/sage/graphs/generators/platonic_solids.py @@ -142,7 +142,7 @@ def OctahedralGraph(): Construct and show an Octahedral graph:: sage: g = graphs.OctahedralGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot Create several octahedral graphs in a Sage graphics array They will be drawn differently due to the use of the spring-layout algorithm:: diff --git a/src/sage/graphs/generators/random.py b/src/sage/graphs/generators/random.py index 5dab4071f49..d253633621c 100644 --- a/src/sage/graphs/generators/random.py +++ b/src/sage/graphs/generators/random.py @@ -69,7 +69,7 @@ def RandomGNP(n, p, seed=None, fast=True, algorithm='Sage'): We plot a random graph on 12 nodes with probability `p = .71`:: sage: gnp = graphs.RandomGNP(12,.71) - sage: gnp.show() # long time + sage: gnp.show() # long time # needs sage.plot We view many random graphs using a graphics array:: @@ -1359,7 +1359,7 @@ def RandomTree(n, seed=None): sage: G = graphs.RandomTree(10) sage: G.is_tree() True - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot TESTS: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index a090eb3f73d..b5092e16ca9 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -456,7 +456,7 @@ def Cell600(embedding=1): EXAMPLES:: sage: # long time - sage: g = graphs.Cell600() + sage: g = graphs.Cell600() # needs sage.rings.number_field sage: g.size() 720 sage: g.is_regular(12) @@ -532,7 +532,7 @@ def Cell120(): EXAMPLES:: sage: # long time - sage: g = graphs.Cell120() + sage: g = graphs.Cell120() # needs sage.rings.number_field sage: g.size() 1200 sage: g.is_regular(4) @@ -1066,7 +1066,7 @@ def BidiakisCube(): sage: g = graphs.BidiakisCube(); g Bidiakis cube: Graph on 12 vertices - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot sage: g.order() 12 sage: g.size() @@ -1297,7 +1297,7 @@ def BrinkmannGraph(): sage: G = graphs.BrinkmannGraph(); G Brinkmann graph: Graph on 21 vertices - sage: G.show() # long time + sage: G.show() # long time # needs sage.plot sage: G.order() 21 sage: G.size() @@ -2184,7 +2184,7 @@ def EllinghamHorton54Graph(): TESTS:: - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot """ edge_dict = { 0: [1, 11, 15], 1: [2, 47], 2: [3, 13], 3: [4, 8], 4: [5, 15], @@ -2425,7 +2425,7 @@ def FlowerSnark(): Now show it:: - sage: F.show() # long time + sage: F.show() # long time # needs sage.plot """ d = {0: [1, 14, 15], 1: [2, 11], 2: [3, 7], 3: [2, 4, 16], 4: [5, 14], 5: [6, 10], 6: [5, 7, 17], 8: [7, 9, 13], 9: [10, 18], 11: [10, 12], @@ -2844,7 +2844,7 @@ def HeawoodGraph(): Heawood graph: Graph on 14 vertices sage: H.graph6_string() 'MhEGHC@AI?_PC@_G_' - sage: (graphs.HeawoodGraph()).show() # long time + sage: (graphs.HeawoodGraph()).show() # long time # needs sage.plot TESTS:: @@ -3303,7 +3303,7 @@ def KrackhardtKiteGraph(): Construct and show a Krackhardt kite graph :: sage: g = graphs.KrackhardtKiteGraph() - sage: g.show() # long time + sage: g.show() # long time # needs sage.plot TESTS:: @@ -4534,7 +4534,7 @@ def TutteGraph(): 69 sage: g.is_planar() True - sage: g.vertex_connectivity() # long time + sage: g.vertex_connectivity() # long time # needs sage.numerical.mip 3 sage: g.girth() 4 @@ -4755,17 +4755,17 @@ def MathonStronglyRegularGraph(t): EXAMPLES:: sage: from sage.graphs.generators.smallgraphs import MathonStronglyRegularGraph - sage: G = MathonStronglyRegularGraph(0) # long time + sage: G = MathonStronglyRegularGraph(0) # long time # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) # long time (784, 243, 82, 72) TESTS:: sage: # long time - sage: G = graphs.MathonStronglyRegularGraph(1) + sage: G = graphs.MathonStronglyRegularGraph(1) # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) - sage: G = graphs.MathonStronglyRegularGraph(2) + sage: G = graphs.MathonStronglyRegularGraph(2) # needs sage.libs.gap sage: G.is_strongly_regular(parameters=True) (784, 297, 116, 110) @@ -4789,7 +4789,7 @@ def JankoKharaghaniGraph(v): EXAMPLES:: - sage: g = graphs.JankoKharaghaniGraph(936) # long time + sage: g = graphs.JankoKharaghaniGraph(936) # long time # needs sage.libs.pari sage: g.is_strongly_regular(parameters=True) # long time (936, 375, 150, 150) @@ -4881,7 +4881,7 @@ def JankoKharaghaniTonchevGraph(): EXAMPLES:: - sage: Gamma=graphs.JankoKharaghaniTonchevGraph() # long time + sage: Gamma=graphs.JankoKharaghaniTonchevGraph() # long time # needs sage.libs.gap sage: Gamma.is_strongly_regular(parameters=True) # long time (324, 153, 72, 72) """ diff --git a/src/sage/graphs/generators/world_map.py b/src/sage/graphs/generators/world_map.py index 76c32335f60..f131aa446e2 100644 --- a/src/sage/graphs/generators/world_map.py +++ b/src/sage/graphs/generators/world_map.py @@ -48,7 +48,7 @@ def AfricaMap(continental=False, year=2018): TESTS:: - sage: Africa.plot() # long time + sage: Africa.plot() # long time # needs sage.plot Graphics object consisting of 159 graphics primitives """ if year != 2018: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 19cc35bfb0b..bc03ec01252 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -959,7 +959,7 @@ def _matrix_(self, R=None, vertices=None): [1 1 0 0 0] [1 1 0 0 0] [1 1 0 0 0] - sage: factor(m.charpoly()) # needs sage.modules + sage: factor(m.charpoly()) # needs sage.libs.pari sage.modules x^3 * (x^2 - 6) """ return self.am(vertices=vertices, base_ring=R) @@ -1983,7 +1983,7 @@ def adjacency_matrix(self, sparse=None, vertices=None, *, base_ring=None, **kwds A different matrix implementation:: - sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, # needs sage.modules + sage: graphs.PathGraph(5).adjacency_matrix(sparse=False, # needs numpy sage.modules ....: implementation='numpy') [0 1 0 0 0] [1 0 1 0 0] @@ -6811,13 +6811,13 @@ def steiner_tree(self, vertices, weighted=False, solver=None, verbose=0, sage: g = graphs.RandomGNP(30, .5) sage: first5 = g.vertices(sort=True)[:5] - sage: st = g.steiner_tree(first5) - sage: st.is_tree() + sage: st = g.steiner_tree(first5) # needs sage.numerical.mip + sage: st.is_tree() # needs sage.numerical.mip True And all the 5 vertices are contained in this tree :: - sage: all(v in st for v in first5) + sage: all(v in st for v in first5) # needs sage.numerical.mip True An exception is raised when the problem is impossible, i.e. if the @@ -7024,7 +7024,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None sage: d6 += r'@ADA@AAg?GAQW?[aIaSwHYcD@qQb@Dd?\hJTI@OHlJ_?C_OEIKoeC' sage: d6 += r'R@_BC?Q??YBFosqITEA?IvCU_' sage: G = DiGraph(d6, format='dig6') - sage: G.edge_connectivity() + sage: G.edge_connectivity() # needs sage.numerical.mip 5 sage: G.edge_disjoint_spanning_trees(5) # long time # needs sage.numerical.mip [Digraph on 28 vertices, @@ -7055,11 +7055,12 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None Choice of the algorithm:: - sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) # needs sage.numerical.mip + sage: # needs sage.numerical.mip + sage: Graph().edge_disjoint_spanning_trees(0, algorithm=None) [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="Roskind-Tarjan") [] - sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip + sage: Graph().edge_disjoint_spanning_trees(0, algorithm="MILP") [] sage: Graph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -7067,7 +7068,7 @@ def edge_disjoint_spanning_trees(self, k, algorithm=None, root=None, solver=None ValueError: algorithm must be None, "Rosking-Tarjan" or "MILP" for undirected graphs sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm=None) [] - sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") # needs sage.numerical.mip + sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="MILP") [] sage: DiGraph().edge_disjoint_spanning_trees(0, algorithm="foo") Traceback (most recent call last): @@ -7284,7 +7285,8 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, The two sides of the edge cut are obviously shorter paths:: - sage: value,edges,[set1,set2] = g.edge_cut(0, 14, use_edge_labels=True, vertices=True) + sage: value, edges, [set1, set2] = g.edge_cut(0, 14, use_edge_labels=True, + ....: vertices=True) sage: g.subgraph(set1).is_isomorphic(graphs.PathGraph(len(set1))) True sage: g.subgraph(set2).is_isomorphic(graphs.PathGraph(len(set2))) @@ -7307,7 +7309,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, sage: g = graphs.RandomGNP(20,.3) sage: for u,v in g.edges(sort=True, labels=False): ....: g.set_edge_label(u,v,round(random(),5)) - sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="LP") + sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="LP") # needs sage.numerical.mip True sage: g.edge_cut(0, 1, algorithm="FF") == g.edge_cut(0, 1, algorithm="igraph") # optional - python_igraph True @@ -7315,7 +7317,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, Rounded return value when using the LP method:: sage: g = graphs.PappusGraph() - sage: g.edge_cut(1, 2, value_only=True, algorithm="LP") + sage: g.edge_cut(1, 2, value_only=True, algorithm="LP") # needs sage.numerical.mip 3 :trac:`12797`:: @@ -7326,7 +7328,7 @@ def edge_cut(self, s, t, value_only=True, use_edge_labels=False, vertices=False, sage: G = DiGraph([(0, 3, 1), (0, 4, 1), (2, 1, 1), (3, 2, 1), (4, 2, 1)]) sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True) [1, [(2, 1, 1)]] - sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True, algorithm='LP') + sage: G.edge_cut(0, 1, value_only=False, use_edge_labels=True, algorithm='LP') # needs sage.numerical.mip (1, [(2, 1)]) """ self._scream_if_not_simple(allow_loops=True) @@ -9523,8 +9525,8 @@ def flow(self, x, y, value_only=True, integer=False, use_edge_labels=True, sage: for u, v in g.edge_iterator(labels=False): ....: g.set_edge_label(u, v, round(random(), 5)) sage: flow_ff = g.flow(0, 1, algorithm="FF") - sage: flow_lp = g.flow(0, 1, algorithm="LP") - sage: abs(flow_ff - flow_lp) < 0.01 + sage: flow_lp = g.flow(0, 1, algorithm="LP") # needs sage.numerical.mip + sage: abs(flow_ff - flow_lp) < 0.01 # needs sage.numerical.mip True sage: flow_igraph = g.flow(0, 1, algorithm="igraph") # optional python_igraph sage: abs(flow_ff - flow_igraph) < 0.00001 # optional python_igraph @@ -12369,7 +12371,7 @@ def set_edge_label(self, u, v, l): ....: 9: [6, 11], 10: [9, 1], 11: [10, 6], 12: [13, 6], ....: 13: [16, 2], 14: [10, -6], 15: [0, -10], 16: [14, -6], ....: 17: [16, -10], 18: [6, -4]} - sage: SD.plot(pos=posn, vertex_size=400, vertex_colors={'#FFFFFF':list(range(1,19))}, edge_labels=True).show() # long time + sage: SD.plot(pos=posn, vertex_size=400, vertex_colors={'#FFFFFF':list(range(1,19))}, edge_labels=True).show() # long time, needs sage.plot :: @@ -15632,7 +15634,7 @@ def distance(self, u, v, by_weight=False, weight_function=None, check_weight=Tru sage: G.distance(0,1) +Infinity sage: G = Graph({ 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse = True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.distance(0, 3) 2 sage: G.distance(0, 3, by_weight=True) @@ -16650,7 +16652,7 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, [] sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, ....: sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_path(0, 3) [0, 4, 3] sage: G.shortest_path(0, 3, by_weight=True) @@ -16837,7 +16839,7 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, +Infinity sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, ....: sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_path_length(0, 3) 2 sage: G.shortest_path_length(0, 3, by_weight=True) @@ -17145,7 +17147,7 @@ def shortest_paths(self, u, by_weight=False, algorithm=None, 9: [0, 10, 9], 10: [0, 10], 11: [0, 10, 11], 18: [0, 19, 18], 19: [0, 19]} sage: G = Graph( { 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2} }, sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: G.shortest_paths(0, by_weight=True) {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 4]} @@ -17556,8 +17558,8 @@ def shortest_path_all_pairs(self, by_weight=False, algorithm=None, Some standard examples (see :meth:`~GenericGraph.shortest_paths` for more examples on how to use the input variables):: - sage: G = Graph( { 0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2} }, sparse=True) - sage: G.plot(edge_labels=True).show() # long time + sage: G = Graph({0: {1: 1}, 1: {2: 1}, 2: {3: 1}, 3: {4: 2}, 4: {0: 2}}, sparse=True) + sage: G.plot(edge_labels=True).show() # long time # needs sage.plot sage: dist, pred = G.shortest_path_all_pairs(by_weight = True) sage: dist {0: {0: 0, 1: 1, 2: 2, 3: 3, 4: 2}, @@ -19087,7 +19089,7 @@ def tensor_product(self, other): Graph on 10 vertices sage: T.size() 10 - sage: T.plot() # long time + sage: T.plot() # long time # needs sage.plot Graphics object consisting of 21 graphics primitives :: @@ -19098,7 +19100,7 @@ def tensor_product(self, other): Graph on 200 vertices sage: T.size() 900 - sage: T.plot() # long time + sage: T.plot() # long time # needs sage.plot Graphics object consisting of 1101 graphics primitives TESTS: @@ -19168,7 +19170,7 @@ def lexicographic_product(self, other): sage: C = graphs.CycleGraph(5) sage: L = C.lexicographic_product(Z); L Graph on 10 vertices - sage: L.plot() # long time + sage: L.plot() # long time # needs sage.plot Graphics object consisting of 36 graphics primitives :: @@ -19177,7 +19179,7 @@ def lexicographic_product(self, other): sage: P = graphs.PetersenGraph() sage: L = D.lexicographic_product(P); L Graph on 200 vertices - sage: L.plot() # long time + sage: L.plot() # long time # needs sage.plot Graphics object consisting of 3501 graphics primitives TESTS: @@ -19248,7 +19250,7 @@ def strong_product(self, other): sage: C = graphs.CycleGraph(5) sage: S = C.strong_product(Z); S Graph on 10 vertices - sage: S.plot() # long time + sage: S.plot() # long time # needs sage.plot Graphics object consisting of 36 graphics primitives :: @@ -19257,7 +19259,7 @@ def strong_product(self, other): sage: P = graphs.PetersenGraph() sage: S = D.strong_product(P); S Graph on 200 vertices - sage: S.plot() # long time + sage: S.plot() # long time # needs sage.plot Graphics object consisting of 1701 graphics primitives TESTS: @@ -19328,7 +19330,7 @@ def disjunctive_product(self, other): sage: Z = graphs.CompleteGraph(2) sage: D = Z.disjunctive_product(Z); D Graph on 4 vertices - sage: D.plot() # long time + sage: D.plot() # long time # needs sage.plot Graphics object consisting of 11 graphics primitives :: @@ -19336,7 +19338,7 @@ def disjunctive_product(self, other): sage: C = graphs.CycleGraph(5) sage: D = C.disjunctive_product(Z); D Graph on 10 vertices - sage: D.plot() # long time + sage: D.plot() # long time # needs sage.plot Graphics object consisting of 46 graphics primitives TESTS: @@ -23601,7 +23603,7 @@ def is_isomorphic(self, other, certificate=False, verbosity=0, edge_labels=False sage: position_E = {} sage: for vert in position_D: ....: position_E[b[vert]] = position_D[vert] - sage: graphics_array([D.plot(pos=position_D), E.plot(pos=position_E)]).show() # long time + sage: graphics_array([D.plot(pos=position_D), E.plot(pos=position_E)]).show() # long time, needs sage.plot :: @@ -24587,7 +24589,7 @@ def katz_centrality(self, alpha, u=None): all 4 vertices have the same centrality) :: sage: G = graphs.CycleGraph(4) - sage: G.katz_centrality(1/20) # needs sage.modules + sage: G.katz_centrality(1/20) # needs sage.modules sage.rings.number_field {0: 1/9, 1: 1/9, 2: 1/9, 3: 1/9} Note that in the below example the nodes having indegree `0` also have @@ -24596,7 +24598,7 @@ def katz_centrality(self, alpha, u=None): sage: G = DiGraph({1: [10], 2:[10,11], 3:[10,11], 4:[], 5:[11, 4], 6:[11], ....: 7:[10,11], 8:[10,11], 9:[10], 10:[11, 5, 8], 11:[6]}) - sage: G.katz_centrality(.85) # rel tol 1e-14 # needs sage.modules + sage: G.katz_centrality(.85) # rel tol 1e-14 # needs sage.modules sage.rings.number_field {1: 0.000000000000000, 2: 0.000000000000000, 3: 0.000000000000000, @@ -24617,7 +24619,7 @@ def katz_centrality(self, alpha, u=None): TESTS:: - sage: # needs sage.modules + sage: # needs sage.modules sage.rings.number_field sage: graphs.PathGraph(3).katz_centrality(1/20) {0: 11/199, 1: 21/199, 2: 11/199} sage: graphs.PathGraph(4).katz_centrality(1/20) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index fe02be46c77..be302ca6043 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -783,10 +783,10 @@ class Graph(GenericGraph): #. A Seidel adjacency matrix:: - sage: from sage.combinat.matrices.hadamard_matrix import ( # needs sage.modules + sage: from sage.combinat.matrices.hadamard_matrix import ( # needs sage.combinat sage.modules ....: regular_symmetric_hadamard_matrix_with_constant_diagonal as rshcd) - sage: m = rshcd(16,1) - matrix.identity(16) # needs sage.modules - sage: Graph(m, # needs sage.modules + sage: m = rshcd(16,1) - matrix.identity(16) # needs sage.combinat sage.modules + sage: Graph(m, # needs sage.combinat sage.modules ....: format="seidel_adjacency_matrix").is_strongly_regular(parameters=True) (16, 6, 2, 2) @@ -2463,7 +2463,7 @@ def is_triangle_free(self, algorithm='dense_graph', certificate=False): Comparison of algorithms:: - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: G = graphs.RandomBarabasiAlbert(50,2) ....: bm = G.is_triangle_free(algorithm='matrix') ....: bb = G.is_triangle_free(algorithm='bitset') @@ -3334,15 +3334,15 @@ def bounded_outdegree_orientation(self, bound, solver=None, verbose=False, divided by 2. Anything less, though, is impossible. sage: g = graphs.RandomGNP(40, .4) - sage: mad = g.maximum_average_degree() + sage: mad = g.maximum_average_degree() # needs sage.numerical.mip Hence this is possible :: - sage: d = g.bounded_outdegree_orientation(integer_ceil(mad/2)) + sage: d = g.bounded_outdegree_orientation(integer_ceil(mad/2)) # needs sage.numerical.mip While this is not:: - sage: try: + sage: try: # needs sage.numerical.mip ....: g.bounded_outdegree_orientation(integer_ceil(mad/2-1)) ....: print("Error") ....: except ValueError: @@ -3746,7 +3746,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, 3 sage: G.chromatic_number(algorithm="MILP") 3 - sage: G.chromatic_number(algorithm="CP") + sage: G.chromatic_number(algorithm="CP") # needs sage.libs.flint 3 sage: G.chromatic_number(algorithm="parallel") 3 @@ -3786,7 +3786,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, 0 sage: G.chromatic_number(algorithm="MILP") 0 - sage: G.chromatic_number(algorithm="CP") + sage: G.chromatic_number(algorithm="CP") # needs sage.libs.flint 0 sage: G.chromatic_number(algorithm="parallel") 0 @@ -3801,7 +3801,7 @@ def chromatic_number(self, algorithm="DLX", solver=None, verbose=0, sage: G = graphs.RandomGNP(15, .2) sage: algorithms = ['DLX', 'MILP', 'CP', 'parallel'] - sage: len(set([G.chromatic_number(algorithm=algo) for algo in algorithms])) == 1 + sage: len(set([G.chromatic_number(algorithm=algo) for algo in algorithms])) == 1 # needs sage.libs.flint True """ self._scream_if_not_simple(allow_multiple_edges=True) @@ -4166,7 +4166,7 @@ def matching(self, value_only=False, algorithm="Edmonds", Same test with the Linear Program formulation:: sage: g = graphs.PappusGraph() - sage: g.matching(algorithm="LP", value_only=True) + sage: g.matching(algorithm="LP", value_only=True) # needs sage.numerical.mip 9 .. PLOT:: @@ -4182,7 +4182,7 @@ def matching(self, value_only=False, algorithm="Edmonds", sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) sage: sorted(g.matching()) # needs sage.networkx [(0, 1, 0), (2, 3, -5)] - sage: sorted(g.matching(algorithm="LP")) + sage: sorted(g.matching(algorithm="LP")) # needs sage.numerical.mip [(0, 1, 0), (2, 3, -5)] When ``use_edge_labels`` is set to ``True``, with Edmonds' algorithm and @@ -4191,7 +4191,7 @@ def matching(self, value_only=False, algorithm="Edmonds", sage: g = Graph([(0,1,0), (1,2,999), (2,3,-5)]) sage: g.matching(use_edge_labels=True) # needs sage.networkx [(1, 2, 999)] - sage: g.matching(algorithm="LP", use_edge_labels=True) + sage: g.matching(algorithm="LP", use_edge_labels=True) # needs sage.numerical.mip [(1, 2, 999)] With loops and multiedges:: @@ -5088,18 +5088,20 @@ def convexity_properties(self): .. NOTE:: - If you want to compute many convex hulls, keep this object in memory - ! When it is created, it builds a table of useful information to + If you want to compute many convex hulls, keep this object in memory! + When it is created, it builds a table of useful information to compute convex hulls. As a result :: + sage: # needs sage.numerical.mip sage: g = graphs.PetersenGraph() sage: g.convexity_properties().hull([1, 3]) [1, 2, 3] sage: g.convexity_properties().hull([3, 7]) [2, 3, 7] - Is a terrible waste of computations, while :: + is a terrible waste of computations, while :: + sage: # needs sage.numerical.mip sage: g = graphs.PetersenGraph() sage: CP = g.convexity_properties() sage: CP.hull([1, 3]) @@ -5107,7 +5109,7 @@ def convexity_properties(self): sage: CP.hull([3, 7]) [2, 3, 7] - Makes perfect sense. + makes perfect sense. """ from sage.graphs.convexity_properties import ConvexityProperties return ConvexityProperties(self) @@ -5849,7 +5851,7 @@ def distance_graph(self, dist): sage: # long time sage: G = graphs.CubeGraph(8) sage: H = G.distance_graph([1,3,5,7]) - sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) + sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # needs sage.symbolic sage: degrees.append(2^8) sage: degrees == H.degree_histogram() True @@ -7500,7 +7502,7 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, EXAMPLES:: sage: C = Graph('DJ{') - sage: C.cliques_vertex_clique_number() + sage: C.cliques_vertex_clique_number() # needs sage.plot {0: 2, 1: 4, 2: 4, 3: 4, 4: 4} sage: E = C.cliques_maximal(); E [[0, 4], [1, 2, 3, 4]] @@ -7510,12 +7512,12 @@ def cliques_vertex_clique_number(self, algorithm="cliquer", vertices=None, sage: F = graphs.Grid2dGraph(2,3) sage: F.cliques_vertex_clique_number(algorithm="networkx") # needs networkx {(0, 0): 2, (0, 1): 2, (0, 2): 2, (1, 0): 2, (1, 1): 2, (1, 2): 2} - sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) + sage: F.cliques_vertex_clique_number(vertices=[(0, 1), (1, 2)]) # needs sage.plot {(0, 1): 2, (1, 2): 2} sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]}) sage: G.show(figsize=[2,2]) # needs sage.plot - sage: G.cliques_vertex_clique_number() + sage: G.cliques_vertex_clique_number() # needs sage.plot {0: 3, 1: 3, 2: 3, 3: 3} """ if algorithm == "cliquer": @@ -8283,9 +8285,9 @@ def is_inscribable(self, solver="ppl", verbose=0): EXAMPLES:: sage: H = graphs.HerschelGraph() - sage: H.is_inscribable() # long time (> 1 sec) + sage: H.is_inscribable() # long time (> 1 sec) # needs sage.numerical.mip False - sage: H.planar_dual().is_inscribable() # long time (> 1 sec) + sage: H.planar_dual().is_inscribable() # long time (> 1 sec) # needs sage.numerical.mip True sage: C = graphs.CubeGraph(3) @@ -8929,8 +8931,8 @@ def perfect_matchings(self, labels=False): [[(-2, 1, 'x'), (-1, 2, 'y')], [(-2, 2, 'b'), (-1, 1, 'a')]] sage: G = graphs.CompleteGraph(8) - sage: mpc = G.matching_polynomial().coefficients(sparse=False)[0] - sage: len(list(G.perfect_matchings())) == mpc + sage: mpc = G.matching_polynomial().coefficients(sparse=False)[0] # needs sage.libs.flint + sage: len(list(G.perfect_matchings())) == mpc # needs sage.libs.flint True sage: G = graphs.PetersenGraph().copy(immutable=True) @@ -9049,15 +9051,15 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0, True sage: graphs.WheelGraph(5).has_perfect_matching() # needs networkx False - sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True - sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") False - sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True - sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") # needs sage.numerical.mip True sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") False @@ -9156,7 +9158,7 @@ def effective_resistance(self, i, j, *, base_ring=None): Using a different base ring:: - sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 # needs sage.modules + sage: H.effective_resistance(1, 5, base_ring=RDF) # abs tol 1e-14 # needs numpy sage.modules 1.2000000000000000 sage: H.effective_resistance(1, 1, base_ring=RDF) # needs sage.modules 0.0 @@ -9189,7 +9191,7 @@ def effective_resistance(self, i, j, *, base_ring=None): 2/3 sage: G = Graph([(0,1),(0,2),(0,3),(0,4),(0,5),(1,2),(2,3),(3,4),(4,5),(5,1)]) sage: r = G.effective_resistance(0,3) - sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) + sage: r == fibonacci(2*(5-3)+1)*fibonacci(2*3-1)/fibonacci(2*5) # needs sage.libs.pari True sage: G = graphs.PathGraph(4) sage: G.delete_edge(2,3) @@ -9303,7 +9305,7 @@ def effective_resistance_matrix(self, vertices=None, nonedgesonly=True, A different base ring:: - sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() # needs sage.modules + sage: H.effective_resistance_matrix(base_ring=RDF)[0, 0].parent() # needs numpy sage.modules Real Double Field .. SEEALSO:: diff --git a/src/sage/graphs/graph_coloring.pyx b/src/sage/graphs/graph_coloring.pyx index f11bc3c4a05..b58881c5fd7 100644 --- a/src/sage/graphs/graph_coloring.pyx +++ b/src/sage/graphs/graph_coloring.pyx @@ -1599,7 +1599,7 @@ def _vizing_edge_coloring(g): True sage: all(g.has_edge(e) for C in colors for e in C) True - sage: all(len(Graph(C).matching()) == len(C) for C in colors) + sage: all(len(Graph(C).matching()) == len(C) for C in colors) # needs networkx True """ # This implementation was discussed in github issue #34809 @@ -2239,7 +2239,7 @@ cdef class Test: TESTS:: sage: from sage.graphs.graph_coloring import Test - sage: Test().random(1) + sage: Test().random(1) # needs sage.libs.flint """ self.random_all_graph_colorings(tests) @@ -2258,7 +2258,7 @@ cdef class Test: TESTS:: sage: from sage.graphs.graph_coloring import Test - sage: Test().random_all_graph_colorings(1) + sage: Test().random_all_graph_colorings(1) # needs sage.libs.flint """ from sage.graphs.generators.random import RandomGNP cdef set S diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index b8e9226bc2c..9dec951aa98 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -972,8 +972,8 @@ def query(self, query_dict=None, display_cols=None, **kwds): EXAMPLES:: sage: D = GraphDatabase() - sage: q = D.query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5]) - sage: q.show() + sage: q = D.query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5]) # needs sage.symbolic + sage: q.show() # needs sage.symbolic Graph6 Num Vertices Degree Sequence ------------------------------------------------------------ @ 1 [0] @@ -1109,7 +1109,7 @@ def interactive_query(self, display_cols, **kwds): EXAMPLES:: sage: D = GraphDatabase() - sage: D.interactive_query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=5, max_degree=3) + sage: D.interactive_query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=5, max_degree=3) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: not available in Jupyter notebook diff --git a/src/sage/graphs/graph_decompositions/cutwidth.pyx b/src/sage/graphs/graph_decompositions/cutwidth.pyx index 208bd69dea4..ddaf746adac 100644 --- a/src/sage/graphs/graph_decompositions/cutwidth.pyx +++ b/src/sage/graphs/graph_decompositions/cutwidth.pyx @@ -335,7 +335,7 @@ def cutwidth(G, algorithm="exponential", cut_off=0, solver=None, verbose=False, Comparison of algorithms:: sage: from sage.graphs.graph_decompositions.cutwidth import cutwidth - sage: for i in range(2): # long time + sage: for i in range(2): # long time # needs sage.numerical.mip ....: G = graphs.RandomGNP(7, 0.3) ....: ve, le = cutwidth(G, algorithm="exponential") ....: vm, lm = cutwidth(G, algorithm="MILP", solver='GLPK') diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index f1d53f31e95..e45371bc6d9 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -606,7 +606,7 @@ class GraphGenerators(): sage: L = list(graphs(5, lambda G: G.size() <= 4)) sage: len(L) 14 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all graphs with up to 5 vertices and up to 4 edges. @@ -615,7 +615,7 @@ class GraphGenerators(): sage: L = list(graphs(5, lambda G: G.size() <= 4, augment='vertices')) sage: len(L) 31 - sage: graphs_list.show_graphs(L) # long time + sage: graphs_list.show_graphs(L) # long time # needs sage.plot Generate all graphs with degree at most 2, up to 6 vertices. @@ -1280,7 +1280,7 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr ....: for i in range(g.order()): ....: A.rescale_row(i, 1 / len(A.nonzero_positions_in_row(i))) ....: return A - sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, # needs sage.modules + sage: g = graphs.cospectral_graphs(5, matrix_function=DinverseA, # needs sage.libs.pari sage.modules ....: graphs=lambda g: min(g.degree()) > 0) sage: sorted(sorted(g.graph6_string() for g in glist) for glist in g) # needs sage.modules [['Dlg', 'Ds_']] diff --git a/src/sage/graphs/hyperbolicity.pyx b/src/sage/graphs/hyperbolicity.pyx index fd7a717a2a4..6475b5a719a 100644 --- a/src/sage/graphs/hyperbolicity.pyx +++ b/src/sage/graphs/hyperbolicity.pyx @@ -1188,7 +1188,7 @@ def hyperbolicity(G, Comparison of results:: sage: from sage.graphs.hyperbolicity import hyperbolicity - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: G = graphs.RandomBarabasiAlbert(100,2) ....: d1,_,_ = hyperbolicity(G, algorithm='basic') ....: d2,_,_ = hyperbolicity(G, algorithm='CCL') @@ -1202,7 +1202,7 @@ def hyperbolicity(G, sage: from sage.graphs.hyperbolicity import hyperbolicity sage: import random sage: random.seed() - sage: for i in range(10): # long time + sage: for i in range(10): # long time # needs networkx ....: n = random.randint(2, 20) ....: m = random.randint(0, n*(n-1) / 2) ....: G = graphs.RandomGNM(n, m) diff --git a/src/sage/graphs/independent_sets.pyx b/src/sage/graphs/independent_sets.pyx index 23c8677b34a..f1dc1260c34 100644 --- a/src/sage/graphs/independent_sets.pyx +++ b/src/sage/graphs/independent_sets.pyx @@ -141,12 +141,12 @@ cdef class IndependentSets: Compute the number of matchings, and check with Sage's implementation:: sage: from sage.graphs.independent_sets import IndependentSets - sage: from sage.graphs.matchpoly import matching_polynomial + sage: from sage.graphs.matchpoly import matching_polynomial # needs sage.libs.flint sage: def check_matching(G): ....: number_of_matchings = sum(map(abs, matching_polynomial(G).coefficients(sparse=False))) ....: if number_of_matchings != IndependentSets(G.line_graph()).cardinality(): ....: raise ValueError("something goes wrong") - sage: for i in range(30): + sage: for i in range(30): # needs sage.libs.flint ....: check_matching(graphs.RandomGNP(11, .3)) Compare the result with the output of :meth:`subgraph_search`:: diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index e90e51e0c87..a231927c4b4 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1922,7 +1922,7 @@ def SRG_100_44_18_20(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_100_44_18_20 - sage: G = SRG_100_44_18_20() # long time + sage: G = SRG_100_44_18_20() # long time # needs sage.groups sage: G.is_strongly_regular(parameters=True) # long time (100, 44, 18, 20) """ @@ -1944,7 +1944,7 @@ def SRG_100_45_20_20(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_100_45_20_20 - sage: G = SRG_100_45_20_20() # long time + sage: G = SRG_100_45_20_20() # long time # needs sage.groups sage: G.is_strongly_regular(parameters=True) # long time (100, 45, 20, 20) """ @@ -2616,7 +2616,7 @@ def SRG_630_85_20_10(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import SRG_630_85_20_10 - sage: G = SRG_630_85_20_10() # long time + sage: G = SRG_630_85_20_10() # long time # needs sage.groups sage: G.is_strongly_regular(parameters=True) # long time (630, 85, 20, 10) """ @@ -2812,7 +2812,7 @@ def strongly_regular_graph(int v, int k, int l, int mu=-1, bint existence=False, Petersen's graph from its set of parameters:: - sage: graphs.strongly_regular_graph(10,3,0,1,existence=True) + sage: graphs.strongly_regular_graph(10,3,0,1,existence=True) # needs sage.libs.pari True sage: graphs.strongly_regular_graph(10,3,0,1) complement(Johnson graph with parameters 5,2): Graph on 10 vertices @@ -3133,15 +3133,15 @@ def _build_small_srg_database(): complement(two-intersection set in PG(8,2)): Graph on 256 vertices sage: graphs.strongly_regular_graph(512, 73, 12, 10) # not tested (too long), needs sage.rings.finite_rings two-weight code: [219, 9] linear code over GF(2): Graph on 512 vertices - sage: graphs.strongly_regular_graph(512, 219, 106, 84) # long time + sage: graphs.strongly_regular_graph(512, 219, 106, 84) # long time, needs sage.combinat two-intersection set in PG(9,2): Graph on 512 vertices sage: graphs.strongly_regular_graph(512, 315, 202, 180) # not tested (too long), needs sage.rings.finite_rings two-weight code: [70, 9] linear code over GF(2): Graph on 512 vertices - sage: graphs.strongly_regular_graph(625, 364, 213, 210) # long time + sage: graphs.strongly_regular_graph(625, 364, 213, 210) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices - sage: graphs.strongly_regular_graph(625, 416, 279, 272) # long time + sage: graphs.strongly_regular_graph(625, 416, 279, 272) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices - sage: graphs.strongly_regular_graph(625, 468, 353, 342) # long time + sage: graphs.strongly_regular_graph(625, 468, 353, 342) # long time, needs sage.libs.pari complement(two-intersection set in PG(4,5)): Graph on 625 vertices sage: graphs.strongly_regular_graph(729, 336, 153,156) # not tested (too long) two-intersection set in PG(6,3): Graph on 729 vertices @@ -3286,7 +3286,7 @@ def _check_database(): EXAMPLES:: sage: from sage.graphs.strongly_regular_db import _check_database - sage: _check_database() # long time + sage: _check_database() # long time # needs sage.libs.pari Sage cannot build a (512 133 24 38 ) that exists. Comment ... ... In Andries Brouwer's database: diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index 5a7b048ddfe..64c53b1d6d9 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -562,7 +562,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: R = PolynomialRing(ZZ, 'x') sage: R((-1)^5*x*T(1-x,0)).factor() # needs sage.symbolic (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) - sage: G.chromatic_polynomial().factor() + sage: G.chromatic_polynomial().factor() # needs sage.libs.flint (x - 2) * (x - 1) * x * (x^3 - 9*x^2 + 29*x - 32) TESTS: From c33eee7dfb7c07696f861859f5935162116a8355 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 27 Aug 2023 13:39:40 -0700 Subject: [PATCH 104/225] sage.graphs: Update # needs --- src/sage/graphs/bipartite_graph.py | 4 ++-- src/sage/graphs/connectivity.pyx | 9 ++++++--- src/sage/graphs/convexity_properties.pyx | 8 ++++---- src/sage/graphs/domination.py | 4 ++-- src/sage/graphs/generators/basic.py | 15 +++++++++------ src/sage/graphs/generic_graph.py | 8 ++++---- src/sage/graphs/hypergraph_generators.py | 2 +- src/sage/graphs/tutte_polynomial.py | 2 +- 8 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index ee63977a071..84e66d0a1a1 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -1530,8 +1530,8 @@ def matching_polynomial(self, algorithm="Godsil", name=None): polynomial:: sage: g = graphs.RandomTree(20) - sage: p = g.characteristic_polynomial() - sage: p == BipartiteGraph(g).matching_polynomial(algorithm='rook') + sage: p = g.characteristic_polynomial() # needs sage.modules + sage: p == BipartiteGraph(g).matching_polynomial(algorithm='rook') # needs sage.modules True TESTS:: diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index a1f1815743a..cb58f4f91d8 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -1078,7 +1078,8 @@ def edge_connectivity(G, sage: for u,v in tree.edge_iterator(labels=None): ....: tree.set_edge_label(u, v, random()) sage: minimum = min(tree.edge_labels()) - sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, use_edge_labels=True) # needs sage.numerical.mip + sage: [_, [(_, _, l)]] = edge_connectivity(tree, value_only=False, # needs sage.numerical.mip + ....: use_edge_labels=True) sage: l == minimum # needs sage.numerical.mip True @@ -1102,12 +1103,14 @@ def edge_connectivity(G, We check that the result with Boost is the same as the result without Boost:: sage: g = graphs.RandomGNP(15, .3) - sage: edge_connectivity(g, implementation="boost") == edge_connectivity(g, implementation="sage") + sage: (edge_connectivity(g, implementation="boost") # needs sage.numerical.mip + ....: == edge_connectivity(g, implementation="sage")) True Boost interface also works with directed graphs:: - sage: edge_connectivity(digraphs.Circuit(10), implementation="boost", vertices=True) + sage: edge_connectivity(digraphs.Circuit(10), implementation="boost", + ....: vertices=True) [1, [(0, 1)], [{0}, {1, 2, 3, 4, 5, 6, 7, 8, 9}]] However, the Boost algorithm is not reliable if the input is directed diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index b2a96335d44..c422d0c3190 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -132,7 +132,7 @@ cdef class ConvexityProperties: sage: CP = ConvexityProperties(g) sage: CP.hull([1, 3]) [1, 2, 3] - sage: CP.hull_number() + sage: CP.hull_number() # needs sage.numerical.mip 3 TESTS:: @@ -410,10 +410,10 @@ cdef class ConvexityProperties: sage: from sage.graphs.convexity_properties import ConvexityProperties sage: g = graphs.PetersenGraph() sage: CP = ConvexityProperties(g) - sage: CP.hull_number() + sage: CP.hull_number() # needs sage.numerical.mip 3 - sage: generating_set = CP.hull_number(value_only=False) - sage: CP.hull(generating_set) + sage: generating_set = CP.hull_number(value_only=False) # needs sage.numerical.mip + sage: CP.hull(generating_set) # needs sage.numerical.mip [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """ cdef int i diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 37416d428a8..089d7706f36 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -383,8 +383,8 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, The method is robust to vertices with incomparable labels:: sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)]) - sage: L = list(G.dominating_sets()) - sage: len(L) + sage: L = list(G.dominating_sets()) # needs sage.numerical.mip + sage: len(L) # needs sage.numerical.mip 6 """ g._scream_if_not_simple(allow_multiple_edges=True, allow_loops=not total) diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 11083069adc..57cf2d2be6e 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -66,22 +66,25 @@ def BullGraph(): `x` is a variable, `A` the adjacency matrix of the graph, and `I` the identity matrix of the same dimensions as `A`:: + sage: # needs sage.libs.flint sage: chrompoly = g.chromatic_polynomial() # needs sage.libs.flint sage: x = chrompoly.parent()('x') # needs sage.libs.flint sage: x * (x - 2) * (x - 1)^3 == chrompoly # needs sage.libs.flint True - sage: charpoly = g.characteristic_polynomial() - sage: M = g.adjacency_matrix(); M + + sage: # needs sage.libs.flint sage.modules + sage: charpoly = g.characteristic_polynomial() # needs sage.modules + sage: M = g.adjacency_matrix(); M # needs sage.modules [0 1 1 0 0] [1 0 1 1 0] [1 1 0 0 1] [0 1 0 0 0] [0 0 1 0 0] - sage: Id = identity_matrix(ZZ, M.nrows()) - sage: D = x*Id - M # needs sage.libs.flint - sage: D.determinant() == charpoly # needs sage.libs.flint sage.symbolic + sage: Id = identity_matrix(ZZ, M.nrows()) # needs sage.modules + sage: D = x*Id - M # needs sage.libs.flint sage.modules + sage: D.determinant() == charpoly # needs sage.libs.flint sage.modules sage.symbolic True - sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly # needs sage.libs.flint + sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly # needs sage.libs.flint sage.modules True """ edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)] diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index bc03ec01252..a0757788160 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -16700,7 +16700,7 @@ def shortest_path(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] - sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx + sage: import networkx; algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx sage: all(G.shortest_path(1, 2, algorithm=alg) == [] ....: for alg in algs) True @@ -16890,7 +16890,7 @@ def shortest_path_length(self, u, v, by_weight=False, algorithm=None, sage: G = Graph() sage: G.add_vertices([1, 2]) sage: algs = ['BFS', 'BFS_Bid', 'Dijkstra_Bid', 'Bellman-Ford_Boost'] - sage: algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx + sage: import networkx; algs += ['Dijkstra_NetworkX', 'Dijkstra_Bid_NetworkX'] # needs networkx sage: all(G.shortest_path_length(1, 2, algorithm=alg) == Infinity ....: for alg in algs) True @@ -23259,7 +23259,7 @@ def automorphism_group(self, partition=None, verbosity=0, sage: G1 = Graph(':H`ECw@HGXGAGUG`e') sage: G = G1.automorphism_group() # needs sage.groups - sage: G.subgroups() + sage: G.subgroups() # needs sage.groups [Subgroup generated by [()] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)]), Subgroup generated by [(0,7)(1,4)(2,3)(6,8)] of (Permutation Group with generators [(0,7)(1,4)(2,3)(6,8)])] @@ -24042,7 +24042,7 @@ class by some canonization function `c`. If `G` and `H` are graphs, ....: [(0,1), (0,2), (1,2)], ....: [(0,1), (0,2), (0,3)]] sage: algos = ['sage'] - sage: algos.append('bliss') # optional - bliss + sage: import sage.graphs.bliss; algos.append('bliss') # optional - bliss sage: S = Set([0,1,2]) sage: for (algo, edges) in product(algos, edges_list): # needs sage.combinat ....: L = cartesian_product([S] * len(edges)) diff --git a/src/sage/graphs/hypergraph_generators.py b/src/sage/graphs/hypergraph_generators.py index 3d6a7d28cd6..4291e024001 100644 --- a/src/sage/graphs/hypergraph_generators.py +++ b/src/sage/graphs/hypergraph_generators.py @@ -257,7 +257,7 @@ def UniformRandomUniform(self, n, k, m): Traceback (most recent call last): ... ValueError: the uniformity should be non-negative - sage: hypergraphs.UniformRandomUniform(52, I, 17) + sage: hypergraphs.UniformRandomUniform(52, I, 17) # needs sage.symbolic Traceback (most recent call last): ... ValueError: the uniformity should be an integer diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index 64c53b1d6d9..e82150eeb9c 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -580,7 +580,7 @@ def tutte_polynomial(G, edge_selector=None, cache=None): sage: g.add_edges([(0,1,1),(1,5,2),(5,3,3),(5,2,4),(2,4,5),(0,2,6),(0,3,7),(0,4,8),(0,5,9)]) sage: g.tutte_polynomial()(1,1) 52 - sage: g.spanning_trees_count() + sage: g.spanning_trees_count() # needs sage.modules 52 """ R = ZZ['x, y'] From 6738f327be2656f40663448d04fa1384daf04b79 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 3 Sep 2023 16:36:13 -0700 Subject: [PATCH 105/225] sage.graphs: Update # needs --- src/sage/graphs/bipartite_graph.py | 1 + src/sage/graphs/domination.py | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index 84e66d0a1a1..e7863bf04e2 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -1536,6 +1536,7 @@ def matching_polynomial(self, algorithm="Godsil", name=None): TESTS:: + sage: # needs sage.modules sage: g = BipartiteGraph(matrix.ones(4, 3)) sage: g.matching_polynomial() # needs sage.libs.flint x^7 - 12*x^5 + 36*x^3 - 24*x diff --git a/src/sage/graphs/domination.py b/src/sage/graphs/domination.py index 089d7706f36..0dcab74e90c 100644 --- a/src/sage/graphs/domination.py +++ b/src/sage/graphs/domination.py @@ -344,7 +344,7 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, Minimum connected dominating sets of the Peterson graph:: sage: G = graphs.PetersenGraph() - sage: G.dominating_set(total=True, value_only=True) + sage: G.dominating_set(total=True, value_only=True) # needs sage.numerical.mip 4 sage: sorted(G.dominating_sets(k=1, connected=True)) [[0, 1, 2, 6], @@ -361,7 +361,8 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, Subgraph induced by the dominating set is connected:: sage: G = graphs.PetersenGraph() - sage: all(G.subgraph(vertices=dom).is_connected() for dom in G.dominating_set(k=1, connected=True)) + sage: all(G.subgraph(vertices=dom).is_connected() + ....: for dom in G.dominating_set(k=1, connected=True)) True Minimum distance-k connected dominating sets of the Tietze graph:: @@ -375,7 +376,7 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, TESTS:: sage: g = Graph([(0, 1)]) - sage: next(g.dominating_sets(k=-1)) # needs sage.numerical.mip + sage: next(g.dominating_sets(k=-1)) Traceback (most recent call last): ... ValueError: the domination distance must be a non-negative integer @@ -383,8 +384,8 @@ def dominating_sets(g, k=1, independent=False, total=False, connected=False, The method is robust to vertices with incomparable labels:: sage: G = Graph([(1, 'A'), ('A', 2), (2, 3), (3, 1)]) - sage: L = list(G.dominating_sets()) # needs sage.numerical.mip - sage: len(L) # needs sage.numerical.mip + sage: L = list(G.dominating_sets()) + sage: len(L) 6 """ g._scream_if_not_simple(allow_multiple_edges=True, allow_loops=not total) From b0108a29412cada098aff8cbd1731f7329b65b0c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 5 Sep 2023 17:09:07 -0700 Subject: [PATCH 106/225] sage.combinat.posets, sage.graphs: Update # needs --- src/sage/combinat/posets/hasse_cython_flint.pyx | 1 + src/sage/graphs/chrompoly.pyx | 1 + src/sage/graphs/matchpoly.pyx | 1 + 3 files changed, 3 insertions(+) diff --git a/src/sage/combinat/posets/hasse_cython_flint.pyx b/src/sage/combinat/posets/hasse_cython_flint.pyx index 0b33eed0b3f..fcbe29faaf6 100644 --- a/src/sage/combinat/posets/hasse_cython_flint.pyx +++ b/src/sage/combinat/posets/hasse_cython_flint.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs sage.modules r""" Some fast computations for finite posets using FLINT matrices """ diff --git a/src/sage/graphs/chrompoly.pyx b/src/sage/graphs/chrompoly.pyx index d0611a3df84..f596272219e 100644 --- a/src/sage/graphs/chrompoly.pyx +++ b/src/sage/graphs/chrompoly.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs """ Chromatic polynomial diff --git a/src/sage/graphs/matchpoly.pyx b/src/sage/graphs/matchpoly.pyx index 22361379291..10c8d524164 100644 --- a/src/sage/graphs/matchpoly.pyx +++ b/src/sage/graphs/matchpoly.pyx @@ -1,4 +1,5 @@ # cython: binding=True +# sage.doctest: needs sage.libs.flint sage.graphs """ Matching polynomial From 3807b6bce52c1c33183773ac30dcee192271b062 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 9 Sep 2023 16:00:36 -0700 Subject: [PATCH 107/225] sage.combinat.designs: Update # needs --- src/sage/combinat/designs/bibd.py | 4 +-- src/sage/combinat/designs/block_design.py | 35 +++++++++++-------- src/sage/combinat/designs/database.py | 10 +++--- .../designs/group_divisible_designs.py | 6 ++-- .../combinat/designs/incidence_structures.py | 30 ++++++++-------- .../combinat/designs/orthogonal_arrays.py | 2 +- .../orthogonal_arrays_build_recursive.py | 4 +-- .../orthogonal_arrays_find_recursive.pyx | 2 +- src/sage/combinat/designs/resolvable_bibd.py | 10 +++--- 9 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index ed44883be25..a8bbc879874 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -236,7 +236,7 @@ def balanced_incomplete_block_design(v, k, lambd=1, existence=False, use_LJCR=Fa (10,4,2)-Balanced Incomplete Block Design sage: designs.balanced_incomplete_block_design(50,25,24) # needs sage.schemes (50,25,24)-Balanced Incomplete Block Design - sage: designs.balanced_incomplete_block_design(29,15,15) # needs sage.libs.pari + sage: designs.balanced_incomplete_block_design(29,15,15) # needs sage.libs.pari sage.schemes (29,15,15)-Balanced Incomplete Block Design """ # Trivial BIBD @@ -1125,7 +1125,7 @@ def v_5_1_BIBD(v, check=True): sage: from sage.combinat.designs.bibd import v_5_1_BIBD sage: i = 0 - sage: while i<200: # needs sage.libs.pari + sage: while i<200: # needs sage.libs.pari sage.schemes ....: i += 20 ....: _ = v_5_1_BIBD(i+1) ....: _ = v_5_1_BIBD(i+5) diff --git a/src/sage/combinat/designs/block_design.py b/src/sage/combinat/designs/block_design.py index 69f73dc92a0..4b14b18073d 100644 --- a/src/sage/combinat/designs/block_design.py +++ b/src/sage/combinat/designs/block_design.py @@ -122,8 +122,8 @@ def are_hyperplanes_in_projective_geometry_parameters(v, k, lmbda, return_parame sage: are_hyperplanes_in_projective_geometry_parameters(40, 13, 4, ....: return_parameters=True) (True, (3, 3)) - sage: PG = designs.ProjectiveGeometryDesign(3, 2, GF(3)) - sage: PG.is_t_design(return_parameters=True) + sage: PG = designs.ProjectiveGeometryDesign(3, 2, GF(3)) # needs sage.combinat + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 40, 13, 4)) sage: are_hyperplanes_in_projective_geometry_parameters(15, 3, 1) @@ -217,13 +217,13 @@ def ProjectiveGeometryDesign(n, d, F, algorithm=None, point_coordinates=True, ch The set of `d`-dimensional subspaces in a `n`-dimensional projective space forms `2`-designs (or balanced incomplete block designs):: - sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)); PG + sage: PG = designs.ProjectiveGeometryDesign(4, 2, GF(2)); PG # needs sage.combinat Incidence structure with 31 points and 155 blocks - sage: PG.is_t_design(return_parameters=True) + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 31, 7, 7)) - sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) - sage: PG.is_t_design(return_parameters=True) + sage: PG = designs.ProjectiveGeometryDesign(3, 1, GF(4)) # needs sage.combinat + sage: PG.is_t_design(return_parameters=True) # needs sage.combinat (True, (2, 85, 5, 1)) Check with ``F`` being a prime power:: @@ -707,6 +707,7 @@ def projective_plane(n, check=True, existence=False): EXAMPLES:: + sage: # needs sage.schemes sage: designs.projective_plane(2) (7,3,1)-Balanced Incomplete Block Design sage: designs.projective_plane(3) @@ -737,6 +738,7 @@ def projective_plane(n, check=True, existence=False): TESTS:: + sage: # needs sage.schemes sage: designs.projective_plane(2197, existence=True) True sage: designs.projective_plane(6, existence=True) @@ -816,6 +818,7 @@ def AffineGeometryDesign(n, d, F, point_coordinates=True, check=True): EXAMPLES:: + sage: # needs sage.combinat sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) sage: BD.is_t_design(return_parameters=True) (True, (2, 8, 2, 1)) @@ -958,16 +961,18 @@ def HadamardDesign(n): EXAMPLES:: - sage: designs.HadamardDesign(7) # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: designs.HadamardDesign(7) Incidence structure with 7 points and 7 blocks - sage: print(designs.HadamardDesign(7)) # needs sage.modules + sage: print(designs.HadamardDesign(7)) Incidence structure with 7 points and 7 blocks For example, the Hadamard 2-design with `n = 11` is a design whose parameters are `2-(11, 5, 2)`. We verify that `NJ = 5J` for this design. :: - sage: D = designs.HadamardDesign(11); N = D.incidence_matrix() # needs sage.modules - sage: J = matrix(ZZ, 11, 11, [1]*11*11); N*J # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: D = designs.HadamardDesign(11); N = D.incidence_matrix() + sage: J = matrix(ZZ, 11, 11, [1]*11*11); N*J [5 5 5 5 5 5 5 5 5 5 5] [5 5 5 5 5 5 5 5 5 5 5] [5 5 5 5 5 5 5 5 5 5 5] @@ -1011,7 +1016,8 @@ def Hadamard3Design(n): EXAMPLES:: - sage: designs.Hadamard3Design(12) # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: designs.Hadamard3Design(12) Incidence structure with 12 points and 22 blocks We verify that any two blocks of the Hadamard `3`-design `3-(8, 4, 1)` @@ -1021,9 +1027,10 @@ def Hadamard3Design(n): :: - sage: D = designs.Hadamard3Design(8) # needs sage.modules - sage: N = D.incidence_matrix() # needs sage.modules - sage: N.transpose()*N # needs sage.modules + sage: # needs sage.combinat sage.modules + sage: D = designs.Hadamard3Design(8) + sage: N = D.incidence_matrix() + sage: N.transpose()*N [4 2 2 2 2 2 2 2 2 2 2 2 2 0] [2 4 2 2 2 2 2 2 2 2 2 2 0 2] [2 2 4 2 2 2 2 2 2 2 2 0 2 2] diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 5302771756c..de5ce4cf815 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -1466,8 +1466,8 @@ def OA_17_560(): sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array sage: from sage.combinat.designs.database import OA_17_560 - sage: OA = OA_17_560() # needs sage.rings.finite_rings - sage: is_orthogonal_array(OA,17,560,2) # needs sage.rings.finite_rings + sage: OA = OA_17_560() # needs sage.rings.finite_rings sage.schemes + sage: is_orthogonal_array(OA,17,560,2) # needs sage.rings.finite_rings sage.schemes True The design is available from the general constructor:: @@ -3845,13 +3845,13 @@ def DM_57_8_1(): sage: from sage.combinat.designs.designs_pyx import is_difference_matrix sage: from sage.combinat.designs.database import DM_57_8_1 - sage: G,M = DM_57_8_1() # needs sage.rings.finite_rings - sage: is_difference_matrix(M,G,8,1) # needs sage.rings.finite_rings + sage: G,M = DM_57_8_1() # needs sage.rings.finite_rings sage.schemes + sage: is_difference_matrix(M,G,8,1) # needs sage.rings.finite_rings sage.schemes True Can be obtained from the constructor:: - sage: _ = designs.difference_matrix(57,8) # needs sage.rings.finite_rings + sage: _ = designs.difference_matrix(57,8) # needs sage.rings.finite_rings sage.schemes """ M = orthogonal_array(8,8) M = [R for R in M if any(x!=R[0] for x in R)] # removing the 0..0, 1..1, 7..7 rows. diff --git a/src/sage/combinat/designs/group_divisible_designs.py b/src/sage/combinat/designs/group_divisible_designs.py index 0bc9c38ef00..a56d11549a6 100644 --- a/src/sage/combinat/designs/group_divisible_designs.py +++ b/src/sage/combinat/designs/group_divisible_designs.py @@ -257,6 +257,7 @@ class GroupDivisibleDesign(IncidenceStructure): With unspecified groups:: + sage: # needs sage.schemes sage: D = designs.transversal_design(4,3).relabel(list('abcdefghiklm'),inplace=False).blocks() sage: GDD = GroupDivisibleDesign('abcdefghiklm',None,D) sage: sorted(GDD.groups()) @@ -321,8 +322,9 @@ def groups(self): Non-integer ground set:: - sage: TD=designs.transversal_design(5,5) - sage: TD.relabel({i:chr(97+i) for i in range(25)}) + sage: # needs sage.schemes + sage: TD = designs.transversal_design(5,5) + sage: TD.relabel({i: chr(97+i) for i in range(25)}) sage: TD.groups() [['a', 'b', 'c', 'd', 'e'], ['f', 'g', 'h', 'i', 'j'], diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index 5252b3be769..ece83194ca2 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -357,18 +357,18 @@ def __contains__(self, block): sage: str="I had a dream of a time when a 3-lines patch does not kill one hour" sage: sets = Subsets(str.split(), 4) - sage: IS = IncidenceStructure(sets) # a complete 4-uniform hypergraph + sage: IS = IncidenceStructure(sets) # a complete 4-uniform hypergraph sage: ["I", "dream", "of", "one"] in IS True sage: ["does", "patch", "kill", "dream"] in IS True sage: ["Am", "I", "finally", "done ?"] in IS False - sage: IS = designs.ProjectiveGeometryDesign(3, 1, GF(2), # needs sage.rings.finite_rings + sage: IS = designs.ProjectiveGeometryDesign(3, 1, GF(2), # needs sage.combinat ....: point_coordinates=False) - sage: [3,8,7] in IS # needs sage.rings.finite_rings + sage: [3,8,7] in IS # needs sage.combinat True - sage: [3,8,9] in IS + sage: [3,8,9] in IS # needs sage.combinat False """ try: @@ -1513,10 +1513,10 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): sage: BD.is_t_design(0,6,3,7) or BD.is_t_design(0,7,4,7) or BD.is_t_design(0,7,3,8) False - sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) # needs sage.rings.finite_rings - sage: BD.is_t_design(1) + sage: BD = designs.AffineGeometryDesign(3, 1, GF(2)) # needs sage.combinat + sage: BD.is_t_design(1) # needs sage.combinat True - sage: BD.is_t_design(2) + sage: BD.is_t_design(2) # needs sage.combinat True Steiner triple and quadruple systems are other names for `2-(v,3,1)` and @@ -1924,8 +1924,8 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, sage: TD.is_resolvable() True - sage: AG = designs.AffineGeometryDesign(3,1,GF(2)) # needs sage.rings.finite_rings - sage: AG.is_resolvable() # needs sage.rings.finite_rings + sage: AG = designs.AffineGeometryDesign(3,1,GF(2)) # needs sage.combinat + sage: AG.is_resolvable() # needs sage.combinat True Their classes:: @@ -1936,10 +1936,11 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, sage: cls # random [[[0, 3], [1, 2]], [[1, 3], [0, 2]]] - sage: b, cls = AG.is_resolvable(True) # needs sage.rings.finite_rings + sage: # needs sage.combinat + sage: b, cls = AG.is_resolvable(True) sage: b True - sage: cls # random + sage: cls # random [[[6, 7], [4, 5], [0, 1], [2, 3]], [[5, 7], [0, 4], [3, 6], [1, 2]], [[0, 2], [4, 7], [1, 3], [5, 6]], @@ -1958,9 +1959,10 @@ def is_resolvable(self, certificate=False, solver=None, verbose=0, check=True, TESTS:: - sage: _, cls1 = AG.is_resolvable(certificate=True) # needs sage.rings.finite_rings - sage: _, cls2 = AG.is_resolvable(certificate=True) # needs sage.rings.finite_rings - sage: cls1 is cls2 # needs sage.rings.finite_rings + sage: # needs sage.combinat + sage: _, cls1 = AG.is_resolvable(certificate=True) + sage: _, cls2 = AG.is_resolvable(certificate=True) + sage: cls1 is cls2 False """ if self._classes is None: diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index b37cf2be2b3..f6160258169 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings sage.schemes r""" Orthogonal arrays (OA) diff --git a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py index c30041a9c9b..39842c4959c 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py +++ b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py @@ -64,8 +64,8 @@ def construction_3_3(k,n,m,i,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_3 sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_3 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array - sage: k=11;n=177 - sage: is_orthogonal_array(construction_3_3(*find_construction_3_3(k,n)[1]),k,n,2) + sage: k = 11; n = 177 + sage: is_orthogonal_array(construction_3_3(*find_construction_3_3(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(9,91)) diff --git a/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx b/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx index 1843cbe00e8..066eecb9197 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +++ b/src/sage/combinat/designs/orthogonal_arrays_find_recursive.pyx @@ -1,4 +1,4 @@ -# sage.doctest: needs sage.rings.finite_rings +# sage.doctest: needs sage.rings.finite_rings sage.schemes # cython: cdivision=True r""" Orthogonal arrays (find recursive constructions) diff --git a/src/sage/combinat/designs/resolvable_bibd.py b/src/sage/combinat/designs/resolvable_bibd.py index ed098ce746c..05a1859bee8 100644 --- a/src/sage/combinat/designs/resolvable_bibd.py +++ b/src/sage/combinat/designs/resolvable_bibd.py @@ -180,7 +180,7 @@ def kirkman_triple_system(v,existence=False): TESTS:: - sage: for i in range(3,300,6): + sage: for i in range(3,300,6): # needs sage.combinat ....: _ = designs.kirkman_triple_system(i) """ if v%6 != 3: @@ -458,7 +458,7 @@ def PBD_4_7(v,check=True, existence=False): All values `\leq 300`:: - sage: for i in range(1,300,3): + sage: for i in range(1,300,3): # needs sage.schemes ....: if i not in [10,19,31]: ....: assert PBD_4_7(i,existence=True) is True ....: _ = PBD_4_7(i,check=True) @@ -711,16 +711,16 @@ def PBD_4_7_from_Y(gdd,check=True): EXAMPLES:: sage: from sage.combinat.designs.resolvable_bibd import PBD_4_7_from_Y - sage: PBD_4_7_from_Y(designs.transversal_design(7,8)) + sage: PBD_4_7_from_Y(designs.transversal_design(7,8)) # needs sage.schemes Pairwise Balanced Design on 169 points with sets of sizes in [4, 7] TESTS:: - sage: PBD_4_7_from_Y(designs.balanced_incomplete_block_design(10,10)) + sage: PBD_4_7_from_Y(designs.balanced_incomplete_block_design(10,10)) # needs sage.schemes Traceback (most recent call last): ... ValueError: The GDD should only contain blocks of size {4,5,7} but there are other: [10] - sage: PBD_4_7_from_Y(designs.transversal_design(4,3)) + sage: PBD_4_7_from_Y(designs.transversal_design(4,3)) # needs sage.schemes Traceback (most recent call last): ... RuntimeError: A group has size 3 but I do not know how to build a (10,[4,7])-PBD From faa0f533fb0a6416400eaa259123f6efa0fda1dc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 9 Sep 2023 16:01:41 -0700 Subject: [PATCH 108/225] sage.graphs: Update # needs --- src/sage/graphs/bipartite_graph.py | 2 +- .../graphs/generators/classical_geometries.py | 24 ++++++++++--------- src/sage/graphs/generators/families.py | 8 +++---- src/sage/graphs/generators/smallgraphs.py | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index e7863bf04e2..19746f1710c 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -2303,7 +2303,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, The two algorithms should return the same result:: - sage: # needs numpy + sage: # needs networkx numpy sage: g = BipartiteGraph(graphs.RandomBipartite(10, 10, .5)) sage: vc1 = g.vertex_cover(algorithm="Konig") sage: vc2 = g.vertex_cover(algorithm="Cliquer") diff --git a/src/sage/graphs/generators/classical_geometries.py b/src/sage/graphs/generators/classical_geometries.py index bf1aa04e933..1bfe55f0f54 100644 --- a/src/sage/graphs/generators/classical_geometries.py +++ b/src/sage/graphs/generators/classical_geometries.py @@ -1045,7 +1045,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, using the built-in construction:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: g = graphs.T2starGeneralizedQuadrangleGraph(4); g T2*(O,4); GQ(3, 5): Graph on 64 vertices sage: g.is_strongly_regular(parameters=True) @@ -1057,7 +1057,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, supplying your own hyperoval:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') sage: O = [vector(F,(0,0,0,1)),vector(F,(0,0,1,0))] + [vector(F, (0,1,x^2,x)) ....: for x in F] @@ -1068,7 +1068,7 @@ def T2starGeneralizedQuadrangleGraph(q, dual=False, hyperoval=None, field=None, TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') # repeating a point... sage: O = [vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] sage: graphs.T2starGeneralizedQuadrangleGraph(4, hyperoval=O, field=F) @@ -1168,21 +1168,23 @@ def HaemersGraph(q, hyperoval=None, hyperoval_matching=None, field=None, check_h using the built-in constructions:: - sage: g = graphs.HaemersGraph(4); g # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4); g Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (96, 19, 2, 4) supplying your own hyperoval_matching:: - sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings + sage: g = graphs.HaemersGraph(4, hyperoval_matching=((0,5),(1,4),(2,3))); g Haemers(4): Graph on 96 vertices - sage: g.is_strongly_regular(parameters=True) # needs sage.rings.finite_rings + sage: g.is_strongly_regular(parameters=True) (96, 19, 2, 4) TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(4,'b') # repeating a point... sage: O = [vector(F,(0,1,0,0)),vector(F,(0,0,1,0))]+[vector(F, (0,1,x^2,x)) for x in F] sage: graphs.HaemersGraph(4, hyperoval=O, field=F) @@ -1392,7 +1394,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov using the built-in construction:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: g = graphs.Nowhere0WordsTwoWeightCodeGraph(8); g Nowhere0WordsTwoWeightCodeGraph(8): Graph on 196 vertices sage: g.is_strongly_regular(parameters=True) @@ -1403,7 +1405,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov supplying your own hyperoval:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(8) sage: O = [vector(F,(0,0,1)),vector(F,(0,1,0))] + [vector(F, (1,x^2,x)) ....: for x in F] @@ -1414,7 +1416,7 @@ def Nowhere0WordsTwoWeightCodeGraph(q, hyperoval=None, field=None, check_hyperov TESTS:: - sage: # needs sage.rings.finite_rings + sage: # needs sage.combinat sage.rings.finite_rings sage: F = GF(8) # repeating a point... sage: O = [vector(F,(1,0,0)),vector(F,(0,1,0))]+[vector(F, (1,x^2,x)) for x in F] sage: graphs.Nowhere0WordsTwoWeightCodeGraph(8,hyperoval=O,field=F) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index ecc626f2451..f7d6f28cf4b 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -4147,12 +4147,12 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): EXAMPLES:: - sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) # needs sage.modules sage.rings.finite_rings + sage: # needs sage.combinat sage.modules sage.rings.finite_rings + sage: graphs.MuzychukS6Graph(3, 3).is_strongly_regular(parameters=True) (378, 116, 34, 36) - sage: phi = {(2,(0,2)):0, (1,(1,3)):1, (0,(0,3)):1, (2,(1,2)):1, # needs sage.modules + sage: phi = {(2,(0,2)):0, (1,(1,3)):1, (0,(0,3)):1, (2,(1,2)):1, ....: (1,(1,2)):0, (0,(0,2)):0, (3,(0,3)):0, (3,(1,3)):1} - sage: graphs.MuzychukS6Graph(2, 2, # needs sage.modules sage.rings.finite_rings - ....: Phi=phi).is_strongly_regular(parameters=True) + sage: graphs.MuzychukS6Graph(2, 2, Phi=phi).is_strongly_regular(parameters=True) (16, 5, 0, 2) TESTS:: diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index b5092e16ca9..c113dcdf6be 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -1424,7 +1424,7 @@ def BuckyBall(): The Bucky Ball can also be created by extracting the 1-skeleton of the Bucky Ball polyhedron, but this is much slower:: - sage: # needs sage.geometry.polyhedron sage.rings.number_field + sage: # needs sage.geometry.polyhedron sage.groups sage.rings.number_field sage: g = polytopes.buckyball().vertex_graph() sage: g.remove_loops() sage: h = graphs.BuckyBall() From 3a0fc5257f11205aa550268005ff09c5a7bf46d4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 9 Sep 2023 16:52:48 -0700 Subject: [PATCH 109/225] sage.combinat: Update # needs --- src/sage/combinat/posets/lattices.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 45f5715f0e7..8fb9055afdb 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -2293,9 +2293,9 @@ def is_orthocomplemented(self, unique=False): False sage: D6 = posets.DiamondPoset(6) - sage: D6.is_orthocomplemented() + sage: D6.is_orthocomplemented() # needs sage.groups True - sage: D6.is_orthocomplemented(unique=True) + sage: D6.is_orthocomplemented(unique=True) # needs sage.groups False sage: hexagon = LatticePoset({0:[1, 2], 1:[3], 2:[4], 3:[5], 4:[5]}) @@ -2453,8 +2453,8 @@ def is_geometric(self): Canonical example is the lattice of partitions of finite set ordered by refinement:: - sage: L = posets.SetPartitions(4) - sage: L.is_geometric() + sage: L = posets.SetPartitions(4) # needs sage.combinat + sage: L.is_geometric() # needs sage.combinat True Smallest example of geometric lattice that is not modular:: @@ -2754,8 +2754,8 @@ def is_upper_semimodular(self, certificate=False): sage: L.is_upper_semimodular() False - sage: L = LatticePoset(posets.IntegerPartitions(4)) - sage: L.is_upper_semimodular() + sage: L = LatticePoset(posets.IntegerPartitions(4)) # needs sage.combinat + sage: L.is_upper_semimodular() # needs sage.combinat True sage: L = LatticePoset({1:[2, 3, 4], 2: [5], 3:[5, 6], 4:[6], 5:[7], 6:[7]}) @@ -4021,21 +4021,21 @@ def is_subdirectly_reducible(self, certificate=False): EXAMPLES:: sage: N5 = posets.PentagonPoset() - sage: N5.is_subdirectly_reducible() + sage: N5.is_subdirectly_reducible() # needs sage.combinat False sage: hex = LatticePoset({1: [2, 3], 2: [4], 3: [5], 4: [6], 5: [6]}) - sage: hex.is_subdirectly_reducible() + sage: hex.is_subdirectly_reducible() # needs sage.combinat True - sage: hex.is_subdirectly_reducible(certificate=True) + sage: hex.is_subdirectly_reducible(certificate=True) # needs sage.combinat (True, (Finite lattice containing 5 elements, Finite lattice containing 5 elements)) - sage: N5.is_subdirectly_reducible(certificate=True) + sage: N5.is_subdirectly_reducible(certificate=True) # needs sage.combinat (False, (2, 3)) - sage: res, cert = hex.is_subdirectly_reducible(certificate=True) - sage: cert[0].is_isomorphic(N5) + sage: res, cert = hex.is_subdirectly_reducible(certificate=True) # needs sage.combinat + sage: cert[0].is_isomorphic(N5) # needs sage.combinat True .. SEEALSO:: @@ -4241,7 +4241,7 @@ def is_constructible_by_doublings(self, type) -> bool: sage: posets.PentagonPoset().is_constructible_by_doublings('interval') True - sage: posets.DiamondPoset(5).is_constructible_by_doublings('any') + sage: posets.DiamondPoset(5).is_constructible_by_doublings('any') # needs sage.combinat False After doubling both upper and lower pseudo-interval a lattice is @@ -5006,7 +5006,7 @@ def feichtner_yuzvinsky_ring(self, G, use_defining=False, base_ring=None): sage: Arr = H(a-b, b-c, c-d, d-a) sage: P = LatticePoset(Arr.intersection_poset()) sage: FY = P.feichtner_yuzvinsky_ring([P.top(),5,1,2,3,4]) - sage: FY.defining_ideal().groebner_basis() + sage: FY.defining_ideal().groebner_basis() # needs sage.libs.singular [h0^2 - h0*h1, h1^2, h2, h3, h4, h5] TESTS:: From 8c58146ddf47faa3cace024200b76020546e883d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Sep 2023 13:28:00 -0700 Subject: [PATCH 110/225] sage.combinat: Update # needs --- .../orthogonal_arrays_build_recursive.py | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py index 39842c4959c..fa0da27b293 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py +++ b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py @@ -134,8 +134,8 @@ def construction_3_4(k,n,m,r,s,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_find_recursive import find_construction_3_4 sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_4 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array - sage: k=8;n=196 - sage: is_orthogonal_array(construction_3_4(*find_construction_3_4(k,n)[1]),k,n,2) + sage: k = 8; n = 196 + sage: is_orthogonal_array(construction_3_4(*find_construction_3_4(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(8,164)) @@ -210,7 +210,7 @@ def construction_3_5(k,n,m,r,s,t,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_5 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array sage: k=8;n=111 - sage: is_orthogonal_array(construction_3_5(*find_construction_3_5(k,n)[1]),k,n,2) + sage: is_orthogonal_array(construction_3_5(*find_construction_3_5(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(8,90)) @@ -302,7 +302,7 @@ def construction_3_6(k,n,m,i,explain_construction=False): sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_3_6 sage: from sage.combinat.designs.orthogonal_arrays import is_orthogonal_array sage: k=8;n=95 - sage: is_orthogonal_array(construction_3_6(*find_construction_3_6(k,n)[1]),k,n,2) + sage: is_orthogonal_array(construction_3_6(*find_construction_3_6(k,n)[1]),k,n,2) # needs sage.schemes True sage: print(designs.orthogonal_arrays.explain_construction(10,756)) @@ -497,7 +497,7 @@ def construction_q_x(k, q, x, check=True, explain_construction=False): EXAMPLES:: sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import construction_q_x - sage: _ = construction_q_x(9,16,6) + sage: _ = construction_q_x(9,16,6) # needs sage.schemes sage: print(designs.orthogonal_arrays.explain_construction(9,158)) (q-x)-construction with q=16,x=6 from: @@ -650,11 +650,11 @@ def thwart_lemma_3_5(k,n,m,a,b,c,d=0,complement=False,explain_construction=False sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import thwart_lemma_3_5 sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array - sage: OA = thwart_lemma_3_5(6,23,7,5,7,8) - sage: is_orthogonal_array(OA,6,23*7+5+7+8,2) + sage: OA = thwart_lemma_3_5(6,23,7,5,7,8) # needs sage.schemes + sage: is_orthogonal_array(OA,6,23*7+5+7+8,2) # needs sage.schemes True - sage: print(designs.orthogonal_arrays.explain_construction(10,408)) + sage: print(designs.orthogonal_arrays.explain_construction(10,408)) # needs sage.schemes Lemma 4.1 with n=13,m=28 from: Charles J.Colbourn, Jeffrey H. Dinitz, Mieczyslaw Wojtas, Thwarts in transversal designs, @@ -784,7 +784,7 @@ def thwart_lemma_4_1(k,n,m,explain_construction=False): EXAMPLES:: - sage: print(designs.orthogonal_arrays.explain_construction(10,408)) + sage: print(designs.orthogonal_arrays.explain_construction(10,408)) # needs sage.schemes Lemma 4.1 with n=13,m=28 from: Charles J.Colbourn, Jeffrey H. Dinitz, Mieczyslaw Wojtas, Thwarts in transversal designs, @@ -960,25 +960,21 @@ def three_factor_product(k,n1,n2,n3,check=False,explain_construction=False): EXAMPLES:: + sage: # needs sage.schemes sage: from sage.combinat.designs.designs_pyx import is_orthogonal_array sage: from sage.combinat.designs.orthogonal_arrays_build_recursive import three_factor_product - sage: OA = three_factor_product(4,4,4,4) sage: is_orthogonal_array(OA,5,64) True - sage: OA = three_factor_product(4,3,4,5) sage: is_orthogonal_array(OA,5,60) True - sage: OA = three_factor_product(5,4,5,7) sage: is_orthogonal_array(OA,6,140) True - sage: OA = three_factor_product(9,8,9,9) # long time sage: is_orthogonal_array(OA,10,8*9*9) # long time True - sage: print(designs.orthogonal_arrays.explain_construction(10,648)) Three-factor product with n=8.9.9 from: Peter J. Dukes, Alan C.H. Ling, From 7775dd25c637958cd2f7983c51232df4d8200335 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 12 Sep 2023 13:28:18 -0700 Subject: [PATCH 111/225] sage.sandpiles: Update # needs --- src/sage/sandpiles/sandpile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index e6cba3195ca..979623da65a 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -2429,7 +2429,7 @@ def betti_complexes(self): sage: p[0] [{0: -8, 1: 5, 2: 4, 3: 1}, Simplicial complex with vertex set (1, 2, 3) and facets {(3,), (1, 2)}] - sage: S.resolution() + sage: S.resolution() # needs sage.libs.singular 'R^1 <-- R^5 <-- R^5 <-- R^1' sage: S.betti() # needs sage.libs.singular 0 1 2 3 From d9ad096684d2fa65d35f950a5ff08cfb94c23806 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 15 Sep 2023 22:16:07 -0700 Subject: [PATCH 112/225] Fixups --- src/sage/combinat/designs/block_design.py | 2 +- src/sage/graphs/generators/basic.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/designs/block_design.py b/src/sage/combinat/designs/block_design.py index 4b14b18073d..2a3bf142edd 100644 --- a/src/sage/combinat/designs/block_design.py +++ b/src/sage/combinat/designs/block_design.py @@ -937,7 +937,7 @@ def WittDesign(n): EXAMPLES:: - sage: # optional - gap_packages (design package) + sage: # optional - gap_package_design sage: BD = designs.WittDesign(9) sage: BD.is_t_design(return_parameters=True) (True, (2, 9, 3, 1)) diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index 57cf2d2be6e..5dfe78f01a8 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -67,24 +67,24 @@ def BullGraph(): the identity matrix of the same dimensions as `A`:: sage: # needs sage.libs.flint - sage: chrompoly = g.chromatic_polynomial() # needs sage.libs.flint - sage: x = chrompoly.parent()('x') # needs sage.libs.flint - sage: x * (x - 2) * (x - 1)^3 == chrompoly # needs sage.libs.flint + sage: chrompoly = g.chromatic_polynomial() + sage: x = chrompoly.parent()('x') + sage: x * (x - 2) * (x - 1)^3 == chrompoly True sage: # needs sage.libs.flint sage.modules - sage: charpoly = g.characteristic_polynomial() # needs sage.modules - sage: M = g.adjacency_matrix(); M # needs sage.modules + sage: charpoly = g.characteristic_polynomial() + sage: M = g.adjacency_matrix(); M [0 1 1 0 0] [1 0 1 1 0] [1 1 0 0 1] [0 1 0 0 0] [0 0 1 0 0] - sage: Id = identity_matrix(ZZ, M.nrows()) # needs sage.modules - sage: D = x*Id - M # needs sage.libs.flint sage.modules - sage: D.determinant() == charpoly # needs sage.libs.flint sage.modules sage.symbolic + sage: Id = identity_matrix(ZZ, M.nrows()) + sage: D = x*Id - M + sage: D.determinant() == charpoly # needs sage.symbolic True - sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly # needs sage.libs.flint sage.modules + sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly True """ edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)] From ef15f9c71c30f3528545406237189f73732a4cb0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 21:15:39 -0700 Subject: [PATCH 113/225] sage.graphs: Update # needs --- src/sage/graphs/generators/families.py | 2 +- src/sage/graphs/generic_graph.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index f7d6f28cf4b..c03edd90945 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -3938,7 +3938,7 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): [-4 -3 -2 2 3 4 -1 0 1] [-2 -4 -3 4 2 3 1 -1 0] - sage: # needs sage.modules sage.rings.finite_rings sage.groups sage.libs.gap + sage: # needs sage.groups sage.libs.gap sage.modules sage.rings.finite_rings sage: G.relabel(range(9)) sage: G3x3 = graphs.MathonPseudocyclicStronglyRegularGraph(2, G=G, L=L) sage: G3x3.is_strongly_regular(parameters=True) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index a0757788160..55145e38321 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -4827,7 +4827,7 @@ def min_spanning_tree(self, [(0, 2, 10), (1, 2, 1)] sage: Graph(g.min_spanning_tree(algorithm='Prim_Boost', weight_function=weight)).edges(sort=True) [(0, 2, 10), (1, 2, 1)] - sage: Graph(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)).edges(sort=True) # needs networkx + sage: Graph(g.min_spanning_tree(algorithm='NetworkX', weight_function=weight)).edges(sort=True) # needs networkx [(0, 2, 10), (1, 2, 1)] If the graph is directed, it is transformed into an undirected graph:: @@ -20948,7 +20948,7 @@ def plot(self, **options): The following illustrates the format of a position dictionary:: - sage: G.get_pos() # currently random across platforms, see #9593 # needs sage.plot + sage: G.get_pos() # currently random across platforms, see #9593 # needs sage.plot {0: [1.17..., -0.855...], 1: [1.81..., -0.0990...], 2: [1.35..., 0.184...], From 3485e3e2007b5d84ca078bb1a0c0804505dfaa7b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 21:16:29 -0700 Subject: [PATCH 114/225] build/pkgs/numpy: Update to 1.26.0 --- build/pkgs/numpy/checksums.ini | 6 +++--- build/pkgs/numpy/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/numpy/checksums.ini b/build/pkgs/numpy/checksums.ini index b71fbb37b7e..886bc13768b 100644 --- a/build/pkgs/numpy/checksums.ini +++ b/build/pkgs/numpy/checksums.ini @@ -1,5 +1,5 @@ tarball=numpy-VERSION.tar.gz -sha1=514f9201d6c3ba0f7e88400e72bb3fb179aa31fc -md5=23bf7c39807a9cce5c8ea0ba293b7dd9 -cksum=3121934199 +sha1=a3f9d79d7852f5d35ff35693fc31d17ea270d2d0 +md5=69bd28f07afbeed2bb6ecd467afcd469 +cksum=3599108965 upstream_url=https://pypi.io/packages/source/n/numpy/numpy-VERSION.tar.gz diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index 0635ee2cc52..5ff8c4f5d2a 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.26.0rc1 +1.26.0 From f5e55f4c582a319861eebc5dbd166222d3e82737 Mon Sep 17 00:00:00 2001 From: dcoudert Date: Sun, 17 Sep 2023 11:56:20 +0200 Subject: [PATCH 115/225] PR #36277: changes suggested by the reviewer --- src/sage/graphs/digraph.py | 29 +++++++++++++++-------------- src/sage/graphs/graph.py | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/sage/graphs/digraph.py b/src/sage/graphs/digraph.py index aca8e530c6d..c57224eba22 100644 --- a/src/sage/graphs/digraph.py +++ b/src/sage/graphs/digraph.py @@ -1717,28 +1717,29 @@ def feedback_edge_set(self, constraint_generation=True, value_only=False, ###################################### # Ordering-based MILP Implementation # ###################################### - p = MixedIntegerLinearProgram(maximization=False, solver=solver) + else: + p = MixedIntegerLinearProgram(maximization=False, solver=solver) - b = p.new_variable(binary=True) - d = p.new_variable(integer=True, nonnegative=True) + b = p.new_variable(binary=True) + d = p.new_variable(integer=True, nonnegative=True) - n = self.order() + n = self.order() - for u, v in self.edge_iterator(labels=None): - p.add_constraint(d[u] - d[v] + n * b[u, v], min=1) + for u, v in self.edge_iterator(labels=None): + p.add_constraint(d[u] - d[v] + n * b[u, v], min=1) - for v in self: - p.add_constraint(d[v] <= n) + for v in self: + p.add_constraint(d[v] <= n) - p.set_objective(p.sum(b[e] for e in self.edge_iterator(labels=False))) + p.set_objective(p.sum(b[e] for e in self.edge_iterator(labels=False))) - p.solve(log=verbose) + p.solve(log=verbose) - b_sol = p.get_values(b, convert=bool, tolerance=integrality_tolerance) + b_sol = p.get_values(b, convert=bool, tolerance=integrality_tolerance) - if value_only: - return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e]) - return [e for e in self.edge_iterator(labels=False) if b_sol[e]] + if value_only: + return sum(1 for e in self.edge_iterator(labels=False) if b_sol[e]) + return [e for e in self.edge_iterator(labels=False) if b_sol[e]] # Construction diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index f4485c2d47f..99802f0a36c 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -2065,7 +2065,7 @@ def apex_vertices(self, k=None): if not P: # The graph is planar it = self.vertex_iterator() return [next(it) for _ in range(k)] - elif len(P) > 1: + if len(P) > 1: return [] # We proceed with the non planar component From d973daffa26f7748bb83ebd4679f11ed9bdfc0c3 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Wed, 6 Sep 2023 20:32:15 +0200 Subject: [PATCH 116/225] =?UTF-8?q?add=20R=C3=A9my=20Oudompheng's=20implem?= =?UTF-8?q?entation=20of=20the=20BMSS=20algorithm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Oudompheng --- src/doc/en/reference/references/index.rst | 5 +- .../elliptic_curves/ell_curve_isogeny.py | 89 +++++++++++++++++-- 2 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index e09f339513f..bccb3dc9022 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1046,9 +1046,10 @@ REFERENCES: equations: I. Fibonacci and Lucas perfect powers." Annals of Math, 2006. -.. [BMSS2006] Alin Bostan, Bruno Salvy, Francois Morain, Eric Schost. Fast - algorithms for computing isogenies between elliptic +.. [BMSS2006] Alin Bostan, Bruno Salvy, François Morain, Éric Schost. + Fast algorithms for computing isogenies between elliptic curves. [Research Report] 2006, pp.28. + https://arxiv.org/pdf/cs/0609020.pdf .. [BN2010] \D. Bump and M. Nakasuji. Integration on `p`-adic groups and crystal bases. diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 383cc8e4fd7..5247f2afc06 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -69,7 +69,10 @@ use of univariate vs. bivariate polynomials and rational functions. - Lorenz Panny (2022-04): major cleanup of code and documentation + - Lorenz Panny (2022): inseparable duals + +- Rémy Oudompheng (2023): implementation of the BMSS algorithm """ # **************************************************************************** @@ -3345,6 +3348,72 @@ def _composition_impl(left, right): return NotImplemented +def compute_isogeny_bmss(E1, E2, l): + r""" + Compute the kernel polynomial of the unique normalized isogeny + of degree ``l`` between ``E1`` and ``E2``. + + ALGORITHM: [BMSS2006], algorithm *fastElkies'*. + + AUTHORS: Rémy Oudompheng. + `Original code ` + released under the + `MIT license `. + Slightly adjusted for inclusion in the Sage library. + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_bmss + sage: E1 = EllipticCurve(GF(167), [153, 112]) + sage: E2 = EllipticCurve(GF(167), [56, 40]) + sage: compute_isogeny_bmss(E1, E2, 13) + x^6 + 139*x^5 + 73*x^4 + 139*x^3 + 120*x^2 + 88*x + """ + Rx, x = E1.base_ring()["x"].objgen() + # Compute C = 1/(1 + Ax^4 + Bx^6) mod x^4l + A, B = E1.a4(), E1.a6() + C = (1 + A * x**4 + B * x**6).inverse_series_trunc(4 * l) + # Solve differential equation + # The number of terms doubles at each iteration. + # S'^2 = G(x,S) = (1 + A2 S^4 + B2 S^6) / (1 + Ax^4 + Bx^6) + # S = x + O(x^2) + A2, B2 = E2.a4(), E2.a6() + S = x + (A2 - A) / 10 * x**5 + (B2 - B) / 14 * x**7 + sprec = 8 + while sprec < 4 * l: + assert sprec % 2 == 0 + if sprec > 2 * l: + sprec = 2 * l + # s1 => s1 + x^k s2 + # 2 s1' s2' - dG/dS(x, s1) s2 = G(x, s1) - s1'2 + s1 = S + ds1 = s1.derivative() + s1pows = [1, s1] + while len(s1pows) < 7: + s1pows.append(s1._mul_trunc_(s1pows[-1], 2 * sprec)) + GS = C * (1 + A2 * s1pows[4] + B2 * s1pows[6]) + dGS = C * (4 * A2 * s1pows[3] + 6 * B2 * s1pows[5]) + # s2' = (dGS / 2s1') s2 + (G(x, s1) - s1'2) / (2s1') + denom = (2 * ds1).inverse_series_trunc(2 * sprec) + a = dGS._mul_trunc_(denom, 2 * sprec) + b = (GS - ds1**2)._mul_trunc_(denom, 2 * sprec) + s2 = a.add_bigoh(2 * sprec).solve_linear_de(prec=2 * sprec, b=b, f0=0) + S = s1 + Rx(s2) + sprec = 2 * sprec + # Reconstruct: + # S = x * T(x^2) + # Compute U = 1/T^2 + # Reconstruct N(1/x) / D(1/x) = U + T = Rx([S[2 * i + 1] for i in range(2 * l)]) + U = T._mul_trunc_(T, 2 * l).inverse_series_trunc(2 * l) + _, Q = Rx(U).rational_reconstruction(x ** (2 * l), l, l) + Q = Q.add_bigoh((l + 1) // 2) + if not Q.is_square(): + raise ValueError(f"the two curves are not linked by a cyclic normalized isogeny of degree {l}") + Q = Q.sqrt() + ker = Rx(Q).reverse(degree=l//2) + return ker.monic() + def compute_isogeny_stark(E1, E2, ell): r""" Return the kernel polynomial of an isogeny of degree ``ell`` @@ -3497,10 +3566,10 @@ def split_kernel_polynomial(poly): from sage.misc.misc_c import prod return prod([p for p,e in poly.squarefree_decomposition()]) -def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): +def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm=None): r""" - Return the kernel polynomial of an isogeny of degree ``ell`` - from ``E1`` to ``E2``. + Return the kernel polynomial of a cyclic, separable, normalized + isogeny of degree ``ell`` from ``E1`` to ``E2``. INPUT: @@ -3510,7 +3579,9 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): - ``ell`` -- the degree of an isogeny from ``E1`` to ``E2`` - - ``algorithm`` -- currently only ``"stark"`` (default) is implemented + - ``algorithm`` -- ``None`` (default, choose automatically) or + ``"bmss"`` (:func:`compute_isogeny_bmss`) or + ``"stark"`` (:func:`compute_isogeny_stark`) OUTPUT: @@ -3567,9 +3638,13 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm="stark"): from sage.misc.superseded import deprecation deprecation(34871, 'The "starks" algorithm is being renamed to "stark".') algorithm = 'stark' - if algorithm != "stark": - raise NotImplementedError(f'unknown algorithm {algorithm}') - return compute_isogeny_stark(E1, E2, ell).radical() + if algorithm is None: + algorithm = 'stark' if ell < 10 else 'bmss' + if algorithm == 'bmss': + return compute_isogeny_bmss(E1, E2, ell) + if algorithm == 'stark': + return compute_isogeny_stark(E1, E2, ell).radical() + raise NotImplementedError(f'unknown algorithm {algorithm}') def compute_intermediate_curves(E1, E2): r""" From 852fee4735d20d905e98faf4a2ac29aff9b7c8c4 Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Sun, 17 Sep 2023 23:58:12 +0200 Subject: [PATCH 117/225] move author information from docstring to comment --- .../schemes/elliptic_curves/ell_curve_isogeny.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 5247f2afc06..f36919bd3c1 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -3353,13 +3353,7 @@ def compute_isogeny_bmss(E1, E2, l): Compute the kernel polynomial of the unique normalized isogeny of degree ``l`` between ``E1`` and ``E2``. - ALGORITHM: [BMSS2006], algorithm *fastElkies'*. - - AUTHORS: Rémy Oudompheng. - `Original code ` - released under the - `MIT license `. - Slightly adjusted for inclusion in the Sage library. + ALGORITHM: [BMSS2006]_, algorithm *fastElkies'*. EXAMPLES:: @@ -3369,6 +3363,10 @@ def compute_isogeny_bmss(E1, E2, l): sage: compute_isogeny_bmss(E1, E2, 13) x^6 + 139*x^5 + 73*x^4 + 139*x^3 + 120*x^2 + 88*x """ + # Original author of this function: Rémy Oudompheng. + # https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/isogeny_weber/isogenies.py#L272-L332 + # Released under the MIT license: https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/LICENSE + # Slightly adjusted for inclusion in the Sage library. Rx, x = E1.base_ring()["x"].objgen() # Compute C = 1/(1 + Ax^4 + Bx^6) mod x^4l A, B = E1.a4(), E1.a6() From c67d9077f34a6cc5dad423c56f46577511487262 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Tue, 19 Sep 2023 13:36:16 -0700 Subject: [PATCH 118/225] (co)homology as vector space enhancements: duality between homology and cohomology: - new method 'dual' to switch between them - new method 'eval' to evaluate cochains on chains and vice versa - new method '_test_duality' to make sure that our orderings on the bases for homology and cohomology are consistent - "implement" mod 2 Steenrod operations for cubical complexes by converting those complexes to simplicial complexes. Likely very slow. --- .../homology_vector_space_with_basis.py | 115 ++++++++++++++++-- 1 file changed, 105 insertions(+), 10 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index bf53c7b6113..e19021588ca 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -26,17 +26,22 @@ # https://www.gnu.org/licenses/ ######################################################################## +from sage.algebras.steenrod.steenrod_algebra import SteenrodAlgebra from sage.misc.cachefunc import cached_method from sage.categories.algebras import Algebras +from sage.categories.category import Category +from sage.categories.left_modules import LeftModules from sage.categories.modules import Modules from sage.combinat.free_module import CombinatorialFreeModule +from sage.matrix.constructor import matrix from sage.sets.family import Family try: from sage.topology.simplicial_complex import SimplicialComplex from sage.topology.simplicial_set import SimplicialSet_arbitrary + from sage.topology.cubical_complex import CubicalComplex except ImportError: - SimplicialComplex = SimplicialSet_arbitrary = () + SimplicialComplex = SimplicialSet_arbitrary = CubicalComplex = () class HomologyVectorSpaceWithBasis(CombinatorialFreeModule): @@ -385,6 +390,60 @@ def _to_cycle_on_basis(self, i): cochains=self._cohomology) return chains.from_vector(vec) + def dual(self): + r""" + Return the dual space. + + If ``self`` is homology, return the cohomology ring. If + ``self`` is cohomology, return the homology as a vector space. + + EXAMPLES:: + + sage: T = simplicial_complexes.Torus() + sage: hom = T.homology_with_basis(GF(2)) + sage: coh = T.cohomology_ring(GF(2)) + sage: hom.dual() is coh + True + sage: coh.dual() is hom + True + """ + if self._cohomology: + return HomologyVectorSpaceWithBasis(self.base_ring(), self.complex(), not self._cohomology) + return CohomologyRing(self.base_ring(), self.complex()) + + def _test_duality(self, **options): + r""" + Test whether the ordered bases for homology and cohomology are compatible. + Return nothing if the test succeeds. + + This checks whether each evaluation map `H^n \otimes H_n \to + k` is represented by the identity matrix, in terms of the + chosen bases. + + TESTS:: + + sage: T = simplicial_complexes.Torus() + sage: K = T.suspension() + sage: K.set_immutable() + sage: H = K.cohomology_ring(QQ) + sage: H._test_duality() + + sage: simplicial_complexes.RandomComplex(8, 2, .2).homology_with_basis(GF(2))._test_duality() + sage: simplicial_complexes.RandomComplex(8, 2, .4).homology_with_basis(GF(2))._test_duality() + sage: simplicial_complexes.RandomComplex(8, 2, .6).homology_with_basis(GF(2))._test_duality() + + sage: simplicial_complexes.RandomComplex(12, 3, .5).homology_with_basis(GF(2))._test_duality() # long time + """ + okay = True + dual = self.dual() + dims = [a[0] for a in self._indices] + for dim in range(max(dims) + 1): + n = len(self.basis(dim)) + m = matrix(n, n, [a.eval(b) for a in self.basis(dim) for b in dual.basis(dim)]) + okay = (m == 1) + if not okay: + print('error in dimension {}'.format(dim)) + class Element(CombinatorialFreeModule.Element): def to_cycle(self): r""" @@ -413,6 +472,22 @@ def to_cycle(self): raise ValueError("only defined for homogeneous elements") return sum(c * self.parent()._to_cycle_on_basis(i) for i, c in self) + def eval(self, other): + r""" + Evaluate ``self`` at ``other``. + + INPUT: + + - ``other`` -- an element of the dual space: if ``self`` + is an element of cohomology in dimension `n`, then + ``other`` should be an element of homology in dimension + `n`, and vice versa. + """ + if self.parent()._cohomology: + return self.to_cycle().eval(other.to_cycle()) + else: + return other.to_cycle().eval(self.to_cycle()) + class CohomologyRing(HomologyVectorSpaceWithBasis): """ @@ -431,6 +506,7 @@ class CohomologyRing(HomologyVectorSpaceWithBasis): - ``base_ring`` -- must be a field - ``cell_complex`` -- the cell complex whose homology we are computing + - ``category`` -- (optional) a subcategory of modules with basis EXAMPLES:: @@ -485,8 +561,8 @@ def __init__(self, base_ring, cell_complex): sage: H = RP2.cohomology_ring(GF(5)) sage: TestSuite(H).run() """ - cat = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() - HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, True, cat) + category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() + HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, True, category) def _repr_(self): """ @@ -686,10 +762,16 @@ def Sq(self, i): .. WARNING:: - This is only implemented for simplicial complexes. + The main implementation is only for simplicial + complexes and simplicial sets; cubical complexes are + converted to simplicial complexes first. Note that + this converted complex may be large and so computations + may be slow. There is no implementation for + `\Delta`-complexes. This cohomology operation is only defined in - characteristic 2. + characteristic 2. Odd primary Steenrod operations are not + implemented. Algorithm: see González-Díaz and Réal [GDR1999]_, Corollary 3.2. @@ -707,6 +789,7 @@ def Sq(self, i): sage: y.Sq(1) h^{3,0} + sage: # long time sage: RP4 = simplicial_complexes.RealProjectiveSpace(4) sage: H = RP4.cohomology_ring(GF(2)) sage: x = H.basis()[1,0] @@ -714,7 +797,7 @@ def Sq(self, i): sage: z = H.basis()[3,0] sage: x.Sq(1) == y True - sage: z.Sq(1) # long time + sage: z.Sq(1) h^{4,0} This calculation is much faster with simplicial sets (on @@ -728,12 +811,16 @@ def Sq(self, i): TESTS:: - sage: T = cubical_complexes.Torus() + sage: RP_cubical = cubical_complexes.RealProjectivePlane() + sage: x = RP_cubical.cohomology_ring(GF(2)).basis()[1,0] + sage: x.Sq(1) + h^{2,0} + sage: T = delta_complexes.Torus() sage: x = T.cohomology_ring(GF(2)).basis()[1,0] sage: x.Sq(1) Traceback (most recent call last): ... - NotImplementedError: Steenrod squares are only implemented for simplicial complexes and simplicial sets + NotImplementedError: Steenrod squares are not implemented for this type of cell complex sage: S2 = simplicial_complexes.Sphere(2) sage: x = S2.cohomology_ring(GF(7)).basis()[2,0] sage: x.Sq(1) @@ -743,9 +830,17 @@ def Sq(self, i): """ P = self.parent() scomplex = P.complex() + if isinstance(scomplex, CubicalComplex): + # Convert cubical complex to simplicial complex, and + # convert self to basis element in the new complex's + # cohomology ring. + scomplex = SimplicialComplex(scomplex, is_mutable=False) + P = scomplex.cohomology_ring(self.base_ring()) + self = P.sum_of_terms(self.monomial_coefficients().items()) if not isinstance(scomplex, (SimplicialComplex, SimplicialSet_arbitrary)): - raise NotImplementedError('Steenrod squares are only implemented for ' - 'simplicial complexes and simplicial sets') + raise NotImplementedError('Steenrod squares are not implemented for ' + 'this type of cell complex') + scomplex = P.complex() base_ring = P.base_ring() if base_ring.characteristic() != 2: raise ValueError('Steenrod squares are only defined in characteristic 2') From 7ef7249ee34835629b76481890ce5a483f6c0ffb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 16 Sep 2023 15:44:27 -0700 Subject: [PATCH 119/225] build/pkgs/setuptools[_wheel]/install-requires.txt: >= 68.1.1 --- build/pkgs/setuptools/install-requires.txt | 4 +++- build/pkgs/setuptools_wheel/install-requires.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) mode change 100644 => 120000 build/pkgs/setuptools_wheel/install-requires.txt diff --git a/build/pkgs/setuptools/install-requires.txt b/build/pkgs/setuptools/install-requires.txt index e0cf7c9b5dc..c12b5900873 100644 --- a/build/pkgs/setuptools/install-requires.txt +++ b/build/pkgs/setuptools/install-requires.txt @@ -1 +1,3 @@ -setuptools >=49.6.0, <64 +# 68.1.0 Promote pyproject.toml's [tool.setuptools] out of beta. +# 68.1.1 Fix editable install finder handling of nested packages +setuptools >= 68.1.1 diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt deleted file mode 100644 index d3767a68c8f..00000000000 --- a/build/pkgs/setuptools_wheel/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -setuptools >= 65.6 diff --git a/build/pkgs/setuptools_wheel/install-requires.txt b/build/pkgs/setuptools_wheel/install-requires.txt new file mode 120000 index 00000000000..c5cfb4ff0a9 --- /dev/null +++ b/build/pkgs/setuptools_wheel/install-requires.txt @@ -0,0 +1 @@ +../setuptools/install-requires.txt \ No newline at end of file From 1774d74dbcadebdf559477c6bd2e8f35fc65bf89 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 20 Sep 2023 09:19:40 -0700 Subject: [PATCH 120/225] build/pkgs/setuptools: Update to 68.2.2 --- build/pkgs/setuptools/checksums.ini | 6 +++--- build/pkgs/setuptools/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/setuptools/checksums.ini b/build/pkgs/setuptools/checksums.ini index e666bb16483..150e3c25335 100644 --- a/build/pkgs/setuptools/checksums.ini +++ b/build/pkgs/setuptools/checksums.ini @@ -1,5 +1,5 @@ tarball=setuptools-VERSION.tar.gz -sha1=43e83ae0716615a7df123a5731412d1cd66dc81d -md5=222b8c1a7432457d8485f947a0e0fde6 -cksum=3076207771 +sha1=b0c9b16863c57d70adc22651906eea7eaee09803 +md5=d967ca2ba7f46db887daee2d5c9bd6a2 +cksum=2346145273 upstream_url=https://pypi.io/packages/source/s/setuptools/setuptools-VERSION.tar.gz diff --git a/build/pkgs/setuptools/package-version.txt b/build/pkgs/setuptools/package-version.txt index c068d01a2ed..fc312b9c8c1 100644 --- a/build/pkgs/setuptools/package-version.txt +++ b/build/pkgs/setuptools/package-version.txt @@ -1 +1 @@ -68.1.2 +68.2.2 From 581fb46b68a0aede450bb650bf23cc85e6794abc Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 20 Sep 2023 13:38:24 -0700 Subject: [PATCH 121/225] The mod 2 cohomology ring of a simplicial complex/set as a module over the Steenrod algebra. Create a new class, CohomologyRing_mod2, for this, because these Steenrod operations on cohomology are only implemented at the prime 2. Use the new class automatically when users create `K.cohomology_ring(GF(2))` for a complex `K`. Move the existing "Sq" method to the new class, and create new methods to make the module action transparent. Also create a method steenrod_module_map in case (a) someone wants access to these matrices and (b) for future use, and in particular for computing the Steenrod algebra action on homology. --- .../homology_vector_space_with_basis.py | 337 ++++++++++++++++-- src/sage/topology/cell_complex.py | 5 +- 2 files changed, 304 insertions(+), 38 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index e19021588ca..3345b1caa3b 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -34,6 +34,8 @@ from sage.categories.modules import Modules from sage.combinat.free_module import CombinatorialFreeModule from sage.matrix.constructor import matrix +from sage.modules.free_module_element import vector +from sage.rings.finite_rings.finite_field_constructor import GF from sage.sets.family import Family try: @@ -409,11 +411,13 @@ def dual(self): """ if self._cohomology: return HomologyVectorSpaceWithBasis(self.base_ring(), self.complex(), not self._cohomology) + if self.base_ring() == GF(2): + return CohomologyRing_mod2(self.base_ring(), self.complex()) return CohomologyRing(self.base_ring(), self.complex()) def _test_duality(self, **options): r""" - Test whether the ordered bases for homology and cohomology are compatible. + Test if the ordered bases for homology and cohomology are compatible. Return nothing if the test succeeds. This checks whether each evaluation map `H^n \otimes H_n \to @@ -482,6 +486,29 @@ def eval(self, other): is an element of cohomology in dimension `n`, then ``other`` should be an element of homology in dimension `n`, and vice versa. + + This just calls the :meth:`~sage.homology.chains.Cochains.Element.eval` + method on the representing chains and cochains. + + EXAMPLES:: + + sage: T = simplicial_complexes.Torus() + sage: homology = T.homology_with_basis(QQ) + sage: cohomology = T.cohomology_ring(QQ) + sage: a1, a2 = homology.basis(1) + sage: alpha1, alpha2 = cohomology.basis(1) + sage: a1.to_cycle() + (0, 3) - (0, 6) + (3, 6) + sage: alpha1.to_cycle() + -\chi_(1, 3) - \chi_(1, 4) - \chi_(2, 3) - \chi_(2, 4) - \chi_(2, 5) + \chi_(3, 6) + sage: a1.eval(alpha1) + 1 + sage: alpha2.to_cycle() + \chi_(1, 3) + \chi_(1, 4) + \chi_(1, 6) + \chi_(2, 4) - \chi_(4, 5) + \chi_(5, 6) + sage: alpha2.eval(a1) + 0 + sage: (2 * alpha2).eval(a1 + a2) + 2 """ if self.parent()._cohomology: return self.to_cycle().eval(other.to_cycle()) @@ -522,46 +549,22 @@ class CohomologyRing(HomologyVectorSpaceWithBasis): -h^{4,0} sage: x * x -h^{4,0} - - There are mod 2 cohomology operations defined, also, for - simplicial complexes and simplicial sets:: - - sage: Hmod2 = CP2.cohomology_ring(GF(2)) - sage: y = Hmod2.basis(2)[2,0] - sage: y.Sq(2) - h^{4,0} - - sage: # needs sage.groups - sage: Y = simplicial_sets.RealProjectiveSpace(6).suspension() - sage: H_Y = Y.cohomology_ring(GF(2)) - sage: b = H_Y.basis()[2,0] - sage: b.Sq(1) - h^{3,0} - sage: b.Sq(2) - 0 - sage: c = H_Y.basis()[4,0] - sage: c.Sq(1) - h^{5,0} - sage: c.Sq(2) - h^{6,0} - sage: c.Sq(3) - h^{7,0} - sage: c.Sq(4) - 0 """ - def __init__(self, base_ring, cell_complex): + def __init__(self, base_ring, cell_complex, category=None): """ Initialize ``self``. EXAMPLES:: sage: RP2 = simplicial_complexes.ProjectivePlane() - sage: H = RP2.cohomology_ring(GF(2)) - sage: TestSuite(H).run() sage: H = RP2.cohomology_ring(GF(5)) sage: TestSuite(H).run() + sage: T = simplicial_complexes.Torus() + sage: H = T.cohomology_ring(QQ) + sage: TestSuite(H).run() """ - category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() + if category is None: + category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, True, category) def _repr_(self): @@ -752,6 +755,88 @@ def cup_product(self, other): """ return self * other + +class CohomologyRing_mod2(CohomologyRing): + """ + The mod 2 cohomology ring. + + Based on :class:`CohomologyRing`, with Steenrod operations included. + + .. NOTE:: + + This is not intended to be created directly by the user, but + instead via the + :meth:`cohomology ring` + of a :class:`cell + complex`. + + INPUT: + + - ``base_ring`` -- must be the field ``GF(2)`` + - ``cell_complex`` -- the cell complex whose homology we are + computing + - ``category`` -- (optional) a subcategory of modules with basis + + EXAMPLES: + + Mod 2 cohomology operations are defined:: + + sage: CP2 = simplicial_complexes.ComplexProjectivePlane() + sage: Hmod2 = CP2.cohomology_ring(GF(2)) + sage: y = Hmod2.basis(2)[2,0] + sage: y.Sq(2) + h^{4,0} + + sage: # needs sage.groups + sage: Y = simplicial_sets.RealProjectiveSpace(6).suspension() + sage: H_Y = Y.cohomology_ring(GF(2)) + sage: b = H_Y.basis()[2,0] + sage: b.Sq(1) + h^{3,0} + sage: b.Sq(2) + 0 + sage: c = H_Y.basis()[4,0] + sage: c.Sq(1) + h^{5,0} + sage: c.Sq(2) + h^{6,0} + sage: c.Sq(3) + h^{7,0} + sage: c.Sq(4) + 0 + + Cohomology can be viewed as a left module over the Steenrod + algebra, and also as a right module:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) + sage: H = RP4.cohomology_ring(GF(2)) + sage: x = H.basis()[1,0] + sage: Sq(0,1) * x + h^{4,0} + sage: Sq(3) * x + 0 + sage: x * Sq(3) + h^{4,0} + """ + + def __init__(self, base_ring, cell_complex): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: RP2 = simplicial_complexes.ProjectivePlane() + sage: H = RP2.cohomology_ring(GF(2)) + sage: TestSuite(H).run() + """ + if base_ring != GF(2): + raise ValueError + category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() + category = Category.join((category, LeftModules(SteenrodAlgebra(2)))) + CohomologyRing.__init__(self, base_ring, cell_complex, category=category) + + class Element(CohomologyRing.Element): def Sq(self, i): r""" Return the result of applying `Sq^i` to this element. @@ -790,6 +875,7 @@ def Sq(self, i): h^{3,0} sage: # long time + sage: # needs sage.groups sage: RP4 = simplicial_complexes.RealProjectiveSpace(4) sage: H = RP4.cohomology_ring(GF(2)) sage: x = H.basis()[1,0] @@ -821,12 +907,6 @@ def Sq(self, i): Traceback (most recent call last): ... NotImplementedError: Steenrod squares are not implemented for this type of cell complex - sage: S2 = simplicial_complexes.Sphere(2) - sage: x = S2.cohomology_ring(GF(7)).basis()[2,0] - sage: x.Sq(1) - Traceback (most recent call last): - ... - ValueError: Steenrod squares are only defined in characteristic 2 """ P = self.parent() scomplex = P.complex() @@ -843,6 +923,8 @@ def Sq(self, i): scomplex = P.complex() base_ring = P.base_ring() if base_ring.characteristic() != 2: + # This should never happen: the class should only be + # instantiated in characteristic 2. raise ValueError('Steenrod squares are only defined in characteristic 2') # We keep the same notation as in [GDR1999]. # The trivial cases: @@ -936,6 +1018,187 @@ def Sq(self, i): ret += P._from_dict(result, remove_zeros=False) return ret + def _acted_upon_(self, a, self_on_left): + r""" + Define multiplication of ``self`` by ``a``, an + element of the Steenrod algebra. + + INPUT: + + - ``a`` - an element of the mod 2 Steenrod algebra + - ``self_on_left`` -- ``True`` if we are computing ``self * a``, + otherwise ``a * self`` + + Algorithm: for left multiplication by ``a``, since we have + :meth:`Sq` to compute multiplication by a single generator + `Sq^i`, first convert ``a`` to the Serre-Cartan basis --- + that is, sums of products of the elements `Sq^i` --- and + then apply :meth:`Sq` repeatedly. Right multiplication by + ``a`` is the same as left multiplication by the antipode + applied to ``a``. + + EXAMPLES:: + + sage: # needs sage.groups + sage: SRP4 = simplicial_sets.RealProjectiveSpace(4).suspension() + sage: H = SRP4.cohomology_ring(GF(2)) + sage: x = H.basis()[2,0] + sage: Sq(0,1) * x + h^{5,0} + sage: Sq(3) * x + 0 + sage: x * Sq(3) + h^{5,0} + + TESTS:: + + sage: (Sq(2) * Sq(1)) * x == Sq(2) * (Sq(1) * x) + True + sage: x * (Sq(1) * Sq(2)) == (x * Sq(1)) * Sq(2) + True + """ + # Handle field elements first. + if a in self.base_ring(): + return self.map_coefficients(lambda c: c*a) + if self_on_left: # i.e., module element on left + a = a.antipode() + b = a.change_basis('adem') + ans = self.parent().zero() + mono_dict = b.monomial_coefficients() + for seq in mono_dict: + x = self + for i in reversed(seq): + x = x.Sq(i) + ans += mono_dict[seq] * x + return ans + + def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): + r""" + Return a component of the module structure map `A \otimes + H \to H`, where `H` is this cohomology ring and `A` is the + Steenrod algebra. + + INPUT: + + - ``deg_domain`` -- the degree of the domain in the cohomology + ring + + - ``deg_codomain`` -- the degree of the codomain in the + cohomology ring + + - ``side`` (optional, default ``'left'``) -- are we computing + the action as a left module action or a right module? (This + documentation is written from the point of view of a left + action for brevity. Just switch all of the tensors for the + right action.) + + Writing `m` for ``deg_domain`` and `n` for ``deg_codomain``, this + returns `A^{n-m} \otimes H^{m} \to H^{n}`, one single + component of the map making `H` into an `A`-module. + + .. WARNING:: + + This is only implemented in characteristic two. The main + implementation is only for simplicial complexes and simplicial + sets; cubical complexes are converted to simplicial complexes + first. Note that this converted complex may be large and so + computations may be slow. There is no implementation for + `\Delta`-complexes. + + Algorithm: use the Milnor basis for the truncated Steenrod + algebra `A`, and for cohomology, use the basis with which it + is equipped. For each pair of basis elements `a` and `h`, + compute the product `a \otimes h`, and use this to assemble a + matrix defining the action map via multiplication on the + appropriate side. That is, if ``side`` is ``'left`'', return a + matrix suitable for multiplication on the left, etc. + + EXAMPLES:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(4) + sage: H = RP4.cohomology_ring(GF(2)) + sage: H.steenrod_module_map(1, 2) + [1] + sage: H.steenrod_module_map(1, 3) + [0] + sage: H.steenrod_module_map(1, 4, 'left') + [1 0] + sage: H.steenrod_module_map(1, 4, 'right') + [1] + [1] + + Products of projective spaces:: + + sage: RP3 = simplicial_sets.RealProjectiveSpace(3) + sage: K = RP3.product(RP3) + sage: H = K.cohomology_ring(GF(2)) + sage: H + Cohomology ring of RP^3 x RP^3 over Finite Field of size 2 + + There is one column for each element `a \otimes b`, where `a` + is a basis element for the Steenrod algebra and `b` is a basis + element for the cohomology algebra. There is one row for each + basis element of the cohomology algebra. Unfortunately, the + chosen basis is not the monomial basis for this truncated + polynomial algebra:: + + sage: x1, x2 = H.basis(1) + sage: x1 * x1 + h^{2,0} + h^{2,1} + sage: x2 * x2 + h^{2,2} + sage: x1 * x2 + h^{2,0} + + sage: H.steenrod_module_map(1, 2) + [1 0] + [1 0] + [0 1] + sage: H.steenrod_module_map(1, 3, 'left') + [0 0] + [0 0] + [0 0] + [0 0] + sage: H.steenrod_module_map(1, 3, 'right') + [0 0 0 0] + [0 0 0 0] + sage: H.steenrod_module_map(2, 3) + [0 0 0] + [1 1 0] + [0 0 0] + [0 0 0] + """ + side = side.lower() + if side not in ['right', 'left']: + raise ValueError('side must be either "left" or "right"') + base_ring = self.base_ring() + char = base_ring.characteristic() + # Use sorted(...) so that there are reproducible orders on the bases. + A_basis = sorted(SteenrodAlgebra(char).basis(deg_codomain - deg_domain)) + H_basis_dom = sorted(self.basis(deg_domain)) + H_basis_cod = self.basis(deg_codomain).keys() + H_basis_cod = {elt: idx for idx, elt in enumerate(sorted(H_basis_cod))} + entries = [] + for a in A_basis: + for h in H_basis_dom: + vec = vector(base_ring, len(H_basis_cod)) + if side == 'left': + x = a * h + else: + x = h * a + monos = x.monomial_coefficients() + for seq in monos: + vec[H_basis_cod[seq]] = monos[seq] + entries.extend(vec) + # We built the matrix column by column, so now we take the + # transpose. + if side == 'left': + return matrix(base_ring, len(A_basis) * len(H_basis_dom), + len(H_basis_cod), entries).transpose() + return matrix(base_ring, len(A_basis) * len(H_basis_dom), + len(H_basis_cod), entries) + def sum_indices(k, i_k_plus_one, S_k_plus_one): r""" diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 906936a44c1..8ed9204736d 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -47,6 +47,7 @@ from sage.structure.sage_object import SageObject from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ +from sage.rings.finite_rings.finite_field_constructor import GF from sage.misc.abstract_method import abstract_method @@ -972,7 +973,9 @@ def cohomology_ring(self, base_ring=QQ): Cohomology ring of Simplicial complex with 9 vertices and 18 facets over Rational Field """ - from sage.homology.homology_vector_space_with_basis import CohomologyRing + from sage.homology.homology_vector_space_with_basis import CohomologyRing, CohomologyRing_mod2 + if base_ring == GF(2): + return CohomologyRing_mod2(base_ring, self) return CohomologyRing(base_ring, self) @abstract_method From 31993f74e1a2e5986c1a51bdb989f8bc35d8871d Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 20 Sep 2023 20:25:57 -0700 Subject: [PATCH 122/225] Give mod 2 homology the structure of a module over the Steenrod algebra. This uses the module structure on cohomology together with vector space dualization to put a module structure on homology. While Sq^n increases dimension in cohomology by n, it lowers homological degree by n. --- src/doc/en/reference/references/index.rst | 5 + .../homology_vector_space_with_basis.py | 207 +++++++++++++++++- src/sage/topology/cell_complex.py | 10 +- 3 files changed, 211 insertions(+), 11 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index e09f339513f..afff315cde9 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1002,6 +1002,11 @@ REFERENCES: group actions}, (preprint March 2003, available on Mitter's MIT website). +.. [Boa1982] J. M. Boardman, "The eightfold way to BP-operations", + in *Current trends in algebraic topology*, pp. 187–226, + Canadian Mathematical Society Proceedings, 2, Part 1. + Providence 1982. ISBN 978-0-8218-6003-8. + .. [Bond2007] P. Bonderson, Nonabelian anyons and interferometry, Dissertation (2007). https://thesis.library.caltech.edu/2447/ diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 3345b1caa3b..a319eef50d6 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -31,6 +31,7 @@ from sage.categories.algebras import Algebras from sage.categories.category import Category from sage.categories.left_modules import LeftModules +from sage.categories.right_modules import RightModules from sage.categories.modules import Modules from sage.combinat.free_module import CombinatorialFreeModule from sage.matrix.constructor import matrix @@ -409,10 +410,15 @@ def dual(self): sage: coh.dual() is hom True """ - if self._cohomology: - return HomologyVectorSpaceWithBasis(self.base_ring(), self.complex(), not self._cohomology) if self.base_ring() == GF(2): + if self._cohomology: + return HomologyVectorSpaceWithBasis_mod2(self.base_ring(), + self.complex()) return CohomologyRing_mod2(self.base_ring(), self.complex()) + if self._cohomology: + return HomologyVectorSpaceWithBasis(self.base_ring(), + self.complex(), + not self._cohomology) return CohomologyRing(self.base_ring(), self.complex()) def _test_duality(self, **options): @@ -510,11 +516,187 @@ def eval(self, other): sage: (2 * alpha2).eval(a1 + a2) 2 """ + if not self or not other: + return self.base_ring().zero() if self.parent()._cohomology: return self.to_cycle().eval(other.to_cycle()) else: return other.to_cycle().eval(self.to_cycle()) +class HomologyVectorSpaceWithBasis_mod2(HomologyVectorSpaceWithBasis): + r""" + Homology vector space mod 2. + + Based on :class:`HomologyVectorSpaceWithBasis`, with Steenrod + operations included. + + .. NOTE:: + + This is not intended to be created directly by the user, but + instead via the method + :meth:`~sage.topology.cell_complex.GenericCellComplex.homology_with_basis` + for the class of :class:`cell + complexes`. + + .. TODO:: + + Implement Steenrod operations on (co)homology at odd primes, + and thereby implement this class over `\GF{p}` for any `p`. + + INPUT: + + - ``base_ring`` -- must be the field ``GF(2)`` + - ``cell_complex`` -- the cell complex whose homology we are + computing + - ``category`` -- (optional) a subcategory of modules with basis + + This does not include the ``cohomology`` argument present for + :class:`HomologyVectorSpaceWithBasis`: use + :class:`CohomologyRing_mod2` for cohomology. + + EXAMPLES: + + Mod 2 cohomology operations are defined on both the left and the + right:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP4.homology_with_basis(GF(2)) + sage: x4 = H.basis()[4,0] + sage: x4 * Sq(1) + h_{3,0} + sage: Sq(1) * x4 + h_{3,0} + sage: Sq(2) * x4 + h_{2,0} + sage: Sq(3) * x4 + h_{1,0} + sage: Sq(0,1) * x4 + h_{1,0} + sage: x4 * Sq(0,1) + h_{1,0} + sage: Sq(3) * x4 + h_{1,0} + sage: x4 * Sq(3) + 0 + """ + def __init__(self, base_ring, cell_complex, category=None): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: H = simplicial_complexes.Torus().homology_with_basis(GF(2)) + sage: TestSuite(H).run() + sage: H = simplicial_complexes.Sphere(3).homology_with_basis(GF(2)) + sage: TestSuite(H).run() + """ + if base_ring != GF(2): + raise ValueError + category = Modules(base_ring).WithBasis().Graded().FiniteDimensional().or_subcategory(category) + category = Category.join((category, + LeftModules(SteenrodAlgebra(2)), + RightModules(SteenrodAlgebra(2)))) + HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, + cohomology=False, + category=category) + + class Element(HomologyVectorSpaceWithBasis.Element): + + def _acted_upon_(self, a, self_on_left): + r""" + Define multiplication of ``self`` by ``a``, an + element of the Steenrod algebra. + + INPUT: + + - ``a`` - an element of the mod 2 Steenrod algebra + - ``self_on_left`` -- ``True`` if we are computing ``self * a``, + otherwise ``a * self`` + + Algorithm: use the action of the Steenrod algebra `A` on + cohomology to construct the action on homology. That is, + given a right action of `A` on `H^*`, + + .. MATH:: + + \phi_L: H^* \otimes A \to H^* + + we define (a la Boardman [Boa1982]_, p. 190) + + .. MATH:: + + S'' \phi_L: A \otimes H_* \to H_* + + using the formula + + .. MATH:: + + \langle (S'' \phi) (f \otimes a), x \rangle + = \langle f, \phi_L (a \otimes x) \rangle, + + for `f \in H_m`, `a \in A^n`, and `x \in + H^{m-n}`. Somewhat more succintly, we define the action `f + \cdot a` by + + .. MATH:: + + (f \cdot a) (x) = f (a \cdot x) + + So given `f` (a.k.a. ``self``) and `a`, we compute `f (a + \cdot x)` for all basis elements `x` in `H^{m-n}`, + yielding a vector indexed by those basis elements. Since + our basis for homology is dual to the basis for + cohomology, we can then use the homology basis to convert + the vector to an element of `H_{m-n}`. + + This gives a right module structure. To get a left module + structure, use the right module structure after applying + the antipode to `a`. + + EXAMPLES:: + + sage: # needs sage.groups + sage: RP5 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP5.homology_with_basis(GF(2)) + sage: x5 = list(H.basis(5))[0] + sage: Sq(1) * x5 + 0 + sage: Sq(2) * x5 + h_{3,0} + sage: x5 * Sq(2) + h_{3,0} + + TESTS:: + + sage: # needs sage.groups + sage: RP4 = simplicial_sets.RealProjectiveSpace(5) + sage: H = RP4.homology_with_basis(GF(2)) + sage: x4 = H.basis()[4,0] + sage: (Sq(1) * Sq(2)) * x4 != 0 + True + sage: (Sq(1) * Sq(2)) * x4 == Sq(1) * (Sq(2) * x4) + True + sage: x4 * (Sq(2) * Sq(1)) == (x4 * Sq(2)) * Sq(1) + True + """ + # Handle field elements first. + if a in self.base_ring(): + return self.map_coefficients(lambda c: c*a) + if not self_on_left: # i.e., module element on left + a = a.antipode() + + m = self.degree() + n = a.degree() + if m <= n: + return self.parent().zero() + + vec = [] + for x in sorted(self.parent().dual().basis(m-n)): + vec.append(self.eval(a * x)) + B = list(self.parent().basis(m-n)) + return self.parent().linear_combination(zip(B, vec)) + class CohomologyRing(HomologyVectorSpaceWithBasis): """ @@ -757,7 +939,7 @@ def cup_product(self, other): class CohomologyRing_mod2(CohomologyRing): - """ + r""" The mod 2 cohomology ring. Based on :class:`CohomologyRing`, with Steenrod operations included. @@ -770,6 +952,11 @@ class CohomologyRing_mod2(CohomologyRing): of a :class:`cell complex`. + .. TODO:: + + Implement Steenrod operations on (co)homology at odd primes, + and thereby implement this class over `\GF{p}` for any `p`. + INPUT: - ``base_ring`` -- must be the field ``GF(2)`` @@ -779,7 +966,8 @@ class CohomologyRing_mod2(CohomologyRing): EXAMPLES: - Mod 2 cohomology operations are defined:: + Mod 2 cohomology operations are defined on both the left and the + right:: sage: CP2 = simplicial_complexes.ComplexProjectivePlane() sage: Hmod2 = CP2.cohomology_ring(GF(2)) @@ -833,7 +1021,9 @@ def __init__(self, base_ring, cell_complex): if base_ring != GF(2): raise ValueError category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() - category = Category.join((category, LeftModules(SteenrodAlgebra(2)))) + category = Category.join((category, + LeftModules(SteenrodAlgebra(2)), + RightModules(SteenrodAlgebra(2)))) CohomologyRing.__init__(self, base_ring, cell_complex, category=category) class Element(CohomologyRing.Element): @@ -1052,6 +1242,7 @@ def _acted_upon_(self, a, self_on_left): TESTS:: + sage: # needs sage.groups sage: (Sq(2) * Sq(1)) * x == Sq(2) * (Sq(1) * x) True sage: x * (Sq(1) * Sq(2)) == (x * Sq(1)) * Sq(2) @@ -1110,7 +1301,7 @@ def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): is equipped. For each pair of basis elements `a` and `h`, compute the product `a \otimes h`, and use this to assemble a matrix defining the action map via multiplication on the - appropriate side. That is, if ``side`` is ``'left`'', return a + appropriate side. That is, if ``side`` is ``'left'``, return a matrix suitable for multiplication on the left, etc. EXAMPLES:: @@ -1140,8 +1331,8 @@ def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): is a basis element for the Steenrod algebra and `b` is a basis element for the cohomology algebra. There is one row for each basis element of the cohomology algebra. Unfortunately, the - chosen basis is not the monomial basis for this truncated - polynomial algebra:: + chosen basis for this truncated polynomial algebra is not the + monomial basis:: sage: x1, x2 = H.basis(1) sage: x1 * x1 diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 8ed9204736d..2002c9f6b89 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -837,8 +837,7 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): .. SEEALSO:: If ``cohomology`` is ``True``, this returns the cohomology - as a graded module. For the ring structure, use - :meth:`cohomology_ring`. + as a ring: it calls :meth:`cohomology_ring`. EXAMPLES:: @@ -866,7 +865,12 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): sage: list(H.basis(3)) # needs sage.modules [h^{3,0}] """ - from sage.homology.homology_vector_space_with_basis import HomologyVectorSpaceWithBasis + from sage.homology.homology_vector_space_with_basis import \ + HomologyVectorSpaceWithBasis, HomologyVectorSpaceWithBasis_mod2 + if base_ring == GF(2): + if cohomology: + return self.cohomology_ring(base_ring) + return HomologyVectorSpaceWithBasis_mod2(base_ring, self) return HomologyVectorSpaceWithBasis(base_ring, self, cohomology) def cohomology_ring(self, base_ring=QQ): From 0b995cf72b38783748895eedcdd961c7e48df95b Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Thu, 21 Sep 2023 17:20:32 -0400 Subject: [PATCH 123/225] src/sage/repl/ipython_kernel/kernel.py: hide a PEP 420 warning Hide a warning that stems from using upstream (unbundled) pydevd with debugpy. New versions of debugpy work around it, but it's better if we can support older versions for a while. --- src/sage/repl/ipython_kernel/kernel.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/sage/repl/ipython_kernel/kernel.py b/src/sage/repl/ipython_kernel/kernel.py index 73681716aa2..db7554eed59 100644 --- a/src/sage/repl/ipython_kernel/kernel.py +++ b/src/sage/repl/ipython_kernel/kernel.py @@ -16,7 +16,18 @@ # *************************************************************************** import sys -from ipykernel.ipkernel import IPythonKernel +import warnings +with warnings.catch_warnings(): + # When upstream pydevd (as opposed to the bundled version) is used + # with debugpy, a PEP 420 warning is emitted. Debugpy and/or + # pydevd will eventually work around this, but as of September + # 2023, hiding the warning gives us more flexibility in the + # versions of those packages that we can accept. + warnings.filterwarnings("ignore", + message=r".*pkg_resources\.declare_namespace", + category=DeprecationWarning) + from ipykernel.ipkernel import IPythonKernel + from ipykernel.zmqshell import ZMQInteractiveShell from traitlets import Type From 7d813544a82d6b24a8a2b4a5a638cc2d96878076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 22 Sep 2023 09:40:49 +0200 Subject: [PATCH 124/225] add q-Fuss-Catalan numbers --- src/sage/combinat/q_analogues.py | 41 ++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index 541fc98353c..bc66aba7079 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -67,10 +67,9 @@ def q_int(n, q=None): sage: q_int(0, 3r) 0 - """ if n not in ZZ: - raise ValueError('%s must be an integer' % n) + raise ValueError(f'{n} must be an integer') if q is None: q = ZZ['q'].gen() @@ -78,7 +77,7 @@ def q_int(n, q=None): return parent(q)(0) if n > 0: return sum(q**i for i in range(n)) - return -q**n*sum(q**i for i in range(-n)) + return -q**n * sum(q**i for i in range(-n)) def q_factorial(n, q=None): @@ -211,7 +210,7 @@ def q_binomial(n, k, q=None, algorithm='auto'): 2 sage: q_binomial(4,2,3.14) 152.030056160000 - sage: R = GF(25, 't') + sage: R = GF((5, 2), 't') sage: t = R.gen(0) sage: q_binomial(6, 3, t) 2*t + 3 @@ -452,10 +451,16 @@ def q_multinomial(seq, q=None, binomial_algorithm='auto'): gaussian_multinomial = q_multinomial -def q_catalan_number(n, q=None): +def q_catalan_number(n, m=1, q=None): """ Return the `q`-Catalan number of index `n`. + INPUT: + + - ``m`` -- optional integer (default: 1) to get the ``m``-Fuss-Catalan numbers + + - ``q`` -- optional variable + If `q` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. @@ -467,10 +472,16 @@ def q_catalan_number(n, q=None): sage: from sage.combinat.q_analogues import q_catalan_number sage: q_catalan_number(4) q^12 + q^10 + q^9 + 2*q^8 + q^7 + 2*q^6 + q^5 + 2*q^4 + q^3 + q^2 + 1 + sage: p = ZZ['p'].0 - sage: q_catalan_number(4,p) + sage: q_catalan_number(4,q=p) p^12 + p^10 + p^9 + 2*p^8 + p^7 + 2*p^6 + p^5 + 2*p^4 + p^3 + p^2 + 1 + sage: q_catalan_number(3,m=2) + q^12 + q^10 + q^9 + q^8 + q^7 + 2*q^6 + q^5 + q^4 + q^3 + q^2 + 1 + + TESTS:: + The `q`-Catalan number of index `n` is only defined for `n` a nonnegative integer (:trac:`11411`):: @@ -479,8 +490,6 @@ def q_catalan_number(n, q=None): ... ValueError: argument (-2) must be a nonnegative integer - TESTS:: - sage: q_catalan_number(3).parent() Univariate Polynomial Ring in q over Integer Ring sage: q_catalan_number(0).parent() @@ -489,10 +498,12 @@ def q_catalan_number(n, q=None): if n in ZZ: if n in {0, 1}: return q_int(1, q) - elif n >= 2: - return (prod(q_int(j, q) for j in range(n + 2, 2 * n + 1)) // - prod(q_int(j, q) for j in range(2, n + 1))) - raise ValueError("argument (%s) must be a nonnegative integer" % n) + if n >= 2: + return (prod(q_int(j, q) + for j in range(m * n + 2, (m + 1) * n + 1)) // + prod(q_int(j, q) + for j in range(2, n + 1))) + raise ValueError(f"argument ({n}) must be a nonnegative integer") def qt_catalan_number(n): @@ -800,7 +811,7 @@ def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): Mathematical Society 101, no. 4 (1987): 771-775. :doi:`10.1090/S0002-9939-1987-0911049-8` - .. [Delsarte48] \S. Delsarte, *Fonctions de Möbius Sur Les Groupes Abeliens + .. [Delsarte48] \S. Delsarte, *Fonctions de Möbius Sur Les Groupes Abéliens Finis*, Annals of Mathematics, second series, Vol. 45, No. 3, (Jul 1948), pp. 600-609. http://www.jstor.org/stable/1969047 @@ -822,7 +833,7 @@ def q_subgroups_of_abelian_group(la, mu, q=None, algorithm='birkhoff'): if algorithm == 'delsarte': def F(args): - prd = lambda j: prod(args[j]-q**i for i in range(mu_c[j+1],mu_c[j])) + prd = lambda j: prod(args[j]-q**i for i in range(mu_c[j+1], mu_c[j])) F1 = prod(args[i]**mu_c[i+1] * prd(i) for i in range(k-1)) return F1 * prod(args[k-1]-q**i for i in range(mu_c[k-1])) @@ -866,7 +877,7 @@ def q_stirling_number1(n, k, q=None): q^3 + 3*q^2 + 4*q + 3 sage: all(stirling_number1(6,k) == q_stirling_number1(6,k)(1) - ....: for k in range(1,7)) + ....: for k in range(1,6)) True sage: x = polygen(QQ['q'],'x') From 42eba196fd0599e16500c6efb563cc820d8a9652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 22 Sep 2023 09:52:11 +0200 Subject: [PATCH 125/225] fix doc --- src/sage/combinat/q_analogues.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index bc66aba7079..800afe15e74 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -480,7 +480,7 @@ def q_catalan_number(n, m=1, q=None): sage: q_catalan_number(3,m=2) q^12 + q^10 + q^9 + q^8 + q^7 + 2*q^6 + q^5 + q^4 + q^3 + q^2 + 1 - TESTS:: + TESTS: The `q`-Catalan number of index `n` is only defined for `n` a nonnegative integer (:trac:`11411`):: From 0317ffc0f386939f5ae313922b54f5f7cc85ac07 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 11:57:32 -0700 Subject: [PATCH 126/225] sage.graphs: Fix # needs --- src/sage/graphs/distances_all_pairs.pyx | 4 +-- .../graphs/generators/distance_regular.pyx | 28 +++++++++++-------- src/sage/graphs/graph.py | 4 +-- src/sage/graphs/strongly_regular_db.pyx | 6 ++-- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 865a0cea140..362f9624854 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -2296,8 +2296,8 @@ def szeged_index(G, algorithm=None): Check that both algorithms return same value:: - sage: # long time - sage: G = graphs.RandomBarabasiAlbert(100, 2) # needs networkx + sage: # long time, needs networkx + sage: G = graphs.RandomBarabasiAlbert(100, 2) sage: a = szeged_index(G, algorithm='low') sage: b = szeged_index(G, algorithm='high') sage: a == b diff --git a/src/sage/graphs/generators/distance_regular.pyx b/src/sage/graphs/generators/distance_regular.pyx index 7a476b192dc..f05e4d714f7 100644 --- a/src/sage/graphs/generators/distance_regular.pyx +++ b/src/sage/graphs/generators/distance_regular.pyx @@ -359,9 +359,10 @@ def TruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.TruncatedWittGraph() # long time # needs sage.libs.pari sage.modules - sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules - ([15, 14, 12, None], [None, 1, 1, 9]) + sage: # long time, needs sage.libs.pari sage.modules + sage: G = graphs.TruncatedWittGraph() + sage: G.is_distance_regular(True) + ([15, 14, 12, None], [None, 1, 1, 9]) REFERENCES: @@ -388,9 +389,9 @@ def DoublyTruncatedWittGraph(): EXAMPLES:: - sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.libs.pari sage.modules - sage: G.is_distance_regular(True) # needs sage.libs.pari sage.modules - ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) + sage: G = graphs.DoublyTruncatedWittGraph() # needs sage.libs.pari sage.modules + sage: G.is_distance_regular(True) # needs sage.libs.pari sage.modules + ([7, 6, 4, 4, None], [None, 1, 1, 1, 6]) REFERENCES: @@ -411,8 +412,9 @@ def distance_3_doubly_truncated_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() # long time, needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time (due to above) # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.distance_3_doubly_truncated_Golay_code_graph() + sage: G.is_distance_regular(True) # long time (due to above) ([9, 8, 6, 3, None], [None, 1, 1, 3, 8]) ALGORITHM: @@ -446,8 +448,9 @@ def shortened_00_11_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # long time (9 s), needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.shortened_00_11_binary_Golay_code_graph() # 9 s + sage: G.is_distance_regular(True) ([21, 20, 16, 6, 2, 1, None], [None, 1, 2, 6, 16, 20, 21]) ALGORITHM: @@ -485,8 +488,9 @@ def shortened_000_111_extended_binary_Golay_code_graph(): EXAMPLES:: - sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # long time (25 s), needs sage.modules sage.rings.finite_rings - sage: G.is_distance_regular(True) # long time # needs sage.modules sage.rings.finite_rings + sage: # long time, needs sage.modules sage.rings.finite_rings + sage: G = graphs.shortened_000_111_extended_binary_Golay_code_graph() # 25 s + sage: G.is_distance_regular(True) ([21, 20, 16, 9, 2, 1, None], [None, 1, 2, 3, 16, 20, 21]) ALGORITHM: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index be302ca6043..a7bb3eb810a 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -5848,10 +5848,10 @@ def distance_graph(self, dist): The graph of eight-bit strings, adjacent if different in an odd number of bits:: - sage: # long time + sage: # long time, needs sage.symbolic sage: G = graphs.CubeGraph(8) sage: H = G.distance_graph([1,3,5,7]) - sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) # needs sage.symbolic + sage: degrees = [0]*sum([binomial(8,j) for j in [1,3,5,7]]) sage: degrees.append(2^8) sage: degrees == H.degree_histogram() True diff --git a/src/sage/graphs/strongly_regular_db.pyx b/src/sage/graphs/strongly_regular_db.pyx index a231927c4b4..2c3cecfeed5 100644 --- a/src/sage/graphs/strongly_regular_db.pyx +++ b/src/sage/graphs/strongly_regular_db.pyx @@ -1923,7 +1923,7 @@ def SRG_100_44_18_20(): sage: from sage.graphs.strongly_regular_db import SRG_100_44_18_20 sage: G = SRG_100_44_18_20() # long time # needs sage.groups - sage: G.is_strongly_regular(parameters=True) # long time + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (100, 44, 18, 20) """ L = ['100', '110', '130', '140', '200', '230', '240', '300', '310', '320', @@ -1945,7 +1945,7 @@ def SRG_100_45_20_20(): sage: from sage.graphs.strongly_regular_db import SRG_100_45_20_20 sage: G = SRG_100_45_20_20() # long time # needs sage.groups - sage: G.is_strongly_regular(parameters=True) # long time + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (100, 45, 20, 20) """ L = ['120', '140', '200', '210', '201', '401', '411', '321', '002', '012', @@ -2617,7 +2617,7 @@ def SRG_630_85_20_10(): sage: from sage.graphs.strongly_regular_db import SRG_630_85_20_10 sage: G = SRG_630_85_20_10() # long time # needs sage.groups - sage: G.is_strongly_regular(parameters=True) # long time + sage: G.is_strongly_regular(parameters=True) # long time # needs sage.groups (630, 85, 20, 10) """ from sage.graphs.generators.intersection import IntersectionGraph From 5660f1258ab641a491836359b8663e4ca11ec48f Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 12:02:37 -0700 Subject: [PATCH 127/225] src/sage/sandpiles/sandpile.py: Fix last doctest change --- src/sage/sandpiles/sandpile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index 979623da65a..83c11b4e4ce 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -2751,7 +2751,7 @@ def solve(self): EXAMPLES:: sage: S = Sandpile({0: {}, 1: {2: 2}, 2: {0: 4, 1: 1}}, 0) - sage: Z = S.solve() # needs sage.libs.singular + sage: Z = S.solve(); Z # needs sage.libs.singular [[-0.707107000000000 + 0.707107000000000*I, 0.707107000000000 - 0.707107000000000*I], [-0.707107000000000 - 0.707107000000000*I, From 94babfd4f579488b487a29fe0eefd36989528ccb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 12:24:56 -0700 Subject: [PATCH 128/225] sage.graphs: Add # needs --- src/sage/graphs/graph_latex.py | 2 +- src/sage/graphs/graph_plot_js.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index e495ca160a4..76db076502c 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.plot r""" LaTeX options for graphs diff --git a/src/sage/graphs/graph_plot_js.py b/src/sage/graphs/graph_plot_js.py index 3bcabb58152..f1045446d65 100644 --- a/src/sage/graphs/graph_plot_js.py +++ b/src/sage/graphs/graph_plot_js.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.plot r""" Graph plotting in Javascript with d3.js From 3af41ccd1b1a3abae08154ea32d6d9ec14a113ef Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 23 Sep 2023 12:32:28 -0700 Subject: [PATCH 129/225] src/sage/graphs/generators/families.py: More block tags, docstring cosmetics --- src/sage/graphs/generators/families.py | 50 ++++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index c03edd90945..85ea52a4571 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2205,11 +2205,11 @@ def LCFGraph(n, shift_list, repeats): INPUT: - - ``n`` - the number of nodes. + - ``n`` -- the number of nodes. - - ``shift_list`` - a list of integer shifts mod n. + - ``shift_list`` -- a list of integer shifts mod `n`. - - ``repeats`` - the number of times to repeat the + - ``repeats`` -- the number of times to repeat the process. @@ -3841,22 +3841,26 @@ def MathonPseudocyclicMergingGraph(M, t): sage: from sage.graphs.generators.families import MathonPseudocyclicMergingGraph as mer sage: from sage.graphs.generators.smallgraphs import _EllipticLinesProjectivePlaneScheme as ES - sage: G = mer(ES(3), 0) # long time # needs sage.libs.gap - sage: G.is_strongly_regular(parameters=True) # long time + + sage: # long time, needs sage.libs.gap + sage: G = mer(ES(3), 0) + sage: G.is_strongly_regular(parameters=True) (784, 243, 82, 72) - sage: G = mer(ES(3), 1) # long time # needs sage.libs.gap - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = mer(ES(3), 1) + sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) - sage: G = mer(ES(3), 2) # long time # needs sage.libs.gap - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = mer(ES(3), 2) + sage: G.is_strongly_regular(parameters=True) (784, 297, 116, 110) - sage: G = mer(ES(2), 2) # needs sage.libs.gap + sage: G = mer(ES(2), 2) Traceback (most recent call last): ... AssertionError... - sage: M = ES(3) # needs sage.libs.gap - sage: M = [M[1],M[0],M[2],M[3]] # needs sage.libs.gap - sage: G = mer(M, 2) # needs sage.libs.gap + + sage: # needs sage.libs.gap + sage: M = ES(3) + sage: M = [M[1],M[0],M[2],M[3]] + sage: G = mer(M, 2) Traceback (most recent call last): ... AssertionError... @@ -4114,27 +4118,27 @@ def MuzychukS6Graph(n, d, Phi='fixed', Sigma='fixed', verbose=False): INPUT: - - ``n`` (integer)-- a prime power + - ``n`` (integer) -- a prime power - - ``d`` (integer)-- must be odd if `n` is odd + - ``d`` (integer) -- must be odd if `n` is odd - ``Phi`` is an optional parameter of the construction; it must be either - - 'fixed'-- this will generate fixed default `\Phi_i`, for `i \in M`, or + - ``'fixed'`` -- this will generate fixed default `\Phi_i`, for `i \in M`, or - - 'random'-- `\Phi_i` are generated at random, or + - ``'random'`` -- `\Phi_i` are generated at random, or - - A dictionary describing the functions `\Phi_i`; for `i \in M`, - Phi[(i, T)] in `M`, for each edge T of `L` on `i`. - Also, each `\Phi_i` must be injective. + - A dictionary describing the functions `\Phi_i`; for `i \in M`, + Phi[(i, T)] in `M`, for each edge T of `L` on `i`. + Also, each `\Phi_i` must be injective. - ``Sigma`` is an optional parameter of the construction; it must be either - - 'fixed'-- this will generate a fixed default `\Sigma`, or + - ``'fixed'`` -- this will generate a fixed default `\Sigma`, or - - 'random'-- `\Sigma` is generated at random. + - ``'random'`` -- `\Sigma` is generated at random. - - ``verbose`` (Boolean)-- default is False. If True, print progress information + - ``verbose`` (Boolean) -- default is ``False``. If ``True``, print progress information .. SEEALSO:: From 46af4135e35f175e7ee3691f47c89ea33a7fb6f0 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 23 Sep 2023 16:47:56 -0400 Subject: [PATCH 130/225] src/sage/tests/cmdline.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/tests/cmdline.py | 98 ++++++++++++++------------------------- 1 file changed, 36 insertions(+), 62 deletions(-) diff --git a/src/sage/tests/cmdline.py b/src/sage/tests/cmdline.py index ad0c44aa274..5a4b78cd9fa 100644 --- a/src/sage/tests/cmdline.py +++ b/src/sage/tests/cmdline.py @@ -231,75 +231,49 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False Test ``sage-run`` on a Python file, both with an absolute and with a relative path:: - sage: dir = tmp_dir(); name = 'python_test_file.py' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("print(3^33)\n") - sage: F.close() - sage: (out, err, ret) = test_executable(["sage", fullname]) - sage: print(out) - 34 - sage: err - '' - sage: ret - 0 - sage: (out, err, ret) = test_executable(["sage", name], cwd=dir) - sage: print(out) - 34 - sage: err - '' - sage: ret - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: + ....: name = 'python_test_file.py' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("print(3^33)\n") + ....: test_executable(["sage", fullname]) + ....: test_executable(["sage", name], cwd=dir) + ('34\n', '', 0) + ('34\n', '', 0) The same as above, but now with a ``.sage`` file. This indirectly also tests the preparser:: - sage: dir = tmp_dir(); name = 'sage_test_file.sage' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("k. = GF(5^3); print(a^124)\n") - sage: F.close() - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", fullname]) - sage: print(out) # long time - 1 - sage: err # long time - '' - sage: ret # long time - 0 - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", name], cwd=dir) - sage: print(out) # long time - 1 - sage: err # long time - '' - sage: ret # long time - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: # long time + ....: name = 'sage_test_file.sage' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("k. = GF(5^3); print(a^124)\n") + ....: test_executable(["sage", fullname]) + ....: test_executable(["sage", name], cwd=dir) + ('1\n', '', 0) + ('1\n', '', 0) Test running a ``.spyx`` file:: - sage: dir = tmp_dir(); name = 'sage_test_file.spyx' - sage: fullname = os.path.join(dir, name) - sage: F = open(fullname, 'w') - sage: _ = F.write("from cysignals.signals cimport *\nfrom sage.rings.integer cimport Integer\ncdef long i, s = 0\nsig_on()\nfor i in range(1000): s += i\nsig_off()\nprint(Integer(s))") - sage: F.close() - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", fullname], pydebug_ignore_warnings=True) - sage: print(out) # long time - 499500 - sage: import re # long time - sage: bool(re.match('Compiling.*spyx.*', err)) # long time - True - sage: ret # long time - 0 - sage: (out, err, ret) = test_executable([ # long time - ....: "sage", name], cwd=dir, pydebug_ignore_warnings=True) - sage: print(out) # long time - 499500 - sage: bool(re.match('Compiling.*spyx.*', err)) # long time - True - sage: ret # long time - 0 + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as dir: # long time + ....: name = 'sage_test_file.spyx' + ....: fullname = os.path.join(dir, name) + ....: with open(fullname, 'w') as F: + ....: _ = F.write("from cysignals.signals cimport *\n") + ....: _ = F.write("from sage.rings.integer cimport Integer\n") + ....: _ = F.write("cdef long i, s = 0\n") + ....: _ = F.write("sig_on()\n") + ....: _ = F.write("for i in range(5): s += i\n") + ....: _ = F.write("sig_off()\n") + ....: _ = F.write("print(Integer(s))") + ....: test_executable(["sage", fullname], pydebug_ignore_warnings=True) + ....: test_executable(["sage", name], cwd=dir, pydebug_ignore_warnings=True) + ('10\n', 'Compiling .../sage_test_file.spyx...\n', 0) + ('10\n', 'Compiling sage_test_file.spyx...\n', 0) Testing ``sage --preparse FILE`` and ``sage -t FILE``. First create a file and preparse it:: From dac31c8ad7a0bba861eefffb99733b3d3798e09c Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 20 Sep 2023 20:25:57 -0700 Subject: [PATCH 131/225] Give mod 2 homology the structure of a module over the Steenrod algebra. This uses the module structure on cohomology together with vector space dualization to put a module structure on homology. While Sq^n increases dimension in cohomology by n, it lowers homological degree by n. Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/homology/homology_vector_space_with_basis.py Co-authored-by: Travis Scrimshaw Update src/sage/topology/cell_complex.py Co-authored-by: Travis Scrimshaw --- .../homology_vector_space_with_basis.py | 41 +++++++++---------- src/sage/topology/cell_complex.py | 4 +- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index a319eef50d6..632f9631052 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -444,15 +444,13 @@ def _test_duality(self, **options): sage: simplicial_complexes.RandomComplex(12, 3, .5).homology_with_basis(GF(2))._test_duality() # long time """ - okay = True + tester = self._tester(**options)) dual = self.dual() dims = [a[0] for a in self._indices] - for dim in range(max(dims) + 1): + for dim in range(max(max(dims), tester._max_runs) + 1): n = len(self.basis(dim)) m = matrix(n, n, [a.eval(b) for a in self.basis(dim) for b in dual.basis(dim)]) - okay = (m == 1) - if not okay: - print('error in dimension {}'.format(dim)) + tester.assertEqual(m, 1,f "error in dimension {dim}") class Element(CombinatorialFreeModule.Element): def to_cycle(self): @@ -488,10 +486,10 @@ def eval(self, other): INPUT: - - ``other`` -- an element of the dual space: if ``self`` + - ``other`` -- an element of the dual space; if ``self`` is an element of cohomology in dimension `n`, then ``other`` should be an element of homology in dimension - `n`, and vice versa. + `n`, and vice versa This just calls the :meth:`~sage.homology.chains.Cochains.Element.eval` method on the representing chains and cochains. @@ -523,6 +521,7 @@ def eval(self, other): else: return other.to_cycle().eval(self.to_cycle()) + class HomologyVectorSpaceWithBasis_mod2(HomologyVectorSpaceWithBasis): r""" Homology vector space mod 2. @@ -594,7 +593,7 @@ def __init__(self, base_ring, cell_complex, category=None): if base_ring != GF(2): raise ValueError category = Modules(base_ring).WithBasis().Graded().FiniteDimensional().or_subcategory(category) - category = Category.join((category, + category = Category.join((category, LeftModules(SteenrodAlgebra(2)), RightModules(SteenrodAlgebra(2)))) HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, @@ -691,11 +690,10 @@ def _acted_upon_(self, a, self_on_left): if m <= n: return self.parent().zero() - vec = [] - for x in sorted(self.parent().dual().basis(m-n)): - vec.append(self.eval(a * x)) - B = list(self.parent().basis(m-n)) - return self.parent().linear_combination(zip(B, vec)) + P = self.parent() + B = list(P.basis(m-n)) + return P._from_dict({b.support()[0]: self.eval(a * x) + for x in sorted(self.parent().dual().basis(m-n))}) class CohomologyRing(HomologyVectorSpaceWithBasis): @@ -1019,9 +1017,9 @@ def __init__(self, base_ring, cell_complex): sage: TestSuite(H).run() """ if base_ring != GF(2): - raise ValueError + raise ValueError("the base ring must be GF(2)") category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() - category = Category.join((category, + category = Category.join((category, LeftModules(SteenrodAlgebra(2)), RightModules(SteenrodAlgebra(2)))) CohomologyRing.__init__(self, base_ring, cell_complex, category=category) @@ -1277,12 +1275,11 @@ def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): - ``deg_codomain`` -- the degree of the codomain in the cohomology ring - - ``side`` (optional, default ``'left'``) -- are we computing - the action as a left module action or a right module? (This - documentation is written from the point of view of a left - action for brevity. Just switch all of the tensors for the - right action.) + - ``side`` default ``'left'``) -- whether we are computing + the action as a left module action or a right module + We will write this with respect to the left action; + for the right action, just switch all of the the tensors. Writing `m` for ``deg_domain`` and `n` for ``deg_codomain``, this returns `A^{n-m} \otimes H^{m} \to H^{n}`, one single component of the map making `H` into an `A`-module. @@ -1296,7 +1293,9 @@ def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): computations may be slow. There is no implementation for `\Delta`-complexes. - Algorithm: use the Milnor basis for the truncated Steenrod + ALGORITHM: + + Use the Milnor basis for the truncated Steenrod algebra `A`, and for cohomology, use the basis with which it is equipped. For each pair of basis elements `a` and `h`, compute the product `a \otimes h`, and use this to assemble a diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 2002c9f6b89..57401fdcfc6 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -867,9 +867,9 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): """ from sage.homology.homology_vector_space_with_basis import \ HomologyVectorSpaceWithBasis, HomologyVectorSpaceWithBasis_mod2 + if cohomology: + return self.cohomology_ring(base_ring) if base_ring == GF(2): - if cohomology: - return self.cohomology_ring(base_ring) return HomologyVectorSpaceWithBasis_mod2(base_ring, self) return HomologyVectorSpaceWithBasis(base_ring, self, cohomology) From 3386b9771da01f0be07d4399144a7f4614c03a76 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 22 Sep 2023 19:08:36 -0700 Subject: [PATCH 132/225] tidying up reviewer changes, adding a few other small fixes --- .../homology_vector_space_with_basis.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 632f9631052..503da8e6a90 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -444,13 +444,13 @@ def _test_duality(self, **options): sage: simplicial_complexes.RandomComplex(12, 3, .5).homology_with_basis(GF(2))._test_duality() # long time """ - tester = self._tester(**options)) + tester = self._tester(**options) dual = self.dual() dims = [a[0] for a in self._indices] for dim in range(max(max(dims), tester._max_runs) + 1): n = len(self.basis(dim)) m = matrix(n, n, [a.eval(b) for a in self.basis(dim) for b in dual.basis(dim)]) - tester.assertEqual(m, 1,f "error in dimension {dim}") + tester.assertEqual(m, 1, f"error in dimension {dim}") class Element(CombinatorialFreeModule.Element): def to_cycle(self): @@ -596,7 +596,8 @@ def __init__(self, base_ring, cell_complex, category=None): category = Category.join((category, LeftModules(SteenrodAlgebra(2)), RightModules(SteenrodAlgebra(2)))) - HomologyVectorSpaceWithBasis.__init__(self, base_ring, cell_complex, + HomologyVectorSpaceWithBasis.__init__(self, base_ring, + cell_complex, cohomology=False, category=category) @@ -681,18 +682,17 @@ def _acted_upon_(self, a, self_on_left): """ # Handle field elements first. if a in self.base_ring(): - return self.map_coefficients(lambda c: c*a) - if not self_on_left: # i.e., module element on left - a = a.antipode() - + return a * self m = self.degree() n = a.degree() if m <= n: return self.parent().zero() + if not self_on_left: # i.e., module element on left + a = a.antipode() P = self.parent() B = list(P.basis(m-n)) - return P._from_dict({b.support()[0]: self.eval(a * x) + return P._from_dict({x.support()[0]: self.eval(a * x) for x in sorted(self.parent().dual().basis(m-n))}) @@ -960,7 +960,6 @@ class CohomologyRing_mod2(CohomologyRing): - ``base_ring`` -- must be the field ``GF(2)`` - ``cell_complex`` -- the cell complex whose homology we are computing - - ``category`` -- (optional) a subcategory of modules with basis EXAMPLES: From e0aaa04d603839a659cb202175128a9aca06ae98 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 25 Sep 2023 13:11:39 -0700 Subject: [PATCH 133/225] Detect whether the base ring is GF(2) in a consistent and robust way. --- .../homology_vector_space_with_basis.py | 27 +++++++++++++++---- src/sage/topology/cell_complex.py | 13 +++++---- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 503da8e6a90..912de6c4f55 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -410,7 +410,7 @@ def dual(self): sage: coh.dual() is hom True """ - if self.base_ring() == GF(2): + if is_GF2(self.base_ring()): if self._cohomology: return HomologyVectorSpaceWithBasis_mod2(self.base_ring(), self.complex()) @@ -590,7 +590,7 @@ def __init__(self, base_ring, cell_complex, category=None): sage: H = simplicial_complexes.Sphere(3).homology_with_basis(GF(2)) sage: TestSuite(H).run() """ - if base_ring != GF(2): + if not is_GF2(base_ring): raise ValueError category = Modules(base_ring).WithBasis().Graded().FiniteDimensional().or_subcategory(category) category = Category.join((category, @@ -641,7 +641,7 @@ def _acted_upon_(self, a, self_on_left): .. MATH:: - (f \cdot a) (x) = f (a \cdot x) + (f \cdot a) (x) = f (a \cdot x). So given `f` (a.k.a. ``self``) and `a`, we compute `f (a \cdot x)` for all basis elements `x` in `H^{m-n}`, @@ -1015,7 +1015,7 @@ def __init__(self, base_ring, cell_complex): sage: H = RP2.cohomology_ring(GF(2)) sage: TestSuite(H).run() """ - if base_ring != GF(2): + if not is_GF2(base_ring): raise ValueError("the base ring must be GF(2)") category = Algebras(base_ring).WithBasis().Graded().FiniteDimensional() category = Category.join((category, @@ -1105,11 +1105,12 @@ def Sq(self, i): P = scomplex.cohomology_ring(self.base_ring()) self = P.sum_of_terms(self.monomial_coefficients().items()) if not isinstance(scomplex, (SimplicialComplex, SimplicialSet_arbitrary)): + print(scomplex, isinstance(scomplex, SimplicialComplex)) raise NotImplementedError('Steenrod squares are not implemented for ' 'this type of cell complex') scomplex = P.complex() base_ring = P.base_ring() - if base_ring.characteristic() != 2: + if not is_GF2(base_ring): # This should never happen: the class should only be # instantiated in characteristic 2. raise ValueError('Steenrod squares are only defined in characteristic 2') @@ -1428,3 +1429,19 @@ def sum_indices(k, i_k_plus_one, S_k_plus_one): return [[S_k]] return [[i_k] + l for i_k in range(S_k, i_k_plus_one) for l in sum_indices(k-1, i_k, S_k)] + +def is_GF2(R): + """ + Return ``True`` iff ``R`` is isomorphic to the field GF(2). + + EXAMPLES:: + + sage: from sage.homology.homology_vector_space_with_basis import is_GF2 + sage: is_GF2(GF(2)) + True + sage: is_GF2(GF(2, impl='ntl')) + True + sage: is_GF2(GF(3)) + False + """ + return 2 == R.cardinality() == R.characteristic() diff --git a/src/sage/topology/cell_complex.py b/src/sage/topology/cell_complex.py index 57401fdcfc6..2f5abd5fc2b 100644 --- a/src/sage/topology/cell_complex.py +++ b/src/sage/topology/cell_complex.py @@ -47,7 +47,6 @@ from sage.structure.sage_object import SageObject from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.rings.finite_rings.finite_field_constructor import GF from sage.misc.abstract_method import abstract_method @@ -866,10 +865,12 @@ def homology_with_basis(self, base_ring=QQ, cohomology=False): [h^{3,0}] """ from sage.homology.homology_vector_space_with_basis import \ - HomologyVectorSpaceWithBasis, HomologyVectorSpaceWithBasis_mod2 + HomologyVectorSpaceWithBasis, HomologyVectorSpaceWithBasis_mod2, \ + is_GF2 + if cohomology: return self.cohomology_ring(base_ring) - if base_ring == GF(2): + if is_GF2(base_ring): return HomologyVectorSpaceWithBasis_mod2(base_ring, self) return HomologyVectorSpaceWithBasis(base_ring, self, cohomology) @@ -977,8 +978,10 @@ def cohomology_ring(self, base_ring=QQ): Cohomology ring of Simplicial complex with 9 vertices and 18 facets over Rational Field """ - from sage.homology.homology_vector_space_with_basis import CohomologyRing, CohomologyRing_mod2 - if base_ring == GF(2): + from sage.homology.homology_vector_space_with_basis import CohomologyRing, \ + CohomologyRing_mod2, is_GF2 + + if is_GF2(base_ring): return CohomologyRing_mod2(base_ring, self) return CohomologyRing(base_ring, self) From 659a9b2bce5d8efb873b4b0afc438890f026194c Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 25 Sep 2023 13:29:59 -0700 Subject: [PATCH 134/225] Improve handling of multiplication by field elements --- .../homology_vector_space_with_basis.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 912de6c4f55..ee946987e35 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -36,7 +36,6 @@ from sage.combinat.free_module import CombinatorialFreeModule from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector -from sage.rings.finite_rings.finite_field_constructor import GF from sage.sets.family import Family try: @@ -679,10 +678,15 @@ def _acted_upon_(self, a, self_on_left): True sage: x4 * (Sq(2) * Sq(1)) == (x4 * Sq(2)) * Sq(1) True + sage: 1 * x4 + h_{4,0} + sage: x4 * 0 + 0 """ # Handle field elements first. - if a in self.base_ring(): - return a * self + ret = CombinatorialFreeModule.Element._acted_upon_(self, a, self_on_left) + if ret is not None: # did the scalar action + return ret m = self.degree() n = a.degree() if m <= n: @@ -1245,10 +1249,15 @@ def _acted_upon_(self, a, self_on_left): True sage: x * (Sq(1) * Sq(2)) == (x * Sq(1)) * Sq(2) True + sage: x * 1 + h^{2,0} + sage: 0 * x + 0 """ # Handle field elements first. - if a in self.base_ring(): - return self.map_coefficients(lambda c: c*a) + ret = CombinatorialFreeModule.Element._acted_upon_(self, a, self_on_left) + if ret is not None: # did the scalar action + return ret if self_on_left: # i.e., module element on left a = a.antipode() b = a.change_basis('adem') From 0e03d70832bd87b6880126304165aa98a0094901 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 25 Sep 2023 13:55:28 -0700 Subject: [PATCH 135/225] "R.characteristic()" should be a tiny bit faster than "R.cardinality()" --- src/sage/homology/homology_vector_space_with_basis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index ee946987e35..542f2d5873b 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -1453,4 +1453,4 @@ def is_GF2(R): sage: is_GF2(GF(3)) False """ - return 2 == R.cardinality() == R.characteristic() + return 2 == R.characteristic() == R.cardinality() From bdb573be454a0eff26a368f7dcc37659d53d2c25 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 22 Sep 2023 20:13:09 -0400 Subject: [PATCH 136/225] src/sage/repl/interpreter.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/repl/interpreter.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py index c8fd27b35fa..b9a222c12ef 100644 --- a/src/sage/repl/interpreter.py +++ b/src/sage/repl/interpreter.py @@ -777,14 +777,14 @@ def load_config_file(self, *args, **kwds): Test that :trac:`15972` has been fixed:: - sage: from sage.misc.temporary_file import tmp_dir + sage: import tempfile sage: from sage.repl.interpreter import SageTerminalApp - sage: d = tmp_dir() sage: from IPython.paths import get_ipython_dir - sage: IPYTHONDIR = get_ipython_dir() - sage: os.environ['IPYTHONDIR'] = d - sage: SageTerminalApp().load_config_file() - sage: os.environ['IPYTHONDIR'] = IPYTHONDIR + sage: with tempfile.TemporaryDirectory() as d: + ....: IPYTHONDIR = get_ipython_dir() + ....: os.environ['IPYTHONDIR'] = d + ....: SageTerminalApp().load_config_file() + ....: os.environ['IPYTHONDIR'] = IPYTHONDIR """ super().load_config_file(*args, **kwds) newconfig = sage_ipython_config.default() From ff832cc731bec6565e4ee6623e554d1150fd6b5a Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 23 Sep 2023 16:57:27 -0400 Subject: [PATCH 137/225] src/sage/misc/cython.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/misc/cython.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 5f83f585c3a..fecf8f978bd 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -157,24 +157,31 @@ def cython(filename, verbose=0, compile_message=False, first moving to a tempdir to avoid clutter. Before :trac:`22113`, the create_local_c_file argument was not tested for C++ code:: - sage: d = sage.misc.temporary_file.tmp_dir() - sage: os.chdir(d) - sage: with open("test.pyx", 'w') as f: - ....: _ = f.write("# distutils: language = c++\n" - ....: "from libcpp.vector cimport vector\n" - ....: "cdef vector[int] * v = new vector[int](4)\n") - sage: output = sage.misc.cython.cython("test.pyx", create_local_c_file=True) + sage: orig_cwd = os.getcwd() + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: os.chdir(d) + ....: with open("test.pyx", 'w') as f: + ....: _ = f.write("# distutils: language = c++\n" + ....: "from libcpp.vector cimport vector\n" + ....: "cdef vector[int] * v = new vector[int](4)\n") + ....: output = sage.misc.cython.cython("test.pyx", + ....: create_local_c_file=True) + ....: os.chdir(orig_cwd) Accessing a ``.pxd`` file from the current directory works:: - sage: d = sage.misc.temporary_file.tmp_dir() - sage: os.chdir(d) - sage: with open("helper.pxd", 'w') as f: - ....: _ = f.write("cdef inline int the_answer(): return 42") - sage: cython(''' - ....: from helper cimport the_answer - ....: print(the_answer()) - ....: ''') + sage: orig_cwd = os.getcwd() + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: os.chdir(d) + ....: with open("helper.pxd", 'w') as f: + ....: _ = f.write("cdef inline int the_answer(): return 42") + ....: cython( + ....: "from helper cimport the_answer\n" + ....: "print(the_answer())" + ....: ) + ....: os.chdir(orig_cwd) 42 Warning and error messages generated by Cython are properly From 97d6f4bd4a6c993b32b23d5cb64c6c837bdcce7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 27 Sep 2023 08:57:32 +0200 Subject: [PATCH 138/225] swap parameters for backward compatibility --- src/sage/combinat/q_analogues.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index 800afe15e74..1f873e4a5b4 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -451,16 +451,16 @@ def q_multinomial(seq, q=None, binomial_algorithm='auto'): gaussian_multinomial = q_multinomial -def q_catalan_number(n, m=1, q=None): +def q_catalan_number(n, q=None, m=1): """ Return the `q`-Catalan number of index `n`. INPUT: - - ``m`` -- optional integer (default: 1) to get the ``m``-Fuss-Catalan numbers - - ``q`` -- optional variable + - ``m`` -- optional integer (default: 1) to get the ``m``-Fuss-Catalan numbers + If `q` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. @@ -474,10 +474,10 @@ def q_catalan_number(n, m=1, q=None): q^12 + q^10 + q^9 + 2*q^8 + q^7 + 2*q^6 + q^5 + 2*q^4 + q^3 + q^2 + 1 sage: p = ZZ['p'].0 - sage: q_catalan_number(4,q=p) + sage: q_catalan_number(4, p) p^12 + p^10 + p^9 + 2*p^8 + p^7 + 2*p^6 + p^5 + 2*p^4 + p^3 + p^2 + 1 - sage: q_catalan_number(3,m=2) + sage: q_catalan_number(3, m=2) q^12 + q^10 + q^9 + q^8 + q^7 + 2*q^6 + q^5 + q^4 + q^3 + q^2 + 1 TESTS: From 81996bb0514b1fcf19567f811887b89e7e68b9bf Mon Sep 17 00:00:00 2001 From: Lorenz Panny Date: Tue, 26 Sep 2023 09:49:26 +0200 Subject: [PATCH 139/225] make some implicit assumptions in BMSS code explicit --- .../schemes/elliptic_curves/ell_curve_isogeny.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index f4cb69f9b9b..eb4de1d8190 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -3334,6 +3334,9 @@ def compute_isogeny_bmss(E1, E2, l): Compute the kernel polynomial of the unique normalized isogeny of degree ``l`` between ``E1`` and ``E2``. + Both curves must be given in short Weierstrass form, and the + characteristic must be either `0` or no smaller than `4l+4`. + ALGORITHM: [BMSS2006]_, algorithm *fastElkies'*. EXAMPLES:: @@ -3348,6 +3351,13 @@ def compute_isogeny_bmss(E1, E2, l): # https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/isogeny_weber/isogenies.py#L272-L332 # Released under the MIT license: https://github.com/remyoudompheng/isogeny_weber/blob/64289127a337ac1bf258b711e02fea02b7df5275/LICENSE # Slightly adjusted for inclusion in the Sage library. + if E1.a1() or E1.a2() or E1.a3(): + raise ValueError('E1 must be a short Weierstrass curve') + if E2.a1() or E2.a2() or E2.a3(): + raise ValueError('E2 must be a short Weierstrass curve') + char = E1.base_ring().characteristic() + if char != 0 and char < 4*l + 4: + raise ValueError('characteristic must be at least 4*degree+4') Rx, x = E1.base_ring()["x"].objgen() # Compute C = 1/(1 + Ax^4 + Bx^6) mod x^4l A, B = E1.a4(), E1.a6() @@ -3577,12 +3587,18 @@ def compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm=None): from sage.misc.superseded import deprecation deprecation(34871, 'The "starks" algorithm is being renamed to "stark".') algorithm = 'stark' + if algorithm is None: + char = E1.base_ring().characteristic() + if char != 0 and char < 4*ell + 4: + raise NotImplementedError(f'no algorithm for computing kernel polynomial from domain and codomain is implemented for degree {ell} and characteristic {char}') algorithm = 'stark' if ell < 10 else 'bmss' + if algorithm == 'bmss': return compute_isogeny_bmss(E1, E2, ell) if algorithm == 'stark': return compute_isogeny_stark(E1, E2, ell).radical() + raise NotImplementedError(f'unknown algorithm {algorithm}') def compute_intermediate_curves(E1, E2): From a436b1fe78a8d71d80f00be17a1066100f858595 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 25 Mar 2023 14:19:53 -0700 Subject: [PATCH 140/225] .github/workflows/doc-build-pdf.yml: Update from doc-build.yml, change container --- .github/workflows/doc-build-pdf.yml | 116 +++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 12 deletions(-) diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 6eacba7fe52..26e09589506 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -5,6 +5,15 @@ on: push: workflow_dispatch: # Allow to run manually + inputs: + platform: + description: 'Platform' + required: true + default: 'ubuntu-focal-standard' + docker_tag: + description: 'Docker tag' + required: true + default: 'dev' concurrency: # Cancel previous runs of this workflow for the same branch @@ -12,36 +21,118 @@ concurrency: cancel-in-progress: true jobs: - build-docs: + get_ci_fixes: runs-on: ubuntu-latest - # Use "maximal" so that texlive is installed - # Use "fedora-31" for build diversity - container: ghcr.io/sagemath/sage/sage-docker-fedora-31-maximal-with-targets:dev steps: - name: Checkout + id: checkout uses: actions/checkout@v4 - - name: Merge CI fixes from sagemath/sage run: | .ci/merge-fixes.sh env: GH_TOKEN: ${{ github.token }} + - name: Store CI fixes in upstream artifact + run: | + mkdir -p upstream + git format-patch --stdout test_base > upstream/ci_fixes.patch + - uses: actions/upload-artifact@v2 + with: + path: upstream + name: upstream - - name: Prepare + build-docs-pdf: + runs-on: ubuntu-latest + container: ghcr.io/sagemath/sage/sage-${{ github.event.inputs.platform || 'ubuntu-focal-standard' }}-with-targets:${{ github.event.inputs.docker_tag || 'dev'}} + needs: [get_ci_fixes] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Update system packages + run: | + export PATH="build/bin:$PATH" + eval $(sage-print-system-package-command auto update) + eval $(sage-print-system-package-command auto --yes --no-install-recommends install zip) + eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git texlive) + + + - name: Add prebuilt tree as a worktree + id: worktree run: | - apt-get update && apt-get install -y zip - # Reuse built SAGE_LOCAL contained in the Docker image - ./bootstrap - ./configure --enable-build-as-root --prefix=/sage/local --with-sage-venv --enable-download-from-upstream-url + set -ex + git config --global user.email "ci-sage@example.com" + git config --global user.name "Build & Test workflow" + git config --global --add safe.directory $(pwd) + # If actions/checkout downloaded our source tree using the GitHub REST API + # instead of with git (because do not have git installed in our image), + # we first make the source tree a repo. + if [ ! -d .git ]; then git init && git add -A && git commit --quiet -m "new"; fi + # Tag this state of the source tree "new". This is what we want to build and test. + git tag -f new + # Our container image contains a source tree in /sage with a full build of Sage. + # But /sage is not a git repository. + # We make /sage a worktree whose index is at tag "new". + # We then commit the current sources and set the tag "old". (This keeps all mtimes unchanged.) + # Then we update worktree and index with "git reset --hard new". + # (This keeps mtimes of unchanged files unchanged and mtimes of changed files newer than unchanged files.) + # Finally we reset the index to "old". (This keeps all mtimes unchanged.) + # The changed files now show up as uncommitted changes. + # The final "git add -N" makes sure that files that were added in "new" do not show + # as untracked files, which would be removed by "git clean -fx". + git worktree add --detach worktree-image + rm -rf /sage/.git && mv worktree-image/.git /sage/ + rm -rf worktree-image && ln -s /sage worktree-image + if [ ! -f worktree-image/.gitignore ]; then cp .gitignore worktree-image/; fi + (cd worktree-image && git add -A && git commit --quiet --allow-empty -m "old" -a && git tag -f old && git reset --hard new && git reset --quiet old && git add -N . && git status) + # Keep track of changes to built HTML + new_version=$(cat src/VERSION.txt); (cd /sage/local/share/doc/sage/html/en && find . -name "*.html" | xargs sed -i '/class="sidebar-brand-text"/s/Sage [0-9a-z.]* /Sage '$new_version' /'; git init && (echo "*.svg binary"; echo "*.pdf binary") >> .gitattributes && (echo ".buildinfo"; echo '*.inv'; echo '.git*'; echo '*.svg'; echo '*.pdf'; echo '*.png'; echo 'searchindex.js') > .gitignore; git add -A && git commit --quiet -m "old") + + - name: Download upstream artifact + uses: actions/download-artifact@v3 + with: + path: upstream + name: upstream + + - name: Apply CI fixes from sagemath/sage + # After applying the fixes, make sure all changes are marked as uncommitted changes. + run: | + if [ -r upstream/ci_fixes.patch ]; then + (cd worktree-image && git commit -q -m "current changes" --allow-empty -a && git am; git reset --quiet old; git add -N .) < upstream/ci_fixes.patch + fi + + - name: Incremental build + id: incremental + run: | + # Now re-bootstrap and build. The build is incremental because we were careful with the timestamps. + ./bootstrap && make build + working-directory: ./worktree-image + env: + MAKE: make -j2 + SAGE_NUM_THREADS: 2 + + - name: Build (fallback to non-incremental) + id: build + if: always() && steps.worktree.outcome == 'success' && steps.incremental.outcome != 'success' + run: | + set -ex + make doc-clean doc-uninstall sagelib-clean && git clean -fx src/sage && ./config.status && make build + working-directory: ./worktree-image + env: + MAKE: make -j2 + SAGE_NUM_THREADS: 2 - - name: Build + - name: Build docs (PDF) + id: docbuild + if: always() && (steps.incremental.outcome == 'success' || steps.build.outcome == 'success') run: make build V=0 && make doc-pdf + working-directory: ./worktree-image env: MAKE: make -j2 SAGE_NUM_THREADS: 2 - TEXMFHOME: /sage/texmf - name: Copy docs + if: always() && steps.docbuild.outcome == 'success' run: | # For some reason the deploy step below cannot find /sage/... # So copy everything from there to local folder @@ -51,6 +142,7 @@ jobs: zip -r docs-pdf.zip docs - name: Upload docs + if: always() && steps.copy.outcome == 'success' uses: actions/upload-artifact@v3 with: name: docs-pdf From 9b01611835feb68c4d1be59bcc94a223a99c78fa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 26 Sep 2023 15:09:16 -0700 Subject: [PATCH 141/225] .github/workflows/doc-build-pdf.yml: Use actions/upload-artifact@v3 --- .github/workflows/doc-build-pdf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 26e09589506..653e2a62b4c 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -36,7 +36,7 @@ jobs: run: | mkdir -p upstream git format-patch --stdout test_base > upstream/ci_fixes.patch - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: path: upstream name: upstream From 2d27dd6fdbed9c6ad792ca94424255b992cda2bb Mon Sep 17 00:00:00 2001 From: Vincent Delecroix Date: Sun, 3 Sep 2023 23:06:45 +0200 Subject: [PATCH 142/225] Upgrade pplpy to 0.8.9 --- build/pkgs/pplpy/checksums.ini | 6 +++--- build/pkgs/pplpy/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pplpy/checksums.ini b/build/pkgs/pplpy/checksums.ini index 22961af9a1f..73f16fc3f00 100644 --- a/build/pkgs/pplpy/checksums.ini +++ b/build/pkgs/pplpy/checksums.ini @@ -1,5 +1,5 @@ tarball=pplpy-VERSION.tar.gz -sha1=9f0d531d77dab19f1f0f350022687a8bd749aee2 -md5=980223c38fc95b2f4f8265f20b45a98e -cksum=3147352163 +sha1=dc9e8a7a867ee1c066bdbecf22b6a59dc2052711 +md5=220fc7ab95d7bd62d40acb276f9b149f +cksum=2156962833 upstream_url=https://pypi.io/packages/source/p/pplpy/pplpy-VERSION.tar.gz diff --git a/build/pkgs/pplpy/package-version.txt b/build/pkgs/pplpy/package-version.txt index 1e9b46b2298..55485e17937 100644 --- a/build/pkgs/pplpy/package-version.txt +++ b/build/pkgs/pplpy/package-version.txt @@ -1 +1 @@ -0.8.7 +0.8.9 From c22728a5c97a509997e319099b15adacaee7bfb8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 16:25:08 -0700 Subject: [PATCH 143/225] build/pkgs/pplpy/patches/cython3-legacy.patch: Remove --- build/pkgs/pplpy/patches/cython3-legacy.patch | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 build/pkgs/pplpy/patches/cython3-legacy.patch diff --git a/build/pkgs/pplpy/patches/cython3-legacy.patch b/build/pkgs/pplpy/patches/cython3-legacy.patch deleted file mode 100644 index a038da16d6b..00000000000 --- a/build/pkgs/pplpy/patches/cython3-legacy.patch +++ /dev/null @@ -1,22 +0,0 @@ -commit e6f3e66154138ce3e31e803e74b8c71787c70acc -Author: Gonzalo Tornaría -Date: Wed Jul 19 20:47:52 2023 -0300 - - cython3 support using legacy directives - -diff --git a/setup.py b/setup.py -index 13d543b..55dcd34 100755 ---- a/setup.py -+++ b/setup.py -@@ -38,7 +38,11 @@ class build_ext(_build_ext): - self.extensions[:] = cythonize( - self.extensions, - include_path=sys.path, -- compiler_directives={'embedsignature': True}) -+ compiler_directives={ -+ 'embedsignature': True, -+ 'legacy_implicit_noexcept': True, -+ 'c_api_binop_methods': True, -+ }) - - _build_ext.run(self) From 525dedd68f8b995aade17d3644a48578e5e29413 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 16:33:24 -0700 Subject: [PATCH 144/225] build/pkgs/pplpy/patches/relative-import.patch: Remove --- .../pkgs/pplpy/patches/relative-import.patch | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 build/pkgs/pplpy/patches/relative-import.patch diff --git a/build/pkgs/pplpy/patches/relative-import.patch b/build/pkgs/pplpy/patches/relative-import.patch deleted file mode 100644 index 3c011203367..00000000000 --- a/build/pkgs/pplpy/patches/relative-import.patch +++ /dev/null @@ -1,21 +0,0 @@ -From aaa28537fa7ea061ebb8d5131b1e23673eaf741d Mon Sep 17 00:00:00 2001 -From: Matthias Koeppe -Date: Sun, 31 Jul 2022 12:39:34 -0700 -Subject: [PATCH] ppl/bit_arrays.pxd: Use relative cimport - ---- - ppl/bit_arrays.pxd | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ppl/bit_arrays.pxd b/ppl/bit_arrays.pxd -index eb57434..145a978 100644 ---- a/ppl/bit_arrays.pxd -+++ b/ppl/bit_arrays.pxd -@@ -1,4 +1,4 @@ --from ppl_decl cimport * -+from .ppl_decl cimport * - - cdef class Bit_Row(object): - cdef PPL_Bit_Row *thisptr --- -GitLab From c5599a3b05c26a34506fd154cc056ea979cabd02 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 16:41:57 -0700 Subject: [PATCH 145/225] .github/workflows/build.yml, doc-build.yml: Fix get_ci_fixes when there are no fixes --- .github/workflows/build.yml | 4 +++- .github/workflows/doc-build.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f8b6b52a890..5d2df419891 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,9 @@ jobs: - name: Store CI fixes in upstream artifact run: | mkdir -p upstream - git format-patch --stdout test_base > upstream/ci_fixes.patch + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi - uses: actions/upload-artifact@v3 with: path: upstream diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 04ccb2b28fe..c7f4eb3aaeb 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -26,7 +26,9 @@ jobs: - name: Store CI fixes in upstream artifact run: | mkdir -p upstream - git format-patch --stdout test_base > upstream/ci_fixes.patch + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi - uses: actions/upload-artifact@v3 with: path: upstream From 7565e0c82d6f3c432df00a2e5c333b9c049dc24d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 16:51:07 -0700 Subject: [PATCH 146/225] .github/workflows/doc-build-pdf.yml: Fix get_ci_fixes when there are no fixes --- .github/workflows/doc-build-pdf.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/doc-build-pdf.yml b/.github/workflows/doc-build-pdf.yml index 653e2a62b4c..0413954210b 100644 --- a/.github/workflows/doc-build-pdf.yml +++ b/.github/workflows/doc-build-pdf.yml @@ -35,7 +35,9 @@ jobs: - name: Store CI fixes in upstream artifact run: | mkdir -p upstream - git format-patch --stdout test_base > upstream/ci_fixes.patch + if git format-patch --stdout test_base > ci_fixes.patch; then + cp ci_fixes.patch upstream/ + fi - uses: actions/upload-artifact@v3 with: path: upstream From a6aa117a60a0ca26c33268df40904eed43a0a8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 28 Sep 2023 08:31:02 +0200 Subject: [PATCH 147/225] fix E228 and E225 in coding,crypto,dynamics,geometry,manifolds,modular --- src/sage/coding/code_bounds.py | 10 +-- src/sage/coding/code_constructions.py | 6 +- src/sage/coding/databases.py | 6 +- src/sage/coding/golay_code.py | 2 +- src/sage/coding/grs_code.py | 6 +- src/sage/coding/guava.py | 8 +-- src/sage/coding/guruswami_sudan/gs_decoder.py | 4 +- src/sage/coding/information_set_decoder.py | 2 +- src/sage/coding/linear_code.py | 70 +++++++++--------- src/sage/coding/linear_rank_metric.py | 4 +- src/sage/coding/parity_check_code.py | 2 +- src/sage/coding/self_dual_codes.py | 10 +-- src/sage/coding/two_weight_db.py | 50 ++++++------- src/sage/crypto/classical.py | 2 +- src/sage/crypto/classical_cipher.py | 4 +- src/sage/crypto/lwe.py | 28 ++++---- src/sage/crypto/mq/rijndael_gf.py | 2 +- src/sage/crypto/mq/sr.py | 64 ++++++++--------- src/sage/crypto/stream_cipher.py | 2 +- .../arithmetic_dynamics/berkovich_ds.py | 28 ++++---- .../endPN_automorphism_group.py | 46 ++++++------ .../endPN_minimal_model.py | 4 +- .../arithmetic_dynamics/generic_ds.py | 4 +- .../product_projective_ds.py | 6 +- .../arithmetic_dynamics/projective_ds.py | 24 +++---- .../dynamics/arithmetic_dynamics/wehlerK3.py | 34 ++++----- .../dynamics/cellular_automata/solitons.py | 12 ++-- src/sage/geometry/cone.py | 6 +- src/sage/geometry/lattice_polytope.py | 4 +- .../geometry/polyhedron/backend_polymake.py | 2 +- src/sage/geometry/polyhedron/base_QQ.py | 6 +- src/sage/geometry/polyhedron/base_RDF.py | 6 +- src/sage/geometry/polyhedron/base_ZZ.py | 6 +- .../geometry/polyhedron/cdd_file_format.py | 2 +- .../polyhedron/ppl_lattice_polytope.py | 12 ++-- .../geometry/polyhedron/representation.py | 2 +- src/sage/geometry/pseudolines.py | 26 +++---- src/sage/geometry/ribbon_graph.py | 12 ++-- .../parametrized_surface3d.py | 8 +-- src/sage/geometry/toric_lattice.py | 14 ++-- src/sage/geometry/triangulation/element.py | 20 +++--- .../triangulation/point_configuration.py | 28 ++++---- src/sage/manifolds/chart.py | 2 +- .../differentiable/automorphismfield_group.py | 2 +- src/sage/manifolds/differentiable/curve.py | 4 +- .../manifolds/differentiable/degenerate.py | 4 +- .../differentiable/degenerate_submanifold.py | 32 ++++----- src/sage/manifolds/differentiable/diff_map.py | 4 +- .../differentiable/integrated_curve.py | 72 +++++++++---------- .../differentiable/levi_civita_connection.py | 2 +- src/sage/manifolds/differentiable/manifold.py | 8 +-- .../differentiable/manifold_homset.py | 8 +-- src/sage/manifolds/differentiable/metric.py | 24 +++---- .../manifolds/differentiable/tangent_space.py | 2 +- .../manifolds/differentiable/tensorfield.py | 2 +- .../manifolds/differentiable/vectorfield.py | 6 +- .../differentiable/vectorfield_module.py | 24 +++---- src/sage/manifolds/utilities.py | 10 +-- src/sage/modular/abvar/constructor.py | 6 +- src/sage/modular/abvar/cuspidal_subgroup.py | 4 +- src/sage/modular/abvar/finite_subgroup.py | 4 +- src/sage/modular/abvar/homspace.py | 4 +- src/sage/modular/abvar/lseries.py | 2 +- src/sage/modular/abvar/torsion_subgroup.py | 4 +- .../modular/arithgroup/arithgroup_generic.py | 10 +-- .../modular/arithgroup/arithgroup_perm.py | 56 +++++++-------- src/sage/modular/arithgroup/congroup_gamma.py | 20 +++--- .../modular/arithgroup/congroup_gamma0.py | 10 +-- .../modular/arithgroup/congroup_gamma1.py | 16 ++--- .../modular/arithgroup/congroup_generic.py | 4 +- src/sage/modular/arithgroup/congroup_sl2z.py | 2 +- src/sage/modular/local_comp/smoothchar.py | 2 +- src/sage/modular/modform/ambient_R.py | 2 +- src/sage/modular/modform/ambient_eps.py | 8 +-- src/sage/modular/modform/constructor.py | 2 +- .../modular/modform/cuspidal_submodule.py | 10 +-- src/sage/modular/modform/eis_series.py | 12 ++-- .../modular/modform/eisenstein_submodule.py | 2 +- .../modular/modform/hecke_operator_on_qexp.py | 6 +- src/sage/modular/modform/numerical.py | 4 +- src/sage/modular/modform/ring.py | 8 +-- src/sage/modular/modform/space.py | 14 ++-- src/sage/modular/modform/submodule.py | 2 +- src/sage/modular/modform/vm_basis.py | 2 +- src/sage/modular/modform/weight1.py | 2 +- .../modform_hecketriangle/abstract_ring.py | 2 +- .../modform_hecketriangle/abstract_space.py | 12 ++-- .../modform_hecketriangle/constructor.py | 4 +- .../hecke_triangle_group_element.py | 4 +- src/sage/modular/overconvergent/genus0.py | 4 +- .../modular/overconvergent/hecke_series.py | 4 +- .../modular/pollack_stevens/distributions.py | 2 +- 92 files changed, 525 insertions(+), 525 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 5b9ebedc06e..c1e0eb77022 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -361,7 +361,7 @@ def gilbert_lower_bound(n, q, d): 128/7 """ _check_n_q_d(n, q, d, field_based=False) - ans=q**n/volume_hamming(n,q,d-1) + ans = q**n/volume_hamming(n,q,d-1) return ans def plotkin_upper_bound(n,q,d, algorithm=None): @@ -389,16 +389,16 @@ def plotkin_upper_bound(n,q,d, algorithm=None): return QQ(libgap.UpperBoundPlotkin(n, d, q)) else: t = 1 - 1/q - if (q==2) and (n == 2*d) and (d%2 == 0): + if (q == 2) and (n == 2*d) and (d % 2 == 0): return 4*d - elif (q==2) and (n == 2*d + 1) and (d%2 == 1): + elif (q == 2) and (n == 2*d + 1) and (d % 2 == 1): return 4*d + 4 elif d > t*n: return int(d/( d - t*n)) elif d < t*n + 1: fact = (d-1) / t from sage.rings.real_mpfr import RR - if RR(fact)==RR(int(fact)): + if RR(fact) == RR(int(fact)): fact = int(fact) + 1 return int(d/( d - t * fact)) * q**(n - fact) @@ -487,7 +487,7 @@ def ff(n,d,w,q): def get_list(n,d,q): I = [] for i in range(1,int(r*n)+1): - if i**2-2*r*n*i+r*n*d>0: + if i**2-2*r*n*i+r*n*d > 0: I.append(i) return I I = get_list(n,d,q) diff --git a/src/sage/coding/code_constructions.py b/src/sage/coding/code_constructions.py index 2cd68c11a28..d96ad3c7627 100644 --- a/src/sage/coding/code_constructions.py +++ b/src/sage/coding/code_constructions.py @@ -321,7 +321,7 @@ def walsh_matrix(m0): if m > 1: row2 = [x.list() for x in walsh_matrix(m-1).augment(walsh_matrix(m-1)).rows()] return matrix(GF(2), m, 2**m, [[0]*2**(m-1) + [1]*2**(m-1)] + row2) - raise ValueError("%s must be an integer > 0."%m0) + raise ValueError("%s must be an integer > 0." % m0) ##################### main constructions ##################### @@ -356,7 +356,7 @@ def DuadicCodeEvenPair(F,S1,S2): from .cyclic_code import CyclicCode n = len(S1) + len(S2) + 1 if not _is_a_splitting(S1,S2,n): - raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n)) + raise TypeError("%s, %s must be a splitting of %s." % (S1,S2,n)) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") @@ -406,7 +406,7 @@ def DuadicCodeOddPair(F,S1,S2): from .cyclic_code import CyclicCode n = len(S1) + len(S2) + 1 if not _is_a_splitting(S1,S2,n): - raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n)) + raise TypeError("%s, %s must be a splitting of %s." % (S1,S2,n)) q = F.order() k = Mod(q,n).multiplicative_order() FF = GF(q**k,"z") diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index 7839cd8c693..3826734c09b 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -274,9 +274,9 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, from sage.rings.finite_rings.finite_field_constructor import FiniteField from sage.matrix.constructor import Matrix - d=int(b) - if d!=b or d%2==1 or d <= 0: - raise ValueError("b (%s) must be a positive even integer."%b) + d = int(b) + if d != b or d % 2 == 1 or d <= 0: + raise ValueError("b (%s) must be a positive even integer." % b) from .linear_code import LinearCode from .binary_code import BinaryCode, BinaryCodeClassifier if k < 1 or n < 2: diff --git a/src/sage/coding/golay_code.py b/src/sage/coding/golay_code.py index b55cd8a4f4d..e698605825e 100644 --- a/src/sage/coding/golay_code.py +++ b/src/sage/coding/golay_code.py @@ -271,7 +271,7 @@ def weight_distribution(self): n = self.length() if n == 23: return ([1]+[0]*6+[253]+[506]+[0]*2+[1288]*2+[0]*2+[506] - +[253]+[0]*6+[1]) + + [253]+[0]*6+[1]) if n == 24: return ([1]+[0]*7+[759]+[0]*3+[2576]+[0]*3+[759]+[0]*7+[1]) if n == 11: diff --git a/src/sage/coding/grs_code.py b/src/sage/coding/grs_code.py index b0824a51f62..82a0a5cfe72 100644 --- a/src/sage/coding/grs_code.py +++ b/src/sage/coding/grs_code.py @@ -1235,7 +1235,7 @@ def _decode_to_code_and_message(self, r): l0 = n-1-t l1 = n-1-t-(k-1) S = matrix(C.base_field(), n, l0+l1+2, - lambda i, j: (C.evaluation_points()[i])**j if j<(l0+1) + lambda i, j: (C.evaluation_points()[i])**j if j < (l0+1) else r_list[i]*(C.evaluation_points()[i])**(j-(l0+1))) S = S.right_kernel() S = S.basis_matrix().row(0) @@ -1978,9 +1978,9 @@ def decode_to_message(self, word_and_erasure_vector): if C1_length == k: return self.connected_encoder().unencode_nocheck(word) C1_evaluation_points = [self.code().evaluation_points()[i] for i in - range(n) if erasure_vector[i]!=1] + range(n) if erasure_vector[i] != 1] C1_column_multipliers = [self.code().column_multipliers()[i] for i in - range(n) if erasure_vector[i]!=1] + range(n) if erasure_vector[i] != 1] C1 = GeneralizedReedSolomonCode(C1_evaluation_points, k, C1_column_multipliers) return C1.decode_to_message(punctured_word) diff --git a/src/sage/coding/guava.py b/src/sage/coding/guava.py index e9f0404b458..92e2dc80451 100644 --- a/src/sage/coding/guava.py +++ b/src/sage/coding/guava.py @@ -69,8 +69,8 @@ def QuasiQuadraticResidueCode(p): """ GapPackage("guava", spkg="gap_packages").require() libgap.load_package("guava") - C=libgap.QQRCode(p) - G=C.GeneratorMat() + C = libgap.QQRCode(p) + G = C.GeneratorMat() MS = MatrixSpace(GF(2), len(G), len(G[0])) return LinearCode(MS(G)) @@ -104,7 +104,7 @@ def RandomLinearCodeGuava(n, k, F): GapPackage("guava", spkg="gap_packages").require() libgap.load_package("guava") - C=libgap.RandomLinearCode(n,k,F) - G=C.GeneratorMat() + C = libgap.RandomLinearCode(n,k,F) + G = C.GeneratorMat() MS = MatrixSpace(F, len(G), len(G[0])) return LinearCode(MS(G)) diff --git a/src/sage/coding/guruswami_sudan/gs_decoder.py b/src/sage/coding/guruswami_sudan/gs_decoder.py index 3021cbbfab6..bf4c78d71e4 100644 --- a/src/sage/coding/guruswami_sudan/gs_decoder.py +++ b/src/sage/coding/guruswami_sudan/gs_decoder.py @@ -371,7 +371,7 @@ def guruswami_sudan_decoding_radius(C=None, n_k=None, l=None, s=None): def get_tau(s,l): "Return the decoding radius given this s and l" - if s<=0 or l<=0: + if s <= 0 or l <= 0: return -1 return gilt(n - n/2*(s+1)/(l+1) - (k-1)/2*l/s) if l is None and s is None: @@ -482,7 +482,7 @@ def _suitable_parameters_given_tau(tau, C=None, n_k=None): atau = n - tau smin = tau * w / (atau ** 2 - n * w) s = floor(1 + smin) - D = (s - smin) * (atau ** 2 - n * w) * s + (w**2) /4 + D = (s - smin) * (atau ** 2 - n * w) * s + (w**2) / 4 l = floor(atau / w * s + 0.5 - sqrt(D)/w) return (s, l) diff --git a/src/sage/coding/information_set_decoder.py b/src/sage/coding/information_set_decoder.py index 5d4d28a7c47..dad1f2b06f3 100644 --- a/src/sage/coding/information_set_decoder.py +++ b/src/sage/coding/information_set_decoder.py @@ -587,7 +587,7 @@ def time_search_loop(p): P = [ time_search_loop(p) for p in range(tau+1) ] def compute_estimate(p): - iters = 1.* binomial(n, k)/ \ + iters = 1. * binomial(n, k) / \ sum( binomial(n-tau, k-i)*binomial(tau,i) for i in range(p+1) ) estimate = iters*(T + sum(P[pi] * (q-1)**pi * binomial(k, pi) for pi in range(p+1) )) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index ac1581f2691..0d84996a483 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -277,7 +277,7 @@ def _dump_code_in_leon_format(C): from sage.misc.temporary_file import tmp_filename F = C.base_ring() p = F.order() # must be prime and <11 - s = "LIBRARY code;\n"+"code=seq(%s,%s,%s,seq(\n"%(p,C.dimension(),C.length()) + s = "LIBRARY code;\n"+"code=seq(%s,%s,%s,seq(\n" % (p,C.dimension(),C.length()) Gr = [str(r)[1:-1].replace(" ","") for r in C.generator_matrix().rows()] s += ",\n".join(Gr) + "\n));\nFINISH;" file_loc = tmp_filename() @@ -605,25 +605,25 @@ def assmus_mattson_designs(self, t, mode=None): n = len(G.columns()) Cp = C.dual_code() wts = C.weight_distribution() - d = min([i for i in range(1,len(wts)) if wts[i]!=0]) - if t>=d: + d = min([i for i in range(1,len(wts)) if wts[i] != 0]) + if t >= d: return 0 - nonzerowts = [i for i in range(len(wts)) if wts[i]!=0 and i<=n and i>=d] - if mode=="verbose": + nonzerowts = [i for i in range(len(wts)) if wts[i] != 0 and i <= n and i >= d] + if mode == "verbose": for w in nonzerowts: print("The weight w={} codewords of C* form a t-(v,k,lambda) design, where\n \ t={}, v={}, k={}, lambda={}. \nThere are {} block of this design.".format( w,t,n,w,wts[w]*binomial(w,t)//binomial(n,t),wts[w])) wtsp = Cp.weight_distribution() - dp = min([i for i in range(1,len(wtsp)) if wtsp[i]!=0]) - nonzerowtsp = [i for i in range(len(wtsp)) if wtsp[i]!=0 and i<=n-t and i>=dp] - s = len([i for i in range(1,n) if wtsp[i]!=0 and i<=n-t and i>0]) - if mode=="verbose": + dp = min([i for i in range(1,len(wtsp)) if wtsp[i] != 0]) + nonzerowtsp = [i for i in range(len(wtsp)) if wtsp[i] != 0 and i <= n-t and i >= dp] + s = len([i for i in range(1,n) if wtsp[i] != 0 and i <= n-t and i > 0]) + if mode == "verbose": for w in nonzerowtsp: print("The weight w={} codewords of C* form a t-(v,k,lambda) design, where\n \ t={}, v={}, k={}, lambda={}. \nThere are {} block of this design.".format( w,t,n,w,wts[w]*binomial(w,t)//binomial(n,t),wts[w])) - if s<=d-t: + if s <= d-t: des = [[t,(n,w,wts[w]*binomial(w,t)//binomial(n,t))] for w in nonzerowts] ans = ans + ["weights from C: ",nonzerowts,"designs from C: ",des] desp = [[t,(n,w,wtsp[w]*binomial(w,t)//binomial(n,t))] for w in nonzerowtsp] @@ -672,20 +672,20 @@ def binomial_moment(self, i): J = range(1,n+1) Cp = self.dual_code() dp = Cp.minimum_distance() - if in-dp and i<=n: - return binomial(n,i)*(q**(i+k-n) -1)//(q-1) + if i > n-dp and i <= n: + return binomial(n,i)*(q**(i+k-n) - 1)//(q-1) from sage.combinat.set_partition import SetPartitions P = SetPartitions(J,2).list() b = QQ(0) for p in P: p = list(p) S = p[0] - if len(S)==n-i: + if len(S) == n-i: C_S = self.shortened(S) k_S = C_S.dimension() - b = b + (q**(k_S) -1)//(q-1) + b = b + (q**(k_S) - 1)//(q-1) return b @cached_method @@ -827,7 +827,7 @@ def characteristic_polynomial(self): k = C.dimension() n = C.length() q = (C.base_ring()).order() - return q**(n-k)*prod([1-x/j for j in Sd if j>0]) + return q**(n-k)*prod([1-x/j for j in Sd if j > 0]) def chinen_polynomial(self): """ @@ -955,7 +955,7 @@ def divisor(self): V = VectorSpace(QQ,n+1) S = V(A).nonzero_positions() S0 = [S[i] for i in range(1,len(S))] - if len(S)>1: + if len(S) > 1: return GCD(S0) return 1 @@ -1220,7 +1220,7 @@ def galois_closure(self, F0): q0 = F0.order() a = q.log(q0) # test if F/F0 is a field extension if not isinstance(a, Integer): - raise ValueError("Base field must be an extension of given field %s"%F0) + raise ValueError("Base field must be an extension of given field %s" % F0) n = len(G.columns()) k = len(G.rows()) G0 = [[x**q0 for x in g.list()] for g in G.rows()] @@ -1302,7 +1302,7 @@ def is_permutation_equivalent(self,other,algorithm=None): B2 = NonlinearBinaryCodeStruct(CW2) ans = B1.is_isomorphic(B2) if ans is not False: - if algorithm=="verbose": + if algorithm == "verbose": Sn = SymmetricGroup(n) return True, Sn([i+1 for i in ans])**(-1) return True @@ -1640,28 +1640,28 @@ def permutation_automorphism_group(self, algorithm="partition"): GapPackage("guava", spkg="gap_packages").require() libgap.LoadPackage('guava') wts = self.weight_distribution() # bottleneck 1 - nonzerowts = [i for i in range(len(wts)) if wts[i]!=0] + nonzerowts = [i for i in range(len(wts)) if wts[i] != 0] Sn = libgap.SymmetricGroup(n) Sn_sage = SymmetricGroup(n) Gp = Sn # initializing G in gap C = libgap(G).GeneratorMatCode(libgap.GF(q)) eltsC = C.Elements() - if algorithm=="gap+verbose": + if algorithm == "gap+verbose": print("\n Minimum distance: %s \n Weight distribution: \n %s" % (nonzerowts[1], wts)) stop = 0 # only stop if all gens are autos for i in range(1,len(nonzerowts)): if stop == 1: break wt = nonzerowts[i] - if algorithm=="gap+verbose": + if algorithm == "gap+verbose": size = Gp.Size() print("\n Using the %s codewords of weight %s \n Supergroup size: \n %s\n " % (wts[wt], wt, size)) - Cwt=filter(lambda c: c.WeightCodeword()==wt, eltsC) # bottleneck 2 (repeated - matCwt=list(map(lambda c: c.VectorCodeword(), Cwt)) # for each i until stop = 1) + Cwt = filter(lambda c: c.WeightCodeword() == wt, eltsC) # bottleneck 2 (repeated + matCwt = list(map(lambda c: c.VectorCodeword(), Cwt)) # for each i until stop = 1) if len(matCwt) > 0: A = libgap(matCwt).MatrixAutomorphisms() Gp = A.Intersection2(Gp) # bottleneck 3 - if Gp.Size()==1: + if Gp.Size() == 1: return PermutationGroup([()]) gens = Gp.GeneratorsOfGroup() stop = 1 # get ready to stop @@ -1671,7 +1671,7 @@ def permutation_automorphism_group(self, algorithm="partition"): break G = PermutationGroup(list(map(Sn_sage, gens))) return G - if algorithm=="partition": + if algorithm == "partition": if q == 2: from sage.groups.perm_gps.partn_ref.refinement_binary import LinearBinaryCodeStruct B = LinearBinaryCodeStruct(G) @@ -1703,7 +1703,7 @@ def permutation_automorphism_group(self, algorithm="partition"): else: return PermutationGroup([]) return AutGp - if algorithm=="codecan": + if algorithm == "codecan": gens, _ = self.automorphism_group_gens("permutational") return PermutationGroup([x.get_perm() for x in gens]) raise NotImplementedError("The only algorithms implemented currently are 'gap', 'gap+verbose', and 'partition'.") @@ -1866,17 +1866,17 @@ def weight_distribution(self, algorithm=None): algorithm = "gap" F = self.base_ring() n = self.length() - if algorithm=="gap": + if algorithm == "gap": from sage.libs.gap.libgap import libgap Gmat = self.generator_matrix() q = self.base_ring().order() z = 0*libgap.Z(q)*([0]*self.length()) # GAP zero vector - w=libgap(Gmat).DistancesDistributionMatFFEVecFFE(libgap.GF(q),z) + w = libgap(Gmat).DistancesDistributionMatFFEVecFFE(libgap.GF(q),z) return w.sage() - elif algorithm=="binary": + elif algorithm == "binary": from sage.coding.binary_code import weight_dist return weight_dist(self.generator_matrix()) - elif algorithm=="leon": + elif algorithm == "leon": if not(F.order() in [2,3,5,7]): raise NotImplementedError("The algorithm 'leon' is only implemented for q = 2,3,5,7.") # The GAP command DirectoriesPackageLibrary tells the location of the latest @@ -2030,8 +2030,8 @@ def zeta_polynomial(self, name="T"): if d == 1 or dperp == 1: print("\n WARNING: There is no guarantee this function works when the minimum distance") print(" of the code or of the dual code equals 1.\n") - RT = PolynomialRing(QQ,"%s"%name) - R = PolynomialRing(QQ,3,"xy%s"%name) + RT = PolynomialRing(QQ,"%s" % name) + R = PolynomialRing(QQ,3,"xy%s" % name) x,y,T = R.gens() we = self.weight_enumerator() A = R(we) @@ -2380,9 +2380,9 @@ def _repr_(self): """ R = self.base_ring() if R in Fields(): - return "[%s, %s] linear code over GF(%s)"%(self.length(), self.dimension(), R.cardinality()) + return "[%s, %s] linear code over GF(%s)" % (self.length(), self.dimension(), R.cardinality()) else: - return "[%s, %s] linear code over %s"%(self.length(), self.dimension(), R) + return "[%s, %s] linear code over %s" % (self.length(), self.dimension(), R) def _latex_(self): r""" diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index babb22ff1ce..6a7cd14cb62 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -731,9 +731,9 @@ def _repr_(self): R = self.base_field() S = self.sub_field() if R and S in Fields(): - return "[%s, %s] linear rank metric code over GF(%s)/GF(%s)"%(self.length(), self.dimension(), R.cardinality(), S.cardinality()) + return "[%s, %s] linear rank metric code over GF(%s)/GF(%s)" % (self.length(), self.dimension(), R.cardinality(), S.cardinality()) else: - return "[%s, %s] linear rank metric code over %s/%s"%(self.length(), self.dimension(), R, S) + return "[%s, %s] linear rank metric code over %s/%s" % (self.length(), self.dimension(), R, S) def _latex_(self): r""" diff --git a/src/sage/coding/parity_check_code.py b/src/sage/coding/parity_check_code.py index d131ecaf80a..0adafbbba57 100644 --- a/src/sage/coding/parity_check_code.py +++ b/src/sage/coding/parity_check_code.py @@ -304,7 +304,7 @@ def encode(self, message): sage: C.encode(message) (1, 0, 4, 2, 0, 3, 2, 3) """ - parity=self.code().base_field().zero() + parity = self.code().base_field().zero() for i in message.list(): parity += i return vector(self.code().base_field(), message.list() + [-parity]) diff --git a/src/sage/coding/self_dual_codes.py b/src/sage/coding/self_dual_codes.py index 67f90226ccb..d60d161d28d 100644 --- a/src/sage/coding/self_dual_codes.py +++ b/src/sage/coding/self_dual_codes.py @@ -537,7 +537,7 @@ def self_dual_binary_codes(n): "Type":"I","Comment": "Huge aut gp. Unique codeword of smallest non-zero wt.\ Same spectrum as '[18,3]' sd code."} # [18,5]: - C = self_dual_binary_codes(n-2)["%s"%(n-2)]["5"]["code"] + C = self_dual_binary_codes(n-2)["%s" % (n-2)]["5"]["code"] A0 = C.redundancy_matrix() genmat = _I2(n).augment(block_diagonal_matrix([A0,_matId(n)[8]])) # G = PermutationGroup( [ "(5,10)(6,11)", "(5,11)(6,10)", "(5,11,12)(6,7,10)",\ @@ -550,7 +550,7 @@ def self_dual_binary_codes(n): self_dual_codes_18_5 = {"order autgp":451584,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment": "'Exceptional' construction."} # [18,6]: - C = self_dual_binary_codes(n-2)["%s"%(n-2)]["6"]["code"] + C = self_dual_binary_codes(n-2)["%s" % (n-2)]["6"]["code"] A0 = C.redundancy_matrix() genmat = _I2(n).augment(block_diagonal_matrix([A0,_matId(n)[8]])) G = PermutationGroup( [ "(9,18)", "(7,10)(11,17)", "(7,11)(10,17)", "(6,7)(11,12)", @@ -649,7 +649,7 @@ def self_dual_binary_codes(n): # G = PermutationGroup( [ "(5,6)(15,16)", "(5,15)(6,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)", "(8,17)(9,10)", "(8,10)(9,17)", "(8,10,20)(9,19,17)",\ # "(8,19,20,9,17,10,18)", "(7,8,19,20,9,18)(10,17)"] ) - spectrum =[1, 0, 0, 0, 29, 0, 32, 0, 226, 0, 448, 0, 226, 0, 32, 0, 29, 0, 0, 0, 1] + spectrum = [1, 0, 0, 0, 29, 0, 32, 0, 226, 0, 448, 0, 226, 0, 32, 0, 29, 0, 0, 0, 1] self_dual_codes_20_3 = {"order autgp":30965760,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":"Min dist 4."} # [20,4]: @@ -660,7 +660,7 @@ def self_dual_binary_codes(n): # "(1,2,3,11,14,4,12)(5,17,18)(6,15,8)", "(1,5,13,17,14,8,2,7,3,16,12,6,11,18)(4,15)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(10,20)",\ # "(2,3,12)(4,11,14)(5,17,18)(6,15,8)(9,10,19,20)"] ) - spectrum =[1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] + spectrum = [1, 0, 2, 0, 29, 0, 56, 0, 226, 0, 396, 0, 226, 0, 56, 0, 29, 0, 2, 0, 1] self_dual_codes_20_4 = {"order autgp":28901376,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":""} # [20,5]: @@ -715,7 +715,7 @@ def self_dual_binary_codes(n): # G = PermutationGroup( [ "(9,10)(19,20)", "(9,19)(10,20)", "(8,9)(18,19)", "(7,8)(17,18)",\ # "(6,7)(16,17)", "(5,6)(15,16)", "(4,5)(14,15)", "(3,4)(13,14)",\ # "(2,3)(12,13)", "(1,2)(11,12)"] ) - spectrum =[1, 0, 0, 0, 45, 0, 0, 0, 210, 0, 512, 0, 210, 0, 0, 0, 45, 0, 0, 0, 1] + spectrum = [1, 0, 0, 0, 45, 0, 0, 0, 210, 0, 512, 0, 210, 0, 0, 0, 45, 0, 0, 0, 1] self_dual_codes_20_8 = {"order autgp":1857945600,"code":LinearCode(genmat),"spectrum":spectrum, "Type":"I","Comment":"Huge aut gp. Min dist 4."} # [20,9]: (genmat, K20 are equiv) diff --git a/src/sage/coding/two_weight_db.py b/src/sage/coding/two_weight_db.py index 44695300f33..1ad3d584310 100644 --- a/src/sage/coding/two_weight_db.py +++ b/src/sage/coding/two_weight_db.py @@ -179,17 +179,17 @@ 'w1': 99, 'w2': 108, 'K' : GF(3), - 'M' : ("10000021022112121121110122002121000010001102020020110112102112202221021020201"+ + 'M' : ("10000021022112121121110122002121000010001102020020110112102112202221021020201" + "20202212102220222022222110122210022201211222111110211101121002011102101111002", - "01000020121020200200211101202000100111001222222022121120012020122110122122221"+ + "01000020121020200200211101202000100111001222222022121120012020122110122122221" + "02222102012112111221111021101101021121002001022221202211100102212212010222102", - "00100021001211011111111202122021010221101221212220022221200011221102002202120"+ + "00100021001211011111111202122021010221101221212220022221200011221102002202120" + "20121121000101000111020212200020121210011112210001001022001012222020000100212", - "00010022122200222202201212212020101202111221111211112001022110001001221210110"+ + "00010022122200222202201212212020101202111221111211112001022110001001221210110" + "12211020202200222000021101010212001022212020002112011200021100210001100121020", - "00001021201002010011020210220020010200212211101111221012101020222021111111212"+ + "00001021201002010011020210220020010200212211101111221012101020222021111111212" + "11120012122110211222201220220201222200102101111020112221020112012102211120101", - "00000120112212122122202110022120001200022010100102202210012211211120100101022"+ + "00000120112212122122202110022120001200022010100102202210012211211120100101022" + "01011212011101110111112202111200111021221112222211222020120010222012022220012"), 'source': "Shared by Eric Chen [ChenDB]_.", }, @@ -199,25 +199,25 @@ 'w1': 96, 'w2': 112, 'K' : GF(2), - 'M' : ("1000000000111111101010000100011001111101101010010010011110001101111001101100111000111101010101110011"+ + 'M' : ("1000000000111111101010000100011001111101101010010010011110001101111001101100111000111101010101110011" + "11110010100111101001001100111101011110111100101101110100111100011111011011100111110010100110110000", - "0100000000010110011100100010101010101111011010001001010110011010101011011101000110000001101101010110"+ + "0100000000010110011100100010101010101111011010001001010110011010101011011101000110000001101101010110" + "10110111110101000000011011001100010111110001001011011100111100100000110001011001110110011101011000", - "0010000000011100111110111011000011010100100011110000001100011011101111001010001100110110000001111000"+ + "0010000000011100111110111011000011010100100011110000001100011011101111001010001100110110000001111000" + "11000000101011010111110101000111110010011011101110000010110100000011100010011111100100111101010010", - "0001000000001111100010000000100101010001110111100010010010010111000100101100010001001110111101110100"+ + "0001000000001111100010000000100101010001110111100010010010010111000100101100010001001110111101110100" + "10010101101100110011010011101100110100100011011101100000110011110011111000000010110101011111101111", - "0000100000110010010000010110000111010011010101000010110100101010011011000011001100001110011011110001"+ + "0000100000110010010000010110000111010011010101000010110100101010011011000011001100001110011011110001" + "11101000010000111101101100111100001011010010111011100101101001111000100011000010110111111111011100", - "0000010000110100111001111011010000101110001011100010010010010111100101011001011011100110101110100001"+ + "0000010000110100111001111011010000101110001011100010010010010111100101011001011011100110101110100001" + "01101010110010100011000101111100100001110111001001001001001100001101110110000110101010011010101101", - "0000001000011011110010110100010010001100000011001000011101000110001101001000110110010101011011001111"+ + "0000001000011011110010110100010010001100000011001000011101000110001101001000110110010101011011001111" + "01111111010011111010100110011001110001001000001110000110111011010000011101001110111001011011001011", - "0000000100111001101011110010111100100001010100100110001100100110010101111001100101101001000101011000"+ + "0000000100111001101011110010111100100001010100100110001100100110010101111001100101101001000101011000" + "10001001111101011101001001010111010011011101010011010000101010011001010110011110010000011011111001", - "0000000010101011010101010101011100111101111110100011011001001010111101100111010110100101100110101100"+ + "0000000010101011010101010101011100111101111110100011011001001010111101100111010110100101100110101100" + "00000001100011110110010101100001000000010100001101111011111000110001100101101010000001110101011100", - "0000000001101100111101011000010000000011010100000110101010011010100111100001000011010011011101110111"+ + "0000000001101100111101011000010000000011010100000110101010011010100111100001000011010011011101110111" + "01110111011110101100100100110110011100001001000001010011010010010111110011101011101001101101011010"), 'source': "Shared by Eric Chen [ChenDB]_.", }, @@ -227,23 +227,23 @@ 'w1': 96, 'w2': 112, 'K' : GF(2), - 'M' : ("10100011001110100010100010010000100100001011110010001010011000000001101011110011001001000010011110111011111"+ + 'M' : ("10100011001110100010100010010000100100001011110010001010011000000001101011110011001001000010011110111011111" + "0001001010110110110111001100111100011011101000000110101110001010100011110011111111110111010100101011000101111111", - "01100010110101110100001000010110001010010010011000111101111001011101000011101011100111111110001100000111010"+ + "01100010110101110100001000010110001010010010011000111101111001011101000011101011100111111110001100000111010" + "1101001000110001111011001100101011110101011110010001101011110000100000101101100010110100001111001100110011001111", - "00010010001001011011001110011101111110000000101110101000110110011001110101011011101011011011000010010011111"+ + "00010010001001011011001110011101111110000000101110101000110110011001110101011011101011011011000010010011111" + "1110110100111111000000110011101101000000001010000000011000111111100101100001110011110001110011110110100111100001", - "00001000100010101110101110011100010101110011010110000001111111100111010000101110001010100100000001011010111"+ + "00001000100010101110101110011100010101110011010110000001111111100111010000101110001010100100000001011010111" + "1001001000000011000011001100100100111010000000001010111001001100100101011110001100110001000000111001100100100111", - "00000101010100010101101110011101001000101110000000000111101100011000000001110100000001011010101001111110110"+ + "00000101010100010101101110011101001000101110000000000111101100011000000001110100000001011010101001111110110" + "0010110111100111000000110011110110101101110000001111100001010001100101100001110011110001101101000000000000100001", - "00000000000000000000010000011101011100100010000110110100101011001011001100000001011000101010100111000111101"+ + "00000000000000000000010000011101011100100010000110110100101011001011001100000001011000101010100111000111101" + "0011100011011011011111100010011100010111101001011001001101100010011010001011010110001110100001001111110010100100", - "00000000000000000000000001011010110110101111010110101001001001000101010000000000001011000011000010100100110"+ + "00000000000000000000000001011010110110101111010110101001001001000101010000000000001011000011000010100100110" + "0000110000111101100010000111111111101101001010110000111111101110101011010010010001011101110011111001100100101110", - "00000000000000000000000000110111101011110010101110000110010010100010001010000000010100011000101000010011000"+ + "00000000000000000000000000110111101011110010101110000110010010100010001010000000010100011000101000010011000" + "0110000111100110100001001011111111111010110000001010111111110011110110001100100010101011101101110110011000110110", - "00000000000000000000000000000000000000000000000001111111111111111111111110000001111111111111111111111111111"+ + "00000000000000000000000000000000000000000000000001111111111111111111111110000001111111111111111111111111111" + "1111111100000000000011111111111111000000111111111111111111000000000000111111111111000000000000000000111111000110"), 'source': "Shared by Eric Chen [ChenDB]_.", }, diff --git a/src/sage/crypto/classical.py b/src/sage/crypto/classical.py index 616dc861652..e5da119086a 100644 --- a/src/sage/crypto/classical.py +++ b/src/sage/crypto/classical.py @@ -3644,7 +3644,7 @@ def inverse_key(self, K): """ S = self.key_space() n = S.ngens() - return S([ (-i)%(n) for i in K._element_list ]) + return S([ (-i) % (n) for i in K._element_list ]) def encoding(self, M): """ diff --git a/src/sage/crypto/classical_cipher.py b/src/sage/crypto/classical_cipher.py index fd2c2464293..b775c426058 100644 --- a/src/sage/crypto/classical_cipher.py +++ b/src/sage/crypto/classical_cipher.py @@ -517,7 +517,7 @@ def __call__(self, M, mode="ECB"): g = self.key() N = len(M) m = self.parent().block_length() - if not N%m == 0: + if not N % m == 0: raise TypeError("Argument M (= %s) must be a string of length k*%s." % (M, m)) Melt = M._element_list # this uses the internal structure of string monoids # Caution: this is parsed as an outer loop in k and an inner loop in i: @@ -572,7 +572,7 @@ def __call__(self, M, mode="ECB"): # This uses the internal structure of string monoids Melt = M._element_list Kelt = K._element_list - return S([ (Melt[i]+Kelt[i%m])%n for i in range(len(M)) ]) + return S([ (Melt[i]+Kelt[i % m]) % n for i in range(len(M)) ]) def inverse(self): E = self.parent() diff --git a/src/sage/crypto/lwe.py b/src/sage/crypto/lwe.py index 0be1b92d77e..db675ebafaa 100644 --- a/src/sage/crypto/lwe.py +++ b/src/sage/crypto/lwe.py @@ -170,7 +170,7 @@ def _repr_(self): sage: UniformSampler(-2, 2) UniformSampler(-2, 2) """ - return "UniformSampler(%d, %d)"%(self.lower_bound, self.upper_bound) + return "UniformSampler(%d, %d)" % (self.lower_bound, self.upper_bound) class UniformPolynomialSampler(SageObject): @@ -236,7 +236,7 @@ def _repr_(self): sage: UniformPolynomialSampler(ZZ['x'], 8, -3, 3) UniformPolynomialSampler(8, -3, 3) """ - return "UniformPolynomialSampler(%d, %d, %d)"%(self.n, self.lower_bound, self.upper_bound) + return "UniformPolynomialSampler(%d, %d, %d)" % (self.n, self.lower_bound, self.upper_bound) class LWE(SageObject): @@ -329,7 +329,7 @@ def __init__(self, n, q, D, secret_dist='uniform', m=None): lb, ub = map(ZZ, secret_dist) self.__s = vector(self.K, self.n, [randint(lb,ub) for _ in range(n)]) except (IndexError, TypeError): - raise TypeError("Parameter secret_dist=%s not understood."%(secret_dist)) + raise TypeError("Parameter secret_dist=%s not understood." % (secret_dist)) def _repr_(self): """ @@ -345,9 +345,9 @@ def _repr_(self): LWE(20, 401, Discrete Gaussian sampler over the Integers with sigma = 3.000000 and c = 0.000000, (-3, 3), None) """ if isinstance(self.secret_dist, str): - return "LWE(%d, %d, %s, '%s', %s)"%(self.n,self.K.order(),self.D,self.secret_dist, self.m) + return "LWE(%d, %d, %s, '%s', %s)" % (self.n,self.K.order(),self.D,self.secret_dist, self.m) else: - return "LWE(%d, %d, %s, %s, %s)"%(self.n,self.K.order(),self.D,self.secret_dist, self.m) + return "LWE(%d, %d, %s, %s, %s)" % (self.n,self.K.order(),self.D,self.secret_dist, self.m) def __call__(self): """ @@ -362,7 +362,7 @@ def __call__(self): if self.m is not None: if self.__i >= self.m: raise IndexError("Number of available samples exhausted.") - self.__i+=1 + self.__i += 1 a = self.FM.random_element() return a, a.dot_product(self.__s) + self.K(self.D()) @@ -480,7 +480,7 @@ def __init__(self, n, instance='key', m=None): LWE(131, 64311834871, UniformSampler(0, 11109), 'noise', 181) """ - if n<89: + if n < 89: raise TypeError("Parameter too small") n2 = n @@ -509,7 +509,7 @@ def __init__(self, n, instance='key', m=None): m = n2+l LWE.__init__(self, n=n1, q=q, D=D, secret_dist='noise', m=m) else: - raise TypeError("Parameter instance=%s not understood."%(instance)) + raise TypeError("Parameter instance=%s not understood." % (instance)) class RingLWE(SageObject): """ @@ -551,7 +551,7 @@ def __init__(self, N, q, D, poly=None, secret_dist='uniform', m=None): self.K = IntegerModRing(q) if self.n != D.n: - raise ValueError("Noise distribution has dimensions %d != %d"%(D.n, self.n)) + raise ValueError("Noise distribution has dimensions %d != %d" % (D.n, self.n)) self.D = D self.q = q @@ -568,7 +568,7 @@ def __init__(self, N, q, D, poly=None, secret_dist='uniform', m=None): elif secret_dist == 'noise': self.__s = self.D() else: - raise TypeError("Parameter secret_dist=%s not understood."%(secret_dist)) + raise TypeError("Parameter secret_dist=%s not understood." % (secret_dist)) def _repr_(self): """ @@ -580,9 +580,9 @@ def _repr_(self): RingLWE(16, 401, Discrete Gaussian sampler for polynomials of degree < 8 with σ=3.000000 in each component, x^8 + 1, 'uniform', None) """ if isinstance(self.secret_dist, str): - return "RingLWE(%d, %d, %s, %s, '%s', %s)"%(self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) + return "RingLWE(%d, %d, %s, %s, '%s', %s)" % (self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) else: - return "RingLWE(%d, %d, %s, %s, %s, %s)"%(self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) + return "RingLWE(%d, %d, %s, %s, %s, %s)" % (self.N, self.K.order(), self.D, self.poly, self.secret_dist, self.m) def __call__(self): """ @@ -602,7 +602,7 @@ def __call__(self): if self.m is not None: if self.__i >= self.m: raise IndexError("Number of available samples exhausted.") - self.__i+=1 + self.__i += 1 a = self.R_q.random_element() return vector(a), vector(a * (self.__s) + self.D()) @@ -710,7 +710,7 @@ def _repr_(self): RingLWEConverter(RingLWE(20, 257, Discrete Gaussian sampler for polynomials of degree < 8 with σ=5.000000 in each component, x^8 - x^6 + x^4 - x^2 + 1, 'uniform', None)) """ - return "RingLWEConverter(%s)"%str(self.ringlwe) + return "RingLWEConverter(%s)" % str(self.ringlwe) def samples(m, n, lwe, seed=None, balanced=False, **kwds): """ diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index ba24ed0627e..55ae295f2cd 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -1311,7 +1311,7 @@ def expand_key_poly(self, row, col, round): recur_j = (key_col - self._Nk) - (recur_r * self._Nb) result = self.expand_key_poly(row, recur_j, recur_r) # Identify key_col - 1 - recur_r = int((key_col- 1)/self._Nb) + recur_r = int((key_col - 1)/self._Nb) recur_j = (key_col - 1) - (recur_r * self._Nb) return result + \ self.expand_key_poly(row, recur_j, recur_r) diff --git a/src/sage/crypto/mq/sr.py b/src/sage/crypto/mq/sr.py index 091ff4a96fa..f4ddf5c1844 100644 --- a/src/sage/crypto/mq/sr.py +++ b/src/sage/crypto/mq/sr.py @@ -586,7 +586,7 @@ def __getattr__(self, attr): self.Mstar = self.ShiftRows * self.Lin return self.Mstar - raise AttributeError("%s has no attribute %s"%(type(self), attr)) + raise AttributeError("%s has no attribute %s" % (type(self), attr)) def _repr_(self): """ @@ -598,9 +598,9 @@ def _repr_(self): SR*(1,2,2,4) """ if self._star: - return "SR*(%d,%d,%d,%d)"%(self._n, self._r, self._c, self._e) + return "SR*(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e) else: - return "SR(%d,%d,%d,%d)"%(self._n, self._r, self._c, self._e) + return "SR(%d,%d,%d,%d)" % (self._n, self._r, self._c, self._e) def base_ring(self): r""" @@ -748,7 +748,7 @@ def sub_byte(self, b): [1, 0, 1, 1], [1, 1, 0, 1]]) - elif e==8: + elif e == 8: if not hasattr(self, "_L"): self._L = Matrix(GF(2), 8, 8, [[1, 0, 0, 0, 1, 1, 1, 1], [1, 1, 0, 0, 0, 1, 1, 1], @@ -911,7 +911,7 @@ def shift_rows(self, d): d = self.state_array(d) ret = [] for i in range(d.nrows()): - ret += list(d.row(i)[i%d.ncols():]) + list(d.row(i)[:i%d.ncols()]) + ret += list(d.row(i)[i % d.ncols():]) + list(d.row(i)[:i % d.ncols()]) return Matrix(self.base_ring(), self._r, self._c, ret) def mix_columns(self, d): @@ -958,7 +958,7 @@ def mix_columns(self, d): [1, a, a+1, 1], [1, 1, a, a+1], [a+1, 1, 1, a]]) - ret =[] + ret = [] for column in d.columns(): ret.append(M * column) # AES uses the column major ordering @@ -1315,7 +1315,7 @@ def __call__(self, P, K): elif len(P) == len(K) == r*c*e: _type = self.vector else: - raise TypeError("length %d or %d doesn't match either %d or %d"%(len(P),len(K),r*c,r*c*e)) + raise TypeError("length %d or %d doesn't match either %d or %d" % (len(P),len(K),r*c,r*c*e)) else: raise TypeError("plaintext or key parameter not understood") @@ -1332,46 +1332,46 @@ def __call__(self, P, K): for r in range(self._n-1): if get_verbose() >= 2: - print("R[%02d].start %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].start %s" % (r+1, self.hex_str_vector(P))) P = SubBytes(P) if get_verbose() >= 2: - print("R[%02d].s_box %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].s_box %s" % (r+1, self.hex_str_vector(P))) P = ShiftRows(P) if get_verbose() >= 2: - print("R[%02d].s_row %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].s_row %s" % (r+1, self.hex_str_vector(P))) P = MixColumns(P) if get_verbose() >= 2: - print("R[%02d].m_col %s"%(r+1, self.hex_str_vector(P))) + print("R[%02d].m_col %s" % (r+1, self.hex_str_vector(P))) K = KeyExpansion(K, r+1) if get_verbose() >= 2: - print("R[%02d].k_sch %s"%(r+1, self.hex_str_vector(K))) + print("R[%02d].k_sch %s" % (r+1, self.hex_str_vector(K))) P = AddRoundKey(P, K) P = SubBytes(P) if get_verbose() >= 2: - print("R[%02d].s_box %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].s_box %s" % (self.n, self.hex_str_vector(P))) P = ShiftRows(P) if get_verbose() >= 2: - print("R[%02d].s_row %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].s_row %s" % (self.n, self.hex_str_vector(P))) if not self._star: P = MixColumns(P) if get_verbose() >= 2: - print("R[%02d].m_col %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].m_col %s" % (self.n, self.hex_str_vector(P))) K = KeyExpansion(K, self._n) if get_verbose() >= 2: - print("R[%02d].k_sch %s"%(self.n, self.hex_str_vector(K))) + print("R[%02d].k_sch %s" % (self.n, self.hex_str_vector(K))) P = AddRoundKey(P, K) if get_verbose() >= 2: - print("R[%02d].output %s"%(self.n, self.hex_str_vector(P))) + print("R[%02d].output %s" % (self.n, self.hex_str_vector(P))) return _type(P) @@ -1860,7 +1860,7 @@ def round_polynomials(self, i, plaintext=None, ciphertext=None): plaintext = Matrix(R, r*c*e, 1, self.phi(plaintext)) return tuple((w1 + k0 + plaintext).list()) - elif i>0 and i<=n: + elif i > 0 and i <= n: if self._star and i == n: M = self.Mstar @@ -1957,8 +1957,8 @@ def key_schedule_polynomials(self, i): if r == 1: sbox += self.inversion_polynomials(kj[(c - 1)*e:(c - 1)*e + e], si[0:e], e) if r == 2: - sbox += self.inversion_polynomials( kj[(2*c -1)*e : (2*c -1)*e + e] , si[0:1*e], e ) - sbox += self.inversion_polynomials( kj[(2*c -2)*e : (2*c -2)*e + e] , si[e:2*e], e ) + sbox += self.inversion_polynomials( kj[(2*c - 1)*e : (2*c - 1)*e + e] , si[0:1*e], e ) + sbox += self.inversion_polynomials( kj[(2*c - 2)*e : (2*c - 2)*e + e] , si[e:2*e], e ) if r == 4: if self._aes_mode: sbox += self.inversion_polynomials( kj[(4*c-3)*e : (4*c-3)*e + e] , si[0*e : 1*e] , e ) @@ -2108,19 +2108,19 @@ def polynomial_system(self, P=None, K=None, C=None): plaintext, key, ciphertext = data if plaintext is False: - raise TypeError("type %s of P not understood"%(type(plaintext))) + raise TypeError("type %s of P not understood" % (type(plaintext))) elif plaintext is None: plaintext = self.random_element("vector") if key is None: key = self.random_element("vector") elif key is False and ciphertext is False: - raise TypeError("type %s of K not understood"%(type(key))) + raise TypeError("type %s of K not understood" % (type(key))) if ciphertext is None: ciphertext = self(plaintext, key) elif ciphertext is False: - raise TypeError("type %s of C not understood"%(type(ciphertext))) + raise TypeError("type %s of C not understood" % (type(ciphertext))) for i in range(n+1): system.append( self.round_polynomials(i, plaintext, ciphertext) ) @@ -2324,13 +2324,13 @@ def lin_matrix(self, length=None): for k in range( 0, length ): for i in range(0, 4): for j in range(0, 4): - lin[k*4+j, k*4+i] = l[(i-j)%4] ** (2**j) + lin[k*4+j, k*4+i] = l[(i-j) % 4] ** (2**j) elif e == 8: l = [k.from_integer(x) for x in (5, 9, 249, 37, 244, 1, 181, 143)] for k in range( 0, length ): for i in range(0, 8): for j in range(0, 8): - lin[k*8+j, k*8+i] = l[(i-j)%8] ** (2**j) + lin[k*8+j, k*8+i] = l[(i-j) % 8] ** (2**j) return lin @@ -2480,7 +2480,7 @@ def field_polynomials(self, name, i, l=None): l = r*c _vars = self.vars(name, i, l, e) - return [_vars[e*j+k]**2 - _vars[e*j+(k+1)%e] for j in range(l) for k in range(e)] + return [_vars[e*j+k]**2 - _vars[e*j+(k+1) % e] for j in range(l) for k in range(e)] class SR_gf2(SR_generic): def __init__(self, n=1, r=1, c=1, e=4, star=False, **kwargs): @@ -2665,7 +2665,7 @@ def antiphi(self, l): elif isinstance(l, tuple): return tuple(ret) elif is_Matrix(l): - return Matrix(self.base_ring(), self.r *self.c, 1, ret) + return Matrix(self.base_ring(), self.r * self.c, 1, ret) else: raise TypeError @@ -2911,7 +2911,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = P.gens()[e:] w = P.gens()[:e] @@ -3086,7 +3086,7 @@ def _inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = Matrix(P, e, 1, P.gens()[e:]) w = Matrix(P, e, 1, P.gens()[:e]) @@ -3123,8 +3123,8 @@ def _inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, l.append( (Cw * x + o).list()[:-1] ) else: l.append( (Cw * x + o).list() ) - l.append( (Cw * S *x + x).list() ) - l.append( (Cx * S *w + w).list() ) + l.append( (Cw * S * x + x).list() ) + l.append( (Cx * S * w + w).list() ) if not biaffine_only: l.append( ((Cw * S**2 + Cx*S)*x).list() ) l.append( ((Cx * S**2 + Cw*S)*w).list() ) @@ -3280,7 +3280,7 @@ def inversion_polynomials_single_sbox(self, x=None, w=None, biaffine_only=None, e = self.e if x is None and w is None: # make sure it prints like in the book. - names = ["w%d" % i for i in reversed(range(e))] + ["x%d"%i for i in reversed(range(e))] + names = ["w%d" % i for i in reversed(range(e))] + ["x%d" % i for i in reversed(range(e))] P = PolynomialRing(GF(2), e*2, names, order='lex') x = P.gens()[e:] w = P.gens()[:e] diff --git a/src/sage/crypto/stream_cipher.py b/src/sage/crypto/stream_cipher.py index c6f46c8cef0..7eb69e3c7b7 100644 --- a/src/sage/crypto/stream_cipher.py +++ b/src/sage/crypto/stream_cipher.py @@ -95,7 +95,7 @@ def __call__(self, M, mode="ECB"): N = len(M) Melt = M._element_list Kelt = lfsr_sequence(poly.list(), IS, N) - return B([ (Melt[i]+int(Kelt[i]))%n for i in range(N) ]) + return B([ (Melt[i]+int(Kelt[i])) % n for i in range(N) ]) def _repr_(self): r""" diff --git a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py index de956719603..203eb70b563 100644 --- a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py @@ -232,7 +232,7 @@ def __classcall_private__(cls, dynamical_system, domain=None, ideal=None): 2*3^15 + 2*3^16 + 2*3^17 + 2*3^18 + 2*3^19 + 2*3^20 + O(3^21)) """ if not (is_Berkovich_Cp(domain) or domain is None): - raise TypeError('domain must be a Berkovich space over Cp, not %s' %domain) + raise TypeError('domain must be a Berkovich space over Cp, not %s' % domain) if isinstance(domain, Berkovich_Cp_Affine): if not isinstance(dynamical_system, DynamicalSystem_affine): @@ -269,7 +269,7 @@ def __classcall_private__(cls, dynamical_system, domain=None, ideal=None): raise ValueError('conflicting inputs for ideal and domain') else: raise ValueError('base ring of domain of dynamical_system must be p-adic or a number field ' - 'not %s' %morphism_domain.base_ring()) + 'not %s' % morphism_domain.base_ring()) if is_AffineSpace(morphism_domain): return DynamicalSystem_Berkovich_affine(dynamical_system, domain) @@ -444,7 +444,7 @@ def _repr_(self): """ domain_str = self._domain._repr_() return "Dynamical system of " + domain_str + " induced by the map" + \ - "\n Defn: %s"%('\n '.join(self._system._repr_defn().split('\n'))) + "\n Defn: %s" % ('\n '.join(self._system._repr_defn().split('\n'))) class DynamicalSystem_Berkovich_projective(DynamicalSystem_Berkovich): @@ -524,19 +524,19 @@ def __classcall_private__(cls, dynamical_system, domain=None): R = dynamical_system.base_ring() morphism_domain = dynamical_system.domain() if not is_ProjectiveSpace(morphism_domain): - raise TypeError('the domain of dynamical_system must be projective space, not %s' %morphism_domain) + raise TypeError('the domain of dynamical_system must be projective space, not %s' % morphism_domain) if morphism_domain.dimension_relative() != 1: raise ValueError('domain was not relative dimension 1') if not isinstance(R, pAdicBaseGeneric): if domain is None: - raise TypeError('dynamical system defined over %s, not p-adic, ' %morphism_domain.base_ring() + + raise TypeError('dynamical system defined over %s, not p-adic, ' % morphism_domain.base_ring() + 'and domain is None') if not isinstance(domain, Berkovich_Cp_Projective): - raise TypeError('domain was %s, not a projective Berkovich space over Cp' %domain) + raise TypeError('domain was %s, not a projective Berkovich space over Cp' % domain) if domain.base() != morphism_domain: - raise ValueError('base of domain was %s, with coordinate ring %s ' %(domain.base(), - domain.base().coordinate_ring())+ 'while dynamical_system acts on %s, ' %morphism_domain + - 'with coordinate ring %s' %morphism_domain.coordinate_ring()) + raise ValueError('base of domain was %s, with coordinate ring %s ' % (domain.base(), + domain.base().coordinate_ring()) + 'while dynamical_system acts on %s, ' % morphism_domain + + 'with coordinate ring %s' % morphism_domain.coordinate_ring()) else: domain = Berkovich_Cp_Projective(morphism_domain) return typecall(cls, dynamical_system, domain) @@ -686,7 +686,7 @@ def conjugate(self, M, adjugate=False, new_ideal=None): return DynamicalSystem_Berkovich(self._system.conjugate(M, adjugate=adjugate)) from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal if not (isinstance(new_ideal, NumberFieldFractionalIdeal) or new_ideal is None or new_ideal in ZZ): - raise TypeError('new_ideal must be an ideal of a number field, not %s' %new_ideal) + raise TypeError('new_ideal must be an ideal of a number field, not %s' % new_ideal) new_system = self._system.conjugate(M, adjugate=adjugate) system_domain = new_system.domain() if new_ideal is None: @@ -1003,15 +1003,15 @@ def __classcall_private__(cls, dynamical_system, domain=None): R = dynamical_system.base_ring() morphism_domain = dynamical_system.domain() if not is_AffineSpace(morphism_domain): - raise TypeError('the domain of dynamical_system must be affine space, not %s' %morphism_domain) + raise TypeError('the domain of dynamical_system must be affine space, not %s' % morphism_domain) if morphism_domain.dimension_relative() != 1: raise ValueError('domain not relative dimension 1') if not isinstance(R, pAdicBaseGeneric): if domain is None: - raise TypeError('dynamical system defined over %s, not padic, ' %morphism_domain.base_ring() + + raise TypeError('dynamical system defined over %s, not padic, ' % morphism_domain.base_ring() + 'and domain was not specified') if not isinstance(domain, Berkovich_Cp_Affine): - raise TypeError('domain was %s, not an affine Berkovich space over Cp' %domain) + raise TypeError('domain was %s, not an affine Berkovich space over Cp' % domain) else: domain = Berkovich_Cp_Affine(morphism_domain.base_ring()) return typecall(cls, dynamical_system, domain) @@ -1080,6 +1080,6 @@ def __call__(self, x): try: x = self.domain()(x) except (TypeError, ValueError): - raise ValueError('action of dynamical system not defined on %s' %x) + raise ValueError('action of dynamical system not defined on %s' % x) proj_system = self.homogenize(1) return proj_system(x.as_projective_point()).as_affine_point() diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index e8e5ddba1c4..d42d3ca8b2d 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -100,7 +100,7 @@ def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") z = R.gen(0) @@ -227,7 +227,7 @@ def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, elements.append(matrix(F, 2, [zeta, alpha*(1-zeta), 0, 1])) factors = (f2 - z*g2).factor() L1 = NumberField(z**2 + 1,'i') - i=L1.gen(0) + i = L1.gen(0) L2 = NumberField(z**2 + 3,'isqrt3') isqrt3 = L2.gen(0) for psi in factors: @@ -310,7 +310,7 @@ def height_bound(polynomial): 413526 """ # first check that polynomial is over QQ or ZZ - K=polynomial.parent() + K = polynomial.parent() if K.is_field(): R = K.ring() @@ -318,7 +318,7 @@ def height_bound(polynomial): R = K F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") # scale polynomial so that it has integer coefficients with gcd 1 @@ -672,7 +672,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun F = R.base_ring() - if F != QQ and F!= ZZ: + if F != QQ and F != ZZ: raise TypeError("coefficient ring is not the rational numbers or the integers") z = R.gen(0) @@ -739,7 +739,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun # the only possible groups are C_n, D_2n for n|6 or n|4 # all of these groups have order dividing 24 while (congruence < (2*MaxH**2)) and len(elements) < gcd(orderaut + [24]): - if badprimes%p != 0: #prime of good reduction + if badprimes % p != 0: #prime of good reduction # compute automorphisms mod p phi_p = f.change_ring(GF(p))/g.change_ring(GF(p)) sorted_automorphisms = automorphism_group_FF(phi_p) @@ -797,7 +797,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun # if an element of Aut_{F_p} has been lifted to QQ # remove that element from Aut_{F_p} so we don't # attempt to lift that element again unnecessarily - automorphisms=remove_redundant_automorphisms(automorphisms, + automorphisms = remove_redundant_automorphisms(automorphisms, orderelts, primepowers, temp) if order == 4: #have some elements of order 4 # so possible aut group is Z/4 or D_4 @@ -808,7 +808,7 @@ def automorphism_group_QQ_CRT(rational_function, prime_lower_bound=4, return_fun badorders.append(4) else: #no elements of order d in some F_v for m in divisors(N): - if m%order == 0: + if m % order == 0: badorders.append(m) #no elements of that order or any order that # is a multiple of it @@ -880,12 +880,12 @@ def automorphism_group_FF(rational_function, absolute=False, iso_type=False, ret if not return_functions: if absolute: - R=G[1][0].parent() + R = G[1][0].parent() if R.is_field(): R = R.ring() G[1] = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G[1]] else: - R=G[0].parent() + R = G[0].parent() if R.is_field(): R = R.ring() G = [matrix(R.base_ring(),[[R(g.numerator())[1],R(g.numerator())[0]],[R(g.denominator())[1],R(g.denominator())[0]]]) for g in G] @@ -941,7 +941,7 @@ def field_descent(sigma, y): if not remainder.is_constant(): return else: - x = x+ F(remainder) + x = x + F(remainder) steps = 1 while not quotient.is_constant(): @@ -949,7 +949,7 @@ def field_descent(sigma, y): if not remainder.is_constant(): return else: - x = x+ F(remainder)*a**(steps) + x = x + F(remainder)*a**(steps) steps += 1 return x + F(quotient)*a**(steps) @@ -1125,12 +1125,12 @@ def three_stable_points(rational_function, invariant_list): b = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0] - T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] - - T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][0] *T[t[2]][1] + + T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][0] * T[t[2]][1] + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][0] + T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][0]*T[t[2]][1] - T[0][1]*T[1][0]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][0]) - c = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + c = (T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][0]*T[1][1]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] - T[0][1]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + T[0][1]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + @@ -1138,10 +1138,10 @@ def three_stable_points(rational_function, invariant_list): T[0][1]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][0]*T[t[2]][1]) d = (T[0][0]*T[1][0]*T[2][1]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] - - T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][0]*T[1][0]*T[2][1]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][0]*T[1][1]*T[2][0]*T[t[0]][0]*T[t[1]][1]*T[t[2]][1] + T[0][0]*T[1][1]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0] + - T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][0] *T[t[2]][1]- + T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][0] * T[t[2]][1] - T[0][1]*T[1][0]*T[2][0]*T[t[0]][1]*T[t[1]][1]*T[t[2]][0]) if a*d - b*c != 0: @@ -1240,9 +1240,9 @@ def automorphism_group_FF_alg2(rational_function): y = fix.roots(multiplicities=False)[0] preimage = R(f(z) - y*g(z)) minimal_preimage = R(prod(x[0] for x in preimage.factor())) - if minimal_preimage.degree() + bool(preimage.degree()= 3: + if minimal_preimage.degree() + bool(preimage.degree() < D) >= 3: T_poly = minimal_preimage - infinity_check = bool(preimage.degree() max_reg_cyclic[0] and gcd(len(H), p) != p: max_reg_cyclic = [len(H), g, H] - discard = list(set(discard +H)) # adjoin all new elements to discard + discard = list(set(discard + H)) # adjoin all new elements to discard n_reg = max_reg_cyclic[0] # Test for dihedral subgroup. A subgroup of index 2 is always normal, so the diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py b/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py index 735e0800a6f..58df10c4a4c 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py @@ -273,7 +273,7 @@ def affine_minimal(vp, return_transformation=False, D=None, quick=False): #If the valuation of a prime in the resultant is small enough, we can say the #map is affine minimal at that prime without using the local minimality loop. See #Theorem 3.2.2 in [Molnar, M.Sc. thesis] - if d%2 == 0: + if d % 2 == 0: g = d else: g = 2*d @@ -1106,7 +1106,7 @@ def coshdelta(z): rep = 2*CC.gen(0) from math import isnan if isnan(v0.abs()): - raise ValueError("invalid covariant: %s"%v0) + raise ValueError("invalid covariant: %s" % v0) # get orbit S = matrix(ZZ,2,2,[0,-1,1,0]) diff --git a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py index 25d8645ae86..d09b15ab78c 100644 --- a/src/sage/dynamics/arithmetic_dynamics/generic_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/generic_ds.py @@ -217,10 +217,10 @@ def _repr_(self): 'Dynamical System of Projective Space of dimension 1 over Rational Field\n Defn: Defined on coordinates by sending (x : y) to\n (x^3 : x*y^2)' """ - s = "%s of %s"%(self._repr_type(), self.domain()) + s = "%s of %s" % (self._repr_type(), self.domain()) d = self._repr_defn() if d != '': - s += "\n Defn: %s"%('\n '.join(self._repr_defn().split('\n'))) + s += "\n Defn: %s" % ('\n '.join(self._repr_defn().split('\n'))) return s def as_scheme_morphism(self): diff --git a/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py index caf82a3b00d..9d6836c1e36 100644 --- a/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/product_projective_ds.py @@ -104,9 +104,9 @@ def _call_with_args(self, P, check=True): try: P = self.domain()(P) except (TypeError, NotImplementedError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self.domain())) - elif self.domain()!= P.codomain(): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self.domain())) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self.domain())) + elif self.domain() != P.codomain(): + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self.domain())) A = self.domain() Q = list(P) diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 6520177f4a7..ef1e50c78e9 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -2071,7 +2071,7 @@ def green_function(self, P, v, **kwds): K = R v = BR.places(prec=prec)[0] else: - raise ValueError("invalid valuation (=%s) entered"%v) + raise ValueError("invalid valuation (=%s) entered" % v) #Coerce all polynomials in F into polynomials with coefficients in K F = self.change_ring(K, check=False) @@ -2082,7 +2082,7 @@ def green_function(self, P, v, **kwds): if err is not None: err = R(err) if not err > 0: - raise ValueError("error bound (=%s) must be positive"%err) + raise ValueError("error bound (=%s) must be positive" % err) #if doing error estimates, compute needed number of iterates D = (dim + 1) * (d - 1) + 1 @@ -2115,7 +2115,7 @@ def green_function(self, P, v, **kwds): else: #non-archimedean h = max([c.local_height(v, prec=prec) for c in poly.coefficients()]) if h > maxh: - maxh=h + maxh = h if maxh == 0: maxh = 1 #avoid division by 0 if isinstance(v, RingHomomorphism_im_gens): #archimedean @@ -2126,7 +2126,7 @@ def green_function(self, P, v, **kwds): if C != 0: N = R(C / (err*(d-1))).log(d).abs().ceil() else: #we just need log||P||_v - N=1 + N = 1 #START GREEN FUNCTION CALCULATION if isinstance(v, RingHomomorphism_im_gens): #embedding for archimedean local height @@ -2550,7 +2550,7 @@ def multiplier(self, P, n, check=True): """ if check: if self.nth_iterate(P, n) != P: - raise ValueError("%s is not periodic of period %s"%(P, n)) + raise ValueError("%s is not periodic of period %s" % (P, n)) if n < 1: raise ValueError("period must be a positive integer") N = self.domain().ambient_space().dimension_relative() @@ -2689,7 +2689,7 @@ def _nth_preimage_tree_helper(self, Q, n, m, **kwds): if return_points: points = kwds["points"] - if n==1: + if n == 1: # Base case of recursion return D, points else: @@ -2699,7 +2699,7 @@ def _nth_preimage_tree_helper(self, Q, n, m, **kwds): D.update(self._nth_preimage_tree_helper(pt, n-1, m+1, **kwds)[0]) return D, points else: - if n==1: + if n == 1: # Base case of recursion return D else: @@ -3506,7 +3506,7 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): hyperplane_found = True break if not hyperplane_found: - raise ValueError('no possible conjugation over %s makes all preperiodic points affine' %R) + raise ValueError('no possible conjugation over %s makes all preperiodic points affine' % R) else: # if the characteristic is 0, R contains Z if R.characteristic() == 0: @@ -3541,7 +3541,7 @@ def affine_preperiodic_model(self, m, n, return_conjugation=False): if hyperplane_found: break else: - raise NotImplementedError('cannot find affine periodic model over %s' %(R)) + raise NotImplementedError('cannot find affine periodic model over %s' % (R)) source = PS.subscheme(CR.gens()[-1]) mat = PS.hyperplane_transformation_matrix(source, hyperplane) if R.is_field(): @@ -4176,7 +4176,7 @@ def critical_point_portrait(self, check=True, use_algebraic_closure=True): N = len(crit_points) for i in range(N): done = False - Q= F(crit_points[i]) + Q = F(crit_points[i]) while not done: if Q in crit_points: done = True @@ -6248,7 +6248,7 @@ def reduced_form(self, **kwds): pp_d = pts_poly.degree() pts_poly_CF = pts_poly_CF.subs({pts_poly_CF.parent().gen(1):1}).univariate_polynomial() max_mult = max([pp_d - pts_poly_CF.degree()] + [ex for p,ex in pts_poly_CF.roots()]) - assert (n<=4), "n > 4, failed to find usable poly" + assert (n <= 4), "n > 4, failed to find usable poly" G,m = pts_poly.reduced_form(prec=prec, emb=emb, smallest_coeffs=False) sm_f = self.conjugate(m) @@ -8150,7 +8150,7 @@ def is_conjugate(self, other, R=None, num_cpus=2): return m1.is_similar(m2) # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() - if (n==1) and (R in NumberFields() or R in FiniteFields())\ + if (n == 1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return False tup = conjugating_set_initializer(f, g) diff --git a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py index cc4078c017a..f1ea230df16 100644 --- a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py +++ b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py @@ -364,8 +364,8 @@ def Gpoly(self, component, k): i = Indices[0] j = Indices[1] - return (self._Lcoeff(component, j)**2) * (self._Qcoeff(component, i, i)) - (self._Lcoeff(component, i))* \ - (self._Lcoeff(component, j)) * (self._Qcoeff(component, i, j)) + (self._Lcoeff( component, i)**2)* \ + return (self._Lcoeff(component, j)**2) * (self._Qcoeff(component, i, i)) - (self._Lcoeff(component, i)) * \ + (self._Lcoeff(component, j)) * (self._Qcoeff(component, i, j)) + (self._Lcoeff( component, i)**2) * \ (self._Qcoeff( component, j, j)) @cached_method @@ -668,11 +668,11 @@ def Ramification_poly(self, i): - 168*y0*y1^2*y2^3 - 122*y1^3*y2^3 + 14*y0^2*y2^4 + 8*y0*y1*y2^4 - 112*y1^2*y2^4 + y2^6 """ return ((self._Lcoeff(i, 0))**2)*(self._Qcoeff(i, 1, 2))**2 + \ - ((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 2)**2)+ \ - ((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 0, 1)**2)- \ + ((self._Lcoeff(i, 1))**2)*(self._Qcoeff(i, 0, 2)**2) + \ + ((self._Lcoeff(i, 2))**2)*(self._Qcoeff(i, 0, 1)**2) - \ 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 2))\ - -2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 1, 2))\ - -2*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 0, 2)) + \ + - 2*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 1, 2))\ + - 2*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 0, 2)) + \ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 1))*(self._Qcoeff(i, 0, 1))*(self._Qcoeff(i, 2, 2)) + \ 4*(self._Lcoeff(i, 0))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 0, 2))*(self._Qcoeff(i, 1, 1)) + \ 4*(self._Lcoeff(i, 1))*(self._Lcoeff(i, 2))*(self._Qcoeff(i, 1, 2))*(self._Qcoeff(i, 0, 0)) - \ @@ -1104,7 +1104,7 @@ def sigmaX(self, P, **kwds): try: P = self(list(P)) except (TypeError, NotImplementedError, AttributeError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self)) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self)) pt = list(P[0]) + [0, 0, 0] if P[1][0] != 0: [a,b,c] = [P[1][0]*self.Gpoly(1, 0)(*pt), @@ -1134,11 +1134,11 @@ def sigmaX(self, P, **kwds): #Define the blow-up map with (s0,s1) the new `\mathbb{P}^1` coordinates #so that the points on the fiber come in pairs on the lines defined by `(s0,s1)` #this allows us to extend the involution to degenerate fibers - if P[0][0]!= 0: + if P[0][0] != 0: t1 = BR(P[0][1]/P[0][0]) t = w1 - t1 phi = R.hom([s0, s0*w1, s1*t + s0*P[0][2]/P[0][0], z0, z1, z2], S) - elif P[0][1]!= 0: + elif P[0][1] != 0: t1 = BR(P[0][0]/P[0][1]) t = w1 - t1 phi = R.hom([s0*w1, s0, s1*t + s0*P[0][2]/P[0][1], z0, z1, z2], S) @@ -1215,7 +1215,7 @@ def sigmaX(self, P, **kwds): for i in range(2, len(T)): e = 0 if newT[i] != 0: - while (newT[i]/s**e).subs({s:0})==0: + while (newT[i]/s**e).subs({s:0}) == 0: e += 1 maxexp.append(e) e = min(maxexp) @@ -1346,7 +1346,7 @@ def sigmaY(self,P, **kwds): try: P = self(list(P)) except (TypeError, NotImplementedError, AttributeError): - raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(P, self)) + raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (P, self)) pt = [0, 0, 0] + list(P[1]) if P[0][0] != 0: [a, b, c] = [P[0][0]*self.Gpoly(0, 0)(*pt), @@ -1380,7 +1380,7 @@ def sigmaY(self,P, **kwds): t1 = BR(P[1][1]/P[1][0]) t = w1 - t1 phi = R.hom([z0, z1, z2, s0, s0*w1, s1*t + s0*P[1][2]/P[1][0]], S) - elif P[1][1]!= 0: + elif P[1][1] != 0: t1 = BR(P[1][0]/P[1][1]) t = w1 - t1 phi = R.hom([z0, z1, z2, s0*w1, s0, s1*t + s0*P[1][2]/P[1][1]], S) @@ -1624,7 +1624,7 @@ def lambda_plus(self, P, v, N, m, n, prec=100): 0.89230705169161608922595928129 """ if not (v == 0 or v.is_prime()): - raise ValueError("invalid valuation (= %s) entered"%v) + raise ValueError("invalid valuation (= %s) entered" % v) R = RealField(prec) if v == 0: K = R @@ -1763,7 +1763,7 @@ def lambda_minus(self, P, v, N, m, n, prec=100): newQ = copy(Q) newQ.scale_by([1/Q[0][l], 1]) - if PK[1][i].abs()<= PK[1][k].abs(): + if PK[1][i].abs() <= PK[1][k].abs(): A = Rx(W.Gpoly(1, k))(tuple(newQ[0]))*PK[1][i]/PK[1][k] else: A = -Rx(W.Gpoly(1, i))(tuple(newQ[0]))*PK[1][k]/PK[1][i] @@ -2024,11 +2024,11 @@ def fiber(self, p, component): P0 = [Zero, Zero, Zero] + P Points = [] - if (self.Gpoly(component,0)(P0)!= 0): + if (self.Gpoly(component,0)(P0) != 0): #We are using the quadratic formula, we need this check to ensure that the points #will be rational - T0 = (self.Hpoly(component, 0, 1)(P0)**2 -4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0)) - T1 = (self.Hpoly(component, 0, 2)(P0)**2 -4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0)) + T0 = (self.Hpoly(component, 0, 1)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 1)(P0)) + T1 = (self.Hpoly(component, 0, 2)(P0)**2 - 4*self.Gpoly(component, 0)(P0)*self.Gpoly(component, 2)(P0)) if (T0.is_square() and T1.is_square()): T0 = T0.sqrt() T1 = T1.sqrt() diff --git a/src/sage/dynamics/cellular_automata/solitons.py b/src/sage/dynamics/cellular_automata/solitons.py index 7ae254ed69f..4afb3f104a2 100644 --- a/src/sage/dynamics/cellular_automata/solitons.py +++ b/src/sage/dynamics/cellular_automata/solitons.py @@ -951,7 +951,7 @@ def print_states(self, num=None, vacuum_letter='.'): state = [vacuum]*(num_factors - len(state)) + list(state) output = [self._column_repr(b, vacuum_letter) for b in state] max_width = max(b.width() for b in output) - start = ascii_art("t: %s \n"%i) + start = ascii_art("t: %s \n" % i) start._baseline = -1 print(start + sum((ascii_art(' '*(max_width-b.width())) + b for b in output), @@ -1024,7 +1024,7 @@ def latex_states(self, num=None, as_array=True, box_width='5pt'): def compact_repr(b): if as_array and b == vacuum: - return "\\makebox[%s]{.}"%box_width + return "\\makebox[%s]{.}" % box_width if b.parent()._tableau_height == 1: temp = latex(b[0]) @@ -1034,22 +1034,22 @@ def compact_repr(b): temp += "\\end{array}" if b == vacuum: - return "{\\color{gray} %s}"%temp + return "{\\color{gray} %s}" % temp return temp # "\\makebox[%s]{$%s$}"%(box_width, temp) num_factors = len(self._states[num-1]) if as_array: ret = "{\\arraycolsep=0.5pt \\begin{array}" - ret += "{c|c%s}\n"%('c'*num_factors) + ret += "{c|c%s}\n" % ('c'*num_factors) else: ret = "{\\begin{array}" ret += "{c|c}\n" for i,state in enumerate(self._states[:num]): state = [vacuum]*(num_factors-len(state)) + list(state) if as_array: - ret += "t = %s & \\cdots & %s \\\\\n"%(i, r" & ".join(compact_repr(b) for b in state)) + ret += "t = %s & \\cdots & %s \\\\\n" % (i, r" & ".join(compact_repr(b) for b in state)) else: - ret += "t = %s & \\cdots %s \\\\\n"%(i, r" ".join(compact_repr(b) for b in state)) + ret += "t = %s & \\cdots %s \\\\\n" % (i, r" ".join(compact_repr(b) for b in state)) ret += "\\end{array}}\n" return LatexExpr(ret) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index f0a8620011a..1b4a60b0013 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -4165,7 +4165,7 @@ def relative_quotient(self, subcone): Nsubcone = subcone.sublattice() extra_ray = None - if Ncone.dimension()-Nsubcone.dimension()==1: + if Ncone.dimension()-Nsubcone.dimension() == 1: extra_ray = set(self.rays().set() - subcone.rays().set()).pop() Q = Ncone.quotient(Nsubcone, positive_point=extra_ray) @@ -4262,7 +4262,7 @@ def relative_orthogonal_quotient(self, supercone): Msupercone = supercone.orthogonal_sublattice() extra_ray = None - if Mcone.dimension()-Msupercone.dimension()==1: + if Mcone.dimension()-Msupercone.dimension() == 1: extra_ray = set(supercone.rays().set() - self.rays().set()).pop() Q = Mcone.quotient(Msupercone, positive_dual_point=extra_ray) @@ -4391,7 +4391,7 @@ def semigroup_generators(self): origin = self.nrays() # last one in pc pc = PointConfiguration(tuple(self.rays()) + (N(0),), star=origin) triangulation = pc.triangulate() - subcones = ( Cone(( self.ray(i) for i in simplex if i!=origin ), + subcones = ( Cone(( self.ray(i) for i in simplex if i != origin ), lattice=N, check=False) for simplex in triangulation ) gens = set() diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 26c7d9a3819..7847955db7b 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -3239,7 +3239,7 @@ def index_of_max(iterable): * permutations[n_s][1] if d == 0: d = (PM[k, permutations[n_s][1](i+1) - 1] - -permutations[0][1](first_row)[i]) + - permutations[0][1](first_row)[i]) if d < 0: break if d < 0: @@ -3309,7 +3309,7 @@ def index_of_max(iterable): if d < 0: # We move to the next line continue - elif d==0: + elif d == 0: # Maximal values agree, so possible symmetry if s != l: permutations_bar[n_p][0] = S_f((l + 1, s + 1), check=False) * permutations_bar[n_p][0] diff --git a/src/sage/geometry/polyhedron/backend_polymake.py b/src/sage/geometry/polyhedron/backend_polymake.py index 624ae2f6340..089e687f3f8 100644 --- a/src/sage/geometry/polyhedron/backend_polymake.py +++ b/src/sage/geometry/polyhedron/backend_polymake.py @@ -537,7 +537,7 @@ def _init_Hrepresentation_from_polymake(self): self._Hrepresentation = [] parent = self.parent() for g in p.FACETS.sage(): - if all(x==0 for x in g[1:]): + if all(x == 0 for x in g[1:]): # Ignore vertical inequality pass else: diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 007f000eb56..d31c5bc254c 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -38,7 +38,7 @@ def _is_zero(self, x): sage: p._is_zero(1/100000) False """ - return x==0 + return x == 0 def _is_nonneg(self, x): """ @@ -60,7 +60,7 @@ def _is_nonneg(self, x): sage: p._is_nonneg(-1/100000) False """ - return x>=0 + return x >= 0 def _is_positive(self, x): """ @@ -82,7 +82,7 @@ def _is_positive(self, x): sage: p._is_positive(0) False """ - return x>0 + return x > 0 _base_ring = QQ diff --git a/src/sage/geometry/polyhedron/base_RDF.py b/src/sage/geometry/polyhedron/base_RDF.py index fe75503edf2..b3ba587746e 100644 --- a/src/sage/geometry/polyhedron/base_RDF.py +++ b/src/sage/geometry/polyhedron/base_RDF.py @@ -45,7 +45,7 @@ def _is_zero(self, x): sage: p._is_zero(1e-10) True """ - return abs(x)<=1e-6 + return abs(x) <= 1e-6 def _is_nonneg(self, x): """ @@ -72,7 +72,7 @@ def _is_nonneg(self, x): sage: p._is_nonneg(-1e-10) True """ - return x>=-1e-6 + return x >= -1e-6 def _is_positive(self, x): """ @@ -99,6 +99,6 @@ def _is_positive(self, x): sage: p._is_positive(-1e-10) True """ - return x>=-1e-6 + return x >= -1e-6 _base_ring = RDF diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 561ed76d70c..5e6633c7b3f 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -736,12 +736,12 @@ def _subpoly_parallel_facets(self): sage: list( Polyhedron()._subpoly_parallel_facets() ) [The empty polyhedron in ZZ^0] """ - if self.dim()>2 or not self.is_compact(): + if self.dim() > 2 or not self.is_compact(): raise NotImplementedError('only implemented for bounded polygons') from sage.geometry.polyhedron.plot import cyclic_sort_vertices_2d vertices = cyclic_sort_vertices_2d(self.vertices()) n = len(vertices) - if n==1: # single point + if n == 1: # single point yield self return edge_vectors = [] @@ -759,7 +759,7 @@ def _subpoly_parallel_facets(self): for e in edges: point += e v.append(point) - if point!=origin: # does not close up, not a subpolygon + if point != origin: # does not close up, not a subpolygon continue yield parent([v, [], []], None) diff --git a/src/sage/geometry/polyhedron/cdd_file_format.py b/src/sage/geometry/polyhedron/cdd_file_format.py index 4388f2ecb0b..728f20bb9b5 100644 --- a/src/sage/geometry/polyhedron/cdd_file_format.py +++ b/src/sage/geometry/polyhedron/cdd_file_format.py @@ -128,7 +128,7 @@ def cdd_Hrepresentation(cdd_type, ieqs, eqns, file_output=None): s = 'H-representation\n' if eqns is not None: - assert len(eqns)>0 + assert len(eqns) > 0 n = len(eqns) s += "linearity " + repr(n) + ' ' s += _to_space_separated_string(range(1,n+1)) + '\n' diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 91e4d4de82f..e62e108e61d 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -153,13 +153,13 @@ def LatticePolytope_PPL(*args): TypeError: polyhedron has non-integral generators """ polytope_class = LatticePolytope_PPL_class - if len(args)==1 and isinstance(args[0], C_Polyhedron): + if len(args) == 1 and isinstance(args[0], C_Polyhedron): polyhedron = args[0] polytope_class = _class_for_LatticePolytope(polyhedron.space_dimension()) if not all(p.is_point() and p.divisor() == 1 for p in polyhedron.generators()): raise TypeError('polyhedron has non-integral generators') return polytope_class(polyhedron) - if len(args)==1 \ + if len(args) == 1 \ and isinstance(args[0], (list, tuple)) \ and isinstance(args[0][0], (list,tuple)): vertices = args[0] @@ -278,7 +278,7 @@ def is_simplex(self): sage: LatticePolytope_PPL((0,0,0), (1,0,0), (0,1,0)).is_simplex() True """ - return self.affine_dimension()+1==self.n_vertices() + return self.affine_dimension()+1 == self.n_vertices() @cached_method def bounding_box(self): @@ -467,7 +467,7 @@ def integral_points_not_interior_to_facets(self): ((-1, -1), (-1, 1), (0, 0), (1, -1), (1, 1)) """ n = 1 + self.space_dimension() - self.affine_dimension() - return tuple(p[0] for p in self._integral_points_saturating() if len(p[1])!=n) + return tuple(p[0] for p in self._integral_points_saturating() if len(p[1]) != n) @cached_method def vertices(self): @@ -586,7 +586,7 @@ def fibration_generator(self, dim): # "points" are the potential vertices of the fiber. They are # in the $codim$-skeleton of the polytope, which is contained # in the points that saturate at least $dim$ equations. - points = [ p for p in self._integral_points_saturating() if len(p[1])>=dim ] + points = [ p for p in self._integral_points_saturating() if len(p[1]) >= dim ] points = sorted(points, key=lambda x:len(x[1])) # iterate over point combinations subject to all points being on one facet. @@ -597,7 +597,7 @@ def point_combinations_iterator(n, i0=0, saturated=None): saturated_ieqs = ieqs else: saturated_ieqs = saturated.intersection(ieqs) - if len(saturated_ieqs)==0: + if len(saturated_ieqs) == 0: continue if n == 1: yield [i] diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index 554e36ec239..76a7d8831fa 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -1068,7 +1068,7 @@ def _repr_(self): have_A = not self.A().is_zero() if have_A: s += repr(self.A()) + ' x ' - if self.b()>=0: + if self.b() >= 0: if have_A: s += '+' else: diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 8ce4496c65a..cc52979b577 100644 --- a/src/sage/geometry/pseudolines.py +++ b/src/sage/geometry/pseudolines.py @@ -240,9 +240,9 @@ def __init__(self, seq, encoding="auto"): self._n = max(map(max, seq)) + 1 if (self._n * (self._n-1))/2 != len(seq): raise ValueError( - "A line is numbered "+str(self._n-1)+" but the number"+ - " of transpositions is different from binomial("+ - str(self._n-1)+",2). Are the lines numbered from 0 to n-1?"+ + "A line is numbered "+str(self._n-1)+" but the number" + + " of transpositions is different from binomial(" + + str(self._n-1)+",2). Are the lines numbered from 0 to n-1?" + " Are they really non-parallel? Please check the documentation.") self._permutations = [[] for i in range(self._n)] @@ -258,12 +258,12 @@ def __init__(self, seq, encoding="auto"): self._n = len(seq) self._permutations = [list(_) for _ in seq] - if max(map(max, seq)) != self._n -1 : + if max(map(max, seq)) != self._n - 1 : raise ValueError("Are the lines really numbered from 0 to n-1?") # Felsner encoding elif (encoding == "Felsner" or - (encoding == "auto" and len(seq[0]) == len(seq) -1)): + (encoding == "auto" and len(seq[0]) == len(seq) - 1)): seq = deepcopy(seq) self._n = len(seq) @@ -339,14 +339,14 @@ def transpositions(self): k = 0 while i != perm[perm[i][0]][0]: i = perm[i][0] - k+= 1 + k += 1 if k > self._n: raise ValueError( - "It looks like the data does not correspond to a"+ - "pseudoline arrangement. We have found k>2 lines"+ - "such that the ith line meets the (i+1)th before"+ - " the (i-1)th (this creates a cyclic dependency)"+ + "It looks like the data does not correspond to a" + + "pseudoline arrangement. We have found k>2 lines" + + "such that the ith line meets the (i+1)th before" + + " the (i-1)th (this creates a cyclic dependency)" + " which is totally impossible.") t.append((i, perm[i][0])) @@ -446,10 +446,10 @@ def show(self, **args): if abs(iy-jy) != 1: raise ValueError( - "There has been a problem while plotting the figure. It "+ - "seems that the lines are not correctly ordered. Please "+ + "There has been a problem while plotting the figure. It " + + "seems that the lines are not correctly ordered. Please " + "check the pseudolines modules documentation, there is a " - +"warning about that. ") + + "warning about that. ") lines[i].append((x+2,jy)) lines[j].append((x+2,iy)) diff --git a/src/sage/geometry/ribbon_graph.py b/src/sage/geometry/ribbon_graph.py index 809d6edba9a..12918ae29b5 100644 --- a/src/sage/geometry/ribbon_graph.py +++ b/src/sage/geometry/ribbon_graph.py @@ -988,7 +988,7 @@ def homology_basis(self): del vertices[i][2*m:2*m+2] k = 0 else: - k+=1 + k += 1 for i in range(len(basis)): for j in range(1, len(basis[i])): @@ -1074,9 +1074,9 @@ def normalize(self): pos_sigma = _find(aux_sigma,aux_val) #Now we set the found positions to the new normalized value - darts_rho[pos_darts]=i+1 - aux_sigma[pos_sigma[0]][pos_sigma[1]]=i+1 - aux_rho[pos_rho[0]][pos_rho[1]]=i+1 + darts_rho[pos_darts] = i+1 + aux_sigma[pos_sigma[0]][pos_sigma[1]] = i+1 + aux_rho[pos_rho[0]][pos_rho[1]] = i+1 return RibbonGraph( PermutationConstructor([tuple(x) for x in aux_sigma]), @@ -1213,7 +1213,7 @@ def bipartite_ribbon_graph(p, q): aux_tuple = [i*q + j + 1 for j in range(q)] sigma += [aux_tuple] for i in range(q): - aux_tuple = [p*q + i*p + j +1 for j in range(p)] + aux_tuple = [p*q + i*p + j + 1 for j in range(p)] sigma += [aux_tuple] for i in range(p*q): if (i+1) % q == 0: @@ -1223,7 +1223,7 @@ def bipartite_ribbon_graph(p, q): t = 0 if (i+1) % q != 0: t = 1 - aux_edge = [i+1, p*q + k*p - ((i+1 + t*q)/q).floor() +1] + aux_edge = [i+1, p*q + k*p - ((i+1 + t*q)/q).floor() + 1] rho += [aux_edge] return RibbonGraph( PermutationConstructor([tuple(x) for x in sigma]), diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index c0161ab0c4f..fd56b956c90 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -415,7 +415,7 @@ def _repr_(self): name = 'Parametrized surface' if self.name is not None: name += " ('%s')" % self.name - s ='%(designation)s with equation %(eq)s' % \ + s = '%(designation)s with equation %(eq)s' % \ {'designation': name, 'eq': str(self.equation)} return s @@ -1410,7 +1410,7 @@ def shape_operator(self): """ shop = self.shape_operator_coefficients() - shop_matrix=matrix([[shop[(1,1)],shop[(1,2)]], + shop_matrix = matrix([[shop[(1,1)],shop[(1,2)]], [shop[(2,1)],shop[(2,2)]]]) return shop_matrix @@ -1492,10 +1492,10 @@ def connection_coefficients(self): for i,j,k in product((1, 2), repeat=3): dg[(i,j,k)] = _simplify_full_rad(gg[(j,k)].differentiate(x[i])) - structfun={} + structfun = {} for i,j,k in product((1, 2), repeat=3): structfun[(i,j,k)] = sum(gi[(k,s)]*(dg[(i,j,s)] + dg[(j,i,s)] - -dg[(s,i,j)])/2 + - dg[(s,i,j)])/2 for s in (1,2)) structfun[(i,j,k)] = _simplify_full_rad(structfun[(i,j,k)]) return structfun diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index c5d35bb2002..a72f31f04d2 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -582,9 +582,9 @@ def direct_sum(self, other): def make_name(N1, N2, use_latex=False): if use_latex: - return latex(N1)+ r' \oplus ' +latex(N2) + return latex(N1) + r' \oplus ' + latex(N2) else: - return N1._name+ '+' +N2._name + return N1._name + '+' + N2._name rank = self.rank() + other.rank() name = make_name(self, other, False) @@ -1492,7 +1492,7 @@ def __init__(self, V, W, check=True, positive_point=None, positive_dual_point=No return self._flip_sign_of_generator = False - assert self.is_torsion_free() and self.ngens()==1, \ + assert self.is_torsion_free() and self.ngens() == 1, \ 'You may only specify a positive direction in the codimension one case.' quotient_generator = self.gen(0) lattice = self.V().ambient_module() @@ -1500,16 +1500,16 @@ def __init__(self, V, W, check=True, positive_point=None, positive_dual_point=No assert positive_point in lattice, 'positive_point must be a lattice point.' point_quotient = self(positive_point) scalar_product = quotient_generator.vector()[0] * point_quotient.vector()[0] - if scalar_product==0: + if scalar_product == 0: raise ValueError(str(positive_point)+' is zero in the quotient.') elif (positive_point is None) and (positive_dual_point is not None): assert positive_dual_point in lattice.dual(), 'positive_dual_point must be a dual lattice point.' scalar_product = quotient_generator.lift() * positive_dual_point - if scalar_product==0: + if scalar_product == 0: raise ValueError(str(positive_dual_point)+' is zero on the lift of the quotient generator.') else: raise ValueError('You may not specify both positive_point and positive_dual_point.') - self._flip_sign_of_generator = (scalar_product<0) + self._flip_sign_of_generator = (scalar_product < 0) def gens(self): """ @@ -1529,7 +1529,7 @@ def gens(self): """ gens = self.smith_form_gens() if self._flip_sign_of_generator: - assert len(gens)==1 + assert len(gens) == 1 return (-gens[0],) else: return gens diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index 7486488adb1..16b55ab7cac 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -80,9 +80,9 @@ def triangulation_render_2d(triangulation, **kwds): tmp_lines = [] for t in triangulation: - if len(t)>=2: + if len(t) >= 2: tmp_lines.append([t[0], t[1]]) - if len(t)>=3: + if len(t) >= 3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) all_lines = [] @@ -103,7 +103,7 @@ def triangulation_render_2d(triangulation, **kwds): plot_triangs = sum([ polygon2d([coord[t[0]], coord[t[1]], coord[t[2]]], zorder=0, rgbcolor=(0.8, 1, 0.8), **kwds) - for t in triangulation if len(t)>=3 ]) + for t in triangulation if len(t) >= 3 ]) return \ plot_points + \ @@ -142,12 +142,12 @@ def triangulation_render_3d(triangulation, **kwds): tmp_lines = [] for t in triangulation: - if len(t)>=2: + if len(t) >= 2: tmp_lines.append([t[0], t[1]]) - if len(t)>=3: + if len(t) >= 3: tmp_lines.append([t[0], t[2]]) tmp_lines.append([t[1], t[2]]) - if len(t)>=4: + if len(t) >= 4: tmp_lines.append([t[0], t[3]]) tmp_lines.append([t[1], t[3]]) tmp_lines.append([t[2], t[3]]) @@ -175,9 +175,9 @@ def triangulation_render_3d(triangulation, **kwds): tmp_triangs = [] for t in triangulation: - if len(t)>=3: + if len(t) >= 3: tmp_triangs.append([t[0], t[1], t[2]]) - if len(t)>=4: + if len(t) >= 4: tmp_triangs.append([t[0], t[1], t[3]]) tmp_triangs.append([t[0], t[2], t[3]]) tmp_triangs.append([t[1], t[2], t[3]]) @@ -265,7 +265,7 @@ def __init__(self, triangulation, parent, check=True): except TypeError: triangulation = tuple( self.point_configuration().int_to_simplex(i) for i in triangulation ) - assert not check or all( len(t)==self.point_configuration().dim()+1 + assert not check or all( len(t) == self.point_configuration().dim()+1 for t in triangulation) self._triangulation = triangulation @@ -924,4 +924,4 @@ def adjacency_graph(self): """ vertices = [Set(_) for _ in list(self)] return Graph([vertices, - lambda x,y: len(x-y)==1]) + lambda x,y: len(x-y) == 1]) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index d75af2af4ce..14afe670c16 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -287,7 +287,7 @@ def _have_TOPCOM(cls): out = next(PointConfiguration._TOPCOM_exec('points2placingtriang', '[[0,1],[1,1]]', verbose=False)) PointConfiguration._have_TOPCOM_cached = True - assert out=='{{0,1}}',\ + assert out == '{{0,1}}',\ 'TOPCOM ran but did not produce the correct output!' except pexpect.ExceptionPexpect: PointConfiguration._have_TOPCOM_cached = False @@ -320,7 +320,7 @@ def __classcall__(cls, points, projective=False, connected=True, fine=False, reg defined_affine = True if star is not None and star not in ZZ: star_point = tuple(star) - if len(star_point)0 for t in triangulation): + if not all( t.count(o) > 0 for t in triangulation): continue yield self(triangulation) @@ -1228,7 +1228,7 @@ def face_interior(self, dim=None, codim=None): d = [ self.face_codimension(i) for i in range(self.n_points()) ] - return tuple( tuple(i for i in range(self.n_points()) if d[i]==codim ) + return tuple( tuple(i for i in range(self.n_points()) if d[i] == codim ) for codim in range(self.dim()+1) ) def exclude_points(self, point_idx_list): @@ -1408,12 +1408,12 @@ def circuits_support(self): independent_k = [] for idx in possible_dependency: rk = matrix([ U[i] for i in idx ]).rank() - if rk==k: + if rk == k: independent_k.append(idx) else: supports_k.append(idx) yield idx - assert independent_k==[] # there are no independent (self.dim()+3)-tuples + assert independent_k == [] # there are no independent (self.dim()+3)-tuples def circuits(self): r""" @@ -1476,9 +1476,9 @@ def circuits(self): for support in self.circuits_support(): m = matrix([ U[i] for i in support ]).transpose() ker = m.right_kernel().basis()[0] - assert len(ker)==len(support) - Cplus = [ support[i] for i in range(len(support)) if ker[i]>0 ] - Cminus = [ support[i] for i in range(len(support)) if ker[i]<0 ] + assert len(ker) == len(support) + Cplus = [ support[i] for i in range(len(support)) if ker[i] > 0 ] + Cminus = [ support[i] for i in range(len(support)) if ker[i] < 0 ] Czero = set( range(n) ).difference(support) Circuits += ( (tuple(Cplus), tuple(Czero), tuple(Cminus)), ) self._circuits = Circuits @@ -1627,7 +1627,7 @@ def lexicographic_triangulation(self): basepts = [ b[1:] for b in basepts ] # undecorate def make_cotriang(basepts): - if len(basepts)==0: + if len(basepts) == 0: return [frozenset()] triangulation = set() for tail in make_cotriang(basepts[1:]): @@ -1782,7 +1782,7 @@ def farthest_point(self, points, among=None): sage: pc.farthest_point([pc.point(0)]) P(1, 1) """ - if len(points)==0: + if len(points) == 0: return self.point(0) if among is None: among = self.points() @@ -1795,7 +1795,7 @@ def farthest_point(self, points, among=None): d_max = min(self.distance(p,q) for q in points) continue d = min(self.distance(p,q) for q in points) - if d>d_max: + if d > d_max: p_max = p return p_max diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py index b2d329e064b..0705d4ecd88 100644 --- a/src/sage/manifolds/chart.py +++ b/src/sage/manifolds/chart.py @@ -3140,7 +3140,7 @@ def _plot_xx_list(xx_list, rem_coords, ranges, steps, number_values): elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) - if nca != 2 and nca !=3: + if nca != 2 and nca != 3: raise ValueError("bad number of ambient coordinates: {}".format(nca)) if ranges is None: ranges = {} diff --git a/src/sage/manifolds/differentiable/automorphismfield_group.py b/src/sage/manifolds/differentiable/automorphismfield_group.py index 72955d48b3c..c0e782798aa 100644 --- a/src/sage/manifolds/differentiable/automorphismfield_group.py +++ b/src/sage/manifolds/differentiable/automorphismfield_group.py @@ -355,7 +355,7 @@ def _latex_(self): """ from sage.misc.latex import latex - return r"\mathrm{GL}\left("+ latex(self._vmodule)+ r"\right)" + return r"\mathrm{GL}\left(" + latex(self._vmodule) + r"\right)" def base_module(self): r""" diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index 7ee1517c43d..fd77c39dfc4 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -650,7 +650,7 @@ def tangent_vector_field(self, name=None, latex_name=None): if latex_name is None: if name is None: if self._latex_name is not None: - latex_name = r"{%s'}"%(self._latex_name) + latex_name = r"{%s'}" % (self._latex_name) else: latex_name = name if name is None and self._name is not None: @@ -912,7 +912,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) - if n_pc != 2 and n_pc !=3: + if n_pc != 2 and n_pc != 3: raise ValueError("the number of coordinates involved in the " + "plot must be either 2 or 3, not {}".format(n_pc)) # indices of plot coordinates diff --git a/src/sage/manifolds/differentiable/degenerate.py b/src/sage/manifolds/differentiable/degenerate.py index 30846aa6891..82de8c39d74 100644 --- a/src/sage/manifolds/differentiable/degenerate.py +++ b/src/sage/manifolds/differentiable/degenerate.py @@ -479,7 +479,7 @@ def __init__(self, tensor, embedding, screen=None): self.display(frame) for i in self._domain._ambient.index_generator(tensor.tensor_rank()): for j in range(len(i)): - if i[j]==self._domain._ambient._dim-self._domain._sindex-1: + if i[j] == self._domain._ambient._dim-self._domain._sindex-1: self[frame, i] = 0 def __call__(self, *args): @@ -517,7 +517,7 @@ def __call__(self, *args): except ValueError: pass if not self._domain.is_tangent(vector): - raise ValueError("The provided vector field is not "+ + raise ValueError("The provided vector field is not " + "tangent to {}".format(self._domain._name)) try: return TensorField.__call__(self._tensor.along(self._embedding), *args) diff --git a/src/sage/manifolds/differentiable/degenerate_submanifold.py b/src/sage/manifolds/differentiable/degenerate_submanifold.py index 67d5228f2d9..581162b88f5 100644 --- a/src/sage/manifolds/differentiable/degenerate_submanifold.py +++ b/src/sage/manifolds/differentiable/degenerate_submanifold.py @@ -500,7 +500,7 @@ def set_transverse(self, rigging=None, normal=None): raise ValueError("{} is normal to {}".format(u.display(), self._name)) rig.append(u) l2 += 1 - if l1+l2!=self._codim: + if l1+l2 != self._codim: raise ValueError("length of the transverse must be {}".format(self._codim)) self._transverse['normal'] = tuple(nor) self._transverse['rigging'] = tuple(rig) @@ -558,12 +558,12 @@ def screen(self, name, screen, rad, latex_name=None): else: rad = [rad] if name in self._screens: - if list(screen)==self._screens[name]._screen and list(rad)==self._screens[name]._rad: + if list(screen) == self._screens[name]._screen and list(rad) == self._screens[name]._rad: return self._screens[name] else: raise ValueError("a different screen distribution with the " "same name had already been set") - if len(screen)+len(rad)!=self._dim: + if len(screen)+len(rad) != self._dim: raise ValueError("total length screen+rad must be {}".format(self._dim)) frame = self.default_frame() im = self.immersion() @@ -625,7 +625,7 @@ def induced_metric(self) -> DegenerateMetric: submanifold S embedded in 4-dimensional differentiable manifold M """ - if self._induced_metric is None or self._induced_metric._components=={}: + if self._induced_metric is None or self._induced_metric._components == {}: self._induced_metric = self.metric() self._induced_metric.set( self.immersion().pullback(self.ambient_metric())) @@ -741,7 +741,7 @@ def _ambient_decomposition(self, screen=None): rig = self._transverse['rigging'] else: raise ValueError("set first a screen distribution") - if self._codim==1: + if self._codim == 1: xi = rad[0] v = rig[0] g = self.ambient_metric() @@ -833,7 +833,7 @@ def _adapted_frame_(self, screen=None): self.set_change_of_frame(f.along(self.immersion()), e.along( self.immersion()), GLHPhi(A.along(self.immersion()))) b = e.dual_basis() - if self._codim==1: + if self._codim == 1: if not self._adapted_frame: e[self._dim-self._sindex].set_name('N') else: @@ -893,7 +893,7 @@ def adapted_frame(self, screen=None): """ e = self._adapted_frame_(screen).along(self.immersion()) b = e.dual_basis() - if self._codim==1: + if self._codim == 1: if not self._adapted_frame: e[self._dim-self._sindex].set_name('N') else: @@ -959,7 +959,7 @@ def second_fundamental_form(self, screen=None): """ if self._ambient._dim-self._dim != 1: - raise ValueError("'second_fundamental_form' is defined"+ + raise ValueError("'second_fundamental_form' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1018,7 +1018,7 @@ def projection(self, tensor, screen=None): sage: U1 = S.projection(U) # long time """ - if tensor.tensor_type()[0]!=1: + if tensor.tensor_type()[0] != 1: raise NotImplementedError("``projection`` is implemented only for " "tensors with 1 as contravariant order") return TangentTensor(tensor, self.immersion(), screen) @@ -1061,8 +1061,8 @@ def screen_projection(self, tensor, screen=None): sage: U1 = S.screen_projection(U); # long time """ - if tensor.tensor_type()[0]!=1: - raise NotImplementedError("``projection`` is implemented only for "+ + if tensor.tensor_type()[0] != 1: + raise NotImplementedError("``projection`` is implemented only for " + "tensors with 1 as contravariant order") frame = self.adapted_frame(screen) T = tensor.copy() @@ -1299,7 +1299,7 @@ def principal_directions(self, screen=None): """ if self._codim != 1: - raise ValueError("'principal directions' is defined"+ + raise ValueError("'principal directions' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1316,7 +1316,7 @@ def principal_directions(self, screen=None): for eigen_vector in eigen_space[1]: v = self._ambient.vector_field(name="e_{}".format(next(counter)) ).along(self.immersion()) - v[frame, :] = [elt for elt in eigen_vector]+ [0] + v[frame, :] = [elt for elt in eigen_vector] + [0] res.append((TangentTensor(v, self.immersion()), self.scalar_field( {chart: eigen_space[0] for chart in self.top_charts()}))) #res[-1][0].set_name("e_{}".format(next(counter))) @@ -1367,7 +1367,7 @@ def mean_curvature(self, screen=None): """ if self._codim != 1: - raise ValueError("'mean_curvature' is defined"+ + raise ValueError("'mean_curvature' is defined" + " only for hypersurfaces.") if screen is None: screen = self.default_screen() @@ -1650,7 +1650,7 @@ def normal_tangent_vector(self): """ rad = [elt.along(self._domain.immersion()) for elt in self._rad] - if self._domain._codim==1: + if self._domain._codim == 1: xi = rad[0] xi.set_name(name='xi', latex_name=r'\xi') return xi @@ -1695,7 +1695,7 @@ def rigging(self): """ im = self._domain.immersion() rig = [elt.along(im) for elt in self._domain._transverse['rigging']] - if self._domain._codim!=1: + if self._domain._codim != 1: return rig xi = self.normal_tangent_vector() v = rig[0] diff --git a/src/sage/manifolds/differentiable/diff_map.py b/src/sage/manifolds/differentiable/diff_map.py index ded6843afb3..a6f960c76f8 100644 --- a/src/sage/manifolds/differentiable/diff_map.py +++ b/src/sage/manifolds/differentiable/diff_map.py @@ -641,11 +641,11 @@ def differential(self, point: ManifoldPoint) -> FiniteRankFreeModuleMorphism: for i in range(n2)] bases = (chart1.frame().at(point), chart2.frame().at(image_point)) if self._name is not None and point._name is not None: - name = 'd%s_%s'%(self._name, point._name) + name = 'd%s_%s' % (self._name, point._name) else: name = None if self._latex_name is not None and point._latex_name is not None: - latex_name = r'{\mathrm{d}%s}_{%s}'%(self._latex_name, + latex_name = r'{\mathrm{d}%s}_{%s}' % (self._latex_name, point._latex_name) else: latex_name = None diff --git a/src/sage/manifolds/differentiable/integrated_curve.py b/src/sage/manifolds/differentiable/integrated_curve.py index 74f76ab3e33..0d01a9afd70 100644 --- a/src/sage/manifolds/differentiable/integrated_curve.py +++ b/src/sage/manifolds/differentiable/integrated_curve.py @@ -523,7 +523,7 @@ def __init__(self, parent, equations_rhs, velocities, # extract all the variables appearing in the initial tangent # vector components: initial_coord_basis = chart.frame().at(initial_pt) - initial_tgt_vec_comps=initial_tangent_vector[initial_coord_basis,:] + initial_tgt_vec_comps = initial_tangent_vector[initial_coord_basis,:] for comp in initial_tgt_vec_comps: if isinstance(comp, Expression): parameters = parameters.union(comp.variables()) @@ -777,7 +777,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): @@ -1397,9 +1397,9 @@ def jacobian(t,y): "to {}) is out ".format(sol[n][0]) + "of the chart domain; a curve with a " + "smaller maximal value of the curve " + - "parameter, or a smaller initial tangent "+ - "vector, might be considered. You can also try "+ - "'solve_across_charts' in order not to be "+ + "parameter, or a smaller initial tangent " + + "vector, might be considered. You can also try " + + "'solve_across_charts' in order not to be " + "confined to a single chart") else: self._solutions[solution_key] = coords_sol @@ -1994,7 +1994,7 @@ def interpolate(self, solution_key=None, method=None, "with the key '{}' ".format(interpolation_key) + "by default.") - if method=='cubic spline': + if method == 'cubic spline': self._interpolations[interpolation_key] = [] dim = self.codomain().dim() if not isinstance(self._solutions[solution_key][0], tuple): @@ -2002,7 +2002,7 @@ def interpolate(self, solution_key=None, method=None, coordinate_curve = [] for point in self._solutions[solution_key]: coordinate_curve += [[point[0], point[i+1]]] - self._interpolations[interpolation_key]+=[Spline(coordinate_curve)] + self._interpolations[interpolation_key] += [Spline(coordinate_curve)] else: # case multi charts j = 0 for chart, sol in self._solutions[solution_key]: @@ -2014,7 +2014,7 @@ def interpolate(self, solution_key=None, method=None, interp_chart += [Spline(coordinate_curve)] self._interpolations[interpolation_key] += [(chart, interp_chart)] self._interpolations[interpolation_key+"_chart_"+str(j)] = interp_chart - j+=1 + j += 1 else: raise ValueError("no available method of interpolation " + "referred to as '{}'".format(method)) @@ -2264,7 +2264,7 @@ def tangent_vector_eval_at(self, t, # contain lists of instances of the Spline class raise TypeError("unexpected type of interpolation object") - interpolated_coordinates=[coordinate_curve_spline(t) + interpolated_coordinates = [coordinate_curve_spline(t) for coordinate_curve_spline in interpolation] M = self.codomain() p = M.point(interpolated_coordinates, chart=self._chart, name=None) @@ -2456,7 +2456,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, if ambient_coords is None: ambient_coords = chart[:] # all chart coordinates are used n_pc = len(ambient_coords) - if n_pc != 2 and n_pc !=3: + if n_pc != 2 and n_pc != 3: raise ValueError("the number of coordinates involved in " + "the plot must be either 2 or 3, " + "not {}".format(n_pc)) @@ -2493,7 +2493,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, "tuple/list of 2 elements") else: p = prange #'p' declared only for the line below to be shorter - if p[0]param_max or p[1]param_max: + if p[0] < param_min or p[0] > param_max or p[1] < param_min or p[1] > param_max: raise ValueError("parameter range should be a " + "subinterval of the curve domain " + "({})".format(self.domain())) @@ -2534,8 +2534,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2552,8 +2552,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2572,7 +2572,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, from sage.plot.plot3d.shapes import arrow3d scale = kwds.pop('scale') - plot_points_tangent=kwds.pop('plot_points_tangent') + plot_points_tangent = kwds.pop('plot_points_tangent') width_tangent = kwds.pop('width_tangent') plot_vectors = Graphics() @@ -2594,8 +2594,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2613,8 +2613,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2679,7 +2679,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, # to be shorter transf[pc] = AUX.expr()[jpc] AUX2 = transf[pc].variables() # idem - required_coords=required_coords.union(AUX2) + required_coords = required_coords.union(AUX2) break else: raise ValueError("no expression has been found for " + @@ -2716,8 +2716,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2734,8 +2734,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2745,11 +2745,11 @@ def plot_integrated(self, chart=None, ambient_coords=None, xp = [fastf[j](*arg) for j in range(len(ambient_coords))] plot_curve.append(xp) - if k==0 and t > tmin: + if k == 0 and t > tmin: # in case an initial offset was earlier added to # 'tmin' in order to avoid errors, it is now needed # to cancel this offset for the next steps - t=tmin + t = tmin t += dt @@ -2787,8 +2787,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_min + 0.01*dt if verbose: print("A tiny initial offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the first point "+ + "{} ".format(0.01*dt) + + "was introduced for the first point " + "only, in order to safely compute " + "it from the interpolation.") @@ -2806,8 +2806,8 @@ def plot_integrated(self, chart=None, ambient_coords=None, t = param_max - 0.01*dt if verbose: print("A tiny final offset equal to " + - "{} ".format(0.01*dt)+ - "was introduced for the last point "+ + "{} ".format(0.01*dt) + + "was introduced for the last point " + "in order to safely compute " + "it from the interpolation.") @@ -2826,13 +2826,13 @@ def plot_integrated(self, chart=None, ambient_coords=None, AUX = AUX.substitute(required_coords_values) # 'AUX' only used for the lines of code to # be shorter - xp+=[numerical_approx(AUX)] + xp += [numerical_approx(AUX)] pushed_comp = 0 for coord in transf[pc].variables(): D = Dpc_Dcoord[pc][coord] D = D.substitute(required_coords_values) - D=numerical_approx(D) + D = numerical_approx(D) pushed_comp += Dcoord_Dt[coord] * D pushed_vec += [pushed_comp] @@ -2857,7 +2857,7 @@ def plot_integrated(self, chart=None, ambient_coords=None, # in case an initial offset was earlier added to # 'tmin' in order to avoid errors, it is now needed # to cancel this offset for the next steps - t=tmin + t = tmin t += dt return plot_vectors + DifferentiableCurve._graphics(self, @@ -3644,7 +3644,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): @@ -4020,7 +4020,7 @@ def system(self, verbose=False): description += "Initial tangent vector: {} ".format(v0) description += "with components " - description +="{}".format(initial_tgt_vec_comps) + description += "{}".format(initial_tgt_vec_comps) description += " with respect to {}\n\n".format(chart) for coord_func,velocity in zip(chart[:],self._velocities): diff --git a/src/sage/manifolds/differentiable/levi_civita_connection.py b/src/sage/manifolds/differentiable/levi_civita_connection.py index 7ff2643e32b..00ebf69b47f 100644 --- a/src/sage/manifolds/differentiable/levi_civita_connection.py +++ b/src/sage/manifolds/differentiable/levi_civita_connection.py @@ -520,7 +520,7 @@ def make_Connect(local_list_ijk,chart,ginv,gg,manif): for i,j,k in local_list_ijk: rsum = 0 for s in manif.irange(): - if ginv[i,s, chart]!=0: + if ginv[i,s, chart] != 0: rsum += ginv[i,s, chart] * ( gg[s,k, chart].diff(j) + gg[j,s, chart].diff(k) diff --git a/src/sage/manifolds/differentiable/manifold.py b/src/sage/manifolds/differentiable/manifold.py index 904e291ab8e..3a7820e01ec 100644 --- a/src/sage/manifolds/differentiable/manifold.py +++ b/src/sage/manifolds/differentiable/manifold.py @@ -1904,7 +1904,7 @@ def tensor_field(self, *args, **kwargs): vmodule = self.vector_field_module(dest_map) resu = vmodule.tensor((k, l), name=name, latex_name=latex_name, sym=sym, antisym=antisym) - if len(args)>2: + if len(args) > 2: # Some components are to be initialized resu._init_components(args[2], **kwargs) return resu @@ -2173,7 +2173,7 @@ def multivector_field(self, *args, **kwargs): vmodule = self.vector_field_module(dest_map) resu = vmodule.alternating_contravariant_tensor(degree, name=name, latex_name=latex_name) - if len(args)>1: + if len(args) > 1: # Some components are to be initialized resu._init_components(args[1], **kwargs) return resu @@ -2277,7 +2277,7 @@ def diff_form(self, *args, **kwargs) -> DiffForm: vmodule = self.vector_field_module(dest_map) resu = vmodule.alternating_form(degree, name=name, latex_name=latex_name) - if len(args)>1: + if len(args) > 1: # Some components are to be initialized resu._init_components(args[1], **kwargs) return resu @@ -4187,7 +4187,7 @@ class :class:`~sage.manifolds.differentiable.diff_map.DiffMap` """ vmodule = self.vector_field_module(dest_map) dim = vmodule.ambient_domain().dimension() - if signature=='positive': + if signature == 'positive': signat = dim - 2 else: signat = 2 - dim diff --git a/src/sage/manifolds/differentiable/manifold_homset.py b/src/sage/manifolds/differentiable/manifold_homset.py index 2d35505f63c..20660a01652 100644 --- a/src/sage/manifolds/differentiable/manifold_homset.py +++ b/src/sage/manifolds/differentiable/manifold_homset.py @@ -931,7 +931,7 @@ def _an_element_(self): v = codom.tangent_space(p)(v_comps) # The equations defining the curve: - eqns_rhs=[-(x0_B-x0_A)/2*sin(param-t_min)]+[0 for i in range(dim-1)] + eqns_rhs = [-(x0_B-x0_A)/2*sin(param-t_min)]+[0 for i in range(dim-1)] # combined with the initial components above, all velocities # vanish, except the first one, which is a cosine function. # This differential system results in a curve constant in all @@ -1188,8 +1188,8 @@ def __init__(self, domain, codomain, name=None, latex_name=None): else: self._name = name if latex_name is None: - self._latex_name=r"\mathrm{{Hom}_{autoparallel}}" - self._latex_name+= r"\left({},{}\right)".format( + self._latex_name = r"\mathrm{{Hom}_{autoparallel}}" + self._latex_name += r"\left({},{}\right)".format( domain._latex_name, codomain._latex_name) else: self._latex_name = latex_name @@ -1644,7 +1644,7 @@ def __init__(self, domain, codomain, name=None, latex_name=None): self._name = name if latex_name is None: self._latex_name = r"\mathrm{{Hom}_{geodesic}}" - self._latex_name+= r"\left({},{}\right)".format( + self._latex_name += r"\left({},{}\right)".format( domain._latex_name, codomain._latex_name) else: self._latex_name = latex_name diff --git a/src/sage/manifolds/differentiable/metric.py b/src/sage/manifolds/differentiable/metric.py index 8211ad1a625..74fdd076e45 100644 --- a/src/sage/manifolds/differentiable/metric.py +++ b/src/sage/manifolds/differentiable/metric.py @@ -384,15 +384,15 @@ def __init__(self, vector_field_module, name, signature=None, raise TypeError("the metric signature must be an integer") if (signature < - ndim) or (signature > ndim): raise ValueError("metric signature out of range") - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") self._signature = signature # the pair (n_+, n_-): self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2) - self._indic_signat = 1 - 2*(self._signature_pm[1]%2) # (-1)^n_- + self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_- # Initialization of derived quantities: PseudoRiemannianMetric._init_derived(self) @@ -1229,8 +1229,8 @@ def weyl(self, name=None, latex_name=None): rscal = self.ricci_scalar() # First index of the Ricci tensor raised with the metric ricup = ric.up(self, 0) - aux = self*ricup + ric*delta - rscal/(n-1)* self*delta - self._weyl = riem + 2/(n-2)* aux.antisymmetrize(2,3) + aux = self*ricup + ric*delta - rscal/(n-1) * self*delta + self._weyl = riem + 2/(n-2) * aux.antisymmetrize(2,3) if name is None: name = "C(" + self._name + ")" if latex_name is None: @@ -2134,15 +2134,15 @@ def __init__(self, vector_field_module, name, signature=None, raise TypeError("the metric signature must be an integer") if (signature < - ndim) or (signature > ndim): raise ValueError("metric signature out of range") - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") self._signature = signature # the pair (n_+, n_-): self._signature_pm = ((ndim+signature)//2, (ndim-signature)//2) - self._indic_signat = 1 - 2*(self._signature_pm[1]%2) # (-1)^n_- + self._indic_signat = 1 - 2*(self._signature_pm[1] % 2) # (-1)^n_- # Initialization of derived quantities: PseudoRiemannianMetricParal._init_derived(self) @@ -2654,12 +2654,12 @@ def __init__(self, vector_field_module, name, signature=None, else: try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: + if sign != ndim: raise ValueError("{} is different from {}".format(sign, ndim)) except TypeError: raise TypeError("signature must be an iterable") @@ -2971,10 +2971,10 @@ def __init__(self, vector_field_module, name, signature=None, else: try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: + if sign != ndim: raise ValueError("{} is different from {}".format(sign, ndim)) except TypeError: raise TypeError("signature must be an iterable") diff --git a/src/sage/manifolds/differentiable/tangent_space.py b/src/sage/manifolds/differentiable/tangent_space.py index 4b90e711a79..98a60cede2a 100644 --- a/src/sage/manifolds/differentiable/tangent_space.py +++ b/src/sage/manifolds/differentiable/tangent_space.py @@ -246,7 +246,7 @@ def __init__(self, point: ManifoldPoint, base_ring=None): """ manif = point._manifold name = "T_{} {}".format(point._name, manif._name) - latex_name = r"T_{%s}\,%s"%(point._latex_name, manif._latex_name) + latex_name = r"T_{%s}\,%s" % (point._latex_name, manif._latex_name) self._point = point self._manif = manif if base_ring is None: diff --git a/src/sage/manifolds/differentiable/tensorfield.py b/src/sage/manifolds/differentiable/tensorfield.py index 861b05c1d1b..9e302688024 100644 --- a/src/sage/manifolds/differentiable/tensorfield.py +++ b/src/sage/manifolds/differentiable/tensorfield.py @@ -4041,7 +4041,7 @@ def down( return result if not isinstance(pos, (int, Integer)): raise TypeError("the argument 'pos' must be an integer") - if pos<0 or pos>=n_con: + if pos < 0 or pos >= n_con: print("pos = {}".format(pos)) raise ValueError("position out of range") return non_degenerate_form.contract(0, self, pos) diff --git a/src/sage/manifolds/differentiable/vectorfield.py b/src/sage/manifolds/differentiable/vectorfield.py index 01a9c52d93c..22b5df5717f 100644 --- a/src/sage/manifolds/differentiable/vectorfield.py +++ b/src/sage/manifolds/differentiable/vectorfield.py @@ -715,7 +715,7 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, elif not isinstance(ambient_coords, tuple): ambient_coords = tuple(ambient_coords) nca = len(ambient_coords) - if nca != 2 and nca !=3: + if nca != 2 and nca != 3: raise ValueError("the number of ambient coordinates must be " + "either 2 or 3, not {}".format(nca)) if ranges is None: @@ -757,11 +757,11 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, steps = {} for coord in coords: if coord not in steps: - steps[coord] = (ranges[coord][1] - ranges[coord][0])/ \ + steps[coord] = (ranges[coord][1] - ranges[coord][0]) / \ (number_values[coord]-1) else: number_values[coord] = 1 + int( - (ranges[coord][1] - ranges[coord][0])/ steps[coord]) + (ranges[coord][1] - ranges[coord][0]) / steps[coord]) # # 2/ Plots # ----- diff --git a/src/sage/manifolds/differentiable/vectorfield_module.py b/src/sage/manifolds/differentiable/vectorfield_module.py index d954b5d4839..11b94366a40 100644 --- a/src/sage/manifolds/differentiable/vectorfield_module.py +++ b/src/sage/manifolds/differentiable/vectorfield_module.py @@ -1188,15 +1188,15 @@ def metric(self, name: str, signature: Optional[int] = None, latex_name: Optiona ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) if elt > ndim: raise ValueError("{} must be less than {}".format(elt,ndim)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: - raise ValueError("{} is different from the dimension".format(sign)+ + if sign != ndim: + raise ValueError("{} is different from the dimension".format(sign) + " of the manifold, who is {}".format(ndim)) - if signature[2]!=0: + if signature[2] != 0: from sage.manifolds.differentiable.metric import DegenerateMetric return DegenerateMetric(self, name, signature=signature, latex_name=latex_name) @@ -1205,8 +1205,8 @@ def metric(self, name: str, signature: Optional[int] = None, latex_name: Optiona if signature is None: signature = (ndim,0) if isinstance(signature, (Integer, int)): - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") @@ -2395,13 +2395,13 @@ def metric(self, name, signature=None, latex_name=None): ndim = self._ambient_domain.dimension() try: for elt in signature: - if (elt<0) or (not isinstance(elt, (int, Integer))): + if (elt < 0) or (not isinstance(elt, (int, Integer))): raise ValueError("{} must be a positive integer".format(elt)) sign = signature[0]+signature[1]+signature[2] - if sign!=ndim: - raise ValueError("{} is different from the dimension".format(sign)+ + if sign != ndim: + raise ValueError("{} is different from the dimension".format(sign) + " of the manifold, who is {}".format(ndim)) - if signature[2]!=0: + if signature[2] != 0: from sage.manifolds.differentiable.metric import DegenerateMetricParal return DegenerateMetricParal(self, name, signature=signature, latex_name=latex_name) @@ -2410,8 +2410,8 @@ def metric(self, name, signature=None, latex_name=None): if signature is None: signature = (ndim,0) if isinstance(signature, (Integer, int)): - if (signature+ndim)%2 == 1: - if ndim%2 == 0: + if (signature+ndim) % 2 == 1: + if ndim % 2 == 0: raise ValueError("the metric signature must be even") else: raise ValueError("the metric signature must be odd") diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py index c66d54e774e..4b7c21532aa 100644 --- a/src/sage/manifolds/utilities.py +++ b/src/sage/manifolds/utilities.py @@ -323,9 +323,9 @@ def composition(self, ex, operator): if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(cos(w0))): x = self(x) # treatment of nested abs(sin_or_cos(...)) # Simplifications for values of x in the range [-pi, 2*pi]: - if x>=0 and x<=pi: + if x >= 0 and x <= pi: ex = sin(x) - elif (x>pi and x<=2*pi) or (x>=-pi and x<0): + elif (x > pi and x <= 2*pi) or (x >= -pi and x < 0): ex = -sin(x) return ex if argum.operator() is cos: @@ -335,9 +335,9 @@ def composition(self, ex, operator): if x.has(abs_symbolic(sin(w0))) or x.has(abs_symbolic(cos(w0))): x = self(x) # treatment of nested abs(sin_or_cos(...)) # Simplifications for values of x in the range [-pi, 2*pi]: - if (x>=-pi/2 and x<=pi/2) or (x>=3*pi/2 and x<=2*pi): + if (x >= -pi/2 and x <= pi/2) or (x >= 3*pi/2 and x <= 2*pi): ex = cos(x) - elif (x>pi/2 and x<=3*pi/2) or (x>=-pi and x<-pi/2): + elif (x > pi/2 and x <= 3*pi/2) or (x >= -pi and x < -pi/2): ex = -cos(x) return ex # If no pattern is found, we default to ExpressionTreeWalker: @@ -983,7 +983,7 @@ def _repr_(self): # dictionary to group multiple occurrences of differentiation: d/dxdx -> d/dx^2 etc. occ = dict((i, strv[i] + "^" + str(diffargs.count(i)) - if (diffargs.count(i)>1) else strv[i]) + if (diffargs.count(i) > 1) else strv[i]) for i in diffargs) res = "d" + str(numargs) + "(" + str(funcname) + ")/d" + "d".join( diff --git a/src/sage/modular/abvar/constructor.py b/src/sage/modular/abvar/constructor.py index 7a99398a237..5dd6a77b4ca 100644 --- a/src/sage/modular/abvar/constructor.py +++ b/src/sage/modular/abvar/constructor.py @@ -95,7 +95,7 @@ def J0(N): sage: J0(33) is J0(33) True """ - key = 'J0(%s)'%N + key = 'J0(%s)' % N try: return _get(key) except ValueError: @@ -113,7 +113,7 @@ def J1(N): sage: J1(389) Abelian variety J1(389) of dimension 6112 """ - key = 'J1(%s)'%N + key = 'J1(%s)' % N try: return _get(key) except ValueError: @@ -130,7 +130,7 @@ def JH(N, H): sage: JH(389,[16]) Abelian variety JH(389,[16]) of dimension 64 """ - key = 'JH(%s,%s)'%(N,H) + key = 'JH(%s,%s)' % (N,H) try: return _get(key) except ValueError: diff --git a/src/sage/modular/abvar/cuspidal_subgroup.py b/src/sage/modular/abvar/cuspidal_subgroup.py index fe174e6631a..82e373ad716 100644 --- a/src/sage/modular/abvar/cuspidal_subgroup.py +++ b/src/sage/modular/abvar/cuspidal_subgroup.py @@ -209,7 +209,7 @@ def _repr_(self): sage: G._repr_() 'Finite subgroup with invariants [3, 3] over QQ of Abelian variety J0(27) of dimension 1' """ - return "Cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety()) + return "Cuspidal subgroup %sover QQ of %s" % (self._invariants_repr(), self.abelian_variety()) def lattice(self): """ @@ -313,7 +313,7 @@ def _repr_(self): sage: G._repr_() 'Finite subgroup with invariants [3] over QQ of Abelian variety J0(27) of dimension 1' """ - return "Rational cuspidal subgroup %sover QQ of %s"%(self._invariants_repr(), self.abelian_variety()) + return "Rational cuspidal subgroup %sover QQ of %s" % (self._invariants_repr(), self.abelian_variety()) def lattice(self): """ diff --git a/src/sage/modular/abvar/finite_subgroup.py b/src/sage/modular/abvar/finite_subgroup.py index ec76a0f5e26..74f7dd6389b 100644 --- a/src/sage/modular/abvar/finite_subgroup.py +++ b/src/sage/modular/abvar/finite_subgroup.py @@ -529,7 +529,7 @@ def _repr_(self): field = "QQ" else: field = str(K) - return "Finite subgroup %sover %s of %s"%(self._invariants_repr(), field, self.__abvar) + return "Finite subgroup %sover %s of %s" % (self._invariants_repr(), field, self.__abvar) def _invariants_repr(self): """ @@ -544,7 +544,7 @@ def _invariants_repr(self): sage: J0(42).cuspidal_subgroup()._invariants_repr() 'with invariants [2, 2, 12, 48] ' """ - return 'with invariants %s '%(self.invariants(), ) + return 'with invariants %s ' % (self.invariants(), ) def order(self): """ diff --git a/src/sage/modular/abvar/homspace.py b/src/sage/modular/abvar/homspace.py index 8e89399d611..06ec268e2ec 100644 --- a/src/sage/modular/abvar/homspace.py +++ b/src/sage/modular/abvar/homspace.py @@ -397,7 +397,7 @@ def _repr_(self): sage: End(J)._repr_() 'Endomorphism ring of Abelian variety J0(11) of dimension 1' """ - return "Space of homomorphisms from %s to %s"%\ + return "Space of homomorphisms from %s to %s" %\ (self.domain(), self.codomain()) def _get_matrix(self, g): @@ -501,7 +501,7 @@ def gen(self, i=0): """ self.calculate_generators() if i > self.ngens(): - raise ValueError("self only has %s generators"%self.ngens()) + raise ValueError("self only has %s generators" % self.ngens()) return self.element_class(self, self._gens[i]) def ngens(self): diff --git a/src/sage/modular/abvar/lseries.py b/src/sage/modular/abvar/lseries.py index 48c3377a4c5..84823684f03 100644 --- a/src/sage/modular/abvar/lseries.py +++ b/src/sage/modular/abvar/lseries.py @@ -322,7 +322,7 @@ def __init__(self, abvar, p): Lseries.__init__(self, abvar) p = Integer(p) if not p.is_prime(): - raise ValueError("p (=%s) must be prime"%p) + raise ValueError("p (=%s) must be prime" % p) self.__p = p def __eq__(self, other): diff --git a/src/sage/modular/abvar/torsion_subgroup.py b/src/sage/modular/abvar/torsion_subgroup.py index b2a5c35f8b9..14a52ba0284 100644 --- a/src/sage/modular/abvar/torsion_subgroup.py +++ b/src/sage/modular/abvar/torsion_subgroup.py @@ -219,7 +219,7 @@ def order(self, proof=True): n = O[0] self._order = n return n - raise RuntimeError("Unable to compute order of torsion subgroup (it is in %s)"%O) + raise RuntimeError("Unable to compute order of torsion subgroup (it is in %s)" % O) def lattice(self): """ @@ -697,7 +697,7 @@ def _repr_(self): sage: J0(23).qbar_torsion_subgroup()._repr_() 'Group of all torsion points in QQbar on Abelian variety J0(23) of dimension 2' """ - return 'Group of all torsion points in QQbar on %s'%self.__abvar + return 'Group of all torsion points in QQbar on %s' % self.__abvar def field_of_definition(self): """ diff --git a/src/sage/modular/arithgroup/arithgroup_generic.py b/src/sage/modular/arithgroup/arithgroup_generic.py index 844d8db7165..093541b9b06 100644 --- a/src/sage/modular/arithgroup/arithgroup_generic.py +++ b/src/sage/modular/arithgroup/arithgroup_generic.py @@ -1020,7 +1020,7 @@ def generators(self, algorithm="farey"): [0 1], [ 0 -1], [-2 1], [ 0 -1], [-2 3], [ 2 -1], [2 1] ] """ - if algorithm=="farey": + if algorithm == "farey": return self.farey_symbol().generators() elif algorithm == "todd-coxeter": return self.todd_coxeter()[1] @@ -1252,7 +1252,7 @@ def dimension_eis(self, k=2): if k > 1: return self.nregcusps() else: # k = 1 - return ZZ(self.nregcusps()/ ZZ(2)) + return ZZ(self.nregcusps() / ZZ(2)) def as_permutation_group(self): r""" @@ -1279,7 +1279,7 @@ def as_permutation_group(self): sage: P.an_element() in G True """ - _,_,l_edges,s2_edges=self.todd_coxeter() + _,_,l_edges,s2_edges = self.todd_coxeter() n = len(l_edges) s3_edges = [None] * n r_edges = [None] * n @@ -1289,10 +1289,10 @@ def as_permutation_group(self): r_edges[ii] = s2_edges[i] if self.is_even(): from sage.modular.arithgroup.arithgroup_perm import EvenArithmeticSubgroup_Permutation - g=EvenArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) + g = EvenArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) else: from sage.modular.arithgroup.arithgroup_perm import OddArithmeticSubgroup_Permutation - g=OddArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) + g = OddArithmeticSubgroup_Permutation(S2=s2_edges,S3=s3_edges,L=l_edges,R=r_edges) g.relabel() return g diff --git a/src/sage/modular/arithgroup/arithgroup_perm.py b/src/sage/modular/arithgroup/arithgroup_perm.py index c8536611724..9f7371c1702 100644 --- a/src/sage/modular/arithgroup/arithgroup_perm.py +++ b/src/sage/modular/arithgroup/arithgroup_perm.py @@ -150,49 +150,49 @@ def sl2z_word_problem(A): output = [] # If A00 is zero - if A[0,0]==0: - c=A[1,1] + if A[0,0] == 0: + c = A[1,1] if c != 1: - A=A*Lm**(c-1)*Rm*Lmi + A = A*Lm**(c-1)*Rm*Lmi output.extend([(0,1-c),(1,-1),(0,1)]) else: - A=A*Rm*Lmi + A = A*Rm*Lmi output.extend([(1,-1),(0,1)]) - if A[0,0]<0: # Make sure A00 is positive - A=SL2Z(-1)*A + if A[0,0] < 0: # Make sure A00 is positive + A = SL2Z(-1)*A output.extend([(1,-1), (0,1), (1,-1), (0,1), (1,-1), (0,1)]) - if A[0,1]<0: # if A01 is negative make it positive - n=(-A[0,1]/A[0,0]).ceil() #n s.t. 0 <= A[0,1]+n*A[0,0] < A[0,0] - A=A*Lm**n + if A[0,1] < 0: # if A01 is negative make it positive + n = (-A[0,1]/A[0,0]).ceil() #n s.t. 0 <= A[0,1]+n*A[0,0] < A[0,0] + A = A*Lm**n output.append((0, -n)) # At this point A00>0 and A01>=0 - while not (A[0,0]==0 or A[0,1]==0): - if A[0,0]>A[0,1]: - n=(A[0,0]/A[0,1]).floor() - A=A*SL2Z([1,0,-n,1]) + while not (A[0,0] == 0 or A[0,1] == 0): + if A[0,0] > A[0,1]: + n = (A[0,0]/A[0,1]).floor() + A = A*SL2Z([1,0,-n,1]) output.append((1, n)) else: # A[0,0]<=A[0,1] - n=(A[0,1]/A[0,0]).floor() - A=A*SL2Z([1,-n,0,1]) + n = (A[0,1]/A[0,0]).floor() + A = A*SL2Z([1,-n,0,1]) output.append((0, n)) - if A==SL2Z(1): + if A == SL2Z(1): pass # done, so don't add R^0 - elif A[0,0]==0: - c=A[1,1] + elif A[0,0] == 0: + c = A[1,1] if c != 1: - A=A*Lm**(c-1)*Rm*Lmi + A = A*Lm**(c-1)*Rm*Lmi output.extend([(0,1-c),(1,-1),(0, 1)]) else: - A=A*Rm*Lmi + A = A*Rm*Lmi output.extend([(1,-1),(0,1)]) else: - c=A[1,0] + c = A[1,0] if c: - A=A*Rm**(-c) + A = A*Rm**(-c) output.append((1,c)) output.reverse() @@ -255,7 +255,7 @@ def word_of_perms(w, p1, p2): m = [p1.order(),p2.order()] for i,j in w: - M *= p[i]**(j%m[i]) + M *= p[i]**(j % m[i]) return M @@ -586,11 +586,11 @@ def _repr_(self): 'Arithmetic subgroup of index 24' """ if self.index() < 20: - return "Arithmetic subgroup with permutations of right cosets\n S2=%s\n S3=%s\n L=%s\n R=%s" %( + return "Arithmetic subgroup with permutations of right cosets\n S2=%s\n S3=%s\n L=%s\n R=%s" % ( self.S2(), self.S3(), self.L(), self.R()) else: - return "Arithmetic subgroup of index %d" %self.index() + return "Arithmetic subgroup of index %d" % self.index() # # Attribute access @@ -1002,13 +1002,13 @@ def _index_to_lr_cusp_width(self): l_cycle_length = [None]*self.index() for c in l.cycle_tuples(singletons=True): for i in c: - l_cycle_length[i-1]=len(c) + l_cycle_length[i-1] = len(c) r = G.R() r_cycle_length = [None]*self.index() for c in r.cycle_tuples(singletons=True): for i in c: - r_cycle_length[i-1]=len(c) + r_cycle_length[i-1] = len(c) return (l_cycle_length, r_cycle_length) @@ -1484,7 +1484,7 @@ def is_congruence(self): s = l**20 * r**onefifth * l**(-4) * ~r #Congruence if the seven permutations below are trivial: - rel =~a*~r*a*r + rel = ~a*~r*a*r if not rel.is_one(): verbose("Failed relation B1") return False diff --git a/src/sage/modular/arithgroup/congroup_gamma.py b/src/sage/modular/arithgroup/congroup_gamma.py index bba5868dab6..a9eeb2a5769 100644 --- a/src/sage/modular/arithgroup/congroup_gamma.py +++ b/src/sage/modular/arithgroup/congroup_gamma.py @@ -73,7 +73,7 @@ def _repr_(self): sage: Gamma(133)._repr_() 'Congruence Subgroup Gamma(133)' """ - return "Congruence Subgroup Gamma(%s)"%self.level() + return "Congruence Subgroup Gamma(%s)" % self.level() def _latex_(self): r""" @@ -86,7 +86,7 @@ def _latex_(self): sage: latex(Gamma(20)) \Gamma(20) """ - return "\\Gamma(%s)"%self.level() + return "\\Gamma(%s)" % self.level() def __reduce__(self): """ @@ -154,7 +154,7 @@ def _contains_sl2(self, a,b,c,d): """ N = self.level() # don't need to check d == 1 as this is automatic from det - return ((a%N == 1) and (b%N == 0) and (c%N == 0)) + return ((a % N == 1) and (b % N == 0) and (c % N == 0)) def ncusps(self): r""" @@ -170,9 +170,9 @@ def ncusps(self): 432345564227567616 """ n = self.level() - if n==1: + if n == 1: return ZZ(1) - if n==2: + if n == 2: return ZZ(3) return prod([p**(2*e) - p**(2*e-2) for (p,e) in n.factor()])//2 @@ -200,18 +200,18 @@ def _find_cusps(self): n = self.level() C = [QQ(x) for x in range(n)] - n0=n//2 - n1=(n+1)//2 + n0 = n//2 + n1 = (n+1)//2 for r in range(1, n1): - if r > 1 and gcd(r,n)==1: + if r > 1 and gcd(r,n) == 1: C.append(ZZ(r)/ZZ(n)) - if n0==n/2 and gcd(r,n0)==1: + if n0 == n/2 and gcd(r,n0) == 1: C.append(ZZ(r)/ZZ(n0)) for s in range(2,n1): for r in range(1, 1+n): - if GCD_list([s,r,n])==1: + if GCD_list([s,r,n]) == 1: # GCD_list is ~40x faster than gcd, since gcd wastes loads # of time initialising a Sequence type. u,v = _lift_pair(r,s,n) diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index e960ce477d3..70d263ebc45 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -147,7 +147,7 @@ def _repr_(self): sage: Gamma0(98)._repr_() 'Congruence Subgroup Gamma0(98)' """ - return "Congruence Subgroup Gamma0(%s)"%self.level() + return "Congruence Subgroup Gamma0(%s)" % self.level() def __reduce__(self): """ @@ -171,7 +171,7 @@ def _latex_(self): sage: latex(Gamma0(20)) \Gamma_0(20) """ - return "\\Gamma_0(%s)"%self.level() + return "\\Gamma_0(%s)" % self.level() @cached_method def _generators_for_H(self): @@ -364,10 +364,10 @@ def generators(self, algorithm="farey"): # reasons, which aren't the ones the Farey symbol code gives return [ self([0,-1,1,0]), self([1,1,0,1]) ] - elif algorithm=="farey": + elif algorithm == "farey": return self.farey_symbol().generators() - elif algorithm=="todd-coxeter": + elif algorithm == "todd-coxeter": from sage.modular.modsym.p1list import P1List from .congroup import generators_helper level = self.level() @@ -507,7 +507,7 @@ def nu2(self): [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0] """ n = self.level() - if n%4 == 0: + if n % 4 == 0: return ZZ(0) return prod([ 1 + kronecker_symbol(-4, p) for p, _ in n.factor()]) diff --git a/src/sage/modular/arithgroup/congroup_gamma1.py b/src/sage/modular/arithgroup/congroup_gamma1.py index d32d3646256..00dc9e8c0a5 100644 --- a/src/sage/modular/arithgroup/congroup_gamma1.py +++ b/src/sage/modular/arithgroup/congroup_gamma1.py @@ -117,7 +117,7 @@ def _repr_(self): sage: Gamma1(133)._repr_() 'Congruence Subgroup Gamma1(133)' """ - return "Congruence Subgroup Gamma1(%s)"%self.level() + return "Congruence Subgroup Gamma1(%s)" % self.level() def __reduce__(self): """ @@ -141,7 +141,7 @@ def _latex_(self): sage: latex(Gamma1(3)) \Gamma_1(3) """ - return "\\Gamma_1(%s)"%self.level() + return "\\Gamma_1(%s)" % self.level() def is_even(self): """ @@ -221,9 +221,9 @@ def generators(self, algorithm="farey"): [ 3 -2], [ 3 -2], [ 9 -2], [-12 7] ] """ - if algorithm=="farey": + if algorithm == "farey": return self.farey_symbol().generators() - elif algorithm=="todd-coxeter": + elif algorithm == "todd-coxeter": from sage.modular.modsym.g1list import G1list from .congroup import generators_helper level = self.level() @@ -253,7 +253,7 @@ def _contains_sl2(self, a,b,c,d): """ N = self.level() # don't need to check d == 1 mod N as this is automatic from det - return ((a%N == 1) and (c%N == 0)) + return ((a % N == 1) and (c % N == 0)) def nu2(self): r""" @@ -459,7 +459,7 @@ def dimension_cusp_forms(self, k=2, eps=None, algorithm="CohenOesterle"): if eps.is_trivial(): return Gamma0(N).dimension_cusp_forms(k) - if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()): + if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k % 2) == 0 and eps.is_odd()): return ZZ(0) if k == 1: @@ -543,7 +543,7 @@ def dimension_eis(self, k=2, eps=None, algorithm="CohenOesterle"): return Gamma0(N).dimension_eis(k) # Note case of k = 0 and trivial character already dealt with separately, so k <= 0 here is valid: - if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()): + if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k % 2) == 0 and eps.is_odd()): return ZZ(0) if algorithm == "Quer": @@ -637,7 +637,7 @@ def dimension_new_cusp_forms(self, k=2, eps=None, p=0, algorithm="CohenOesterle" from .congroup_gammaH import mumu - if p == 0 or N%p != 0 or eps.conductor().valuation(p) == N.valuation(p): + if p == 0 or N % p != 0 or eps.conductor().valuation(p) == N.valuation(p): D = [eps.conductor()*d for d in divisors(N//eps.conductor())] return sum([Gamma1_constructor(M).dimension_cusp_forms(k, eps.restrict(M), algorithm)*mumu(N//M) for M in D]) eps_p = eps.restrict(N//p) diff --git a/src/sage/modular/arithgroup/congroup_generic.py b/src/sage/modular/arithgroup/congroup_generic.py index e71426f9922..edf056784e6 100644 --- a/src/sage/modular/arithgroup/congroup_generic.py +++ b/src/sage/modular/arithgroup/congroup_generic.py @@ -544,7 +544,7 @@ def _new_group_from_level(self, level): from .congroup_gammaH import is_GammaH from .all import Gamma0, Gamma1, GammaH N = self.level() - if (level%N) and (N%level): + if (level % N) and (N % level): raise ValueError("one level must divide the other") if is_Gamma0(self): return Gamma0(level) @@ -558,7 +558,7 @@ def _new_group_from_level(self, level): newH = [ h + diff for h in H for diff in diffs ] return GammaH(level, [x for x in newH if gcd(level, x) == 1]) else: - return GammaH(level, [ h%level for h in H ]) + return GammaH(level, [ h % level for h in H ]) else: raise NotImplementedError diff --git a/src/sage/modular/arithgroup/congroup_sl2z.py b/src/sage/modular/arithgroup/congroup_sl2z.py index 69a977994d0..e0bc3abe12e 100644 --- a/src/sage/modular/arithgroup/congroup_sl2z.py +++ b/src/sage/modular/arithgroup/congroup_sl2z.py @@ -146,7 +146,7 @@ def _latex_(self): sage: latex(SL2Z) \mbox{\rm SL}_2(\Bold{Z}) """ - return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_()) + return "\\mbox{\\rm SL}_2(%s)" % (ZZ._latex_()) def is_subgroup(self, right): """ diff --git a/src/sage/modular/local_comp/smoothchar.py b/src/sage/modular/local_comp/smoothchar.py index b56befe27cb..c81677589a9 100644 --- a/src/sage/modular/local_comp/smoothchar.py +++ b/src/sage/modular/local_comp/smoothchar.py @@ -1283,7 +1283,7 @@ def _reduce_Qp(self, level, x): p = self.prime() r = ZZ(x.norm().valuation(p) / 2) y = x / p**r - if p==2 and y.trace().valuation(2) < 1: + if p == 2 and y.trace().valuation(2) < 1: raise ValueError("%s not congruent mod %s to an elt of Qp" % (x, self.ideal(level))) Y = (y.trace() / 2) % self.ideal(level).smallest_integer() X = p**r * Y diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index 9601342faeb..95c69eea5be 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -123,7 +123,7 @@ def _compute_q_expansion_basis(self, prec=None): newB.append(f) V = A.span(gens) if len(newB) != self.dimension(): - raise RuntimeError("The dimension of the space is %s but the basis we computed has %s elements"%(self.dimension(), len(newB))) + raise RuntimeError("The dimension of the space is %s but the basis we computed has %s elements" % (self.dimension(), len(newB))) lst = [R(f) for f in newB] return [f/f[f.valuation()] for f in lst] else: diff --git a/src/sage/modular/modform/ambient_eps.py b/src/sage/modular/modform/ambient_eps.py index 8f14e22ce20..71502963bb8 100644 --- a/src/sage/modular/modform/ambient_eps.py +++ b/src/sage/modular/modform/ambient_eps.py @@ -118,9 +118,9 @@ def __init__(self, character, weight=2, base_ring=None, eis_only=False): """ if not dirichlet.is_DirichletCharacter(character): - raise TypeError("character (=%s) must be a Dirichlet character"%character) + raise TypeError("character (=%s) must be a Dirichlet character" % character) if base_ring is None: - base_ring=character.base_ring() + base_ring = character.base_ring() if character.base_ring() != base_ring: character = character.change_ring(base_ring) if base_ring.characteristic() != 0: @@ -152,10 +152,10 @@ def _repr_(self): Modforms of level 8 """ if self._eis_only: - return "Modular Forms space of character %s and weight %s over %s" %( + return "Modular Forms space of character %s and weight %s over %s" % ( self.character()._repr_short_(), self.weight(), self.base_ring()) else: - return "Modular Forms space of dimension %s, character %s and weight %s over %s"%( + return "Modular Forms space of dimension %s, character %s and weight %s over %s" % ( self.dimension(), self.character()._repr_short_(), self.weight(), self.base_ring()) @cached_method diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index 023f9a380d2..b632f6d398c 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -126,7 +126,7 @@ def canonical_parameters(group, level, weight, base_ring): group = arithgroup.Gamma0(m) if not isinstance(base_ring, CommutativeRing): - raise TypeError("base_ring (=%s) must be a commutative ring"%base_ring) + raise TypeError("base_ring (=%s) must be a commutative ring" % base_ring) # it is *very* important to include the level as part of the data # that defines the key, since Dirichlet characters of different diff --git a/src/sage/modular/modform/cuspidal_submodule.py b/src/sage/modular/modform/cuspidal_submodule.py index 19a0b5661c0..954542073dc 100644 --- a/src/sage/modular/modform/cuspidal_submodule.py +++ b/src/sage/modular/modform/cuspidal_submodule.py @@ -90,7 +90,7 @@ def __init__(self, ambient_space): True """ from sage.misc.verbose import verbose - verbose('creating cuspidal submodule of %s'%ambient_space) + verbose('creating cuspidal submodule of %s' % ambient_space) d = ambient_space._dim_cuspidal() V = ambient_space.module() G = [V.gen(i) for i in range(d)] @@ -121,7 +121,7 @@ def _repr_(self): sage: S = CuspForms(Gamma1(3),6); S._repr_() 'Cuspidal subspace of dimension 1 of Modular Forms space of dimension 3 for Congruence Subgroup Gamma1(3) of weight 6 over Rational Field' """ - return "Cuspidal subspace of dimension %s of %s"%(self.dimension(), self.ambient_module()) + return "Cuspidal subspace of dimension %s of %s" % (self.dimension(), self.ambient_module()) def is_cuspidal(self): """ @@ -393,7 +393,7 @@ def _compute_q_expansion_basis(self, prec=None): else: prec = Integer(prec) - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) B = [] dim = 0 @@ -484,7 +484,7 @@ def _compute_diamond_matrix(self, d): [ 0 0 0 0 0 -1 0] [ 0 0 0 0 0 0 -1] """ - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) A = Matrix(QQ, 0, 0) for c in chars: chi = c.minimize_base_ring() @@ -525,7 +525,7 @@ def _compute_hecke_matrix(self, n): True """ - chars=self.group().characters_mod_H(sign=-1, galois_orbits=True) + chars = self.group().characters_mod_H(sign=-1, galois_orbits=True) A = Matrix(QQ, 0, 0) for c in chars: chi = c.minimize_base_ring() diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index be0f2557c73..f7575f6b150 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -137,13 +137,13 @@ def eisenstein_series_qexp(k, prec=10, K=QQ, var='q', normalization='linear'): try: a0fac = K(1/a0den) except ZeroDivisionError: - raise ValueError("The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0den, K)) + raise ValueError("The denominator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (a0den, K)) elif normalization == 'constant': a0num = a0.numerator() try: a0fac = K(1/a0num) except ZeroDivisionError: - raise ValueError("The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s"%(a0num, K)) + raise ValueError("The numerator of -B_k/(2*k) (=%s) must be invertible in the ring %s" % (a0num, K)) elif normalization == 'integral': a0fac = None else: @@ -155,7 +155,7 @@ def eisenstein_series_qexp(k, prec=10, K=QQ, var='q', normalization='linear'): # The following is *dramatically* faster than doing the more natural # "R(ls)" would be: E = ZZ[var](ls, prec=prec, check=False).change_ring(QQ) - if len(ls)>0: + if len(ls) > 0: E._unsafe_mutate(0, a0) return R(E, prec) # The following is an older slower alternative to the above three lines: @@ -431,15 +431,15 @@ def eisenstein_series_lseries(weight, prec=53, # Using a string for residues is a hack but it works well # since this will make PARI/GP compute sqrt(pi) with the # right precision. - residues='[sqrt(Pi)*(%s)]'%((-1)**Integer(j/2)*bernoulli(j)/j), + residues ='[sqrt(Pi)*(%s)]' % ((-1)**Integer(j/2)*bernoulli(j)/j), prec=prec) - s = 'coeff = %s;'%f.list() + s = 'coeff = %s;' % f.list() L.init_coeffs('coeff[k+1]',pari_precode=s, max_imaginary_part=max_imaginary_part, max_asymp_coeffs=max_asymp_coeffs) L.check_functional_equation() - L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)'%(j,f)) + L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)' % (j,f)) return L diff --git a/src/sage/modular/modform/eisenstein_submodule.py b/src/sage/modular/modform/eisenstein_submodule.py index fd1731574fa..90370ecf78d 100644 --- a/src/sage/modular/modform/eisenstein_submodule.py +++ b/src/sage/modular/modform/eisenstein_submodule.py @@ -37,7 +37,7 @@ def __init__(self, ambient_space): True """ from sage.misc.verbose import verbose - verbose('creating eisenstein submodule of %s'%ambient_space) + verbose('creating eisenstein submodule of %s' % ambient_space) d = ambient_space._dim_eisenstein() V = ambient_space.module() n = V.dimension() diff --git a/src/sage/modular/modform/hecke_operator_on_qexp.py b/src/sage/modular/modform/hecke_operator_on_qexp.py index 36e092d8200..48590ba7d23 100644 --- a/src/sage/modular/modform/hecke_operator_on_qexp.py +++ b/src/sage/modular/modform/hecke_operator_on_qexp.py @@ -83,9 +83,9 @@ def hecke_operator_on_qexp(f, n, k, eps=None, eps = DirichletGroup(1, base_ring=ZZ)[0] if check: if not (is_PowerSeries(f) or is_ModularFormElement(f)): - raise TypeError("f (=%s) must be a power series or modular form"%f) + raise TypeError("f (=%s) must be a power series or modular form" % f) if not is_DirichletCharacter(eps): - raise TypeError("eps (=%s) must be a Dirichlet character"%eps) + raise TypeError("eps (=%s) must be a Dirichlet character" % eps) k = Integer(k) n = Integer(n) v = [] @@ -215,7 +215,7 @@ def hecke_operator_on_basis(B, n, k, eps=None, already_echelonized=False): Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 12 and degree 4 """ if not isinstance(B, (list, tuple)): - raise TypeError("B (=%s) must be a list or tuple"%B) + raise TypeError("B (=%s) must be a list or tuple" % B) if len(B) == 0: if eps is None: R = CyclotomicField(1) diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index c13ebcbb77d..f811939ca5f 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -28,7 +28,7 @@ from sage.structure.sequence import Sequence # This variable controls importing the SciPy library sparingly -scipy=None +scipy = None @richcmp_method class NumericalEigenforms(SageObject): @@ -163,7 +163,7 @@ def _repr_(self): sage: n._repr_() 'Numerical Hecke eigenvalues for Congruence Subgroup Gamma0(61) of weight 2' """ - return "Numerical Hecke eigenvalues for %s of weight %s"%( + return "Numerical Hecke eigenvalues for %s of weight %s" % ( self._group, self._weight) @cached_method diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 90e149340e4..2e98067413e 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -103,7 +103,7 @@ def _span_of_forms_in_weight(forms, weight, prec, stop_dim=None, use_random=Fals [ 0 1 0 195660 12080128] [ 0 0 1 -48 1080] """ - t = verbose('multiplying forms up to weight %s'%weight) + t = verbose('multiplying forms up to weight %s' % weight) # Algorithm: run through the monomials of the appropriate weight, and build # up the vector space they span. @@ -396,7 +396,7 @@ def _generators_variables_dictionnary(self, poly_parent, gens): nb_var = poly_parent.ngens() nb_gens = self.ngens() if nb_var != nb_gens: - raise ValueError('the number of variables (%s) must be equal to the number of generators of the modular forms ring (%s)'%(nb_var, self.ngens())) + raise ValueError('the number of variables (%s) must be equal to the number of generators of the modular forms ring (%s)' % (nb_var, self.ngens())) return {poly_parent.gen(i): self(gens[i]) for i in range(0, nb_var)} def from_polynomial(self, polynomial, gens=None): @@ -520,7 +520,7 @@ def _element_constructor_(self, forms_datum): if self.group().is_subgroup(forms_datum.group()) and self.base_ring().has_coerce_map_from(forms_datum.base_ring()): forms_dictionary = {forms_datum.weight(): forms_datum} else: - raise ValueError('the group (%s) and/or the base ring (%s) of the given modular form is not consistant with the base space: %s'%(forms_datum.group(), forms_datum.base_ring(), self)) + raise ValueError('the group (%s) and/or the base ring (%s) of the given modular form is not consistant with the base space: %s' % (forms_datum.group(), forms_datum.base_ring(), self)) elif forms_datum in self.base_ring(): forms_dictionary = {0:forms_datum} elif isinstance(forms_datum, MPolynomial): @@ -1021,7 +1021,7 @@ def q_expansion_basis(self, weight, prec=None, use_random=True): return [] if prec is None: - prec=self.modular_forms_of_weight(weight).sturm_bound() + prec = self.modular_forms_of_weight(weight).sturm_bound() working_prec = max(prec, self.modular_forms_of_weight(weight).sturm_bound()) diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index 82b20da8167..36daef1d17b 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -138,9 +138,9 @@ def __init__(self, group, weight, character, base_ring, category=None): global WARN if WARN: print("Modular forms -- under development -- do not trust yet.") - WARN=False + WARN = False if not arithgroup.is_CongruenceSubgroup(group): - raise TypeError("group (=%s) must be a congruence subgroup"%group) + raise TypeError("group (=%s) must be a congruence subgroup" % group) weight = Integer(weight) if not ((character is None) or isinstance(character, dirichlet.DirichletCharacter)): raise TypeError("character must be a Dirichlet character") @@ -405,7 +405,7 @@ def __normalize_prec(self, prec): else: prec = Integer(prec) if prec < 0: - raise ValueError("prec (=%s) must be at least 0"%prec) + raise ValueError("prec (=%s) must be at least 0" % prec) return prec @cached_method @@ -1422,7 +1422,7 @@ def gen(self, n): try: return self.basis()[int(n)] except IndexError: - raise ValueError("Generator %s not defined"%n) + raise ValueError("Generator %s not defined" % n) def gens(self): """ @@ -1551,7 +1551,7 @@ def cuspidal_submodule(self): else: assert S.dimension() == self.dimension() self.__is_cuspidal = True - S.__is_eisenstein = (S.dimension()==0) + S.__is_eisenstein = (S.dimension() == 0) S.__is_cuspidal = True return S @@ -1737,7 +1737,7 @@ def eisenstein_submodule(self): else: assert E.dimension() == self.dimension() self.__is_eisenstein = True - E.__is_cuspidal = (E.dimension()==0) + E.__is_cuspidal = (E.dimension() == 0) E.__is_eisenstein = True return E @@ -1903,7 +1903,7 @@ def find_in_space(self, f, forms=None, prec=None, indep=True): else: B = V.span(w) if is_PowerSeries(f) and f.prec() < n: - raise ValueError("you need at least %s terms of precision"%n) + raise ValueError("you need at least %s terms of precision" % n) x = V(f.padded_list(n)) return B.coordinates(x) diff --git a/src/sage/modular/modform/submodule.py b/src/sage/modular/modform/submodule.py index 49b6c12b493..441f6d9dd05 100644 --- a/src/sage/modular/modform/submodule.py +++ b/src/sage/modular/modform/submodule.py @@ -61,7 +61,7 @@ def _repr_(self): sage: ModularForms(Gamma1(13),2).eisenstein_subspace()._repr_() 'Eisenstein subspace of dimension 11 of Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field' """ - return "Modular Forms subspace of dimension %s of %s"%(self.dimension(), self.ambient_module()) + return "Modular Forms subspace of dimension %s of %s" % (self.dimension(), self.ambient_module()) def _compute_coefficients(self, element, X): """ diff --git a/src/sage/modular/modform/vm_basis.py b/src/sage/modular/modform/vm_basis.py index 559c36828e9..f83c6bbcc1f 100644 --- a/src/sage/modular/modform/vm_basis.py +++ b/src/sage/modular/modform/vm_basis.py @@ -128,7 +128,7 @@ def victor_miller_basis(k, prec=10, cusp_only=False, var='q'): - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL) """ k = Integer(k) - if k%2 == 1 or k==2: + if k % 2 == 1 or k == 2: return Sequence([]) elif k < 0: raise ValueError("k must be non-negative") diff --git a/src/sage/modular/modform/weight1.py b/src/sage/modular/modform/weight1.py index b7a2caa7a41..4cb34df7513 100644 --- a/src/sage/modular/modform/weight1.py +++ b/src/sage/modular/modform/weight1.py @@ -177,7 +177,7 @@ def hecke_stable_subspace(chi, aux_prime=ZZ(2)): # The theory does not guarantee that J is exactly S_1(chi), just that it is # intermediate between S_1(chi) and M_1(chi). In every example I know of, # it is equal to S_1(chi), but just for honesty, we check this anyway. - t=verbose("Checking cuspidality", level=1) + t = verbose("Checking cuspidality", level=1) JEis = V.span(V(x.padded_list(R)) for x in EisensteinForms(chi, 1).q_echelon_basis(prec=R)) D = JEis.intersection(J) if D.dimension() != 0: diff --git a/src/sage/modular/modform_hecketriangle/abstract_ring.py b/src/sage/modular/modform_hecketriangle/abstract_ring.py index f2b0e77d920..f28917578af 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_ring.py +++ b/src/sage/modular/modform_hecketriangle/abstract_ring.py @@ -497,7 +497,7 @@ def reduce_type(self, analytic_type=None, degree=None): return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=self.weight(), ep=self.ep()) else: (weight, ep) = degree - if (self.is_homogeneous() and (weight != self.weight() or ep!=self.ep())): + if (self.is_homogeneous() and (weight != self.weight() or ep != self.ep())): analytic_type = self._analytic_type.reduce_to([]) return FormsSpace(analytic_type, group=self.group(), base_ring=self.base_ring(), k=weight, ep=ep) diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index 110b0fe3be7..d1e23066aff 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -535,7 +535,7 @@ def contains_coeff_ring(self): False """ - return ((self.AT("holo") <= self._analytic_type) and (self.weight()==QQ(0)) and (self.ep()==ZZ(1))) + return ((self.AT("holo") <= self._analytic_type) and (self.weight() == QQ(0)) and (self.ep() == ZZ(1))) def element_from_coordinates(self, vec): r""" @@ -633,7 +633,7 @@ def homogeneous_part(self, k, ep): ValueError: QuasiMeromorphicModularForms(n=6, k=4, ep=1) over Integer Ring already is homogeneous with degree (4, 1) != (5, 1)! """ - if (k==self._weight and ep==self._ep): + if (k == self._weight and ep == self._ep): return self else: raise ValueError("{} already is homogeneous with degree ({}, {}) != ({}, {})!".format(self, self._weight, self._ep, k, ep)) @@ -829,7 +829,7 @@ def F_simple(self, order_1=ZZ(0)): if (order_inf > 0 and order_1 > 0): new_space = self.extend_type("cusp") - elif (order_inf >=0 and order_1 >= 0): + elif (order_inf >= 0 and order_1 >= 0): new_space = self.extend_type("holo") else: new_space = self.extend_type("weak") @@ -981,7 +981,7 @@ def Faber_pol(self, m, order_1=ZZ(0), fix_d=False, d_num_prec=None): # The first term is zero only up to numerical errors, # so we manually have to remove it if (not d.parent().is_exact()): - temp_reminder=temp_reminder.truncate_neg(-temp_exp+1) + temp_reminder = temp_reminder.truncate_neg(-temp_exp+1) return fab_pol.polynomial() @@ -1214,7 +1214,7 @@ def F_basis_pol(self, m, order_1=ZZ(0)): (x,y,z,d) = self.rat_field().gens() n = self._group.n() - if (n ==infinity): + if (n == infinity): order_1 = ZZ(order_1) order_inf = self._l1 - order_1 finf_pol = d*(x-y**2) @@ -2538,7 +2538,7 @@ def gen(self, k=0): """ k = ZZ(k) - if k>=0 and k < self.dimension(): + if k >= 0 and k < self.dimension(): return self.gens()[k] else: raise ValueError("Invalid index: k={} does not satisfy 0 <= k <= {}!".format(k, self.dimension())) diff --git a/src/sage/modular/modform_hecketriangle/constructor.py b/src/sage/modular/modform_hecketriangle/constructor.py index 9471394bea1..845098fe862 100644 --- a/src/sage/modular/modform_hecketriangle/constructor.py +++ b/src/sage/modular/modform_hecketriangle/constructor.py @@ -402,7 +402,7 @@ def FormsRing(analytic_type, group=3, base_ring=ZZ, red_hom=False): if analytic_type <= AT("weak"): if analytic_type <= AT("holo"): if analytic_type <= AT("cusp"): - if analytic_type <=AT([]): + if analytic_type <= AT([]): raise ValueError("Analytic type Zero is not valid for forms rings.") else: from .graded_ring import CuspFormsRing @@ -420,7 +420,7 @@ def FormsRing(analytic_type, group=3, base_ring=ZZ, red_hom=False): if analytic_type <= AT(["weak", "quasi"]): if analytic_type <= AT(["holo", "quasi"]): if analytic_type <= AT(["cusp", "quasi"]): - if analytic_type <=AT(["quasi"]): + if analytic_type <= AT(["quasi"]): raise ValueError("Analytic type Zero is not valid for forms rings.") else: from .graded_ring import QuasiCuspFormsRing diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py index 7c3867923c9..b0241196107 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py @@ -295,7 +295,7 @@ def word_S_T(self): S = self.parent().S() (L, sgn) = self._word_S_T_data() - M = [S if v[0]==0 else Tf(v[1]) for v in L] + M = [S if v[0] == 0 else Tf(v[1]) for v in L] if sgn > 0: sgn = self.parent().I() else: @@ -1025,7 +1025,7 @@ def primitive_representative(self, method="block"): G = self.parent() if self.is_identity(): - method="block" + method = "block" if self.is_elliptic(): if self.parent().n() == infinity: diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index 04e86a0732e..62d189e49d5 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -387,7 +387,7 @@ def _set_radius(self, radius): pi = p e = d if not e.is_integral(): - raise ValueError("no element of base ring (=%s) has normalised valuation %s" % (self.base_ring(), radius * 12 /(p-1))) + raise ValueError("no element of base ring (=%s) has normalised valuation %s" % (self.base_ring(), radius * 12 / (p-1))) self._radius = radius self._const = pi ** ZZ(e) @@ -1250,7 +1250,7 @@ def _discover_recurrence_matrix(self, use_smithline=True): xyring = PolynomialRing(self.base_ring(), ["x","y"], 2) x,y = xyring.gens() cc = self.prime() ** (-12/(self.prime() - 1)) - bigI = x*SmiH(y*cc)- y*cc*SmiH(x) + bigI = x*SmiH(y*cc) - y*cc*SmiH(x) smallI = xyring(bigI / (x - cc*y)) r = matrix(ZZ, self.prime(), self.prime()) for i in range(self.prime()): diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index fa66f2aa0a3..5183106e458 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -1004,14 +1004,14 @@ def level1_UpGj(p, klist, m, extra_data=False): e, Ep1 = katz_expansions(k0, p, ellp, mdash, n) verbose("done steps 2+3", t) - t=cputime() + t = cputime() # Step 4 G = compute_G(p, Ep1) Alist = [] verbose("done step 4a", t) - t=cputime() + t = cputime() for k in klist: k = ZZ(k) # convert to sage integer kdiv = k // (p - 1) diff --git a/src/sage/modular/pollack_stevens/distributions.py b/src/sage/modular/pollack_stevens/distributions.py index 274cdfa87a4..7aaad3c6f0e 100644 --- a/src/sage/modular/pollack_stevens/distributions.py +++ b/src/sage/modular/pollack_stevens/distributions.py @@ -319,7 +319,7 @@ def _element_constructor_(self, val, **kwargs): """ ordp = kwargs.get('ord',0) check = kwargs.get('check',True) - normalize= kwargs.get('normalize',True) + normalize = kwargs.get('normalize',True) return self.Element(val, self, ordp, check, normalize) def _coerce_map_from_(self, other): From 87c2f1e33f84ad460a9608bf6c6c7e2570f07883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 28 Sep 2023 17:38:58 +0200 Subject: [PATCH 148/225] fix detail --- src/sage/modular/modform/eis_series.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index f7575f6b150..39d78cdc0ea 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -431,15 +431,15 @@ def eisenstein_series_lseries(weight, prec=53, # Using a string for residues is a hack but it works well # since this will make PARI/GP compute sqrt(pi) with the # right precision. - residues ='[sqrt(Pi)*(%s)]' % ((-1)**Integer(j/2)*bernoulli(j)/j), + residues='[sqrt(Pi)*(%s)]' % ((-1)**Integer(j // 2) * bernoulli(j) / j), prec=prec) s = 'coeff = %s;' % f.list() - L.init_coeffs('coeff[k+1]',pari_precode=s, + L.init_coeffs('coeff[k+1]', pari_precode=s, max_imaginary_part=max_imaginary_part, max_asymp_coeffs=max_asymp_coeffs) L.check_functional_equation() - L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)' % (j,f)) + L.rename('L-series associated to the weight %s Eisenstein series %s on SL_2(Z)' % (j, f)) return L From 11995a6e4fd7f183d420f307af77297974a77a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 28 Sep 2023 17:55:10 +0200 Subject: [PATCH 149/225] fixing pep8 E275 in rings/ and combinat/ --- src/sage/combinat/alternating_sign_matrix.py | 4 ++-- src/sage/combinat/binary_tree.py | 4 ++-- .../cluster_algebra_quiver/cluster_seed.py | 2 +- .../combinat/cluster_algebra_quiver/quiver.py | 4 ++-- src/sage/combinat/combination.py | 4 ++-- src/sage/combinat/constellation.py | 2 +- src/sage/combinat/crystals/direct_sum.py | 2 +- src/sage/combinat/derangements.py | 4 ++-- src/sage/combinat/dlx.py | 2 +- src/sage/combinat/e_one_star.py | 2 +- src/sage/combinat/finite_state_machine.py | 2 +- src/sage/combinat/free_module.py | 12 ++++++------ src/sage/combinat/ncsf_qsym/ncsf.py | 2 +- src/sage/combinat/ncsf_qsym/qsym.py | 2 +- src/sage/combinat/ncsym/dual.py | 2 +- src/sage/combinat/ncsym/ncsym.py | 2 +- src/sage/combinat/parallelogram_polyomino.py | 8 ++++---- src/sage/combinat/partition_algebra.py | 2 +- src/sage/combinat/permutation.py | 6 +++--- src/sage/combinat/posets/posets.py | 4 ++-- .../combinat/root_system/branching_rules.py | 2 +- src/sage/combinat/root_system/cartan_type.py | 4 ++-- src/sage/combinat/root_system/pieri_factors.py | 2 +- .../root_system/weight_lattice_realizations.py | 2 +- src/sage/combinat/sf/sf.py | 2 +- src/sage/combinat/shuffle.py | 8 ++++---- src/sage/combinat/similarity_class_type.py | 8 ++++---- .../symmetric_group_representations.py | 2 +- src/sage/combinat/tableau.py | 4 ++-- src/sage/combinat/tamari_lattices.py | 6 +++--- src/sage/combinat/words/abstract_word.py | 2 +- src/sage/combinat/words/morphism.py | 4 ++-- .../combinat/words/word_infinite_datatypes.py | 10 +++++----- src/sage/rings/asymptotic/growth_group.py | 4 ++-- .../rings/asymptotic/growth_group_cartesian.py | 2 +- src/sage/rings/cfinite_sequence.py | 4 ++-- src/sage/rings/continued_fraction.py | 2 +- .../function_field/function_field_polymod.py | 6 +++--- src/sage/rings/function_field/valuation.py | 2 +- src/sage/rings/infinity.py | 8 ++++---- .../rings/multi_power_series_ring_element.py | 4 ++-- src/sage/rings/number_field/number_field.py | 8 ++++---- .../rings/number_field/number_field_rel.py | 2 +- src/sage/rings/padics/padic_valuation.py | 8 ++++---- .../padics/unramified_extension_generic.py | 2 +- src/sage/rings/pari_ring.py | 2 +- .../rings/polynomial/binary_form_reduce.py | 2 +- .../polynomial/polynomial_element_generic.py | 2 +- .../polynomial/polynomial_quotient_ring.py | 4 ++-- src/sage/rings/qqbar.py | 10 +++++----- .../rings/valuation/augmented_valuation.py | 4 ++-- .../rings/valuation/inductive_valuation.py | 2 +- src/sage/rings/valuation/limit_valuation.py | 6 +++--- src/sage/rings/valuation/mapped_valuation.py | 4 ++-- src/sage/rings/valuation/valuation_space.py | 18 +++++++++--------- 55 files changed, 117 insertions(+), 117 deletions(-) diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index 80d4ab301b7..dcdd0ffb614 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -1823,7 +1823,7 @@ def __classcall_private__(cls, n, **kwds): """ - assert(isinstance(n, (int, Integer))) + assert (isinstance(n, (int, Integer))) return ContreTableaux_n(n, **kwds) @@ -1985,7 +1985,7 @@ def __classcall_private__(cls, n, last_column, **kwds): """ - assert(isinstance(n, (int, Integer))) + assert (isinstance(n, (int, Integer))) return TruncatedStaircases_nlastcolumn(n, last_column, **kwds) diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index 8e876ab137a..2840165685d 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -914,7 +914,7 @@ def make_node(self, child_list=[None, None]): """ self._require_mutable() child_lst = [self.__class__(self.parent(), x) for x in child_list] - if not(len(child_lst) == 2): + if not (len(child_lst) == 2): raise ValueError("the list must have length 2") self.__init__(self.parent(), child_lst, check=False) @@ -1873,7 +1873,7 @@ def left_border_symmetry(self): labelled = self in LabelledBinaryTrees() labels = [] t = self - while(t): + while (t): border.append(t[1].left_border_symmetry()) if labelled: labels.append(t.label()) diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index a67af5739ce..ff40af714c2 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -4345,7 +4345,7 @@ def oriented_exchange_graph(self): j = i.mutate(k, inplace=False) Varj = tuple(sorted(j.cluster())) covers.append((Vari, Varj)) - if not(Varj in known_clusters): + if not (Varj in known_clusters): known_clusters += [Varj] stack.append(j) diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver.py b/src/sage/combinat/cluster_algebra_quiver/quiver.py index 23d4e5c3a62..028f8abb797 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver.py @@ -2180,7 +2180,7 @@ def d_vector_fan(self): from sage.geometry.fan import Fan from sage.geometry.cone import Cone - if not(self.is_finite()): + if not (self.is_finite()): raise ValueError('only makes sense for quivers of finite type') seed = ClusterSeed(self) return Fan([Cone(s.d_matrix().columns()) @@ -2228,7 +2228,7 @@ def g_vector_fan(self): from sage.geometry.fan import Fan from sage.geometry.cone import Cone - if not(self.is_finite()): + if not (self.is_finite()): raise ValueError('only supported for quivers of finite type') seed = ClusterSeed(self).principal_extension() return Fan([Cone(s.g_matrix().columns()) diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index fc8b044d89d..dca90c2a4e3 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -242,7 +242,7 @@ def __ne__(self, other): sage: c != Combinations([1,2,3,3]) True """ - return not(self == other) + return not (self == other) def __repr__(self): """ @@ -395,7 +395,7 @@ def __ne__(self, other): sage: c != Combinations((1,2,2,3), 2) True """ - return not(self == other) + return not (self == other) def __repr__(self): """ diff --git a/src/sage/combinat/constellation.py b/src/sage/combinat/constellation.py index cbefe06054d..b617315c07f 100644 --- a/src/sage/combinat/constellation.py +++ b/src/sage/combinat/constellation.py @@ -565,7 +565,7 @@ def is_isomorphic(self, other, return_map=False): True """ if return_map: - if not(self.degree() == other.degree() and + if not (self.degree() == other.degree() and self.length() == other.length()): return False, None sn, sn_map = self.relabel(return_map=True) diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index e66ea6e9ef5..0aaaad8debb 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -141,7 +141,7 @@ def __init__(self, crystals, facade, keepkey, category, **options): if len(crystals) == 0: raise ValueError("the direct sum is empty") else: - assert(crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) + assert (crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: self.module_generators = tuple([ self((i,b)) for i,B in enumerate(crystals) diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index 0c4b8a3d9d7..93ae0e8d7cb 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -445,10 +445,10 @@ def _rand_der(self): mark = [x < 0 for x in A] i, u = n, n while u >= 2: - if not(mark[i - 1]): + if not (mark[i - 1]): while True: j = randrange(1, i) - if not(mark[j - 1]): + if not (mark[j - 1]): A[i - 1], A[j - 1] = A[j - 1], A[i - 1] break p = random() diff --git a/src/sage/combinat/dlx.py b/src/sage/combinat/dlx.py index d243abbc9c2..25990fe55fe 100644 --- a/src/sage/combinat/dlx.py +++ b/src/sage/combinat/dlx.py @@ -237,7 +237,7 @@ def _constructmatrix(self, ones, initialsolution=None): for r in ones: curRow = r[0] # row index columns = r[1] # column indexes - if not(columns): + if not (columns): continue columns.sort() diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index cb6e5607931..dbab29b1381 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -287,7 +287,7 @@ def __init__(self, v, t, color=None): self._vector = (ZZ**len(v))(v) self._vector.set_immutable() - if not((t in ZZ) and 1 <= t <= len(v)): + if not ((t in ZZ) and 1 <= t <= len(v)): raise ValueError('the type must be an integer between 1 and len(v)') self._type = t diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 494e8154c80..c76373962b9 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -9614,7 +9614,7 @@ def find_final_word_out(state): return final_word_out for state in self.iter_states(): - assert(not in_progress) + assert (not in_progress) # trailing_letters is an infinite iterator additionally # marking positions trailing_letters = itertools.cycle(enumerate(letters)) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 5c196c6cbf4..2ad7845f0a5 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1349,9 +1349,9 @@ def __classcall_private__(cls, modules, **options): sage: T in Modules(ZZ).FiniteDimensional() True """ - assert(len(modules) > 0) + assert (len(modules) > 0) R = modules[0].base_ring() - assert(all(module in ModulesWithBasis(R)) for module in modules) + assert (all(module in ModulesWithBasis(R)) for module in modules) # should check the base ring # flatten the list of modules so that tensor(A, tensor(B,C)) gets rewritten into tensor(A, B, C) modules = sum([module._sets if isinstance(module, CombinatorialFreeModule_Tensor) else (module,) for module in modules], ()) @@ -1572,8 +1572,8 @@ def tensor_constructor(self, modules): + B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6] + 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6] """ - assert(module in ModulesWithBasis(self.base_ring()) for module in modules) - assert(tensor(modules) == self) + assert (module in ModulesWithBasis(self.base_ring()) for module in modules) + assert (tensor(modules) == self) # a list l such that l[i] is True if modules[i] is readily a tensor product is_tensor = [isinstance(module, CombinatorialFreeModule_Tensor) for module in modules] # the tensor_constructor, on basis elements @@ -1772,9 +1772,9 @@ def __init__(self, modules, **options): Free module generated by {2, 4, 5} over Integer Ring (+) Free module generated by {2, 4, 7} over Integer Ring sage: TestSuite(C).run() """ - assert(len(modules)) # TODO: generalize to a family or tuple + assert (len(modules)) # TODO: generalize to a family or tuple R = modules[0].base_ring() - assert(all(module in ModulesWithBasis(R)) for module in modules) + assert (all(module in ModulesWithBasis(R)) for module in modules) # should check the base ring self._sets = modules CombinatorialFreeModule.__init__(self, R, diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f9aafb014aa..435d6f1243b 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -410,7 +410,7 @@ def __init__(self, R): sage: TestSuite(NonCommutativeSymmetricFunctions(QQ)).run() """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring cat = GradedHopfAlgebras(R).WithRealizations().Cocommutative() Parent.__init__(self, category=cat) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index fe4e58277b1..a1949436b07 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -557,7 +557,7 @@ def __init__(self, R): sage: TestSuite(QuasiSymmetricFunctions(QQ)).run() """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R).Commutative() self._category = category diff --git a/src/sage/combinat/ncsym/dual.py b/src/sage/combinat/ncsym/dual.py index 5acd9c8f176..4cec7d5cf79 100644 --- a/src/sage/combinat/ncsym/dual.py +++ b/src/sage/combinat/ncsym/dual.py @@ -48,7 +48,7 @@ def __init__(self, R): sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run() """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Commutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 64772ade2d7..0a733ce20a7 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -294,7 +294,7 @@ def __init__(self, R): sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ)).run() """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Cocommutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/parallelogram_polyomino.py b/src/sage/combinat/parallelogram_polyomino.py index 9c4ceedfd19..3b5fb336644 100644 --- a/src/sage/combinat/parallelogram_polyomino.py +++ b/src/sage/combinat/parallelogram_polyomino.py @@ -253,7 +253,7 @@ def __setitem__(self, key, value): sage: o["size"]=-6 """ - assert(key in self._available_options) + assert (key in self._available_options) if value == "?": res = "Current value : " + str(self._options[key]) option_key = self._available_options[key] @@ -263,9 +263,9 @@ def __setitem__(self, key, value): else: available_options = self._available_options if "values" in available_options: - assert(value in self._available_options[key]["values"]) + assert (value in self._available_options[key]["values"]) if "checker" in available_options: - assert(available_options["checker"](value)) + assert (available_options["checker"](value)) self._options[key] = value def __call__(self, *get_values, **options): @@ -450,7 +450,7 @@ def _dispatch(self, obj, dispatch_to, option, *get_values, **set_values): sage: e.options(delim='p'); e p """ - assert(option in self._available_options) + assert (option in self._available_options) if dispatch_to[-1] == "_": dispatch_to = dispatch_to[:-1] f = getattr(obj, dispatch_to + "_" + str(self._options[option])) diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 0b7eb06c3a5..be9b5826211 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -1980,7 +1980,7 @@ def set_partition_composition(sp1, sp2): total_removed = 0 for cc in connected_components: # Remove the vertices that live in the middle two rows - new_cc = [x for x in cc if not((x[0] < 0 and x[1] == 1) or + new_cc = [x for x in cc if not ((x[0] < 0 and x[1] == 1) or (x[0] > 0 and x[1] == 2))] if not new_cc: diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 5cf89374de9..308cb4909bd 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -1579,7 +1579,7 @@ def merge_and_countv(ivA_A, ivB_B): i, j = 0, 0 ivC = [] lA, lB = len(A), len(B) - while(i < lA and j < lB): + while (i < lA and j < lB): if B[j] < A[i]: C.append(B[j]) ivC.append(ivB[j] + lA - i) @@ -2267,7 +2267,7 @@ def longest_increasing_subsequences(self): """ n = self.size() if n == 0: - return([[]]) + return ([[]]) from bisect import insort, bisect @@ -5396,7 +5396,7 @@ def _tableau_contribution(T): 3 """ from sage.combinat.tableau import StandardTableaux - return(StandardTableaux(T.shape()).cardinality()) + return (StandardTableaux(T.shape()).cardinality()) ################################################################ # Parent classes diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index c31597c72e9..0963c2b9d31 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -681,7 +681,7 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio for the poset as it contains duplicate elements """ # Avoiding some errors from the user when data should be a pair - if not(element_labels is None or isinstance(element_labels, (dict, list))): + if not (element_labels is None or isinstance(element_labels, (dict, list))): raise TypeError("element_labels should be a dict or a list if " "different from None. (Did you intend data to be " "equal to a pair ?)") @@ -5219,7 +5219,7 @@ def rees_product(self, other): ... TypeError: the Rees product is defined only for graded posets """ - if not(self.is_graded() and other.is_graded()): + if not (self.is_graded() and other.is_graded()): raise TypeError('the Rees product is defined only for graded posets') rk0 = self.rank_function() diff --git a/src/sage/combinat/root_system/branching_rules.py b/src/sage/combinat/root_system/branching_rules.py index d92d08a8eed..b2ace92a56d 100644 --- a/src/sage/combinat/root_system/branching_rules.py +++ b/src/sage/combinat/root_system/branching_rules.py @@ -1125,7 +1125,7 @@ def __ne__(self, other): sage: b1 != b2 True """ - return not(self == other) + return not (self == other) def __mul__(self, other): """ diff --git a/src/sage/combinat/root_system/cartan_type.py b/src/sage/combinat/root_system/cartan_type.py index 727319bc230..816fbadcd57 100644 --- a/src/sage/combinat/root_system/cartan_type.py +++ b/src/sage/combinat/root_system/cartan_type.py @@ -2129,7 +2129,7 @@ def row_annihilator(self, m=None): annihilator_basis = m.integer_kernel().gens() if len(annihilator_basis) != 1: raise ValueError("the kernel is not 1 dimensional") - assert(all(coef > 0 for coef in annihilator_basis[0])) + assert (all(coef > 0 for coef in annihilator_basis[0])) return Family(dict((i,annihilator_basis[0][i])for i in self.index_set())) @@ -2711,7 +2711,7 @@ def __init__(self, letter, n, affine=1): False """ - assert(letter in ['A', 'B', 'C', 'BC', 'D', 'E', 'F', 'G']) + assert (letter in ['A', 'B', 'C', 'BC', 'D', 'E', 'F', 'G']) self.letter = letter self.n = n self.affine = affine diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index d2627a36413..28b26d8bf6f 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -700,7 +700,7 @@ def __contains__(self, w): if len(support) < len(red): # There should be no repetitions return False - if not(self._min_length <= len(support) and + if not (self._min_length <= len(support) and len(support) <= self._max_length and self._min_support.issubset(support) and support.issubset(self._max_support)): diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 25dd3c90acf..7a6e76faacc 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -292,7 +292,7 @@ def _test_weight_lattice_realization(self, **options): # Check that the fundamental weights form the dual basis of the simple coroots for i in self.index_set(): - assert(Lambda[i].is_dominant()) + assert (Lambda[i].is_dominant()) for j in self.index_set(): tester.assertEqual(Lambda[j].scalar(alphacheck[i]), (1 if i == j else 0)) diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index 56b3b96f279..81665f56fbd 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -865,7 +865,7 @@ def __init__(self, R): """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert(R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R self._base = R # Won't be needed when CategoryObject won't override anymore base_ring cat = GradedHopfAlgebras(R).Commutative().Cocommutative() if R in PrincipalIdealDomains(): diff --git a/src/sage/combinat/shuffle.py b/src/sage/combinat/shuffle.py index 4c8a9cdd217..d8cf7539f0b 100644 --- a/src/sage/combinat/shuffle.py +++ b/src/sage/combinat/shuffle.py @@ -220,10 +220,10 @@ def __init__(self, l1, l2, element_constructor=None): [[2, 3, 4, 5], [2, 5, 3, 4], [5, 2, 3, 4], [2, 3, 5, 4], [1, 2, 3, 5], [1, 5, 2, 3], [5, 1, 2, 3], [1, 2, 5, 3]] """ - assert(isinstance(l1, Iterable) and + assert (isinstance(l1, Iterable) and isinstance(l2, Iterable)) - assert(all(isinstance(elem, Iterable) for elem in l1)) - assert(all(isinstance(elem, Iterable) for elem in l2)) + assert (all(isinstance(elem, Iterable) for elem in l1)) + assert (all(isinstance(elem, Iterable) for elem in l2)) if element_constructor is None: try: @@ -361,7 +361,7 @@ def __init__(self, l1, l2, element_constructor=None): [word: aabbb, word: baabb, word: ababb, word: bbaab, word: babab, word: abbab, word: bbbaa, word: bbaba, word: babba, word: abbba] """ - assert(isinstance(l1, Iterable) and isinstance(l2, Iterable)) + assert (isinstance(l1, Iterable) and isinstance(l2, Iterable)) if element_constructor is None: try: diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 94e87115ea3..f3169e19ba7 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -1421,15 +1421,15 @@ def input_parsing(data): try: data = Partition(data) case = 'par' - except(TypeError, ValueError): + except (TypeError, ValueError): try: data = SimilarityClassType(data) case = 'sim' - except(TypeError, ValueError): + except (TypeError, ValueError): try: data = PrimarySimilarityClassType(*data) case = 'pri' - except(TypeError, ValueError): + except (TypeError, ValueError): raise ValueError("expected a Partition, a SimilarityClassType or a PrimarySimilarityClassType, got a %s" % type(data)) return case, data @@ -1686,7 +1686,7 @@ def ext_orbit_centralizers(input_data, q=None, selftranspose=False): for item in product(*[IterableFunctionCall(lambda x: ext_orbit_centralizers(x, q=q, selftranspose=selftranspose), PT) for PT in tau]): size = prod([list(entry)[0] for entry in item]) freq = prod([list(entry)[1] for entry in item]) - yield(size, freq) + yield (size, freq) def matrix_centralizer_cardinalities_length_two(n, q=None, selftranspose=False, invertible=False): diff --git a/src/sage/combinat/symmetric_group_representations.py b/src/sage/combinat/symmetric_group_representations.py index ee518756525..2db6ac21ce8 100644 --- a/src/sage/combinat/symmetric_group_representations.py +++ b/src/sage/combinat/symmetric_group_representations.py @@ -627,7 +627,7 @@ def representation_matrix_for_simple_transposition(self, i): [ 1/2 1/2] """ from copy import copy - if not(1 <= i < sum(self._partition)): + if not (1 <= i < sum(self._partition)): raise TypeError Y = self._yang_baxter_graph index_lookup = {b: a for a, b in enumerate(list(Y))} diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index cd3c902e1c9..f13daf65a1e 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -6408,7 +6408,7 @@ def __iter__(self): from sage.combinat.partition import Partitions # Iterates through with maximum entry as order i = 1 - while(True): + while (True): for part in Partitions(self.size): if i != 1: for k in range(1, self.size+1): @@ -6508,7 +6508,7 @@ def __iter__(self): # Iterates through with maximum entry as order i = 1 n = sum(self.shape) - while(True): + while (True): if i != 1: for k in range(1, n+1): for c in integer_vectors_nk_fast_iter(n - k, i-1): diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 6ef7dd06cdc..6bcca79ca97 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -87,7 +87,7 @@ def paths_in_triangle(i, j, a, b) -> list[tuple[int, ...]]: sage: paths_in_triangle(3,2,5,3) [(1, 0, 1, 0, 0), (1, 1, 0, 0, 0)] """ - if not(b >= j and j * a >= i * b and i >= 0): + if not (b >= j and j * a >= i * b and i >= 0): raise ValueError("the endpoint is not valid") if i == 0: @@ -215,9 +215,9 @@ def GeneralizedTamariLattice(a, b, m=1, check=True): .. [BMFPR] \M. Bousquet-Melou, E. Fusy, L.-F. Preville Ratelle. *The number of intervals in the m-Tamari lattices*. :arxiv:`1106.1498` """ - if not(gcd(a, b) == 1 and a >= b): + if not (gcd(a, b) == 1 and a >= b): raise ValueError("the numbers a and b must be coprime with a>=b") - if not(a >= b * m): + if not (a >= b * m): raise ValueError("the condition a>=b*m does not hold") def covers(p): diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index 1488d8e7271..e63fd8b912f 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -641,7 +641,7 @@ def _to_integer_iterator(self, use_parent_alphabet=False): mapping = {} next_value = 0 for letter in self: - if not(letter in mapping): + if not (letter in mapping): mapping[letter] = next_value next_value += 1 yield mapping[letter] diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index b06acd3839e..2223ef752ca 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -2295,13 +2295,13 @@ def list_of_conjugates(self): c = [] m = self c.append(m) - while(m.has_left_conjugate()): + while (m.has_left_conjugate()): m = m.conjugate(1) if m == self: break c.append(m) m = self - while(m.has_right_conjugate()): + while (m.has_right_conjugate()): m = m.conjugate(-1) if m == self: break diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index defef1e84d1..1e41a5e4e22 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -237,8 +237,8 @@ def __getitem__(self, key): if isinstance(key, slice): # Infinite words if self._len is Infinity or self._len is None: - if not(key.start is None) and key.start < 0 or \ - not(key.stop is None) and key.stop < 0: + if not (key.start is None) and key.start < 0 or \ + not (key.stop is None) and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else key.step if step > 0: @@ -831,8 +831,8 @@ def __getitem__(self, key): """ if isinstance(key, slice): if self._len is Infinity or self._len is None: - if not(key.start is None) and key.start < 0 or \ - not(key.stop is None) and key.stop < 0: + if not (key.start is None) and key.start < 0 or \ + not (key.stop is None) and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else int(key.step) if step >= 0: @@ -862,7 +862,7 @@ def __getitem__(self, key): step = 1 if key.step is None else int(key.step) # If either key.start or key.stop is negative, # then we need to expand the word. - if start < 0 or (not(stop is None) and stop < 0): + if start < 0 or (not (stop is None) and stop < 0): data = list(self)[key] length = None # If key.step is negative, then we need to expand a prefix. diff --git a/src/sage/rings/asymptotic/growth_group.py b/src/sage/rings/asymptotic/growth_group.py index 27c14592bca..906a0dbae57 100644 --- a/src/sage/rings/asymptotic/growth_group.py +++ b/src/sage/rings/asymptotic/growth_group.py @@ -3137,7 +3137,7 @@ def _log_factor_(self, base=None, locals=None): return ((e, coefficient),) if var.startswith('exp('): - assert(var[-1] == ')') + assert (var[-1] == ')') v = var[4:-1] else: v = 'log(%s)' % (var,) @@ -3207,7 +3207,7 @@ def _rpow_element_(self, base, locals=None): x^(log(2)) """ var = str(self.parent()._var_) - if not(var.startswith('log(') and self.exponent.is_one()): + if not (var.startswith('log(') and self.exponent.is_one()): raise ValueError('Variable %s is not a log of something.' % (var,)) new_var = var[4:-1] if base == 'e': diff --git a/src/sage/rings/asymptotic/growth_group_cartesian.py b/src/sage/rings/asymptotic/growth_group_cartesian.py index f93535e8d8e..447c25fa64d 100644 --- a/src/sage/rings/asymptotic/growth_group_cartesian.py +++ b/src/sage/rings/asymptotic/growth_group_cartesian.py @@ -837,7 +837,7 @@ def next_custom(self): S.next_custom() O.next_custom() - assert(len(newS) == len(newO)) + assert (len(newS) == len(newO)) if (len(Sfactors) == len(newS) and len(Ofactors) == len(newO)): diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index 7229dab646a..26cce303581 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -155,7 +155,7 @@ def CFiniteSequences(base_ring, names=None, category=None): raise NotImplementedError("Multidimensional o.g.f. not implemented.") if category is None: category = Fields() - if not(base_ring in (QQ, ZZ)): + if not (base_ring in (QQ, ZZ)): raise ValueError("O.g.f. base not rational.") polynomial_ring = PolynomialRing(base_ring, names) return CFiniteSequences_generic(polynomial_ring, category) @@ -301,7 +301,7 @@ def __classcall_private__(cls, ogf): """ br = ogf.base_ring() - if not(br in (QQ, ZZ)): + if not (br in (QQ, ZZ)): br = QQ # if the base ring of the o.g.f is not QQ, we force it to QQ and see if the o.g.f converts nicely # trying to figure out the ogf variables diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index a3f877e423d..0765188366f 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -725,7 +725,7 @@ def _mpfr_(self, R): # in order to find the nearest approximation we possibly need to # augment our precision on convergents. while True: - assert not(p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not(p_even << (N+1) >= (2*m_even+1) * q_even) + assert not (p_odd << (N+1) <= (2*m_odd-1) * q_odd) or not (p_even << (N+1) >= (2*m_even+1) * q_even) if p_odd << (N+1) <= (2*m_odd-1) * q_odd: return R(sgn * m_even) >> N if p_even << (N+1) >= (2*m_even+1) * q_even: diff --git a/src/sage/rings/function_field/function_field_polymod.py b/src/sage/rings/function_field/function_field_polymod.py index 460096c94a1..b740b771bec 100644 --- a/src/sage/rings/function_field/function_field_polymod.py +++ b/src/sage/rings/function_field/function_field_polymod.py @@ -1127,9 +1127,9 @@ def _simple_model(self, name='v'): L = M.base_field() K = L.base_field() - assert(isinstance(K, RationalFunctionField)) - assert(K is not L) - assert(L is not M) + assert (isinstance(K, RationalFunctionField)) + assert (K is not L) + assert (L is not M) if not K.constant_field().is_perfect(): raise NotImplementedError("simple_model() only implemented over perfect constant fields") diff --git a/src/sage/rings/function_field/valuation.py b/src/sage/rings/function_field/valuation.py index e8afd1cb232..3c92f8cf212 100644 --- a/src/sage/rings/function_field/valuation.py +++ b/src/sage/rings/function_field/valuation.py @@ -1474,7 +1474,7 @@ def _repr_(self): [ Valuation at the infinite place, v(y - 1) = 2 ]-adic valuation] """ - assert(self.domain().base() is not self.domain()) + assert (self.domain().base() is not self.domain()) if repr(self._base_valuation) == repr(self.restriction(self.domain().base())): return repr(self._base_valuation) return super()._repr_() diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index c5ab0b24f32..3c4a960c037 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -1865,11 +1865,11 @@ def test_signed_infinity(pos_inf): assert InfinityRing(pos_inf) is infinity, msg assert InfinityRing(-pos_inf) is minus_infinity, msg assert infinity == pos_inf, msg - assert not(infinity > pos_inf), msg - assert not(infinity < pos_inf), msg + assert not (infinity > pos_inf), msg + assert not (infinity < pos_inf), msg assert minus_infinity == -pos_inf, msg - assert not(minus_infinity > -pos_inf), msg - assert not(minus_infinity < -pos_inf), msg + assert not (minus_infinity > -pos_inf), msg + assert not (minus_infinity < -pos_inf), msg assert pos_inf > -pos_inf, msg assert infinity > -pos_inf, msg assert pos_inf > minus_infinity, msg diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index bd6fbde6247..8801d2d279a 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -1954,7 +1954,7 @@ def exp(self, prec=infinity): if x.is_zero(): return exp_c val = x.valuation() - assert(val >= 1) + assert (val >= 1) prec = min(prec, self.prec()) if is_Infinite(prec): @@ -2051,7 +2051,7 @@ def log(self, prec=infinity): if x.is_zero(): return log_c val = x.valuation() - assert(val >= 1) + assert (val >= 1) prec = min(prec, self.prec()) if is_Infinite(prec): diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 7fe89197011..b4ba6de1362 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -2839,7 +2839,7 @@ def is_CM(self): # Return cached answer if available try: return self.__is_CM - except(AttributeError): + except (AttributeError): pass # Then, deal with simple cases @@ -2925,7 +2925,7 @@ def complex_conjugation(self): # Return cached answer if available try: return self.__complex_conjugation - except(AttributeError): + except (AttributeError): pass # Then, deal with simple cases @@ -2956,7 +2956,7 @@ def complex_conjugation(self): # In the remaining case, self.is_CM() should have cached __max_tot_real_sub try: F, phi = self.__max_tot_real_sub - except(AttributeError): + except (AttributeError): F, phi = self.maximal_totally_real_subfield() if self.is_absolute(): K_rel = self.relativize(phi, self.variable_name() * 2) @@ -3061,7 +3061,7 @@ def maximal_totally_real_subfield(self): try: return self.__max_tot_real_sub - except(AttributeError): + except (AttributeError): pass if isinstance( diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 1e8a6a17fe1..26ab82bc54f 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -1358,7 +1358,7 @@ def is_CM_extension(self): try: return self.__is_CM_extension - except(AttributeError): + except (AttributeError): pass if self.relative_degree() == 2: diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index b6ea2ea75ee..90e9d205ac5 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -256,7 +256,7 @@ def create_key_and_extra_args_for_number_field_from_valuation(self, R, v, prime, else: raise NotImplementedError("cannot rewrite %r which is defined on %r as a pseudo-valuation on %r" % (v, v.domain(), G.parent())) - assert(v.domain() is G.parent()) + assert (v.domain() is G.parent()) # To obtain uniqueness of p-adic valuations, we need a canonical # description of v. We consider all extensions of vK to L and select @@ -397,11 +397,11 @@ def create_object(self, version, key, **extra_args): R = key[0] parent = DiscretePseudoValuationSpace(R) if isinstance(R, pAdicGeneric): - assert(len(key) == 1) + assert (len(key) == 1) return parent.__make_element_class__(pAdicValuation_padic)(parent) elif R is ZZ or R is QQ: prime = key[1] - assert(len(key) == 2) + assert (len(key) == 2) return parent.__make_element_class__(pAdicValuation_int)(parent, prime) else: v = key[1] @@ -1281,7 +1281,7 @@ def simplify(self, x, error=None, force=False, size_heuristic_bound=32): if self._relative_size(rational) < self._relative_size(best): best = rational - assert(self(x-best) > error) + assert (self(x-best) > error) return best diff --git a/src/sage/rings/padics/unramified_extension_generic.py b/src/sage/rings/padics/unramified_extension_generic.py index b73b88ebc1c..67aa2be9267 100644 --- a/src/sage/rings/padics/unramified_extension_generic.py +++ b/src/sage/rings/padics/unramified_extension_generic.py @@ -229,7 +229,7 @@ def _frob_gen(self, arithmetic=True): approx = (self(a.residue()**exp)).lift_to_precision(self.precision_cap()) #first approximation f = self.defining_polynomial() g = f.derivative() - while(f(approx) != 0): #hensel lift frobenius(a) + while (f(approx) != 0): #hensel lift frobenius(a) approx = approx - f(approx)/g(approx) return approx diff --git a/src/sage/rings/pari_ring.py b/src/sage/rings/pari_ring.py index 98b42c2634a..b44ee143680 100644 --- a/src/sage/rings/pari_ring.py +++ b/src/sage/rings/pari_ring.py @@ -123,7 +123,7 @@ def __pow__(self, other): sage: a^2 9 """ - if not(other in PariRing()): + if not (other in PariRing()): other = Pari(other) return self.__class__(self.__x ** other.__x, parent=_inst) diff --git a/src/sage/rings/polynomial/binary_form_reduce.py b/src/sage/rings/polynomial/binary_form_reduce.py index fb60089a751..1a9896f2199 100644 --- a/src/sage/rings/polynomial/binary_form_reduce.py +++ b/src/sage/rings/polynomial/binary_form_reduce.py @@ -418,7 +418,7 @@ def get_bound_poly(F, prec=53, norm_type='norm', emb=None): else: compF = F n = F.degree() - assert(n > 2), "degree 2 polynomial" + assert (n > 2), "degree 2 polynomial" z0F, thetaF = covariant_z0(compF, prec=prec, emb=emb) if norm_type == 'norm': diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 1f447fc1287..b6a260e7008 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -1267,7 +1267,7 @@ def hensel_lift(self, a): # Newton iteration # Todo: compute everything up to the adequate precision at each step b = ~dera - while(True): + while (True): na = a - selfa * b if na == a: return a diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index e372be888ee..99d90a5c8f7 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -2099,10 +2099,10 @@ def _isomorphic_ring(self): basis = [self.gen()**i*self.base_ring().gen()**j for i in range(self.degree()) for j in range(self.base_ring().degree())] - assert(len(basis) == isomorphic_ring.degree()) + assert (len(basis) == isomorphic_ring.degree()) from sage.matrix.constructor import matrix A = matrix([to_isomorphic_ring(b)._vector_() for b in basis]) - assert(A.is_square()) + assert (A.is_square()) # solve x*A = (0,1,0,…,0) x = A.solve_left(A.column_space().basis()[1]) primitive_element = sum(c*b for c,b in zip(x.list(), basis)) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 9602d569984..77d035896d0 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -3399,7 +3399,7 @@ def super_poly(self, super, checked=None): continue if self is u.child1: return u.child1_poly(poly) - assert(self is u.child2) + assert (self is u.child2) return u.child2_poly(poly) return None @@ -3447,7 +3447,7 @@ def __call__(self, elt): return elt.field_element_value() gen = elt.generator() sp = gen.super_poly(self) - assert(not(sp is None)) + assert (not (sp is None)) return self._field(elt.field_element_value().polynomial()(sp)) @@ -7543,7 +7543,7 @@ def find_fn(factor, prec): my_factor = find_zero_result(find_fn, qpf) # Factoring always returns monic polynomials over the rationals - assert(my_factor.is_monic()) + assert (my_factor.is_monic()) if my_factor.degree() == 1: return ANRational(-my_factor[0]) @@ -7586,7 +7586,7 @@ def find_fn(factor, prec): return ip(self_val) my_factor = find_zero_result(find_fn, fpf) - assert(my_factor.is_monic()) + assert (my_factor.is_monic()) if my_factor.degree() == 1: return ANExtensionElement(gen, -my_factor[0]) @@ -7751,7 +7751,7 @@ def handle_sage_input(self, sib, coerce, is_qqbar): ({call: {atomic:QQbar}({binop:+ {atomic:1} {atomic:I}})}, True) """ if self._generator is QQbar_I_generator: - assert(is_qqbar) + assert (is_qqbar) re, im = self._value.list() im_part = sib.prod([sib(im, True), sib.name('I')], simplify=True) v = sib.sum([sib(re, True), im_part], simplify=True) diff --git a/src/sage/rings/valuation/augmented_valuation.py b/src/sage/rings/valuation/augmented_valuation.py index 37fda19d7dc..7019fc39e91 100644 --- a/src/sage/rings/valuation/augmented_valuation.py +++ b/src/sage/rings/valuation/augmented_valuation.py @@ -631,7 +631,7 @@ def is_gauss_valuation(self): False """ - assert(self._mu > 0) + assert (self._mu > 0) return False def monic_integral_model(self, G): @@ -1120,7 +1120,7 @@ def lift(self, F): G = PolynomialRing(F.base_ring(), 'x')(list(F)) else: G = F.polynomial() - assert(G(self._residue_field_generator()) == F) + assert (G(self._residue_field_generator()) == F) F = G.change_variable_name(self._base_valuation.residue_ring().variable_name()) H = self._base_valuation.lift(F) diff --git a/src/sage/rings/valuation/inductive_valuation.py b/src/sage/rings/valuation/inductive_valuation.py index 8cc999d5bbd..5da834ad018 100644 --- a/src/sage/rings/valuation/inductive_valuation.py +++ b/src/sage/rings/valuation/inductive_valuation.py @@ -1033,7 +1033,7 @@ def is_minimal(self, f, assume_equivalence_irreducible=False): assert not F.is_constant() return F.is_irreducible() else: - assert(self(f) <= 0) # f is monic + assert (self(f) <= 0) # f is monic # f is not minimal: # Let g be f stripped of its leading term, i.e., g = f - x^n. # Then g and f are equivalent with respect to this valuation diff --git a/src/sage/rings/valuation/limit_valuation.py b/src/sage/rings/valuation/limit_valuation.py index 2820c7123a9..6aae23d9cfa 100644 --- a/src/sage/rings/valuation/limit_valuation.py +++ b/src/sage/rings/valuation/limit_valuation.py @@ -531,7 +531,7 @@ def _improve_approximation(self): check=False, principal_part_bound=1 if self._approximation.E() * self._approximation.F() == self._approximation.phi().degree() else None, report_degree_bounds_and_caches=True) - assert(len(approximations) == 1) + assert (len(approximations) == 1) self._approximation, _, _, self._next_coefficients, self._next_valuations = approximations[0] def _improve_approximation_for_call(self, f): @@ -669,7 +669,7 @@ def residue_ring(self): return R else: from sage.rings.polynomial.polynomial_ring import is_PolynomialRing - assert(is_PolynomialRing(R)) + assert (is_PolynomialRing(R)) return R.base_ring() def _ge_(self, other): @@ -787,7 +787,7 @@ def _weakly_separating_element(self, other): # phi of the initial approximant must be good enough to separate it # from any other approximant of an extension ret = self._initial_approximation.phi() - assert(self(ret) > other(ret)) # I could not come up with an example where this fails + assert (self(ret) > other(ret)) # I could not come up with an example where this fails return ret else: # if the valuations are sane, it should be possible to separate diff --git a/src/sage/rings/valuation/mapped_valuation.py b/src/sage/rings/valuation/mapped_valuation.py index e2ec88ae306..1aab2ff34b8 100644 --- a/src/sage/rings/valuation/mapped_valuation.py +++ b/src/sage/rings/valuation/mapped_valuation.py @@ -657,7 +657,7 @@ def _repr_(self): from .limit_valuation import MacLaneLimitValuation if isinstance(self._base_valuation, MacLaneLimitValuation): # print the minimal information that singles out this valuation from all approximants - assert(self._base_valuation._initial_approximation in self._approximants) + assert (self._base_valuation._initial_approximation in self._approximants) approximants = [v.augmentation_chain()[::-1] for v in self._approximants] augmentations = self._base_valuation._initial_approximation.augmentation_chain()[::-1] unique_approximant = None @@ -665,7 +665,7 @@ def _repr_(self): if len([a for a in approximants if a[:l + 1] == augmentations[:l + 1]]) == 1: unique_approximant = augmentations[:l + 1] break - assert(unique_approximant is not None) + assert (unique_approximant is not None) if unique_approximant[0].is_gauss_valuation(): unique_approximant[0] = unique_approximant[0].restriction(unique_approximant[0].domain().base_ring()) if len(unique_approximant) == 1: diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index be0e9192c7c..84d67430c82 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -592,7 +592,7 @@ def extension(self, ring): Rational Field """ extensions = self.extensions(ring) - assert(extensions) + assert (extensions) if len(extensions) > 1: raise ValueError("there is no unique extension of %r from %r to %r" % (self, self.domain(), ring)) return extensions[0] @@ -756,7 +756,7 @@ def separating_element(self, others): factor = ret ret = delta while any(other(ret) >= 0 for other in others[:i]): - assert(others[i](ret) < 0) + assert (others[i](ret) < 0) ret *= factor else: # others[i](ret) > 0 # construct an element which approximates a unit with respect to others[i] @@ -801,16 +801,16 @@ def _strictly_separating_element(self, other): numerator = self._weakly_separating_element(other) n = self(numerator) nn = other(numerator) - assert(n > 0) - assert(nn is not infinity) + assert (n > 0) + assert (nn is not infinity) if (nn < 0): return numerator denominator = other._weakly_separating_element(self) d = self(denominator) dd = other(denominator) - assert(dd > 0) - assert(d is not infinity) + assert (dd > 0) + assert (d is not infinity) if d < 0: # The following may fail if denominator is not # invertible in the domain, but we don't have a better @@ -828,7 +828,7 @@ def _strictly_separating_element(self, other): # a/b > d/n and b/a > nn/dd # which is # dd/nn > a/b > d/n - assert(dd/nn > d/n) + assert (dd/nn > d/n) from sage.rings.continued_fraction import continued_fraction ab_cf = [] dn_cf = continued_fraction(d/n) @@ -851,8 +851,8 @@ def _strictly_separating_element(self, other): a,b = ab.numerator(), ab.denominator() ret = self.domain()(numerator**a / denominator**b) - assert(self(ret) > 0) - assert(other(ret) < 0) + assert (self(ret) > 0) + assert (other(ret) < 0) return ret def _weakly_separating_element(self, other): From aee71fedf0424ae8e3b762877330e115490bec04 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 09:38:37 -0700 Subject: [PATCH 150/225] .github/workflows: Remove ci-wsl, ci-cygwin-standard --- .github/workflows/ci-cygwin-standard.yml | 137 ----------------------- .github/workflows/ci-wsl.yml | 54 --------- 2 files changed, 191 deletions(-) delete mode 100644 .github/workflows/ci-cygwin-standard.yml delete mode 100644 .github/workflows/ci-wsl.yml diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml deleted file mode 100644 index 326dd62490e..00000000000 --- a/.github/workflows/ci-cygwin-standard.yml +++ /dev/null @@ -1,137 +0,0 @@ -name: CI cygwin-standard - -on: - push: - tags: - - '*' - workflow_dispatch: - # Allow to run manually - -jobs: - -############################################## stage-i ########################################## - - cygwin-stage-i-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: i-a - # builds openblas - targets: iml gsl - - cygwin-stage-i-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: i-b - targets: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy - -############################################## stage-ii ########################################## - - cygwin-stage-ii-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-a - previous_stages: i-* - targets: cvxopt rpy2 - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-b - previous_stages: i-* - targets: singular maxima gap pari gfan palp arb ecm givaro - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-c: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-c - previous_stages: i-* - targets: cypari eclib fplll linbox giac - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-d: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-d - previous_stages: i-* - targets: ipython ipywidgets notebook - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - - cygwin-stage-ii-e: - uses: ./.github/workflows/cygwin.yml - with: - stage: ii-e - previous_stages: i-* - targets: threejs tachyon pillow jmol m4rie sympy lrcalc lcalc symmetrica cliquer libbraiding planarity rw elliptic_curves combinatorial_designs sympow - needs: [cygwin-stage-i-a, cygwin-stage-i-b] - -############################################## stage-iii ########################################## - - cygwin-stage-iii-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: iii-a - previous_stages: ii-* - targets: sagelib - needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] - - cygwin-stage-iii-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: iii-b - previous_stages: ii-* - targets: networkx - needs: [cygwin-stage-ii-a, cygwin-stage-ii-b, cygwin-stage-ii-c, cygwin-stage-ii-d, cygwin-stage-ii-e] - -############################################## stage-iv ########################################## - - cygwin-stage-iv: - uses: ./.github/workflows/cygwin.yml - with: - stage: iv - previous_stages: iii-* - targets: build - needs: [cygwin-stage-iii-a, cygwin-stage-iii-b] - -############################################## stage-v ########################################### - - cygwin-stage-v-a: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-a - previous_stages: iv - targets: ptest-nodoc - needs: [cygwin-stage-iv] - - cygwin-stage-v-b: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-b - previous_stages: iv - targets: 4ti2 pynormaliz topcom lrslib latte_int cryptominisat - needs: [cygwin-stage-iv] - - cygwin-stage-v-c: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-c - previous_stages: iv - targets: sage_numerical_backends_coin - needs: [cygwin-stage-iv] - - cygwin-stage-v-d: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-d - previous_stages: iv - targets: qepcad barvinok isl qhull primecount plantri kenzo libsemigroups mcqd meataxe mpfrcx openssl p_group_cohomology rst2ipynb sirocco tdlib tides - needs: [cygwin-stage-iv] - - cygwin-stage-v-e: - uses: ./.github/workflows/cygwin.yml - with: - stage: v-e - previous_stages: iv - targets: doc-html - needs: [cygwin-stage-iv] diff --git a/.github/workflows/ci-wsl.yml b/.github/workflows/ci-wsl.yml deleted file mode 100644 index ae83e1d6a0f..00000000000 --- a/.github/workflows/ci-wsl.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build & Test WSL - -on: - push: - tags: - - '*' - branches: - - 'public/build/**wsl**' - workflow_dispatch: - # Allow to run manually - -jobs: - windows: - runs-on: windows-latest - name: Ubuntu 20.04 - # Following https://github.com/sagemath/sage/issues/25206#comment:63 - steps: - - name: Configure git - run: git config --global core.symlinks true - - uses: actions/checkout@v4 - - name: Install Ubuntu 20.04 (in WSL) - run: | - (New-Object System.Net.WebClient).DownloadFile("https://aka.ms/wslubuntu2004", "Ubuntu.appx") - Expand-Archive Ubuntu.appx - Ubuntu\ubuntu2004.exe install --root - - name: Install dependencies - run: | - wsl sudo apt-get update -y - wsl sudo apt-get install -y tox - - name: Build - run: wsl tox -e local-sudo-ubuntu-standard -- SAGE_NUM_THREADS=4 build - env: - # WSL runs everything as root, so we have to enable build as root user - EXTRA_CONFIGURE_ARGS: "--enable-build-as-root" - # If make is invoked in parellel (i.e. with -jN where N > 1), then we sometimes run into errors for some reason - # So keep N small in order to minimize the risk - MAKE: "make -j2" - WSLENV: EXTRA_CONFIGURE_ARGS:MAKE - - name: Test - run: wsl tox -e local-sudo-ubuntu-standard -- SAGE_NUM_THREADS=4 ptest - - name: Prepare logs artifact - run: mkdir -p "artifacts/logs"; cp -r .tox/*/log "artifacts/logs" - shell: bash - if: always() - - uses: actions/upload-artifact@v3 - with: - path: artifacts - name: logs - if: always() - - name: Print out logs for immediate inspection - # and markup the output with GitHub Actions logging commands - run: .github/workflows/scan-logs.sh "artifacts/logs" - shell: bash - if: always() From e63a3f5c111d52a988078b16075be95d956a9e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 28 Sep 2023 20:01:40 +0200 Subject: [PATCH 151/225] a few details in combinat (designs) --- .../designs/group_divisible_designs.py | 86 +++++++++---------- src/sage/combinat/designs/resolvable_bibd.py | 3 + src/sage/combinat/designs/twographs.py | 16 ++-- src/sage/combinat/matrices/dlxcpp.py | 9 +- src/sage/combinat/tuple.py | 5 +- 5 files changed, 63 insertions(+), 56 deletions(-) diff --git a/src/sage/combinat/designs/group_divisible_designs.py b/src/sage/combinat/designs/group_divisible_designs.py index e1d90155920..b589489cfec 100644 --- a/src/sage/combinat/designs/group_divisible_designs.py +++ b/src/sage/combinat/designs/group_divisible_designs.py @@ -24,19 +24,20 @@ --------- """ -#***************************************************************************** +# **************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.arith.misc import is_prime_power -from sage.misc.unknown import Unknown +from sage.misc.unknown import Unknown from .incidence_structures import IncidenceStructure -def group_divisible_design(v,K,G,existence=False,check=False): + +def group_divisible_design(v, K, G, existence=False, check=False): r""" Return a `(v,K,G)`-Group Divisible Design. @@ -90,36 +91,31 @@ def group_divisible_design(v,K,G,existence=False,check=False): blocks = None # from a (v+1,k,1)-BIBD - if (len(G) == 1 and - len(K) == 1 and - G[0]+1 in K): + if len(G) == 1 == len(K) and G[0] + 1 in K: from .bibd import balanced_incomplete_block_design k = K[0] if existence: - return balanced_incomplete_block_design(v+1,k,existence=True) - BIBD = balanced_incomplete_block_design(v+1,k) + return balanced_incomplete_block_design(v + 1, k, existence=True) + BIBD = balanced_incomplete_block_design(v + 1, k) groups = [[x for x in S if x != v] for S in BIBD if v in S] - d = {p:i for i,p in enumerate(sum(groups,[]))} + d = {p: i for i, p in enumerate(sum(groups, []))} d[v] = v BIBD.relabel(d) - groups = [list(range((k-1)*i,(k-1)*(i+1))) for i in range(v//(k-1))] + groups = [list(range((k - 1) * i, (k - 1) * (i + 1))) + for i in range(v // (k - 1))] blocks = [S for S in BIBD if v not in S] # (v,{4},{2})-GDD - elif (v % 2 == 0 and - K == [4] and - G == [2] and - GDD_4_2(v//2,existence=True)): + elif (v % 2 == 0 and K == [4] and + G == [2] and GDD_4_2(v // 2, existence=True)): if existence: return True - return GDD_4_2(v//2,check=check) + return GDD_4_2(v // 2, check=check) # From a TD(k,g) - elif (len(G) == 1 and - len(K) == 1 and - K[0]*G[0] == v): + elif (len(G) == 1 == len(K) and K[0] * G[0] == v): from .orthogonal_arrays import transversal_design - return transversal_design(k=K[0],n=G[0],existence=existence) + return transversal_design(k=K[0], n=G[0], existence=existence) if blocks: return GroupDivisibleDesign(v, @@ -134,7 +130,8 @@ def group_divisible_design(v,K,G,existence=False,check=False): return Unknown raise NotImplementedError -def GDD_4_2(q,existence=False,check=True): + +def GDD_4_2(q, existence=False, check=True): r""" Return a `(2q,\{4\},\{2\})`-GDD for `q` a prime power with `q\equiv 1\pmod{6}`. @@ -180,26 +177,27 @@ def GDD_4_2(q,existence=False,check=True): return True from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF - G = GF(q,'x') + G = GF(q, 'x') w = G.primitive_element() e = w**((q - 1) // 3) # A first parallel class is defined. G acts on it, which yields all others. - first_class = [[(0,0),(1,w**i),(1,e*w**i),(1,e*e*w**i)] + first_class = [[(0, 0), (1, w**i), (1, e * w**i), (1, e * e * w**i)] for i in range((q - 1) // 6)] - label = {p:i for i,p in enumerate(G)} - classes = [[[2*label[x[1]+g]+(x[0]+j) % 2 for x in S] + label = {p: i for i, p in enumerate(G)} + classes = [[[2 * label[x[1] + g] + (x[0] + j) % 2 for x in S] for S in first_class] for g in G for j in range(2)] - return GroupDivisibleDesign(2*q, - groups=[[i,i+1] for i in range(0,2*q,2)], - blocks=sum(classes,[]), - K=[4], - G=[2], - check=check, - copy=False) + return GroupDivisibleDesign(2 * q, + groups=[[i, i + 1] for i in range(0, 2 * q, 2)], + blocks=sum(classes, []), + K=[4], + G=[2], + check=check, + copy=False) + class GroupDivisibleDesign(IncidenceStructure): r""" @@ -261,9 +259,9 @@ class GroupDivisibleDesign(IncidenceStructure): sage: GDD = GroupDivisibleDesign('abcdefghiklm',None,D) sage: sorted(GDD.groups()) [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['k', 'l', 'm']] - """ - def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, copy=True,**kwds): + def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, + check=True, copy=True, **kwds): r""" Constructor function @@ -286,8 +284,7 @@ def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, check=False, **kwds) - if (groups is None or - (copy is False and self._point_to_index is None)): + if (groups is None or (copy is False and self._point_to_index is None)): self._groups = groups elif self._point_to_index is None: self._groups = [g[:] for g in groups] @@ -295,7 +292,9 @@ def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=True, self._groups = [[self._point_to_index[x] for x in g] for g in groups] if check or groups is None: - is_gdd = is_group_divisible_design(self._groups,self._blocks,self.num_points(),G,K,lambd,verbose=1) + is_gdd = is_group_divisible_design(self._groups, self._blocks, + self.num_points(), G, K, + lambd, verbose=1) assert is_gdd if groups is None: self._groups = is_gdd[1] @@ -337,7 +336,7 @@ def groups(self): def __repr__(self): r""" - Returns a string that describes self + Return a string that describes ``self``. EXAMPLES:: @@ -347,11 +346,10 @@ def __repr__(self): sage: GDD = GroupDivisibleDesign(40,groups,TD); GDD Group Divisible Design on 40 points of type 10^4 """ + group_sizes = [len(g) for g in self._groups] - group_sizes = [len(_) for _ in self._groups] - - gdd_type = ["{}^{}".format(s,group_sizes.count(s)) - for s in sorted(set(group_sizes))] + gdd_type = ("{}^{}".format(s, group_sizes.count(s)) + for s in sorted(set(group_sizes))) gdd_type = ".".join(gdd_type) if not gdd_type: @@ -359,4 +357,4 @@ def __repr__(self): v = self.num_points() - return "Group Divisible Design on {} points of type {}".format(v,gdd_type) + return "Group Divisible Design on {} points of type {}".format(v, gdd_type) diff --git a/src/sage/combinat/designs/resolvable_bibd.py b/src/sage/combinat/designs/resolvable_bibd.py index 4af0bed4bb6..12ca7b11c30 100644 --- a/src/sage/combinat/designs/resolvable_bibd.py +++ b/src/sage/combinat/designs/resolvable_bibd.py @@ -140,6 +140,7 @@ def resolvable_balanced_incomplete_block_design(v,k,existence=False): return Unknown raise NotImplementedError("I don't know how to build a ({},{},1)-RBIBD!".format(v,3)) + def kirkman_triple_system(v,existence=False): r""" Return a Kirkman Triple System on `v` points. @@ -437,6 +438,7 @@ def v_4_1_rbibd(v,existence=False): assert BIBD.is_resolvable() return BIBD + def PBD_4_7(v,check=True, existence=False): r""" Return a `(v,\{4,7\})`-PBD @@ -683,6 +685,7 @@ def PBD_4_7(v,check=True, existence=False): check=check, copy=False) + def PBD_4_7_from_Y(gdd,check=True): r""" Return a `(3v+1,\{4,7\})`-PBD from a `(v,\{4,5,7\},\NN-\{3,6,10\})`-GDD. diff --git a/src/sage/combinat/designs/twographs.py b/src/sage/combinat/designs/twographs.py index 5c9a90afbcd..54d684cb9d2 100644 --- a/src/sage/combinat/designs/twographs.py +++ b/src/sage/combinat/designs/twographs.py @@ -59,6 +59,7 @@ from sage.combinat.designs.incidence_structures import IncidenceStructure from itertools import combinations + class TwoGraph(IncidenceStructure): r""" Two-graphs class. @@ -199,9 +200,10 @@ def taylor_twograph(q): from sage.graphs.generators.classical_geometries import TaylorTwographSRG return TaylorTwographSRG(q).twograph() -def is_twograph(T): + +def is_twograph(T) -> bool: r""" - Checks that the incidence system `T` is a two-graph + Check whether the incidence system `T` is a two-graph. INPUT: @@ -237,7 +239,7 @@ def is_twograph(T): return False # A structure for a fast triple existence check - v_to_blocks = {v:set() for v in range(T.num_points())} + v_to_blocks = {v: set() for v in range(T.num_points())} for B in T._blocks: B = frozenset(B) for x in B: @@ -248,8 +250,8 @@ def has_triple(x_y_z): return bool(v_to_blocks[x] & v_to_blocks[y] & v_to_blocks[z]) # Check that every quadruple contains an even number of triples - for quad in combinations(range(T.num_points()),4): - if sum(map(has_triple,combinations(quad,3))) % 2 == 1: + for quad in combinations(range(T.num_points()), 4): + if sum(map(has_triple, combinations(quad, 3))) % 2 == 1: return False return True @@ -296,10 +298,10 @@ def twograph_descendant(G, v, name=None): sage: twograph_descendant(p, 5, name=True) descendant of Petersen graph at 5: Graph on 9 vertices """ - G = G.seidel_switching(G.neighbors(v),inplace=False) + G = G.seidel_switching(G.neighbors(v), inplace=False) G.delete_vertex(v) if name: - G.name('descendant of '+G.name()+' at '+str(v)) + G.name('descendant of ' + G.name() + ' at ' + str(v)) else: G.name('') return G diff --git a/src/sage/combinat/matrices/dlxcpp.py b/src/sage/combinat/matrices/dlxcpp.py index e235f885188..fce16e7d2ad 100644 --- a/src/sage/combinat/matrices/dlxcpp.py +++ b/src/sage/combinat/matrices/dlxcpp.py @@ -1,7 +1,7 @@ """ Dancing links C++ wrapper """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2008 Carlo Hamalainen , # # Distributed under the terms of the GNU General Public License (GPL) @@ -13,14 +13,15 @@ # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** # OneExactCover and AllExactCovers are almost exact copies of the # functions with the same name in sage/combinat/dlx.py by Tom Boothby. from .dancing_links import dlx_solver + def DLXCPP(rows): """ Solves the Exact Cover problem by using the Dancing Links algorithm @@ -85,6 +86,7 @@ def DLXCPP(rows): while x.search(): yield x.get_solution() + def AllExactCovers(M): """ Solves the exact cover problem on the matrix M (treated as a dense @@ -112,6 +114,7 @@ def AllExactCovers(M): for s in DLXCPP(rows): yield [M.row(i) for i in s] + def OneExactCover(M): """ Solves the exact cover problem on the matrix M (treated as a dense diff --git a/src/sage/combinat/tuple.py b/src/sage/combinat/tuple.py index 95ae68b040c..8336fb4cbb6 100644 --- a/src/sage/combinat/tuple.py +++ b/src/sage/combinat/tuple.py @@ -15,13 +15,14 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from itertools import product, combinations_with_replacement from sage.arith.misc import binomial +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.rings.integer_ring import ZZ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from itertools import product, combinations_with_replacement + class Tuples(Parent, UniqueRepresentation): """ From a80b5c0ad9ae1ab273a8db7ed6a26fb9727fdfed Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 26 Dec 2021 15:05:39 -0800 Subject: [PATCH 152/225] tox.ini, build/bin/write-dockerfile.sh, build/bin/sage-print-system-package-command: Add alpine --- build/bin/sage-print-system-package-command | 6 ++++++ build/bin/write-dockerfile.sh | 7 +++++-- build/pkgs/_bootstrap/distros/alpine.txt | 6 ++++++ build/pkgs/_prereq/distros/alpine.txt | 10 ++++++++++ build/pkgs/patch/distros/alpine.txt | 1 + tox.ini | 7 +++++++ 6 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 build/pkgs/_bootstrap/distros/alpine.txt create mode 100644 build/pkgs/_prereq/distros/alpine.txt create mode 100644 build/pkgs/patch/distros/alpine.txt diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command index b493ebd0ffb..c36f64e19bf 100755 --- a/build/bin/sage-print-system-package-command +++ b/build/bin/sage-print-system-package-command @@ -162,6 +162,12 @@ case $system:$command in nix*:install) [ -n "$system_packages" ] && print_shell_command "nix-env --install $system_packages" ;; + alpine:update) + print_shell_command "apk update" + ;; + alpine:install) + [ -n "$system_packages" ] && print_shell_command "apk add $system_packages" + ;; pip:install) [ -n "$system_packages" ] && print_shell_command "sage -pip install $system_packages" ;; diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 6980f6b6e4b..2a3b368ff05 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -158,8 +158,11 @@ EOF RUN="RUN . /opt/conda/etc/profile.d/conda.sh; conda activate base; " # to activate the conda env ;; *) - echo "Not implemented: package installation for SYSTEM=$SYSTEM" >&2 - exit 1 + cat < Date: Sun, 26 Dec 2021 15:47:43 -0800 Subject: [PATCH 153/225] Add more alpine.txt --- build/pkgs/bzip2/distros/alpine.txt | 1 + build/pkgs/curl/distros/alpine.txt | 1 + build/pkgs/flint/distros/alpine.txt | 1 + build/pkgs/freetype/distros/alpine.txt | 1 + build/pkgs/gc/distros/alpine.txt | 1 + build/pkgs/gdb/distros/alpine.txt | 1 + build/pkgs/gengetopt/distros/alpine.txt | 1 + build/pkgs/gf2x/distros/alpine.txt | 1 + build/pkgs/gfortran/distros/alpine.txt | 1 + build/pkgs/glpk/distros/alpine.txt | 1 + build/pkgs/gmp/distros/alpine.txt | 1 + build/pkgs/gsl/distros/alpine.txt | 1 + build/pkgs/libatomic_ops/distros/alpine.txt | 1 + build/pkgs/libffi/distros/alpine.txt | 1 + build/pkgs/libgd/distros/alpine.txt | 2 +- build/pkgs/liblzma/distros/alpine.txt | 1 + build/pkgs/libpng/distros/alpine.txt | 1 + build/pkgs/ncurses/distros/alpine.txt | 1 + build/pkgs/openblas/distros/alpine.txt | 1 + build/pkgs/pari/distros/alpine.txt | 1 + build/pkgs/pcre/distros/alpine.txt | 1 + build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt | 6 ++++++ build/pkgs/perl_term_readline_gnu/distros/alpine.txt | 1 + build/pkgs/qhull/distros/alpine.txt | 1 + build/pkgs/r/distros/alpine.txt | 1 + build/pkgs/sqlite/distros/alpine.txt | 1 + build/pkgs/suitesparse/distros/alpine.txt | 1 + build/pkgs/valgrind/distros/alpine.txt | 1 + build/pkgs/xz/distros/alpine.txt | 1 + build/pkgs/zeromq/distros/alpine.txt | 1 + build/pkgs/zlib/distros/alpine.txt | 1 + 31 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/bzip2/distros/alpine.txt create mode 100644 build/pkgs/curl/distros/alpine.txt create mode 100644 build/pkgs/flint/distros/alpine.txt create mode 100644 build/pkgs/freetype/distros/alpine.txt create mode 100644 build/pkgs/gc/distros/alpine.txt create mode 100644 build/pkgs/gdb/distros/alpine.txt create mode 100644 build/pkgs/gengetopt/distros/alpine.txt create mode 100644 build/pkgs/gf2x/distros/alpine.txt create mode 100644 build/pkgs/gfortran/distros/alpine.txt create mode 100644 build/pkgs/glpk/distros/alpine.txt create mode 100644 build/pkgs/gmp/distros/alpine.txt create mode 100644 build/pkgs/gsl/distros/alpine.txt create mode 100644 build/pkgs/libatomic_ops/distros/alpine.txt create mode 100644 build/pkgs/libffi/distros/alpine.txt create mode 100644 build/pkgs/liblzma/distros/alpine.txt create mode 100644 build/pkgs/libpng/distros/alpine.txt create mode 100644 build/pkgs/ncurses/distros/alpine.txt create mode 100644 build/pkgs/openblas/distros/alpine.txt create mode 100644 build/pkgs/pari/distros/alpine.txt create mode 100644 build/pkgs/pcre/distros/alpine.txt create mode 100644 build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt create mode 100644 build/pkgs/perl_term_readline_gnu/distros/alpine.txt create mode 100644 build/pkgs/qhull/distros/alpine.txt create mode 100644 build/pkgs/r/distros/alpine.txt create mode 100644 build/pkgs/sqlite/distros/alpine.txt create mode 100644 build/pkgs/suitesparse/distros/alpine.txt create mode 100644 build/pkgs/valgrind/distros/alpine.txt create mode 100644 build/pkgs/xz/distros/alpine.txt create mode 100644 build/pkgs/zeromq/distros/alpine.txt create mode 100644 build/pkgs/zlib/distros/alpine.txt diff --git a/build/pkgs/bzip2/distros/alpine.txt b/build/pkgs/bzip2/distros/alpine.txt new file mode 100644 index 00000000000..7a457127148 --- /dev/null +++ b/build/pkgs/bzip2/distros/alpine.txt @@ -0,0 +1 @@ +bzip2 diff --git a/build/pkgs/curl/distros/alpine.txt b/build/pkgs/curl/distros/alpine.txt new file mode 100644 index 00000000000..13368f82902 --- /dev/null +++ b/build/pkgs/curl/distros/alpine.txt @@ -0,0 +1 @@ +curl diff --git a/build/pkgs/flint/distros/alpine.txt b/build/pkgs/flint/distros/alpine.txt new file mode 100644 index 00000000000..8d3c2b0865b --- /dev/null +++ b/build/pkgs/flint/distros/alpine.txt @@ -0,0 +1 @@ +flint-dev diff --git a/build/pkgs/freetype/distros/alpine.txt b/build/pkgs/freetype/distros/alpine.txt new file mode 100644 index 00000000000..25c2024f453 --- /dev/null +++ b/build/pkgs/freetype/distros/alpine.txt @@ -0,0 +1 @@ +freetype-dev diff --git a/build/pkgs/gc/distros/alpine.txt b/build/pkgs/gc/distros/alpine.txt new file mode 100644 index 00000000000..f6666d60505 --- /dev/null +++ b/build/pkgs/gc/distros/alpine.txt @@ -0,0 +1 @@ +gc-dev diff --git a/build/pkgs/gdb/distros/alpine.txt b/build/pkgs/gdb/distros/alpine.txt new file mode 100644 index 00000000000..59ccb367d89 --- /dev/null +++ b/build/pkgs/gdb/distros/alpine.txt @@ -0,0 +1 @@ +gdb diff --git a/build/pkgs/gengetopt/distros/alpine.txt b/build/pkgs/gengetopt/distros/alpine.txt new file mode 100644 index 00000000000..2865264cd70 --- /dev/null +++ b/build/pkgs/gengetopt/distros/alpine.txt @@ -0,0 +1 @@ +gengetopt diff --git a/build/pkgs/gf2x/distros/alpine.txt b/build/pkgs/gf2x/distros/alpine.txt new file mode 100644 index 00000000000..9e56153852f --- /dev/null +++ b/build/pkgs/gf2x/distros/alpine.txt @@ -0,0 +1 @@ +gf2x-dev diff --git a/build/pkgs/gfortran/distros/alpine.txt b/build/pkgs/gfortran/distros/alpine.txt new file mode 100644 index 00000000000..48e76bee68c --- /dev/null +++ b/build/pkgs/gfortran/distros/alpine.txt @@ -0,0 +1 @@ +gfortran diff --git a/build/pkgs/glpk/distros/alpine.txt b/build/pkgs/glpk/distros/alpine.txt new file mode 100644 index 00000000000..9cbe780a80e --- /dev/null +++ b/build/pkgs/glpk/distros/alpine.txt @@ -0,0 +1 @@ +glpk-dev diff --git a/build/pkgs/gmp/distros/alpine.txt b/build/pkgs/gmp/distros/alpine.txt new file mode 100644 index 00000000000..ec016288fc1 --- /dev/null +++ b/build/pkgs/gmp/distros/alpine.txt @@ -0,0 +1 @@ +gmp-dev diff --git a/build/pkgs/gsl/distros/alpine.txt b/build/pkgs/gsl/distros/alpine.txt new file mode 100644 index 00000000000..6b84f9c4763 --- /dev/null +++ b/build/pkgs/gsl/distros/alpine.txt @@ -0,0 +1 @@ +gsl-dev diff --git a/build/pkgs/libatomic_ops/distros/alpine.txt b/build/pkgs/libatomic_ops/distros/alpine.txt new file mode 100644 index 00000000000..b06d2d1dd97 --- /dev/null +++ b/build/pkgs/libatomic_ops/distros/alpine.txt @@ -0,0 +1 @@ +libatomic_ops-dev diff --git a/build/pkgs/libffi/distros/alpine.txt b/build/pkgs/libffi/distros/alpine.txt new file mode 100644 index 00000000000..f3ea12da9f0 --- /dev/null +++ b/build/pkgs/libffi/distros/alpine.txt @@ -0,0 +1 @@ +libffi-dev diff --git a/build/pkgs/libgd/distros/alpine.txt b/build/pkgs/libgd/distros/alpine.txt index 3f310cfdeb0..5d6f6016ad5 100644 --- a/build/pkgs/libgd/distros/alpine.txt +++ b/build/pkgs/libgd/distros/alpine.txt @@ -1 +1 @@ -gd +gd-dev diff --git a/build/pkgs/liblzma/distros/alpine.txt b/build/pkgs/liblzma/distros/alpine.txt new file mode 100644 index 00000000000..da4a99a970e --- /dev/null +++ b/build/pkgs/liblzma/distros/alpine.txt @@ -0,0 +1 @@ +xz-dev diff --git a/build/pkgs/libpng/distros/alpine.txt b/build/pkgs/libpng/distros/alpine.txt new file mode 100644 index 00000000000..9d134f4db00 --- /dev/null +++ b/build/pkgs/libpng/distros/alpine.txt @@ -0,0 +1 @@ +libpng-dev diff --git a/build/pkgs/ncurses/distros/alpine.txt b/build/pkgs/ncurses/distros/alpine.txt new file mode 100644 index 00000000000..5b70894d7c9 --- /dev/null +++ b/build/pkgs/ncurses/distros/alpine.txt @@ -0,0 +1 @@ +ncurses-dev diff --git a/build/pkgs/openblas/distros/alpine.txt b/build/pkgs/openblas/distros/alpine.txt new file mode 100644 index 00000000000..363072a2f2f --- /dev/null +++ b/build/pkgs/openblas/distros/alpine.txt @@ -0,0 +1 @@ +openblas-dev diff --git a/build/pkgs/pari/distros/alpine.txt b/build/pkgs/pari/distros/alpine.txt new file mode 100644 index 00000000000..964927dedb0 --- /dev/null +++ b/build/pkgs/pari/distros/alpine.txt @@ -0,0 +1 @@ +pari-dev diff --git a/build/pkgs/pcre/distros/alpine.txt b/build/pkgs/pcre/distros/alpine.txt new file mode 100644 index 00000000000..a16e4119734 --- /dev/null +++ b/build/pkgs/pcre/distros/alpine.txt @@ -0,0 +1 @@ +pcre-dev diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt new file mode 100644 index 00000000000..c100879ddcd --- /dev/null +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/alpine.txt @@ -0,0 +1,6 @@ +perl-term-readkey +perl-dev +perl-file-slurp +perl-json +perl-xml-writer +perl-xml-libxslt diff --git a/build/pkgs/perl_term_readline_gnu/distros/alpine.txt b/build/pkgs/perl_term_readline_gnu/distros/alpine.txt new file mode 100644 index 00000000000..2ce91c8024b --- /dev/null +++ b/build/pkgs/perl_term_readline_gnu/distros/alpine.txt @@ -0,0 +1 @@ +perl-term-readline-gnu diff --git a/build/pkgs/qhull/distros/alpine.txt b/build/pkgs/qhull/distros/alpine.txt new file mode 100644 index 00000000000..f2adb17f761 --- /dev/null +++ b/build/pkgs/qhull/distros/alpine.txt @@ -0,0 +1 @@ +qhull-dev diff --git a/build/pkgs/r/distros/alpine.txt b/build/pkgs/r/distros/alpine.txt new file mode 100644 index 00000000000..97b6cfc9422 --- /dev/null +++ b/build/pkgs/r/distros/alpine.txt @@ -0,0 +1 @@ +R-dev diff --git a/build/pkgs/sqlite/distros/alpine.txt b/build/pkgs/sqlite/distros/alpine.txt new file mode 100644 index 00000000000..1598840794c --- /dev/null +++ b/build/pkgs/sqlite/distros/alpine.txt @@ -0,0 +1 @@ +sqlite-dev diff --git a/build/pkgs/suitesparse/distros/alpine.txt b/build/pkgs/suitesparse/distros/alpine.txt new file mode 100644 index 00000000000..2013d8ad35d --- /dev/null +++ b/build/pkgs/suitesparse/distros/alpine.txt @@ -0,0 +1 @@ +suitesparse-dev diff --git a/build/pkgs/valgrind/distros/alpine.txt b/build/pkgs/valgrind/distros/alpine.txt new file mode 100644 index 00000000000..e7af4129194 --- /dev/null +++ b/build/pkgs/valgrind/distros/alpine.txt @@ -0,0 +1 @@ +valgrind diff --git a/build/pkgs/xz/distros/alpine.txt b/build/pkgs/xz/distros/alpine.txt new file mode 100644 index 00000000000..d66e95ca507 --- /dev/null +++ b/build/pkgs/xz/distros/alpine.txt @@ -0,0 +1 @@ +xz diff --git a/build/pkgs/zeromq/distros/alpine.txt b/build/pkgs/zeromq/distros/alpine.txt new file mode 100644 index 00000000000..c5f85376b35 --- /dev/null +++ b/build/pkgs/zeromq/distros/alpine.txt @@ -0,0 +1 @@ +zeromq-dev diff --git a/build/pkgs/zlib/distros/alpine.txt b/build/pkgs/zlib/distros/alpine.txt new file mode 100644 index 00000000000..ec3c9ffcf26 --- /dev/null +++ b/build/pkgs/zlib/distros/alpine.txt @@ -0,0 +1 @@ +zlib-dev From 0bab09ca9fa029fc6284ab37d9ec8e84f95ddff3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 26 Dec 2021 16:23:43 -0800 Subject: [PATCH 154/225] build/pkgs/_prereq/distros/alpine.txt: Add coreutils --- build/pkgs/_prereq/distros/alpine.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/build/pkgs/_prereq/distros/alpine.txt b/build/pkgs/_prereq/distros/alpine.txt index af9a2d6511c..159c452cf30 100644 --- a/build/pkgs/_prereq/distros/alpine.txt +++ b/build/pkgs/_prereq/distros/alpine.txt @@ -8,3 +8,4 @@ bc gcc g++ ca-certificates +coreutils From 651c91e55c706d26a72710ff7e733b7355506d38 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 26 Dec 2021 16:31:17 -0800 Subject: [PATCH 155/225] build/pkgs/{graphviz,qhull,r}/distros/alpine.txt: Add non-dev packages --- build/pkgs/graphviz/distros/alpine.txt | 2 +- build/pkgs/qhull/distros/alpine.txt | 1 + build/pkgs/r/distros/alpine.txt | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build/pkgs/graphviz/distros/alpine.txt b/build/pkgs/graphviz/distros/alpine.txt index 52aa6f38376..4d95609306f 100644 --- a/build/pkgs/graphviz/distros/alpine.txt +++ b/build/pkgs/graphviz/distros/alpine.txt @@ -1 +1 @@ -graphviz-dev +graphviz diff --git a/build/pkgs/qhull/distros/alpine.txt b/build/pkgs/qhull/distros/alpine.txt index f2adb17f761..149747bebb0 100644 --- a/build/pkgs/qhull/distros/alpine.txt +++ b/build/pkgs/qhull/distros/alpine.txt @@ -1 +1,2 @@ qhull-dev +qhull diff --git a/build/pkgs/r/distros/alpine.txt b/build/pkgs/r/distros/alpine.txt index 97b6cfc9422..8bb0d38745d 100644 --- a/build/pkgs/r/distros/alpine.txt +++ b/build/pkgs/r/distros/alpine.txt @@ -1 +1,2 @@ R-dev +R From 1e01f4576ee9f67c89a4d7ac59d9a1bf93f633b3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 27 Dec 2021 11:41:36 -0800 Subject: [PATCH 156/225] build/pkgs/mpfr/distros/alpine.txt: New --- build/pkgs/mpfr/distros/alpine.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 build/pkgs/mpfr/distros/alpine.txt diff --git a/build/pkgs/mpfr/distros/alpine.txt b/build/pkgs/mpfr/distros/alpine.txt new file mode 100644 index 00000000000..002d7509052 --- /dev/null +++ b/build/pkgs/mpfr/distros/alpine.txt @@ -0,0 +1 @@ +mpfr-dev From 4df0d1a0c8486f56dd0363fa04f8dc928ee578ce Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 28 Sep 2023 12:03:11 -0700 Subject: [PATCH 157/225] A few more changes suggested by reviewer --- src/sage/homology/homology_vector_space_with_basis.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 542f2d5873b..ace9775d56b 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -1008,7 +1008,6 @@ class CohomologyRing_mod2(CohomologyRing): sage: x * Sq(3) h^{4,0} """ - def __init__(self, base_ring, cell_complex): """ Initialize ``self``. @@ -1217,7 +1216,7 @@ def _acted_upon_(self, a, self_on_left): INPUT: - - ``a`` - an element of the mod 2 Steenrod algebra + - ``a`` -- an element of the mod 2 Steenrod algebra - ``self_on_left`` -- ``True`` if we are computing ``self * a``, otherwise ``a * self`` @@ -1284,7 +1283,7 @@ def steenrod_module_map(self, deg_domain, deg_codomain, side='left'): - ``deg_codomain`` -- the degree of the codomain in the cohomology ring - - ``side`` default ``'left'``) -- whether we are computing + - ``side`` -- (default ``'left'``) whether we are computing the action as a left module action or a right module We will write this with respect to the left action; @@ -1440,8 +1439,8 @@ def sum_indices(k, i_k_plus_one, S_k_plus_one): for l in sum_indices(k-1, i_k, S_k)] def is_GF2(R): - """ - Return ``True`` iff ``R`` is isomorphic to the field GF(2). + r""" + Return ``True`` iff ``R`` is isomorphic to the field `\GF{2}`. EXAMPLES:: From 1d8c4a205e63504e39e69590b75ca35c915c1b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 15:27:40 +0200 Subject: [PATCH 158/225] a few less parentheses in combinat and rings --- src/sage/combinat/alternating_sign_matrix.py | 6 ++--- .../combinat/binary_recurrence_sequences.py | 2 +- src/sage/combinat/binary_tree.py | 4 ++-- .../cluster_algebra_quiver/cluster_seed.py | 11 ++++------ .../cluster_algebra_quiver/mutation_type.py | 22 +++++++++---------- src/sage/combinat/crystals/direct_sum.py | 7 +++--- src/sage/combinat/derangements.py | 6 ++--- src/sage/combinat/e_one_star.py | 4 ++-- src/sage/combinat/finite_state_machine.py | 4 ++-- src/sage/combinat/integer_lists/base.pyx | 4 ++-- .../combinat/integer_vectors_mod_permgroup.py | 4 ++-- src/sage/combinat/interval_posets.py | 2 +- src/sage/combinat/ncsf_qsym/ncsf.py | 4 ++-- src/sage/combinat/ncsf_qsym/qsym.py | 4 ++-- src/sage/combinat/ncsym/dual.py | 6 ++--- src/sage/combinat/ncsym/ncsym.py | 6 ++--- src/sage/combinat/permutation.py | 4 ++-- src/sage/combinat/posets/cartesian_product.py | 6 ++--- src/sage/combinat/root_system/root_space.py | 7 +++--- .../weight_lattice_realizations.py | 6 ++--- src/sage/combinat/sf/schur.py | 2 +- src/sage/combinat/sf/sf.py | 4 ++-- src/sage/combinat/sf/sfa.py | 6 ++--- src/sage/combinat/shuffle.py | 15 ++++++------- src/sage/combinat/subword.py | 8 +++---- src/sage/combinat/superpartition.py | 8 +++---- src/sage/combinat/tableau.py | 6 ++--- src/sage/combinat/tamari_lattices.py | 2 +- src/sage/combinat/words/abstract_word.py | 2 +- src/sage/combinat/words/finite_word.py | 16 +++++++------- src/sage/combinat/words/morphism.py | 4 ++-- src/sage/combinat/words/suffix_trees.py | 2 +- .../combinat/words/word_infinite_datatypes.py | 10 ++++----- src/sage/rings/continued_fraction.py | 2 +- src/sage/rings/fast_arith.pyx | 18 ++++++++------- .../padics/unramified_extension_generic.py | 6 ++--- .../polynomial/infinite_polynomial_element.py | 2 +- src/sage/rings/polynomial/plural.pyx | 6 ++--- .../polynomial/polynomial_element_generic.py | 4 ++-- src/sage/rings/polynomial/symmetric_ideal.py | 8 +++---- .../rings/polynomial/symmetric_reduction.pyx | 4 ++-- src/sage/rings/real_mpfr.pyx | 2 +- src/sage/rings/valuation/valuation_space.py | 20 ++++++++--------- 43 files changed, 136 insertions(+), 140 deletions(-) diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index dcdd0ffb614..c17f371ba48 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -1821,9 +1821,8 @@ def __classcall_private__(cls, n, **kwds): sage: C = ContreTableaux(4) sage: type(C) - """ - assert (isinstance(n, (int, Integer))) + assert isinstance(n, (int, Integer)) return ContreTableaux_n(n, **kwds) @@ -1983,9 +1982,8 @@ def __classcall_private__(cls, n, last_column, **kwds): sage: T = TruncatedStaircases(4, [2,3]) sage: type(T) - """ - assert (isinstance(n, (int, Integer))) + assert isinstance(n, (int, Integer)) return TruncatedStaircases_nlastcolumn(n, last_column, **kwds) diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index 9527c512360..ee3f82dde57 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -705,7 +705,7 @@ def pthpowers(self, p, Bound): #CRT by hand to gain speed for i in list(cong): - if not (i % modu in cong1): #congruence in cong is inconsistent with any in cong1 + if i % modu not in cong1: #congruence in cong is inconsistent with any in cong1 cong.remove(i) #remove that congruence killed_something = True diff --git a/src/sage/combinat/binary_tree.py b/src/sage/combinat/binary_tree.py index 2840165685d..7d304ed1499 100644 --- a/src/sage/combinat/binary_tree.py +++ b/src/sage/combinat/binary_tree.py @@ -914,7 +914,7 @@ def make_node(self, child_list=[None, None]): """ self._require_mutable() child_lst = [self.__class__(self.parent(), x) for x in child_list] - if not (len(child_lst) == 2): + if len(child_lst) != 2: raise ValueError("the list must have length 2") self.__init__(self.parent(), child_lst, check=False) @@ -1873,7 +1873,7 @@ def left_border_symmetry(self): labelled = self in LabelledBinaryTrees() labels = [] t = self - while (t): + while t: border.append(t[1].left_border_symmetry()) if labelled: labels.append(t.label()) diff --git a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py index ff40af714c2..514acb43636 100644 --- a/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py +++ b/src/sage/combinat/cluster_algebra_quiver/cluster_seed.py @@ -1555,7 +1555,6 @@ def g_vector(self, k): sage: [S.g_vector(k) for k in range(3)] [(1, 0, 0), (0, 0, -1), (0, -1, 0)] """ - if not (self._is_principal or self._use_g_vec or (self._use_fpolys and self._cluster)): raise ValueError("Unable to calculate g-vectors. Need to use g vectors.") if k not in range(self._n): @@ -1823,8 +1822,6 @@ def d_matrix(self, show_warnings=True): [1 1 1 1] [1 0 1 1] [0 0 0 1] - - """ if not (self._use_d_vec or self._use_fpolys or self._track_mut): # raise ValueError("No d-vectors initialized.") @@ -4345,7 +4342,7 @@ def oriented_exchange_graph(self): j = i.mutate(k, inplace=False) Varj = tuple(sorted(j.cluster())) covers.append((Vari, Varj)) - if not (Varj in known_clusters): + if Varj not in known_clusters: known_clusters += [Varj] stack.append(j) @@ -4456,7 +4453,7 @@ def find_upper_bound(self, verbose=False): new_gen_found = False i = 0 M_gens = M.gens() - while (not new_gen_found) and i < len(M_gens): + while not new_gen_found and i < len(M_gens): f = initial_product_ideal.reduce(M_gens[i]) if f != 0: rels.append('z' + str(len(gens) - 2 * rank - 1) + '*' + initial_product + '-(' + str(f) + ')') @@ -4466,7 +4463,7 @@ def find_upper_bound(self, verbose=False): print('') i += 1 - def get_upper_cluster_algebra_element(self,a): + def get_upper_cluster_algebra_element(self, a): r""" Compute an element in the upper cluster algebra of `B` corresponding to the vector `a \in \ZZ^n`. @@ -4556,7 +4553,7 @@ def LLM_gen_set(self, size_limit=-1): break a = aSet[i] genSet.append(self.get_upper_cluster_algebra_element(a)) - return (genSet) + return genSet def _compute_compatible_vectors(self, vd): r""" diff --git a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py index 3ff53f5dd31..524c95a80df 100644 --- a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py @@ -892,9 +892,9 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): # Exception 1 case (4-cycle): edges = sg.edges(sort=True, labels=False) - if not (c1[0],c1[1]) in edges and not (c1[1],c1[0]) in edges and sg.is_isomorphic( exception_graph1 ): - dg_tmp = DiGraph( dg ) - dg_tmp.delete_vertices( c1 ) + if (c1[0], c1[1]) not in edges and (c1[1], c1[0]) not in edges and sg.is_isomorphic(exception_graph1): + dg_tmp = DiGraph(dg) + dg_tmp.delete_vertices(c1) components = dg_tmp.connected_components(sort=False) # if not len(components) == 2: @@ -1081,13 +1081,13 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): if len( in_neighbors ) == 1: in_neighbors.extend(in_neighbors) - if not (in_neighbors[0],v) in oriented_trian_edges: + if (in_neighbors[0], v) not in oriented_trian_edges: return _false_return(24) - elif not (in_neighbors[1],v) in oriented_trian_edges: + elif (in_neighbors[1], v) not in oriented_trian_edges: return _false_return(25) - elif not (v,out_neighbors[0]) in oriented_trian_edges: + elif (v, out_neighbors[0]) not in oriented_trian_edges: return _false_return(26) - elif not (v,out_neighbors[1]) in oriented_trian_edges: + elif (v, out_neighbors[1]) not in oriented_trian_edges: return _false_return(27) # if a vertex has valency 3 than 2 of its neighboring edges must be contained in an oriented triangle and the remaining must not @@ -1106,14 +1106,14 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): return _false_return(30) if not long_cycle[1] == QuiverMutationType(['D',n]): return _false_return(31) - if not (v,out_neighbors[0]) in long_cycle[0] and not (v,out_neighbors[1]) in long_cycle[0]: + if (v, out_neighbors[0]) not in long_cycle[0] and (v, out_neighbors[1]) not in long_cycle[0]: return _false_return(32) if (v,out_neighbors[0]) not in oriented_trian_edges and (v,out_neighbors[1]) not in oriented_trian_edges: return _false_return(33) elif w[0] == 2: in_neighbors = dg.neighbors_in( v ) out_neighbors = dg.neighbors_out( v ) - if not (v,out_neighbors[0]) in oriented_trian_edges: + if (v, out_neighbors[0]) not in oriented_trian_edges: return _false_return(34) elif len( in_neighbors ) == 1: if (in_neighbors[0],v) not in oriented_trian_edges: @@ -1124,9 +1124,9 @@ def _connected_mutation_type_AAtildeD(dg, ret_conn_vert=False): return _false_return(36) if not long_cycle[1] == QuiverMutationType(['D',n]): return _false_return(37) - if not (in_neighbors[0],v) in long_cycle[0] and not (in_neighbors[1],v) in long_cycle[0]: + if (in_neighbors[0], v) not in long_cycle[0] and (in_neighbors[1], v) not in long_cycle[0]: return _false_return(38) - if (in_neighbors[0],v) not in oriented_trian_edges and (in_neighbors[1],v) not in oriented_trian_edges: + if (in_neighbors[0], v) not in oriented_trian_edges and (in_neighbors[1], v) not in oriented_trian_edges: return _false_return(39) else: return _false_return(40) diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index 0aaaad8debb..d1b227ce6e0 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -141,11 +141,12 @@ def __init__(self, crystals, facade, keepkey, category, **options): if len(crystals) == 0: raise ValueError("the direct sum is empty") else: - assert (crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) + assert all(crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: - self.module_generators = tuple([ self((i,b)) for i,B in enumerate(crystals) - for b in B.module_generators ]) + self.module_generators = tuple([self((i, b)) + for i, B in enumerate(crystals) + for b in B.module_generators]) else: self.module_generators = sum((tuple(B.module_generators) for B in crystals), ()) diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index 93ae0e8d7cb..d7c883c22c5 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -445,10 +445,10 @@ def _rand_der(self): mark = [x < 0 for x in A] i, u = n, n while u >= 2: - if not (mark[i - 1]): + if not mark[i - 1]: while True: j = randrange(1, i) - if not (mark[j - 1]): + if not mark[j - 1]: A[i - 1], A[j - 1] = A[j - 1], A[i - 1] break p = random() @@ -461,7 +461,7 @@ def _rand_der(self): def random_element(self): r""" - Produces all derangements of a positive integer, a list, or + Produce all derangements of a positive integer, a list, or a string. The list or string may contain repeated elements. If an integer `n` is given, then a random derangements of `[1, 2, 3, \ldots, n]` is returned diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index dbab29b1381..df189f0cfe3 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1418,8 +1418,8 @@ def __init__(self, sigma, method='suffix'): raise ValueError("the substitution (%s) must be unimodular" % sigma) first_letter = sigma.codomain().alphabet()[0] - if not (first_letter in ZZ) or (first_letter < 1): - raise ValueError("the substitution (%s) must be defined on positive integers" % sigma) + if first_letter not in ZZ or first_letter < 1: + raise ValueError(f"the substitution ({sigma}) must be defined on positive integers") self._sigma = WordMorphism(sigma) self._d = self._sigma.domain().alphabet().cardinality() diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index c76373962b9..33384a148ac 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -1563,7 +1563,7 @@ def is_final(self): sage: A.is_final False """ - return (self.final_word_out is not None) + return self.final_word_out is not None @is_final.setter def is_final(self, is_final): @@ -9614,7 +9614,7 @@ def find_final_word_out(state): return final_word_out for state in self.iter_states(): - assert (not in_progress) + assert not in_progress # trailing_letters is an infinite iterator additionally # marking positions trailing_letters = itertools.cycle(enumerate(letters)) diff --git a/src/sage/combinat/integer_lists/base.pyx b/src/sage/combinat/integer_lists/base.pyx index 91b372d2392..c39937c3ac6 100644 --- a/src/sage/combinat/integer_lists/base.pyx +++ b/src/sage/combinat/integer_lists/base.pyx @@ -163,7 +163,7 @@ cdef class IntegerListsBackend(): left.floor == right.floor and left.ceiling == right.ceiling) if equal: - return (op == Py_EQ or op == Py_LE or op == Py_GE) + return op == Py_EQ or op == Py_LE or op == Py_GE if op == Py_EQ: return False if op == Py_NE: @@ -481,7 +481,7 @@ cdef class Envelope(): left.min_slope == right.min_slope and left.max_slope == right.max_slope) if equal: - return (op == Py_EQ or op == Py_LE or op == Py_GE) + return op == Py_EQ or op == Py_LE or op == Py_GE if op == Py_EQ: return False if op == Py_NE: diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 8503bd978c5..dea941577b5 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -225,9 +225,9 @@ def __classcall__(cls, G, sum=None, max_part=None, sgs=None): return IntegerVectorsModPermutationGroup_All(G, sgs=sgs) else: if sum is not None: - assert (sum == NN(sum)) + assert sum == NN(sum) if max_part is not None: - assert (max_part == NN(max_part)) + assert max_part == NN(max_part) return IntegerVectorsModPermutationGroup_with_constraints(G, sum, max_part, sgs=sgs) diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index 3c8e85061f3..2440843bac1 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -1229,7 +1229,7 @@ def insertion(self, i) -> TIP: sage: def test_equivalence(n): ....: for T in TamariIntervalPosets(n): ....: for i in range(1, n + 2): - ....: if not (insert_alternative(T, i) == T.insertion(i)): + ....: if insert_alternative(T, i) != T.insertion(i): ....: print(T, i) ....: return False ....: return True diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index 435d6f1243b..7916180ff23 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -409,8 +409,8 @@ def __init__(self, R): sage: NCSF2 = NonCommutativeSymmetricFunctions(Integers(23)) sage: TestSuite(NonCommutativeSymmetricFunctions(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring cat = GradedHopfAlgebras(R).WithRealizations().Cocommutative() Parent.__init__(self, category=cat) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index a1949436b07..874c392bd86 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -556,8 +556,8 @@ def __init__(self, R): sage: QSym2 = QuasiSymmetricFunctions(Integers(23)) sage: TestSuite(QuasiSymmetricFunctions(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R).Commutative() self._category = category diff --git a/src/sage/combinat/ncsym/dual.py b/src/sage/combinat/ncsym/dual.py index 4cec7d5cf79..05b3a38b1b3 100644 --- a/src/sage/combinat/ncsym/dual.py +++ b/src/sage/combinat/ncsym/dual.py @@ -47,9 +47,9 @@ def __init__(self, R): sage: NCSymD2 = SymmetricFunctionsNonCommutingVariablesDual(Integers(23)) sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ).dual()).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed once CategoryObject won't override base_ring + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Commutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/ncsym/ncsym.py b/src/sage/combinat/ncsym/ncsym.py index 0a733ce20a7..7fc037d49b1 100644 --- a/src/sage/combinat/ncsym/ncsym.py +++ b/src/sage/combinat/ncsym/ncsym.py @@ -293,9 +293,9 @@ def __init__(self, R): sage: NCSym2 = SymmetricFunctionsNonCommutingVariables(Integers(23)) sage: TestSuite(SymmetricFunctionsNonCommutingVariables(QQ)).run() """ - # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed once CategoryObject won't override base_ring + # change the line below to assert R in Rings() once MRO issues from #15536, #15475 are resolved + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed once CategoryObject won't override base_ring category = GradedHopfAlgebras(R) # TODO: .Cocommutative() Parent.__init__(self, category=category.WithRealizations()) diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 308cb4909bd..8b3d1899ba0 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -1579,7 +1579,7 @@ def merge_and_countv(ivA_A, ivB_B): i, j = 0, 0 ivC = [] lA, lB = len(A), len(B) - while (i < lA and j < lB): + while i < lA and j < lB: if B[j] < A[i]: C.append(B[j]) ivC.append(ivB[j] + lA - i) @@ -2267,7 +2267,7 @@ def longest_increasing_subsequences(self): """ n = self.size() if n == 0: - return ([[]]) + return [[]] from bisect import insort, bisect diff --git a/src/sage/combinat/posets/cartesian_product.py b/src/sage/combinat/posets/cartesian_product.py index e8c602895cd..abf2ec94b4d 100644 --- a/src/sage/combinat/posets/cartesian_product.py +++ b/src/sage/combinat/posets/cartesian_product.py @@ -172,7 +172,7 @@ def le_lex(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True @@ -239,7 +239,7 @@ def le_product(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True @@ -285,7 +285,7 @@ def le_native(self, left, right): sage: T = [Q((0, 0)), Q((1, 1)), Q((0, 1)), Q((1, 0))] sage: for a in T: ....: for b in T: - ....: assert(Q.le(a, b) == (a <= b)) + ....: assert Q.le(a, b) == (a <= b) ....: print('%s <= %s = %s' % (a, b, a <= b)) (0, 0) <= (0, 0) = True (0, 0) <= (1, 1) = True diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py index b2359c547d5..cb7fc672ac2 100644 --- a/src/sage/combinat/root_system/root_space.py +++ b/src/sage/combinat/root_system/root_space.py @@ -287,7 +287,7 @@ def is_positive_root(self): sage: w.is_positive_root() False """ - return all( c >= 0 for c in self.coefficients() ) + return all(c >= 0 for c in self.coefficients()) @cached_in_parent_method def associated_coroot(self): @@ -319,12 +319,11 @@ def associated_coroot(self): alphacheck[1] sage: alpha[1].associated_coroot().parent() # needs sage.graphs Coroot lattice of the Root system of type ['B', 3] - """ - #assert(self in self.parent().roots() is not False) + # assert self in self.parent().roots() scaled_coroot = self.parent().to_coroot_space_morphism()(self) s = self.scalar(scaled_coroot) - return scaled_coroot.map_coefficients(lambda c: (2*c) // s) + return scaled_coroot.map_coefficients(lambda c: (2 * c) // s) def quantum_root(self): r""" diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 7a6e76faacc..be54faa6bcb 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -1087,13 +1087,13 @@ def symmetric_form(self, la): iset = P.index_set() + ('delta',) return sum(cl*sym[iset.index(ml),iset.index(mr)]*cr - for ml,cl in self for mr,cr in la) + for ml, cl in self for mr, cr in la) # # This should be in a method to_weight_lattice() # alphac = self.simple_coroots() # Lambda = self.fundamental_weights() - # assert( t == self.plus(t.scalar(alphac[i]) * Lambda[i] for i in self.index_set() ) ) - # t = self.plus( t.scalar(alphac[i]) * c[i] * Lambda[i] for i in self.index_set() ) + # assert t == self.plus(t.scalar(alphac[i]) * Lambda[i] for i in self.index_set()) + # t = self.plus( t.scalar(alphac[i]) * c[i] * Lambda[i] for i in self.index_set()) def to_weight_space(self, base_ring=None): r""" diff --git a/src/sage/combinat/sf/schur.py b/src/sage/combinat/sf/schur.py index 202c31d7cee..96d3e5f5510 100644 --- a/src/sage/combinat/sf/schur.py +++ b/src/sage/combinat/sf/schur.py @@ -715,7 +715,7 @@ def f(partition): quotient = ZZq((prod(1-q_lim**(n+j-i) for (i, j) in partition.cells())) / prod(1-q_lim**h for h in partition.hooks())) - return (power * quotient.subs({q_lim: q})) + return power * quotient.subs({q_lim: q}) return self.parent()._apply_module_morphism(self, f, q.parent()) diff --git a/src/sage/combinat/sf/sf.py b/src/sage/combinat/sf/sf.py index 81665f56fbd..06e0a1335eb 100644 --- a/src/sage/combinat/sf/sf.py +++ b/src/sage/combinat/sf/sf.py @@ -865,8 +865,8 @@ def __init__(self, R): """ # change the line below to assert(R in Rings()) once MRO issues from #15536, #15475 are resolved - assert (R in Fields() or R in Rings()) # side effect of this statement assures MRO exists for R - self._base = R # Won't be needed when CategoryObject won't override anymore base_ring + assert R in Fields() or R in Rings() # side effect of this statement assures MRO exists for R + self._base = R # Won't be needed when CategoryObject won't override anymore base_ring cat = GradedHopfAlgebras(R).Commutative().Cocommutative() if R in PrincipalIdealDomains(): cat &= UniqueFactorizationDomains() diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 432fbd06ef5..7873beabd77 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -1439,21 +1439,21 @@ def check_word(w): return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] < w[-1]) + return w[0] < w[-1] elif comparison == 0: def check_word(w): if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d: return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] == w[-1]) + return w[0] == w[-1] elif comparison == 1: def check_word(w): if sum((1 for i in range(n-1) if w[i] > w[i+1])) != d: return False if sum((1 for i in range(n-1) if w[i] == w[i+1])) != s: return False - return (w[0] > w[-1]) + return w[0] > w[-1] def coeff_of_m_mu_in_result(mu): # Compute the coefficient of the monomial symmetric diff --git a/src/sage/combinat/shuffle.py b/src/sage/combinat/shuffle.py index d8cf7539f0b..8bae3eda267 100644 --- a/src/sage/combinat/shuffle.py +++ b/src/sage/combinat/shuffle.py @@ -137,7 +137,7 @@ def __eq__(self, other): """ if not isinstance(other, type(self)): return False - return (self._l1 == other._l1 and self._l2 == other._l2) + return self._l1 == other._l1 and self._l2 == other._l2 def __ne__(self, other): """ @@ -220,10 +220,9 @@ def __init__(self, l1, l2, element_constructor=None): [[2, 3, 4, 5], [2, 5, 3, 4], [5, 2, 3, 4], [2, 3, 5, 4], [1, 2, 3, 5], [1, 5, 2, 3], [5, 1, 2, 3], [1, 2, 5, 3]] """ - assert (isinstance(l1, Iterable) and - isinstance(l2, Iterable)) - assert (all(isinstance(elem, Iterable) for elem in l1)) - assert (all(isinstance(elem, Iterable) for elem in l2)) + assert isinstance(l1, Iterable) and isinstance(l2, Iterable) + assert all(isinstance(elem, Iterable) for elem in l1) + assert all(isinstance(elem, Iterable) for elem in l2) if element_constructor is None: try: @@ -313,7 +312,7 @@ def comp_binom(el1, el2): return (ll1 + ll2).binomial(ll2) return sum(comp_binom(el1, el2) - for (el1, el2) in itertools.product(self._l1, self._l2)) + for (el1, el2) in itertools.product(self._l1, self._l2)) class ShuffleProduct(ShuffleProduct_abstract): @@ -361,7 +360,7 @@ def __init__(self, l1, l2, element_constructor=None): [word: aabbb, word: baabb, word: ababb, word: bbaab, word: babab, word: abbab, word: bbbaa, word: bbaba, word: babba, word: abbba] """ - assert (isinstance(l1, Iterable) and isinstance(l2, Iterable)) + assert isinstance(l1, Iterable) and isinstance(l2, Iterable) if element_constructor is None: try: @@ -519,7 +518,7 @@ def __contains__(self, iterable): return iterable[i + 1:] == l2[i_l2:] if i_l2 == len_l2: return iterable[i + 1:] == l1[i_l1:] - return (i_l1 + 1 == len_l1) and (i_l2 + 1 == len_l2) + return i_l1 + 1 == len_l1 and i_l2 + 1 == len_l2 def cardinality(self): r""" diff --git a/src/sage/combinat/subword.py b/src/sage/combinat/subword.py index 50869bd600a..9cced6b8645 100644 --- a/src/sage/combinat/subword.py +++ b/src/sage/combinat/subword.py @@ -292,11 +292,11 @@ def random_element(self): sage: for i in range(100): ....: w = S1.random_element() ....: if w in S2: - ....: assert(not w) + ....: assert not w sage: for i in range(100): ....: w = S2.random_element() ....: if w in S1: - ....: assert(not w) + ....: assert not w """ return self._build(elt for elt in self._w if prandom.randint(0, 1)) @@ -465,11 +465,11 @@ def random_element(self): sage: for i in range(100): ....: w = S1.random_element() ....: if w in S2: - ....: assert(not w) + ....: assert not w sage: for i in range(100): ....: w = S2.random_element() ....: if w in S1: - ....: assert(not w) + ....: assert not w """ sample = prandom.sample(self._w, self._k) if self._build is list: diff --git a/src/sage/combinat/superpartition.py b/src/sage/combinat/superpartition.py index f278eb70e11..a2e77f8a5b1 100644 --- a/src/sage/combinat/superpartition.py +++ b/src/sage/combinat/superpartition.py @@ -92,7 +92,7 @@ @richcmp_method class SuperPartition(ClonableArray, - metaclass=InheritComparisonClasscallMetaclass): + metaclass=InheritComparisonClasscallMetaclass): r""" A super partition. @@ -688,9 +688,9 @@ def add_horizontal_border_strip_star(self, h) -> list: row_changed = [row1 - row2 for row1, row2 in zip(elt, sp1)] new_sp = [elt, [(i[0] + 1, elt[i[0] + 1]) for i in circ_list if row_changed[i[0]] != 0] - # TODO: Check that this is not supposed to be - # a tuple of size 1 - + [(i) for i in circ_list if row_changed[i[0]] == 0]] + # TODO: Check that this is not supposed to be + # a tuple of size 1 + + [(i) for i in circ_list if row_changed[i[0]] == 0]] if len(set([k for (j, k) in new_sp[1]])) == len(new_sp[1]): out += [SuperPartition.from_circled_diagram(*new_sp)] return out diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index f13daf65a1e..2103cb810a7 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -4507,7 +4507,7 @@ def __classcall_private__(self, t): # check that SST is strictly increasing in columns # we know that len(rnext) <= len(rcur) as the SST cannot have # more columns in the next row than the current row. - assert (len(rnext) <= len(rcur)) + assert len(rnext) <= len(rcur) for cix in range(len(rnext)): if rnext[cix] <= rcur[cix]: @@ -6408,7 +6408,7 @@ def __iter__(self): from sage.combinat.partition import Partitions # Iterates through with maximum entry as order i = 1 - while (True): + while True: for part in Partitions(self.size): if i != 1: for k in range(1, self.size+1): @@ -6508,7 +6508,7 @@ def __iter__(self): # Iterates through with maximum entry as order i = 1 n = sum(self.shape) - while (True): + while True: if i != 1: for k in range(1, n+1): for c in integer_vectors_nk_fast_iter(n - k, i-1): diff --git a/src/sage/combinat/tamari_lattices.py b/src/sage/combinat/tamari_lattices.py index 6bcca79ca97..0c71da46673 100644 --- a/src/sage/combinat/tamari_lattices.py +++ b/src/sage/combinat/tamari_lattices.py @@ -217,7 +217,7 @@ def GeneralizedTamariLattice(a, b, m=1, check=True): """ if not (gcd(a, b) == 1 and a >= b): raise ValueError("the numbers a and b must be coprime with a>=b") - if not (a >= b * m): + if a < b * m: raise ValueError("the condition a>=b*m does not hold") def covers(p): diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index e63fd8b912f..e3c2fcc5676 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -641,7 +641,7 @@ def _to_integer_iterator(self, use_parent_alphabet=False): mapping = {} next_value = 0 for letter in self: - if not (letter in mapping): + if letter not in mapping: mapping[letter] = next_value next_value += 1 yield mapping[letter] diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index e476b756183..bf355d9d10a 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -5938,15 +5938,15 @@ def sturmian_desubstitute_as_possible(self): w_isolated = word_from_letter[l_isolated] # the word associated to the isolated letter w_running = word_from_letter[l_running] # the word associated to the running letter min_run = minimal_run[l_running] - if (prefix_letter == l_isolated) or (prefix_length <= min_run): + if prefix_letter == l_isolated or prefix_length <= min_run: desubstitued_word = W() else: desubstitued_word = w_running ** (prefix_length - min_run) for i in runs[l_running]: desubstitued_word = desubstitued_word + w_isolated + w_running ** (i - min_run) - if (current_run_length > 0): + if current_run_length > 0: desubstitued_word = desubstitued_word + w_isolated - if (previous_letter == l_running) and (current_run_length > min_run): + if previous_letter == l_running and current_run_length > min_run: desubstitued_word = desubstitued_word + w_running ** (current_run_length - min_run) return desubstitued_word.sturmian_desubstitute_as_possible() @@ -6064,7 +6064,7 @@ def is_tangent(self): - Thierry Monteil """ - if (self.parent().alphabet().cardinality() != 2): + if self.parent().alphabet().cardinality() != 2: raise TypeError('your word must be defined on a binary alphabet') a, b = self.parent().alphabet() mini = 0 @@ -6077,10 +6077,10 @@ def is_tangent(self): if i == b: height = height - 1 mini = min(mini, height) - return (maxi - mini <= 2) + return maxi - mini <= 2 # TODO. - # 1. Those three swap functions should use the cmp of python. + # 1. Those three swap functions should use the cmp of python # 2. The actual code should then be copied as is in the Word_over_Alphabet # and continue to use the parent cmp # 3. Once Word can define Words over alphabet, the examples @@ -7213,10 +7213,10 @@ def __call__(self, i): """ j = i for c in self: - if (j - c.length() < 0): + if j < c.length(): return c[j] j -= c.length() - raise IndexError("index (=%s) out of range" % i) + raise IndexError(f"index (={i}) out of range") class Factorization(list): diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 2223ef752ca..7e04e8646d0 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -2295,13 +2295,13 @@ def list_of_conjugates(self): c = [] m = self c.append(m) - while (m.has_left_conjugate()): + while m.has_left_conjugate(): m = m.conjugate(1) if m == self: break c.append(m) m = self - while (m.has_right_conjugate()): + while m.has_right_conjugate(): m = m.conjugate(-1) if m == self: break diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index c3646a36907..5e4fa13ddea 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -1366,7 +1366,7 @@ def _count_and_skip(self, node, i, j): ('explicit', 1) """ trans = self._find_transition(node, self._letters[i]) - while (trans[0][1] is not None and trans[0][1] - trans[0][0] + 1 <= j - i): + while trans[0][1] is not None and trans[0][1] - trans[0][0] + 1 <= j - i: node = trans[1] i += trans[0][1] - trans[0][0] + 1 if i == j: diff --git a/src/sage/combinat/words/word_infinite_datatypes.py b/src/sage/combinat/words/word_infinite_datatypes.py index 1e41a5e4e22..9998d3487d5 100644 --- a/src/sage/combinat/words/word_infinite_datatypes.py +++ b/src/sage/combinat/words/word_infinite_datatypes.py @@ -237,8 +237,8 @@ def __getitem__(self, key): if isinstance(key, slice): # Infinite words if self._len is Infinity or self._len is None: - if not (key.start is None) and key.start < 0 or \ - not (key.stop is None) and key.stop < 0: + if key.start is not None and key.start < 0 or \ + key.stop is not None and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else key.step if step > 0: @@ -831,8 +831,8 @@ def __getitem__(self, key): """ if isinstance(key, slice): if self._len is Infinity or self._len is None: - if not (key.start is None) and key.start < 0 or \ - not (key.stop is None) and key.stop < 0: + if key.start is not None and key.start < 0 or \ + key.stop is not None and key.stop < 0: raise ValueError("for infinite words, start and stop values cannot be negative") step = 1 if key.step is None else int(key.step) if step >= 0: @@ -840,7 +840,7 @@ def __getitem__(self, key): if key.stop is None: length = Infinity stop = None - else: # key.stop > 0 + else: # key.stop > 0 length = int(max(0, ceil((key.stop-start)/float(step)))) stop = int(key.stop) data = itertools.islice(self, start, stop, step) diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index 0765188366f..e701c917062 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -700,7 +700,7 @@ def _mpfr_(self, R): q_odd = self.denominator(2 * k + 1) m_even = (p_even << N) // q_even # floor((2^N p_even) / q_even) m_odd = (p_odd << N + q_odd - 1) // q_odd # ceil((2^N p_odd) / q_odd) - while (m_odd - m_even) > 1: + while m_odd - m_even > 1: k += 1 p_even = self.numerator(2 * k) p_odd = self.numerator(2 * k + 1) diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index bdb5884668e..0eca810920e 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -233,7 +233,7 @@ cdef class arith_int: return self.abs_int(a) if a<0: a=-a if b<0: b=-b - while(b): + while b: c = a % b a = b b = c @@ -261,7 +261,7 @@ cdef class arith_int: if b<0: b = -b; qsign = -1 p = 1; q = 0; r = 0; s = 1 - while (b): + while b: c = a % b; quot = a/b a = b; b = c new_r = p - quot*r @@ -360,13 +360,15 @@ cdef class arith_llong: cdef long long c_gcd_longlong(self, long long a, long long b) except -1: cdef long long c - if a==0: + if a == 0: return self.abs_longlong(b) - if b==0: + if b == 0: return self.abs_longlong(a) - if a<0: a=-a - if b<0: b=-b - while(b): + if a < 0: + a = -a + if b < 0: + b = -b + while b: c = a % b a = b b = c @@ -396,7 +398,7 @@ cdef class arith_llong: if b<0: b = -b; qsign = -1 p = 1; q = 0; r = 0; s = 1 - while (b): + while b: c = a % b; quot = a/b a = b; b = c new_r = p - quot*r diff --git a/src/sage/rings/padics/unramified_extension_generic.py b/src/sage/rings/padics/unramified_extension_generic.py index 67aa2be9267..6892c7fbddf 100644 --- a/src/sage/rings/padics/unramified_extension_generic.py +++ b/src/sage/rings/padics/unramified_extension_generic.py @@ -225,12 +225,12 @@ def _frob_gen(self, arithmetic=True): exp = p a = self.gen() if not arithmetic: - exp = p**(self.absolute_degree()-1) + exp = p**(self.absolute_degree() - 1) approx = (self(a.residue()**exp)).lift_to_precision(self.precision_cap()) #first approximation f = self.defining_polynomial() g = f.derivative() - while (f(approx) != 0): #hensel lift frobenius(a) - approx = approx - f(approx)/g(approx) + while f(approx) != 0: # hensel lift frobenius(a) + approx = approx - f(approx) / g(approx) return approx def uniformizer_pow(self, n): diff --git a/src/sage/rings/polynomial/infinite_polynomial_element.py b/src/sage/rings/polynomial/infinite_polynomial_element.py index fc8449b340e..760c0dd57ab 100644 --- a/src/sage/rings/polynomial/infinite_polynomial_element.py +++ b/src/sage/rings/polynomial/infinite_polynomial_element.py @@ -952,7 +952,7 @@ def symmetric_cancellation_order(self, other): for i in Lsmall: # i is a shift of the smaller polynomial j += 1 ExpoSmall = Fsmall[i] - while (j < lenBig): + while j < lenBig: found = False if Lbig[j] >= i: ExpoBigSave = [e for e in Fbig[Lbig[j]]] diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index c9903625b38..16c8c09fbc3 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -2107,7 +2107,7 @@ cdef class NCPolynomial_plural(RingElement): raise TypeError("The input degrees must be a dictionary of variables to exponents.") # Extract the monomials that match the specifications - while(p): + while p: flag = 0 for i from 0<=iself._parent)._base) p = pNext(p) @@ -2363,7 +2363,7 @@ cdef class NCPolynomial_plural(RingElement): i += 1 p_Setm(m, r) - while(p): + while p: if p_ExpVectorEqual(p, m, r) == 1: p_Delete(&m,r) return si2sa(p_GetCoeff(p, r), r, (self._parent)._base) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index b6a260e7008..58a6a4d2308 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -1267,14 +1267,14 @@ def hensel_lift(self, a): # Newton iteration # Todo: compute everything up to the adequate precision at each step b = ~dera - while (True): + while True: na = a - selfa * b if na == a: return a a = na selfa = self(a) dera = der(a) - b *= 2 - dera*b + b *= 2 - dera * b def _factor_of_degree(self, deg): """ diff --git a/src/sage/rings/polynomial/symmetric_ideal.py b/src/sage/rings/polynomial/symmetric_ideal.py index 12a629ad741..f9cae63ea4b 100644 --- a/src/sage/rings/polynomial/symmetric_ideal.py +++ b/src/sage/rings/polynomial/symmetric_ideal.py @@ -655,14 +655,14 @@ def symmetrisation(self, N=None, tailreduce=False, report=None, use_full_group=F from sage.combinat.permutation import Permutation from sage.rings.polynomial.symmetric_reduction import SymmetricReductionStrategy RStrat = SymmetricReductionStrategy(self.ring(),OUT.gens(),tailreduce=tailreduce) - while (OUT != newOUT): + while OUT != newOUT: OUT = newOUT PermutedGens = list(OUT.gens()) if not (report is None): print("Apply permutations") - for i in range(1,N): - for j in range(i+1,N+1): - P = Permutation(((i,j))) + for i in range(1, N): + for j in range(i + 1, N + 1): + P = Permutation(((i, j))) for X in OUT.gens(): p = RStrat.reduce(X**P,report=report) if p._p != 0: diff --git a/src/sage/rings/polynomial/symmetric_reduction.pyx b/src/sage/rings/polynomial/symmetric_reduction.pyx index 6cc00047de8..e873fcc5397 100644 --- a/src/sage/rings/polynomial/symmetric_reduction.pyx +++ b/src/sage/rings/polynomial/symmetric_reduction.pyx @@ -487,7 +487,7 @@ cdef class SymmetricReductionStrategy: p = p / p.lc() if (self._min_lm is None) or (p.lm() < self._min_lm): self._min_lm = p.lm() - while (i < l) and (self._lengths[i] < newLength): + while i < l and self._lengths[i] < newLength: i += 1 self._lm.insert(i, p) self._lengths.insert(i, newLength) @@ -514,7 +514,7 @@ cdef class SymmetricReductionStrategy: self._lm.pop(i) self._lengths.pop(i) j = 0 - while (j < i) and (self._lengths[j] < q_len): + while j < i and self._lengths[j] < q_len: j += 1 self._lm.insert(j, q) self._lengths.insert(j, q_len) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index a78680d0ee2..fb2eb1d718c 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -3905,7 +3905,7 @@ cdef class RealNumber(sage.structure.element.RingElement): cdef Integer k - while (not low_done) or (not high_done): + while not low_done or not high_done: # Move the low side k = (c*b - d*a) // (d*e - c*f) diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index 84d67430c82..ce737c93969 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -592,7 +592,7 @@ def extension(self, ring): Rational Field """ extensions = self.extensions(ring) - assert (extensions) + assert extensions if len(extensions) > 1: raise ValueError("there is no unique extension of %r from %r to %r" % (self, self.domain(), ring)) return extensions[0] @@ -756,7 +756,7 @@ def separating_element(self, others): factor = ret ret = delta while any(other(ret) >= 0 for other in others[:i]): - assert (others[i](ret) < 0) + assert others[i](ret) < 0 ret *= factor else: # others[i](ret) > 0 # construct an element which approximates a unit with respect to others[i] @@ -801,16 +801,16 @@ def _strictly_separating_element(self, other): numerator = self._weakly_separating_element(other) n = self(numerator) nn = other(numerator) - assert (n > 0) - assert (nn is not infinity) - if (nn < 0): + assert n > 0 + assert nn is not infinity + if nn < 0: return numerator denominator = other._weakly_separating_element(self) d = self(denominator) dd = other(denominator) - assert (dd > 0) - assert (d is not infinity) + assert dd > 0 + assert d is not infinity if d < 0: # The following may fail if denominator is not # invertible in the domain, but we don't have a better @@ -828,11 +828,11 @@ def _strictly_separating_element(self, other): # a/b > d/n and b/a > nn/dd # which is # dd/nn > a/b > d/n - assert (dd/nn > d/n) + assert dd / nn > d / n from sage.rings.continued_fraction import continued_fraction ab_cf = [] - dn_cf = continued_fraction(d/n) - ddnn_cf = continued_fraction(dd/nn) + dn_cf = continued_fraction(d / n) + ddnn_cf = continued_fraction(dd / nn) for i, (x,y) in enumerate(zip(dn_cf, ddnn_cf)): if x == y: ab_cf.append(x) From dee3b9fe66cc51748e356bbfe513f96de9c7b3c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 15:53:54 +0200 Subject: [PATCH 159/225] change formulation in the doc of q-Catalan --- src/sage/combinat/q_analogues.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/q_analogues.py b/src/sage/combinat/q_analogues.py index 1f873e4a5b4..ec4fb594470 100644 --- a/src/sage/combinat/q_analogues.py +++ b/src/sage/combinat/q_analogues.py @@ -354,12 +354,12 @@ def q_binomial(n, k, q=None, algorithm='auto'): # the algorithms while algorithm == 'naive': - denom = prod(one - q**i for i in range(1, k+1)) + denom = prod(one - q**i for i in range(1, k + 1)) if not denom: # q is a root of unity, use the cyclotomic algorithm algorithm = 'cyclotomic' break else: - num = prod(one - q**i for i in range(n-k+1, n+1)) + num = prod(one - q**i for i in range(n - k + 1, n + 1)) try: try: return num // denom @@ -459,7 +459,7 @@ def q_catalan_number(n, q=None, m=1): - ``q`` -- optional variable - - ``m`` -- optional integer (default: 1) to get the ``m``-Fuss-Catalan numbers + - ``m`` -- (optional integer) to get instead the ``m``-Fuss-Catalan numbers If `q` is unspecified, then it defaults to using the generator `q` for a univariate polynomial ring over the integers. From be29cd1213d561a73764a7e52aeaed11b58a86ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 17:54:30 +0200 Subject: [PATCH 160/225] suggested details --- src/sage/combinat/designs/group_divisible_designs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/designs/group_divisible_designs.py b/src/sage/combinat/designs/group_divisible_designs.py index b589489cfec..9a17d42f114 100644 --- a/src/sage/combinat/designs/group_divisible_designs.py +++ b/src/sage/combinat/designs/group_divisible_designs.py @@ -113,7 +113,7 @@ def group_divisible_design(v, K, G, existence=False, check=False): return GDD_4_2(v // 2, check=check) # From a TD(k,g) - elif (len(G) == 1 == len(K) and K[0] * G[0] == v): + elif len(G) == 1 == len(K) and K[0] * G[0] == v: from .orthogonal_arrays import transversal_design return transversal_design(k=K[0], n=G[0], existence=existence) @@ -176,8 +176,8 @@ def GDD_4_2(q, existence=False, check=True): if existence: return True - from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF - G = GF(q, 'x') + from sage.rings.finite_rings.finite_field_constructor import FiniteField + G = FiniteField(q, 'x') w = G.primitive_element() e = w**((q - 1) // 3) @@ -284,7 +284,7 @@ def __init__(self, points, groups, blocks, G=None, K=None, lambd=1, check=False, **kwds) - if (groups is None or (copy is False and self._point_to_index is None)): + if groups is None or (copy is False and self._point_to_index is None): self._groups = groups elif self._point_to_index is None: self._groups = [g[:] for g in groups] From e9a9a0be2271d2c643ab6c685ada341ed7543b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 18:10:45 +0200 Subject: [PATCH 161/225] a few more links to errors in the doc --- src/sage/categories/sets_with_partial_maps.py | 3 +- src/sage/graphs/generic_graph.py | 4 +-- src/sage/interfaces/axiom.py | 2 +- src/sage/interfaces/gap.py | 2 +- src/sage/interfaces/giac.py | 2 +- src/sage/interfaces/maple.py | 2 +- src/sage/interfaces/maxima.py | 2 +- src/sage/interfaces/mwrank.py | 2 +- src/sage/libs/gap/libgap.pyx | 2 +- src/sage/matrix/matrix0.pyx | 8 ++--- src/sage/matrix/matrix_integer_dense.pyx | 4 +-- src/sage/modular/abvar/abvar.py | 29 ++++++++++--------- src/sage/modular/modsym/p1list.pyx | 4 +-- src/sage/rings/finite_rings/integer_mod.pyx | 7 +++-- src/sage/rings/integer.pyx | 3 +- .../rings/padics/padic_extension_generic.py | 3 +- .../padics/padic_floating_point_element.pyx | 3 +- src/sage/rings/power_series_ring_element.pyx | 20 ++++++------- src/sage/schemes/curves/projective_curve.py | 4 +-- .../schemes/elliptic_curves/ell_generic.py | 2 +- .../elliptic_curves/ell_number_field.py | 2 +- .../elliptic_curves/gal_reps_number_field.py | 2 +- .../schemes/elliptic_curves/period_lattice.py | 12 ++++---- .../tensor/modules/tensor_with_indices.py | 4 +-- 24 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/sage/categories/sets_with_partial_maps.py b/src/sage/categories/sets_with_partial_maps.py index 08448342ab1..5b2f9b35427 100644 --- a/src/sage/categories/sets_with_partial_maps.py +++ b/src/sage/categories/sets_with_partial_maps.py @@ -13,10 +13,11 @@ from sage.categories.category_singleton import Category_singleton from .objects import Objects + class SetsWithPartialMaps(Category_singleton): """ The category whose objects are sets and whose morphisms are - maps that are allowed to raise a ValueError on some inputs. + maps that are allowed to raise a :class:`ValueError` on some inputs. This category is equivalent to the category of pointed sets, via the equivalence sending an object X to X union {error}, diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 66703a0f7c1..4e12838d3c4 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -23178,9 +23178,9 @@ def automorphism_group(self, partition=None, verbosity=0, TESTS: - We get a KeyError when given an invalid partition (:trac:`6087`):: + We get a :class:`KeyError` when given an invalid partition (:trac:`6087`):: - sage: g=graphs.CubeGraph(3) + sage: g = graphs.CubeGraph(3) sage: g.relabel() sage: g.automorphism_group(partition=[[0,1,2],[3,4,5]],algorithm='sage') # needs sage.groups Traceback (most recent call last): diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 939a142aa70..5df8d2e184a 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -43,7 +43,7 @@ clisp. If the string "error" (case insensitive) occurs in the output of -anything from axiom, a RuntimeError exception is raised. +anything from axiom, a :class:`RuntimeError` exception is raised. EXAMPLES: We evaluate a very simple expression in axiom. diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 61f38af2d26..dd4c87ce988 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -430,7 +430,7 @@ def load_package(self, pkg, verbose=False): """ Load the Gap package with the given name. - If loading fails, raise a RuntimeError exception. + If loading fails, raise a :class:`RuntimeError` exception. TESTS:: diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index d7a259fd3d5..cd7e7b8def5 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -48,7 +48,7 @@ If the string "error" (case insensitive) occurs in the output of -anything from Giac, a RuntimeError exception is raised. +anything from Giac, a :class:`RuntimeError` exception is raised. Tutorial -------- diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index e9f0d5d6fb0..42f680e001b 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -36,7 +36,7 @@ (x-y)*(x^4+x^3*y+x^2*y^2+x*y^3+y^4) If the string "error" (case insensitive) occurs in the output of -anything from Maple, a RuntimeError exception is raised. +anything from Maple, a :class:`RuntimeError` exception is raised. Tutorial -------- diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index c55f9797ef2..5526e2c6458 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -35,7 +35,7 @@ If the string "error" (case insensitive) occurs in the output of -anything from Maxima, a RuntimeError exception is raised. +anything from Maxima, a :class:`RuntimeError` exception is raised. EXAMPLES: We evaluate a very simple expression in Maxima. diff --git a/src/sage/interfaces/mwrank.py b/src/sage/interfaces/mwrank.py index 35d73277109..92a9081eb4c 100644 --- a/src/sage/interfaces/mwrank.py +++ b/src/sage/interfaces/mwrank.py @@ -294,7 +294,7 @@ def eval(self, s, **kwds): .. NOTE:: - If a RuntimeError exception is raised, then the mwrank + If a :class:`RuntimeError` exception is raised, then the mwrank interface is restarted and the command is retried once. EXAMPLES:: diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx index 05ca5f7d4fb..33a17cff528 100644 --- a/src/sage/libs/gap/libgap.pyx +++ b/src/sage/libs/gap/libgap.pyx @@ -412,7 +412,7 @@ class Gap(Parent): def load_package(self, pkg): """ - If loading fails, raise a RuntimeError exception. + If loading fails, raise a :class:`RuntimeError` exception. TESTS:: diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index d781fc822b0..9f3ff8e6942 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -393,7 +393,7 @@ cdef class Matrix(sage.structure.element.Matrix): """ This function gets called when you're about to change this matrix. - If self is immutable, a ValueError is raised, since you should + If self is immutable, a :class:`ValueError` is raised, since you should never change a mutable matrix. If self is mutable, the cache of results about self is deleted. @@ -406,10 +406,10 @@ cdef class Matrix(sage.structure.element.Matrix): cdef check_bounds_and_mutability(self, Py_ssize_t i, Py_ssize_t j): """ This function gets called when you're about to set the i,j entry of - this matrix. If i or j is out of range, an IndexError exception is - raised. + this matrix. If i or j is out of range, an :class:`IndexError` + exception is raised. - If self is immutable, a ValueError is raised, since you should + If self is immutable, a :class:`ValueError` is raised, since you should never change a mutable matrix. If self is mutable, the cache of results about self is deleted. diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 8c276f2ca29..d4d2819c13c 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -1712,8 +1712,8 @@ cdef class Matrix_integer_dense(Matrix_dense): Return a pair (F, C) such that the rows of C form a symplectic basis for self and ``F = C * self * C.transpose()``. - Raise a ValueError if self is not anti-symmetric, or self is not - alternating. + Raise a :class:`ValueError` if self is not anti-symmetric, + or self is not alternating. Anti-symmetric means that `M = -M^t`. Alternating means that the diagonal of `M` is identically zero. diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index 54ef9cc41c5..7d46f6a36bb 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -580,9 +580,11 @@ def newform_decomposition(self, names=None): def newform_label(self): """ Return the label [level][isogeny class][group] of the newform - `f` such that this abelian variety is isogenous to the - newform abelian variety `A_f`. If this abelian variety is - not simple, raise a ValueError. + `f` such that this abelian variety is isogenous to the newform + abelian variety `A_f`. + + If this abelian variety is not simple, this raises + a :class:`ValueError`. OUTPUT: string @@ -687,8 +689,10 @@ def elliptic_curve(self): def _isogeny_to_newform_abelian_variety(self): r""" Return an isogeny from self to an abelian variety `A_f` - attached to a newform. If self is not simple (so that no such - isogeny exists), raise a ValueError. + attached to a newform. + + If self is not simple (so that no such + isogeny exists), this raises a :class:`ValueError`. EXAMPLES:: @@ -733,13 +737,12 @@ def _simple_isogeny(self, other): """ Given self and other, if both are simple, and correspond to the same newform with the same congruence subgroup, return an isogeny. - Otherwise, raise a ValueError. - INPUT: + Otherwise, this raises a :class:`ValueError`. + INPUT: - - ``self, other`` - modular abelian varieties - + - ``self, other`` -- modular abelian varieties OUTPUT: an isogeny @@ -3183,7 +3186,7 @@ def degen_t(self, none_if_not_known=False): `(t,N)`, where `N` is the ambient level and `t` is an integer that divides the quotient of `N` by the newform level. This function returns the tuple - `(t,N)`, or raises a ValueError if self isn't simple. + `(t,N)`, or raises a :class:`ValueError` if self is not simple. .. note:: @@ -3235,16 +3238,14 @@ def isogeny_number(self, none_if_not_known=False): """ Return the number (starting at 0) of the isogeny class of new simple abelian varieties that self is in. If self is not simple, - raises a ValueError exception. + raises a :class:`ValueError` exception. INPUT: - - - ``none_if_not_known`` - bool (default: False); if + - ``none_if_not_known`` -- bool (default: False); if True then this function may return None instead of True of False if we don't already know the isogeny number of self. - EXAMPLES: We test the none_if_not_known flag first:: sage: J0(33).isogeny_number(none_if_not_known=True) is None diff --git a/src/sage/modular/modsym/p1list.pyx b/src/sage/modular/modsym/p1list.pyx index 30a8f7471dd..1fc3e2de952 100644 --- a/src/sage/modular/modsym/p1list.pyx +++ b/src/sage/modular/modsym/p1list.pyx @@ -1371,8 +1371,8 @@ def lift_to_sl2z(c, d, N): sage: lift_to_sl2z(2,3,6000000) [1, 1, 2, 3] - You will get a ValueError exception if the input is invalid. Note - that here gcd(15,6,24)=3:: + You will get a :class:`ValueError` exception if the input is invalid. + Note that here gcd(15,6,24)=3:: sage: lift_to_sl2z(15,6,24) Traceback (most recent call last): diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 046b737a833..4fb4656cdd2 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -646,11 +646,14 @@ cdef class IntegerMod_abstract(FiniteRingElement): ``R`` is the parent of ``self``. - OUTPUT: Integer `x` such that `b^x = a`, if this exists; a ValueError otherwise. + OUTPUT: + + Integer `x` such that `b^x = a`, if this exists; a :class:`ValueError` + otherwise. .. NOTE:: - The algorithm first factors the modulus, then invokes Pari's ``znlog`` + The algorithm first factors the modulus, then invokes Pari's :pari:`znlog` function for each odd prime power in the factorization of the modulus. This method can be quite slow for large moduli. diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 0ca24804524..4202bcc9a10 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -2326,7 +2326,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): OUTPUT: If ``truncate_mode`` is 0 (default), then returns the exact n'th root - if ``self`` is an n'th power, or raises a ValueError if it is not. + if ``self`` is an n'th power, or raises a :class:`ValueError` + if it is not. If ``truncate_mode`` is 1, then if either ``n`` is odd or ``self`` is positive, returns a pair ``(root, exact_flag)`` where ``root`` is the diff --git a/src/sage/rings/padics/padic_extension_generic.py b/src/sage/rings/padics/padic_extension_generic.py index 88027e19439..edd65c85f60 100644 --- a/src/sage/rings/padics/padic_extension_generic.py +++ b/src/sage/rings/padics/padic_extension_generic.py @@ -375,7 +375,8 @@ def exact_ring(self): """ Return the order with the same defining polynomial. - Will raise a ValueError if the coefficients of the defining polynomial are not integral. + Will raise a :class:`ValueError` if the coefficients of the defining + polynomial are not integral. EXAMPLES:: diff --git a/src/sage/rings/padics/padic_floating_point_element.pyx b/src/sage/rings/padics/padic_floating_point_element.pyx index d6153a1f673..32c8e25cde2 100644 --- a/src/sage/rings/padics/padic_floating_point_element.pyx +++ b/src/sage/rings/padics/padic_floating_point_element.pyx @@ -144,7 +144,8 @@ cdef class pAdicFloatingPointElement(FPElement): precision. If a rational is returned, its denominator will equal ``p^ordp(self)``. - This method will raise a ValueError when this element is infinity. + This method will raise a :class:`ValueError` when this element + is infinity. EXAMPLES:: diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index 8bfabb73701..5e2c4511e49 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1510,21 +1510,21 @@ cdef class PowerSeries(AlgebraElement): INPUT: - - ``prec`` - integer (default: None): if not None and the series - has infinite precision, truncates series at precision - prec. + - ``prec`` - integer (default: ``None``): if not ``None`` + and the series has infinite precision, truncates series at + precision prec. - - ``extend`` - bool (default: False); if True, return a square + - ``extend`` - bool (default: ``False``); if ``True``, return a square root in an extension ring, if necessary. Otherwise, raise - a ValueError if the square root is not in the base power series - ring. For example, if ``extend`` is True the square root of a - power series with odd degree leading coefficient is - defined as an element of a formal extension ring. + a :class:`ValueError` if the square root is not in the + base power series ring. For example, if ``extend`` is ``True`` + the square root of a power series with odd degree leading + coefficient is defined as an element of a formal extension ring. - - ``name`` - string; if ``extend`` is True, you must also specify the print + - ``name`` - string; if ``extend`` is ``True``, you must also specify the print name of the formal square root. - - ``all`` - bool (default: False); if True, return all square + - ``all`` - bool (default: ``False``); if ``True``, return all square roots of self, instead of just one. ALGORITHM: Newton's method diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 958a402da19..5a4f9f5f4ce 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2009,7 +2009,7 @@ def _points_via_singular(self, sort=True): .. note:: The Brill-Noether package does not always work (i.e., the - 'bn' algorithm. When it fails a RuntimeError exception is + 'bn' algorithm. When it fails a :class:`RuntimeError` exception is raised. """ f = self.defining_polynomial()._singular_() @@ -2150,7 +2150,7 @@ def rational_points(self, algorithm="enum", sort=True): .. NOTE:: The Brill-Noether package does not always work (i.e., the 'bn' - algorithm. When it fails a RuntimeError exception is raised. + algorithm. When it fails a :class:`RuntimeError` exception is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 8e7fb204892..5b569ae54e3 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -729,7 +729,7 @@ def lift_x(self, x, all=False, extend=False): - ``all`` (bool, default False) -- if True, return a (possibly empty) list of all points; if False, return just one point, - or raise a ValueError if there are none. + or raise a :class:`ValueError` if there are none. - ``extend`` (bool, default False) -- diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 54777488572..7f5752b9e92 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -2256,7 +2256,7 @@ def rank(self, **kwds): If the upper and lower bounds given by Simon two-descent are the same, then the rank has been uniquely identified and we - return this. Otherwise, we raise a ValueError with an error + return this. Otherwise, we raise a :class:`ValueError` with an error message specifying the upper and lower bounds. .. NOTE:: diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index e257b511371..8861f643198 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -432,7 +432,7 @@ def _non_surjective(E, patience=100): - ``list`` -- A list of primes where mod-`p` representation is very likely not surjective. At any prime not in this list, the representation is - definitely surjective. If E has CM, a ValueError is raised. + definitely surjective. If E has CM, a :class:`ValueError` is raised. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index fe07917abaa..3597123f188 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -813,14 +813,14 @@ def is_real(self): """ return self.real_flag != 0 - def is_rectangular(self): + def is_rectangular(self) -> bool: r""" - Return True if this period lattice is rectangular. + Return ``True`` if this period lattice is rectangular. .. NOTE:: - Only defined for real lattices; a RuntimeError is raised for - non-real lattices. + Only defined for real lattices; a :class:`RuntimeError` + is raised for non-real lattices. EXAMPLES:: @@ -864,8 +864,8 @@ def real_period(self, prec=None, algorithm='sage'): .. NOTE:: - Only defined for real lattices; a RuntimeError is raised for - non-real lattices. + Only defined for real lattices; a :class:`RuntimeError` + is raised for non-real lattices. EXAMPLES:: diff --git a/src/sage/tensor/modules/tensor_with_indices.py b/src/sage/tensor/modules/tensor_with_indices.py index 2e4c611b11a..8a637315af8 100644 --- a/src/sage/tensor/modules/tensor_with_indices.py +++ b/src/sage/tensor/modules/tensor_with_indices.py @@ -258,8 +258,8 @@ def _parse_indices(indices, tensor_type=None, allow_contraction=True, indices. Parse ``indices`` checking usual conventions on repeating indices, - wildcard, balanced parentheses/brackets and raises a ValueError if not. - Return a couple contravariant/covariant indices. + wildcard, balanced parentheses/brackets and raises a :class:`ValueError` + if not. Return a couple contravariant/covariant indices. INPUT: From 83813eb2d563af5b71c890712ed8f09c073fc818 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 09:13:41 -0700 Subject: [PATCH 162/225] build/pkgs/packaging/dependencies: Now depends on flit_core, not setuptools --- build/pkgs/packaging/dependencies | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/packaging/dependencies b/build/pkgs/packaging/dependencies index 17220ffcc37..b63b7e33635 100644 --- a/build/pkgs/packaging/dependencies +++ b/build/pkgs/packaging/dependencies @@ -1,4 +1,4 @@ - | setuptools pip wheel pyparsing setuptools_wheel $(PYTHON) + | flit_core pip $(PYTHON) ---------- All lines of this file are ignored except the first. From 445090863a56ddfa1a758ee7a11f45a967241f6d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 09:14:30 -0700 Subject: [PATCH 163/225] build/pkgs/flit_core: Update to 3.9.0 --- build/pkgs/flit_core/checksums.ini | 6 +++--- build/pkgs/flit_core/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/flit_core/checksums.ini b/build/pkgs/flit_core/checksums.ini index b439592878c..cf7f0bb2b55 100644 --- a/build/pkgs/flit_core/checksums.ini +++ b/build/pkgs/flit_core/checksums.ini @@ -1,5 +1,5 @@ tarball=flit_core-VERSION.tar.gz -sha1=fc82acf2a93d3bf6ce41ed1a1160f5be51ffda2a -md5=4a4791e97f3a8c9a1645064a35636ee6 -cksum=2732326458 +sha1=05d6d7a3df5bdbd9df1b37a65662e5dbe94f23fd +md5=3bc52f1952b9a78361114147da63c35b +cksum=1703912415 upstream_url=https://pypi.io/packages/source/f/flit_core/flit_core-VERSION.tar.gz diff --git a/build/pkgs/flit_core/package-version.txt b/build/pkgs/flit_core/package-version.txt index a76ccff2a6e..a5c4c763394 100644 --- a/build/pkgs/flit_core/package-version.txt +++ b/build/pkgs/flit_core/package-version.txt @@ -1 +1 @@ -3.7.1 +3.9.0 From 10d98a6e25c993f45342b0b6c1b0a2f032d1e314 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 09:15:37 -0700 Subject: [PATCH 164/225] build/pkgs/pip: Update to 23.2.1 --- build/pkgs/pip/checksums.ini | 6 +++--- build/pkgs/pip/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pip/checksums.ini b/build/pkgs/pip/checksums.ini index 1ae66fbc20a..9b6376d1abb 100644 --- a/build/pkgs/pip/checksums.ini +++ b/build/pkgs/pip/checksums.ini @@ -1,5 +1,5 @@ tarball=pip-VERSION.tar.gz -sha1=29167fffe19874a74247fe92f4fdba1bb1221c61 -md5=996f58a94fe0b8b82b6795c42bd171ba -cksum=537001443 +sha1=4bdfd8e976b5122cf55f4f4740f7305f1ffa4310 +md5=e9b1226701a56ee3fcc81aba60d25d75 +cksum=1940746834 upstream_url=https://pypi.io/packages/source/p/pip/pip-VERSION.tar.gz diff --git a/build/pkgs/pip/package-version.txt b/build/pkgs/pip/package-version.txt index 4c3dad97552..3f833b5b536 100644 --- a/build/pkgs/pip/package-version.txt +++ b/build/pkgs/pip/package-version.txt @@ -1 +1 @@ -22.3.1 +23.2.1 From 4c4458e78bffd3f597c143d8bdc4d8cee2d0f197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 20:08:29 +0200 Subject: [PATCH 165/225] from gap to libgap --- src/sage/groups/perm_gps/cubegroup.py | 43 +++++++++++++-------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/sage/groups/perm_gps/cubegroup.py b/src/sage/groups/perm_gps/cubegroup.py index 128d3beb480..4993dac2398 100644 --- a/src/sage/groups/perm_gps/cubegroup.py +++ b/src/sage/groups/perm_gps/cubegroup.py @@ -93,13 +93,12 @@ # ***************************************************************************** from sage.groups.perm_gps.permgroup import PermutationGroup_generic -import random +from random import randint from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp, richcmp_method - +from sage.libs.gap.libgap import libgap from sage.rings.real_double import RDF -from sage.interfaces.gap import gap from sage.groups.perm_gps.permgroup_element import PermutationGroupElement from sage.misc.lazy_import import lazy_import lazy_import("sage.plot.polygon", "polygon") @@ -931,19 +930,19 @@ def repr2d(self, mv): """ g = self.parse(mv) lst = self.facets(g) - line1 = " +--------------+\n" - line2 = " |%3d %3d %3d |\n"%(lst[0],lst[1],lst[2]) - line3 = " |%3d top %3d |\n"%(lst[3],lst[4]) - line4 = " |%3d %3d %3d |\n"%(lst[5],lst[6],lst[7]) - line5 = "+------------+--------------+-------------+------------+\n" - line6 = "|%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |\n"%(lst[8],lst[9],lst[10],lst[16],lst[17],lst[18],lst[24],lst[25],lst[26],lst[32],lst[33],lst[34]) - line7 = "|%3d left%3d |%3d front%3d |%3d right%3d |%3d rear%3d |\n"%(lst[11],lst[12],lst[19],lst[20],lst[27],lst[28],lst[35],lst[36]) - line8 = "|%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |%3d %3d %3d |\n"%(lst[13],lst[14],lst[15],lst[21],lst[22],lst[23],lst[29],lst[30],lst[31],lst[37],lst[38],lst[39]) - line9 = "+------------+--------------+-------------+------------+\n" - line10 = " |%3d %3d %3d |\n"%(lst[40],lst[41],lst[42]) - line11 = " |%3d bottom%3d |\n"%(lst[43],lst[44]) - line12 = " |%3d %3d %3d |\n"%(lst[45],lst[46],lst[47]) - line13 = " +--------------+\n" + line1 = " ┌──────────────┐\n" + line2 = " │%3d %3d %3d │\n"%(lst[0],lst[1],lst[2]) + line3 = " │%3d top %3d │\n"%(lst[3],lst[4]) + line4 = " │%3d %3d %3d │\n"%(lst[5],lst[6],lst[7]) + line5 = "┌────────────┼──────────────┼─────────────┬────────────┐\n" + line6 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n"%(lst[8],lst[9],lst[10],lst[16],lst[17],lst[18],lst[24],lst[25],lst[26],lst[32],lst[33],lst[34]) + line7 = "│%3d left%3d │%3d front%3d │%3d right%3d │%3d rear%3d │\n"%(lst[11],lst[12],lst[19],lst[20],lst[27],lst[28],lst[35],lst[36]) + line8 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n"%(lst[13],lst[14],lst[15],lst[21],lst[22],lst[23],lst[29],lst[30],lst[31],lst[37],lst[38],lst[39]) + line9 = "└────────────┼──────────────┼─────────────┴────────────┘\n" + line10 = " │%3d %3d %3d │\n"%(lst[40],lst[41],lst[42]) + line11 = " │%3d bottom%3d │\n"%(lst[43],lst[44]) + line12 = " │%3d %3d %3d │\n"%(lst[45],lst[46],lst[47]) + line13 = " └──────────────┘\n" return line1+line2+line3+line4+line5+line6+line7+line8+line9+line10+line11+line12+line13 def plot_cube(self, mv, title=True, colors=[lpurple, yellow, red, green, orange, blue]): @@ -1107,7 +1106,7 @@ def solve(self, state, algorithm='default'): C = RubiksCube(g) return C.solve(algorithm) - hom = self._gap_().EpimorphismFromFreeGroup() + hom = libgap(self).EpimorphismFromFreeGroup() soln = hom.PreImagesRepresentative(str(g)) sol = str(soln) names = self.gen_names() @@ -1352,8 +1351,8 @@ def cubie(self, size, gap, x, y, z, colors, stickers=True): sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3) # needs sage.plot Graphics3d Object """ - sides = cubie_face_list[x,y,z] - t = 2*size+gap + sides = cubie_face_list[x, y, z] + t = 2 * size + gap my_colors = [colors[sides[i]+6] for i in range(6)] if stickers: B = Box(size, size, size, color=(.1, .1, .1)) @@ -1377,7 +1376,7 @@ def plot3d(self, stickers=True): side_colors = [Texture(color=c, ambient=.75) for c in self.colors] start_colors = sum([[c]*8 for c in side_colors], []) facets = self._group.facets(self._state) - facet_colors = [0]*48 + facet_colors = [0] * 48 for i in range(48): facet_colors[facets[i]-1] = start_colors[i] all_colors = side_colors + facet_colors @@ -1493,7 +1492,7 @@ def solve(self, algorithm="hybrid", timeout=15): return solver.solve(self._state, algorithm="gap") else: - raise ValueError("Unrecognized algorithm: %s" % algorithm) + raise ValueError(f"Unrecognized algorithm: {algorithm}") def scramble(self, moves=30): """ @@ -1522,7 +1521,7 @@ def scramble(self, moves=30): all = [] for i in range(moves): while move[0] == last_move[0]: - move = "RLUDBF"[random.randint(0,5)] + " '2"[random.randint(0,2)] + move = "RLUDBF"[randint(0, 5)] + " '2"[randint(0, 2)] last_move = move all.append(move) return self.move(' '.join(all)) From b0811699fc83daeede9fbbda1f39925753196cb7 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 29 Sep 2023 11:08:51 -0700 Subject: [PATCH 166/225] Do not run sage-env more than once, for real. --- src/bin/sage-env | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bin/sage-env b/src/bin/sage-env index 2a63be5b7c0..5c1b4b87ac7 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -121,7 +121,8 @@ if [ "$SAGE_ENV_SOURCED" = "$SAGE_ENV_VERSION" ]; then # Already sourced, nothing to do. return 0 fi -export SAGE_ENV_SOURCED="$SAGE_ENV_VERSION" +# Set SAGE_ENV_SOURCED to the appropriate value at the end of this file, once +# $SAGE_LOCAL, $SAGE_VENV, $SAGE_SRC have been set. # The compilers are set in order of priority by # 1) environment variables @@ -643,3 +644,7 @@ fi # our doctests predictable (which was the status quo with earlier # versions of debugpy). export PYDEVD_DISABLE_FILE_VALIDATION=1 + +# Finally, set SAGE_ENV_SOURCED as evidence that this script has been +# run successfully. +export SAGE_ENV_SOURCED="6:$SAGE_LOCAL:$SAGE_VENV:$SAGE_SRC" From ccd9ec006f21704dd144f56855329bb1f5838a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 29 Sep 2023 20:47:39 +0200 Subject: [PATCH 167/225] more fixes in cubegroup.py --- src/sage/groups/perm_gps/cubegroup.py | 291 +++++++++++++------------- 1 file changed, 144 insertions(+), 147 deletions(-) diff --git a/src/sage/groups/perm_gps/cubegroup.py b/src/sage/groups/perm_gps/cubegroup.py index 4993dac2398..134c018d3c4 100644 --- a/src/sage/groups/perm_gps/cubegroup.py +++ b/src/sage/groups/perm_gps/cubegroup.py @@ -32,19 +32,19 @@ sage: rubik = CubeGroup() sage: rubik.display2d("") - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ AUTHORS: @@ -81,7 +81,7 @@ - Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996. -- Joyner,D., Adventures in Group Theory, Johns Hopkins Univ Press, +- Joyner, D., Adventures in Group Theory, Johns Hopkins Univ Press, 2002. """ @@ -112,21 +112,21 @@ ####################### predefined colors ################## named_colors = { - 'red': (1,0,0), ## F face - 'green': (0,1,0), ## R face - 'blue': (0,0,1), ## D face - 'yellow': (1,1,0), ## L face - 'white': (1,1,1), ## none - 'orange': (1,0.6,0.3), ## B face - 'purple': (1,0,1), ## none - 'lpurple': (1,0.63,1), ## U face - 'lightblue': (0,1,1), ## none - 'lgrey': (0.75,0.75,0.75), ## sagemath.org color + 'red': (1, 0, 0), ## F face + 'green': (0, 1, 0), ## R face + 'blue': (0, 0, 1), ## D face + 'yellow': (1, 1, 0), ## L face + 'white': (1, 1, 1), ## none + 'orange': (1, 0.6, 0.3), ## B face + 'purple': (1, 0, 1), ## none + 'lpurple': (1, 0.63, 1), ## U face + 'lightblue': (0, 1, 1), ## none + 'lgrey': (0.75, 0.75, 0.75), ## sagemath.org color } globals().update(named_colors) ######################################################### -#written by Tom Boothby, placed in the public domain +# written by Tom Boothby, placed in the public domain def xproj(x, y, z, r): r""" @@ -532,19 +532,19 @@ class CubeGroup(PermutationGroup_generic): sage: rubik = CubeGroup() sage: rubik.display2d("") - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ :: @@ -573,13 +573,13 @@ def __init__(self): sage: rubik.order() 43252003274489856000 """ - U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" ## U = top - L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" ## L = left - F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" ## F = front - R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" ## R = right - B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" ## B = back or rear - D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" ## D = down or bottom - PermutationGroup_generic.__init__(self, gens=[B,D,F,L,R,U], canonicalize=False) + U = "( 1, 3, 8, 6)( 2, 5, 7, 4)( 9,33,25,17)(10,34,26,18)(11,35,27,19)" # U = top + L = "( 9,11,16,14)(10,13,15,12)( 1,17,41,40)( 4,20,44,37)( 6,22,46,35)" # L = left + F = "(17,19,24,22)(18,21,23,20)( 6,25,43,16)( 7,28,42,13)( 8,30,41,11)" # F = front + R = "(25,27,32,30)(26,29,31,28)( 3,38,43,19)( 5,36,45,21)( 8,33,48,24)" # R = right + B = "(33,35,40,38)(34,37,39,36)( 3, 9,46,32)( 2,12,47,29)( 1,14,48,27)" # B = back or rear + D = "(41,43,48,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40)" # D = down or bottom + PermutationGroup_generic.__init__(self, gens=[B, D, F, L, R, U], canonicalize=False) def gen_names(self): """ @@ -836,7 +836,7 @@ def faces(self, mv): faceD = [[fcts[40],fcts[41],fcts[42]],[fcts[43],0,fcts[44]],[fcts[45],fcts[46],fcts[47]]] faceF = [[fcts[16],fcts[17],fcts[18]],[fcts[19],0,fcts[20]],[fcts[21],fcts[22],fcts[23]]] faceB = [[fcts[32],fcts[33],fcts[34]],[fcts[35],0,fcts[36]],[fcts[37],fcts[38],fcts[39]]] - return {'right':faceR,'left':faceL,'up':faceU,'down':faceD,'front':faceF,'back':faceB} + return {'right': faceR, 'left': faceL, 'up': faceU, 'down': faceD, 'front': faceF, 'back': faceB} def move(self, mv): r""" @@ -870,19 +870,19 @@ def display2d(self, mv): sage: rubik = CubeGroup() sage: rubik.display2d("R") - +--------------+ - | 1 2 38 | - | 4 top 36 | - | 6 7 33 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 3 | 27 29 32 | 48 34 35 | - | 12 left 13 | 20 front 5 | 26 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 8 | 25 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 19 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ + ┌──────────────┐ + │ 1 2 38 │ + │ 4 top 36 │ + │ 6 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 3 │ 27 29 32 │ 48 34 35 │ + │ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 8 │ 25 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 19 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ print(self.repr2d(mv)) @@ -895,53 +895,53 @@ def repr2d(self, mv): sage: rubik = CubeGroup() sage: print(rubik.repr2d("")) - +--------------+ - | 1 2 3 | - | 4 top 5 | - | 6 7 8 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | - | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | - | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 43 | - | 44 bottom 45 | - | 46 47 48 | - +--------------+ + ┌──────────────┐ + │ 1 2 3 │ + │ 4 top 5 │ + │ 6 7 8 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 19 │ 25 26 27 │ 33 34 35 │ + │ 12 left 13 │ 20 front 21 │ 28 right 29 │ 36 rear 37 │ + │ 14 15 16 │ 22 23 24 │ 30 31 32 │ 38 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 43 │ + │ 44 bottom 45 │ + │ 46 47 48 │ + └──────────────┘ :: sage: print(rubik.repr2d("R")) - +--------------+ - | 1 2 38 | - | 4 top 36 | - | 6 7 33 | - +------------+--------------+-------------+------------+ - | 9 10 11 | 17 18 3 | 27 29 32 | 48 34 35 | - | 12 left 13 | 20 front 5 | 26 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 8 | 25 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 19 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ + ┌──────────────┐ + │ 1 2 38 │ + │ 4 top 36 │ + │ 6 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 9 10 11 │ 17 18 3 │ 27 29 32 │ 48 34 35 │ + │ 12 left 13 │ 20 front 5 │ 26 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 8 │ 25 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 19 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ You can see the right face has been rotated but not the left face. """ g = self.parse(mv) lst = self.facets(g) line1 = " ┌──────────────┐\n" - line2 = " │%3d %3d %3d │\n"%(lst[0],lst[1],lst[2]) - line3 = " │%3d top %3d │\n"%(lst[3],lst[4]) - line4 = " │%3d %3d %3d │\n"%(lst[5],lst[6],lst[7]) + line2 = " │%3d %3d %3d │\n" % (lst[0], lst[1], lst[2]) + line3 = " │%3d top %3d │\n" % (lst[3], lst[4]) + line4 = " │%3d %3d %3d │\n" % (lst[5], lst[6], lst[7]) line5 = "┌────────────┼──────────────┼─────────────┬────────────┐\n" - line6 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n"%(lst[8],lst[9],lst[10],lst[16],lst[17],lst[18],lst[24],lst[25],lst[26],lst[32],lst[33],lst[34]) - line7 = "│%3d left%3d │%3d front%3d │%3d right%3d │%3d rear%3d │\n"%(lst[11],lst[12],lst[19],lst[20],lst[27],lst[28],lst[35],lst[36]) - line8 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n"%(lst[13],lst[14],lst[15],lst[21],lst[22],lst[23],lst[29],lst[30],lst[31],lst[37],lst[38],lst[39]) + line6 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n" % (lst[8], lst[9], lst[10], lst[16], lst[17], lst[18], lst[24], lst[25], lst[26], lst[32], lst[33], lst[34]) + line7 = "│%3d left%3d │%3d front%3d │%3d right%3d │%3d rear%3d │\n" % (lst[11], lst[12], lst[19], lst[20], lst[27], lst[28], lst[35], lst[36]) + line8 = "│%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │%3d %3d %3d │\n" % (lst[13], lst[14], lst[15], lst[21], lst[22], lst[23], lst[29], lst[30], lst[31], lst[37], lst[38], lst[39]) line9 = "└────────────┼──────────────┼─────────────┴────────────┘\n" - line10 = " │%3d %3d %3d │\n"%(lst[40],lst[41],lst[42]) - line11 = " │%3d bottom%3d │\n"%(lst[43],lst[44]) - line12 = " │%3d %3d %3d │\n"%(lst[45],lst[46],lst[47]) + line10 = " │%3d %3d %3d │\n" % (lst[40], lst[41], lst[42]) + line11 = " │%3d bottom%3d │\n" % (lst[43], lst[44]) + line12 = " │%3d %3d %3d │\n" % (lst[45], lst[46], lst[47]) line13 = " └──────────────┘\n" return line1+line2+line3+line4+line5+line6+line7+line8+line9+line10+line11+line12+line13 @@ -969,8 +969,8 @@ def plot_cube(self, mv, title=True, colors=[lpurple, yellow, red, green, orange, clrs = sum(cubies) + sum(centers) clrs.axes(show=False) if title: - t = text('sagemath.org', (7.8,-3.5),rgbcolor=lgrey) - P = clrs+t + t = text('sagemath.org', (7.8, -3.5),rgbcolor=lgrey) + P = clrs + t P.axes(show=False) return P return clrs @@ -1010,10 +1010,10 @@ def plot3d_cube(self, mv, title=True): P = cubeR+cubeF+cubeU+centers P.axes(show=False) if title: - t1 = text('Up, Front, and Right faces. ' , (-0.2,-2.5)) - t2 = text(' sagemath.org', (0.8,-3.1),rgbcolor=lgrey) - t3 = text(" ",(3.5,0),rgbcolor=white) - P = P+t1+t2+t3 + t1 = text('Up, Front, and Right faces. ' , (-0.2, -2.5)) + t2 = text(' sagemath.org', (0.8, -3.1),rgbcolor=lgrey) + t3 = text(" ", (3.5, 0), rgbcolor=white) + P = P + t1 + t2 + t3 P.axes(show=False) return P return P @@ -1106,12 +1106,11 @@ def solve(self, state, algorithm='default'): C = RubiksCube(g) return C.solve(algorithm) - hom = libgap(self).EpimorphismFromFreeGroup() - soln = hom.PreImagesRepresentative(str(g)) - sol = str(soln) - names = self.gen_names() - for i in range(6): - sol = sol.replace("x%s" % (i + 1), names[i]) + group = libgap(self) + hom = group.EpimorphismFromFreeGroup() + sol = str(hom.PreImagesRepresentative(libgap(g))) + for i, name in enumerate(self.gen_names()): + sol = sol.replace("x%s" % (i + 1), name) return sol @@ -1201,19 +1200,19 @@ class RubiksCube(SageObject): :: sage: C = RubiksCube("R*L"); C - +--------------+ - | 17 2 38 | - | 20 top 36 | - | 22 7 33 | - +------------+--------------+-------------+------------+ - | 11 13 16 | 41 18 3 | 27 29 32 | 48 34 6 | - | 10 left 15 | 44 front 5 | 26 right 31 | 45 rear 4 | - | 9 12 14 | 46 23 8 | 25 28 30 | 43 39 1 | - +------------+--------------+-------------+------------+ - | 40 42 19 | - | 37 bottom 21 | - | 35 47 24 | - +--------------+ + ┌──────────────┐ + │ 17 2 38 │ + │ 20 top 36 │ + │ 22 7 33 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 11 13 16 │ 41 18 3 │ 27 29 32 │ 48 34 6 │ + │ 10 left 15 │ 44 front 5 │ 26 right 31 │ 45 rear 4 │ + │ 9 12 14 │ 46 23 8 │ 25 28 30 │ 43 39 1 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 40 42 19 │ + │ 37 bottom 21 │ + │ 35 47 24 │ + └──────────────┘ sage: C.show() # needs sage.plot sage: C.solve(algorithm='gap') # long time 'L*R' @@ -1279,20 +1278,19 @@ def _repr_(self): EXAMPLES:: sage: RubiksCube().move("R*U") - +--------------+ - | 3 5 38 | - | 2 top 36 | - | 1 4 25 | - +------------+--------------+-------------+------------+ - | 33 34 35 | 9 10 8 | 19 29 32 | 48 26 27 | - | 12 left 13 | 20 front 7 | 18 right 31 | 45 rear 37 | - | 14 15 16 | 22 23 6 | 17 28 30 | 43 39 40 | - +------------+--------------+-------------+------------+ - | 41 42 11 | - | 44 bottom 21 | - | 46 47 24 | - +--------------+ - + ┌──────────────┐ + │ 3 5 38 │ + │ 2 top 36 │ + │ 1 4 25 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 33 34 35 │ 9 10 8 │ 19 29 32 │ 48 26 27 │ + │ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 6 │ 17 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 11 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ return self._group.repr2d(self._state) @@ -1502,20 +1500,19 @@ def scramble(self, moves=30): sage: C = RubiksCube() sage: C.scramble() # random - +--------------+ - | 38 29 35 | - | 20 top 42 | - | 11 44 30 | - +------------+--------------+-------------+------------+ - | 48 13 17 | 6 15 24 | 43 23 9 | 1 36 32 | - | 4 left 18 | 7 front 37 | 12 right 26 | 5 rear 10 | - | 33 31 40 | 14 28 8 | 25 47 16 | 22 2 3 | - +------------+--------------+-------------+------------+ - | 46 21 19 | - | 45 bottom 39 | - | 27 34 41 | - +--------------+ - + ┌──────────────┐ + │ 3 5 38 │ + │ 2 top 36 │ + │ 1 4 25 │ + ┌────────────┼──────────────┼─────────────┬────────────┐ + │ 33 34 35 │ 9 10 8 │ 19 29 32 │ 48 26 27 │ + │ 12 left 13 │ 20 front 7 │ 18 right 31 │ 45 rear 37 │ + │ 14 15 16 │ 22 23 6 │ 17 28 30 │ 43 39 40 │ + └────────────┼──────────────┼─────────────┴────────────┘ + │ 41 42 11 │ + │ 44 bottom 21 │ + │ 46 47 24 │ + └──────────────┘ """ last_move = move = " " all = [] From 6429f21cff81824853fc328debb8032a69e581a7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 10:25:02 -0700 Subject: [PATCH 168/225] .github/workflows/docker.yml, tox.ini: Use the commit sha before merging the CI fixes as the DOCKER_TAG --- .github/workflows/docker.yml | 18 ++++++++++++------ tox.ini | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index db4896bbd12..d49aa516356 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -179,12 +179,6 @@ jobs: (export PATH=$(pwd)/build/bin:$PATH; (cd upstream && bash -x update-pkgs.sh) && sed -i.bak '/upstream/d' .dockerignore && echo "/:toolchain:/i ADD upstream upstream" | sed -i.bak -f - build/bin/write-dockerfile.sh && git diff) if: inputs.upstream_artifact - - name: Merge CI fixes from sagemath/sage - run: | - .ci/merge-fixes.sh - env: - GH_TOKEN: ${{ github.token }} - - name: Try to login to ghcr.io if: inputs.docker_push_repository != '' # https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable @@ -197,6 +191,9 @@ jobs: echo "DOCKER_PUSH_REPOSITORY=$(echo ${{ inputs.docker_push_repository }} | tr "[:upper:]" "[:lower:]")" >> $GITHUB_ENV echo "DOCKER_CONFIG_FILE=$HOME/.docker/config.json" >> $GITHUB_ENV fi + # This line needs to be run before the step "Merge CI fixes from sagemath/sage". + DOCKER_TAG="$(git describe --dirty --always)" + echo "DOCKER_TAG=$DOCKER_TAG" >> $GITHUB_ENV # From the docker documentation via .ci/update-env.sh: # "A tag name must be valid ASCII and may # contain lowercase and uppercase letters, digits, underscores, periods and @@ -211,6 +208,15 @@ jobs: EXTRA_DOCKER_TAGS="dev $EXTRA_DOCKER_TAGS";; esac echo "EXTRA_DOCKER_TAGS=$EXTRA_DOCKER_TAGS" >> $GITHUB_ENV + + - name: Merge CI fixes from sagemath/sage + # This step needs to happen after the commit sha is put in DOCKER_TAG + # so that multi-stage builds can work correctly. + run: | + .ci/merge-fixes.sh + env: + GH_TOKEN: ${{ github.token }} + - name: Configure and build Sage distribution within a Docker container run: | set -o pipefail; EXTRA_DOCKER_BUILD_ARGS="--build-arg NUMPROC=4 --build-arg USE_MAKEFLAGS=\"-k V=0 SAGE_NUM_THREADS=3\"" tox -e $TOX_ENV -- $TARGETS 2>&1 | sed "/^configure: notice:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: warning:/s|^|::warning file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;/^configure: error:/s|^|::error file=artifacts/$LOGS_ARTIFACT_NAME/config.log::|;" diff --git a/tox.ini b/tox.ini index 39a087c1062..28a5fee6d46 100644 --- a/tox.ini +++ b/tox.ini @@ -142,6 +142,7 @@ passenv = TARGETS_OPTIONAL docker: EXTRA_DOCKER_BUILD_ARGS docker: EXTRA_DOCKER_TAGS + docker: DOCKER_TAG # Use DOCKER_BUILDKIT=1 for new version - for which unfortunately we cannot save failed builds as an image docker: DOCKER_BUILDKIT docker: BUILDKIT_INLINE_CACHE @@ -699,7 +700,7 @@ commands = docker: bash -c 'for docker_target in {env:DOCKER_TARGETS:with-targets}; do \ docker: BUILD_IMAGE_STEM=sage-$(echo {envname} | sed "s/docker-//;s/-incremental//"); \ docker: BUILD_IMAGE=$DOCKER_PUSH_REPOSITORY$BUILD_IMAGE_STEM-$docker_target; \ - docker: BUILD_TAG=$(git describe --dirty --always); \ + docker: BUILD_TAG={env:DOCKER_TAG:$(git describe --dirty --always)}; \ docker: TAG_ARGS=$(for tag in $BUILD_TAG {env:EXTRA_DOCKER_TAGS:}; do echo --tag $BUILD_IMAGE:$tag; done); \ docker: DOCKER_BUILDKIT={env:DOCKER_BUILDKIT:0} \ docker: docker build . -f {envdir}/Dockerfile \ From 8f57adb85390a48158b835503655e29e92f68c68 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 11:50:57 -0700 Subject: [PATCH 169/225] tox.ini: When setting --with-system-python3=force, always provision the python3 depcheck dependencies --- tox.ini | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 28a5fee6d46..75ffeed48c3 100644 --- a/tox.ini +++ b/tox.ini @@ -529,7 +529,11 @@ setenv = # - python # # Setting "--with-system-python3=yes" explicitly in case we change the configure default - # to "--with-system-python3=force" as originally proposed in #32060 + # to "--with-system-python3=force" as originally proposed in #32060. + # + # For all factors that set "--with-system-python3=force", + # we add "_bootstrap liblzma bzip2 libffi libpng zlib" to EXTRA_SAGE_PACKAGES_5 + # so that the configured python3 can be accepted by configure. PYTHON_MAJOR=3 PYTHON_MINOR=10 python3.9: PYTHON_MINOR=9 @@ -540,16 +544,20 @@ setenv = python3_spkg: CONFIG_CONFIGURE_ARGS_1=--without-system-python3 python3.9,python3.10,python3.11,python3.12: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python{env:PYTHON_MAJOR}.{env:PYTHON_MINOR} python3.9,python3.10,python3.11,python3.12: EXTRA_SAGE_PACKAGES_5=_python{env:PYTHON_MAJOR}.{env:PYTHON_MINOR} _bootstrap liblzma bzip2 libffi libpng zlib + # As of 2023-9, Xcode 15.0.0, this is Python 3.9.6. macos-python3_xcode: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/usr/bin/python3 - macos-{python3_xcode,nohomebrew}-{python3.8}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + macos-python3_xcode: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib + macos-{python3_xcode,nohomebrew}-{python3.9}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 # Homebrew keg installs - homebrew-{python3.9,python3.10,python3.11,python3.12}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python={env:HOMEBREW}/opt/python@{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + homebrew-{python3.9,python3.10,python3.11,python3.12}: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python={env:HOMEBREW}/opt/python@{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 # Installers from https://www.python.org/downloads/macos/ (must manually download and install) macos-python3_pythonorg: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/Library/Frameworks/Python.framework/Versions/{env:PYTHON_MAJOR}.{env:PYTHON_MINOR}/bin/python3 + macos-python3_pythonorg: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib # https://github.com/pypa/manylinux manylinux-standard: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=/opt/python/cp{env:PYTHON_MAJOR}{env:PYTHON_MINOR}-cp{env:PYTHON_MAJOR}{env:PYTHON_MINOR}/bin/python3 manylinux-{python3.9,python3.10,python3.11,python3.12}: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng conda: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python3 + conda: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib # # - toolchain # From 2356efa09d236a5aad50acbd4878c4dc4565e2cb Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 12:23:36 -0700 Subject: [PATCH 170/225] build/pkgs/_python3.*/distros/fedora.txt: Packages now include a dot - except on centos-stream-8 --- build/pkgs/_python3.10/distros/fedora.txt | 4 ++-- build/pkgs/_python3.11/distros/fedora.txt | 4 ++-- build/pkgs/_python3.12/distros/fedora.txt | 4 ++-- build/pkgs/_python3.9/distros/fedora.txt | 5 +++-- tox.ini | 2 ++ 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/build/pkgs/_python3.10/distros/fedora.txt b/build/pkgs/_python3.10/distros/fedora.txt index 90e42c91602..02cc9cf73d1 100644 --- a/build/pkgs/_python3.10/distros/fedora.txt +++ b/build/pkgs/_python3.10/distros/fedora.txt @@ -1,2 +1,2 @@ -python310 -python310-devel +python3.10 +python3.10-devel diff --git a/build/pkgs/_python3.11/distros/fedora.txt b/build/pkgs/_python3.11/distros/fedora.txt index a478404f8fb..7fe5c300aed 100644 --- a/build/pkgs/_python3.11/distros/fedora.txt +++ b/build/pkgs/_python3.11/distros/fedora.txt @@ -1,2 +1,2 @@ -python311 -python311-devel +python3.11 +python3.11-devel diff --git a/build/pkgs/_python3.12/distros/fedora.txt b/build/pkgs/_python3.12/distros/fedora.txt index b7ad10be81b..c3e29a02d27 100644 --- a/build/pkgs/_python3.12/distros/fedora.txt +++ b/build/pkgs/_python3.12/distros/fedora.txt @@ -1,2 +1,2 @@ -python312 -python312-devel +python3.12 +python3.12-devel diff --git a/build/pkgs/_python3.9/distros/fedora.txt b/build/pkgs/_python3.9/distros/fedora.txt index 046ffc713b3..c537660392d 100644 --- a/build/pkgs/_python3.9/distros/fedora.txt +++ b/build/pkgs/_python3.9/distros/fedora.txt @@ -1,2 +1,3 @@ -python39 -python39-devel +python3.9 +python3.9-devel +# Except on centos-stream-8, where it is called python39 and python3.9-devel; we special-case this in tox.ini diff --git a/tox.ini b/tox.ini index 75ffeed48c3..81ca5da421b 100644 --- a/tox.ini +++ b/tox.ini @@ -558,6 +558,8 @@ setenv = manylinux-{python3.9,python3.10,python3.11,python3.12}: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng conda: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python3 conda: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib + + centos-stream-8-python3.9: EXTRA_SYSTEM_PACKAGES=python39 python39-devel # # - toolchain # From 6c3d558ca6add713b20ba71312915b0dfb0c01a7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 13:56:52 -0700 Subject: [PATCH 171/225] build/bin/write-dockerfile.sh, .github/workflows/scan-logs.sh: Use more GH Actions output groups --- .github/workflows/scan-logs.sh | 4 ++++ build/bin/write-dockerfile.sh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scan-logs.sh b/.github/workflows/scan-logs.sh index 9cab637e850..5df32b0fc48 100755 --- a/.github/workflows/scan-logs.sh +++ b/.github/workflows/scan-logs.sh @@ -5,9 +5,13 @@ LOGS=${1-logs} for a in $(find "$LOGS" -type f -name "*.log"); do if tail -100 "$a" 2>/dev/null | grep "^[A-Za-z]*Error" >/dev/null; then echo :":"error file=$a:":" ==== ERROR IN LOG FILE $a ==== + echo "::group::$a" cat "$a" + echo "::endgroup::" elif tail -20 "$a" 2>/dev/null | grep -E "^(Warning: Error testing|^sage .*doctest.*failed)" >/dev/null; then echo :":"warning file=$a:":" ==== TESTSUITE FAILURE IN LOG FILE $a ==== + echo "::group::$a" cat "$a" + echo "::endgroup::" fi done diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 6980f6b6e4b..1d0508fe9b3 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -230,11 +230,11 @@ ARG EXTRA_CONFIGURE_ARGS="" EOF if [ ${WITH_SYSTEM_SPKG} = "force" ]; then cat < Date: Thu, 28 Sep 2023 17:15:38 -0700 Subject: [PATCH 172/225] Handle almalinux-8 like centos-8 --- build/pkgs/_python3.9/distros/fedora.txt | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/_python3.9/distros/fedora.txt b/build/pkgs/_python3.9/distros/fedora.txt index c537660392d..334e29fce37 100644 --- a/build/pkgs/_python3.9/distros/fedora.txt +++ b/build/pkgs/_python3.9/distros/fedora.txt @@ -1,3 +1,3 @@ python3.9 python3.9-devel -# Except on centos-stream-8, where it is called python39 and python3.9-devel; we special-case this in tox.ini +# Except on centos-stream-8 and almalinux-8, where it is called python39 and python39-devel; we special-case this in tox.ini diff --git a/tox.ini b/tox.ini index 81ca5da421b..be5194861ba 100644 --- a/tox.ini +++ b/tox.ini @@ -559,7 +559,7 @@ setenv = conda: CONFIG_CONFIGURE_ARGS_1=--with-system-python3=force --with-python=python3 conda: EXTRA_SAGE_PACKAGES_5=_bootstrap liblzma bzip2 libffi libpng zlib - centos-stream-8-python3.9: EXTRA_SYSTEM_PACKAGES=python39 python39-devel + {centos-stream,almalinux}-8-python3.9: EXTRA_SYSTEM_PACKAGES=python39 python39-devel # # - toolchain # From a20d61f9e7b80fb3a615863374891b9251d1d82e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 17:19:10 -0700 Subject: [PATCH 173/225] tox.ini (archlinux): Use IGNORE_MISSING_SYSTEM_PACKAGES=yes --- tox.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index be5194861ba..09bba916e14 100644 --- a/tox.ini +++ b/tox.ini @@ -328,10 +328,11 @@ setenv = gentoo: IGNORE_MISSING_SYSTEM_PACKAGES=no # # https://hub.docker.com/_/archlinux/ + # 2023-09: libgiac went missing, hence IGNORE_MISSING_SYSTEM_PACKAGES=yes # archlinux: SYSTEM=arch archlinux: BASE_IMAGE=archlinux - archlinux: IGNORE_MISSING_SYSTEM_PACKAGES=no + archlinux: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/r/vbatts/slackware # From 3f8d4cbe87894ddc6b0ca428a50718e1c5ef92d1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 28 Sep 2023 20:40:58 -0700 Subject: [PATCH 174/225] build/pkgs/freetype/distros/debian.txt: change to fix debian-sid --- build/pkgs/freetype/distros/debian.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/freetype/distros/debian.txt b/build/pkgs/freetype/distros/debian.txt index 6858a72a2d9..bde4a4c61d8 100644 --- a/build/pkgs/freetype/distros/debian.txt +++ b/build/pkgs/freetype/distros/debian.txt @@ -1 +1 @@ -libfreetype6-dev +libfreetype-dev From f83da2e916f8d1bc70342b7aefd5031e47700fa7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 22:01:30 -0700 Subject: [PATCH 175/225] tox.ini (debian-buster): Use IGNORE_MISSING_SYSTEM_PACKAGES=yes --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 09bba916e14..f0d8a5578a5 100644 --- a/tox.ini +++ b/tox.ini @@ -227,6 +227,7 @@ setenv = ubuntu-mantic: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/_/debian + # debian-buster does not have libfreetype-dev (it only has libfreetype6-dev) # debian-bullseye does not have libgiac-dev # debian-trixie does not have libbrial-dev # @@ -237,6 +238,7 @@ setenv = debian-stretch: BASE_TAG=stretch debian-stretch: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-buster: BASE_TAG=buster + debian-buster: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-bullseye: BASE_TAG=bullseye debian-bullseye: IGNORE_MISSING_SYSTEM_PACKAGES=yes debian-bookworm: BASE_TAG=bookworm From 0366627bd693ab56762e83317d356dd71fc18f3c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 22:45:30 -0700 Subject: [PATCH 176/225] build/pkgs/{pkgconf,_bootstrap}/distros/arch.txt: Update --- build/pkgs/_bootstrap/distros/arch.txt | 3 +-- build/pkgs/pkgconf/distros/arch.txt | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 build/pkgs/pkgconf/distros/arch.txt diff --git a/build/pkgs/_bootstrap/distros/arch.txt b/build/pkgs/_bootstrap/distros/arch.txt index 96fe92340d9..33054ef918c 100644 --- a/build/pkgs/_bootstrap/distros/arch.txt +++ b/build/pkgs/_bootstrap/distros/arch.txt @@ -1,4 +1,3 @@ # Packages needed for ./bootstrap autoconf automake libtool -# Otherwise: Error: could not locate the pkg-config autoconf macros. These are -pkg-config +pkgconf diff --git a/build/pkgs/pkgconf/distros/arch.txt b/build/pkgs/pkgconf/distros/arch.txt new file mode 100644 index 00000000000..05a1a221b7d --- /dev/null +++ b/build/pkgs/pkgconf/distros/arch.txt @@ -0,0 +1 @@ +pkgconf From de726e5122f5e4af26bc95aa3bac945d9471e52d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 30 Sep 2023 12:00:29 +0200 Subject: [PATCH 177/225] suggested details --- src/sage/matrix/matrix_integer_dense.pyx | 10 ++++---- src/sage/modular/abvar/abvar.py | 29 ++++++++++++++---------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index d4d2819c13c..30d76200bb6 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -1706,14 +1706,14 @@ cdef class Matrix_integer_dense(Matrix_dense): def symplectic_form(self): r""" - Find a symplectic basis for self if self is an anti-symmetric, + Find a symplectic basis for ``self`` if ``self`` is an anti-symmetric, alternating matrix. Return a pair (F, C) such that the rows of C form a symplectic - basis for self and ``F = C * self * C.transpose()``. + basis for ``self`` and ``F = C * self * C.transpose()``. - Raise a :class:`ValueError` if self is not anti-symmetric, - or self is not alternating. + Raise a :class:`ValueError` if ``self`` is not anti-symmetric, + or ``self`` is not alternating. Anti-symmetric means that `M = -M^t`. Alternating means that the diagonal of `M` is identically zero. @@ -1722,7 +1722,7 @@ cdef class Matrix_integer_dense(Matrix_dense): `e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k` such that - - `z_i M v^t` = 0 for all vectors `v` + - `z_i M v^t = 0` for all vectors `v` - `e_i M {e_j}^t = 0` for all `i, j` diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index 7d46f6a36bb..818e7cf1a85 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -525,15 +525,17 @@ def label(self) -> str: def newform(self, names=None): """ Return the newform `f` such that this abelian variety is isogenous to - the newform abelian variety `A_f`. If this abelian variety is not - simple, raise a ``ValueError``. + the newform abelian variety `A_f`. + + If this abelian variety is not + simple, this raises a :class:`ValueError`. INPUT: - - ``names`` -- (default: None) If the newform has coefficients in a - number field, then a generator name must be specified. + - ``names`` -- (default: ``None``) If the newform has coefficients + in a number field, then a generator name must be specified. - OUTPUT: A newform `f` so that self is isogenous to `A_f`. + OUTPUT: A newform `f` so that ``self`` is isogenous to `A_f`. EXAMPLES:: @@ -3237,22 +3239,25 @@ def degen_t(self, none_if_not_known=False): def isogeny_number(self, none_if_not_known=False): """ Return the number (starting at 0) of the isogeny class of new - simple abelian varieties that self is in. If self is not simple, - raises a :class:`ValueError` exception. + simple abelian varieties that ``self`` is in. + + If ``self`` is not simple, + this raises a :class:`ValueError` exception. INPUT: - - ``none_if_not_known`` -- bool (default: False); if - True then this function may return None instead of True of False if - we don't already know the isogeny number of self. + - ``none_if_not_known`` -- bool (default: ``False``); if + ``True`` then this function may return ``None`` instead of ``True`` + or ``False`` if + we do not already know the isogeny number of ``self``. - EXAMPLES: We test the none_if_not_known flag first:: + EXAMPLES: We test the ``none_if_not_known`` flag first:: sage: J0(33).isogeny_number(none_if_not_known=True) is None True Of course, `J_0(33)` is not simple, so this function - raises a ValueError:: + raises a :class:`ValueError`:: sage: J0(33).isogeny_number() Traceback (most recent call last): From def59aefc2811e559920fd2dde4e9d8c9f3acbb7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 10:11:54 -0700 Subject: [PATCH 178/225] tox.ini (ubuntu-lunar,mantic): Remove IGNORE_MISSING_SYSTEM_PACKAGES; all standard packages are available --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index f0d8a5578a5..40b5fd2489b 100644 --- a/tox.ini +++ b/tox.ini @@ -222,9 +222,7 @@ setenv = ubuntu-focal: BASE_TAG=focal ubuntu-jammy: BASE_TAG=jammy ubuntu-lunar: BASE_TAG=lunar - ubuntu-lunar: IGNORE_MISSING_SYSTEM_PACKAGES=yes ubuntu-mantic: BASE_TAG=mantic - ubuntu-mantic: IGNORE_MISSING_SYSTEM_PACKAGES=yes # # https://hub.docker.com/_/debian # debian-buster does not have libfreetype-dev (it only has libfreetype6-dev) From 041b35fff35337bc4c6ee91c881df580a1c8cbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 30 Sep 2023 21:19:06 +0200 Subject: [PATCH 179/225] partial cython-lint cleanup in padics/ --- src/sage/rings/padics/CA_template.pxi | 12 +++++----- src/sage/rings/padics/CR_template.pxi | 17 ++++++------- src/sage/rings/padics/FM_template.pxi | 10 ++++---- src/sage/rings/padics/FP_template.pxi | 20 ++++++++-------- .../rings/padics/local_generic_element.pyx | 5 ++-- src/sage/rings/padics/morphism.pxd | 2 +- src/sage/rings/padics/morphism.pyx | 1 - .../rings/padics/padic_ZZ_pX_CA_element.pyx | 19 ++++++++------- .../rings/padics/padic_ZZ_pX_CR_element.pyx | 15 ++++-------- .../rings/padics/padic_ZZ_pX_FM_element.pyx | 24 +++++++++---------- src/sage/rings/padics/padic_ZZ_pX_element.pyx | 3 +-- .../padics/padic_capped_relative_element.pyx | 1 + src/sage/rings/padics/padic_printing.pyx | 13 ++++------ .../rings/padics/padic_relaxed_errors.pyx | 20 ++++++++-------- .../rings/padics/padic_template_element.pxi | 19 +++++++-------- src/sage/rings/padics/pow_computer.pyx | 13 ++++------ src/sage/rings/padics/pow_computer_ext.pxd | 1 - src/sage/rings/padics/pow_computer_ext.pyx | 7 +----- .../rings/padics/pow_computer_relative.pyx | 8 ++++--- src/sage/rings/padics/qadic_flint_FP.pyx | 1 - src/sage/rings/padics/relaxed_template.pxi | 13 +++++----- 21 files changed, 104 insertions(+), 120 deletions(-) diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index d821b5c1576..152db86eaf9 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -89,7 +89,7 @@ cdef class CAElement(pAdicTemplateElement): self.absprec = aprec else: self.absprec = min(aprec, val + rprec) - if isinstance(x,CAElement) and x.parent() is self.parent(): + if isinstance(x, CAElement) and x.parent() is self.parent(): cshift_notrunc(self.value, (x).value, 0, self.absprec, self.prime_pow, True) else: cconv(self.value, x, self.absprec, 0, self.prime_pow) @@ -395,9 +395,8 @@ cdef class CAElement(pAdicTemplateElement): creduce(q.value, q.value, q.absprec, q.prime_pow) return q, r - def __pow__(CAElement self, _right, dummy): - """ + r""" Exponentiation. When ``right`` is divisible by `p` then one can get more @@ -474,8 +473,8 @@ cdef class CAElement(pAdicTemplateElement): return base.__pow__(-_right, dummy) exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -861,6 +860,7 @@ cdef class CAElement(pAdicTemplateElement): """ def tuple_recursive(l): return tuple(tuple_recursive(x) for x in l) if isinstance(l, Iterable) else l + return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.precision_absolute()) def _teichmuller_set_unsafe(self): @@ -1800,6 +1800,7 @@ cdef class pAdicConvert_CA_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_cae_v2(cls, parent, value, absprec): r""" Unpickle capped absolute elements. @@ -1834,4 +1835,3 @@ def unpickle_cae_v2(cls, parent, value, absprec): cunpickle(ans.value, value, ans.prime_pow) ans.absprec = absprec return ans - diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index 863c612587c..57ab352a66f 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -145,7 +145,7 @@ cdef class CRElement(pAdicTemplateElement): else: self.relprec = min(rprec, aprec - val) self.ordp = val - if isinstance(x,CRElement) and x.parent() is self.parent(): + if isinstance(x, CRElement) and x.parent() is self.parent(): cshift_notrunc(self.unit, (x).unit, 0, self.relprec, self.prime_pow, True) else: cconv(self.unit, x, self.relprec, val, self.prime_pow) @@ -678,8 +678,8 @@ cdef class CRElement(pAdicTemplateElement): return base.__pow__(-_right, dummy) exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -732,7 +732,7 @@ cdef class CRElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies by `\pi^{\mbox{shift}}`. Negative shifts may truncate the result if the parent is not a @@ -763,7 +763,7 @@ cdef class CRElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by ``\pi^{\mbox{shift}}``. Positive shifts may truncate the result if the parent is not a @@ -879,7 +879,6 @@ cdef class CRElement(pAdicTemplateElement): q._normalize() return q, r - def add_bigoh(self, absprec): """ Return a new element with absolute precision decreased to @@ -1253,6 +1252,7 @@ cdef class CRElement(pAdicTemplateElement): """ def tuple_recursive(l): return tuple(tuple_recursive(x) for x in l) if isinstance(l, list) else l + return (self.parent(), tuple_recursive(trim_zeros(list(self.expansion()))), self.valuation(), self.precision_relative()) def _teichmuller_set_unsafe(self): @@ -1506,7 +1506,7 @@ cdef class CRElement(pAdicTemplateElement): """ # Since we keep this element normalized there's not much to do here. if p is not None and p != self.parent().prime(): - raise ValueError('ring (%s) residue field of the wrong characteristic'%self.parent()) + raise ValueError('ring (%s) residue field of the wrong characteristic' % self.parent()) if exactzero((self).ordp): raise ValueError("unit part of 0 not defined") cdef Integer val = Integer.__new__(Integer) @@ -1968,7 +1968,7 @@ cdef class pAdicConvert_CR_QQ(RingMap): 1/5 """ cdef Rational ans = Rational.__new__(Rational) - cdef CRElement x = _x + cdef CRElement x = _x if x.relprec == 0: mpq_set_ui(ans.value, 0, 1) else: @@ -2522,6 +2522,7 @@ cdef class pAdicConvert_CR_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_cre_v2(cls, parent, unit, ordp, relprec): """ Unpickles a capped relative element. diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index 3bae827a08c..e319255a85c 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -84,7 +84,7 @@ cdef class FMElement(pAdicTemplateElement): polyt = type(self.prime_pow.modulus) self.value = polyt.__new__(polyt) cconstruct(self.value, self.prime_pow) - if isinstance(x,FMElement) and x.parent() is self.parent(): + if isinstance(x, FMElement) and x.parent() is self.parent(): cshift_notrunc(self.value, (x).value, 0, 0, self.prime_pow, False) else: cconv(self.value, x, self.prime_pow.ram_prec_cap, 0, self.prime_pow) @@ -346,7 +346,6 @@ cdef class FMElement(pAdicTemplateElement): creduce(q.value, q.value, pcap, q.prime_pow) return q, r - def __pow__(FMElement self, _right, dummy): # NOTE: dummy ignored, always use self.prime_pow.ram_prec_cap """ Exponentiation by an integer @@ -381,7 +380,7 @@ cdef class FMElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies self by `\pi^{shift}`. If shift < -self.valuation(), digits will be truncated. See @@ -428,7 +427,7 @@ cdef class FMElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by `\pi^{shift}`, and truncates. Note that this operation will insert arbitrary digits (in @@ -462,7 +461,7 @@ cdef class FMElement(pAdicTemplateElement): return ans def add_bigoh(self, absprec): - """ + r""" Return a new element truncated modulo `\pi^{\mbox{absprec}}`. INPUT: @@ -1542,6 +1541,7 @@ cdef class pAdicConvert_FM_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_fme_v2(cls, parent, value): """ Unpickles a fixed-mod element. diff --git a/src/sage/rings/padics/FP_template.pxi b/src/sage/rings/padics/FP_template.pxi index d253d208410..695e66e2712 100644 --- a/src/sage/rings/padics/FP_template.pxi +++ b/src/sage/rings/padics/FP_template.pxi @@ -142,7 +142,7 @@ cdef class FPElement(pAdicTemplateElement): self._set_infinity() else: self.ordp = val - if isinstance(x,FPElement) and x.parent() is self.parent(): + if isinstance(x, FPElement) and x.parent() is self.parent(): ccopy(self.unit, (x).unit, self.prime_pow) else: cconv(self.unit, x, self.prime_pow.ram_prec_cap, val, self.prime_pow) @@ -584,7 +584,6 @@ cdef class FPElement(pAdicTemplateElement): q._normalize() return q, r - def __pow__(FPElement self, _right, dummy): # NOTE: dummy ignored, always use self.prime_pow.ram_prec_cap """ Exponentiation by an integer @@ -624,8 +623,8 @@ cdef class FPElement(pAdicTemplateElement): _right = -_right exact_exp = True elif self.parent() is _right.parent(): - ## For extension elements, we need to switch to the - ## fraction field sometimes in highly ramified extensions. + # For extension elements, we need to switch to the + # fraction field sometimes in highly ramified extensions. exact_exp = (_right)._is_exact_zero() pright = _right else: @@ -665,7 +664,7 @@ cdef class FPElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _lshift_c(self, long shift): - """ + r""" Multiplies self by `\pi^{shift}`. Negative shifts may truncate the result if the parent is not a @@ -718,7 +717,7 @@ cdef class FPElement(pAdicTemplateElement): return ans cdef pAdicTemplateElement _rshift_c(self, long shift): - """ + r""" Divides by `\pi^{shift}`. Positive shifts may truncate the result if the parent is not a @@ -772,7 +771,7 @@ cdef class FPElement(pAdicTemplateElement): def _repr_(self, mode=None, do_latex=False): """ - Returns a string representation of this element. + Return a string representation of this element. INPUT: @@ -794,7 +793,7 @@ cdef class FPElement(pAdicTemplateElement): return self.parent()._printer.repr_gen(self, do_latex, mode=mode) def add_bigoh(self, absprec): - """ + r""" Return a new element truncated modulo `\pi^{\mbox{absprec}}`. INPUT: @@ -1221,7 +1220,7 @@ cdef class FPElement(pAdicTemplateElement): ValueError: unit part of 0 and infinity not defined """ if p is not None and p != self.parent().prime(): - raise ValueError('Ring (%s) residue field of the wrong characteristic.'%self.parent()) + raise ValueError('Ring (%s) residue field of the wrong characteristic.' % self.parent()) if huge_val(self.ordp): raise ValueError("unit part of 0 and infinity not defined") cdef Integer valuation = PY_NEW(Integer) @@ -1659,7 +1658,7 @@ cdef class pAdicConvert_FP_QQ(RingMap): 1/5 """ cdef Rational ans = Rational.__new__(Rational) - cdef FPElement x = _x + cdef FPElement x = _x if very_pos_val(x.ordp): mpq_set_ui(ans.value, 0, 1) elif very_neg_val(x.ordp): @@ -2140,6 +2139,7 @@ cdef class pAdicConvert_FP_frac_field(Morphism): self._zero = _slots['_zero'] Morphism._update_slots(self, _slots) + def unpickle_fpe_v2(cls, parent, unit, ordp): """ Unpickles a floating point element. diff --git a/src/sage/rings/padics/local_generic_element.pyx b/src/sage/rings/padics/local_generic_element.pyx index 6c78114f395..97d608ca464 100644 --- a/src/sage/rings/padics/local_generic_element.pyx +++ b/src/sage/rings/padics/local_generic_element.pyx @@ -394,8 +394,9 @@ cdef class LocalGenericElement(CommutativeRingElement): unramified_generator = self.parent()(self.parent().residue_field().gen()).lift_to_precision() for c in islice(self.expansion(lift_mode=lift_mode), int(start), int(stop), int(k)): genpow = 1 - if not isinstance(c, list): c = [c] # relevant for the case of base-rings, or one-step - # eisenstein extensions + if not isinstance(c, list): + c = [c] # relevant for the case of base-rings, or one-step + # eisenstein extensions for d in c: ans += d * genpow * ppow genpow *= unramified_generator diff --git a/src/sage/rings/padics/morphism.pxd b/src/sage/rings/padics/morphism.pxd index acb6ebb98d5..b6afedd2377 100644 --- a/src/sage/rings/padics/morphism.pxd +++ b/src/sage/rings/padics/morphism.pxd @@ -7,4 +7,4 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): cdef long _power cdef long _order - cpdef Element _call_(self,x) + cpdef Element _call_(self, x) diff --git a/src/sage/rings/padics/morphism.pyx b/src/sage/rings/padics/morphism.pyx index 73ae1d53471..b29fc204b43 100644 --- a/src/sage/rings/padics/morphism.pyx +++ b/src/sage/rings/padics/morphism.pyx @@ -157,7 +157,6 @@ cdef class FrobeniusEndomorphism_padics(RingHomomorphism): sage: Frob._repr_short() 'Frob' """ - name = self.domain().variable_name() if self._power == 0: s = "Identity" elif self._power == 1: diff --git a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx index 979f9d54ba5..0f5270a9980 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CA_element.pyx @@ -1237,7 +1237,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef long self_ordp = self.valuation_c() cdef long self_relprec = self.absprec - self_ordp cdef long threshold # e / (p-1) - cdef long prime_long cdef mpz_t tmp, tmp2 if mpz_fits_slong_p(self.prime_pow.prime.value) == 0: threshold = 0 @@ -1399,7 +1398,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ cdef pAdicZZpXCAElement right = _right cdef pAdicZZpXCAElement ans - cdef long tmpL cdef ZZ_pX_c tmpP if self.absprec == 0 or right.absprec == 0: return self._new_c(0) @@ -1441,7 +1439,6 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ cdef pAdicZZpXCAElement right = _right cdef pAdicZZpXCAElement ans - cdef long tmpL cdef ZZ_pX_c tmpP if self.absprec == 0 or right.absprec == 0: return self._new_c(0) @@ -1824,7 +1821,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): True """ cdef pAdicZZpXCAElement ans - cdef long aprec, rprec + cdef long aprec if absprec is not None and not isinstance(absprec, Integer): absprec = Integer(absprec) if absprec is None: @@ -1977,9 +1974,9 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.absprec) cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() L.extend(curlist + [zero]*(n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) @@ -2071,7 +2068,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): cdef long ordp = self.valuation_c() cdef long rp = self.absprec - ordp cdef long goal - if n is not None: goal = self.absprec - n + if n is not None: + goal = self.absprec - n cdef pAdicZZpXCAElement v if n is None: L = [] @@ -2084,7 +2082,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): else: v = self._new_c(rp) cdef pAdicZZpXCAElement u = self.unit_part() - if u is self: u = self.__copy__() + if u is self: + u = self.__copy__() while not ZZ_pX_IsZero(u.value): v = self._new_c(rp) self.prime_pow.teichmuller_set_c(&v.value, &u.value, rp) @@ -2092,7 +2091,8 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): L.append(v) elif rp == goal: return v - if rp == 1: break + if rp == 1: + break ZZ_pX_sub(u.value, u.value, v.value) rp -= 1 if self.prime_pow.e == 1: @@ -2319,6 +2319,7 @@ cdef class pAdicZZpXCAElement(pAdicZZpXElement): """ return self.ext_p_list_precs(pos, self.absprec) + def make_ZZpXCAElement(parent, value, absprec, version): """ For pickling. Makes a ``pAdicZZpXCAElement`` with given ``parent``, ``value``, ``absprec``. diff --git a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx index e3bd45e9037..8a8828a5712 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -1415,13 +1415,9 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): sage: z * 25 3 + O(w^6) """ - cdef ZZ_pX_c high_shifter, high_shifter2 + cdef ZZ_pX_c high_shifter cdef ZZ_pX_Modulus_c *modulus - cdef ZZ_pX_Modulus_c modulus_up cdef ntl_ZZ_pContext_class c - cdef PowComputer_ZZ_pX_small_Eis sm - cdef PowComputer_ZZ_pX_big_Eis big - cdef ntl_ZZ_pX printer cdef ZZ_pX_c* high_array cdef long i, high_length if self.prime_pow.e == 1: @@ -1922,7 +1918,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): cdef long exp_val cdef long relprec cdef long threshold # e / (p-1) - cdef long prime_long cdef mpz_t tmp, tmp2 if mpz_fits_slong_p(self.prime_pow.prime.value) == 0: threshold = 0 @@ -2212,7 +2207,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): """ cdef pAdicZZpXCRElement right = _right cdef ZZ_pX_c modulus_corrected - cdef ntl_ZZ_pContext_class ctx cdef pAdicZZpXCRElement ans if self._is_exact_zero(): return self @@ -2805,7 +2799,6 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): return zero elif n >= self.ordp + self.relprec: raise PrecisionError - cdef Integer ordp if self.relprec == 0: # cannot have n = None return [] if lift_mode == 'simple': @@ -2881,11 +2874,11 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.ordp + self.relprec) cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() - L.extend(curlist + [zero]*(n - len(curlist))) + L.extend(curlist + [zero] * (n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) return matrix(R, n, n, L) diff --git a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx index 9dec3affd53..ec5e833662f 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -197,7 +197,6 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): pAdicZZpXElement.__init__(self, parent) if empty: return - cdef mpz_t tmp cdef ZZ_c tmp_z cdef Integer tmp_Int cdef Py_ssize_t i @@ -241,7 +240,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): poly = x.polynomial().list() x = sum([poly[i].lift() * (z ** i) for i in range(len(poly))], parent.zero()) elif isinstance(x, ntl_ZZ_p): - ctx_prec = ZZ_remove(tmp_z, (x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0]) + ZZ_remove(tmp_z, (x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0]) if ZZ_IsOne(tmp_z): x = x.lift() tmp_Int = Integer.__new__(Integer) @@ -613,12 +612,9 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): """ if n < 0: return self._lshift_c(-n) - elif n == 0: + if n == 0: return self cdef pAdicZZpXFMElement ans = self._new_c() - cdef Py_ssize_t i - cdef long topcut, rem - cdef ntl_ZZ holder if n < self.prime_pow.ram_prec_cap: if self.prime_pow.e == 1: ZZ_pX_right_pshift(ans.value, self.value, self.prime_pow.pow_ZZ_tmp(n)[0], self.prime_pow.get_top_context().x) @@ -1034,9 +1030,9 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_top_modulus() cdef ZZ_pX_c x ZZ_pX_SetX(x) - cdef Py_ssize_t i, j + cdef Py_ssize_t i zero = int(0) - for i from 0 <= i < n: + for i in range(n): curlist = cur.list() L.extend(curlist + [zero]*(n - len(curlist))) ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0]) @@ -1443,7 +1439,8 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): cdef long ordp = self.valuation_c() cdef long rp = self.prime_pow.ram_prec_cap - ordp cdef long goal - if n is not None: goal = self.ram_prec_cap - n + if n is not None: + goal = self.ram_prec_cap - n cdef pAdicZZpXFMElement v if n is None: L = [] @@ -1454,15 +1451,18 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): else: v = self._new_c() cdef pAdicZZpXFMElement u = self.unit_part() - if u is self: u = self.__copy__() + if u is self: + u = self.__copy__() while u.valuation_c() < rp: - if n is None: v = self._new_c() + if n is None: + v = self._new_c() self.prime_pow.teichmuller_set_c(&v.value, &u.value, self.prime_pow.ram_prec_cap) if n is None: L.append(v) elif rp == goal: return v - if rp == 1: break + if rp == 1: + break ZZ_pX_sub(u.value, u.value, v.value) rp -= 1 if self.prime_pow.e == 1: diff --git a/src/sage/rings/padics/padic_ZZ_pX_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_element.pyx index b0beaa85617..b23f010edde 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_element.pyx @@ -284,7 +284,6 @@ cdef class pAdicZZpXElement(pAdicExtElement): cdef Integer list_elt cdef ZZ_c halfp cdef Py_ssize_t i, j - cdef ZZ_p_c const_term_holder self.prime_pow.restore_top_context() ###ZZ_p_construct(&const_term_holder) cdef ntl_ZZ holder = ntl_ZZ() @@ -621,6 +620,7 @@ def _test_preprocess_list(R, L): """ return preprocess_list(R(0), L) + cdef preprocess_list(pAdicZZpXElement elt, L): """ See the documentation for :func:`_test_preprocess_list`. @@ -630,7 +630,6 @@ cdef preprocess_list(pAdicZZpXElement elt, L): cdef ntl_ZZ_pContext_class ctx cdef ntl_ZZ pshift_z cdef Integer pshift_m - cdef long aprec cdef ntl_ZZ py_tmp if not isinstance(L, list): raise TypeError("L must be a list") diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index f09708db2c7..10db90d1342 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -576,6 +576,7 @@ def unpickle_pcre_v1(R, unit, ordp, relprec): """ return unpickle_cre_v2(pAdicCappedRelativeElement, R, unit, ordp, relprec) + def base_p_list(Integer n, bint pos, PowComputer_class prime_pow): r""" Return a base-`p` list of digits of ``n``. diff --git a/src/sage/rings/padics/padic_printing.pyx b/src/sage/rings/padics/padic_printing.pyx index 344a1e544a7..aef767034a8 100644 --- a/src/sage/rings/padics/padic_printing.pyx +++ b/src/sage/rings/padics/padic_printing.pyx @@ -928,7 +928,6 @@ cdef class pAdicPrinter_class(SageObject): sage: repr(R(0,10)) '...0000000000' """ - cdef Py_ssize_t i s = "" if self.show_prec == "dots": unknown_digit = "?" @@ -1063,10 +1062,8 @@ cdef class pAdicPrinter_class(SageObject): """ cdef Integer lift_z, pprec cdef int ZZ_pEX - cdef Py_ssize_t i, j + cdef Py_ssize_t i cdef long val - #cdef bint ellipsis = 0 - cdef ellipsis_unram cdef bint integral var_name = self.latex_var_name if do_latex else self.var_name if self.base: @@ -1200,10 +1197,10 @@ cdef class pAdicPrinter_class(SageObject): s += " - " s += self._var(var_name, i, do_latex) else: - s += " - %s"%(arep) + s += " - %s" % (arep) s += self._dot_var(var_name, i, do_latex) elif a == pk: - if s != "": + if s: s += " + " s += self._var(var_name, i, do_latex) else: @@ -1211,9 +1208,9 @@ cdef class pAdicPrinter_class(SageObject): v, u = a.val_unit(self.prime_pow.prime) arep = self._terse_frac(a, v, u, ram_name, do_latex) if s == "": - s = "%s"%arep + s = "%s" % arep else: - s += " + %s"%arep + s += " + %s" % arep s += self._dot_var(var_name, i, do_latex) if ellipsis: s += self._plus_ellipsis(do_latex) diff --git a/src/sage/rings/padics/padic_relaxed_errors.pyx b/src/sage/rings/padics/padic_relaxed_errors.pyx index ddadb111ca9..2157234f62b 100644 --- a/src/sage/rings/padics/padic_relaxed_errors.pyx +++ b/src/sage/rings/padics/padic_relaxed_errors.pyx @@ -5,23 +5,23 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ # **************************************************************************** from sage.rings.padics.precision_error import PrecisionError -cdef inline int ERROR_ABANDON = 1 -cdef inline int ERROR_NOTDEFINED = 1 << 1 -cdef inline int ERROR_PRECISION = 1 << 2 -cdef inline int ERROR_OVERFLOW = 1 << 3 -cdef inline int ERROR_NOTSQUARE = 1 << 4 # maybe we should have something more generic here -cdef inline int ERROR_INTEGRAL = 1 << 5 -cdef inline int ERROR_DIVISION = 1 << 6 -cdef inline int ERROR_CIRCULAR = 1 << 7 +cdef inline int ERROR_ABANDON = 1 +cdef inline int ERROR_NOTDEFINED = 1 << 1 +cdef inline int ERROR_PRECISION = 1 << 2 +cdef inline int ERROR_OVERFLOW = 1 << 3 +cdef inline int ERROR_NOTSQUARE = 1 << 4 # maybe we should have something more generic here +cdef inline int ERROR_INTEGRAL = 1 << 5 +cdef inline int ERROR_DIVISION = 1 << 6 +cdef inline int ERROR_CIRCULAR = 1 << 7 -cdef inline int ERROR_UNEXPECTED = 1 << 30 +cdef inline int ERROR_UNEXPECTED = 1 << 30 def raise_error(error, permissive=False): diff --git a/src/sage/rings/padics/padic_template_element.pxi b/src/sage/rings/padics/padic_template_element.pxi index 06cc00e73f0..06d65d1672c 100644 --- a/src/sage/rings/padics/padic_template_element.pxi +++ b/src/sage/rings/padics/padic_template_element.pxi @@ -146,7 +146,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): x = [x] elif sage.rings.finite_rings.integer_mod.is_IntegerMod(x): if not Integer(self.prime_pow.prime).divides(x.parent().order()): - raise TypeError("p does not divide modulus %s"%x.parent().order()) + raise TypeError("p does not divide modulus %s" % x.parent().order()) elif isinstance(x, Element) and isinstance(x.parent(), FiniteField): k = self.parent().residue_field() if not k.has_coerce_map_from(x.parent()): @@ -624,7 +624,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): return trim_zeros(list(self.unit_part().expansion(lift_mode='smallest'))) cpdef pAdicTemplateElement unit_part(self): - """ + r""" Returns the unit part of this element. This is the `p`-adic element `u` in the same ring so that this @@ -739,7 +739,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): if check_prec and (R.is_fixed_mod() or R.is_floating_point()): check_prec = False if check_prec and absprec > self.precision_absolute(): - raise PrecisionError("insufficient precision to reduce modulo p^%s"%absprec) + raise PrecisionError("insufficient precision to reduce modulo p^%s" % absprec) if field and absprec != 1: raise ValueError("field keyword may only be set at precision 1") if absprec == 0: @@ -834,15 +834,15 @@ cdef long padic_pow_helper(celement result, celement base, long base_val, long b """ if base_val != 0: raise ValueError("in order to raise to a p-adic exponent, base must be a unit") - ####### NOTE: this function needs to be updated for extension elements. ####### + # TODO NOTE: this function needs to be updated for extension elements. cdef long loga_val, loga_aprec, bloga_val, bloga_aprec cdef Integer expcheck, right cteichmuller(prime_pow.powhelper_oneunit, base, base_relprec, prime_pow) cdivunit(prime_pow.powhelper_oneunit, base, prime_pow.powhelper_oneunit, base_relprec, prime_pow) csetone(prime_pow.powhelper_teichdiff, prime_pow) csub(prime_pow.powhelper_teichdiff, prime_pow.powhelper_oneunit, prime_pow.powhelper_teichdiff, base_relprec, prime_pow) - ## For extension elements in ramified extensions, the computation of the - ## valuation and precision of log(a) is more complicated) + # For extension elements in ramified extensions, the computation of the + # valuation and precision of log(a) is more complicated) loga_val = cvaluation(prime_pow.powhelper_teichdiff, base_relprec, prime_pow) loga_aprec = base_relprec # valuation of b*log(a) @@ -862,8 +862,8 @@ cdef long padic_pow_helper(celement result, celement base, long base_val, long b # Here we need to use the exp(b log(a)) definition, # since we can't convert the exponent to an integer raise NotImplementedError("exponents with negative valuation not yet supported") - ## For extension elements in ramified extensions - ## the following precision might need to be changed. + # For extension elements in ramified extensions + # the following precision might need to be changed. cpow(result, prime_pow.powhelper_oneunit, right.value, bloga_aprec, prime_pow) return bloga_aprec @@ -1185,5 +1185,4 @@ cdef class ExpansionIterable(): else: modestr = " (teichmuller)" p = self.elt.prime_pow.prime - return "%s-adic expansion of %s%s"%(p, self.elt, modestr) - + return "%s-adic expansion of %s%s" % (p, self.elt, modestr) diff --git a/src/sage/rings/padics/pow_computer.pyx b/src/sage/rings/padics/pow_computer.pyx index 1c5bdf86897..4c05f1886b5 100644 --- a/src/sage/rings/padics/pow_computer.pyx +++ b/src/sage/rings/padics/pow_computer.pyx @@ -35,7 +35,7 @@ AUTHORS: # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # -# http://www.gnu.org/licenses/ +# https://www.gnu.org/licenses/ #***************************************************************************** import weakref @@ -186,7 +186,6 @@ cdef class PowComputer_class(SageObject): 59049 """ cdef Integer _n = Integer(n) - cdef Integer ans if _n < 0: if mpz_fits_ulong_p((-_n).value) == 0: raise ValueError("result too big") @@ -210,7 +209,7 @@ cdef class PowComputer_class(SageObject): See pow_mpz_t_tmp_demo for an example of this phenomenon. """ - ## READ THE DOCSTRING + # READ THE DOCSTRING raise NotImplementedError def _pow_mpz_t_tmp_demo(self, m, n): @@ -319,7 +318,7 @@ cdef class PowComputer_class(SageObject): sage: PC = PowComputer(3, 5, 10); PC PowComputer for 3 """ - return "PowComputer for %s"%(self.prime) + return "PowComputer for %s" % (self.prime) def _prime(self): """ @@ -411,8 +410,7 @@ cdef class PowComputer_class(SageObject): sage: P(-2) 1/9 """ - cdef Integer z, _n - cdef mpz_t tmp + cdef Integer _n if n is infinity: return Integer(0) if not isinstance(n, Integer): @@ -496,12 +494,10 @@ cdef class PowComputer_base(PowComputer_class): sage: PC = PowComputer(5, 7, 10) sage: PC(3) 125 - """ PowComputer_class.__init__(self, prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, shift_seed) cdef Py_ssize_t i - cdef Integer x mpz_set_ui(self.small_powers[0], 1) if cache_limit > 0: @@ -634,6 +630,7 @@ cdef PowComputer_base PowComputer_c(Integer m, Integer cache_limit, Integer prec pow_comp_cache[key] = weakref.ref(PC) return PC + # To speed up the creation of PowComputers with the same m, we might eventually want to copy over data from an existing PowComputer. def PowComputer(m, cache_limit, prec_cap, in_field = False, prec_type=None): diff --git a/src/sage/rings/padics/pow_computer_ext.pxd b/src/sage/rings/padics/pow_computer_ext.pxd index e87f801971f..114696b34fa 100644 --- a/src/sage/rings/padics/pow_computer_ext.pxd +++ b/src/sage/rings/padics/pow_computer_ext.pxd @@ -105,4 +105,3 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): # cdef context_dict #currently using a dict, optimize for speed later # cdef modulus_dict #currently using a dict, optimize for speed later # - diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 1626990a051..3d47d3af2f9 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -191,8 +191,7 @@ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) excep raise TypeError("unrecognized Eisenstein type") cdef long i - cdef ZZ_pX_c tmp, modup, into_multiplier, shift_seed_inv - cdef ZZ_c a + cdef ZZ_pX_c into_multiplier, shift_seed_inv # We obtain successive p/x^(2^i) by squaring and then dividing by p. So we need one extra digit of precision. prime_pow.restore_top_context() #cdef ntl_ZZ_pContext_class cup = prime_pow.get_context(prime_pow.prec_cap + low_length) @@ -320,7 +319,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long cdef ZZ_pX_c low_part cdef ZZ_pX_c shifted_high_part cdef ZZ_pX_c powerx - cdef ZZ_pX_c shifter cdef ZZ_pX_c lowshift cdef ZZ_pX_c highshift cdef ZZ_pX_c working, working2 @@ -354,7 +352,6 @@ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long else: raise TypeError("inconsistent type") - cdef ntl_ZZ_pX printer if n < 0: if fm: c = self.get_top_context() @@ -478,7 +475,6 @@ cdef class PowComputer_ext(PowComputer_class): raise MemoryError("out of memory allocating power storing") cdef Py_ssize_t i - cdef Integer x ZZ_conv_from_int(self.small_powers[0], 1) @@ -1574,7 +1570,6 @@ cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): self.cleanup_ext() raise MemoryError("out of memory allocating moduli") - cdef ntl_ZZ_pX printer cdef Py_ssize_t i cdef ZZ_pX_c tmp, pol if isinstance(poly, ntl_ZZ_pX): diff --git a/src/sage/rings/padics/pow_computer_relative.pyx b/src/sage/rings/padics/pow_computer_relative.pyx index 2253281bd35..fc51eb3410f 100644 --- a/src/sage/rings/padics/pow_computer_relative.pyx +++ b/src/sage/rings/padics/pow_computer_relative.pyx @@ -150,14 +150,16 @@ cdef class PowComputer_relative(PowComputer_class): Relative PowComputer for modulus x^3 + 5*x + a*5 """ - return "Relative PowComputer for modulus %s"%(self.modulus,) + return "Relative PowComputer for modulus %s" % (self.modulus,) cdef unsigned long capdiv(self, unsigned long n): r""" Return `\lceil n/e \rceil`. """ - if self.e == 1: return n - if n == 0: return 0 + if self.e == 1: + return n + if n == 0: + return 0 return (n - 1)/self.e + 1 def polynomial(self, n=None, var='x'): diff --git a/src/sage/rings/padics/qadic_flint_FP.pyx b/src/sage/rings/padics/qadic_flint_FP.pyx index 020b03b722a..36e898c8590 100644 --- a/src/sage/rings/padics/qadic_flint_FP.pyx +++ b/src/sage/rings/padics/qadic_flint_FP.pyx @@ -108,7 +108,6 @@ cdef class qAdicFloatingPointElement(FPElement): cshift_notrunc(self.prime_pow.poly_flint_rep, self.unit, self.ordp, self.ordp + self.prime_pow.prec_cap, self.prime_pow, False) return self.prime_pow._new_fmpz_poly(self.prime_pow.poly_flint_rep, var), Integer(0) - def _modp_rep(self, use_smallest_mode=False, return_list=True): r""" Return the element with the same reduction mod p that can be expressed diff --git a/src/sage/rings/padics/relaxed_template.pxi b/src/sage/rings/padics/relaxed_template.pxi index a18ffb1cb03..751e42700f0 100644 --- a/src/sage/rings/padics/relaxed_template.pxi +++ b/src/sage/rings/padics/relaxed_template.pxi @@ -948,11 +948,12 @@ cdef class RelaxedElement(pAdicGenericElement): return Integer(self._precrel + self._valuation) def precision_relative(self): - """ + r""" Return the relative precision of this element. This is the power of `p` modulo which the unit part of this element is known. + For unbounded nonzero elements, this methods return `+\infty`. EXAMPLES:: @@ -3056,7 +3057,6 @@ cdef class RelaxedElement_sub(RelaxedElementWithDigits): return 0 - # Multiplication cdef class RelaxedElement_mul(RelaxedElementWithDigits): @@ -3684,7 +3684,7 @@ cdef class RelaxedElement_teichmuller(RelaxedElementWithDigits): p = self.prime_pow.prime size = mpz_sizeinbase(p.value, 2) i = size - 2 - self._xns = [ ] + self._xns = [] while i >= 0: xn = element_class_mul(parent, xn, xn) self._xns.append(xn) @@ -3801,7 +3801,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): self._next = maxordp cdef cdigit digit if digits is not None: - digits = [ Integer(d) for d in digits ] + digits = [Integer(d) for d in digits] for d in digits: digit_set_sage(digit, d) element_iadd_digit(self._digits, digit, self._precrel) @@ -3828,7 +3828,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): sage: x == loads(dumps(x)) # indirect doctest True """ - digits = [ ] + digits = [] for i in range(self._initialprecrel): digits.append(digit_get_sage(element_get_digit(self._digits, i))) definition = None @@ -3933,6 +3933,7 @@ cdef class RelaxedElement_unknown(RelaxedElementWithDigits): self._next = svenext return error + def unpickle_unknown(uid, cls, parent, valuation, digits, definition): r""" Unpickle a self-referent relaxed `p`-adic number. @@ -4084,7 +4085,7 @@ cdef class ExpansionIter(): self._next_smallest() elif self.mode == teichmuller_mode: self.tail = elt - self.coefficients = { } + self.coefficients = {} while self.current < self.start: self._next_teichmuller() From efb23b08e74bbfc8573c31a019dd28ea8af9c427 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 15:14:06 -0700 Subject: [PATCH 180/225] pkgs/sage-conf_conda: New, use it in conda install instructions --- pkgs/sage-conf_conda/.gitignore | 6 +++ pkgs/sage-conf_conda/MANIFEST.in | 1 + pkgs/sage-conf_conda/README.rst | 1 + pkgs/sage-conf_conda/VERSION.txt | 1 + pkgs/sage-conf_conda/_sage_conf | 1 + pkgs/sage-conf_conda/bin | 1 + pkgs/sage-conf_conda/pyproject.toml | 1 + pkgs/sage-conf_conda/sage_conf.py | 1 + pkgs/sage-conf_conda/sage_root | 1 + pkgs/sage-conf_conda/setup.cfg | 1 + pkgs/sage-conf_conda/setup.py | 77 +++++++++++++++++++++++++++++ pkgs/sage-conf_pypi/pyproject.toml | 4 +- src/doc/en/installation/conda.rst | 18 ++----- 13 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 pkgs/sage-conf_conda/.gitignore create mode 120000 pkgs/sage-conf_conda/MANIFEST.in create mode 120000 pkgs/sage-conf_conda/README.rst create mode 100644 pkgs/sage-conf_conda/VERSION.txt create mode 120000 pkgs/sage-conf_conda/_sage_conf create mode 120000 pkgs/sage-conf_conda/bin create mode 120000 pkgs/sage-conf_conda/pyproject.toml create mode 120000 pkgs/sage-conf_conda/sage_conf.py create mode 120000 pkgs/sage-conf_conda/sage_root create mode 120000 pkgs/sage-conf_conda/setup.cfg create mode 100644 pkgs/sage-conf_conda/setup.py mode change 100644 => 120000 pkgs/sage-conf_pypi/pyproject.toml diff --git a/pkgs/sage-conf_conda/.gitignore b/pkgs/sage-conf_conda/.gitignore new file mode 100644 index 00000000000..6fdda73c500 --- /dev/null +++ b/pkgs/sage-conf_conda/.gitignore @@ -0,0 +1,6 @@ +/_sage_conf/_conf.py +/build +/dist +/*.egg-info +/.tox +/bin/sage-env-config diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in new file mode 120000 index 00000000000..31ac1aa5100 --- /dev/null +++ b/pkgs/sage-conf_conda/MANIFEST.in @@ -0,0 +1 @@ +../sage-conf_pypi/MANIFEST.in \ No newline at end of file diff --git a/pkgs/sage-conf_conda/README.rst b/pkgs/sage-conf_conda/README.rst new file mode 120000 index 00000000000..feda886cd36 --- /dev/null +++ b/pkgs/sage-conf_conda/README.rst @@ -0,0 +1 @@ +../sage-conf/README.rst \ No newline at end of file diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt new file mode 100644 index 00000000000..7786f0e63e4 --- /dev/null +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -0,0 +1 @@ +10.2.beta5 diff --git a/pkgs/sage-conf_conda/_sage_conf b/pkgs/sage-conf_conda/_sage_conf new file mode 120000 index 00000000000..d92a91bef8c --- /dev/null +++ b/pkgs/sage-conf_conda/_sage_conf @@ -0,0 +1 @@ +../sage-conf/_sage_conf \ No newline at end of file diff --git a/pkgs/sage-conf_conda/bin b/pkgs/sage-conf_conda/bin new file mode 120000 index 00000000000..d7471f37a23 --- /dev/null +++ b/pkgs/sage-conf_conda/bin @@ -0,0 +1 @@ +../sage-conf_pypi/bin \ No newline at end of file diff --git a/pkgs/sage-conf_conda/pyproject.toml b/pkgs/sage-conf_conda/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_conda/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_conf.py b/pkgs/sage-conf_conda/sage_conf.py new file mode 120000 index 00000000000..f4bca8cc55c --- /dev/null +++ b/pkgs/sage-conf_conda/sage_conf.py @@ -0,0 +1 @@ +../sage-conf/sage_conf.py \ No newline at end of file diff --git a/pkgs/sage-conf_conda/sage_root b/pkgs/sage-conf_conda/sage_root new file mode 120000 index 00000000000..2f7df6e4f3f --- /dev/null +++ b/pkgs/sage-conf_conda/sage_root @@ -0,0 +1 @@ +../sage-conf_pypi/sage_root \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.cfg b/pkgs/sage-conf_conda/setup.cfg new file mode 120000 index 00000000000..93df2c80a4b --- /dev/null +++ b/pkgs/sage-conf_conda/setup.cfg @@ -0,0 +1 @@ +../sage-conf/setup.cfg \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py new file mode 100644 index 00000000000..5755edb49ae --- /dev/null +++ b/pkgs/sage-conf_conda/setup.py @@ -0,0 +1,77 @@ +import os +import sys +import shutil +import sysconfig +import platform + +from setuptools import setup +from distutils.command.build_scripts import build_scripts as distutils_build_scripts +from setuptools.command.build_py import build_py as setuptools_build_py +from setuptools.command.egg_info import egg_info as setuptools_egg_info +from distutils.errors import (DistutilsSetupError, DistutilsModuleError, + DistutilsOptionError) + +class build_py(setuptools_build_py): + + def run(self): + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + HERE = os.path.dirname(__file__) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: These two should be user-configurable with options passed to "setup.py install" + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') + SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print(f'Reusing SAGE_ROOT={SAGE_ROOT}') + else: + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists + except Exception: + raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") + cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += """ + --with-python=$CONDA_PREFIX/bin/python \ + --prefix=$CONDA_PREFIX \ + --enable-system-site-packages \ + $(for pkg in $(./sage -package list :standard: \ + --exclude rpy2 \ + --has-file spkg-configure.m4 \ + --has-file distros/conda.txt); do \ + echo --with-system-$pkg=force; \ + done)""" + print(f"Running {cmd}") + sys.stdout.flush() + if os.system(cmd) != 0: + print(f"configure failed; this may be caused by missing build prerequisites.") + sys.stdout.flush() + PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages + os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + raise DistutilsSetupError("configure failed") + + # In this mode, we never run "make". + + # Install configuration + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + setuptools_build_py.run(self) + +class build_scripts(distutils_build_scripts): + + def run(self): + self.distribution.scripts.append(os.path.join('bin', 'sage-env-config')) + if not self.distribution.entry_points: + self.entry_points = self.distribution.entry_points = dict() + distutils_build_scripts.run(self) + +setup( + cmdclass=dict(build_py=build_py, build_scripts=build_scripts) +) diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml deleted file mode 100644 index 9787c3bdf00..00000000000 --- a/pkgs/sage-conf_pypi/pyproject.toml +++ /dev/null @@ -1,3 +0,0 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" diff --git a/pkgs/sage-conf_pypi/pyproject.toml b/pkgs/sage-conf_pypi/pyproject.toml new file mode 120000 index 00000000000..52c93c824e2 --- /dev/null +++ b/pkgs/sage-conf_pypi/pyproject.toml @@ -0,0 +1 @@ +../sage-conf/pyproject.toml \ No newline at end of file diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 5228611de3b..252c77c39d1 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -135,24 +135,12 @@ Here we assume that you are using a git checkout. By default, the most recent version of Python supported by Sage is installed. You can use the additional option ``python=3.9`` in the above - ``env create`` command to select another Python version (here 3.9). - - - Run the ``configure`` script:: - - $ ./bootstrap - $ ./configure --with-python=$CONDA_PREFIX/bin/python \ - --prefix=$CONDA_PREFIX \ - $(for pkg in $(./sage -package list :standard: \ - --exclude rpy2 \ - --has-file spkg-configure.m4 \ - --has-file distros/conda.txt); do \ - echo --with-system-$pkg=force; \ - done) + ``env create`` command to select another Python version (here 3.9). - Install the build prerequisites and the Sage library:: - $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf ./pkgs/sage-setup - $ pip install --no-build-isolation -v -v --editable ./src + $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-conf_conda ./pkgs/sage-setup + $ pip install --no-build-isolation --config-settings editable_mode=compat -v -v --editable ./src - Verify that Sage has been installed:: From ab0960722972c43d097671f806ec567e9fd31df2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 27 Sep 2023 17:23:56 -0700 Subject: [PATCH 181/225] src/doc/en/installation/conda.rst: Add note on editable_mode=compat --- src/doc/en/installation/conda.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 252c77c39d1..063a9fb06cf 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -171,3 +171,11 @@ To build the documentation, use:: $ pip install --no-build-isolation -v -v --editable ./pkgs/sage-docbuild $ sage --docbuild all html + +.. NOTE:: + + The switch ``--config-settings editable_mode=compat`` restores the + `legacy setuptools implementation of editable installations + `_. + Adventurous developers may omit this switch to try the modern, + PEP-660 implementation of editable installations, see :issue:`34209`. From 944bc9723abf50d86036342e24ebd29306f2b9e8 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 29 Sep 2023 15:53:55 -0700 Subject: [PATCH 182/225] pkgs/sage-conf_conda: Fix setup.py --- pkgs/sage-conf_conda/setup.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 5755edb49ae..e2c8d857b9a 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -3,6 +3,9 @@ import shutil import sysconfig import platform +import fnmatch + +from pathlib import Path from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts @@ -25,27 +28,28 @@ def run(self): arch_tag = f'{system}-{machine}' # TODO: These two should be user-configurable with options passed to "setup.py install" SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') - SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox',)] + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print(f'Reusing SAGE_ROOT={SAGE_ROOT}') else: # config.status and other configure output has to be writable. # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. try: - shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists - except Exception: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") - cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" - cmd += """ - --with-python=$CONDA_PREFIX/bin/python \ - --prefix=$CONDA_PREFIX \ - --enable-system-site-packages \ - $(for pkg in $(./sage -package list :standard: \ - --exclude rpy2 \ - --has-file spkg-configure.m4 \ - --has-file distros/conda.txt); do \ - echo --with-system-$pkg=force; \ - done)""" + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again. (Exception: {e})") + cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' + cmd += ' $(for pkg in $(build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' print(f"Running {cmd}") sys.stdout.flush() if os.system(cmd) != 0: From 870ce5d32b19946e21bdf26f455dd1a962cba7aa Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 12:16:08 -0700 Subject: [PATCH 183/225] pkgs/sage-conf_conda/setup.py: In editable mode, do not make a copy of SAGE_ROOT --- pkgs/sage-conf_conda/setup.py | 75 ++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index e2c8d857b9a..4a8aaef9f83 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -10,15 +10,51 @@ from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py -from setuptools.command.egg_info import egg_info as setuptools_egg_info -from distutils.errors import (DistutilsSetupError, DistutilsModuleError, - DistutilsOptionError) +from setuptools.errors import SetupError + class build_py(setuptools_build_py): def run(self): - DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + HERE = os.path.dirname(__file__) + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') + else: + cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' + cmd += ' $(for pkg in $(PATH="build/bin:$PATH" build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' + print(f"Running {cmd}") + sys.stdout.flush() + if os.system(cmd) != 0: + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + print("Warning: A configuration has been written, but the configure script has exited with an error. " + "Carefully check any error messages before continuing.") + else: + print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") + sys.stdout.flush() + PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages + os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + raise SetupError("configure failed") + + # In this mode, we never run "make". + + if not self.editable_mode: + # Install configuration + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + + setuptools_build_py.run(self) + + def _create_writable_sage_root(self): + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) with open(os.path.join(HERE, 'VERSION.txt')) as f: sage_version = f.read().strip() # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version @@ -26,7 +62,7 @@ def run(self): system = platform.system() machine = platform.machine() arch_tag = f'{system}-{machine}' - # TODO: These two should be user-configurable with options passed to "setup.py install" + # TODO: Should be user-configurable with config settings SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}-conda') def ignore(path, names): @@ -35,38 +71,20 @@ def ignore(path, names): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names - if name in ('.tox',)] + if name in ('.tox', '.git', '__pycache__')] - if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): - print(f'Reusing SAGE_ROOT={SAGE_ROOT}') - else: + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): # config.status and other configure output has to be writable. # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. try: shutil.copytree('sage_root', SAGE_ROOT, ignore=ignore) # will fail if already exists except Exception as e: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again. (Exception: {e})") - cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" - cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' - cmd += ' $(for pkg in $(build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' - print(f"Running {cmd}") - sys.stdout.flush() - if os.system(cmd) != 0: - print(f"configure failed; this may be caused by missing build prerequisites.") - sys.stdout.flush() - PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages - os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') - raise DistutilsSetupError("configure failed") + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") - # In this mode, we never run "make". + return SAGE_ROOT - # Install configuration - shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), - os.path.join(HERE, '_sage_conf', '_conf.py')) - shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), - os.path.join(HERE, 'bin', 'sage-env-config')) - setuptools_build_py.run(self) class build_scripts(distutils_build_scripts): @@ -76,6 +94,7 @@ def run(self): self.entry_points = self.distribution.entry_points = dict() distutils_build_scripts.run(self) + setup( cmdclass=dict(build_py=build_py, build_scripts=build_scripts) ) From 77925d09a8116bfbce4c3c29a529b408f4df560b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 14:38:22 -0700 Subject: [PATCH 184/225] pkgs/sage-conf_conda: Make sage_root a symlink to SAGE_ROOT --- pkgs/sage-conf_conda/MANIFEST.in | 54 +++++++++++++++++++++++++++++++- pkgs/sage-conf_conda/sage_root | 2 +- pkgs/sage-conf_conda/setup.py | 8 +++-- 3 files changed, 60 insertions(+), 4 deletions(-) mode change 120000 => 100644 pkgs/sage-conf_conda/MANIFEST.in diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in deleted file mode 120000 index 31ac1aa5100..00000000000 --- a/pkgs/sage-conf_conda/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -../sage-conf_pypi/MANIFEST.in \ No newline at end of file diff --git a/pkgs/sage-conf_conda/MANIFEST.in b/pkgs/sage-conf_conda/MANIFEST.in new file mode 100644 index 00000000000..ea5f85f8c99 --- /dev/null +++ b/pkgs/sage-conf_conda/MANIFEST.in @@ -0,0 +1,53 @@ +prune .tox +include VERSION.txt +graft bin +exclude bin/sage-env-config # generated by configure + +prune sage_root +include sage_root/Makefile +include sage_root/README.md +include sage_root/VERSION.txt +include sage_root/bootstrap +include sage_root/bootstrap-conda +graft sage_root/build +prune sage_root/build/.tox +exclude sage_root/build/bin/sage-build-env-config # generated by configure +exclude sage_root/build/make/Makefile-auto # generated by configure +exclude sage_root/build/make/Makefile # generated by configure + +# These sources are not needed because individual distributions of these are made. +prune sage_root/build/pkgs/*/src* + +graft sage_root/config +include sage_root/configure +include sage_root/configure.ac +graft sage_root/m4 + +# Only these pkgs are needed (because of dependencies on source files, +# see "git grep SAGE_ROOT build/pkgs/*/dependencies") +graft sage_root/pkgs/sage-conf +prune sage_root/pkgs/sage-conf/build +prune sage_root/pkgs/sage-conf/dist +prune sage_root/pkgs/sage-conf/*.egg-info +exclude sage_root/pkgs/sage-conf/_sage_conf/_conf.py # generated by configure +graft sage_root/pkgs/sage-docbuild +prune sage_root/pkgs/sage-docbuild/build +prune sage_root/pkgs/sage-docbuild/dist +prune sage_root/pkgs/sage-docbuild/*.egg-info + +graft sage_root/src/_sage_conf +include sage_root/src/bin/sage-env +include sage_root/src/bin/sage-env-config.in +include sage_root/src/bin/sage-src-env-config.in +include sage_root/src/bin/sage-venv-config +include sage_root/src/bin/sage-version.sh +include sage_root/src/doc/bootstrap # FIXME: should move to builds/pkgs/sagemath_doc_html/ + +global-exclude .tox +global-exclude *~* +global-exclude *.bak +global-exclude *.orig +global-exclude __pycache__ +global-exclude *.py[co] +global-exclude *.so +global-exclude .DS_Store diff --git a/pkgs/sage-conf_conda/sage_root b/pkgs/sage-conf_conda/sage_root index 2f7df6e4f3f..c25bddb6dd4 120000 --- a/pkgs/sage-conf_conda/sage_root +++ b/pkgs/sage-conf_conda/sage_root @@ -1 +1 @@ -../sage-conf_pypi/sage_root \ No newline at end of file +../.. \ No newline at end of file diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 4a8aaef9f83..8d5d9b303fe 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -44,8 +44,11 @@ def run(self): # In this mode, we never run "make". - if not self.editable_mode: - # Install configuration + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), os.path.join(HERE, '_sage_conf', '_conf.py')) shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), @@ -54,6 +57,7 @@ def run(self): setuptools_build_py.run(self) def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) with open(os.path.join(HERE, 'VERSION.txt')) as f: sage_version = f.read().strip() From 66a407eaa4ced5af6155eb98ca379bd3770b3c7e Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 15:08:05 -0700 Subject: [PATCH 185/225] Update README and messages --- pkgs/sage-conf/README.rst | 12 +++++++++++- pkgs/sage-conf_conda/setup.py | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pkgs/sage-conf/README.rst b/pkgs/sage-conf/README.rst index c968612aef2..5730592e35a 100644 --- a/pkgs/sage-conf/README.rst +++ b/pkgs/sage-conf/README.rst @@ -78,10 +78,20 @@ sage_conf in the SageMath distribution The original version of the distribution package ``sage_conf`` is used internally in the SageMath distribution. It is provided in the directory `pkgs/sage-conf `_. -This version of the package is generated by the Sage distribution's ``configure`` +This version of the package is generated by the Sage distribution's ``./configure`` script. +sage_conf for conda +------------------- + +The version of the distribution package in the directory +`pkgs/sage-conf_conda `_ +is used in an experimental installation method of SageMath, where all packages +are provided by conda. This method is described in +https://doc.sagemath.org/html/en/installation/conda.html#using-conda-to-provide-all-dependencies-for-the-sage-library-experimental + + sage_conf in downstream distributions ------------------------------------- diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 8d5d9b303fe..af0177f8ea4 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -34,12 +34,12 @@ def run(self): if os.system(cmd) != 0: if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print("Warning: A configuration has been written, but the configure script has exited with an error. " - "Carefully check any error messages before continuing.") + "Carefully check any messages above before continuing.") else: print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages - os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') + os.system(f'cd {SAGE_ROOT} && export PACKAGES="$(build/bin/sage-get-system-packages conda {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command conda --verbose --sudo install $PACKAGES && echo ""') raise SetupError("configure failed") # In this mode, we never run "make". From 18aebf4077a8d7a98f688ee0548e8ce978a561a0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:13:50 -0700 Subject: [PATCH 186/225] pkgs/sage-conf_conda/setup.py: Skip some files generated in editable mode when copying in non-editable mode --- pkgs/sage-conf_conda/setup.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index af0177f8ea4..a2333f6b8d5 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -10,6 +10,7 @@ from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel from setuptools.errors import SetupError @@ -75,7 +76,9 @@ def ignore(path, names): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names - if name in ('.tox', '.git', '__pycache__')] + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): # config.status and other configure output has to be writable. @@ -99,6 +102,16 @@ def run(self): distutils_build_scripts.run(self) +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + setup( - cmdclass=dict(build_py=build_py, build_scripts=build_scripts) + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) ) From 2c54bdc06263c74078fda88eb5fec37be055ca97 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:15:00 -0700 Subject: [PATCH 187/225] pkgs/sage-conf_pypi/setup.py: Restructure like ..._conda, prepare for editable mode --- .gitignore | 10 ++++ pkgs/sage-conf_pypi/setup.py | 104 +++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index efdbfa8f616..2cec8a0cf62 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,16 @@ build/bin/sage-build-env-config /pkgs/*/*.egg-info /pkgs/*/.tox +/pkgs/sage-conf_pypi/sage_root/config.log +/pkgs/sage-conf_pypi/sage_root/config.status +/pkgs/sage-conf_pypi/sage_root/local/ +/pkgs/sage-conf_pypi/sage_root/logs/ +/pkgs/sage-conf_pypi/sage_root/prefix +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-env-config +/pkgs/sage-conf_pypi/sage_root/src/bin/sage-src-env-config +/pkgs/sage-conf_pypi/sage_root/upstream/ +/pkgs/sage-conf_pypi/sage_root/venv + /pkgs/sagemath-objects/setup.cfg /pkgs/sagemath-bliss/setup.cfg /pkgs/sagemath-coxeter3/setup.cfg diff --git a/pkgs/sage-conf_pypi/setup.py b/pkgs/sage-conf_pypi/setup.py index a689f4d617b..16686a848c9 100644 --- a/pkgs/sage-conf_pypi/setup.py +++ b/pkgs/sage-conf_pypi/setup.py @@ -3,40 +3,35 @@ import shutil import sysconfig import platform +import fnmatch from setuptools import setup from distutils.command.build_scripts import build_scripts as distutils_build_scripts from setuptools.command.build_py import build_py as setuptools_build_py -from setuptools.command.egg_info import egg_info as setuptools_egg_info -from distutils.errors import (DistutilsSetupError, DistutilsModuleError, - DistutilsOptionError) +from setuptools.command.editable_wheel import editable_wheel as setuptools_editable_wheel +from setuptools.errors import SetupError + class build_py(setuptools_build_py): def run(self): - DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) HERE = os.path.dirname(__file__) - with open(os.path.join(HERE, 'VERSION.txt')) as f: - sage_version = f.read().strip() + if self.editable_mode: + SAGE_ROOT = os.path.join(HERE, 'sage_root') + else: + SAGE_ROOT = self._create_writable_sage_root() + # For convenience, set up the homebrew env automatically. This is a no-op if homebrew is not present. - SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' - # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version - # and architecture. - system = platform.system() - machine = platform.machine() - arch_tag = f'{system}-{machine}' - # TODO: These two should be user-configurable with options passed to "setup.py install" - SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + if os.environ.get('CONDA_PREFIX', ''): + SETENV = ':' + else: + SETENV = '(. ./.homebrew-build-env 2> /dev/null || :)' + SAGE_LOCAL = os.path.join(SAGE_ROOT, 'local') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): - print(f'Reusing SAGE_ROOT={SAGE_ROOT}') + print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: - # config.status and other configure output has to be writable. - # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. - try: - shutil.copytree('sage_root', SAGE_ROOT) # will fail if already exists - except Exception: - raise DistutilsSetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured. Please remove it and try again.") cmd = f"cd {SAGE_ROOT} && {SETENV} && ./configure --prefix={SAGE_LOCAL} --with-python={sys.executable} --enable-build-as-root --enable-download-from-upstream-url --with-system-python3=force --with-sage-venv --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" print(f"Running {cmd}") sys.stdout.flush() @@ -45,7 +40,18 @@ def run(self): sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') - raise DistutilsSetupError("configure failed") + raise SetupError("configure failed") + + # Copy over files generated by the configure script + # (see configure.ac AC_CONFIG_FILES) + if self.editable_mode: + pass # same file + else: + shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), + os.path.join(HERE, '_sage_conf', '_conf.py')) + shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), + os.path.join(HERE, 'bin', 'sage-env-config')) + # Here we run "make build" -- which builds everything except for sagelib because we # used configure --disable-sagelib # Alternative: @@ -61,13 +67,44 @@ def run(self): if os.system(cmd) != 0: raise DistutilsSetupError(f"make {TARGETS} failed") - # Install configuration - shutil.copyfile(os.path.join(SAGE_ROOT, 'pkgs', 'sage-conf', '_sage_conf', '_conf.py'), - os.path.join(HERE, '_sage_conf', '_conf.py')) - shutil.copyfile(os.path.join(SAGE_ROOT, 'src', 'bin', 'sage-env-config'), - os.path.join(HERE, 'bin', 'sage-env-config')) setuptools_build_py.run(self) + def _create_writable_sage_root(self): + HERE = os.path.dirname(__file__) + DOT_SAGE = os.environ.get('DOT_SAGE', os.path.join(os.environ.get('HOME'), '.sage')) + with open(os.path.join(HERE, 'VERSION.txt')) as f: + sage_version = f.read().strip() + # After #30534, SAGE_LOCAL no longer contains any Python. So we key the SAGE_ROOT only to Sage version + # and architecture. + system = platform.system() + machine = platform.machine() + arch_tag = f'{system}-{machine}' + # TODO: Should be user-configurable with config settings + SAGE_ROOT = os.path.join(DOT_SAGE, f'sage-{sage_version}-{arch_tag}') + + def ignore(path, names): + # exclude all embedded src trees + if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + return ['src'] + ### ignore more stuff --- .tox etc. + return [name for name in names + if name in ('.tox', '.git', '__pycache__', + 'prefix', 'local', 'venv', 'upstream', + 'config.status', 'config.log', 'logs')] + + if not os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): + # config.status and other configure output has to be writable. + # So (until the Sage distribution supports VPATH builds - #21469), we have to make a copy of sage_root. + try: + shutil.copytree('sage_root', SAGE_ROOT, + ignore=ignore) # will fail if already exists + except Exception as e: + raise SetupError(f"the directory SAGE_ROOT={SAGE_ROOT} already exists but it is not configured ({e}). " + "Please either remove it and try again, or install in editable mode (pip install -e).") + + return SAGE_ROOT + + class build_scripts(distutils_build_scripts): def run(self): @@ -76,6 +113,17 @@ def run(self): self.entry_points = self.distribution.entry_points = dict() distutils_build_scripts.run(self) + +class editable_wheel(setuptools_editable_wheel): + r""" + Customized so that exceptions raised by our build_py + do not lead to the "Customization incompatible with editable install" message + """ + _safely_run = setuptools_editable_wheel.run_command + + setup( - cmdclass=dict(build_py=build_py, build_scripts=build_scripts) + cmdclass=dict(build_py=build_py, + build_scripts=build_scripts, + editable_wheel=editable_wheel) ) From 46c28c0d104535f685931659e864efcd7be7e09b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 20:28:31 -0700 Subject: [PATCH 188/225] pkgs/sage-conf_conda/setup.py: Exit early when no conda env is active --- pkgs/sage-conf_conda/setup.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index a2333f6b8d5..21977a81ca4 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -24,6 +24,10 @@ def run(self): else: SAGE_ROOT = self._create_writable_sage_root() + if not os.environ.get('CONDA_PREFIX', ''): + raise SetupError('No conda environment is active. ' + 'See https://doc.sagemath.org/html/en/installation/conda.html on how to get started.') + if os.path.exists(os.path.join(SAGE_ROOT, 'config.status')): print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: From a330894dc098502b865b58039516ecee6fb6f309 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 21:44:44 -0700 Subject: [PATCH 189/225] sage.sets: More block tags --- src/sage/sets/condition_set.py | 53 +++++++++++++++++++--------------- src/sage/sets/image_set.py | 27 +++++++++-------- src/sage/sets/set.py | 22 +++++++------- 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index ad8c2a8d512..539b850027f 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -260,13 +260,15 @@ def _repr_condition(self, predicate): sage: Evens = ConditionSet(ZZ, is_even) sage: Evens._repr_condition(is_even) '(x)' - sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x]) # needs sage.symbolic - sage: BigSin._repr_condition(BigSin._predicates[0]) # needs sage.symbolic + + sage: # needs sage.symbolic + sage: BigSin = ConditionSet(RR, sin(x) > 0.9, vars=[x]) + sage: BigSin._repr_condition(BigSin._predicates[0]) 'sin(x) > 0.900000000000000' - sage: var('t') # parameter # needs sage.symbolic + sage: var('t') # parameter t - sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) # needs sage.symbolic - sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0]) # needs sage.symbolic + sage: ZeroDimButNotNullary = ConditionSet(ZZ^0, t > 0, vars=("q")) + sage: ZeroDimButNotNullary._repr_condition(ZeroDimButNotNullary._predicates[0]) 't > 0' """ if isinstance(predicate, Expression) and predicate.is_callable(): @@ -342,24 +344,26 @@ def _call_predicate(self, predicate, element): TESTS:: - sage: TripleDigits = ZZ^3 # needs sage.modules - sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate # needs sage.symbolic + sage: # needs sage.modules sage.symbolic + sage: TripleDigits = ZZ^3 + sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 - sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples # needs sage.symbolic + sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: predicate = SmallTriples._predicates[0] # needs sage.symbolic - sage: element = TripleDigits((1, 2, 3)) # needs sage.modules - sage: SmallTriples._call_predicate(predicate, element) # needs sage.modules sage.symbolic + sage: predicate = SmallTriples._predicates[0] + sage: element = TripleDigits((1, 2, 3)) + sage: SmallTriples._call_predicate(predicate, element) sqrt(14) < 12 - sage: var('t') # needs sage.symbolic + sage: # needs sage.modules sage.symbolic + sage: var('t') t - sage: TinyUniverse = ZZ^0 # needs sage.modules - sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) # needs sage.modules sage.symbolic - sage: predicate = Nullary._predicates[0] # needs sage.modules sage.symbolic - sage: element = TinyUniverse(0) # needs sage.modules - sage: Nullary._call_predicate(predicate, element) # needs sage.modules sage.symbolic + sage: TinyUniverse = ZZ^0 + sage: Nullary = ConditionSet(TinyUniverse, t > 0, vars=()) + sage: predicate = Nullary._predicates[0] + sage: element = TinyUniverse(0) + sage: Nullary._call_predicate(predicate, element) t > 0 """ if isinstance(predicate, Expression) and predicate.is_callable(): @@ -375,13 +379,14 @@ def _an_element_(self): TESTS:: - sage: TripleDigits = ZZ^3 # needs sage.modules - sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate # needs sage.symbolic + sage: # needs sage.modules sage.symbolic + sage: TripleDigits = ZZ^3 + sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 - sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples # needs sage.symbolic + sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples { (x, y, z) ∈ Ambient free module of rank 3 over the principal ideal domain Integer Ring : sqrt(x^2 + y^2 + z^2) < 12 } - sage: SmallTriples.an_element() # indirect doctest # needs sage.symbolic + sage: SmallTriples.an_element() # indirect doctest (1, 0, 0) """ for element in self._universe.some_elements(): @@ -409,7 +414,7 @@ def _sympy_(self): EXAMPLES:: - sage: # needs sage.symbolic + sage: # needs sage.modules sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples @@ -468,7 +473,7 @@ def intersection(self, X): EXAMPLES:: - sage: # needs sage.symbolic + sage: # needs sage.modules sage.symbolic sage: in_small_oblong(x, y) = x^2 + 3 * y^2 <= 42 sage: SmallOblongUniverse = ConditionSet(QQ^2, in_small_oblong) sage: SmallOblongUniverse @@ -487,7 +492,7 @@ def intersection(self, X): Combining two ``ConditionSet``s with different formal variables works correctly. The formal variables of the intersection are taken from ``self``:: - sage: # needs sage.symbolic + sage: # needs sage.modules sage.symbolic sage: SmallMirrorUniverse = ConditionSet(QQ^2, in_small_oblong, ....: vars=(y, x)) sage: SmallMirrorUniverse diff --git a/src/sage/sets/image_set.py b/src/sage/sets/image_set.py index 4ad2d76a0a3..0472d793c19 100644 --- a/src/sage/sets/image_set.py +++ b/src/sage/sets/image_set.py @@ -73,12 +73,13 @@ def __init__(self, map, domain_subset, *, category=None, is_injective=None, inve EXAMPLES:: - sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) # needs sage.modules + sage: # needs sage.modules + sage: M = CombinatorialFreeModule(ZZ, [0,1,2,3]) sage: R. = QQ[] - sage: H = Hom(M, R, category=Sets()) # needs sage.modules - sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) # needs sage.modules - sage: Im = f.image() # needs sage.modules - sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', # needs sage.modules + sage: H = Hom(M, R, category=Sets()) + sage: f = H(lambda v: v[0]*x + v[1]*(x^2-y) + v[2]^2*(y+2) + v[3] - v[0]^2) + sage: Im = f.image() + sage: TestSuite(Im).run(skip=['_test_an_element', '_test_pickling', ....: '_test_some_elements', '_test_elements']) """ if not is_Parent(domain_subset): @@ -198,14 +199,15 @@ def lift(self, x): EXAMPLES:: - sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) # needs sage.modules + sage: # needs sage.modules + sage: M = CombinatorialFreeModule(QQ, [0, 1, 2, 3]) sage: R. = ZZ[] - sage: H = Hom(M, R, category=Sets()) # needs sage.modules - sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) # needs sage.modules - sage: Im = f.image() # needs sage.modules - sage: p = Im.lift(Im.an_element()); p # needs sage.modules + sage: H = Hom(M, R, category=Sets()) + sage: f = H(lambda v: floor(v[0])*x + ceil(v[3] - v[0]^2)) + sage: Im = f.image() + sage: p = Im.lift(Im.an_element()); p 2*x - 4 - sage: p.parent() is R # needs sage.modules + sage: p.parent() is R True """ return x @@ -278,7 +280,8 @@ def cardinality(self) -> Integer: sage: Mod2.cardinality() Traceback (most recent call last): ... - NotImplementedError: cannot determine cardinality of a non-injective image of an infinite set + NotImplementedError: cannot determine cardinality of a + non-injective image of an infinite set """ domain_cardinality = self._domain_subset.cardinality() if self._is_injective and self._is_injective != 'check': diff --git a/src/sage/sets/set.py b/src/sage/sets/set.py index 117b830621a..4e8789a2d57 100644 --- a/src/sage/sets/set.py +++ b/src/sage/sets/set.py @@ -1381,19 +1381,18 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) # needs sage.modules + sage: # needs sage.modules + sage: S = Set(QQ^2) sage: T = Set(ZZ) - sage: X = S.union(T); X # needs sage.modules + sage: X = S.union(T); X Set-theoretic union of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() # needs sage.modules + sage: X.category() Category of infinite sets - - sage: latex(X) # needs sage.modules + sage: latex(X) \Bold{Q}^{2} \cup \Bold{Z} - - sage: TestSuite(X).run() # needs sage.modules + sage: TestSuite(X).run() """ if category is None: category = Sets() @@ -1538,15 +1537,16 @@ def __init__(self, X, Y, category=None): EXAMPLES:: - sage: S = Set(QQ^2) # needs sage.modules + sage: # needs sage.modules + sage: S = Set(QQ^2) sage: T = Set(ZZ) - sage: X = S.intersection(T); X # needs sage.modules + sage: X = S.intersection(T); X Set-theoretic intersection of Set of elements of Vector space of dimension 2 over Rational Field and Set of elements of Integer Ring - sage: X.category() # needs sage.modules + sage: X.category() Category of enumerated sets - sage: latex(X) # needs sage.modules + sage: latex(X) \Bold{Q}^{2} \cap \Bold{Z} sage: X = Set(IntegerRange(100)).intersection(Primes()) From e110826f58dbd4411c378b046f229a69e3c6c5ea Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 22:23:06 -0700 Subject: [PATCH 190/225] src/sage/graphs/generators/smallgraphs.py: Fix doctest dataflow warnings --- src/sage/graphs/generators/smallgraphs.py | 29 ++++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index c113dcdf6be..a4f3e1c05ef 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -455,8 +455,8 @@ def Cell600(embedding=1): EXAMPLES:: - sage: # long time - sage: g = graphs.Cell600() # needs sage.rings.number_field + sage: # long time, needs sage.rings.number_field + sage: g = graphs.Cell600() sage: g.size() 720 sage: g.is_regular(12) @@ -531,8 +531,8 @@ def Cell120(): EXAMPLES:: - sage: # long time - sage: g = graphs.Cell120() # needs sage.rings.number_field + sage: # long time, needs sage.rings.number_field + sage: g = graphs.Cell120() sage: g.size() 1200 sage: g.is_regular(4) @@ -4754,18 +4754,19 @@ def MathonStronglyRegularGraph(t): EXAMPLES:: + sage: # long time, needs sage.libs.gap sage: from sage.graphs.generators.smallgraphs import MathonStronglyRegularGraph - sage: G = MathonStronglyRegularGraph(0) # long time # needs sage.libs.gap - sage: G.is_strongly_regular(parameters=True) # long time + sage: G = MathonStronglyRegularGraph(0) + sage: G.is_strongly_regular(parameters=True) (784, 243, 82, 72) TESTS:: - sage: # long time - sage: G = graphs.MathonStronglyRegularGraph(1) # needs sage.libs.gap + sage: # long time, needs sage.libs.gap + sage: G = graphs.MathonStronglyRegularGraph(1) sage: G.is_strongly_regular(parameters=True) (784, 270, 98, 90) - sage: G = graphs.MathonStronglyRegularGraph(2) # needs sage.libs.gap + sage: G = graphs.MathonStronglyRegularGraph(2) sage: G.is_strongly_regular(parameters=True) (784, 297, 116, 110) @@ -4790,11 +4791,11 @@ def JankoKharaghaniGraph(v): EXAMPLES:: sage: g = graphs.JankoKharaghaniGraph(936) # long time # needs sage.libs.pari - sage: g.is_strongly_regular(parameters=True) # long time + sage: g.is_strongly_regular(parameters=True) # long time # needs sage.libs.pari (936, 375, 150, 150) - sage: g = graphs.JankoKharaghaniGraph(1800) # not tested (30s) - sage: g.is_strongly_regular(parameters=True) # not tested (30s) + sage: g = graphs.JankoKharaghaniGraph(1800) # not tested (30s) + sage: g.is_strongly_regular(parameters=True) # not tested (30s) (1800, 1029, 588, 588) """ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF @@ -4881,8 +4882,8 @@ def JankoKharaghaniTonchevGraph(): EXAMPLES:: - sage: Gamma=graphs.JankoKharaghaniTonchevGraph() # long time # needs sage.libs.gap - sage: Gamma.is_strongly_regular(parameters=True) # long time + sage: Gamma = graphs.JankoKharaghaniTonchevGraph() # long time # needs sage.libs.gap + sage: Gamma.is_strongly_regular(parameters=True) # long time # needs sage.libs.gap (324, 153, 72, 72) """ from sage.misc.misc_c import prod From 82fb0f5fec3c69de9007798b2d2f5bc2bbdc4512 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 22:39:45 -0700 Subject: [PATCH 191/225] src/sage/combinat/integer_vectors_mod_permgroup.py: Use more block tags, docstring cosmetics --- .../combinat/integer_vectors_mod_permgroup.py | 115 +++++++++++------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index a4b1b5a5d37..d00a3748149 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -27,7 +27,7 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): r""" - Returns an enumerated set containing integer vectors which are + Return an enumerated set containing integer vectors which are maximal in their orbit under the action of the permutation group ``G`` for the lexicographic order. @@ -137,7 +137,9 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): [[6, 0, 0], [5, 1, 0], [5, 0, 1], [4, 2, 0], [4, 1, 1], [4, 0, 2], [3, 3, 0], [3, 2, 1], [3, 1, 2], [2, 2, 2]] sage: I.category() - Join of Category of finite enumerated sets and Category of subquotients of finite sets and Category of quotients of sets + Join of Category of finite enumerated sets + and Category of subquotients of finite sets + and Category of quotients of sets To get the orbit of any integer vector `v` under the action of the group, use the method :meth:`~sage.combinat.integer_vectors_mod_permgroup.IntegerVectorsModPermutationGroup_All.orbit`; @@ -156,9 +158,9 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): Let us check that canonical integer vectors of the symmetric group are just sorted list of integers:: - sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time - sage: p = iter(I) # long time - sage: for i in range(100): # long time + sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time + sage: p = iter(I) # long time + sage: for i in range(100): # long time ....: v = list(next(p)) ....: assert sorted(v, reverse=True) == v @@ -166,8 +168,8 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): symmetric group `S_n` whose entries sum to `d` than partitions of `d` of at most `n` parts:: - sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time - sage: for i in range(10): # long time + sage: I = IntegerVectorsModPermutationGroup(SymmetricGroup(5)) # long time + sage: for i in range(10): # long time ....: d1 = I.subset(i).cardinality() ....: d2 = Partitions(i, max_length=5).cardinality() ....: print(d1) @@ -187,11 +189,12 @@ class IntegerVectorsModPermutationGroup(UniqueRepresentation): group ``G`` acting on a list of length `n`, all integer vectors of length `n` are canonical:: - sage: G = PermutationGroup([[(6,)]]) # long time - sage: G.cardinality() # long time + sage: # long time + sage: G = PermutationGroup([[(6,)]]) + sage: G.cardinality() 1 - sage: I = IntegerVectorsModPermutationGroup(G) # long time - sage: for i in range(10): # long time + sage: I = IntegerVectorsModPermutationGroup(G) + sage: for i in range(10): ....: d1 = I.subset(i).cardinality() ....: d2 = IntegerVectors(i,6).cardinality() ....: print(d1) @@ -245,9 +248,9 @@ class IntegerVectorsModPermutationGroup_All(UniqueRepresentation, RecursivelyEnu EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])) - sage: I - Integer vectors of length 4 enumerated up to the action of Permutation Group with generators [(1,2,3,4)] + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])); I + Integer vectors of length 4 enumerated up to the action of + Permutation Group with generators [(1,2,3,4)] sage: I.cardinality() +Infinity sage: TestSuite(I).run() @@ -274,7 +277,8 @@ def __init__(self, G, sgs=None): sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]])) sage: I - Integer vectors of length 4 enumerated up to the action of Permutation Group with generators [(1,2,3,4)] + Integer vectors of length 4 enumerated up to the action of + Permutation Group with generators [(1,2,3,4)] sage: I.category() Category of infinite enumerated quotients of sets sage: TestSuite(I).run() @@ -575,10 +579,13 @@ class IntegerVectorsModPermutationGroup_with_constraints(UniqueRepresentation, R EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=1) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=1) sage: I.list() - [[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 0], [1, 1, 1, 1]] - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=6, max_part=4) + [[0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0], [1, 0, 1, 0], [1, 1, 1, 0], + [1, 1, 1, 1]] + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=6, max_part=4) sage: I.list() [[4, 2, 0, 0], [4, 1, 1, 0], [4, 1, 0, 1], [4, 0, 2, 0], [4, 0, 1, 1], [4, 0, 0, 2], [3, 3, 0, 0], [3, 2, 1, 0], [3, 2, 0, 1], [3, 1, 2, 0], @@ -641,7 +648,9 @@ def _repr_(self): def roots(self): r""" - Returns the root of generation of ``self``.This method is + Return the root of generation of ``self``. + + This method is required to build the tree structure of ``self`` which inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`. @@ -656,7 +665,9 @@ def roots(self): def children(self, x): r""" - Returns the list of children of the element ``x``. This method + Return the list of children of the element ``x``. + + This method is required to build the tree structure of ``self`` which inherits from the class :class:`~sage.sets.recursively_enumerated_set.RecursivelyEnumeratedSet_forest`. @@ -671,7 +682,7 @@ def children(self, x): def permutation_group(self): r""" - Returns the permutation group given to define ``self``. + Return the permutation group given to define ``self``. EXAMPLES:: @@ -766,7 +777,7 @@ def __iter__(self): def is_canonical(self, v, check=True): r""" - Returns ``True`` if the integer list ``v`` is maximal in its + Return ``True`` if the integer list ``v`` is maximal in its orbit under the action of the permutation group given to define ``self``. Such integer vectors are said to be canonical. A vector `v` is canonical if and only if @@ -777,7 +788,8 @@ def is_canonical(self, v, check=True): EXAMPLES:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=3) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=3) sage: I.is_canonical([3,0,0,0]) True sage: I.is_canonical([1,0,2,0]) @@ -798,11 +810,16 @@ def ambient(self): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6) + sage: S.ambient() Integer vectors that sum to 6 - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 6, max_part=12); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: 6, max_part=12) + sage: S.ambient() Integer vectors that sum to 6 with constraints: max_part=12 - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=12); S.ambient() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=12) + sage: S.ambient() Integer vectors with constraints: max_part=12 """ if self._sum is not None: @@ -819,12 +836,14 @@ def lift(self, elt): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), max_part=1) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: max_part=1) sage: v = S.lift([1,0,1,0]); v [1, 0, 1, 0] sage: v in IntegerVectors(2,4,max_part=1) True - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=6) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=6) sage: v = S.lift(S.list()[5]); v [4, 1, 1, 0] sage: v in IntegerVectors(n=6) @@ -847,7 +866,8 @@ def retract(self, elt): EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=2, max_part=1) + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=2, max_part=1) sage: S.retract([1,1,0,0]) [1, 1, 0, 0] sage: S.retract([1,0,1,0]) @@ -873,22 +893,35 @@ def retract(self, elt): def an_element(self): r""" - Returns an element of ``self`` or raises an EmptySetError when - ``self`` is empty. + Return an element of ``self``. + + Raises an :class:`EmptySetError` when ``self`` is empty. EXAMPLES:: - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=0, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=0, max_part=1) + sage: S.an_element() [0, 0, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=1, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=1, max_part=1) + sage: S.an_element() [1, 0, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=2, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=2, max_part=1) + sage: S.an_element() [1, 1, 0, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=3, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=3, max_part=1) + sage: S.an_element() [1, 1, 1, 0] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=4, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=4, max_part=1) + sage: S.an_element() [1, 1, 1, 1] - sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), sum=5, max_part=1); S.an_element() + sage: S = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), + ....: sum=5, max_part=1) + sage: S.an_element() Traceback (most recent call last): ... EmptySetError @@ -905,12 +938,12 @@ def an_element(self): def orbit(self, v): r""" - Returns the orbit of the vector ``v`` under the action of the + Return the orbit of the vector ``v`` under the action of the permutation group defining ``self``. The result is a set. INPUT: - - ``v`` - an element of ``self`` or any list of length the + - ``v`` -- an element of ``self`` or any list of length the degree of the permutation group. EXAMPLES: @@ -918,7 +951,7 @@ def orbit(self, v): We convert the result in a list in increasing lexicographic order, to get a reproducible doctest:: - sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]),4) + sage: I = IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3,4)]]), 4) sage: I.orbit([1,1,1,1]) {[1, 1, 1, 1]} sage: sorted(I.orbit([3,0,0,1])) @@ -952,7 +985,7 @@ class Element(ClonableIntArray): def check(self): r""" - Checks that ``self`` meets the constraints of being an element of ``self.parent()``. + Check that ``self`` meets the constraints of being an element of ``self.parent()``. EXAMPLES:: From 67eb2e1f888ca580977d45f9acce9c2b37f79d5b Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 30 Sep 2023 22:44:36 -0700 Subject: [PATCH 192/225] src/sage/combinat/designs/incidence_structures.py: More block tags --- src/sage/combinat/designs/incidence_structures.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index 0c17d27f035..46aada66a6e 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -1538,13 +1538,14 @@ def is_t_design(self, t=None, v=None, k=None, l=None, return_parameters=False): Some examples of Witt designs that need the gap database:: - sage: BD = designs.WittDesign(9) # optional - gap_package_design - sage: BD.is_t_design(2,9,3,1) # optional - gap_package_design + sage: # optional - gap_package_design + sage: BD = designs.WittDesign(9) + sage: BD.is_t_design(2,9,3,1) True - sage: W12 = designs.WittDesign(12) # optional - gap_package_design - sage: W12.is_t_design(5,12,6,1) # optional - gap_package_design + sage: W12 = designs.WittDesign(12) + sage: W12.is_t_design(5,12,6,1) True - sage: W12.is_t_design(4) # optional - gap_package_design + sage: W12.is_t_design(4) True Further examples:: From cac1e592eb6f7e14310224d301a260f2c906771d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 09:10:28 +0200 Subject: [PATCH 193/225] fix remaining W605 warnings in pxi files --- src/sage/libs/linkages/padics/API.pxi | 6 +- .../libs/linkages/padics/fmpz_poly_unram.pxi | 4 +- src/sage/libs/linkages/padics/mpz.pxi | 2 +- .../libs/linkages/padics/unram_shared.pxi | 10 +-- src/sage/libs/symmetrica/sc.pxi | 62 ++++++++----------- .../matrix/matrix_modn_dense_template.pxi | 7 +-- src/sage/symbolic/series_impl.pxi | 2 +- 7 files changed, 41 insertions(+), 52 deletions(-) diff --git a/src/sage/libs/linkages/padics/API.pxi b/src/sage/libs/linkages/padics/API.pxi index 529fc49a95b..ec69c5bbaa3 100644 --- a/src/sage/libs/linkages/padics/API.pxi +++ b/src/sage/libs/linkages/padics/API.pxi @@ -469,7 +469,7 @@ cdef inline long chash(celement a, long ordp, long prec, PowComputer_class prime # the expansion_mode enum is defined in padic_template_element_header.pxi cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, PowComputer_ prime_pow): - """ + r""" Return the next digit in a `\pi`-adic expansion of ``value``. INPUT: @@ -483,7 +483,7 @@ cdef inline cexpansion_next(celement value, expansion_mode mode, long curpower, pass cdef inline cexpansion_getitem(celement value, long m, PowComputer_ prime_pow): - """ + r""" Return the `m`th `\pi`-adic digit in the ``simple_mode`` expansion. INPUT: @@ -512,7 +512,7 @@ cdef list ccoefficients(celement x, long valshift, PowComputer_class prime_pow): pass cdef int cteichmuller(celement out, celement value, long prec, PowComputer_class prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: diff --git a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi index 8b1b80cf0a9..843070f4a42 100644 --- a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi +++ b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi @@ -668,7 +668,7 @@ cdef list ccoefficients(celement x, long valshift, long prec, PowComputer_ prime return ans cdef int cteichmuller(celement out, celement value, long prec, PowComputer_ prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: @@ -848,7 +848,7 @@ cdef inline int cconv_mpz_t_out(mpz_t out, celement x, long valshift, long prec, ## Extra functions ## cdef cmatrix_mod_pn(celement a, long aprec, long valshift, PowComputer_ prime_pow): - """ + r""" Returns the matrix of right multiplication by the element on the power basis `1, x, x^2, \ldots, x^{d-1}` for this extension field. Thus the *rows* of this matrix give the diff --git a/src/sage/libs/linkages/padics/mpz.pxi b/src/sage/libs/linkages/padics/mpz.pxi index 2844a3934f5..3a555e441dc 100644 --- a/src/sage/libs/linkages/padics/mpz.pxi +++ b/src/sage/libs/linkages/padics/mpz.pxi @@ -568,7 +568,7 @@ cdef list ccoefficients(mpz_t x, long valshift, long prec, PowComputer_ prime_po return [ansq] cdef int cteichmuller(mpz_t out, mpz_t value, long prec, PowComputer_ prime_pow) except -1: - """ + r""" Teichmuller lifting. INPUT: diff --git a/src/sage/libs/linkages/padics/unram_shared.pxi b/src/sage/libs/linkages/padics/unram_shared.pxi index 708cf7ac736..472e7de0b11 100644 --- a/src/sage/libs/linkages/padics/unram_shared.pxi +++ b/src/sage/libs/linkages/padics/unram_shared.pxi @@ -84,7 +84,7 @@ def frobenius_unram(self, arithmetic=True): @cython.binding(True) def norm_unram(self, base = None): - """ + r""" Return the absolute or relative norm of this element. .. WARNING:: @@ -95,9 +95,9 @@ def norm_unram(self, base = None): INPUT: - ``base`` -- a subfield of the parent `L` of this element. - The norm is the relative norm from ``L`` to ``base``. - Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. + ``base`` -- a subfield of the parent `L` of this element. + The norm is the relative norm from ``L`` to ``base``. + Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. EXAMPLES:: @@ -171,7 +171,7 @@ def norm_unram(self, base = None): @cython.binding(True) def trace_unram(self, base = None): - """ + r""" Return the absolute or relative trace of this element. If ``base`` is given then ``base`` must be a subfield of the diff --git a/src/sage/libs/symmetrica/sc.pxi b/src/sage/libs/symmetrica/sc.pxi index 6082527561e..4d9fa4f009d 100644 --- a/src/sage/libs/symmetrica/sc.pxi +++ b/src/sage/libs/symmetrica/sc.pxi @@ -4,6 +4,7 @@ cdef extern from 'symmetrica/def.h': INT kranztafel(OP a, OP b, OP res, OP co, OP cl) INT c_ijk_sn(OP i, OP j, OP k, OP res) + def chartafel_symmetrica(n): """ you enter the degree of the symmetric group, as INTEGER @@ -22,8 +23,7 @@ def chartafel_symmetrica(n): [ 0 -1 2 0 2] [ 1 0 -1 -1 3] [-1 1 1 -1 1] - """ - + """ cdef OP cn, cres cn = callocobject() @@ -41,7 +41,6 @@ def chartafel_symmetrica(n): return res - def charvalue_symmetrica(irred, cls, table=None): """ you enter a PARTITION object part, labelling the irreducible @@ -67,10 +66,8 @@ def charvalue_symmetrica(irred, cls, table=None): sage: m == symmetrica.chartafel(n) True """ - cdef OP cirred, cclass, ctable, cresult - cirred = callocobject() cclass = callocobject() cresult = callocobject() @@ -81,8 +78,6 @@ def charvalue_symmetrica(irred, cls, table=None): ctable = callocobject() _op_matrix(table, ctable) - - #FIXME: assume that class is a partition _op_partition(cls, cclass) @@ -101,42 +96,38 @@ def charvalue_symmetrica(irred, cls, table=None): return res - def kranztafel_symmetrica(a, b): - """ - you enter the INTEGER objects, say a and b, and res becomes a - MATRIX object, the charactertable of S_b \wr S_a, co becomes a - VECTOR object of classorders and cl becomes a VECTOR object of + r""" + you enter the INTEGER objects, say `a` and `b`, and ``res`` becomes a + MATRIX object, the charactertable of `S_b \wr S_a`, ``co`` becomes a + VECTOR object of classorders and ``cl`` becomes a VECTOR object of the classlabels. EXAMPLES:: - sage: (a,b,c) = symmetrica.kranztafel(2,2) - sage: a - [ 1 -1 1 -1 1] - [ 1 1 1 1 1] - [-1 1 1 -1 1] - [ 0 0 2 0 -2] - [-1 -1 1 1 1] - sage: b - [2, 2, 1, 2, 1] - sage: for m in c: print(m) - [0 0] - [0 1] - [0 0] - [1 0] - [0 2] - [0 0] - [1 1] - [0 0] - [2 0] - [0 0] - + sage: (a,b,c) = symmetrica.kranztafel(2,2) + sage: a + [ 1 -1 1 -1 1] + [ 1 1 1 1 1] + [-1 1 1 -1 1] + [ 0 0 2 0 -2] + [-1 -1 1 1 1] + sage: b + [2, 2, 1, 2, 1] + sage: for m in c: print(m) + [0 0] + [0 1] + [0 0] + [1 0] + [0 2] + [0 0] + [1 1] + [0 0] + [2 0] + [0 0] """ - cdef OP ca, cb, cres, cco, ccl - ca = callocobject() cb = callocobject() cres = callocobject() @@ -194,4 +185,3 @@ def kranztafel_symmetrica(a, b): ## freeall(ck) ## return res - diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index 69569297923..753a79090e7 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -1,4 +1,4 @@ -""" +r""" Dense matrices over `\ZZ/n\ZZ` for `n` small using the LinBox library (FFLAS/FFPACK) FFLAS/FFPACK are libraries to provide BLAS/LAPACK-style routines for @@ -857,7 +857,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): cpdef _add_(self, right): - """ + r""" Add two dense matrices over `\Z/n\Z` INPUT: @@ -2284,7 +2284,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): return Matrix_dense.determinant(self) cdef xgcd_eliminate(self, celement * row1, celement* row2, Py_ssize_t start_col): - """ + r""" Reduces ``row1`` and ``row2`` by a unimodular transformation using the xgcd relation between their first coefficients ``a`` and ``b``. @@ -2298,7 +2298,6 @@ cdef class Matrix_modn_dense_template(Matrix_dense): ``row2``. It is assumed that all entries before ``start_col`` in ``row1`` and ``row2`` are zero. - OUTPUT: - g: the gcd of the first elements of row1 and diff --git a/src/sage/symbolic/series_impl.pxi b/src/sage/symbolic/series_impl.pxi index abac6155572..1d979dbc505 100644 --- a/src/sage/symbolic/series_impl.pxi +++ b/src/sage/symbolic/series_impl.pxi @@ -1,4 +1,4 @@ -""" +r""" Symbolic Series Symbolic series are special kinds of symbolic expressions that are From 87fdf668364c3decea7e12144129d2ac5cb40ea2 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 1 Oct 2023 07:37:20 +0000 Subject: [PATCH 194/225] Enable conda ci for all PRs and remove experimental label --- .github/workflows/ci-conda.yml | 19 ------------------- src/doc/en/installation/conda.rst | 5 +---- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 9695dc7ef9a..0d920f67fc3 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -7,13 +7,6 @@ on: branches: - 'public/build/**-runci' pull_request: - types: - # Defaults - - opened - - synchronize - - reopened - # When a CI label is added - - labeled workflow_dispatch: # Allow to run manually @@ -27,18 +20,6 @@ jobs: name: Conda runs-on: ${{ matrix.os }} - # Run on push, workflow dispatch and when certain labels are added or are present - if: | - github.event_name != 'pull_request' || - ((github.event.action != 'labeled' && - (contains(github.event.pull_request.labels.*.name, 'c: packages: standard') || - contains(github.event.pull_request.labels.*.name, 'c: packages: optional') || - contains(github.event.pull_request.labels.*.name, 's: run conda ci'))) || - (github.event.action == 'labeled' && - (github.event.label.name == 'c: packages: optional' || - github.event.label.name == 'c: packages: standard' || - github.event.label.name == 's: run conda ci'))) - strategy: fail-fast: false matrix: diff --git a/src/doc/en/installation/conda.rst b/src/doc/en/installation/conda.rst index 5228611de3b..3606a41fb00 100644 --- a/src/doc/en/installation/conda.rst +++ b/src/doc/en/installation/conda.rst @@ -93,7 +93,7 @@ from source as follows: .. _sec-installation-conda-develop: -Using conda to provide all dependencies for the Sage library (experimental) +Using conda to provide all dependencies for the Sage library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can build and install the Sage library from source, using conda to @@ -101,9 +101,6 @@ provide all of its dependencies. This bypasses most of the build system of the Sage distribution and is the fastest way to set up an environment for Sage development. -Note that this is still an experimental feature and may not work as -intended. - Here we assume that you are using a git checkout. - Optionally, set the build parallelism for the Sage library. Use From 9bc136f9cc72dee1557981b9f9180b4670194c81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 10:04:36 +0200 Subject: [PATCH 195/225] refresh the cython file real_roots (pep8, range, etc) --- src/sage/rings/polynomial/real_roots.pyx | 230 ++++++++++++++--------- 1 file changed, 137 insertions(+), 93 deletions(-) diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 4b5ebac6d8e..13eca002d51 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -490,7 +490,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): sage: bp """ - assert(len(coeffs) > 0) + assert len(coeffs) > 0 self.coeffs = coeffs self.lower = lower self.upper = upper @@ -641,7 +641,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): count_maybe_neg = 0 sign = 0 - for i from 1 <= i < n: + for i in range(1, n): lower_sgn = mpz_sgn(c._entries[i]) upper_sgn = mpz_cmp_si(c._entries[i], -self.error) new_count_maybe_pos = count_maybe_pos @@ -735,7 +735,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): if msign == 0: msign = sign elif sign != 0: - assert(msign == sign) + assert msign == sign cdef Rational absolute_mid = self.lower + mid * (self.upper - self.lower) @@ -916,7 +916,8 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): while True: next = degree_reduction_next_size(bp.degree()) - if next is None: return bp + if next is None: + return bp if bp.variations()[0] > next: return bp (rbp, err_info) = bp.down_degree(ctx, Integer(1) << (max_scale - bp.scale_log2), 32) @@ -971,6 +972,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): rng = rng >> (-self.scale_log2) return rng + def mk_ibpi(coeffs, lower=0, upper=1, lsign=0, usign=0, error=1, scale_log2=0, level=0, slope_err=RIF(0)): """ @@ -987,6 +989,7 @@ def mk_ibpi(coeffs, lower=0, upper=1, lsign=0, usign=0, error=1, scale_log2=0, """ return interval_bernstein_polynomial_integer(vector(ZZ, coeffs), QQ(lower), QQ(upper), lsign, usign, error, scale_log2, level, slope_err) + def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int use_ints): """ Given a polynomial in Bernstein form with integer coefficients @@ -1117,7 +1120,8 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u den_log2 = mpz_sizeinbase(den, 2) - 1 cdef int max_den_bits = c_bitsize / 2 - if max_den_bits < 100: max_den_bits = 100 + if max_den_bits < 100: + max_den_bits = 100 # These settings are slower than the above on laguerre(1000), but that's # the only experiment I've done so far... more testing is needed. # cdef int max_den_bits = 3 * c_bitsize / 2 @@ -1131,21 +1135,21 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u den_powers = FreeModule(ZZ, len(c)+1)(0) mpz_set_ui(den_powers._entries[0], 1) max_den_power = 1 - for i from 1 <= i <= n: + for i in range(1, n + 1): mpz_mul_ui(den_powers._entries[i], den_powers._entries[i-1], den_ui) if mpz_sizeinbase(den_powers._entries[i], 2) < max_den_bits: max_den_power = i else: break - for i from 0 <= i < n: + for i in range(n): mpz_set(c1._entries[i], c2._entries[0]) if den_ui == 2: # x == 1/2 - for j from 0 <= j < n-i-1: + for j in range(n-i-1): mpz_add(c2._entries[j], c2._entries[j], c2._entries[j+1]) else: - for j from 0 <= j < n-i-1: + for j in range(n-i-1): if diff_ui != 1: mpz_mul_ui(c2._entries[j], c2._entries[j], diff_ui) if num_ui == 1: @@ -1185,14 +1189,13 @@ def de_casteljau_intvec(Vector_integer_dense c, int c_bitsize, Rational x, int u # this is equal to a + num*(b-a)/den or diff*(a-b)/den + b. # If num max_exp: max_exp = cur_exp @@ -1308,9 +1309,8 @@ def intvec_to_doublevec(Vector_integer_dense b, long err): cdef int delta = -max_exp cdef double d cdef int new_exp - cdef double half = 0.5 - for i from 0 <= i < len(b): + for i in range(len(b)): d = mpz_get_d_2exp(&cur_exp, b._entries[i]) # 0.5 <= d < 1; b._entries[i] ~= d*2^cur_exp new_exp = cur_exp + delta @@ -1400,7 +1400,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): sage: bp """ - assert(len(coeffs) > 0) + assert len(coeffs) > 0 cdef numpy.ndarray[double, ndim=1] coeffs_data = coeffs._vector_numpy self.coeffs = coeffs self.lower = lower @@ -1517,7 +1517,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): count_maybe_neg = 0 sign = 0 - for i from 1 <= i < n: + for i in range(1, n): new_count_maybe_pos = count_maybe_pos new_count_maybe_neg = count_maybe_neg val = cd[i] @@ -1608,7 +1608,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): if msign == 0: msign = sign elif sign != 0: - assert(msign == sign) + assert msign == sign # As long as new_neg and new_pos have # magnitudes less than 0.5, these computations @@ -1658,9 +1658,6 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): sage: bp.slope_range().str(style='brackets') '[-4.8400000000000017 .. 7.2000000000000011]' """ - cdef unsigned int cwf - # fpu_fix_start(&cwf) - width = self.region_width() (min_diff, max_diff) = min_max_diff_doublevec(self.coeffs) err = self.pos_err - self.neg_err @@ -1697,17 +1694,19 @@ def mk_ibpf(coeffs, lower=0, upper=1, lsign=0, usign=0, neg_err=0, pos_err=0, """ return interval_bernstein_polynomial_float(vector(RDF, coeffs), QQ(lower), QQ(upper), lsign, usign, neg_err, pos_err, scale_log2, level, slope_err) -cdef Rational QQ_1_2 = ZZ(1)/2 -cdef Rational QQ_1_32 = QQ(1)/32 -cdef Rational QQ_31_32 = QQ(31)/32 -cdef Rational zero_QQ = QQ(0) -cdef Rational one_QQ = QQ(1) -cdef Integer zero_ZZ = ZZ(0) -cdef Integer one_ZZ = ZZ(1) + +cdef Rational QQ_1_2 = QQ((1, 2)) +cdef Rational QQ_1_32 = QQ((1, 32)) +cdef Rational QQ_31_32 = QQ((31, 32)) +cdef Rational zero_QQ = QQ.zero() +cdef Rational one_QQ = QQ.one() +cdef Integer zero_ZZ = ZZ.zero() +cdef Integer one_ZZ = ZZ.one() cdef Integer ZZ_2_31 = ZZ(2) ** 31 cdef Integer ZZ_2_32 = ZZ(2) ** 32 cdef RealIntervalFieldElement zero_RIF = RIF(0) + def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): """ Given a polynomial in Bernstein form with floating-point coefficients @@ -1747,9 +1746,6 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): c1 = Vector_real_double_dense(vs, 0) c2 = c.__copy__() - cdef unsigned int cwf - # fpu_fix_start(&cwf) - cdef numpy.ndarray[double, ndim=1] c1d = c1._vector_numpy cdef numpy.ndarray[double, ndim=1] c2d = c2._vector_numpy @@ -1758,16 +1754,14 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): cdef int n = len(c) cdef int i, j - cdef int cur_den_steps = 0 - cdef double rx, rnx cdef int extra_err if x == QQ_1_2: - for i from 0 <= i < n: + for i in range(n): c1d[i] = c2d[0] - for j from 0 <= j < n-i-1: + for j in range(n-i-1): c2d[j] = (c2d[j] + c2d[j+1]) * half # The following code lets us avoid O(n^2) floating-point multiplications @@ -1797,6 +1791,7 @@ def de_casteljau_doublevec(Vector_real_double_dense c, Rational x): return (c1, c2, extra_err) + def max_abs_doublevec(Vector_real_double_dense c): """ Given a floating-point vector, return the maximum of the @@ -1813,12 +1808,14 @@ def max_abs_doublevec(Vector_real_double_dense c): cdef double m = 0 cdef double a - for i from 0 <= i < len(c): + for i in range(len(c)): a = fabs(cd[i]) - if a > m: m = a + if a > m: + m = a return m + def wordsize_rational(a, b, wordsize): """ Given rationals a and b, selects a de Casteljau split point r between @@ -1889,7 +1886,7 @@ def wordsize_rational(a, b, wordsize): while True: rf = fld(a) if cur_size == wordsize: - assert(mpfr_number_p(rf.value)) + assert mpfr_number_p(rf.value) exp = mpfr_get_exp(rf.value) if rf <= -(fld(-b)): if exp <= -3: @@ -1906,11 +1903,14 @@ def wordsize_rational(a, b, wordsize): fld = RealField(cur_size, rnd='RNDU') r = rf.exact_rational() - if sub_1: r = r + one_QQ - if swap_01: r = one_QQ - r + if sub_1: + r = r + one_QQ + if swap_01: + r = one_QQ - r # assert 0 <= r <= 1 return r + def relative_bounds(a, b): """ INPUT: @@ -1936,6 +1936,7 @@ def relative_bounds(a, b): width = ah - al return ((bl - al) / width, (bh - al) / width) + cdef int bitsize(Integer a): """ Compute the number of bits required to write a given integer @@ -1959,9 +1960,11 @@ cdef int bitsize(Integer a): """ return int(mpz_sizeinbase(a.value, 2)) + def bitsize_doctest(n): return bitsize(n) + def degree_reduction_next_size(n): """ Given n (a polynomial degree), returns either a smaller integer or None. @@ -1992,11 +1995,14 @@ def degree_reduction_next_size(n): # computing the exact inverse of a k by k matrix seems infeasible # for k much larger than 30.) - if n <= 2: return None + if n <= 2: + return None next = n * 3 // 4 - if next > 30: next = 30 + if next > 30: + next = 30 return next + def precompute_degree_reduction_cache(n): """ Compute and cache the matrices used for degree reduction, starting @@ -2020,7 +2026,8 @@ def precompute_degree_reduction_cache(n): ) """ while True: - if n in dr_cache: return + if n in dr_cache: + return next = degree_reduction_next_size(n) if next is None: dr_cache[n] = (None, None, 0) @@ -2052,6 +2059,7 @@ def precompute_degree_reduction_cache(n): dr_cache[n] = (next, bd, expected_err.floor(), (bdi, bdd)) n = next + def bernstein_down(d1, d2, s): """ Given polynomial degrees d1 and d2 (where d1 < d2), and a number @@ -2088,10 +2096,12 @@ def bernstein_down(d1, d2, s): return pseudoinverse(bernstein_up(d1, d2, s)) + def pseudoinverse(m): mt = m.transpose() return ~(mt * m) * mt + def bernstein_up(d1, d2, s=None): """ Given polynomial degrees d1 and d2, where d1 < d2, compute a matrix bu. @@ -2114,7 +2124,8 @@ def bernstein_up(d1, d2, s=None): [ 8/15 -4 16/3 -13/15] [ -2/5 3 -4 12/5] """ - if s is None: s = d1 + 1 + if s is None: + s = d1 + 1 MS = MatrixSpace(QQ, s, d1+1, sparse=False) m = MS() scale = factorial(d2)/factorial(d2-d1) @@ -2129,6 +2140,7 @@ def bernstein_up(d1, d2, s=None): return m + cdef int subsample_vec(int a, int slen, int llen): """ Given a vector of length llen, and slen < llen, we want to @@ -2176,10 +2188,12 @@ def maximum_root_first_lambda(p): 1.00000000000000 """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] return cl_maximum_root_first_lambda(cl) + def cl_maximum_root_first_lambda(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2204,7 +2218,7 @@ def cl_maximum_root_first_lambda(cl): Real Field with 53 bits of precision and rounding RNDU) """ n = len(cl) - 1 - assert(cl[n] > 0) + assert cl[n] > 0 pending_pos_coeff = cl[n] pending_pos_exp = n lastPos = True @@ -2242,6 +2256,7 @@ def cl_maximum_root_first_lambda(cl): return max_ub_log.upper().exp() + def maximum_root_local_max(p): r""" Given a polynomial with real coefficients, computes an upper bound @@ -2261,10 +2276,12 @@ def maximum_root_local_max(p): 1.41421356237310 """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] return cl_maximum_root_local_max(cl) + def cl_maximum_root_local_max(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2282,7 +2299,7 @@ def cl_maximum_root_local_max(cl): 1.41421356237310 """ n = len(cl) - 1 - assert(cl[n] > 0) + assert cl[n] > 0 max_pos_coeff = cl[n] max_pos_exp = n max_pos_uses = 0 @@ -2300,6 +2317,7 @@ def cl_maximum_root_local_max(cl): return max_ub_log.upper().exp() + def cl_maximum_root(cl): r""" Given a polynomial represented by a list of its coefficients @@ -2321,6 +2339,7 @@ def cl_maximum_root(cl): return min(cl_maximum_root_first_lambda(cl), cl_maximum_root_local_max(cl)) + def root_bounds(p): r""" Given a polynomial with real coefficients, computes a lower and @@ -2350,7 +2369,8 @@ def root_bounds(p): True """ n = p.degree() - if p[n] < 0: p = -p + if p[n] < 0: + p = -p cl = [RIF(x) for x in p.list()] cdef int zero_roots = 0 @@ -2390,6 +2410,7 @@ def root_bounds(p): return (lb, ub) + def rational_root_bounds(p): """ Given a polynomial p with real coefficients, computes rationals @@ -2497,9 +2518,11 @@ def rational_root_bounds(p): return (rlb, rub) + class PrecisionError(ValueError): pass + class bernstein_polynomial_factory: """ An abstract base class for bernstein_polynomial factories. That @@ -2519,8 +2542,10 @@ class bernstein_polynomial_factory: """ def _sign(self, v): - if v > 0: return 1 - if v < 0: return -1 + if v > 0: + return 1 + if v < 0: + return -1 return 0 def lsign(self): @@ -2537,6 +2562,7 @@ class bernstein_polynomial_factory: """ return self._sign(self.coeffs[-1]) + class bernstein_polynomial_factory_intlist(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented @@ -2615,6 +2641,7 @@ class bernstein_polynomial_factory_intlist(bernstein_polynomial_factory): return interval_bernstein_polynomial_integer((ZZ ** len(b))(intv_b), zero_QQ, one_QQ, self.lsign(), self.usign(), 1, scale_log2, 0, zero_RIF) # return bp_of_intlist(self.coeffs, scale_log2) + class bernstein_polynomial_factory_ratlist(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented @@ -2699,6 +2726,7 @@ class bernstein_polynomial_factory_ratlist(bernstein_polynomial_factory): return interval_bernstein_polynomial_integer((ZZ ** len(b))(intv_b), zero_QQ, one_QQ, self.lsign(), self.usign(), 1, scale_log2, 0, zero_RIF) # return bp_of_ratlist(self.coeffs, scale_log2) + class bernstein_polynomial_factory_ar(bernstein_polynomial_factory): """ This class holds an exact Bernstein polynomial (represented as a @@ -2860,7 +2888,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list cdef rr_gap r split_targets = [] - for (l,r,_) in target_list: + for l, r, _ in target_list: if l is None: split_targets += [(QQ(0), None, 0)] else: @@ -2869,7 +2897,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list if lbounds[0] > 0: out_of_bounds = True if r is None: - split_targets += [(QQ(1), None, 0)] + split_targets += [(QQ.one(), None, 0)] else: rbounds = relative_bounds(bounds, r.region()) split_targets += [(rbounds[0], rbounds[1], r.sign)] @@ -2895,7 +2923,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list split = wordsize_rational(split_targets[best_index][0], split_targets[best_index][1], ctx.wordsize) (p1_, p2_, ok) = bp.de_casteljau(ctx, split, msign=split_targets[best_index][2]) - assert(ok) + assert ok cdef interval_bernstein_polynomial p1 = p1_ cdef interval_bernstein_polynomial p2 = p2_ @@ -2918,17 +2946,15 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list tl1 = target_list[:target_list_splitpoint] tl2 = target_list[target_list_splitpoint:] - tiny = ~Integer(32) - if len(tl1) > 0: - if True: # p1.region_width() / bp.region_width() < tiny: + if True: # p1.region_width() / bp.region_width() < tiny: max_lsb = max([t[2] for t in tl1]) p1 = p1.down_degree_iter(ctx, max_lsb) r1 = split_for_targets(ctx, p1, tl1) else: r1 = [] if len(tl2) > 0: - if True: # p2.region_width() / bp.region_width() < tiny: + if True: # p2.region_width() / bp.region_width() < tiny: max_lsb = max([t[2] for t in tl2]) p2 = p2.down_degree_iter(ctx, max_lsb) r2 = split_for_targets(ctx, p2, tl2) @@ -2937,6 +2963,7 @@ def split_for_targets(context ctx, interval_bernstein_polynomial bp, target_list return r1 + r2 + cdef class ocean: """ Given the tools we've defined so far, there are many possible root @@ -3225,6 +3252,7 @@ cdef class ocean: isle = active_islands[i] isle.bp = bp + cdef class island: """ This implements the island portion of my ocean-island root isolation @@ -3530,7 +3558,7 @@ cdef class island: return else: self.refine_recurse(ctx, p1, ancestors, history, False) - assert(self.lgap.upper == p2.lower) + assert self.lgap.upper == p2.lower bp = p2 # return to top of function (tail recursion optimization) @@ -3567,7 +3595,8 @@ cdef class island: """ cur_msb = bp.scale_log2 + bp.bitsize extra_bits = bp.bitsize // 2 - if extra_bits < 30: extra_bits = 30 + if extra_bits < 30: + extra_bits = 30 target_lsb_h = cur_msb - 3*extra_bits target_lsb = cur_msb - 4*extra_bits @@ -3584,8 +3613,6 @@ cdef class island: for i in range(len(ancestors)-1, -1, -1): anc = ancestors[i] if target_lsb_h >= anc.scale_log2: - ancestor_bitsize = anc.bitsize - ancestor_msb = anc.scale_log2 + ancestor_bitsize ancestor_val = anc first_lsb = ancestor_val.scale_log2 first_msb = first_lsb + ancestor_val.bitsize @@ -3629,7 +3656,7 @@ cdef class island: ancestor_val = ancestor_val.down_degree_iter(ctx, target_lsb_h) rel_bounds = relative_bounds(ancestor_val.region(), bp.region()) - assert(rel_bounds[1] == 1) + assert rel_bounds[1] == 1 ancestor_val = split_for_targets(ctx, ancestor_val, [(self.lgap, maybe_rgap, target_lsb_h)])[0] # if rel_lbounds[1] > 0: @@ -3641,7 +3668,7 @@ cdef class island: ancestor_val.usign = bp.usign new_rel_bounds = relative_bounds(ancestor_val.region(), bp.region()) - assert(new_rel_bounds[1] - new_rel_bounds[0] >= Integer(255)/256) + assert new_rel_bounds[1] - new_rel_bounds[0] >= Integer(255)/256 while ancestor_val.scale_log2 < target_lsb_l: ancestors = ancestors + [ancestor_val] @@ -3701,7 +3728,6 @@ cdef class island: return True return False - def done(self, context ctx): """ Check to see if the island is known to contain zero roots or @@ -3725,11 +3751,11 @@ cdef class island: Assuming that the island is done (has either 0 or 1 roots), reports whether the island has a root. """ - - assert(self.known_done) + assert self.known_done return bool(self.bp.max_variations) + cdef class rr_gap: """ A simple class representing the gaps between islands, in my @@ -3748,6 +3774,7 @@ cdef class rr_gap: def region(self): return (self.lower, self.upper) + class linear_map: """ A simple class to map linearly between original coordinates @@ -3768,8 +3795,10 @@ class linear_map: (l, u) = region return ((l - self.lower) / self.width, (u - self.lower) / self.width) + lmap = linear_map(0, 1) + class warp_map: """ A class to map between original coordinates and ocean coordinates. @@ -3798,6 +3827,7 @@ class warp_map: else: return (l/(l+1), u/(u+1)) + def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=False, wordsize=32, retval='rational', strategy=None, max_diameter=None): """ Compute the real roots of a given polynomial with exact @@ -3996,12 +4026,14 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals if ar_input and bounds is not None: raise NotImplementedError("Cannot set your own bounds with algebraic real input") - if ar_input: strategy = 'warp' + if ar_input: + strategy = 'warp' - if bounds is not None and strategy=='warp': + if bounds is not None and strategy == 'warp': raise NotImplementedError("Cannot set your own bounds with strategy=warp") - if seed is None: seed = 1 + if seed is None: + seed = 1 if skip_squarefree: factors = [(p, 1)] @@ -4086,7 +4118,6 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals target_widths = [None] * len(all_roots) - if max_diameter is not None: # Check to make sure that no intervals are too wide. @@ -4108,7 +4139,6 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals target_widths[i] = (root[1] - root[0]) / cur_diam * half_diameter ok = False - for i in range(len(all_roots) - 1): # Check to be sure that all intervals are disjoint. if all_roots[i][0][1] >= all_roots[i+1][0][0]: @@ -4129,14 +4159,16 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals ocean_target = oc.mapping.to_ocean(target_region) oc.reset_root_width(all_roots[i][4], ocean_target[1] - ocean_target[0]) - if ok: break + if ok: + break - for (oc, factor, exp) in oceans: oc.find_roots() + for (oc, factor, exp) in oceans: + oc.find_roots() if do_logging: return ctx, all_roots - if retval=='rational': + if retval == 'rational': return [(r[0], r[2]) for r in all_roots] for i in range(1000): @@ -4199,6 +4231,7 @@ def scale_intvec_var(Vector_integer_dense c, k): c[i] = c[i] * factor factor = (factor * kn) // kd + def taylor_shift1_intvec(Vector_integer_dense c): """ Given a vector of integers c of length d+1, representing the @@ -4229,6 +4262,7 @@ def taylor_shift1_intvec(Vector_integer_dense c): for k from degree-i <= k < degree: mpz_add(c._entries[k], c._entries[k], c._entries[k+1]) + def reverse_intvec(Vector_integer_dense c): """ Given a vector of integers, reverse the vector (like the reverse() @@ -4250,8 +4284,10 @@ def reverse_intvec(Vector_integer_dense c): for i from 0 <= i < c_len // 2: mpz_swap(c._entries[i], c._entries[c_len - 1 - i]) + realfield_rndu_cache = {} + def get_realfield_rndu(n): """ A simple cache for RealField fields (with rounding set to @@ -4274,6 +4310,7 @@ def get_realfield_rndu(n): realfield_rndu_cache[n] = fld return fld + cdef class context: """ A simple context class, which is passed through parts of the @@ -4287,7 +4324,7 @@ cdef class context: """ Initialize a context class. """ - self.seed = seed # saved to make context printable + self.seed = seed # saved to make context printable self.random = randstate().python_random(seed=seed) self.do_logging = do_logging self.wordsize = wordsize @@ -4334,6 +4371,7 @@ cdef class context: def get_be_log(self): return self.be_log + def mk_context(do_logging=False, seed=0, wordsize=32): """ A simple wrapper for creating context objects with coercions, @@ -4349,6 +4387,7 @@ def mk_context(do_logging=False, seed=0, wordsize=32): """ return context(do_logging, seed, wordsize) + def to_bernstein(p, low=0, high=1, degree=None): """ Given a polynomial p with integer coefficients, and rational @@ -4374,7 +4413,6 @@ def to_bernstein(p, low=0, high=1, degree=None): sage: to_bernstein(x^3 + x^2 - x - 1, low=3, high=22/7) ([296352, 310464, 325206, 340605], 9261) """ - if degree is None: degree = p.degree() elif degree < p.degree(): @@ -4462,7 +4500,8 @@ def bernstein_expand(Vector_integer_dense c, int d2): # XXX do experimentation here on how to decide when to divide cdef int max_bits = max_bitsize_intvec(c) / 2 - if max_bits < 64: max_bits = 64 + if max_bits < 64: + max_bits = 64 for i from 0 <= i <= d1: mpz_set(c2._entries[i], c._entries[i]) @@ -4486,6 +4525,7 @@ def bernstein_expand(Vector_integer_dense c, int d2): return (c2, ndivides) + cdef int max_bitsize_intvec(Vector_integer_dense b): """ Given an integer vector, find the approximate log2 of the maximum @@ -4501,15 +4541,18 @@ cdef int max_bitsize_intvec(Vector_integer_dense b): cdef int i cdef int size - for i from 0 <= i < len(b): + for i in range(len(b)): size = mpz_sizeinbase(b._entries[i], 2) - if size > max_bits: max_bits = size + if size > max_bits: + max_bits = size return max_bits + def max_bitsize_intvec_doctest(b): return max_bitsize_intvec(b) + def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): """ Computes the dot product of row k of the matrix m with the vector v @@ -4539,9 +4582,8 @@ def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): sage: dprod_imatrow_vec(m, vector(ZZ, [1, 2, 3]), 1) 26 """ - - assert(0 <= k < m.nrows()) - assert(m.ncols() <= len(v)) + assert 0 <= k < m.nrows() + assert m.ncols() <= len(v) cdef Integer sum = Integer(0) @@ -4552,13 +4594,14 @@ def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): cdef int ra cdef int a mpz_init(tmp) - for a from 0 <= a < msize: + for a in ragne(msize): ra = subsample_vec(a, msize, vsize) - m.get_unsafe_mpz(k,a,tmp) + m.get_unsafe_mpz(k, a, tmp) mpz_addmul(sum.value, tmp, v._entries[ra]) mpz_clear(tmp) return sum + def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): """ Given two integer vectors a and b (of equal, nonzero length), return @@ -4572,9 +4615,8 @@ def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): sage: min_max_delta_intvec(a, b) (30, -5) """ - - assert(len(a) == len(b)) - assert(len(a) > 0) + assert len(a) == len(b) + assert len(a) > 0 cdef Integer max = Integer() cdef Integer min = Integer() @@ -4594,6 +4636,7 @@ def min_max_delta_intvec(Vector_integer_dense a, Vector_integer_dense b): return (max, min) + def min_max_diff_intvec(Vector_integer_dense b): """ Given an integer vector b = (b0, ..., bn), compute the @@ -4606,7 +4649,7 @@ def min_max_diff_intvec(Vector_integer_dense b): (-9, 6) """ l = len(b) - assert(l > 1) + assert l > 1 cdef Integer min_diff = b[1] - b[0] cdef Integer max_diff = Integer() @@ -4624,6 +4667,7 @@ def min_max_diff_intvec(Vector_integer_dense b): return (min_diff, max_diff) + def min_max_diff_doublevec(Vector_real_double_dense c): """ Given a floating-point vector b = (b0, ..., bn), compute the @@ -4638,7 +4682,7 @@ def min_max_diff_doublevec(Vector_real_double_dense c): cdef numpy.ndarray[double, ndim=1] cd = c._vector_numpy l = len(c) - assert(l > 1) + assert l > 1 cdef double min_diff = cd[1] - cd[0] cdef double max_diff = min_diff From 355b39cce59ad9e5cb3e5c8b16915410e83f8591 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Sun, 1 Oct 2023 16:07:56 +0800 Subject: [PATCH 196/225] Remove --enable-system-site-packages for now --- pkgs/sage-conf_conda/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 21977a81ca4..9e8ac353f4f 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -32,7 +32,7 @@ def run(self): print(f'Reusing configured SAGE_ROOT={SAGE_ROOT}') else: cmd = f"cd {SAGE_ROOT} && ./configure --enable-build-as-root --with-system-python3=force --disable-notebook --disable-sagelib --disable-sage_conf --disable-doc" - cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX" --enable-system-site-packages' + cmd += ' --with-python=$CONDA_PREFIX/bin/python --prefix="$CONDA_PREFIX"' cmd += ' $(for pkg in $(PATH="build/bin:$PATH" build/bin/sage-package list :standard: --exclude rpy2 --has-file spkg-configure.m4 --has-file distros/conda.txt); do echo --with-system-$pkg=force; done)' print(f"Running {cmd}") sys.stdout.flush() From 966470e3b90782757429a1f7bceab44f899bed65 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 22 Sep 2023 19:56:13 -0400 Subject: [PATCH 197/225] src/sage/interfaces/gap_workspace.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/interfaces/gap_workspace.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/interfaces/gap_workspace.py b/src/sage/interfaces/gap_workspace.py index 03b40be6856..c104664143a 100644 --- a/src/sage/interfaces/gap_workspace.py +++ b/src/sage/interfaces/gap_workspace.py @@ -88,7 +88,9 @@ def prepare_workspace_dir(dir=None): TESTS:: - sage: prepare_workspace_dir(os.path.join(tmp_dir(), "new")) + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: prepare_workspace_dir(os.path.join(d, "new")) '.../new' """ if dir is None: From 17285d947a1738dc447b8c498c02cf69c4d8158c Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 23 Sep 2023 15:56:03 -0400 Subject: [PATCH 198/225] src/sage/databases/sql_db.py: replace tmp_dir() Standard tempfile.TemporaryDirectory() replacement. Issue: https://github.com/sagemath/sage/issues/36322 --- src/sage/databases/sql_db.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/sage/databases/sql_db.py b/src/sage/databases/sql_db.py index 299d917aed6..4c5d439eda0 100644 --- a/src/sage/databases/sql_db.py +++ b/src/sage/databases/sql_db.py @@ -1026,16 +1026,19 @@ def __init__(self, filename=None, read_only=None, skeleton=None): NOTE: The values of ``display_cols`` are always concatenated in intersections and unions. - Of course, we can save the database to file:: + Of course, we can save the database to file. Here we use a + temporary directory that we clean up afterwards:: - sage: replace_with_your_own_filepath = tmp_dir() - sage: D.save(replace_with_your_own_filepath + 'simon.db') + sage: import tempfile + sage: d = tempfile.TemporaryDirectory() + sage: dbpath = os.path.join(d.name, 'simon.db') + sage: D.save(dbpath) Now the database's hard link is to this file, and not the temporary db file. For example, let's say we open the same file with another class instance. We can load the file as an immutable database:: - sage: E = SQLDatabase(replace_with_your_own_filepath + 'simon.db') + sage: E = SQLDatabase(dbpath) sage: E.show('simon') graph6 vertices edges ------------------------------------------------------------ @@ -1062,6 +1065,11 @@ def __init__(self, filename=None, read_only=None, skeleton=None): Traceback (most recent call last): ... RuntimeError: Cannot drop tables from a read only database. + + Call ``cleanup()`` on the temporary directory to, well, clean it up:: + + sage: d.cleanup() + """ if filename is None: if read_only is None: @@ -1111,10 +1119,12 @@ def __repr__(self): EXAMPLES:: - sage: replace_with_filepath = tmp_dir() + 'test.db' - sage: SD = SQLDatabase(replace_with_filepath, False) - sage: SD.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) - sage: print(SD) + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: dbpath = os.path.join(d, "test.db") + ....: SD = SQLDatabase(dbpath, False) + ....: SD.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) + ....: print(SD) table simon: column n: index: True; primary_key: False; sql: INTEGER; unique: False; @@ -1182,10 +1192,12 @@ def save(self, filename): sage: MonicPolys = SQLDatabase() sage: MonicPolys.create_table('simon', {'n':{'sql':'INTEGER', 'index':True}}) sage: for n in range(20): MonicPolys.add_row('simon', (n,)) - sage: tmp = tmp_dir() # replace with your own file path - sage: MonicPolys.save(tmp+'sage.db') - sage: N = SQLDatabase(tmp+'sage.db') - sage: N.show('simon') + sage: import tempfile + sage: with tempfile.TemporaryDirectory() as d: + ....: dbpath = os.path.join(d, "sage.db") + ....: MonicPolys.save(dbpath) + ....: N = SQLDatabase(dbpath) + ....: N.show('simon') n -------------------- 0 From 064afd271724384d6da4c9ee3179c6e7bc8de8ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 13:56:19 +0200 Subject: [PATCH 199/225] clean one test file --- src/sage/tests/benchmark.py | 528 +++++++++++++++++------------------- 1 file changed, 247 insertions(+), 281 deletions(-) diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index 6ac0136c653..81928df75c0 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -14,11 +14,9 @@ sage: import sage.tests.benchmark """ - from cysignals.alarm import alarm, cancel_alarm, AlarmInterrupt from sage.combinat.combinat import fibonacci from sage.functions.other import factorial -from sage.interfaces.gap import gap from sage.interfaces.gp import gp from sage.interfaces.macaulay2 import macaulay2 from sage.interfaces.magma import magma, Magma @@ -27,6 +25,7 @@ from sage.interfaces.maxima import maxima from sage.interfaces.singular import singular from sage.libs.pari import pari +from sage.lib.libgap import libgap from sage.matrix.matrix_space import MatrixSpace from sage.misc.functional import log from sage.misc.timing import cputime, walltime @@ -40,6 +39,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.schemes.elliptic_curves.constructor import EllipticCurve + def avg(X): """ Return the average of the list X. @@ -50,13 +50,14 @@ def avg(X): sage: avg([1,2,3]) 2.0 """ - s = sum(X,0) - return s/float(len(X)) + s = sum(X, 0) + return s / float(len(X)) STD_SYSTEMS = ['sage', 'maxima', 'gap', 'gp', 'pari', 'python'] OPT_SYSTEMS = ['magma', 'macaulay2', 'maple', 'mathematica'] + class Benchmark: """ A class for running specific benchmarks against different systems. @@ -133,12 +134,12 @@ def run(self, systems=None, timeout=60, trials=1, sort=False, optional=False): mn = min(X) mx = max(X) av = avg(X) - s = '* %-12s%-12f%-12f%-12f%-12s'%(S, mn, av, - mx, trials) + s = '* %-12s%-12f%-12f%-12f%-12s' % (S, mn, av, + mx, trials) if wall: - s += '%15fw'%t + s += '%15fw' % t else: - s += '%15fc'%t + s += '%15fc' % t print(s) except AlarmInterrupt: print('%-12sinterrupted (timeout: %s seconds wall time)' % @@ -188,7 +189,7 @@ def __init__(self, n): 99-Division polynomial """ self.__n = n - self.repr_str = "%s-Division polynomial"%self.__n + self.repr_str = "%s-Division polynomial" % self.__n def sage(self): """ @@ -200,11 +201,10 @@ def sage(self): sage: B = Divpoly(3) sage: isinstance(B.sage(), float) True - """ n = self.__n t = cputime() - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) E.division_polynomial(n) return cputime(t) @@ -222,14 +222,15 @@ def magma(self): """ n = self.__n t = magma.cputime() - magma('DivisionPolynomial(EllipticCurve([1,2,3,4,5]), %s)'%n) + magma('DivisionPolynomial(EllipticCurve([1,2,3,4,5]), %s)' % n) return magma.cputime(t) + class PolySquare(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Square a polynomial of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Square a polynomial of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -241,11 +242,10 @@ def sage(self): sage: B = PolySquare(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = R['x'](range(1,n+1)) + f = R['x'](range(1, n + 1)) t = cputime() f**2 return cputime(t) @@ -260,12 +260,11 @@ def magma(self): sage: B = PolySquare(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('PolynomialRing(%s)![1..%s]'%(R.name(),self.__n)) + f = magma('PolynomialRing(%s)![1..%s]' % (R.name(), self.__n)) t = magma.cputime() - f*f + f * f return magma.cputime(t) def maple(self): @@ -284,18 +283,19 @@ def maple(self): if not (R == ZZ or R == QQ): raise NotImplementedError n = self.__n - f = maple(str(R['x'](range(1,n+1)))) + f = maple(str(R['x'](range(1, n + 1)))) t = walltime() - f*f + f * f return False, walltime(t) + class MPolynomialPower(Benchmark): def __init__(self, nvars=2, exp=10, base=QQ, allow_singular=True): self.nvars = nvars self.exp = exp self.base = base self.allow_singular = allow_singular - s = 'Compute (x_0 + ... + x_%s)^%s over %s'%( + s = 'Compute (x_0 + ... + x_%s)^%s over %s' % ( self.nvars - 1, self.exp, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' @@ -396,14 +396,14 @@ def mathematica(self): (z**self.exp).Expand() return False, walltime(w) -## this doesn't really expand out -- pari has no function to do so, -## as far as I know. -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## z = gp(str(sum(R.gens()))) -## gp.eval('gettime') -## z**self.exp -## return float(gp.eval('gettime/1000.0')) +# this doesn't really expand out -- pari has no function to do so, +# as far as I know. +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# z = gp(str(sum(R.gens()))) +# gp.eval('gettime') +# z**self.exp +# return float(gp.eval('gettime/1000.0')) def magma(self): """ @@ -419,7 +419,7 @@ def magma(self): """ R = magma.PolynomialRing(self.base, self.nvars) z = R.gen(1) - for i in range(2,self.nvars+1): + for i in range(2, self.nvars + 1): z += R.gen(i) t = magma.cputime() z**magma(self.exp) @@ -428,13 +428,13 @@ def magma(self): class MPolynomialMult(Benchmark): def __init__(self, nvars=2, base=QQ, allow_singular=True): - if nvars%2: + if nvars % 2: nvars += 1 self.nvars = nvars self.base = base self.allow_singular = allow_singular - s = 'Compute (x_0 + ... + x_%s) * (x_%s + ... + x_%s) over %s'%( - self.nvars/2 - 1, self.nvars/2, self.nvars, self.base) + s = 'Compute (x_0 + ... + x_%s) * (x_%s + ... + x_%s) over %s' % ( + self.nvars // 2 - 1, self.nvars // 2, self.nvars, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' self.repr_str = s @@ -449,14 +449,13 @@ def maxima(self): sage: B = MPolynomialMult() sage: isinstance(B.maxima()[1], float) True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = maxima(str(sum(R.gens()[:k]))) z1 = maxima(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def maple(self): @@ -469,14 +468,13 @@ def maple(self): sage: B = MPolynomialMult() sage: isinstance(B.maple()[1], float) # optional - maple True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = maple(str(sum(R.gens()[:k]))) z1 = maple(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def mathematica(self): @@ -496,17 +494,17 @@ def mathematica(self): z0 = mathematica(str(sum(R.gens()[:k]))) z1 = mathematica(str(sum(R.gens()[k:]))) w = walltime() - (z0*z1).Expand() + (z0 * z1).Expand() return False, walltime(w) -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## k = self.nvars // 2 -## z0 = gp(str(sum(R.gens()[:k]))) -## z1 = gp(str(sum(R.gens()[k:]))) -## gp.eval('gettime') -## z0*z1 -## return float(gp.eval('gettime/1000.0')) +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# k = self.nvars // 2 +# z0 = gp(str(sum(R.gens()[:k]))) +# z1 = gp(str(sum(R.gens()[k:]))) +# gp.eval('gettime') +# z0*z1 +# return float(gp.eval('gettime/1000.0')) def sage(self): """ @@ -528,7 +526,7 @@ def sage(self): z0 = singular(z0) z1 = singular(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) else: t = cputime() @@ -545,14 +543,13 @@ def macaulay2(self): sage: B = MPolynomialMult() sage: isinstance(B.macaulay2()[1], float) # optional - macaulay2 True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = macaulay2(sum(R.gens()[:k])) z1 = macaulay2(sum(R.gens()[k:])) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) def magma(self): @@ -570,43 +567,44 @@ def magma(self): R = magma.PolynomialRing(self.base, self.nvars) z0 = R.gen(1) k = self.nvars // 2 - for i in range(2,k+1): + for i in range(2, k + 1): z0 += R.gen(i) z1 = R.gen(k + 1) - for i in range(k+1, self.nvars + 1): + for i in range(k + 1, self.nvars + 1): z1 += R.gen(i) t = magma.cputime() z0 * z1 return magma.cputime(t) + class MPolynomialMult2(Benchmark): def __init__(self, nvars=2, base=QQ, allow_singular=True): - if nvars%2: + if nvars % 2: nvars += 1 self.nvars = nvars self.base = base self.allow_singular = allow_singular - s = 'Compute (x_1 + 2*x_2 + 3*x_3 + ... + %s*x_%s) * (%s * x_%s + ... + %s*x_%s) over %s'%( - self.nvars/2, self.nvars/2, self.nvars/2+1, self.nvars/2+1, - self.nvars+1, self.nvars+1, self.base) + s = 'Compute (x_1 + 2*x_2 + 3*x_3 + ... + %s*x_%s) * (%s * x_%s + ... + %s*x_%s) over %s' % ( + self.nvars // 2, self.nvars // 2, self.nvars // 2 + 1, self.nvars // 2 + 1, + self.nvars + 1, self.nvars + 1, self.base) if self.allow_singular: s += ' (use singular for Sage mult.)' self.repr_str = s -## def gp(self): -## R = PolynomialRing(self.base, self.nvars) -## k = self.nvars // 2 -## z0 = R(0) -## z1 = R(0) -## for i in range(k): -## z0 += (i+1)*R.gen(i) -## for i in range(k,self.nvars): -## z1 += (i+1)*R.gen(i) -## z0 = gp(str(z0)) -## z1 = gp(str(z1)) -## gp.eval('gettime') -## z0*z1 -## return float(gp.eval('gettime/1000.0')) +# def gp(self): +# R = PolynomialRing(self.base, self.nvars) +# k = self.nvars // 2 +# z0 = R(0) +# z1 = R(0) +# for i in range(k): +# z0 += (i+1)*R.gen(i) +# for i in range(k,self.nvars): +# z1 += (i+1)*R.gen(i) +# z0 = gp(str(z0)) +# z1 = gp(str(z1)) +# gp.eval('gettime') +# z0*z1 +# return float(gp.eval('gettime/1000.0')) def maxima(self): """ @@ -618,20 +616,19 @@ def maxima(self): sage: B = MPolynomialMult2() sage: isinstance(B.maxima()[1], float) True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = maxima(str(z0)) z1 = maxima(str(z1)) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def macaulay2(self): @@ -644,20 +641,19 @@ def macaulay2(self): sage: B = MPolynomialMult2() sage: isinstance(B.macaulay2()[1], float) # optional - macaulay2 True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = macaulay2(z0) z1 = macaulay2(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) def maple(self): @@ -670,20 +666,19 @@ def maple(self): sage: B = MPolynomialMult2() sage: isinstance(B.maple()[1], float) # optional - maple True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = maple(str(z0)) z1 = maple(str(z1)) w = walltime() - (z0*z1).expand() + (z0 * z1).expand() return False, walltime(w) def mathematica(self): @@ -696,20 +691,19 @@ def mathematica(self): sage: B = MPolynomialMult2() sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ R = PolynomialRing(self.base, self.nvars, 'x') k = self.nvars // 2 z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) z0 = mathematica(str(z0)) z1 = mathematica(str(z1)) w = walltime() - (z0*z1).Expand() + (z0 * z1).Expand() return False, walltime(w) def sage(self): @@ -729,14 +723,14 @@ def sage(self): z0 = R(0) z1 = R(0) for i in range(k): - z0 += (i+1)*R.gen(i) - for i in range(k,self.nvars): - z1 += (i+1)*R.gen(i) + z0 += (i + 1) * R.gen(i) + for i in range(k, self.nvars): + z1 += (i + 1) * R.gen(i) if self.allow_singular: z0 = singular(z0) z1 = singular(z1) t = walltime() - z0*z1 + z0 * z1 return False, walltime(t) else: t = cputime() @@ -753,28 +747,27 @@ def magma(self): sage: B = MPolynomialMult2() sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma.PolynomialRing(self.base, self.nvars) z0 = R.gen(1) k = self.nvars // 2 - for i in range(2,k+1): - z0 += magma(i)*R.gen(i) + for i in range(2, k + 1): + z0 += magma(i) * R.gen(i) z1 = R.gen(k + 1) - for i in range(k+1, self.nvars + 1): - z1 += magma(i)*R.gen(i) + for i in range(k + 1, self.nvars + 1): + z1 += magma(i) * R.gen(i) t = magma.cputime() z0 * z1 return magma.cputime(t) class CharPolyTp(Benchmark): - def __init__(self, N=37,k=2,p=2,sign=1): + def __init__(self, N=37, k=2, p=2, sign=1): self.N = N self.k = k self.p = p self.sign = sign - self.repr_str = "Compute the charpoly (given the matrix) of T_%s on S_%s(Gamma_0(%s)) with sign %s."%(self.p, self.k, self.N, self.sign) + self.repr_str = "Compute the charpoly (given the matrix) of T_%s on S_%s(Gamma_0(%s)) with sign %s." % (self.p, self.k, self.N, self.sign) def matrix(self): try: @@ -856,7 +849,7 @@ class PolyFactor(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = "Factor a product of 2 polynomials of degree %s over %s."%(self.__n, self.__R) + self.repr_str = "Factor a product of 2 polynomials of degree %s over %s." % (self.__n, self.__R) def sage(self): """ @@ -868,12 +861,11 @@ def sage(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.sage(), float) True - """ R = PolynomialRing(self.__R, 'x') - f = R(range(1,self.__n+1)) - g = R(range(self.__n+1,2*(self.__n+1))) - h = f*g + f = R(range(1, self.__n + 1)) + g = R(range(self.__n + 1, 2 * (self.__n + 1))) + h = f * g t = cputime() h.factor() return cputime(t) @@ -888,13 +880,12 @@ def magma(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('PolynomialRing(%s)![1..%s]'%(R.name(),self.__n)) - g = magma('PolynomialRing(%s)![%s+1..2*(%s+1)]'%( - R.name(),self.__n,self.__n)) - h = f*g + f = magma('PolynomialRing(%s)![1..%s]' % (R.name(), self.__n)) + g = magma('PolynomialRing(%s)![%s+1..2*(%s+1)]' % ( + R.name(), self.__n, self.__n)) + h = f * g t = magma.cputime() h.Factorization() return magma.cputime(t) @@ -909,12 +900,11 @@ def gp(self): sage: B = PolyFactor(3, QQ) sage: isinstance(B.gp(), float) True - """ R = PolynomialRing(self.__R, 'x') - f = R(range(1,self.__n+1)) - g = R(range(self.__n+1,2*(self.__n+1))) - h = f*g + f = R(range(1, self.__n + 1)) + g = R(range(self.__n + 1, 2 * (self.__n + 1))) + h = f * g f = gp(h) gp.eval('gettime') f.factor() @@ -924,8 +914,8 @@ def gp(self): class SquareInts(Benchmark): def __init__(self, base=10, ndigits=10**5): self.__ndigits = ndigits - self.base =base - self.repr_str = "Square the integer %s^%s"%(self.base, self.__ndigits) + self.base = base + self.repr_str = "Square the integer %s^%s" % (self.base, self.__ndigits) def sage(self): """ @@ -954,9 +944,8 @@ def gp(self): sage: B = SquareInts() sage: isinstance(B.gp(), float) True - """ - n = gp('%s^%s'%(self.base,self.__ndigits)) + n = gp('%s^%s' % (self.base, self.__ndigits)) gp.eval('gettime') n**2 return float(gp.eval('gettime/1000.0')) @@ -971,9 +960,8 @@ def maxima(self): sage: B = SquareInts() sage: isinstance(B.maxima()[1], float) True - """ - n = maxima('%s^%s'%(self.base,self.__ndigits)) + n = maxima('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) @@ -988,9 +976,8 @@ def magma(self): sage: B = SquareInts() sage: isinstance(B.magma(), float) # optional - magma True - """ - n = magma('%s^%s'%(self.base,self.__ndigits)) + n = magma('%s^%s' % (self.base, self.__ndigits)) t = magma.cputime() n**2 return magma.cputime(t) @@ -1022,16 +1009,15 @@ def maple(self): sage: B = SquareInts() sage: isinstance(B.maple()[1], float) # optional - maple True - """ - n = maple('%s^%s'%(self.base,self.__ndigits)) + n = maple('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: @@ -1039,9 +1025,8 @@ def gap(self): sage: B = SquareInts() sage: isinstance(B.gap()[1], float) True - """ - n = gap('%s^%s'%(self.base,self.__ndigits)) + n = libgap('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) @@ -1056,9 +1041,8 @@ def mathematica(self): sage: B = SquareInts() sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ - n = mathematica('%s^%s'%(self.base,self.__ndigits)) + n = mathematica('%s^%s' % (self.base, self.__ndigits)) t = walltime() n**2 return False, walltime(t) @@ -1068,7 +1052,7 @@ class MatrixSquare(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Square a matrix of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Square a matrix of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -1080,11 +1064,10 @@ def sage(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = MatrixSpace(R,n)(list(range(n*n))) + f = MatrixSpace(R, n)(list(range(n * n))) t = cputime() f**2 return cputime(t) @@ -1099,13 +1082,12 @@ def magma(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('MatrixAlgebra(%s, %s)![0..%s^2-1]'%( - R.name(),self.__n, self.__n)) + f = magma('MatrixAlgebra(%s, %s)![0..%s^2-1]' % ( + R.name(), self.__n, self.__n)) t = magma.cputime() - f*f + f * f return magma.cputime(t) def gp(self): @@ -1118,17 +1100,16 @@ def gp(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.gp(), float) True - """ n = self.__n - m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))'%(n,n,n)) + m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))' % (n, n, n)) gp('gettime') - m*m + m * m return float(gp.eval('gettime/1000.0')) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: @@ -1136,19 +1117,18 @@ def gap(self): sage: B = MatrixSquare(3, QQ) sage: isinstance(B.gap()[1], float) True - """ n = self.__n - m = gap(str([list(range(n*k,n*(k+1))) for k in range(n)])) + m = libgap(str([list(range(n * k, n * (k + 1))) for k in range(n)])) t = walltime() - m*m + m * m return False, walltime(t) class Factorial(Benchmark): def __init__(self, n): self.__n = n - self.repr_str = "Compute the factorial of %s"%self.__n + self.repr_str = "Compute the factorial of %s" % self.__n def sage(self): """ @@ -1176,10 +1156,9 @@ def magma(self): sage: B = Factorial(10) sage: isinstance(B.magma(), float) # optional - magma True - """ t = magma.cputime() - magma('&*[1..%s]'%self.__n) # &* is way better than Factorial!! + magma('&*[1..%s]' % self.__n) # &* is way better than Factorial!! return magma.cputime(t) def maple(self): @@ -1209,16 +1188,16 @@ def gp(self): sage: B = Factorial(10) sage: isinstance(B.gp(), float) True - """ gp.eval('gettime') - gp('%s!'%self.__n) + gp('%s!' % self.__n) return float(gp.eval('gettime/1000.0')) + class Fibonacci(Benchmark): def __init__(self, n): self.__n = n - self.repr_str = "Compute the %s-th Fibonacci number"%self.__n + self.repr_str = "Compute the %s-th Fibonacci number" % self.__n def sage(self): """ @@ -1246,15 +1225,14 @@ def magma(self): sage: B = Fibonacci(10) sage: isinstance(B.magma(), float) # optional - magma True - """ t = magma.cputime() - magma('Fibonacci(%s)'%self.__n) + magma('Fibonacci(%s)' % self.__n) return magma.cputime(t) - def gap(self): + def libgap(self): """ - Time the computation in GAP. + Time the computation in libGAP. EXAMPLES:: @@ -1262,9 +1240,8 @@ def gap(self): sage: B = Fibonacci(10) sage: isinstance(B.gap()[1], float) True - """ - n = gap(self.__n) + n = libgap(self.__n) t = walltime() n.Fibonacci() return False, walltime(t) @@ -1296,17 +1273,16 @@ def gp(self): sage: B = Fibonacci(10) sage: isinstance(B.gp(), float) True - """ gp.eval('gettime') - gp('fibonacci(%s)'%self.__n) + gp('fibonacci(%s)' % self.__n) return float(gp.eval('gettime/1000.0')) class SEA(Benchmark): def __init__(self, p): self.__p = p - self.repr_str = "Do SEA on an elliptic curve over GF(%s)"%self.__p + self.repr_str = "Do SEA on an elliptic curve over GF(%s)" % self.__p def sage(self): """ @@ -1318,9 +1294,8 @@ def sage(self): sage: B = SEA(5) sage: isinstance(B.sage()[1], float) True - """ - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) t = walltime() # Note that from pari 2.4.3, the SEA algorithm is used by the # pari library, but only for large primes, so for a better @@ -1339,18 +1314,18 @@ def magma(self): sage: B = SEA(5) sage: isinstance(B.magma(), float) # optional - magma True - """ magma(0) t = magma.cputime() - magma('#EllipticCurve([GF(%s)|1,2,3,4,5])'%(self.__p)) + magma('#EllipticCurve([GF(%s)|1,2,3,4,5])' % (self.__p)) return magma.cputime(t) + class MatrixKernel(Benchmark): def __init__(self, n, R): self.__n = n self.__R = R - self.repr_str = 'Kernel of a matrix of degree %s over %s'%(self.__n, self.__R) + self.repr_str = 'Kernel of a matrix of degree %s over %s' % (self.__n, self.__R) def sage(self): """ @@ -1362,11 +1337,10 @@ def sage(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.sage(), float) True - """ R = self.__R n = self.__n - f = MatrixSpace(R,n,2*n)(list(range(n*(2*n)))) + f = MatrixSpace(R, n, 2 * n)(list(range(n * (2 * n)))) t = cputime() f.kernel() return cputime(t) @@ -1381,11 +1355,10 @@ def magma(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.magma(), float) # optional - magma True - """ R = magma(self.__R) - f = magma('RMatrixSpace(%s, %s, %s)![0..(%s*2*%s)-1]'%( - R.name(),self.__n, 2*self.__n, self.__n, self.__n)) + f = magma('RMatrixSpace(%s, %s, %s)![0..(%s*2*%s)-1]' % ( + R.name(), self.__n, 2 * self.__n, self.__n, self.__n)) t = magma.cputime() f.Kernel() return magma.cputime(t) @@ -1400,19 +1373,19 @@ def gp(self): sage: B = MatrixKernel(3, QQ) sage: isinstance(B.gp(), float) True - """ n = self.__n - m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))'%(n,2*n,n)) + m = gp('matrix(%s,%s,m,n,%s*(m-1)+(n-1))' % (n, 2 * n, n)) gp('gettime') m.matker() return float(gp.eval('gettime/1000.0')) + class ComplexMultiply(Benchmark): def __init__(self, bits_prec, times): self.__bits_prec = bits_prec self.__times = times - self.repr_str = "List of multiplies of two complex numbers with %s bits of precision %s times"%(self.__bits_prec, self.__times) + self.repr_str = "List of multiplies of two complex numbers with %s bits of precision %s times" % (self.__bits_prec, self.__times) def sage(self): """ @@ -1424,12 +1397,11 @@ def sage(self): sage: B = ComplexMultiply(28, 2) sage: isinstance(B.sage(), float) True - """ CC = ComplexField(self.__bits_prec) - s = CC(2).sqrt() + (CC.gen()*2).sqrt() + s = CC(2).sqrt() + (CC.gen() * 2).sqrt() t = cputime() - [s*s for _ in range(self.__times)] + [s * s for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1446,14 +1418,13 @@ def magma(self): .. NOTE:: decimal digits (despite magma docs that say bits!!) - """ - n = int(self.__bits_prec/log(10,2)) + 1 + n = int(self.__bits_prec / log(10, 2)) + 1 CC = magma.ComplexField(n) s = CC(2).Sqrt() + CC.gen(1).Sqrt() t = magma.cputime() - magma.eval('s := %s;'%s.name()) - magma('[s*s : i in [1..%s]]'%self.__times) + magma.eval('s := %s;' % s.name()) + magma('[s*s : i in [1..%s]]' % self.__times) return magma.cputime(t) def gp(self): @@ -1466,20 +1437,20 @@ def gp(self): sage: B = ComplexMultiply(28, 2) sage: isinstance(B.gp(), float) True - """ - n = int(self.__bits_prec/log(10,2)) + 1 + n = int(self.__bits_prec / log(10, 2)) + 1 gp.set_real_precision(n) gp.eval('s = sqrt(2) + sqrt(2*I);') gp.eval('gettime;') - gp('vector(%s,i,s*s)'%self.__times) + gp('vector(%s,i,s*s)' % self.__times) return float(gp.eval('gettime/1000.0')) + class ModularSymbols1(Benchmark): def __init__(self, N, k=2): self.__N = N self.__k = k - self.repr_str = 'Presentation for modular symbols on Gamma_0(%s) of weight %s'%(self.__N, self.__k) + self.repr_str = 'Presentation for modular symbols on Gamma_0(%s) of weight %s' % (self.__N, self.__k) def sage(self): """ @@ -1507,20 +1478,20 @@ def magma(self): sage: B = ModularSymbols1(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared + magma = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared t = magma.cputime() - magma('ModularSymbols(%s, %s)'%(self.__N, self.__k)) + magma('ModularSymbols(%s, %s)' % (self.__N, self.__k)) return magma.cputime(t) + class ModularSymbolsDecomp1(Benchmark): def __init__(self, N, k=2, sign=1, bnd=10): self.N = N self.k = k self.sign = sign self.bnd = bnd - self.repr_str = 'Decomposition of modular symbols on Gamma_0(%s) of weight %s and sign %s'%(self.N, self.k, self.sign) + self.repr_str = 'Decomposition of modular symbols on Gamma_0(%s) of weight %s and sign %s' % (self.N, self.k, self.sign) def sage(self): """ @@ -1532,7 +1503,6 @@ def sage(self): sage: B = ModularSymbolsDecomp1(11) sage: isinstance(B.sage(), float) True - """ t = cputime() M = ModularSymbols(self.N, self.k, sign=self.sign, use_cache=False) @@ -1549,18 +1519,18 @@ def magma(self): sage: B = ModularSymbolsDecomp1(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - m = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared + m = Magma() # new instance since otherwise modsyms are cached, and cache can't be cleared t = m.cputime() - m.eval('Decomposition(ModularSymbols(%s, %s, %s),%s);'%( + m.eval('Decomposition(ModularSymbols(%s, %s, %s),%s);' % ( self.N, self.k, self.sign, self.bnd)) return m.cputime(t) + class EllipticCurveTraces(Benchmark): def __init__(self, B): self.B = B - self.repr_str = "Compute all a_p for the elliptic curve [1,2,3,4,5], for p < %s"%self.B + self.repr_str = "Compute all a_p for the elliptic curve [1,2,3,4,5], for p < %s" % self.B def sage(self): """ @@ -1574,9 +1544,8 @@ def sage(self): Traceback (most recent call last): ... TypeError: ...anlist() got an unexpected keyword argument 'pari_ints' - """ - E = EllipticCurve([1,2,3,4,5]) + E = EllipticCurve([1, 2, 3, 4, 5]) t = cputime() E.anlist(self.B, pari_ints=True) return cputime(t) @@ -1591,17 +1560,17 @@ def magma(self): sage: B = EllipticCurveTraces(11) sage: isinstance(B.magma(), float) # optional - magma True - """ - E = magma.EllipticCurve([1,2,3,4,5]) + E = magma.EllipticCurve([1, 2, 3, 4, 5]) t = magma.cputime() E.TracesOfFrobenius(self.B) return magma.cputime(t) + class EllipticCurvePointMul(Benchmark): def __init__(self, n): self.n = n - self.repr_str = "Compute %s*(0,0) on the elliptic curve [0, 0, 1, -1, 0] over QQ"%self.n + self.repr_str = "Compute %s*(0,0) on the elliptic curve [0, 0, 1, -1, 0] over QQ" % self.n def sage(self): """ @@ -1613,10 +1582,9 @@ def sage(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.sage(), float) True - """ E = EllipticCurve([0, 0, 1, -1, 0]) - P = E([0,0]) + P = E([0, 0]) t = cputime() self.n * P return cputime(t) @@ -1649,11 +1617,10 @@ def gp(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.gp(), float) True - """ E = gp.ellinit('[0, 0, 1, -1, 0]') gp.eval('gettime') - P = gp([0,0]) + P = gp([0, 0]) E.ellmul(P, self.n) return float(gp.eval('gettime/1000.0')) @@ -1667,18 +1634,18 @@ def pari(self): sage: B = EllipticCurvePointMul(11) sage: isinstance(B.pari(), float) True - """ E = pari('ellinit([0, 0, 1, -1, 0])') pari('gettime') - P = pari([0,0]) + P = pari([0, 0]) E.ellmul(P, self.n) return float(pari('gettime/1000.0')) + class EllipticCurveMW(Benchmark): def __init__(self, ainvs): self.ainvs = ainvs - self.repr_str = "Compute generators for the Mordell-Weil group of the elliptic curve %s over QQ"%self.ainvs + self.repr_str = "Compute generators for the Mordell-Weil group of the elliptic curve %s over QQ" % self.ainvs def sage(self): """ @@ -1714,12 +1681,13 @@ def magma(self): E.Generators() return magma.cputime(t) + class FiniteExtFieldMult(Benchmark): - def __init__(self,field,times): + def __init__(self, field, times): self.__times = times self.field = field - self.e = field.gen()**(field.cardinality()/3) - self.f = field.gen()**(2*field.cardinality()/3) + self.e = field.gen()**(field.cardinality() / 3) + self.f = field.gen()**(2 * field.cardinality() / 3) self.repr_str = "Multiply a^(#K/3) with a^(2*#K/3) where a == K.gen()" def sage(self): @@ -1732,12 +1700,11 @@ def sage(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.sage(), float) True - """ e = self.e f = self.f t = cputime() - [e*f for _ in range(self.__times)] + [e * f for _ in range(self.__times)] return cputime(t) def pari(self): @@ -1750,12 +1717,11 @@ def pari(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.pari(), float) True - """ e = self.e.__pari__() f = self.f.__pari__() t = cputime() - [e*f for _ in range(self.__times)] + [e * f for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1768,13 +1734,12 @@ def magma(self): sage: B = FiniteExtFieldMult(GF(9, 'x'), 2) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma.eval('F := GF(%s)'%(self.field.cardinality())) - magma.eval('e := a^Floor(%s/3);'%(self.field.cardinality())) - magma.eval('f := a^Floor(2*%s/3);'%(self.field.cardinality())) + magma.eval('F := GF(%s)' % (self.field.cardinality())) + magma.eval('e := a^Floor(%s/3);' % (self.field.cardinality())) + magma.eval('f := a^Floor(2*%s/3);' % (self.field.cardinality())) t = magma.cputime() - magma('[e*f : i in [1..%s]]'%self.__times) + magma('[e*f : i in [1..%s]]' % self.__times) return magma.cputime(t) @@ -1782,8 +1747,8 @@ class FiniteExtFieldAdd(Benchmark): def __init__(self, field, times): self.__times = times self.field = field - self.e = field.gen()**(field.cardinality()/3) - self.f = field.gen()**(2*field.cardinality()/3) + self.e = field.gen()**(field.cardinality() / 3) + self.f = field.gen()**(2 * field.cardinality() / 3) self.repr_str = "Add a^(#K/3) to a^(2*#K/3) where a == K.gen()" def sage(self): @@ -1796,12 +1761,11 @@ def sage(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.sage(), float) True - """ e = self.e f = self.f t = cputime() - [e+f for _ in range(self.__times)] + [e + f for _ in range(self.__times)] return cputime(t) def pari(self): @@ -1814,12 +1778,11 @@ def pari(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.pari(), float) True - """ e = self.e.__pari__() f = self.f.__pari__() t = cputime() - [e+f for _ in range(self.__times)] + [e + f for _ in range(self.__times)] return cputime(t) def magma(self): @@ -1832,13 +1795,12 @@ def magma(self): sage: B = FiniteExtFieldAdd(GF(9,'x'), 2) sage: isinstance(B.magma(), float) # optional - magma True - """ - magma.eval('F := GF(%s)'%(self.field.cardinality())) - magma.eval('e := a^Floor(%s/3);'%(self.field.cardinality())) - magma.eval('f := a^Floor(2*%s/3);'%(self.field.cardinality())) + magma.eval('F := GF(%s)' % (self.field.cardinality())) + magma.eval('e := a^Floor(%s/3);' % (self.field.cardinality())) + magma.eval('f := a^Floor(2*%s/3);' % (self.field.cardinality())) t = magma.cputime() - magma('[e+f : i in [1..%s]]'%self.__times) + magma('[e+f : i in [1..%s]]' % self.__times) return magma.cputime(t) @@ -1857,60 +1819,61 @@ def magma(self): def suite1(): - PolySquare(10000,QQ).run() - PolySquare(20000,ZZ).run() - PolySquare(50000,GF(5)).run() - PolySquare(20000,Integers(8)).run() + PolySquare(10000, QQ).run() + PolySquare(20000, ZZ).run() + PolySquare(50000, GF(5)).run() + PolySquare(20000, Integers(8)).run() - SquareInts(10,2000000).run() + SquareInts(10, 2000000).run() - MatrixSquare(200,QQ).run() - MatrixSquare(50,ZZ).run() + MatrixSquare(200, QQ).run() + MatrixSquare(50, ZZ).run() - SquareInts(10,150000).run() + SquareInts(10, 150000).run() - Factorial(2*10**6).run(systems=['sage', 'magma']) + Factorial(2 * 10**6).run(systems=['sage', 'magma']) Fibonacci(10**6).run() - Fibonacci(2*10**7).run(systems=["sage", "magma", "mathematica"]) + Fibonacci(2 * 10**7).run(systems=["sage", "magma", "mathematica"]) - MatrixKernel(150,QQ).run() + MatrixKernel(150, QQ).run() - ComplexMultiply(100000,1000) - ComplexMultiply(100,100000) - ComplexMultiply(53,100000) + ComplexMultiply(100000, 1000) + ComplexMultiply(100, 100000) + ComplexMultiply(53, 100000) - PolyFactor(300,ZZ) - PolyFactor(300,GF(19)) - PolyFactor(700,GF(19)) + PolyFactor(300, ZZ) + PolyFactor(300, GF(19)) + PolyFactor(700, GF(19)) - PolyFactor(500,GF(49,'a')) - PolyFactor(100,GF((10007,3),'a')) + PolyFactor(500, GF((9, 2), 'a')) + PolyFactor(100, GF((10007, 3), 'a')) + + CharPolyTp(54, 4).run() + CharPolyTp(389, 2).run() + CharPolyTp(389, 2, sign=0, p=3).run() + CharPolyTp(1000, 2, sign=1, p=2).run(systems=['sage', 'magma']) + CharPolyTp(1, 100, sign=1, p=5).run(systems=['sage', 'magma']) # Sage's multimodular really sucks here! (GP is way better, even) + CharPolyTp(512, sign=1, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(512, sign=0, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(1024, sign=1, p=3).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(2006, sign=1, p=2).run(systems=['sage', 'magma', 'gp']) + CharPolyTp(2006, sign=1, p=2).run(systems=['sage', 'magma']) # gp takes > 1 minute. - CharPolyTp(54,4).run() - CharPolyTp(389,2).run() - CharPolyTp(389,2,sign=0,p=3).run() - CharPolyTp(1000,2,sign=1,p=2).run(systems=['sage','magma']) - CharPolyTp(1,100,sign=1,p=5).run(systems=['sage','magma']) # Sage's multimodular really sucks here! (GP is way better, even) - CharPolyTp(512,sign=1,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(512,sign=0,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(1024,sign=1,p=3).run(systems=['sage','magma','gp']) - CharPolyTp(2006,sign=1,p=2).run(systems=['sage','magma','gp']) - CharPolyTp(2006,sign=1,p=2).run(systems=['sage','magma']) # gp takes > 1 minute. def mpoly(): # This includes a maxima benchmark. Note that # maxima is *shockingly* slow in comparison to Singular or MAGMA. # It is so slow as to be useless, basically, i.e., factor # of 5000 slower than Singular on this example! - MPolynomialPower(nvars=6,exp=10).run() + MPolynomialPower(nvars=6, exp=10).run() main = ['sage', 'magma'] # just the main competitors - MPolynomialPower(nvars=2,exp=200, allow_singular=False).run(main) - MPolynomialPower(nvars=5,exp=10, allow_singular=False).run(main) - MPolynomialPower(nvars=5,exp=30, allow_singular=True).run(main) - MPolynomialPower(nvars=2,exp=1000, allow_singular=True).run(main) - MPolynomialPower(nvars=10,exp=10, allow_singular=True).run(main) - MPolynomialPower(nvars=4,exp=350, base=GF(7), allow_singular=True).run(main) + MPolynomialPower(nvars=2, exp=200, allow_singular=False).run(main) + MPolynomialPower(nvars=5, exp=10, allow_singular=False).run(main) + MPolynomialPower(nvars=5, exp=30, allow_singular=True).run(main) + MPolynomialPower(nvars=2, exp=1000, allow_singular=True).run(main) + MPolynomialPower(nvars=10, exp=10, allow_singular=True).run(main) + MPolynomialPower(nvars=4, exp=350, base=GF(7), allow_singular=True).run(main) MPolynomialMult(200, allow_singular=False).run(main) MPolynomialMult(400, allow_singular=True).run(main) MPolynomialMult(800, allow_singular=True).run(main) @@ -1948,25 +1911,28 @@ def mpoly_all(include_maple=False): MPolynomialMult(400).run(systems=systems) MPolynomialMult2(256).run(systems=systems) MPolynomialMult2(512).run(systems=systems) - MPolynomialPower(nvars=4,exp=50).run(systems=systems) # mathematica wins - MPolynomialPower(nvars=10,exp=10).run(systems=systems) + MPolynomialPower(nvars=4, exp=50).run(systems=systems) # mathematica wins + MPolynomialPower(nvars=10, exp=10).run(systems=systems) + def modsym_present(): - ModularSymbols1(2006,2) - ModularSymbols1(1,50) - ModularSymbols1(1,100) - ModularSymbols1(1,150) - ModularSymbols1(30,8) - ModularSymbols1(225,4) - ModularSymbols1(2,50) - ModularSymbols1(2,100) + ModularSymbols1(2006, 2) + ModularSymbols1(1, 50) + ModularSymbols1(1, 100) + ModularSymbols1(1, 150) + ModularSymbols1(30, 8) + ModularSymbols1(225, 4) + ModularSymbols1(2, 50) + ModularSymbols1(2, 100) + def modsym_decomp(): - ModularSymbolsDecomp1(1,24).run() - ModularSymbolsDecomp1(125,2).run() - ModularSymbolsDecomp1(389,2).run() - ModularSymbolsDecomp1(1,100).run() - ModularSymbolsDecomp1(54,4).run() + ModularSymbolsDecomp1(1, 24).run() + ModularSymbolsDecomp1(125, 2).run() + ModularSymbolsDecomp1(389, 2).run() + ModularSymbolsDecomp1(1, 100).run() + ModularSymbolsDecomp1(54, 4).run() + def elliptic_curve(): EllipticCurveTraces(100000).run() @@ -1978,7 +1944,7 @@ def elliptic_curve(): # NOTE -- Sage can also do these using Simon's program, which is # *way* *way* faster than MAGMA... - EllipticCurveMW([5,6,7,8,9]).run() - EllipticCurveMW([50,6,7,8,9]).run() + EllipticCurveMW([5, 6, 7, 8, 9]).run() + EllipticCurveMW([50, 6, 7, 8, 9]).run() EllipticCurveMW([1, -1, 0, -79, 289]).run(trials=1) # rank 4 EllipticCurveMW([0, 0, 1, -79, 342]).run(trials=1) # rank 5 (Sage wins) From b9b03174905f71d12336d3d3341816d0021ffecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 14:16:21 +0200 Subject: [PATCH 200/225] forgotten details --- src/sage/tests/benchmark.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index 81928df75c0..ebce5f9730e 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -54,7 +54,7 @@ def avg(X): return s / float(len(X)) -STD_SYSTEMS = ['sage', 'maxima', 'gap', 'gp', 'pari', 'python'] +STD_SYSTEMS = ['sage', 'maxima', 'libgap', 'gp', 'pari', 'python'] OPT_SYSTEMS = ['magma', 'macaulay2', 'maple', 'mathematica'] @@ -1023,7 +1023,7 @@ def libgap(self): sage: from sage.tests.benchmark import SquareInts sage: B = SquareInts() - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True """ n = libgap('%s^%s' % (self.base, self.__ndigits)) @@ -1115,7 +1115,7 @@ def libgap(self): sage: from sage.tests.benchmark import MatrixSquare sage: B = MatrixSquare(3, QQ) - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True """ n = self.__n @@ -1238,7 +1238,7 @@ def libgap(self): sage: from sage.tests.benchmark import Fibonacci sage: B = Fibonacci(10) - sage: isinstance(B.gap()[1], float) + sage: isinstance(B.libgap()[1], float) True """ n = libgap(self.__n) @@ -1256,7 +1256,6 @@ def mathematica(self): sage: B = Fibonacci(10) sage: isinstance(B.mathematica()[1], float) # optional - mathematica True - """ n = mathematica(self.__n) t = walltime() From d28bb848ea5e1fa5a99c9d9c30170f4a42dd2dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 14:18:37 +0200 Subject: [PATCH 201/225] suggested detail --- src/sage/rings/padics/local_generic_element.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/padics/local_generic_element.pyx b/src/sage/rings/padics/local_generic_element.pyx index 97d608ca464..0db91750eca 100644 --- a/src/sage/rings/padics/local_generic_element.pyx +++ b/src/sage/rings/padics/local_generic_element.pyx @@ -395,8 +395,8 @@ cdef class LocalGenericElement(CommutativeRingElement): for c in islice(self.expansion(lift_mode=lift_mode), int(start), int(stop), int(k)): genpow = 1 if not isinstance(c, list): - c = [c] # relevant for the case of base-rings, or one-step - # eisenstein extensions + c = [c] # relevant for the case of base-rings, or one-step + # Eisenstein extensions for d in c: ans += d * genpow * ppow genpow *= unramified_generator From 34e4139acf7bb6d3b5d6956e0d1f43e7a8ed99ce Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 1 Oct 2023 09:41:15 -0700 Subject: [PATCH 202/225] src/sage/sets/condition_set.py: Fix doctest dataflow warning --- src/sage/sets/condition_set.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 539b850027f..e29f0124224 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -414,7 +414,7 @@ def _sympy_(self): EXAMPLES:: - sage: # needs sage.modules sage.symbolic + sage: # needs sympy sage.modules sage.symbolic sage: predicate(x, y, z) = sqrt(x^2 + y^2 + z^2) < 12; predicate (x, y, z) |--> sqrt(x^2 + y^2 + z^2) < 12 sage: SmallTriples = ConditionSet(ZZ^3, predicate); SmallTriples @@ -427,10 +427,9 @@ def _sympy_(self): True sage: (5, 7, 9) in ST False - - sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval # needs sage.symbolic + sage: Interval = ConditionSet(RR, x >= -7, x <= 4, vars=[x]); Interval { x ∈ Real Field with 53 bits of precision : x >= -7, x <= 4 } - sage: Interval._sympy_() # needs sympy sage.symbolic + sage: Interval._sympy_() ConditionSet(x, (x >= -7) & (x <= 4), SageSet(Real Field with 53 bits of precision)) From 99529d52fc105f33ffb7f174f3cfac0c809fa091 Mon Sep 17 00:00:00 2001 From: Mark Zhang <73615076+markz20@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:16:05 -0400 Subject: [PATCH 203/225] Add README.md Table of Contents and Links Added Table of Contents for accessible navigation and hyperlink to official documentation website. Updated macOS Silicon Chip options in platform preparation section. --- README.md | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index aee0c3a0fbc..1b350a7996a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ https://www.sagemath.org +[Sage Documentation](https://doc.sagemath.org/html/en/index.html) + The Sage Library is free software released under the GNU General Public Licence GPLv2+, and included packages have [compatible software licenses](./COPYING.txt). @@ -21,6 +23,24 @@ have [compatible software licenses](./COPYING.txt). have contributed code to Sage. In many cases, documentation for modules and functions list the authors. +Table of Contents +----------------- + +* [Getting Started](#getting-started) +* [Supported Platforms](#supported-platforms) +* [\[Windows\] Preparing the Platform Libraries](#windows-preparing-the-platform) +* [\[macOS\] Preparing the Platform Libraries](#macos-preparing-the-platform) +* [Instructions to Build from Source](#instructions-to-build-from-source) +* [SageMath Docker Images](#sagemath-docker-images) +* [Troubleshooting](#troubleshooting) +* [Contributing to Sage](#contributing-to-sage) +* [Directory Layout](#directory-layout) +* [Build System](#build-system) +* [Relocation](#relocation) +* [Redistribution](#redistribution) +* [Build System](#build-system) +* [Changes to Included Software](#changes-to-included-software) + Getting Started --------------- @@ -47,7 +67,7 @@ macOS, and Windows (using Windows Subsystem for Linux or virtualization). Detailed information on supported platforms for a specific version of Sage -can be found in the section "Availability and installation help" of the +can be found in the section _Availability and installation help_ of the [release tour](https://wiki.sagemath.org/ReleaseTours) for this version. We highly appreciate contributions to Sage that fix portability bugs @@ -64,13 +84,13 @@ your Windows. Make sure you allocate WSL sufficient RAM; 5GB is known to work, w 2GB might be not enough for building Sage from source. Then all instructions for installation in Linux apply. -As an alternative, you can also run Linux on Windows using Docker (see -below) or other virtualization solutions. +As an alternative, you can also run Linux on Windows using Docker ([see +below](#sagemath-docker-images)) or other virtualization solutions. [macOS] Preparing the Platform ------------------------------ -If your Mac uses the Apple Silicon (M1, arm64) architecture: +If your Mac uses the Apple Silicon (M1, M2, arm64) architecture: - If you set up your Mac by transfering files from an older Mac, make sure that the directory ``/usr/local`` does not contain an old copy of Homebrew @@ -117,6 +137,7 @@ More details, providing a background for these instructions, can be found in the [section "Install from Source Code"](https://doc.sagemath.org/html/en/installation/source.html). in the Installation Guide. + 1. Decide on the source/build directory (`SAGE_ROOT`): - On personal computers, any subdirectory of your :envvar:`HOME` From c0a666f05f3a99479a588848d4d9b1e6beda2ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 1 Oct 2023 21:17:10 +0200 Subject: [PATCH 204/225] oops ; fixed --- src/sage/rings/polynomial/real_roots.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 13eca002d51..3e8c489ff14 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -1301,7 +1301,7 @@ def intvec_to_doublevec(Vector_integer_dense b, long err): cdef int i - for i in ragne(len(b)): + for i in range(len(b)): mpz_get_d_2exp(&cur_exp, b._entries[i]) if cur_exp > max_exp: max_exp = cur_exp @@ -4594,7 +4594,7 @@ def dprod_imatrow_vec(Matrix_integer_dense m, Vector_integer_dense v, int k): cdef int ra cdef int a mpz_init(tmp) - for a in ragne(msize): + for a in range(msize): ra = subsample_vec(a, msize, vsize) m.get_unsafe_mpz(k, a, tmp) mpz_addmul(sum.value, tmp, v._entries[ra]) From 64bd321541f1cc8f4d8d0839a51197bc7e5f6e37 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:37:56 -0700 Subject: [PATCH 205/225] build/pkgs/babel: Update to 2.12.1 --- build/pkgs/babel/checksums.ini | 6 +++--- build/pkgs/babel/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/babel/checksums.ini b/build/pkgs/babel/checksums.ini index 70beeda6613..2d8082eb884 100644 --- a/build/pkgs/babel/checksums.ini +++ b/build/pkgs/babel/checksums.ini @@ -1,5 +1,5 @@ tarball=Babel-VERSION.tar.gz -sha1=75baeb68d7481a67ba203191aa460c56b0221fda -md5=9ee7784fd452d456206ecd3a12694010 -cksum=227595701 +sha1=128ccb05798652d1d53004020c9b5bb94d3ff14c +md5=9ac7d8aac42c17a1e6d922017058d2c8 +cksum=2095732623 upstream_url=https://pypi.io/packages/source/b/babel/Babel-VERSION.tar.gz diff --git a/build/pkgs/babel/package-version.txt b/build/pkgs/babel/package-version.txt index 46b81d815a2..3cf561c0b67 100644 --- a/build/pkgs/babel/package-version.txt +++ b/build/pkgs/babel/package-version.txt @@ -1 +1 @@ -2.11.0 +2.12.1 From 1b84d893fd6a31f4c797fd5a6f425808d1c1280a Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:37:26 -0700 Subject: [PATCH 206/225] build/pkgs/pytz: Update to 2023.3 --- build/pkgs/pytz/checksums.ini | 6 +++--- build/pkgs/pytz/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pytz/checksums.ini b/build/pkgs/pytz/checksums.ini index 9c3074def07..59ddb76ec2d 100644 --- a/build/pkgs/pytz/checksums.ini +++ b/build/pkgs/pytz/checksums.ini @@ -1,5 +1,5 @@ tarball=pytz-VERSION.tar.gz -sha1=b356ab5a8b326e9857bbce3e7a1799fc56844827 -md5=91747f483e2906cddda91b0df0b01254 -cksum=635792532 +sha1=1d0de50f5dcbd3fdf8d9690b4a2d7ff27ee7a7b1 +md5=fe54c8f8a1544b4e78b523b264ab071b +cksum=1544859342 upstream_url=https://pypi.io/packages/source/p/pytz/pytz-VERSION.tar.gz diff --git a/build/pkgs/pytz/package-version.txt b/build/pkgs/pytz/package-version.txt index ef52d12ba35..b7547c45d8d 100644 --- a/build/pkgs/pytz/package-version.txt +++ b/build/pkgs/pytz/package-version.txt @@ -1 +1 @@ -2022.5 +2023.3 From 565dddb6b226773588fa4e028802f158d11064c6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:35:56 -0700 Subject: [PATCH 207/225] build/pkgs/attrs: Update to 23.1.0 --- build/pkgs/attrs/checksums.ini | 6 +++--- build/pkgs/attrs/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/attrs/checksums.ini b/build/pkgs/attrs/checksums.ini index 291539baec1..2b364ba1a75 100644 --- a/build/pkgs/attrs/checksums.ini +++ b/build/pkgs/attrs/checksums.ini @@ -1,5 +1,5 @@ tarball=attrs-VERSION.tar.gz -sha1=16d99f8e6f84309a4e399babc2e237da87b445ad -md5=0487081b7ead8753fc46cf7c6d1e28e3 -cksum=3993993002 +sha1=f48d0c0f96e3fbd476821408b81f5c823026546e +md5=6623fed7ffa22261ba25fccaf4d99539 +cksum=3377712336 upstream_url=https://pypi.io/packages/source/a/attrs/attrs-VERSION.tar.gz diff --git a/build/pkgs/attrs/package-version.txt b/build/pkgs/attrs/package-version.txt index ee5c2446981..f8aed3e0b7a 100644 --- a/build/pkgs/attrs/package-version.txt +++ b/build/pkgs/attrs/package-version.txt @@ -1 +1 @@ -22.1.0 +23.1.0 From 4189a8efcfce1137efc588d5acf5bc8427758851 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:39:00 -0700 Subject: [PATCH 208/225] build/pkgs/markupsafe: Update to 2.1.3 --- build/pkgs/markupsafe/checksums.ini | 6 +++--- build/pkgs/markupsafe/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/markupsafe/checksums.ini b/build/pkgs/markupsafe/checksums.ini index 5939d7266eb..ed6d6b9f8b8 100644 --- a/build/pkgs/markupsafe/checksums.ini +++ b/build/pkgs/markupsafe/checksums.ini @@ -1,5 +1,5 @@ tarball=MarkupSafe-VERSION.tar.gz -sha1=8bd9855f5b92145b6bc0d38cc241d0253cccc5a8 -md5=9809f9fdd98bc835b0c21aa8f79cbf30 -cksum=928883078 +sha1=88db36605e2cb308d4e1a3c6e53d0cad64702cac +md5=ca33f119bd0551ce15837f58bb180214 +cksum=3979339255 upstream_url=https://pypi.io/packages/source/m/markupsafe/MarkupSafe-VERSION.tar.gz diff --git a/build/pkgs/markupsafe/package-version.txt b/build/pkgs/markupsafe/package-version.txt index 3e3c2f1e5ed..ac2cdeba013 100644 --- a/build/pkgs/markupsafe/package-version.txt +++ b/build/pkgs/markupsafe/package-version.txt @@ -1 +1 @@ -2.1.1 +2.1.3 From 450b74cd2529d160dc0fd0e706f44a95067e2fd1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:39:36 -0700 Subject: [PATCH 209/225] build/pkgs/certifi: Update to 2023.7.22 --- build/pkgs/certifi/checksums.ini | 6 +++--- build/pkgs/certifi/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/certifi/checksums.ini b/build/pkgs/certifi/checksums.ini index cab6201a644..2c5eca9453c 100644 --- a/build/pkgs/certifi/checksums.ini +++ b/build/pkgs/certifi/checksums.ini @@ -1,5 +1,5 @@ tarball=certifi-VERSION.tar.gz -sha1=4a6fb9ae2afe62b33bab98ae21c0853d026d64c2 -md5=ff9c8d5c7e7fb083de6b874609c5ca68 -cksum=726096582 +sha1=ec7e8dd8ef95edfdb83a1ea040b8b88507b47615 +md5=10a72845d3fc2c38d212b4b7b1872c76 +cksum=3265213618 upstream_url=https://pypi.io/packages/source/c/certifi/certifi-VERSION.tar.gz diff --git a/build/pkgs/certifi/package-version.txt b/build/pkgs/certifi/package-version.txt index e4b8493d095..6679122d61e 100644 --- a/build/pkgs/certifi/package-version.txt +++ b/build/pkgs/certifi/package-version.txt @@ -1 +1 @@ -2022.9.24 +2023.7.22 From 1f6f3eea725aac038a66b4d59db3d1f4ccc2d461 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:57:43 -0700 Subject: [PATCH 210/225] build/pkgs/importlib_metadata: Update to 6.8.0 --- build/pkgs/importlib_metadata/checksums.ini | 6 +++--- build/pkgs/importlib_metadata/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/importlib_metadata/checksums.ini b/build/pkgs/importlib_metadata/checksums.ini index dfcaf149224..8c978b57c5b 100644 --- a/build/pkgs/importlib_metadata/checksums.ini +++ b/build/pkgs/importlib_metadata/checksums.ini @@ -1,5 +1,5 @@ tarball=importlib_metadata-VERSION.tar.gz -sha1=b9b1f85f9d7ea8464990aa48078c2bc18c88b17d -md5=a7d0734680f70b03368b69fe3e89dc56 -cksum=579037727 +sha1=0e5742cd1d559863573bfb4f6cb7ca9ad8dcf466 +md5=c04c814eee1abf42790cfa4bd0454af1 +cksum=1038169537 upstream_url=https://pypi.io/packages/source/i/importlib_metadata/importlib_metadata-VERSION.tar.gz diff --git a/build/pkgs/importlib_metadata/package-version.txt b/build/pkgs/importlib_metadata/package-version.txt index 09b254e90c6..e029aa99b7d 100644 --- a/build/pkgs/importlib_metadata/package-version.txt +++ b/build/pkgs/importlib_metadata/package-version.txt @@ -1 +1 @@ -6.0.0 +6.8.0 From 64c998f6cf3740a0b75a3a73e2bf99e134221313 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 11:57:48 -0700 Subject: [PATCH 211/225] build/pkgs/importlib_resources: Update to 6.0.1 --- build/pkgs/importlib_resources/checksums.ini | 6 +++--- build/pkgs/importlib_resources/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/importlib_resources/checksums.ini b/build/pkgs/importlib_resources/checksums.ini index ac6747edaec..5f8bc23a6fd 100644 --- a/build/pkgs/importlib_resources/checksums.ini +++ b/build/pkgs/importlib_resources/checksums.ini @@ -1,5 +1,5 @@ tarball=importlib_resources-VERSION.tar.gz -sha1=b793f4fb94148414679e3192e731fef25e3e9bc9 -md5=5457c25b89b19fcaca8af03e541dfa41 -cksum=527125049 +sha1=dc5322c0a6414fa823f54ef7fe938210abecd6a8 +md5=ebb549867902e44c9314ac3998e0d31f +cksum=3214105952 upstream_url=https://pypi.io/packages/source/i/importlib_resources/importlib_resources-VERSION.tar.gz diff --git a/build/pkgs/importlib_resources/package-version.txt b/build/pkgs/importlib_resources/package-version.txt index dd0ad7ae60c..5fe60723048 100644 --- a/build/pkgs/importlib_resources/package-version.txt +++ b/build/pkgs/importlib_resources/package-version.txt @@ -1 +1 @@ -5.12.0 +6.0.1 From 09c11a4e94f909b9fe7a286ca3b7903b2a133aac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 24 Aug 2023 15:30:27 -0700 Subject: [PATCH 212/225] build/pkgs/tzlocal: Update to 5.0.1 --- build/pkgs/tzlocal/checksums.ini | 6 +++--- build/pkgs/tzlocal/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/tzlocal/checksums.ini b/build/pkgs/tzlocal/checksums.ini index e0a415cb4fc..eb9533b0f63 100644 --- a/build/pkgs/tzlocal/checksums.ini +++ b/build/pkgs/tzlocal/checksums.ini @@ -1,5 +1,5 @@ tarball=tzlocal-VERSION.tar.gz -sha1=76098dc67f43575cda4ab7cf20ebd1c6aef1ceaa -md5=b20f960e77612ff35c5105bb876f0853 -cksum=2281514998 +sha1=1d61e52edddf882c9af4f5f3f1be0db3788dd7b5 +md5=c209a72fd296ff6e1a98d55c2382ba79 +cksum=1644259932 upstream_url=https://pypi.io/packages/source/t/tzlocal/tzlocal-VERSION.tar.gz diff --git a/build/pkgs/tzlocal/package-version.txt b/build/pkgs/tzlocal/package-version.txt index bf77d549685..6b244dcd696 100644 --- a/build/pkgs/tzlocal/package-version.txt +++ b/build/pkgs/tzlocal/package-version.txt @@ -1 +1 @@ -4.2 +5.0.1 From 09c77cf6df6956897e43dab3e4bfe6fe1e9df092 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 21 Sep 2023 12:34:37 -0700 Subject: [PATCH 213/225] build/pkgs/pytz: Update to 2023.3.post1 --- build/pkgs/pytz/checksums.ini | 6 +++--- build/pkgs/pytz/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pytz/checksums.ini b/build/pkgs/pytz/checksums.ini index 59ddb76ec2d..0b0e03e9863 100644 --- a/build/pkgs/pytz/checksums.ini +++ b/build/pkgs/pytz/checksums.ini @@ -1,5 +1,5 @@ tarball=pytz-VERSION.tar.gz -sha1=1d0de50f5dcbd3fdf8d9690b4a2d7ff27ee7a7b1 -md5=fe54c8f8a1544b4e78b523b264ab071b -cksum=1544859342 +sha1=be3f14bc0d6b89b8c579d8ae4e0fcb4478ff92e6 +md5=84e6569fcc917b096cca1063819c4ab0 +cksum=3925580206 upstream_url=https://pypi.io/packages/source/p/pytz/pytz-VERSION.tar.gz diff --git a/build/pkgs/pytz/package-version.txt b/build/pkgs/pytz/package-version.txt index b7547c45d8d..ccf8d6654d2 100644 --- a/build/pkgs/pytz/package-version.txt +++ b/build/pkgs/pytz/package-version.txt @@ -1 +1 @@ -2023.3 +2023.3.post1 From 9871ad6b4b25971c21f5adf6b3d4733b87e95903 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 1 Oct 2023 15:06:39 -0700 Subject: [PATCH 214/225] bootstrap: Emit SAGE_SPKG_CONFIGURE_... calls for Python site packages after all other packages --- bootstrap | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/bootstrap b/bootstrap index aa5755cfc63..54d0a156239 100755 --- a/bootstrap +++ b/bootstrap @@ -73,9 +73,19 @@ SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(grep -v ^= build/pkgs/$pkgname/SPKG. done for pkgname in $(sage-package list --has-file spkg-configure.m4 | sort); do echo "m4_sinclude([build/pkgs/$pkgname/spkg-configure.m4])" - spkg_configures="$spkg_configures -SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')" + config="SAGE_SPKG_CONFIGURE_$(echo ${pkgname} | tr '[a-z]' '[A-Z]')" + if grep -q SAGE_PYTHON_PACKAGE_CHECK build/pkgs/$pkgname/spkg-configure.m4; then + spkg_configures_python="$spkg_configures_python +$config" + else + spkg_configures="$spkg_configures +$config" + fi done >> m4/sage_spkg_configures.m4 + cat >> m4/sage_spkg_configures.m4 <>>SPKG_INSTALL_REQUIRES_${pkgname}<<<, >>>$(echo $(ENABLE_SYSTEM_SITE_PACKAGES=yes sage-get-system-packages install-requires-toml ${pkgname}))<<<)dnl" >> m4/sage_spkg_versions_toml.m4 fi fi - spkg_configures="$spkg_configures + spkg_finalizes="$spkg_finalizes SAGE_SPKG_FINALIZE([$pkgname], [$pkgtype], [$SPKG_SOURCE], [$SPKG_TREE_VAR])" done - echo "$spkg_configures" >> m4/sage_spkg_configures.m4 + echo "$spkg_finalizes" >> m4/sage_spkg_configures.m4 for a in m4/sage_spkg_versions.m4 m4/sage_spkg_versions_toml.m4; do echo 'changequote(>>>`<<<, >>>'"'"'<<<)dnl' >> $a done From 8de14a7be0b619465de4cbc26b208ec63b690601 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Jun 2022 16:01:57 -0700 Subject: [PATCH 215/225] build/pkgs/flint: Update to 2.9.0 --- build/pkgs/flint/checksums.ini | 6 +++--- build/pkgs/flint/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/flint/checksums.ini b/build/pkgs/flint/checksums.ini index 2f51fa9932d..3d449d98064 100644 --- a/build/pkgs/flint/checksums.ini +++ b/build/pkgs/flint/checksums.ini @@ -1,5 +1,5 @@ tarball=flint-VERSION.tar.gz -sha1=d17a245bddec753c6eb5841b28d0322ba0c9e2b6 -md5=484e62dd7326a4af6e2072f4edbc769f -cksum=1002348409 +sha1=63d90f8242c8f8ab4011fbcfb44b86c154f43abd +md5=c2d3cec326438f159a530c66eb07fafe +cksum=4244948341 upstream_url=http://flintlib.org/flint-VERSION.tar.gz diff --git a/build/pkgs/flint/package-version.txt b/build/pkgs/flint/package-version.txt index 2701a226a2f..c8e38b61405 100644 --- a/build/pkgs/flint/package-version.txt +++ b/build/pkgs/flint/package-version.txt @@ -1 +1 @@ -2.8.4 +2.9.0 From 45aa3d9287dbe84d922c06dadc127c3cbd00e651 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 30 Jun 2022 16:02:19 -0700 Subject: [PATCH 216/225] build/pkgs/arb: Update to 2.23.0 --- build/pkgs/arb/checksums.ini | 6 +++--- build/pkgs/arb/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/arb/checksums.ini b/build/pkgs/arb/checksums.ini index e5efd63346d..80ef43dad5d 100644 --- a/build/pkgs/arb/checksums.ini +++ b/build/pkgs/arb/checksums.ini @@ -1,5 +1,5 @@ tarball=arb-VERSION.tar.gz -sha1=b49978d7a54febbc408297683085f3252b5a3281 -md5=6521245e826eb337eddedd6159eabcb8 -cksum=3488846289 +sha1=a1efe035dd3af3613dd685971a156f652b86ff63 +md5=9b369e29f93cdf2d4f90b57a92526cce +cksum=64252121 upstream_url=https://github.com/fredrik-johansson/arb/archive/VERSION.tar.gz diff --git a/build/pkgs/arb/package-version.txt b/build/pkgs/arb/package-version.txt index d93847fab5f..e9763f6bfed 100644 --- a/build/pkgs/arb/package-version.txt +++ b/build/pkgs/arb/package-version.txt @@ -1 +1 @@ -2.22.1 +2.23.0 From 316bbb38381a248ffcea859c6c3d6c965d068942 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 2 Jul 2022 11:18:13 -0700 Subject: [PATCH 217/225] build/pkgs/flint/spkg-configure.m4: Check function needed by arb 2.23 --- build/pkgs/flint/spkg-configure.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/pkgs/flint/spkg-configure.m4 b/build/pkgs/flint/spkg-configure.m4 index 1a21f60170f..a58108c9d6e 100644 --- a/build/pkgs/flint/spkg-configure.m4 +++ b/build/pkgs/flint/spkg-configure.m4 @@ -1,8 +1,8 @@ SAGE_SPKG_CONFIGURE([flint], [ SAGE_SPKG_DEPCHECK([mpfr ntl], [ AC_CHECK_HEADER(flint/flint.h, [ - dnl fmpz_mod_ctx_init appears in Flint 2.6.0 - AC_SEARCH_LIBS([fmpz_mod_ctx_init], [flint], [ + dnl flint_parallel_binary_splitting appears in Flint 2.9.0, needed by arb 2.23 + AC_SEARCH_LIBS([flint_parallel_binary_splitting], [flint], [ dnl check that NTL is linked in AC_SEARCH_LIBS([fmpz_poly_get_ZZX], [flint], [ From bb35159474cadcb033509182f7df6cb389737276 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 2 Jan 2022 21:58:09 +0000 Subject: [PATCH 218/225] mpc --- build/pkgs/mpc/distros/alpine.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 build/pkgs/mpc/distros/alpine.txt diff --git a/build/pkgs/mpc/distros/alpine.txt b/build/pkgs/mpc/distros/alpine.txt new file mode 100644 index 00000000000..5031c059427 --- /dev/null +++ b/build/pkgs/mpc/distros/alpine.txt @@ -0,0 +1,2 @@ +mpc1 +mpc1-dev From e7d0a44e100f0a8733b01a45f074f7c4e93c11fa Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 2 Oct 2023 13:03:35 +0800 Subject: [PATCH 219/225] Fail fast for PRs --- .github/workflows/ci-conda.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-conda.yml b/.github/workflows/ci-conda.yml index 0d920f67fc3..75babf3ab8c 100644 --- a/.github/workflows/ci-conda.yml +++ b/.github/workflows/ci-conda.yml @@ -21,7 +21,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: - fail-fast: false + fail-fast: ${{ github.event_name == 'pull_request' }} + max-parallel: ${{ github.event_name == 'pull_request' && 2 || 6 }} matrix: os: [ubuntu-latest, macos-latest] python: ['3.9', '3.10', '3.11'] From f8d315467347059ed1d50eb86f83841450530b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 2 Oct 2023 16:07:53 +0200 Subject: [PATCH 220/225] suggested details --- src/sage/rings/polynomial/real_roots.pyx | 40 +++++++++++++----------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 3e8c489ff14..97af8b60ffd 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -679,7 +679,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): cdef int degree(self): """ - Returns the (formal) degree of this polynomial. + Return the (formal) degree of this polynomial. """ return len(self.coeffs) - 1 @@ -776,7 +776,7 @@ cdef class interval_bernstein_polynomial_integer(interval_bernstein_polynomial): def get_msb_bit(self): """ - Returns an approximation of the log2 of the maximum of the + Return an approximation of the log2 of the maximum of the absolute values of the coefficients, as an integer. """ return self.scale_log2 + self.bitsize @@ -1554,7 +1554,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): cdef int degree(self): """ - Returns the (formal) degree of this polynomial. + Return the (formal) degree of this polynomial. """ return len(self.coeffs) - 1 @@ -1642,7 +1642,7 @@ cdef class interval_bernstein_polynomial_float(interval_bernstein_polynomial): def get_msb_bit(self): """ - Returns an approximation of the log2 of the maximum of the + Return an approximation of the log2 of the maximum of the absolute values of the coefficients, as an integer. """ return self.scale_log2 - 53 + self.bitsize @@ -1818,15 +1818,17 @@ def max_abs_doublevec(Vector_real_double_dense c): def wordsize_rational(a, b, wordsize): """ - Given rationals a and b, selects a de Casteljau split point r between - a and b. An attempt is made to select an efficient split point + Given rationals a and b, select a de Casteljau split point r between + a and b. + + An attempt is made to select an efficient split point (according to the criteria mentioned in the documentation for de_casteljau_intvec), with a bias towards split points near a. In full detail: - Takes as input two rationals, a and b, such that 0<=a<=1, 0<=b<=1, - and a!=b. Returns rational r, such that a<=r<=b or b<=r<=a. + This takes as input two rationals, a and b, such that 0<=a<=1, 0<=b<=1, + and a!=b. This returns rational r, such that a<=r<=b or b<=r<=a. The denominator of r is a power of 2. Let m be min(r, 1-r), nm be numerator(m), and dml be log2(denominator(m)). The return value r is taken from the first of the following classes to have any @@ -2550,14 +2552,14 @@ class bernstein_polynomial_factory: def lsign(self): """ - Returns the sign of the first coefficient of this + Return the sign of the first coefficient of this Bernstein polynomial. """ return self._sign(self.coeffs[0]) def usign(self): """ - Returns the sign of the last coefficient of this + Return the sign of the last coefficient of this Bernstein polynomial. """ return self._sign(self.coeffs[-1]) @@ -3077,7 +3079,7 @@ cdef class ocean: def approx_bp(self, scale_log2): """ - Returns an approximation to our Bernstein polynomial with the + Return an approximation to our Bernstein polynomial with the given scale_log2. EXAMPLES:: @@ -3830,10 +3832,10 @@ class warp_map: def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=False, wordsize=32, retval='rational', strategy=None, max_diameter=None): """ - Compute the real roots of a given polynomial with exact - coefficients (integer, rational, and algebraic real coefficients - are supported). Returns a list of pairs of a root and its - multiplicity. + Compute the real roots of a given polynomial with exact coefficients + (integer, rational, and algebraic real coefficients are supported). + + This returns a list of pairs of a root and its multiplicity. The root itself can be returned in one of three different ways. If retval=='rational', then it is returned as a pair of rationals @@ -4050,7 +4052,7 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals cdef ocean oc - for (factor, exp) in factors: + for factor, exp in factors: if strategy=='warp': if factor.constant_coefficient() == 0: x = factor.parent().gen() @@ -4105,7 +4107,7 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals while True: all_roots = copy(extra_roots) - for (oc, factor, exp) in oceans: + for oc, factor, exp in oceans: rel_roots = oc.roots() cur_roots = [oc.mapping.from_ocean(r) for r in rel_roots] @@ -4162,7 +4164,7 @@ def real_roots(p, bounds=None, seed=None, skip_squarefree=False, do_logging=Fals if ok: break - for (oc, factor, exp) in oceans: + for oc, factor, exp in oceans: oc.find_roots() if do_logging: @@ -4467,7 +4469,7 @@ def bernstein_expand(Vector_integer_dense c, int d2): multiplies, but in this version all the multiplies are by single machine words). - Returns a pair consisting of the expanded polynomial, and the maximum + This returns a pair consisting of the expanded polynomial, and the maximum error E. (So if an element of the returned polynomial is a, and the true value of that coefficient is b, then a <= b < a + E.) From 76475e33a4bb2a55c115db62d8417b3b4905796a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 2 Oct 2023 17:24:53 +0200 Subject: [PATCH 221/225] fix import --- src/sage/tests/benchmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index ebce5f9730e..4b9c6483724 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -25,7 +25,7 @@ from sage.interfaces.maxima import maxima from sage.interfaces.singular import singular from sage.libs.pari import pari -from sage.lib.libgap import libgap +from sage.libs.gap.libgap import libgap from sage.matrix.matrix_space import MatrixSpace from sage.misc.functional import log from sage.misc.timing import cputime, walltime From 373cd9c9729e7a78813e328a8d2082fa2c4e3b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 2 Oct 2023 17:34:05 +0200 Subject: [PATCH 222/225] fix doctests --- src/sage/tests/benchmark.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/tests/benchmark.py b/src/sage/tests/benchmark.py index 4b9c6483724..626388bd3ab 100644 --- a/src/sage/tests/benchmark.py +++ b/src/sage/tests/benchmark.py @@ -1026,7 +1026,7 @@ def libgap(self): sage: isinstance(B.libgap()[1], float) True """ - n = libgap('%s^%s' % (self.base, self.__ndigits)) + n = libgap(self.base)**libgap(self.__ndigits) t = walltime() n**2 return False, walltime(t) @@ -1118,8 +1118,10 @@ def libgap(self): sage: isinstance(B.libgap()[1], float) True """ + R = self.__R n = self.__n - m = libgap(str([list(range(n * k, n * (k + 1))) for k in range(n)])) + f = MatrixSpace(R, n)(list(range(n * n))) + m = libgap(f) t = walltime() m * m return False, walltime(t) From ad09d52bd9a09a75fb29ba6d6cd2a5eb2f4f30bd Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Mon, 2 Oct 2023 23:54:03 +0200 Subject: [PATCH 223/225] fix typographic typos --- .../tutorial-implementing-algebraic-structures.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst b/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst index c319c38e7b9..8253bb45547 100644 --- a/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst +++ b/src/doc/en/thematic_tutorials/tutorial-implementing-algebraic-structures.rst @@ -179,7 +179,7 @@ Since we defined the class interactively, instead of in a Python module, those tests will complain about "pickling". We can silence this error by making sage think that the class is defined in a module. We could also just ignore those failing tests for now or call :class:`TestSuite` with the -argument `skip='_test_pickling')`:: +argument ``skip='_test_pickling')``:: sage: import __main__ sage: __main__.MyCyclicGroupAlgebra = MyCyclicGroupAlgebra @@ -238,7 +238,7 @@ Exercises #. Make a tiny modification to ``product_on_basis`` in "MyCyclicGroupAlgebra" to implement the *dual* of the group algebra of the cyclic group instead of its group algebra (so the product is now given by - `b_fb_g=\delta_{f,g}bf`). + `b_fb_g=\delta_{f,g}b_f`). Run the :class:`TestSuite` tests (you may ignore the "pickling" errors). What do you notice? @@ -319,7 +319,7 @@ Diagonal and Triangular Morphisms We now illustrate how to specify that a given morphism is diagonal or triangular with respect to some order on the basis, which means that the morphism is -invertible and `Sage` is able to compute the inverse morphism automatically. +invertible and Sage is able to compute the inverse morphism automatically. Currently this feature requires the domain and codomain to have the same index set (in progress ...). @@ -659,7 +659,7 @@ particular, this construction says that they are: There is a bit of redundancy here: given that ``A`` knows it is a commutative algebra with realizations the infrastructure could, in principle, determine that its realizations are commutative algebras. If this - was done then it would be possible to implement `Bases.super_categories` by + was done then it would be possible to implement ``Bases.super_categories`` by returning:: [A.Realizations().WithBasis()] From ec9ac7f06edd605ac146e50df0fabf6b7c313c38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 3 Oct 2023 13:43:59 +0200 Subject: [PATCH 224/225] suggested detail --- src/sage/libs/linkages/padics/unram_shared.pxi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/libs/linkages/padics/unram_shared.pxi b/src/sage/libs/linkages/padics/unram_shared.pxi index 472e7de0b11..b23168e0eb2 100644 --- a/src/sage/libs/linkages/padics/unram_shared.pxi +++ b/src/sage/libs/linkages/padics/unram_shared.pxi @@ -3,7 +3,7 @@ cimport cython @cython.binding(True) def frobenius_unram(self, arithmetic=True): """ - Returns the image of this element under the Frobenius automorphism + Return the image of this element under the Frobenius automorphism applied to its parent. INPUT: @@ -48,9 +48,9 @@ def frobenius_unram(self, arithmetic=True): ... NotImplementedError: Frobenius automorphism only implemented for unramified extensions - TESTS:: + TESTS: - We check that :trac:`23575` is resolved: + We check that :trac:`23575` is resolved:: sage: x = R.random_element() sage: x.frobenius(arithmetic=false).frobenius() == x @@ -95,9 +95,9 @@ def norm_unram(self, base = None): INPUT: - ``base`` -- a subfield of the parent `L` of this element. - The norm is the relative norm from ``L`` to ``base``. - Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. + - ``base`` -- a subfield of the parent `L` of this element. + The norm is the relative norm from ``L`` to ``base``. + Defaults to the absolute norm down to `\QQ_p` or `\ZZ_p`. EXAMPLES:: From 2f1a76dc24af6c8ca9a804b10913c33a936b4fb8 Mon Sep 17 00:00:00 2001 From: Release Manager Date: Sun, 8 Oct 2023 15:36:24 +0200 Subject: [PATCH 225/225] Updated SageMath version to 10.2.beta6 --- CITATION.cff | 4 ++-- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- build/pkgs/sage_conf/install-requires.txt | 2 +- build/pkgs/sage_docbuild/install-requires.txt | 2 +- build/pkgs/sage_setup/install-requires.txt | 2 +- build/pkgs/sage_sws2rst/install-requires.txt | 2 +- build/pkgs/sagelib/install-requires.txt | 2 +- build/pkgs/sagemath_bliss/install-requires.txt | 2 +- build/pkgs/sagemath_categories/install-requires.txt | 2 +- build/pkgs/sagemath_coxeter3/install-requires.txt | 2 +- build/pkgs/sagemath_environment/install-requires.txt | 2 +- build/pkgs/sagemath_mcqd/install-requires.txt | 2 +- build/pkgs/sagemath_meataxe/install-requires.txt | 2 +- build/pkgs/sagemath_objects/install-requires.txt | 2 +- build/pkgs/sagemath_repl/install-requires.txt | 2 +- build/pkgs/sagemath_sirocco/install-requires.txt | 2 +- build/pkgs/sagemath_tdlib/install-requires.txt | 2 +- pkgs/sage-conf/VERSION.txt | 2 +- pkgs/sage-conf_conda/VERSION.txt | 2 +- pkgs/sage-conf_pypi/VERSION.txt | 2 +- pkgs/sage-docbuild/VERSION.txt | 2 +- pkgs/sage-setup/VERSION.txt | 2 +- pkgs/sage-sws2rst/VERSION.txt | 2 +- pkgs/sagemath-bliss/VERSION.txt | 2 +- pkgs/sagemath-categories/VERSION.txt | 2 +- pkgs/sagemath-coxeter3/VERSION.txt | 2 +- pkgs/sagemath-environment/VERSION.txt | 2 +- pkgs/sagemath-mcqd/VERSION.txt | 2 +- pkgs/sagemath-meataxe/VERSION.txt | 2 +- pkgs/sagemath-objects/VERSION.txt | 2 +- pkgs/sagemath-repl/VERSION.txt | 2 +- pkgs/sagemath-sirocco/VERSION.txt | 2 +- pkgs/sagemath-tdlib/VERSION.txt | 2 +- src/VERSION.txt | 2 +- src/bin/sage-version.sh | 6 +++--- src/sage/version.py | 6 +++--- 38 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 7c31fd13f05..a4eaeb56424 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.2.beta5 +version: 10.2.beta6 doi: 10.5281/zenodo.593563 -date-released: 2023-09-27 +date-released: 2023-10-08 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index 3b70b866392..9d2185159cb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.2.beta5, Release Date: 2023-09-27 +SageMath version 10.2.beta6, Release Date: 2023-10-08 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index f6feef844de..ad369deb69c 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=96468a2d2ec8ee319095f3d2abd73e5f1ec7829d -md5=87391217b5c82275e1cb581721877eec -cksum=370856230 +sha1=80b6c2edf3aeb03b8de332fe07b2ddcad876ed28 +md5=7c474b8e08f3091d418d31188b991c3b +cksum=1679121244 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 886c67921da..07fa92b1e0b 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -b01856309bcb0d25e9cf830da19fa1cdd24df2bf +46997739f9bf574d94ce7e9bea5fd6a05bacf922 diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index f38cdee4efc..1a1aeb82ccf 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.2b5 +sage-conf ~= 10.2b6 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 62965fd0775..835830b3029 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.2b5 +sage-docbuild ~= 10.2b6 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 42ef7aa07f9..b6780898e72 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.2b5 +sage-setup ~= 10.2b6 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 8c3cca6a40a..8529dd6a649 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.2b5 +sage-sws2rst ~= 10.2b6 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 981188d32ca..fa3739fb0e2 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.2b5 +sagemath-standard ~= 10.2b6 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index eaf783b463d..a183832680d 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.2b5 +sagemath-bliss ~= 10.2b6 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 6f9c7bce7d6..deb3d72aaf6 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.2b5 +sagemath-categories ~= 10.2b6 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 79e17497045..b91e7012431 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.2b5 +sagemath-coxeter3 ~= 10.2b6 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 5e7993d773b..f874eb9227e 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.2b5 +sagemath-environment ~= 10.2b6 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index cf817314c08..8de59efbee8 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.2b5 +sagemath-mcqd ~= 10.2b6 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 97b6bb48c9c..0e8a89d1a73 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.2b5 +sagemath-meataxe ~= 10.2b6 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 99b0309ee9e..e35a3687836 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.2b5 +sagemath-objects ~= 10.2b6 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index 9dab260bb52..1a3de989424 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.2b5 +sagemath-repl ~= 10.2b6 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index 7b67a383e35..fd64729fbea 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.2b5 +sagemath-sirocco ~= 10.2b6 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index a5f0a2240a4..62ca038c083 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.2b5 +sagemath-tdlib ~= 10.2b6 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/src/VERSION.txt b/src/VERSION.txt index 7786f0e63e4..71e18f87543 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.2.beta5 +10.2.beta6 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 3bc82696a62..cb6b55a9f90 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.2.beta5' -SAGE_RELEASE_DATE='2023-09-27' -SAGE_VERSION_BANNER='SageMath version 10.2.beta5, Release Date: 2023-09-27' +SAGE_VERSION='10.2.beta6' +SAGE_RELEASE_DATE='2023-10-08' +SAGE_VERSION_BANNER='SageMath version 10.2.beta6, Release Date: 2023-10-08' diff --git a/src/sage/version.py b/src/sage/version.py index 659a7932e4e..338430c34c8 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.2.beta5' -date = '2023-09-27' -banner = 'SageMath version 10.2.beta5, Release Date: 2023-09-27' +version = '10.2.beta6' +date = '2023-10-08' +banner = 'SageMath version 10.2.beta6, Release Date: 2023-10-08'