diff --git a/advanced.sage b/advanced.sage
new file mode 100644
index 0000000000000000000000000000000000000000..8ff4ad99913da96b8a99a03caed293de81c69ed3
--- /dev/null
+++ b/advanced.sage
@@ -0,0 +1,325 @@
+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
diff --git a/basic.sage b/basic.sage
new file mode 100644
index 0000000000000000000000000000000000000000..02250c9c991a0ebe92f455ae97811bef640e6ec7
--- /dev/null
+++ b/basic.sage
@@ -0,0 +1,205 @@
+def Partitions(List):
+  """
+    Generates all proper partitions of List.
+  """
+  if len(List)==0:
+    return [ [] ] 
+  if len(List)==1:
+    return [ ] 
+
+  Res = [] 
+
+  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]] 
+      Res += [  r + [ AA ]  for r in Partitions(M) ]  
+
+  return Res
+# Partitions
+
+
+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(Partitions, TerminalValues):
+  """
+    Returns the vector of compatibility.
+  """
+  return [Compatibility(P, TerminalValues) for P in Partitions]
+# 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 Generate(n, Buffer, Verbose, Save=True, Type=3):
+  """
+    Generates the matrices M_n and M_{C_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_{C_n}, 3 - both.
+  """
+  from datetime import datetime
+  
+  print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "initiating..."
+
+  Count = CountTerminalValues(n)
+  Parts = Partitions(range(n))
+  Vals = TerminalValues(n)
+
+  Mn = []
+  MCn = []
+  rn = 0
+  rCn = 0
+  proc = 0
+  verb = 0
+
+  print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processing terminal values..."
+
+  for V in Vals:
+    proc += 1
+    verb += 1
+    chi = False
+    if Type & 1 == 1:
+      X = Chi(Parts, V)
+      chi = True
+      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:
+      if IsFlow(V):
+        if not chi:
+          X = Chi(Parts, V)
+        MCn += [ X ]
+        rCn += 1
+        if rCn >= 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 MCn overflow (", rCn, ")..."
+          M = Matrix(QQ, MCn)
+          rCn = M.rank()
+          P, L, U = M.LU()
+          MCn = [ U[i].list() for i in range(rCn) ]
+          print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "buffer for MCn completed (", rCn, ")"
+    if verb >= Verbose:
+      print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processed", proc, "of", Count, "...", (100 * proc/Count).round(), "%"
+      verb = 0
+
+  print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "processing terminal values completed"
+
+  Mn  = Matrix(Mn)
+  MCn = Matrix(MCn)
+  
+  if Save:
+    print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "saving the matrices..."
+    
+    s = "saves/basic/" + datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + "_" + n.str() + "_"
+    if Type & 1 == 1:
+      save(Mn, s + "1")
+    if Type & 2 == 2:
+      save(MCn, s + "2")
+  
+  print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "counting the ranks..."
+  
+  rn  = Mn.rank()
+  rCn = MCn.rank()   
+  
+  print datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "counting the ranks completed"
+  
+  return [ n, rn, rCn ]
+# Generate
diff --git a/pairs.sage b/pairs.sage
new file mode 100644
index 0000000000000000000000000000000000000000..90cab3627156c79c8353041ef031fbab8d9f4e1a
--- /dev/null
+++ b/pairs.sage
@@ -0,0 +1,345 @@
+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 IsMatching(TerminalValues):
+  """
+    Returns True if there exists a perfect matching
+    with given values of terminals.
+  """
+  l = len(TerminalValues)
+  if l == 0:
+    return True
+  if l == 1:
+    return False
+  
+  x = Integers(5)(0)
+  for i in range(l-1):
+    if x + TerminalValues[i] + TerminalValues[i+1] == 0:
+      H = TerminalValues[:i] + TerminalValues[i+2:]
+      return IsMatching(H)
+  if x + TerminalValues[0] + TerminalValues[l-1] == 0:
+    return IsMatching(TerminalValues[1:l-2])
+  return False
+# IsMatching
+
+
+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)
+  
+  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
+    X = Chi(PartCls, H)
+    
+    if IsFlow(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 IsMatching(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/pairs/" + 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