Advertisement
jckuri

LatinRectangle.py

Oct 30th, 2016
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.25 KB | None | 0 0
  1. class Edge:
  2.  def __init__(self,v0,v1,capacity):
  3.   self.v0=v0
  4.   self.v1=v1
  5.   self.initialCapacity=capacity
  6.   self.flowCapacity=capacity
  7.   self.backFlowCapacity=0
  8.  def __str__(self):
  9.   s=self.v0+'->'+self.v1+' ('+str(self.flowCapacity)+'/'+str(self.initialCapacity)+') '
  10.   s+=self.v0+'<-'+self.v1+' ('+str(self.backFlowCapacity)+'/'+str(self.initialCapacity)+')'
  11.   return s
  12.  
  13. class Graph:
  14.  def __init__(self,source,sink):
  15.   self.source=source
  16.   self.sink=sink
  17.   self.edges=[]
  18.  def addEdge(self,edge):
  19.   self.edges.append(edge)
  20.  def findVertex(self,vertex):
  21.   edgeList=[]
  22.   for edge in self.edges:
  23.    if edge.v0==vertex and edge.flowCapacity>0:
  24.     edgeList.append(edge)
  25.    if edge.v1==vertex and edge.backFlowCapacity>0:
  26.     edgeList.append(edge)
  27.   return edgeList
  28.  def calculateMaxFlow(self):
  29.   iteration=0
  30.   while True:
  31.    iteration+=1
  32.    print('Iteration: '+str(iteration))
  33.    print(str(self))
  34.    shortestPath=findShortestPathBFS(self)
  35.    if shortestPath==None: break
  36.    self.calculateResidualGraph(shortestPath)
  37.  def calculateResidualGraph(self,shortestPath):
  38.   current=self.source
  39.   pf=getPossibleFlowOfPath(self,shortestPath)
  40.   for edge in shortestPath:
  41.    if current==edge.v0:
  42.     edge.flowCapacity-=pf
  43.     edge.backFlowCapacity+=pf
  44.    else:
  45.     edge.backFlowCapacity-=pf
  46.     edge.flowCapacity+=pf
  47.    current=getNextVertex(current,edge)
  48.  def __str__(self):
  49.   s='Graph: '
  50.   for e in self.edges:
  51.    s+=str(e)+' '
  52.   return s
  53.  
  54. def getNextVertex(vertex,edge):
  55.  return edge.v1 if vertex==edge.v0 else edge.v0
  56.  
  57. def isNotVisited(vertex,visited):
  58.  for v in visited:
  59.   if vertex==v[0]: return False
  60.  return True
  61.  
  62. def getPossibleFlowOfEdge(vertex,edge):
  63.  return edge.flowCapacity if vertex==edge.v0 else edge.backFlowCapacity
  64.  
  65. def getPossibleFlowOfPath(graph,path):
  66.  vertex=graph.source
  67.  possibleFlow=float('inf')
  68.  for edge in path:
  69.   pf=getPossibleFlowOfEdge(vertex,edge)
  70.   if pf<possibleFlow:
  71.    possibleFlow=pf
  72.   vertex=getNextVertex(vertex,edge)
  73.  return possibleFlow
  74.  
  75. def findShortestPathBFS(graph):
  76.  current=(graph.source,[])
  77.  fringe=[]
  78.  visited=[]
  79.  while True:
  80.   neighborEdges=graph.findVertex(current[0])
  81.   for ne in neighborEdges:
  82.    nextVertex=getNextVertex(current[0],ne)
  83.    if isNotVisited(nextVertex,visited):
  84.     fringe.append((nextVertex,current[1]+[ne]))
  85.   visited.append(current)
  86.   if len(fringe)==0: break
  87.   current=fringe[0]
  88.   fringe=fringe[1:]
  89.  shortestPaths=[v[1] for v in visited if v[0]==graph.sink]
  90.  if len(shortestPaths)==0: return None
  91.  shortestPath=shortestPaths[0]
  92.  for path in shortestPaths[1:]:
  93.   if len(path)<len(shortestPath):
  94.    shortestPath=path
  95.   else:
  96.    if len(path)==len(shortestPath):
  97.     if getPossibleFlowOfPath(graph,path)>getPossibleFlowOfPath(graph,shortestPath):
  98.      shortestPath=path
  99.  return shortestPath
  100.  
  101. def getPossibleNumbersForColumn(numbers,A,columnIndex):
  102.  nRows=len(A)
  103.  n=len(numbers)
  104.  column=[A[row][columnIndex] for row in range(nRows)]
  105.  possible=[n for n in numbers if not n in column]
  106.  print('columnIndex: ',columnIndex,' column: ',column,' possible: ',possible)
  107.  return possible
  108.  
  109. def isNewRowPerfectMatching(newRow,numbers):
  110.  newRowSorted=sorted(newRow)
  111.  return newRowSorted==numbers
  112.  
  113. def findNextRow(A,n):
  114.  numbers=[i+1 for i in range(n)]
  115.  L=['L'+str(i) for i in numbers]
  116.  R=['R'+str(i) for i in numbers]
  117.  source='SOURCE'
  118.  sink='SINK'
  119.  g=Graph(source,sink)
  120.  for i in numbers:
  121.   g.addEdge(Edge(source,L[i-1],1))
  122.   g.addEdge(Edge(R[i-1],sink,1))
  123.  for columnIndex in range(n):
  124.   possibleNumbersForColumn=getPossibleNumbersForColumn(numbers,A,columnIndex)
  125.   for p in possibleNumbersForColumn:
  126.    g.addEdge(Edge(L[columnIndex],R[p-1],1))
  127.  g.calculateMaxFlow()
  128.  newRow=[0 for i in numbers]
  129.  for edge in g.edges:
  130.   if edge.v0[0]=='L' and edge.v1[0]=='R':
  131.    iL=int(edge.v0[1:])
  132.    iR=int(edge.v1[1:])
  133.    if(edge.flowCapacity==0): newRow[iL-1]=numbers[iR-1]
  134.  if not isNewRowPerfectMatching(newRow,numbers): return None
  135.  return newRow
  136.  
  137. def printMatrix(A):
  138.  for row in A:
  139.   print(row)
  140.  
  141. def growMatrix(A,n):
  142.  while True:
  143.   print('Matrix:')
  144.   printMatrix(A)
  145.   newRow=findNextRow(A,n)
  146.   if newRow==None: break
  147.   print('New row: ',newRow)
  148.   A.append(newRow)
  149.  print('New row cannot be found.')
  150.  
  151. A=[[1,2,3,4,5],[2,3,4,5,1],[3,4,5,1,2]]
  152. growMatrix(A,5)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement