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