Select Git revision
-
David Mareček authoredDavid Mareček authored
advanced.sage 7.52 KiB
def Partitions(List):
"""
Generates all proper partitions of List.
"""
if len(List)==0:
yield []
return
if len(List)==1:
return
for A in Subsets( List[:-1] ):
if len(A) > 0:
M = List[:-1]
for a in A:
M.remove(a)
AA = A.list() + [List[-1]]
for r in Partitions(M):
yield r + [ AA ]
# Partitions
def Classes(Partition):
"""
Returns a list determining the class
where the partition belongs.
"""
m = max([ max(p) for p in Partition])
Res = range(m + 1)
for P in Partition:
m = min(P)
for p in P:
Res[p] = m
return Res
# Classes
def IsMinPartition(Part, Gamma):
"""
Returns True if given partition is
lexicographically minimal in its class.
"""
X = Classes(Part)
for r in [ GammaPartition(g, Part) for g in Gamma]:
x = Classes(r)
if x < X:
return False
return True
# IsMinPartition
def GammaPartition(Gamma, Partition):
"""
Applies permutation Gamma on Partition.
"""
Res = Set([])
for P in Partition:
P_ = Set([Gamma[r]-1 for r in P])
Res = Res.union(Set([P_]))
return Res
# GammaPartition
def PartitionClasses(Partitions, Gamma):
"""
Returns list of classes of partitions.
"""
Res = []
for Partition in Partitions:
if IsMinPartition(Partition, Gamma):
Res += [ Set([ GammaPartition(g, Partition) for g in Gamma ]) ]
return Res
# PartitionClasses
def NTuples(n):
"""
Generates all n-tuples of {1, 2, 3, 4}^n.
"""
if n==0:
yield []
return
for t in NTuples(n-1):
for i in [1, 2, 3, 4]:
yield t + [i]
# NTuples
def CountTerminalValues(n):
"""
Counts all values of n terminals with
- first item = 1,
- sum of all items = 0.
"""
if n<=1:
return 0
Count = 0
for t in NTuples(n-2):
T = [1] + t
s = Integers(5)(0)
for i in T:
s += i
if s!=0:
Count += 1
return Count
# CountTerminalValues
def TerminalValues(n):
"""
Generates all values of n terminals with
- first item = 1,
- sum of all items = 0.
"""
if n<=1:
yield []
return
for t in NTuples(n-2):
T = [1] + t
s = Integers(5)(0)
for i in T:
s += i
if s!=0:
yield T + [-s]
# TerminalValues
def Compatibility(Partition, TerminalValues):
"""
Returns 1 if the partition is compatible with
values on terminals.
"""
for Class in Partition:
s = Integers(5)(0)
for Index in Class:
s += TerminalValues[Index]
if s!=0:
return 0
return 1
# Compatibility
def Chi(PartitionClasses, TerminalValues):
"""
Returns the vector of compatibility.
"""
return [sum(Compatibility(P, TerminalValues) for P in Part) for Part in PartitionClasses]
# Chi
def IsFlow(TerminalValues):
"""
Returns True if there exists a flow
with given values on terminals.
"""
val = [ Integers(5)(i) for i in range(1,5) ]
for Val in TerminalValues:
val = [ v + Val for v in val if v + Val > 0 ]
return len(val) > 0
# IsFlow
def EncodeTerminalValues(Values):
"""
Encodes values of terminals into one number.
"""
if len(Values) == 1:
return Integer(Values[-1] - 1)
return 4 * EncodeTerminalValues(Values[:-1]) + Integer(Values[-1] - 1)
# EncodeTerminalValues
def GammaValues(Values, Gamma):
"""
Applies permutation Gamma on Values.
"""
Res = []
for i in range(len(Values)):
Res += [ Values[Gamma[i] - 1] ]
s = 1/Integers(5)(Res[0])
if s != 1:
return [ i * s for i in Res]
return Res
# GammaValues
def Generate(n, Buffer, Verbose, Save=True, Type=3):
"""
Generates the matrices M_n and M'_n and
counts their ranks.
If some matrix is too long the rank is computed
by parts with matrix buffer of given size.
The parameter Verbose determines the number
of rows after that a progress message is printed.
The parameter Save determines whether the result
matrices are saved on disk.
The parameter Type determines which matrices
are generated: 1 - M_n, 2 - M'_n, 3 - both.
"""
from datetime import datetime
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "initiating..."
G = DihedralGroup(n)
Gamma = [ g.tuple() for g in G ]
PartCls = PartitionClasses(Partitions(range(n)), Gamma)
PartSml = [ range(n-2), [ n-2, n-1 ] ]
Count = CountTerminalValues(n)
Vals = TerminalValues(n)
Used = []
for i in range(4^(n-1)):
Used += [ False ]
Mn = []
MMn = []
rn = 0
rrn = 0
proc = 0
verb = 0
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processing terminal values..."
for H in Vals:
proc += 1
verb += 1
if verb >= Verbose:
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processed", proc, "of", Count, "...", (100 * proc/Count).round(), "%"
verb = 0
if Used[EncodeTerminalValues(H)]:
continue
Used[EncodeTerminalValues(H)] = True
if IsFlow(H):
X = Chi(PartCls, H)
for G in Gamma:
Used[EncodeTerminalValues(GammaValues(H, G))] = True
if Type & 1 == 1:
Mn += [ X ]
rn += 1
if rn >= Buffer:
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processed", proc, "of", Count, "...", (100 * proc/Count).round(), "%"
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for Mn overflow (", rn, ")..."
M = Matrix(QQ, Mn)
rn = M.rank()
P, L, U = M.LU()
Mn = [ U[i].list() for i in range(rn) ]
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for Mn completed (", rn, ")"
if Type & 2 == 2:
MMn += [ X ]
rrn += 1
if rrn >= Buffer:
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processed", proc, "of", Count, "...", (100 * proc/Count).round(), "%"
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for MMn overflow (", rrn, ")..."
M = Matrix(QQ, MMn)
rrn = M.rank()
P, L, U = M.LU()
MMn = [ U[i].list() for i in range(rrn) ]
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for MMn completed (", rrn, ")"
continue
if (Compatibility(PartSml, H) == 1) and IsFlow(H[:-2]):
X = Chi(PartCls, H)
for G in Gamma:
Used[EncodeTerminalValues(GammaValues(H, G))] = True
if Type & 2 == 2:
MMn += [ X ]
rrn += 1
if rrn >= Buffer:
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processed", proc, "of", Count, "...", (100 * proc/Count).round(), "%"
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for MMn overflow (", rrn, ")..."
M = Matrix(QQ, MMn)
rrn = M.rank()
P, L, U = M.LU()
MMn = [ U[i].list() for i in range(rrn) ]
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for MMn completed (", rrn, ")"
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processing terminal values completed"
Mn = Matrix(Mn)
MMn = Matrix(MMn)
if Save:
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "saving the matrices..."
s = "saves/advanced/" + datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + "_" + n.str() + "_"
if Type & 1 == 1:
save(Mn, s + "1")
if Type & 2 == 2:
save(MMn, s + "2")
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "counting the ranks..."
rn = Mn.rank()
rrn = MMn.rank()
print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "counting the ranks completed"
return [ n, rn, rrn ]
# Generate