00001
00002 """
00003 Main class for pipe Optimization
00004 """
00005
00006 __copyright__ = """
00007 Copyright 2008 Sean Ross-Ross
00008 """
00009 __license__ = """
00010 This file is part of SLIMpy .
00011
00012 SLIMpy is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as published by
00014 the Free Software Foundation, either version 3 of the License, or
00015 (at your option) any later version.
00016
00017 SLIMpy is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021
00022 You should have received a copy of the GNU Lesser General Public License
00023 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00024 """
00025
00026 from slimpy_base.Core.Builders.BuilderBase import BuilderBase
00027 from slimpy_base.Core.Graph.Graph.DiGraph import DiGraph
00028
00029
00030
00031 class PipeBuilder( BuilderBase ):
00032 """
00033 Build the graph into a new graph where all
00034 the commands are represented as tuples
00035 """
00036
00037
00038 def __init__( self ,useSources=True, chain=True ):
00039 self._chain = chain
00040 self.sourcesFlag = useSources
00041
00042
00043 def build( self ,g, targets, sources, breakpoints, **k):
00044
00045
00046 for t in targets:
00047 assert t in g, "target %(t)s not in graph %(g)s " %vars()
00048
00049 self.breakpoints = breakpoints.copy()
00050 self.workingSet = targets.copy()
00051 self.sources = sources.copy()
00052
00053
00054 self.graph = g
00055 self.lst = []
00056 self.done = {}
00057
00058
00059 self._colour = dict.fromkeys( self.workingSet, 'black' )
00060
00061 self.build_aux()
00062
00063 graph = self.toGraph()
00064
00065 self.clear()
00066
00067 return graph
00068
00069 def clear(self):
00070
00071 self.breakpoints = None
00072 self.graph = None
00073 self.lst = None
00074 self.done = None
00075 self.workingSet = None
00076 self._colour = None
00077
00078 return
00079
00080 def colour_grey(self,node):
00081 self._colour[node] = 'grey'
00082
00083 def colour_white(self,node):
00084 self._colour[node] = 'white'
00085
00086 def colour( self, node ):
00087 """
00088 get the colour of the node
00089 """
00090
00091 sf = node in self.sources and self.sourcesFlag
00092
00093 if sf or self._colour.get( node, 'white' ) == 'grey':
00094 return 'grey'
00095 else:
00096 return 'white'
00097
00098
00099 def is_bp(self,node):
00100
00101 if not node:
00102 return False
00103
00104 if self._chain:
00105 return node in self.breakpoints
00106
00107 info = self.graph.node_info( node )
00108
00109 if info['type'] == 'data':
00110 return True
00111 else:
00112 return False
00113
00114 def dynHelper( self, alpha ):
00115
00116 beta = None
00117 depFlag = False
00118 delta = []
00119
00120 edgeColour = self.graph.getEdgeColour
00121 edgeType = self.graph.getEdgeType
00122 for prev in self.graph.invAdj( alpha ):
00123
00124
00125 stdinFlag = edgeType( alpha, prev )
00126
00127
00128
00129 if stdinFlag and not beta:
00130 beta = prev
00131 depFlag = len( self.graph.adj( prev ) ) <= 1
00132
00133 else:
00134 delta.append( prev )
00135
00136
00137
00138
00139
00140 depFlag = beta and depFlag and not beta in self.workingSet
00141
00142
00143 if beta and ( not depFlag ) and edgeColour( beta, alpha ) == 'green':
00144
00145 depFlag = 'b1'
00146
00147 if not beta and ( not depFlag ) and delta and edgeColour( delta[0] , alpha ) == 'green':
00148 depFlag = 'b2'
00149
00150
00151 nxt = [ node for node in self.graph.adj( alpha ) if edgeColour( alpha, node ) != 'red' ]
00152
00153
00154 if self.is_bp(beta ):
00155 depFlag = False
00156
00157
00158
00159 return depFlag, beta , delta , nxt
00160
00161
00162 def nxtupdate( self, nxt, TSC ):
00163
00164 nxt = set( nxt )
00165
00166 nxt.difference_update( TSC['Command'] )
00167
00168 nxt.difference_update( TSC['Target'] )
00169
00170 return nxt
00171
00172 def build_aux( self ):
00173 """
00174 main method to assemble the pipe into the useable structure
00175 """
00176
00177 log = self.env['record']( 10, 'pipebuilder' )
00178 workingSet = self.workingSet
00179
00180
00181
00182
00183
00184 TSC = None
00185 while workingSet:
00186
00187
00188
00189 print >> log, 'Working set: %(workingSet)s' %vars()
00190
00191 alpha = workingSet.pop()
00192
00193 print >> log, 'alpha = %(alpha)s' %vars()
00194
00195
00196 if self.colour( alpha ) == 'grey':
00197 continue
00198
00199 self.colour_grey(alpha)
00200
00201
00202
00203
00204
00205 TSC = {'Target':[alpha], 'Command':[alpha], 'Source':[]}
00206
00207
00208 self.lst.insert( 0, TSC )
00209
00210
00211 pipeFlag = True
00212
00213
00214 while pipeFlag:
00215 print >> log, '\nwhile pipeFlag: alpha=%(alpha)s' %vars()
00216
00217
00218
00219
00220
00221 pipeFlag , beta , delta , nxt = self.dynHelper( alpha )
00222 if not ( pipeFlag or beta or delta or nxt ):
00223
00224 print >> log, '\Adding %(alpha)s to the source of the pipe' %vars()
00225 TSC['Source'].append( alpha )
00226
00227
00228
00229 print >> log, '\tpipeFlag=%(pipeFlag)s , beta=%(beta)s , delta=%(delta)s , nxt=%(nxt)s' %vars()
00230
00231
00232
00233 nxt = self.nxtupdate( nxt, TSC )
00234
00235 TSC['Target'].extend( nxt )
00236 if nxt:
00237 print >> log, '\taddind %(nxt)s to Targets' %vars()
00238
00239 if not self.graph.getEdgeColour( alpha, list( nxt )[0] ) == 'red' :
00240 if TSC['Target'].count(alpha):
00241 TSC['Target'].remove( alpha )
00242 print >> log, '\removing %(alpha)s from Targets' %vars()
00243
00244
00245
00246
00247 if pipeFlag == "b1":
00248
00249 TSC['Source'].append( alpha )
00250 print >> log, '\tappending alpha to source' %vars()
00251
00252
00253
00254
00255
00256 TSC = {'Target':[alpha], 'Command':[alpha], 'Source':[]}
00257 print >> log, '\tCreating new pipe %(TSC)s' %vars()
00258
00259
00260 self.colour_grey(alpha)
00261 self.lst.insert( 0, TSC )
00262
00263 ab = set( self.graph.adj( beta ) )
00264 ab.symmetric_difference_update( TSC['Target'] )
00265 TSC['Target'].extend( ab )
00266 if ab:
00267 print >> log, '\tadding ab - %(ab)s to target of new pipe' %vars()
00268
00269
00270
00271
00272 if pipeFlag == 'b2':
00273
00274 if len( TSC['Command'] ) == 1:
00275 if len(delta) == 1:
00276 if self.colour(delta[0]) == 'grey':
00277 self.lst.remove(TSC)
00278 pipeFlag = None
00279 else:
00280 TSC['Command'] = delta
00281 alpha = delta[0]
00282 delta = []
00283 else:
00284 print >> log, '\tremoving pipe %(TSC)s' %vars()
00285 self.lst.remove( TSC )
00286 pipeFlag = None
00287 print >> log, '\tsetting pipeFlag to None' %vars()
00288 else:
00289 TSC['Source'].extend( [alpha] )
00290
00291
00292 workingSet.add( alpha )
00293
00294 self.colour_white(alpha)
00295 delta = []
00296 pipeFlag = None
00297 print >> log, '\tsetting pipeFlag to None' %vars()
00298
00299
00300
00301 workingSet.update( delta )
00302 if delta: print >> log, '\tupdate the working set with %(delta)s' %vars()
00303
00304 TSC['Source'].extend( delta )
00305 if delta: print >> log, '\tadding %(delta)s to the source of pipe' %vars()
00306
00307 if beta:
00308
00309
00310
00311
00312
00313 TSC['Command'].insert( 0, beta )
00314 print >> log, '\tadding %(beta)s to the beginning of command' %vars()
00315 alpha = beta
00316
00317
00318 if self.colour( beta ) == 'grey':
00319 print >> log, '\t%(beta)s is grey changing pipeFalse to False' %vars()
00320 pipeFlag = False
00321
00322
00323 if not pipeFlag:
00324 workingSet.add( beta )
00325 print >> log, '\tadding %(beta)s to working set' %vars()
00326 else:
00327
00328
00329
00330 self.colour_grey(beta)
00331
00332 print >> log, '\tTSC: %(TSC)s\n' %vars()
00333
00334
00335 if beta:
00336 print >> log, 'adding %(beta)s to source of pipe\n' %vars()
00337 TSC['Source'].append( beta )
00338
00339
00340
00341 def toGraph( self ):
00342 """
00343 return graph representation of built object
00344 """
00345 g = DiGraph()
00346
00347 for l in self.lst:
00348 if l['Source'] == l['Command'] == l['Target']:
00349 continue
00350 s_diff = list(set(l['Source']).intersection( set(l['Target']) ))
00351 if s_diff:
00352
00353 l['Source'].remove( s_diff[0] )
00354 l['Target'].remove( s_diff[0] )
00355 for source in l['Source']:
00356 g.appendEdge( source, tuple( l['Command'] ) )
00357 for target in l['Target']:
00358 g.appendEdge( tuple( l['Command'] ), target )
00359
00360
00361
00362 return g
00363