<s> """<STR_LIT>""" <EOL> from __future__ import print_function <EOL> from collections import deque <EOL> import copy <EOL> import logging <EOL> import pdb <EOL> import sys <EOL> import time <EOL> import warnings <EOL> import traceback <EOL> import numpy <EOL> import theano <EOL> from theano import config <EOL> from theano . compat import izip , OrderedDict <EOL> from six import string_types , iteritems , itervalues <EOL> from six . moves import reduce <EOL> from theano . gof import graph , op , utils , unify , toolbox <EOL> from theano . gof . fg import InconsistencyError <EOL> from theano . misc . ordered_set import OrderedSet <EOL> from . import destroyhandler as dh <EOL> _logger = logging . getLogger ( '<STR_LIT>' ) <EOL> _optimizer_idx = [ <NUM_LIT:0> ] <EOL> def _list_of_nodes ( fgraph ) : <EOL> return list ( graph . io_toposort ( fgraph . inputs , fgraph . outputs ) ) <EOL> class Optimizer ( object ) : <EOL> """<STR_LIT>""" <EOL> def __hash__ ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _optimizer_idx = _optimizer_idx [ <NUM_LIT:0> ] <EOL> _optimizer_idx [ <NUM_LIT:0> ] += <NUM_LIT:1> <EOL> return self . _optimizer_idx <EOL> def __eq__ ( self , other ) : <EOL> return id ( self ) == id ( other ) <EOL> def __neq__ ( self , other ) : <EOL> return id ( self ) != id ( other ) <EOL> def apply ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def optimize ( self , fgraph , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . add_requirements ( fgraph ) <EOL> try : <EOL> orig = theano . tensor . basic . constant . enable <EOL> theano . tensor . basic . constant . enable = False <EOL> ret = self . apply ( fgraph , * args , ** kwargs ) <EOL> finally : <EOL> theano . tensor . basic . constant . enable = orig <EOL> return ret <EOL> def __call__ ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> return self . optimize ( fgraph ) <EOL> def add_requirements ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> name = getattr ( self , '<STR_LIT:name>' , None ) <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , name , id ( self ) ) , file = stream ) <EOL> @ staticmethod <EOL> def print_profile ( stream , prof , level = <NUM_LIT:0> ) : <EOL> if prof is not None : <EOL> raise NotImplementedError ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> class FromFunctionOptimizer ( Optimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fn , requirements = ( ) ) : <EOL> self . apply = fn <EOL> self . requirements = requirements <EOL> def add_requirements ( self , fgraph ) : <EOL> for req in self . requirements : <EOL> req ( fgraph ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> '<STR_LIT:U+0020>' * level , <EOL> str ( self . apply ) , <EOL> id ( self ) ) , file = stream ) <EOL> def __call__ ( self , * args , ** kwargs ) : <EOL> return self . fn ( * args , ** kwargs ) <EOL> def __str__ ( self ) : <EOL> return self . __name__ <EOL> def optimizer ( f ) : <EOL> """<STR_LIT>""" <EOL> rval = FromFunctionOptimizer ( f ) <EOL> rval . __name__ = f . __name__ <EOL> return rval <EOL> def inplace_optimizer ( f ) : <EOL> """<STR_LIT>""" <EOL> dh_handler = dh . DestroyHandler <EOL> requirements = ( lambda fgraph : <EOL> fgraph . attach_feature ( dh_handler ( ) ) , ) <EOL> rval = FromFunctionOptimizer ( f , requirements ) <EOL> rval . __name__ = f . __name__ <EOL> return rval <EOL> class SeqOptimizer ( Optimizer , list ) : <EOL> """<STR_LIT>""" <EOL> @ staticmethod <EOL> def warn ( exc , self , optimizer ) : <EOL> """<STR_LIT>""" <EOL> _logger . error ( "<STR_LIT>" % str ( optimizer ) ) <EOL> _logger . error ( "<STR_LIT>" ) <EOL> _logger . error ( traceback . format_exc ( ) ) <EOL> if config . on_opt_error == '<STR_LIT>' : <EOL> raise exc <EOL> elif config . on_opt_error == '<STR_LIT>' : <EOL> pdb . post_mortem ( sys . exc_info ( ) [ <NUM_LIT:2> ] ) <EOL> def __init__ ( self , * opts , ** kw ) : <EOL> """<STR_LIT>""" <EOL> if len ( opts ) == <NUM_LIT:1> and isinstance ( opts [ <NUM_LIT:0> ] , ( list , tuple ) ) : <EOL> opts = opts [ <NUM_LIT:0> ] <EOL> self [ : ] = opts <EOL> self . failure_callback = kw . pop ( '<STR_LIT>' , None ) <EOL> def apply ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> l = [ ] <EOL> if fgraph . profile : <EOL> validate_before = fgraph . profile . validate_time <EOL> sub_validate_time = [ validate_before ] <EOL> else : <EOL> sub_validate_time = [ ] <EOL> callback_before = fgraph . execute_callbacks_time <EOL> nb_node_before = len ( fgraph . apply_nodes ) <EOL> sub_profs = [ ] <EOL> for optimizer in self : <EOL> try : <EOL> t0 = time . time ( ) <EOL> sub_prof = optimizer . optimize ( fgraph ) <EOL> l . append ( float ( time . time ( ) - t0 ) ) <EOL> sub_profs . append ( sub_prof ) <EOL> if fgraph . profile : <EOL> sub_validate_time . append ( fgraph . profile . validate_time ) <EOL> except AssertionError : <EOL> raise <EOL> except Exception as e : <EOL> if self . failure_callback : <EOL> self . failure_callback ( e , self , optimizer ) <EOL> continue <EOL> else : <EOL> raise <EOL> if fgraph . profile : <EOL> validate_time = fgraph . profile . validate_time - validate_before <EOL> else : <EOL> validate_time = None <EOL> callback_time = fgraph . execute_callbacks_time - callback_before <EOL> return ( self , l , validate_time , callback_time , nb_node_before , <EOL> len ( fgraph . apply_nodes ) , sub_profs , sub_validate_time ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % list . __str__ ( self ) <EOL> def __repr__ ( self ) : <EOL> return list . __repr__ ( self ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> name = getattr ( self , '<STR_LIT:name>' , None ) <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , name , id ( self ) ) , file = stream ) <EOL> if depth != <NUM_LIT:0> : <EOL> depth -= <NUM_LIT:1> <EOL> for opt in self : <EOL> opt . print_summary ( stream , level = ( level + <NUM_LIT:2> ) , depth = depth ) <EOL> @ staticmethod <EOL> def print_profile ( stream , prof , level = <NUM_LIT:0> ) : <EOL> ( opts , prof , validate_time , callback_time , nb_node_before , <EOL> nb_node_after , sub_profs , sub_validate_time ) = prof <EOL> blanc = ( '<STR_LIT:U+0020>' * level ) <EOL> print ( blanc , "<STR_LIT>" , end = '<STR_LIT:U+0020>' , file = stream ) <EOL> if hasattr ( opts , "<STR_LIT:name>" ) : <EOL> print ( blanc , opts . name , end = '<STR_LIT:U+0020>' , file = stream ) <EOL> elif hasattr ( opts , "<STR_LIT>" ) : <EOL> print ( blanc , opts . __name__ , end = '<STR_LIT:U+0020>' , file = stream ) <EOL> print ( ( "<STR_LIT>" <EOL> "<STR_LIT>" % ( <EOL> sum ( prof ) , nb_node_before , nb_node_after ) ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( callback_time ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( validate_time ) , file = stream ) <EOL> if level == <NUM_LIT:0> : <EOL> print ( blanc , "<STR_LIT>" , file = stream ) <EOL> ll = [ ] <EOL> for opt in opts : <EOL> if hasattr ( opt , "<STR_LIT>" ) : <EOL> ll . append ( ( opt . __name__ , opt . __class__ . __name__ , <EOL> opts . index ( opt ) ) ) <EOL> else : <EOL> ll . append ( ( opt . name , opt . __class__ . __name__ , <EOL> opts . index ( opt ) ) ) <EOL> lll = sorted ( zip ( prof , ll ) , key = lambda a : a [ <NUM_LIT:0> ] ) <EOL> for ( t , opt ) in lll [ : : - <NUM_LIT:1> ] : <EOL> if sub_validate_time : <EOL> i = opt [ - <NUM_LIT:1> ] <EOL> val_time = sub_validate_time [ i + <NUM_LIT:1> ] - sub_validate_time [ i ] <EOL> print ( blanc , '<STR_LIT>' % ( <EOL> t , opt , val_time ) , file = stream ) <EOL> else : <EOL> print ( blanc , '<STR_LIT>' % ( t , opt ) , file = stream ) <EOL> if sub_profs [ opt [ - <NUM_LIT:1> ] ] : <EOL> opts [ opt [ - <NUM_LIT:1> ] ] . print_profile ( stream , sub_profs [ opt [ - <NUM_LIT:1> ] ] , <EOL> level = level + <NUM_LIT:1> ) <EOL> print ( file = stream ) <EOL> @ staticmethod <EOL> def merge_profile ( prof1 , prof2 ) : <EOL> """<STR_LIT>""" <EOL> new_t = [ ] <EOL> new_l = [ ] <EOL> new_sub_profile = [ ] <EOL> for l in set ( prof1 [ <NUM_LIT:0> ] ) . intersection ( set ( prof2 [ <NUM_LIT:0> ] ) ) : <EOL> idx1 = prof1 [ <NUM_LIT:0> ] . index ( l ) <EOL> idx2 = prof2 [ <NUM_LIT:0> ] . index ( l ) <EOL> new_t . append ( prof1 [ <NUM_LIT:1> ] [ idx1 ] + <EOL> prof2 [ <NUM_LIT:1> ] [ idx2 ] ) <EOL> new_l . append ( l ) <EOL> if hasattr ( l , '<STR_LIT>' ) : <EOL> assert len ( prof1 [ <NUM_LIT:6> ] [ idx1 ] ) == len ( prof2 [ <NUM_LIT:6> ] [ idx2 ] ) <EOL> new_sub_profile . append ( l . merge_profile ( prof1 [ <NUM_LIT:6> ] [ idx1 ] , <EOL> prof2 [ <NUM_LIT:6> ] [ idx2 ] ) ) <EOL> else : <EOL> new_sub_profile . append ( None ) <EOL> from six import StringIO <EOL> for l in set ( prof1 [ <NUM_LIT:0> ] ) . symmetric_difference ( set ( prof2 [ <NUM_LIT:0> ] ) ) : <EOL> new_l_names = [ o . name for o in new_l ] <EOL> if l . name in new_l_names : <EOL> idx = new_l_names . index ( l . name ) <EOL> io1 = StringIO ( ) <EOL> io2 = StringIO ( ) <EOL> l . print_summary ( io1 ) <EOL> new_l [ idx ] . print_summary ( io2 ) <EOL> if io1 . read ( ) == io2 . read ( ) : <EOL> if l in prof1 [ <NUM_LIT:0> ] : <EOL> p = prof1 <EOL> else : <EOL> p = prof2 <EOL> new_t [ idx ] += p [ <NUM_LIT:1> ] [ p [ <NUM_LIT:0> ] . index ( l ) ] <EOL> if hasattr ( l , '<STR_LIT>' ) : <EOL> assert len ( p [ <NUM_LIT:6> ] [ p [ <NUM_LIT:0> ] . index ( l ) ] ) == len ( new_sub_profile [ idx ] ) <EOL> new_sub_profile [ idx ] = l . merge_profile ( <EOL> new_sub_profile [ idx ] , p [ <NUM_LIT:6> ] [ p [ <NUM_LIT:0> ] . index ( l ) ] ) <EOL> else : <EOL> new_sub_profile [ idx ] = None <EOL> continue <EOL> if l in prof1 [ <NUM_LIT:0> ] : <EOL> p = prof1 <EOL> else : <EOL> p = prof2 <EOL> new_t . append ( p [ <NUM_LIT:1> ] [ p [ <NUM_LIT:0> ] . index ( l ) ] ) <EOL> idx = p [ <NUM_LIT:0> ] . index ( l ) <EOL> new_l . append ( l ) <EOL> new_sub_profile . append ( p [ <NUM_LIT:6> ] [ idx ] ) <EOL> new_opt = SeqOptimizer ( * new_l ) <EOL> assert set ( [ l . name for l in prof1 [ <NUM_LIT:0> ] ] ) . issubset ( <EOL> set ( [ l . name for l in new_l ] ) ) <EOL> assert set ( [ l . name for l in prof2 [ <NUM_LIT:0> ] ] ) . issubset ( <EOL> set ( [ l . name for l in new_l ] ) ) <EOL> assert len ( new_t ) == len ( new_opt ) == len ( new_sub_profile ) <EOL> return ( new_opt , new_t , prof1 [ <NUM_LIT:2> ] + prof2 [ <NUM_LIT:2> ] , <EOL> prof1 [ <NUM_LIT:3> ] + prof2 [ <NUM_LIT:3> ] , <EOL> - <NUM_LIT:1> , - <NUM_LIT:1> , new_sub_profile , [ ] ) <EOL> class _metadict : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . d = { } <EOL> self . l = [ ] <EOL> def __getitem__ ( self , item ) : <EOL> return self . get ( item , None ) <EOL> def __setitem__ ( self , item , value ) : <EOL> try : <EOL> self . d [ item ] = value <EOL> except Exception : <EOL> for i , ( key , val ) in enumerate ( self . l ) : <EOL> if key == item : <EOL> self . l [ i ] = ( item , value ) <EOL> return <EOL> self . l . append ( ( item , value ) ) <EOL> def __delitem__ ( self , item ) : <EOL> try : <EOL> if item in self . d : <EOL> del self . d [ item ] <EOL> return <EOL> except TypeError as e : <EOL> assert "<STR_LIT>" in str ( e ) <EOL> for i , ( key , val ) in enumerate ( self . l ) : <EOL> if key == item : <EOL> del self . l [ i ] <EOL> return <EOL> raise KeyError ( item ) <EOL> def discard ( self , item ) : <EOL> try : <EOL> if item in self . d : <EOL> del self . d [ item ] <EOL> return <EOL> except TypeError as e : <EOL> assert "<STR_LIT>" in str ( e ) <EOL> for i , ( key , val ) in enumerate ( self . l ) : <EOL> if key == item : <EOL> del self . l [ i ] <EOL> return <EOL> def get ( self , item , default ) : <EOL> try : <EOL> return self . d [ item ] <EOL> except Exception : <EOL> for item2 , value in self . l : <EOL> try : <EOL> if item == item2 : <EOL> return value <EOL> if item . equals ( item2 ) : <EOL> return value <EOL> except Exception : <EOL> if item is item2 : <EOL> return value <EOL> else : <EOL> return default <EOL> def clear ( self ) : <EOL> self . d = { } <EOL> self . l = [ ] <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . d , self . l ) <EOL> class MergeFeature ( object ) : <EOL> """<STR_LIT>""" <EOL> def on_attach ( self , fgraph ) : <EOL> assert not hasattr ( fgraph , '<STR_LIT>' ) <EOL> fgraph . merge_feature = self <EOL> self . seen_constants = set ( ) <EOL> self . const_sig = _metadict ( ) <EOL> self . const_sig_inv = _metadict ( ) <EOL> self . nodes_seen = set ( ) <EOL> self . noinput_nodes = OrderedSet ( ) <EOL> self . scheduled = [ ] <EOL> self . blacklist = [ ] <EOL> for node in fgraph . toposort ( ) : <EOL> self . on_import ( fgraph , node , "<STR_LIT>" ) <EOL> def on_change_input ( self , fgraph , node , i , r , new_r , reason ) : <EOL> if node in self . nodes_seen : <EOL> self . nodes_seen . discard ( node ) <EOL> self . process_node ( fgraph , node ) <EOL> if not isinstance ( node , string_types ) : <EOL> assert node . inputs <EOL> if isinstance ( new_r , graph . Constant ) : <EOL> self . process_constant ( fgraph , new_r ) <EOL> def on_import ( self , fgraph , node , reason ) : <EOL> for c in node . inputs : <EOL> if isinstance ( c , graph . Constant ) : <EOL> self . process_constant ( fgraph , c ) <EOL> self . process_node ( fgraph , node ) <EOL> def on_prune ( self , fgraph , node , reason ) : <EOL> self . nodes_seen . discard ( node ) <EOL> if not node . inputs : <EOL> self . noinput_nodes . discard ( node ) <EOL> for c in node . inputs : <EOL> if isinstance ( c , graph . Constant ) and ( len ( c . clients ) <= <NUM_LIT:1> ) : <EOL> sig = self . const_sig [ c ] <EOL> self . const_sig . discard ( c ) <EOL> self . const_sig_inv . discard ( sig ) <EOL> self . seen_constants . discard ( id ( c ) ) <EOL> def process_constant ( self , fgraph , c ) : <EOL> """<STR_LIT>""" <EOL> if id ( c ) in self . seen_constants : <EOL> return <EOL> sig = c . merge_signature ( ) <EOL> other_c = self . const_sig_inv . get ( sig , None ) <EOL> if other_c is not None : <EOL> if c . name : <EOL> other_c . name = c . name <EOL> self . scheduled . append ( [ [ ( c , other_c , '<STR_LIT>' ) ] ] ) <EOL> else : <EOL> self . const_sig [ c ] = sig <EOL> self . const_sig_inv [ sig ] = c <EOL> self . seen_constants . add ( id ( c ) ) <EOL> def process_node ( self , fgraph , node ) : <EOL> """<STR_LIT>""" <EOL> if node in self . nodes_seen : <EOL> return <EOL> node_has_assert = False <EOL> if node . inputs : <EOL> assert len ( node . inputs [ <NUM_LIT:0> ] . clients ) > <NUM_LIT:0> <EOL> assert ( node , <NUM_LIT:0> ) in node . inputs [ <NUM_LIT:0> ] . clients <EOL> merge_candidates = [ c for ( c , i ) in node . inputs [ <NUM_LIT:0> ] . clients <EOL> if c in self . nodes_seen ] <EOL> for i in [ ] : <EOL> if i . owner and isinstance ( i . owner . op , <EOL> theano . tensor . opt . Assert ) : <EOL> node_has_assert = True <EOL> assert_clients = [ c for ( c , _ ) in i . owner . inputs [ <NUM_LIT:0> ] . clients <EOL> if c in self . nodes_seen ] <EOL> for idx in range ( len ( assert_clients ) ) : <EOL> client = assert_clients [ idx ] <EOL> if isinstance ( i . owner . op , theano . tensor . opt . Assert ) : <EOL> for c in client . outputs [ <NUM_LIT:0> ] . clients : <EOL> if c [ <NUM_LIT:0> ] in self . nodes_seen : <EOL> assert_clients . append ( c [ <NUM_LIT:0> ] ) <EOL> merge_candidates . extend ( assert_clients ) <EOL> else : <EOL> merge_candidates = self . noinput_nodes <EOL> replacement_candidates = [ ] <EOL> for candidate in merge_candidates : <EOL> if candidate is node : <EOL> continue <EOL> if len ( node . inputs ) != len ( candidate . inputs ) : <EOL> continue <EOL> cand_has_assert = False <EOL> cand_inputs_assert_removed = [ ] <EOL> for i in candidate . inputs : <EOL> if i . owner and isinstance ( i . owner . op , <EOL> theano . tensor . opt . Assert ) : <EOL> cand_has_assert = True <EOL> cand_inputs_assert_removed . append ( i . owner . inputs [ <NUM_LIT:0> ] ) <EOL> else : <EOL> cand_inputs_assert_removed . append ( i ) <EOL> if node_has_assert : <EOL> node_inputs_assert_removed = [ ] <EOL> for i in node . inputs : <EOL> if i . owner and isinstance ( i . owner . op , <EOL> theano . tensor . opt . Assert ) : <EOL> node_inputs_assert_removed . append ( i . owner . inputs [ <NUM_LIT:0> ] ) <EOL> else : <EOL> node_inputs_assert_removed . append ( i ) <EOL> else : <EOL> node_inputs_assert_removed = node . inputs <EOL> inputs_match = all ( node_in is cand_in <EOL> for node_in , cand_in <EOL> in zip ( node_inputs_assert_removed , <EOL> cand_inputs_assert_removed ) ) <EOL> if inputs_match and node . op == candidate . op : <EOL> if ( node , candidate ) in self . blacklist : <EOL> continue <EOL> if not ( node_has_assert or cand_has_assert ) : <EOL> pairs = list ( zip ( node . outputs , <EOL> candidate . outputs , <EOL> [ '<STR_LIT>' ] * len ( node . outputs ) ) ) <EOL> elif node_has_assert and not cand_has_assert : <EOL> pairs = list ( zip ( candidate . outputs , <EOL> node . outputs , <EOL> [ '<STR_LIT>' ] * len ( node . outputs ) ) ) <EOL> else : <EOL> new_inputs = self . get_merged_assert_input ( node , candidate ) <EOL> new_node = node . op ( * new_inputs ) <EOL> pairs = list ( zip ( node . outputs , <EOL> new_node . owner . outputs , <EOL> [ '<STR_LIT>' ] * len ( node . outputs ) ) ) + list ( zip ( candidate . outputs , <EOL> new_node . owner . outputs , <EOL> [ '<STR_LIT>' ] * len ( node . outputs ) ) ) <EOL> for pair in pairs : <EOL> node_output , cand_output = pair [ : <NUM_LIT:2> ] <EOL> if node_output . name : <EOL> cand_output . name = node_output . name <EOL> replacement_candidates . append ( pairs ) <EOL> if replacement_candidates : <EOL> self . scheduled . append ( replacement_candidates ) <EOL> else : <EOL> self . nodes_seen . add ( node ) <EOL> if not node . inputs : <EOL> self . noinput_nodes . add ( node ) <EOL> def get_merged_assert_input ( self , node , candidate ) : <EOL> new_inputs = [ ] <EOL> for node_i , cand_i in zip ( node . inputs , candidate . inputs ) : <EOL> if ( node_i . owner and <EOL> isinstance ( node_i . owner . op , <EOL> theano . tensor . opt . Assert ) ) : <EOL> if ( cand_i . owner and <EOL> isinstance ( cand_i . owner . op , <EOL> theano . tensor . opt . Assert ) ) : <EOL> node_cond = node_i . owner . inputs [ <NUM_LIT:1> : ] <EOL> cand_cond = cand_i . owner . inputs [ <NUM_LIT:1> : ] <EOL> new_cond = list ( set ( node_cond + cand_cond ) ) <EOL> new_inputs . append ( <EOL> theano . tensor . opt . assert_op ( <EOL> node_i . owner . inputs [ <NUM_LIT:0> ] , <EOL> * new_cond ) ) <EOL> else : <EOL> new_inputs . append ( node_i ) <EOL> else : <EOL> new_inputs . append ( cand_i ) <EOL> return new_inputs <EOL> class MergeOptimizer ( Optimizer ) : <EOL> """<STR_LIT>""" <EOL> def add_requirements ( self , fgraph ) : <EOL> if not hasattr ( fgraph , '<STR_LIT>' ) : <EOL> fgraph . attach_feature ( MergeFeature ( ) ) <EOL> def apply ( self , fgraph ) : <EOL> sched = fgraph . merge_feature . scheduled <EOL> nb_fail = <NUM_LIT:0> <EOL> t0 = time . time ( ) <EOL> if fgraph . profile : <EOL> validate_before = fgraph . profile . validate_time <EOL> callback_before = fgraph . execute_callbacks_time <EOL> callbacks_before = fgraph . execute_callbacks_times . copy ( ) <EOL> nb_merged = <NUM_LIT:0> <EOL> nb_constant = <NUM_LIT:0> <EOL> while sched : <EOL> pairs_list = sched . pop ( ) <EOL> success = True <EOL> for pairs_ in pairs_list : <EOL> var , candidate , merge_mode = pairs_ [ <NUM_LIT:0> ] <EOL> if merge_mode == "<STR_LIT>" and hasattr ( var , '<STR_LIT>' ) : <EOL> pass <EOL> elif ( not hasattr ( var , '<STR_LIT>' ) or <EOL> not hasattr ( candidate , '<STR_LIT>' ) ) : <EOL> continue <EOL> pairs = [ pair [ : <NUM_LIT:2> ] for pair in pairs_ ] <EOL> if var . owner and candidate . owner : <EOL> node = var . owner <EOL> candidate = candidate . owner <EOL> cand_inputs_assert_removed = [ ] <EOL> for i in candidate . inputs : <EOL> if i . owner and isinstance ( i . owner . op , <EOL> theano . tensor . opt . Assert ) : <EOL> cand_inputs_assert_removed . append ( <EOL> i . owner . inputs [ <NUM_LIT:0> ] ) <EOL> else : <EOL> cand_inputs_assert_removed . append ( i ) <EOL> node_inputs_assert_removed = [ ] <EOL> for i in node . inputs : <EOL> if i . owner and isinstance ( i . owner . op , <EOL> theano . tensor . opt . Assert ) : <EOL> node_inputs_assert_removed . append ( <EOL> i . owner . inputs [ <NUM_LIT:0> ] ) <EOL> else : <EOL> node_inputs_assert_removed . append ( i ) <EOL> if merge_mode == "<STR_LIT>" : <EOL> inputs_match = True <EOL> else : <EOL> inputs_match = all ( node_in is cand_in <EOL> for node_in , cand_in in <EOL> zip ( node_inputs_assert_removed , <EOL> cand_inputs_assert_removed ) ) <EOL> if not inputs_match : <EOL> continue <EOL> if hasattr ( pairs [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] . fgraph , '<STR_LIT>' ) : <EOL> clients = pairs [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] . clients + pairs [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] . clients <EOL> if sum ( [ i in utils . flatten ( c . op . destroy_map . values ( ) ) <EOL> for c , i in clients <EOL> if c != '<STR_LIT>' and <EOL> hasattr ( c . op , '<STR_LIT>' ) ] ) > <NUM_LIT:1> : <EOL> continue <EOL> try : <EOL> fgraph . replace_all_validate ( pairs , '<STR_LIT>' ) <EOL> except InconsistencyError : <EOL> success = False <EOL> nb_fail += <NUM_LIT:1> <EOL> fgraph . merge_feature . blacklist . append ( <EOL> ( pairs [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] . owner , pairs [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] . owner ) ) <EOL> if success : <EOL> nb_merged += len ( pairs ) <EOL> if isinstance ( pairs [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] , graph . Constant ) : <EOL> nb_constant += <NUM_LIT:1> <EOL> break <EOL> if fgraph . profile : <EOL> validate_time = fgraph . profile . validate_time - validate_before <EOL> callback_time = fgraph . execute_callbacks_time - callback_before <EOL> callbacks_time = { } <EOL> for k , v in iteritems ( fgraph . execute_callbacks_times ) : <EOL> if k in callbacks_before : <EOL> callbacks_time [ k ] = v - callbacks_before [ k ] <EOL> else : <EOL> callbacks_time [ k ] = v <EOL> else : <EOL> validate_time = None <EOL> callback_time = None <EOL> callbacks_time = { } <EOL> fgraph . merge_feature . blacklist = [ ] <EOL> return ( nb_fail , time . time ( ) - t0 , validate_time , <EOL> callback_time , callbacks_time , nb_merged , nb_constant ) <EOL> def __str__ ( self ) : <EOL> return self . __class__ . __name__ <EOL> @ staticmethod <EOL> def print_profile ( stream , prof , level = <NUM_LIT:0> ) : <EOL> ( nb_fail , replace_time , validate_time , <EOL> callback_time , callbacks_time , nb_merged , nb_constant ) = prof <EOL> blanc = ( '<STR_LIT:U+0020>' * level ) <EOL> print ( blanc , "<STR_LIT>" , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( <EOL> nb_fail , nb_merged , nb_constant ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( <EOL> replace_time , validate_time , callback_time ) , file = stream ) <EOL> if callback_time > <NUM_LIT:1> : <EOL> print ( blanc , "<STR_LIT>" , file = stream ) <EOL> for i in sorted ( iteritems ( callbacks_time ) , key = lambda a : a [ <NUM_LIT:1> ] ) : <EOL> if i [ <NUM_LIT:1> ] > <NUM_LIT:0> : <EOL> print ( i ) <EOL> @ staticmethod <EOL> def merge_profile ( prof1 , prof2 ) : <EOL> def merge_none_number ( v1 , v2 ) : <EOL> if v1 is None : <EOL> return v2 <EOL> if v2 is None : <EOL> return v1 <EOL> return v1 + v2 <EOL> nb_fail = prof1 [ <NUM_LIT:0> ] + prof2 [ <NUM_LIT:0> ] <EOL> replace_time = prof1 [ <NUM_LIT:1> ] + prof2 [ <NUM_LIT:1> ] <EOL> validate_time = merge_none_number ( prof1 [ <NUM_LIT:2> ] , prof2 [ <NUM_LIT:2> ] ) <EOL> callback_time = merge_none_number ( prof1 [ <NUM_LIT:3> ] , prof2 [ <NUM_LIT:3> ] ) <EOL> callbacks_time = merge_dict ( prof1 [ <NUM_LIT:4> ] , prof2 [ <NUM_LIT:4> ] ) <EOL> nb_merged = prof1 [ <NUM_LIT:5> ] + prof2 [ <NUM_LIT:5> ] <EOL> nb_constant = prof1 [ <NUM_LIT:6> ] + prof2 [ <NUM_LIT:6> ] <EOL> return ( nb_fail , replace_time , validate_time , <EOL> callback_time , callbacks_time , nb_merged , nb_constant ) <EOL> def is_same_graph_with_merge ( var1 , var2 , givens = None ) : <EOL> """<STR_LIT>""" <EOL> if givens is None : <EOL> givens = { } <EOL> copied = copy . deepcopy ( [ var1 , var2 , givens ] ) <EOL> vars = copied [ <NUM_LIT:0> : <NUM_LIT:2> ] <EOL> givens = copied [ <NUM_LIT:2> ] <EOL> inputs = theano . gof . graph . inputs ( vars ) <EOL> fgraph = theano . gof . fg . FunctionGraph ( inputs , vars , clone = False ) <EOL> for to_replace , replace_by in iteritems ( givens ) : <EOL> fgraph . replace ( to_replace , replace_by ) <EOL> MergeOptimizer ( ) . optimize ( fgraph ) <EOL> vars_replaced = [ givens . get ( v , v ) for v in vars ] <EOL> o1 , o2 = [ v . owner for v in vars_replaced ] <EOL> if o1 is None and o2 is None : <EOL> return vars_replaced [ <NUM_LIT:0> ] == vars_replaced [ <NUM_LIT:1> ] <EOL> else : <EOL> return o1 is o2 <EOL> def pre_constant_merge ( vars ) : <EOL> """<STR_LIT>""" <EOL> seen_var = set ( ) <EOL> const_sig_inv = { } <EOL> if isinstance ( vars , graph . Variable ) : <EOL> vars = [ vars ] <EOL> def recursive_merge ( var ) : <EOL> if var in seen_var : <EOL> return var <EOL> if not hasattr ( var , '<STR_LIT>' ) : <EOL> return var <EOL> if var . owner and hasattr ( var . owner , "<STR_LIT>" ) : <EOL> return var <EOL> seen_var . add ( var ) <EOL> if isinstance ( var , graph . Constant ) : <EOL> sig = var . signature ( ) <EOL> try : <EOL> if sig in const_sig_inv : <EOL> return const_sig_inv [ sig ] <EOL> const_sig_inv [ sig ] = var <EOL> except TypeError : <EOL> warnings . warn ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" % var ) <EOL> pass <EOL> return var <EOL> if var . owner : <EOL> for idx , inp in enumerate ( var . owner . inputs ) : <EOL> var . owner . inputs [ idx ] = recursive_merge ( inp ) <EOL> return var <EOL> return list ( map ( recursive_merge , vars ) ) <EOL> class LocalOptimizer ( object ) : <EOL> """<STR_LIT>""" <EOL> def __hash__ ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _optimizer_idx = _optimizer_idx [ <NUM_LIT:0> ] <EOL> _optimizer_idx [ <NUM_LIT:0> ] += <NUM_LIT:1> <EOL> return self . _optimizer_idx <EOL> def tracks ( self ) : <EOL> """<STR_LIT>""" <EOL> return None <EOL> def transform ( self , node ) : <EOL> """<STR_LIT>""" <EOL> raise utils . MethodNotDefined ( "<STR_LIT>" , <EOL> type ( self ) , self . __class__ . __name__ ) <EOL> def add_requirements ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , id ( self ) ) , file = stream ) <EOL> class LocalMetaOptimizer ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , tracks = None , optimizers = ( ) ) : <EOL> self . _tracks = tracks <EOL> self . optimizers = list ( optimizers ) <EOL> self . verbose = config . metaopt . verbose <EOL> def register ( self , optimizer ) : <EOL> self . optimizers . append ( optimizer ) <EOL> def tracks ( self ) : <EOL> return self . _tracks <EOL> def transform ( self , node ) : <EOL> if self . _tracks is not None : <EOL> if not isinstance ( node . op , tuple ( self . _tracks ) ) : <EOL> return <EOL> givens = { } <EOL> missing = set ( ) <EOL> for input in node . inputs : <EOL> if isinstance ( input , theano . compile . SharedVariable ) : <EOL> pass <EOL> elif hasattr ( input . tag , '<STR_LIT>' ) : <EOL> givens [ input ] = theano . shared ( <EOL> input . type . filter ( input . tag . test_value ) , <EOL> input . name , <EOL> broadcastable = input . broadcastable , <EOL> borrow = True ) <EOL> else : <EOL> missing . add ( input ) <EOL> if missing : <EOL> givens . update ( self . provide_inputs ( node , missing ) ) <EOL> missing . difference_update ( givens . keys ( ) ) <EOL> if missing : <EOL> if self . verbose : <EOL> print ( ( "<STR_LIT>" <EOL> "<STR_LIT>" % <EOL> ( self . __class__ . __name__ , node , len ( missing ) , node . nin ) ) ) <EOL> return <EOL> if self . verbose : <EOL> print ( ( "<STR_LIT>" % <EOL> ( self . __class__ . __name__ , node , len ( self . optimizers ) ) ) ) <EOL> timings = [ ] <EOL> for opt in self . optimizers : <EOL> outputs = opt . transform ( node ) <EOL> if outputs : <EOL> try : <EOL> fn = theano . function ( [ ] , outputs , givens = givens , <EOL> on_unused_input = '<STR_LIT:ignore>' ) <EOL> timing = min ( self . time_call ( fn ) for _ in range ( <NUM_LIT:3> ) ) <EOL> except Exception as e : <EOL> if self . verbose : <EOL> print ( "<STR_LIT>" % opt , e ) <EOL> continue <EOL> else : <EOL> if self . verbose : <EOL> print ( "<STR_LIT>" % ( opt , timing ) ) <EOL> timings . append ( ( timing , outputs , opt ) ) <EOL> else : <EOL> if self . verbose : <EOL> print ( "<STR_LIT>" % opt ) <EOL> if timings : <EOL> timings . sort ( ) <EOL> if self . verbose : <EOL> print ( "<STR_LIT>" % timings [ <NUM_LIT:0> ] [ <NUM_LIT:2> ] ) <EOL> return timings [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] <EOL> return <EOL> def provide_inputs ( self , node , inputs ) : <EOL> """<STR_LIT>""" <EOL> raise NotImplementedError ( ) <EOL> def time_call ( self , fn ) : <EOL> start = time . time ( ) <EOL> fn ( ) <EOL> return time . time ( ) - start <EOL> class FromFunctionLocalOptimizer ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , fn , tracks = None , requirements = ( ) ) : <EOL> self . transform = fn <EOL> self . _tracks = tracks <EOL> self . requirements = requirements <EOL> def add_requirements ( self , fgraph ) : <EOL> for req in self . requirements : <EOL> req ( fgraph ) <EOL> def tracks ( self ) : <EOL> return self . _tracks <EOL> def __str__ ( self ) : <EOL> return getattr ( self , '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> '<STR_LIT:U+0020>' * level , <EOL> str ( self . transform ) , <EOL> id ( self ) ) , file = stream ) <EOL> def local_optimizer ( tracks , inplace = False , requirements = ( ) ) : <EOL> def decorator ( f ) : <EOL> """<STR_LIT>""" <EOL> if tracks is not None : <EOL> if len ( tracks ) is <NUM_LIT:0> : <EOL> raise ValueError ( "<STR_LIT>" , f . __module__ , f . __name__ ) <EOL> for t in tracks : <EOL> if not ( isinstance ( t , op . Op ) or issubclass ( t , op . PureOp ) ) : <EOL> raise ValueError ( "<STR_LIT>" , f . __module__ , f . __name__ ) <EOL> req = requirements <EOL> if inplace : <EOL> dh_handler = dh . DestroyHandler <EOL> req = tuple ( requirements ) + ( <EOL> lambda fgraph : <EOL> fgraph . attach_feature ( dh_handler ( ) ) , ) <EOL> rval = FromFunctionLocalOptimizer ( f , tracks , req ) <EOL> rval . __name__ = f . __name__ <EOL> return rval <EOL> return decorator <EOL> class LocalOptGroup ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * optimizers ) : <EOL> if len ( optimizers ) == <NUM_LIT:1> and isinstance ( optimizers [ <NUM_LIT:0> ] , list ) : <EOL> optimizers = tuple ( optimizers [ <NUM_LIT:0> ] ) <EOL> self . opts = optimizers <EOL> self . reentrant = any ( getattr ( opt , '<STR_LIT>' , True ) <EOL> for opt in optimizers ) <EOL> self . retains_inputs = all ( getattr ( opt , '<STR_LIT>' , False ) <EOL> for opt in optimizers ) <EOL> def __str__ ( self ) : <EOL> return getattr ( self , '<STR_LIT>' , <EOL> ( '<STR_LIT>' % <EOL> '<STR_LIT:U+002C>' . join ( [ str ( o ) for o in self . opts ] ) ) ) <EOL> def tracks ( self ) : <EOL> t = [ ] <EOL> for l in self . opts : <EOL> tt = l . tracks ( ) <EOL> if tt : <EOL> t . extend ( tt ) <EOL> return t <EOL> def transform ( self , node ) : <EOL> for opt in self . opts : <EOL> repl = opt . transform ( node ) <EOL> if repl : <EOL> return repl <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , id ( self ) ) , file = stream ) <EOL> if depth != <NUM_LIT:0> : <EOL> depth -= <NUM_LIT:1> <EOL> for lopt in self . opts : <EOL> lopt . print_summary ( stream , level = ( level + <NUM_LIT:2> ) , depth = depth ) <EOL> def add_requirements ( self , fgraph ) : <EOL> for opt in self . opts : <EOL> opt . add_requirements ( fgraph ) <EOL> class OpSub ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> reentrant = False <EOL> retains_inputs = True <EOL> def __init__ ( self , op1 , op2 , transfer_tags = True ) : <EOL> self . op1 = op1 <EOL> self . op2 = op2 <EOL> self . transfer_tags = transfer_tags <EOL> def op_key ( self ) : <EOL> return self . op1 <EOL> def tracks ( self ) : <EOL> return [ self . op1 ] <EOL> def transform ( self , node ) : <EOL> if node . op != self . op1 : <EOL> return False <EOL> repl = self . op2 . make_node ( * node . inputs ) <EOL> if self . transfer_tags : <EOL> repl . tag = copy . copy ( node . tag ) <EOL> for output , new_output in zip ( node . outputs , repl . outputs ) : <EOL> new_output . tag = copy . copy ( output . tag ) <EOL> return repl . outputs <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . op1 , self . op2 ) <EOL> class OpRemove ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> reentrant = False <EOL> def __init__ ( self , op ) : <EOL> self . op = op <EOL> def op_key ( self ) : <EOL> return self . op <EOL> def tracks ( self ) : <EOL> return [ self . op ] <EOL> def transform ( self , node ) : <EOL> if node . op != self . op : <EOL> return False <EOL> return node . inputs <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . op ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> '<STR_LIT:U+0020>' * level , <EOL> self . __class__ . __name__ , <EOL> str ( self . op ) , <EOL> id ( self ) ) , file = stream ) <EOL> class PatternSub ( LocalOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , in_pattern , out_pattern , <EOL> allow_multiple_clients = False , <EOL> skip_identities_fn = None , name = None , pdb = False , <EOL> tracks = ( ) , get_nodes = None , <EOL> values_eq_approx = None ) : <EOL> self . in_pattern = in_pattern <EOL> self . out_pattern = out_pattern <EOL> self . values_eq_approx = values_eq_approx <EOL> if isinstance ( in_pattern , ( list , tuple ) ) : <EOL> self . op = self . in_pattern [ <NUM_LIT:0> ] <EOL> elif isinstance ( in_pattern , dict ) : <EOL> self . op = self . in_pattern [ '<STR_LIT>' ] [ <NUM_LIT:0> ] <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . __doc__ = ( self . __class__ . __doc__ + <EOL> "<STR_LIT>" + <EOL> str ( self ) + "<STR_LIT:\n>" ) <EOL> self . allow_multiple_clients = allow_multiple_clients <EOL> self . skip_identities_fn = skip_identities_fn <EOL> if name : <EOL> self . __name__ = name <EOL> self . pdb = pdb <EOL> self . _tracks = tracks <EOL> self . get_nodes = get_nodes <EOL> if tracks != ( ) : <EOL> assert get_nodes <EOL> def op_key ( self ) : <EOL> return self . op <EOL> def tracks ( self ) : <EOL> if self . _tracks != ( ) : <EOL> return self . _tracks <EOL> return [ self . op ] <EOL> def transform ( self , node , get_nodes = True ) : <EOL> """<STR_LIT>""" <EOL> if get_nodes and self . get_nodes is not None : <EOL> for real_node in self . get_nodes ( node ) : <EOL> if real_node == "<STR_LIT>" : <EOL> continue <EOL> ret = self . transform ( real_node , get_nodes = False ) <EOL> if ret is not False and ret is not None : <EOL> assert len ( real_node . outputs ) == len ( ret ) <EOL> if self . values_eq_approx : <EOL> ret . tag . values_eq_approx = self . values_eq_approx <EOL> return dict ( izip ( real_node . outputs , ret ) ) <EOL> if node . op != self . op : <EOL> return False <EOL> def match ( pattern , expr , u , allow_multiple_clients = False , pdb = False ) : <EOL> def retry_with_equiv ( ) : <EOL> if not self . skip_identities_fn : <EOL> return False <EOL> expr_equiv = self . skip_identities_fn ( expr ) <EOL> if expr_equiv is None : <EOL> return False <EOL> return match ( pattern , expr_equiv , u , <EOL> allow_multiple_clients = allow_multiple_clients ) <EOL> if isinstance ( pattern , ( list , tuple ) ) : <EOL> if expr . owner is None : <EOL> return False <EOL> if ( not ( expr . owner . op == pattern [ <NUM_LIT:0> ] ) or <EOL> ( not allow_multiple_clients and len ( expr . clients ) > <NUM_LIT:1> ) ) : <EOL> return retry_with_equiv ( ) <EOL> if len ( pattern ) - <NUM_LIT:1> != len ( expr . owner . inputs ) : <EOL> return retry_with_equiv ( ) <EOL> for p , v in zip ( pattern [ <NUM_LIT:1> : ] , expr . owner . inputs ) : <EOL> u = match ( p , v , u , self . allow_multiple_clients ) <EOL> if not u : <EOL> return False <EOL> elif isinstance ( pattern , dict ) : <EOL> try : <EOL> real_pattern = pattern [ '<STR_LIT>' ] <EOL> except KeyError : <EOL> raise KeyError ( <EOL> "<STR_LIT>" <EOL> % pattern ) <EOL> constraint = pattern . get ( '<STR_LIT>' , lambda expr : True ) <EOL> if constraint ( expr ) : <EOL> return match ( real_pattern , expr , u , <EOL> pattern . get ( '<STR_LIT>' , <EOL> allow_multiple_clients ) ) <EOL> else : <EOL> return retry_with_equiv ( ) <EOL> elif isinstance ( pattern , string_types ) : <EOL> v = unify . Var ( pattern ) <EOL> if u [ v ] is not v and u [ v ] is not expr : <EOL> return retry_with_equiv ( ) <EOL> else : <EOL> u = u . merge ( expr , v ) <EOL> elif ( isinstance ( pattern , ( int , float ) ) and <EOL> isinstance ( expr , graph . Constant ) ) : <EOL> if numpy . all ( <EOL> theano . tensor . constant ( pattern ) . value == expr . value ) : <EOL> return u <EOL> else : <EOL> return retry_with_equiv ( ) <EOL> elif ( isinstance ( pattern , graph . Constant ) and <EOL> isinstance ( expr , graph . Constant ) and <EOL> pattern . equals ( expr ) ) : <EOL> return u <EOL> else : <EOL> return retry_with_equiv ( ) <EOL> if pdb : <EOL> import pdb <EOL> pdb . set_trace ( ) <EOL> return u <EOL> u = match ( self . in_pattern , node . out , unify . Unification ( ) , True , <EOL> self . pdb ) <EOL> if u : <EOL> def build ( pattern , u ) : <EOL> if isinstance ( pattern , ( list , tuple ) ) : <EOL> args = [ build ( p , u ) for p in pattern [ <NUM_LIT:1> : ] ] <EOL> return pattern [ <NUM_LIT:0> ] ( * args ) <EOL> elif isinstance ( pattern , string_types ) : <EOL> return u [ unify . Var ( pattern ) ] <EOL> elif isinstance ( pattern , ( int , float ) ) : <EOL> return pattern <EOL> else : <EOL> return pattern . clone ( ) <EOL> p = self . out_pattern <EOL> ret = build ( p , u ) <EOL> if self . values_eq_approx : <EOL> ret . tag . values_eq_approx = self . values_eq_approx <EOL> return [ ret ] <EOL> else : <EOL> return False <EOL> def __str__ ( self ) : <EOL> if getattr ( self , '<STR_LIT>' , None ) : <EOL> return self . __name__ <EOL> def pattern_to_str ( pattern ) : <EOL> if isinstance ( pattern , ( list , tuple ) ) : <EOL> return "<STR_LIT>" % ( <EOL> str ( pattern [ <NUM_LIT:0> ] ) , <EOL> "<STR_LIT:U+002CU+0020>" . join ( [ pattern_to_str ( p ) for p in pattern [ <NUM_LIT:1> : ] ] ) ) <EOL> elif isinstance ( pattern , dict ) : <EOL> return "<STR_LIT>" % ( <EOL> pattern_to_str ( pattern [ '<STR_LIT>' ] ) , <EOL> str ( pattern . get ( '<STR_LIT>' , '<STR_LIT>' ) ) ) <EOL> else : <EOL> return str ( pattern ) <EOL> return "<STR_LIT>" % ( <EOL> pattern_to_str ( self . in_pattern ) , <EOL> pattern_to_str ( self . out_pattern ) ) <EOL> def __repr__ ( self ) : <EOL> return str ( self ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> name = getattr ( self , '<STR_LIT>' , getattr ( self , '<STR_LIT:name>' , None ) ) <EOL> print ( "<STR_LIT>" % ( <EOL> '<STR_LIT:U+0020>' * level , <EOL> self . __class__ . __name__ , <EOL> name , <EOL> str ( self . in_pattern ) , <EOL> str ( self . out_pattern ) , <EOL> id ( self ) ) , file = stream ) <EOL> class Updater : <EOL> def __init__ ( self , importer , pruner , chin ) : <EOL> self . importer = importer <EOL> self . pruner = pruner <EOL> self . chin = chin <EOL> def on_import ( self , fgraph , node , reason ) : <EOL> if self . importer : <EOL> self . importer ( node ) <EOL> def on_prune ( self , fgraph , node , reason ) : <EOL> if self . pruner : <EOL> self . pruner ( node ) <EOL> def on_change_input ( self , fgraph , node , i , r , new_r , reason ) : <EOL> if self . chin : <EOL> self . chin ( node , i , r , new_r , reason ) <EOL> def on_detach ( self , fgraph ) : <EOL> self . importer = None <EOL> self . pruner = None <EOL> self . chin = None <EOL> class NavigatorOptimizer ( Optimizer ) : <EOL> """<STR_LIT>""" <EOL> @ staticmethod <EOL> def warn ( exc , nav , repl_pairs , local_opt , node ) : <EOL> """<STR_LIT>""" <EOL> if config . on_opt_error != '<STR_LIT:ignore>' : <EOL> _logger . error ( "<STR_LIT>" % str ( local_opt ) ) <EOL> _logger . error ( "<STR_LIT>" % str ( node ) ) <EOL> _logger . error ( "<STR_LIT>" ) <EOL> _logger . error ( traceback . format_exc ( ) ) <EOL> if config . on_opt_error == '<STR_LIT>' : <EOL> pdb . post_mortem ( sys . exc_info ( ) [ <NUM_LIT:2> ] ) <EOL> elif isinstance ( exc , AssertionError ) or config . on_opt_error == '<STR_LIT>' : <EOL> raise exc <EOL> @ staticmethod <EOL> def warn_inplace ( exc , nav , repl_pairs , local_opt , node ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( exc , InconsistencyError ) : <EOL> return <EOL> return NavigatorOptimizer . warn ( exc , nav , repl_pairs , local_opt , node ) <EOL> @ staticmethod <EOL> def warn_ignore ( exc , nav , repl_pairs , local_opt , node ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def __init__ ( self , local_opt , ignore_newtrees = '<STR_LIT>' , <EOL> failure_callback = None ) : <EOL> self . local_opt = local_opt <EOL> if ignore_newtrees == '<STR_LIT>' : <EOL> self . ignore_newtrees = not getattr ( local_opt , '<STR_LIT>' , True ) <EOL> else : <EOL> self . ignore_newtrees = ignore_newtrees <EOL> self . failure_callback = failure_callback <EOL> def attach_updater ( self , fgraph , importer , pruner , chin = None ) : <EOL> """<STR_LIT>""" <EOL> if self . ignore_newtrees : <EOL> importer = None <EOL> if importer is None and pruner is None : <EOL> return None <EOL> u = Updater ( importer , pruner , chin ) <EOL> fgraph . attach_feature ( u ) <EOL> return u <EOL> def detach_updater ( self , fgraph , u ) : <EOL> """<STR_LIT>""" <EOL> if u is not None : <EOL> fgraph . remove_feature ( u ) <EOL> def process_node ( self , fgraph , node , lopt = None ) : <EOL> """<STR_LIT>""" <EOL> lopt = lopt or self . local_opt <EOL> try : <EOL> replacements = lopt . transform ( node ) <EOL> except Exception as e : <EOL> if self . failure_callback is not None : <EOL> self . failure_callback ( e , self , <EOL> [ ( x , None ) for x in node . outputs ] , <EOL> lopt , node ) <EOL> return False <EOL> else : <EOL> raise <EOL> if replacements is False or replacements is None : <EOL> return False <EOL> old_vars = node . outputs <EOL> if isinstance ( replacements , dict ) : <EOL> old_vars = list ( replacements . keys ( ) ) <EOL> replacements = list ( replacements . values ( ) ) <EOL> elif not isinstance ( replacements , ( tuple , list ) ) : <EOL> raise TypeError ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> lopt , replacements ) ) <EOL> if len ( old_vars ) != len ( replacements ) : <EOL> raise ValueError ( '<STR_LIT>' <EOL> % lopt ) <EOL> for r , rnew in zip ( old_vars , replacements ) : <EOL> if rnew is None and len ( r . clients ) > <NUM_LIT:0> : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> repl_pairs = [ ( r , rnew ) for r , rnew in zip ( old_vars , replacements ) <EOL> if rnew is not r and rnew is not None ] <EOL> if len ( repl_pairs ) == <NUM_LIT:0> : <EOL> return False <EOL> try : <EOL> fgraph . replace_all_validate ( repl_pairs , reason = lopt ) <EOL> return True <EOL> except Exception as e : <EOL> if self . failure_callback is not None : <EOL> self . failure_callback ( e , self , repl_pairs , lopt , node ) <EOL> return False <EOL> else : <EOL> raise <EOL> def add_requirements ( self , fgraph ) : <EOL> super ( NavigatorOptimizer , self ) . add_requirements ( fgraph ) <EOL> if self . local_opt : <EOL> self . local_opt . add_requirements ( fgraph ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , id ( self ) ) , file = stream ) <EOL> if depth != <NUM_LIT:0> : <EOL> self . local_opt . print_summary ( stream , level = ( level + <NUM_LIT:2> ) , <EOL> depth = ( depth - <NUM_LIT:1> ) ) <EOL> class TopoOptimizer ( NavigatorOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , local_opt , order = '<STR_LIT>' , ignore_newtrees = False , <EOL> failure_callback = None ) : <EOL> if order not in [ '<STR_LIT>' , '<STR_LIT>' ] : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> self . order = order <EOL> NavigatorOptimizer . __init__ ( self , local_opt , ignore_newtrees , <EOL> failure_callback ) <EOL> def apply ( self , fgraph , start_from = None ) : <EOL> if start_from is None : <EOL> start_from = fgraph . outputs <EOL> callback_before = fgraph . execute_callbacks_time <EOL> nb_nodes_start = len ( fgraph . apply_nodes ) <EOL> t0 = time . time ( ) <EOL> q = deque ( graph . io_toposort ( fgraph . inputs , start_from ) ) <EOL> io_t = time . time ( ) - t0 <EOL> def importer ( node ) : <EOL> if node is not current_node : <EOL> q . append ( node ) <EOL> def pruner ( node ) : <EOL> if node is not current_node : <EOL> try : <EOL> q . remove ( node ) <EOL> except ValueError : <EOL> pass <EOL> u = self . attach_updater ( fgraph , importer , pruner ) <EOL> nb = <NUM_LIT:0> <EOL> try : <EOL> t0 = time . time ( ) <EOL> while q : <EOL> if self . order == '<STR_LIT>' : <EOL> node = q . pop ( ) <EOL> else : <EOL> node = q . popleft ( ) <EOL> current_node = node <EOL> nb += self . process_node ( fgraph , node ) <EOL> loop_t = time . time ( ) - t0 <EOL> except Exception : <EOL> self . detach_updater ( fgraph , u ) <EOL> raise <EOL> self . detach_updater ( fgraph , u ) <EOL> callback_time = fgraph . execute_callbacks_time - callback_before <EOL> nb_nodes_end = len ( fgraph . apply_nodes ) <EOL> return ( self , nb , nb_nodes_start , nb_nodes_end , <EOL> io_t , loop_t , callback_time ) <EOL> @ staticmethod <EOL> def print_profile ( stream , prof , level = <NUM_LIT:0> ) : <EOL> ( opt , nb , nb_nodes_start , nb_nodes_end , <EOL> io_t , loop_t , callback_time ) = prof <EOL> blanc = ( '<STR_LIT:U+0020>' * level ) <EOL> print ( blanc , "<STR_LIT>" , <EOL> getattr ( opt , "<STR_LIT:name>" , getattr ( opt , "<STR_LIT>" , "<STR_LIT>" ) ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" , ( <EOL> nb_nodes_start , nb_nodes_end , nb ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" , io_t , file = stream ) <EOL> print ( blanc , "<STR_LIT>" , loop_t , file = stream ) <EOL> print ( blanc , "<STR_LIT>" , callback_time , file = stream ) <EOL> def __str__ ( self ) : <EOL> return getattr ( self , '<STR_LIT>' , <EOL> '<STR_LIT>' ) <EOL> class OpKeyOptimizer ( NavigatorOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , local_opt , ignore_newtrees = False , <EOL> failure_callback = None ) : <EOL> if not hasattr ( local_opt , '<STR_LIT>' ) : <EOL> raise TypeError ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> NavigatorOptimizer . __init__ ( self , local_opt , ignore_newtrees , <EOL> failure_callback ) <EOL> def apply ( self , fgraph ) : <EOL> op = self . local_opt . op_key ( ) <EOL> if isinstance ( op , ( list , tuple ) ) : <EOL> q = reduce ( list . __iadd__ , map ( fgraph . get_nodes , op ) ) <EOL> else : <EOL> q = list ( fgraph . get_nodes ( op ) ) <EOL> def importer ( node ) : <EOL> if node is not current_node : <EOL> if node . op == op : <EOL> q . append ( node ) <EOL> def pruner ( node ) : <EOL> if node is not current_node and node . op == op : <EOL> try : <EOL> q . remove ( node ) <EOL> except ValueError : <EOL> pass <EOL> u = self . attach_updater ( fgraph , importer , pruner ) <EOL> try : <EOL> while q : <EOL> node = q . pop ( ) <EOL> current_node = node <EOL> self . process_node ( fgraph , node ) <EOL> except Exception : <EOL> self . detach_updater ( fgraph , u ) <EOL> raise <EOL> self . detach_updater ( fgraph , u ) <EOL> def add_requirements ( self , fgraph ) : <EOL> """<STR_LIT>""" <EOL> super ( OpKeyOptimizer , self ) . add_requirements ( fgraph ) <EOL> fgraph . attach_feature ( toolbox . NodeFinder ( ) ) <EOL> class ChangeTracker : <EOL> def __init__ ( self ) : <EOL> self . changed = False <EOL> self . nb_imported = <NUM_LIT:0> <EOL> def on_import ( self , fgraph , node , reason ) : <EOL> self . nb_imported += <NUM_LIT:1> <EOL> self . changed = True <EOL> def on_change_input ( self , fgraph , node , i , r , new_r , reason ) : <EOL> self . changed = True <EOL> def reset ( self ) : <EOL> self . changed = False <EOL> def on_attach ( self , fgraph ) : <EOL> fgraph . change_tracker = self <EOL> def merge_dict ( d1 , d2 ) : <EOL> """<STR_LIT>""" <EOL> d = d1 . copy ( ) <EOL> for k , v in iteritems ( d2 ) : <EOL> if k in d : <EOL> d [ k ] += v <EOL> else : <EOL> d [ k ] = v <EOL> return d <EOL> class EquilibriumOptimizer ( NavigatorOptimizer ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , <EOL> optimizers , <EOL> failure_callback = None , <EOL> ignore_newtrees = True , <EOL> max_use_ratio = None , <EOL> final_optimizers = None , <EOL> cleanup_optimizers = None ) : <EOL> super ( EquilibriumOptimizer , self ) . __init__ ( <EOL> None , <EOL> ignore_newtrees = ignore_newtrees , <EOL> failure_callback = failure_callback ) <EOL> self . local_optimizers_map = OrderedDict ( ) <EOL> self . local_optimizers_all = [ ] <EOL> self . global_optimizers = [ ] <EOL> self . final_optimizers = [ ] <EOL> self . cleanup_optimizers = [ ] <EOL> for opt in optimizers : <EOL> if isinstance ( opt , LocalOptimizer ) : <EOL> if opt . tracks ( ) is None : <EOL> self . local_optimizers_all . append ( opt ) <EOL> else : <EOL> for c in opt . tracks ( ) : <EOL> self . local_optimizers_map . setdefault ( c , [ ] ) . append ( opt ) <EOL> else : <EOL> self . global_optimizers . append ( opt ) <EOL> if final_optimizers : <EOL> self . final_optimizers = final_optimizers <EOL> if cleanup_optimizers : <EOL> self . cleanup_optimizers = cleanup_optimizers <EOL> self . max_use_ratio = max_use_ratio <EOL> assert self . max_use_ratio is not None , ( <EOL> '<STR_LIT>' ) <EOL> def get_local_optimizers ( self ) : <EOL> for opt in self . local_optimizers_all : <EOL> yield opt <EOL> s = set ( ) <EOL> for lopt in itervalues ( self . local_optimizers_map ) : <EOL> for opt in lopt : <EOL> if opt not in s : <EOL> yield opt <EOL> s . add ( opt ) <EOL> def add_requirements ( self , fgraph ) : <EOL> super ( EquilibriumOptimizer , self ) . add_requirements ( fgraph ) <EOL> for opt in self . get_local_optimizers ( ) : <EOL> opt . add_requirements ( fgraph ) <EOL> for opt in self . global_optimizers : <EOL> opt . add_requirements ( fgraph ) <EOL> for opt in self . final_optimizers : <EOL> opt . add_requirements ( fgraph ) <EOL> for opt in self . cleanup_optimizers : <EOL> opt . add_requirements ( fgraph ) <EOL> def apply ( self , fgraph , start_from = None ) : <EOL> change_tracker = ChangeTracker ( ) <EOL> fgraph . attach_feature ( change_tracker ) <EOL> if start_from is None : <EOL> start_from = fgraph . outputs <EOL> else : <EOL> for node in start_from : <EOL> assert node in fgraph . outputs <EOL> changed = True <EOL> max_use_abort = False <EOL> opt_name = None <EOL> global_process_count = { } <EOL> start_nb_nodes = len ( fgraph . apply_nodes ) <EOL> max_nb_nodes = len ( fgraph . apply_nodes ) <EOL> max_use = max_nb_nodes * self . max_use_ratio <EOL> loop_timing = [ ] <EOL> loop_process_count = [ ] <EOL> global_opt_timing = [ ] <EOL> time_opts = { } <EOL> io_toposort_timing = [ ] <EOL> nb_nodes = [ ] <EOL> node_created = { } <EOL> global_sub_profs = [ ] <EOL> final_sub_profs = [ ] <EOL> cleanup_sub_profs = [ ] <EOL> for opt in ( self . global_optimizers + <EOL> list ( self . get_local_optimizers ( ) ) + <EOL> self . final_optimizers + <EOL> self . cleanup_optimizers ) : <EOL> global_process_count . setdefault ( opt , <NUM_LIT:0> ) <EOL> time_opts . setdefault ( opt , <NUM_LIT:0> ) <EOL> node_created . setdefault ( opt , <NUM_LIT:0> ) <EOL> def apply_cleanup ( profs_dict ) : <EOL> changed = False <EOL> for copt in self . cleanup_optimizers : <EOL> change_tracker . reset ( ) <EOL> nb = change_tracker . nb_imported <EOL> t_opt = time . time ( ) <EOL> sub_prof = copt . apply ( fgraph ) <EOL> time_opts [ copt ] += time . time ( ) - t_opt <EOL> profs_dict [ copt ] . append ( sub_prof ) <EOL> if change_tracker . changed : <EOL> process_count . setdefault ( copt , <NUM_LIT:0> ) <EOL> process_count [ copt ] += <NUM_LIT:1> <EOL> global_process_count [ copt ] += <NUM_LIT:1> <EOL> changed = True <EOL> node_created [ copt ] += change_tracker . nb_imported - nb <EOL> return changed <EOL> while changed and not max_use_abort : <EOL> process_count = { } <EOL> t0 = time . time ( ) <EOL> changed = False <EOL> iter_cleanup_sub_profs = { } <EOL> for copt in self . cleanup_optimizers : <EOL> iter_cleanup_sub_profs [ copt ] = [ ] <EOL> sub_profs = [ ] <EOL> for gopt in self . global_optimizers : <EOL> change_tracker . reset ( ) <EOL> nb = change_tracker . nb_imported <EOL> t_opt = time . time ( ) <EOL> sub_prof = gopt . apply ( fgraph ) <EOL> time_opts [ gopt ] += time . time ( ) - t_opt <EOL> sub_profs . append ( sub_prof ) <EOL> if change_tracker . changed : <EOL> process_count . setdefault ( gopt , <NUM_LIT:0> ) <EOL> process_count [ gopt ] += <NUM_LIT:1> <EOL> global_process_count [ gopt ] += <NUM_LIT:1> <EOL> changed = True <EOL> node_created [ gopt ] += change_tracker . nb_imported - nb <EOL> if global_process_count [ gopt ] > max_use : <EOL> max_use_abort = True <EOL> opt_name = ( getattr ( gopt , "<STR_LIT:name>" , None ) or <EOL> getattr ( gopt , "<STR_LIT>" , "<STR_LIT>" ) ) <EOL> global_sub_profs . append ( sub_profs ) <EOL> global_opt_timing . append ( float ( time . time ( ) - t0 ) ) <EOL> changed |= apply_cleanup ( iter_cleanup_sub_profs ) <EOL> topo_t0 = time . time ( ) <EOL> q = deque ( graph . io_toposort ( fgraph . inputs , start_from ) ) <EOL> io_toposort_timing . append ( time . time ( ) - topo_t0 ) <EOL> nb_nodes . append ( len ( q ) ) <EOL> max_nb_nodes = max ( max_nb_nodes , len ( q ) ) <EOL> max_use = max_nb_nodes * self . max_use_ratio <EOL> def importer ( node ) : <EOL> if node is not current_node : <EOL> q . append ( node ) <EOL> def pruner ( node ) : <EOL> if node is not current_node : <EOL> try : <EOL> q . remove ( node ) <EOL> except ValueError : <EOL> pass <EOL> u = self . attach_updater ( fgraph , importer , pruner ) <EOL> try : <EOL> while q : <EOL> node = q . pop ( ) <EOL> current_node = node <EOL> for lopt in ( self . local_optimizers_all + <EOL> self . local_optimizers_map . get ( type ( node . op ) , [ ] ) + <EOL> self . local_optimizers_map . get ( node . op , [ ] ) ) : <EOL> nb = change_tracker . nb_imported <EOL> t_opt = time . time ( ) <EOL> lopt_change = self . process_node ( fgraph , node , lopt ) <EOL> time_opts [ lopt ] += time . time ( ) - t_opt <EOL> if not lopt_change : <EOL> continue <EOL> process_count . setdefault ( lopt , <NUM_LIT:0> ) <EOL> process_count [ lopt ] += <NUM_LIT:1> <EOL> global_process_count [ lopt ] += <NUM_LIT:1> <EOL> changed = True <EOL> node_created [ lopt ] += change_tracker . nb_imported - nb <EOL> changed |= apply_cleanup ( iter_cleanup_sub_profs ) <EOL> if global_process_count [ lopt ] > max_use : <EOL> max_use_abort = True <EOL> opt_name = ( getattr ( lopt , "<STR_LIT:name>" , None ) or <EOL> getattr ( lopt , "<STR_LIT>" , "<STR_LIT>" ) ) <EOL> if node not in fgraph . apply_nodes : <EOL> break <EOL> finally : <EOL> self . detach_updater ( fgraph , u ) <EOL> sub_profs = [ ] <EOL> t_before_final_opt = time . time ( ) <EOL> for gopt in self . final_optimizers : <EOL> change_tracker . reset ( ) <EOL> nb = change_tracker . nb_imported <EOL> t_opt = time . time ( ) <EOL> sub_prof = gopt . apply ( fgraph ) <EOL> time_opts [ gopt ] += time . time ( ) - t_opt <EOL> sub_profs . append ( sub_prof ) <EOL> if change_tracker . changed : <EOL> process_count . setdefault ( gopt , <NUM_LIT:0> ) <EOL> process_count [ gopt ] += <NUM_LIT:1> <EOL> global_process_count [ gopt ] += <NUM_LIT:1> <EOL> changed = True <EOL> node_created [ gopt ] += change_tracker . nb_imported - nb <EOL> if global_process_count [ gopt ] > max_use : <EOL> max_use_abort = True <EOL> opt_name = ( getattr ( gopt , "<STR_LIT:name>" , None ) or <EOL> getattr ( gopt , "<STR_LIT>" , "<STR_LIT>" ) ) <EOL> final_sub_profs . append ( sub_profs ) <EOL> global_opt_timing [ - <NUM_LIT:1> ] += time . time ( ) - t_before_final_opt <EOL> changed |= apply_cleanup ( iter_cleanup_sub_profs ) <EOL> c_sub_profs = [ ] <EOL> for copt , sub_profs in iteritems ( iter_cleanup_sub_profs ) : <EOL> sub_prof = sub_profs [ <NUM_LIT:0> ] <EOL> for s_p in sub_profs [ <NUM_LIT:1> : ] : <EOL> sub_prof = copt . merge_profile ( sub_prof , s_p ) <EOL> c_sub_profs . append ( sub_prof ) <EOL> cleanup_sub_profs . append ( c_sub_profs ) <EOL> loop_process_count . append ( process_count ) <EOL> loop_timing . append ( float ( time . time ( ) - t0 ) ) <EOL> end_nb_nodes = len ( fgraph . apply_nodes ) <EOL> if max_use_abort : <EOL> _logger . error ( "<STR_LIT>" % opt_name + <EOL> "<STR_LIT>" + <EOL> "<STR_LIT>" % <EOL> config . optdb . max_use_ratio ) <EOL> fgraph . remove_feature ( change_tracker ) <EOL> return ( self , loop_timing , loop_process_count , <EOL> ( start_nb_nodes , end_nb_nodes , max_nb_nodes ) , <EOL> global_opt_timing , nb_nodes , time_opts , io_toposort_timing , <EOL> node_created , global_sub_profs , final_sub_profs , cleanup_sub_profs ) <EOL> def print_summary ( self , stream = sys . stdout , level = <NUM_LIT:0> , depth = - <NUM_LIT:1> ) : <EOL> name = getattr ( self , '<STR_LIT:name>' , None ) <EOL> print ( "<STR_LIT>" % ( <EOL> ( '<STR_LIT:U+0020>' * level ) , self . __class__ . __name__ , name , id ( self ) ) , file = stream ) <EOL> if depth != <NUM_LIT:0> : <EOL> for lopt in self . get_local_optimizers ( ) : <EOL> lopt . print_summary ( stream , level = ( level + <NUM_LIT:2> ) , <EOL> depth = ( depth - <NUM_LIT:1> ) ) <EOL> @ staticmethod <EOL> def print_profile ( stream , prof , level = <NUM_LIT:0> ) : <EOL> ( opt , loop_timing , loop_process_count , <EOL> ( start_nb_nodes , end_nb_nodes , max_nb_nodes ) , <EOL> global_opt_timing , nb_nodes , time_opts , io_toposort_timing , <EOL> node_created , global_sub_profs , final_sub_profs , <EOL> cleanup_sub_profs ) = prof <EOL> blanc = ( '<STR_LIT:U+0020>' * level ) <EOL> print ( blanc , "<STR_LIT>" , end = '<STR_LIT:U+0020>' , file = stream ) <EOL> print ( blanc , getattr ( opt , "<STR_LIT:name>" , <EOL> getattr ( opt , "<STR_LIT>" , "<STR_LIT>" ) ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( <EOL> sum ( loop_timing ) , len ( loop_timing ) ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % ( <EOL> start_nb_nodes , end_nb_nodes , max_nb_nodes ) , file = stream ) <EOL> print ( blanc , "<STR_LIT>" % sum ( <EOL> io_toposort_timing ) , file = stream ) <EOL> s = sum ( [ time_opts [ o ] for o in opt . get_local_optimizers ( ) ] ) <EOL> print ( blanc , "<STR_LIT>" % s , file = stream ) <EOL> s = sum ( [ time_opts [ o ] for o in opt . global_optimizers ] ) <EOL> print ( blanc , "<STR_LIT>" % s , file = stream ) <EOL> s = sum ( [ time_opts [ o ] for o in opt . final_optimizers ] ) <EOL> print ( blanc , "<STR_LIT>" % s , file = stream ) <EOL> s = sum ( [ time_opts [ o ] for o in opt . cleanup_optimizers ] ) <EOL> print ( blanc , "<STR_LIT>" % s , file = stream ) <EOL> for i in range ( len ( loop_timing ) ) : <EOL> lopt = "<STR_LIT>" <EOL> if loop_process_count [ i ] : <EOL> d = list ( reversed ( sorted ( iteritems ( loop_process_count [ i ] ) , <EOL> key = lambda a : a [ <NUM_LIT:1> ] ) ) ) <EOL> lopt = "<STR_LIT:U+0020>" . join ( [ str ( ( str ( k ) , v ) ) for k , v <EOL> in d [ : <NUM_LIT:5> ] ] ) <EOL> if len ( d ) > <NUM_LIT:5> : <EOL> lopt += "<STR_LIT>" <EOL> print ( blanc , ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( <EOL> i , loop_timing [ i ] , <EOL> sum ( loop_process_count [ i ] . values ( ) ) , <EOL> global_opt_timing [ i ] , <EOL> io_toposort_timing [ i ] , nb_nodes [ i ] , <EOL> lopt ) ) , file = stream ) <EOL> count_opt = [ ] <EOL> not_used = [ ] <EOL> not_used_time = <NUM_LIT:0> <EOL> process_count = { } <EOL> for o in ( opt . global_optimizers + <EOL> list ( opt . get_local_optimizers ( ) ) + <EOL> list ( opt . final_optimizers ) + <EOL> list ( opt . cleanup_optimizers ) ) : <EOL> process_count . setdefault ( o , <NUM_LIT:0> ) <EOL> for count in loop_process_count : <EOL> for o , v in iteritems ( count ) : <EOL> process_count [ o ] += v <EOL> for o , count in iteritems ( process_count ) : <EOL> if count > <NUM_LIT:0> : <EOL> count_opt . append ( ( time_opts [ o ] , count , <EOL> node_created [ o ] , o ) ) <EOL> else : <EOL> not_used . append ( ( time_opts [ o ] , o ) ) <EOL> not_used_time += time_opts [ o ] <EOL> if count_opt : <EOL> print ( blanc , <EOL> '<STR_LIT>' , <EOL> file = stream ) <EOL> count_opt . sort ( ) <EOL> for ( t , count , n_created , o ) in count_opt [ : : - <NUM_LIT:1> ] : <EOL> print ( blanc , '<STR_LIT>' % ( <EOL> t , count , n_created , o ) , file = stream ) <EOL> print ( blanc , '<STR_LIT>' % ( <EOL> not_used_time , len ( not_used ) ) , file = stream ) <EOL> not_used . sort ( key = lambda nu : ( nu [ <NUM_LIT:0> ] , str ( nu [ <NUM_LIT:1> ] ) ) ) <EOL> for ( t , o ) in not_used [ : : - <NUM_LIT:1> ] : <EOL> if t > <NUM_LIT:0> : <EOL> print ( blanc + "<STR_LIT:U+0020>" , '<STR_LIT>' % ( t , o ) , file = stream ) <EOL> print ( file = stream ) <EOL> gf_opts = [ o for o in ( opt . global_optimizers + <EOL> list ( opt . final_optimizers ) + <EOL> list ( opt . cleanup_optimizers ) ) <EOL> if o . print_profile . __code__ is not <EOL> Optimizer . print_profile . __code__ ] <EOL> if not gf_opts : <EOL> return <EOL> print ( blanc , "<STR_LIT>" , file = stream ) <EOL> for i in range ( len ( loop_timing ) ) : <EOL> print ( blanc , "<STR_LIT>" % i , file = stream ) <EOL> for o , prof in zip ( opt . global_optimizers , global_sub_profs [ i ] ) : <EOL> try : <EOL> o . print_profile ( stream , prof , level + <NUM_LIT:2> ) <EOL> except NotImplementedError : <EOL> print ( blanc , "<STR_LIT>" , o ) <EOL> for o , prof in zip ( opt . final_optimizers , final_sub_profs [ i ] ) : <EOL> try : <EOL> o . print_profile ( stream , prof , level + <NUM_LIT:2> ) <EOL> except NotImplementedError : <EOL> print ( blanc , "<STR_LIT>" , o ) <EOL> for o , prof in zip ( opt . cleanup_optimizers , cleanup_sub_profs [ i ] ) : <EOL> try : <EOL> o . print_profile ( stream , prof , level + <NUM_LIT:2> ) <EOL> except NotImplementedError : <EOL> print ( blanc , "<STR_LIT>" , o ) <EOL> @ staticmethod <EOL> def merge_profile ( prof1 , prof2 ) : <EOL> local_optimizers = OrderedSet ( prof1 [ <NUM_LIT:0> ] . get_local_optimizers ( ) ) . union ( <EOL> prof2 [ <NUM_LIT:0> ] . get_local_optimizers ( ) ) <EOL> global_optimizers = OrderedSet ( prof1 [ <NUM_LIT:0> ] . global_optimizers ) . union ( <EOL> prof2 [ <NUM_LIT:0> ] . global_optimizers ) <EOL> if len ( prof1 [ <NUM_LIT:0> ] . final_optimizers ) > <NUM_LIT:0> or len ( prof2 [ <NUM_LIT:0> ] . final_optimizers ) > <NUM_LIT:0> : <EOL> final_optimizers = OrderedSet ( prof1 [ <NUM_LIT:0> ] . final_optimizers ) . union ( <EOL> prof2 [ <NUM_LIT:0> ] . final_optimizers ) <EOL> else : <EOL> final_optimizers = None <EOL> if len ( prof1 [ <NUM_LIT:0> ] . cleanup_optimizers ) > <NUM_LIT:0> or len ( prof2 [ <NUM_LIT:0> ] . cleanup_optimizers ) > <NUM_LIT:0> : <EOL> cleanup_optimizers = OrderedSet ( prof1 [ <NUM_LIT:0> ] . cleanup_optimizers ) . union ( <EOL> prof2 [ <NUM_LIT:0> ] . cleanup_optimizers ) <EOL> else : <EOL> cleanup_optimizers = None <EOL> new_opt = EquilibriumOptimizer ( <EOL> local_optimizers . union ( global_optimizers ) , <EOL> max_use_ratio = <NUM_LIT:1> , <EOL> final_optimizers = final_optimizers , <EOL> cleanup_optimizers = cleanup_optimizers ) <EOL> def merge_list ( l1 , l2 ) : <EOL> l = copy . copy ( l1 ) <EOL> for idx , nb in enumerate ( l2 ) : <EOL> if idx < len ( l ) : <EOL> l [ idx ] += nb <EOL> else : <EOL> l . append ( nb ) <EOL> return l <EOL> loop_timing = merge_list ( prof1 [ <NUM_LIT:1> ] , prof2 [ <NUM_LIT:1> ] ) <EOL> loop_process_count = list ( prof1 [ <NUM_LIT:2> ] ) <EOL> for i in range ( min ( len ( loop_process_count ) , len ( prof2 [ <NUM_LIT:2> ] ) ) ) : <EOL> process_count = loop_process_count [ i ] <EOL> for process , count in iteritems ( prof2 [ <NUM_LIT:2> ] [ i ] ) : <EOL> if process in process_count : <EOL> process_count [ process ] += count <EOL> else : <EOL> process_count [ process ] = count <EOL> loop_process_count . extend ( prof2 [ <NUM_LIT:2> ] [ len ( loop_process_count ) : ] ) <EOL> max_nb_nodes = max ( prof1 [ <NUM_LIT:3> ] , prof2 [ <NUM_LIT:3> ] ) <EOL> global_opt_timing = merge_list ( prof1 [ <NUM_LIT:4> ] , prof2 [ <NUM_LIT:4> ] ) <EOL> nb_nodes = merge_list ( prof1 [ <NUM_LIT:5> ] , prof2 [ <NUM_LIT:5> ] ) <EOL> time_opts = merge_dict ( prof1 [ <NUM_LIT:6> ] , prof2 [ <NUM_LIT:6> ] ) <EOL> io_toposort_timing = merge_list ( prof1 [ <NUM_LIT:7> ] , prof2 [ <NUM_LIT:7> ] ) <EOL> assert ( len ( loop_timing ) == len ( global_opt_timing ) == <EOL> len ( io_toposort_timing ) == len ( nb_nodes ) ) <EOL> assert len ( loop_timing ) == max ( len ( prof1 [ <NUM_LIT:1> ] ) , len ( prof2 [ <NUM_LIT:1> ] ) ) <EOL> node_created = merge_dict ( prof1 [ <NUM_LIT:8> ] , prof2 [ <NUM_LIT:8> ] ) <EOL> global_sub_profs = merge_list ( prof1 [ <NUM_LIT:9> ] , prof2 [ <NUM_LIT:9> ] ) <EOL> final_sub_profs = merge_list ( prof1 [ <NUM_LIT:10> ] , prof2 [ <NUM_LIT:10> ] ) <EOL> cleanup_sub_profs = merge_list ( prof1 [ <NUM_LIT:10> ] , prof2 [ <NUM_LIT:10> ] ) <EOL> return ( new_opt , <EOL> loop_timing , <EOL> loop_process_count , <EOL> max_nb_nodes , <EOL> global_opt_timing , <EOL> nb_nodes , <EOL> time_opts , <EOL> io_toposort_timing , <EOL> node_created , <EOL> global_sub_profs , <EOL> final_sub_profs , <EOL> cleanup_sub_profs ) <EOL> def _check_chain ( r , chain ) : <EOL> """<STR_LIT>""" <EOL> chain = list ( reversed ( chain ) ) <EOL> while chain : <EOL> elem = chain . pop ( ) <EOL> if elem is None : <EOL> if r . owner is not None : <EOL> return False <EOL> elif r . owner is None : <EOL> return False <EOL> elif isinstance ( elem , op . Op ) : <EOL> if not r . owner . op == elem : <EOL> return False <EOL> else : <EOL> try : <EOL> if ( issubclass ( elem , op . Op ) and <EOL> not isinstance ( r . owner . op , elem ) ) : <EOL> return False <EOL> except TypeError : <EOL> return False <EOL> if chain : <EOL> r = r . owner . inputs [ chain . pop ( ) ] <EOL> return ( r is not None ) <EOL> def check_chain ( r , * chain ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( r , graph . Apply ) : <EOL> r = r . outputs [ <NUM_LIT:0> ] <EOL> return _check_chain ( r , reduce ( list . __iadd__ , ( [ x , <NUM_LIT:0> ] for x in chain ) ) ) <EOL> def pre_greedy_local_optimizer ( list_optimizations , out ) : <EOL> """<STR_LIT>""" <EOL> def local_recursive_function ( list_opt , out , optimized_vars , depth ) : <EOL> if not getattr ( out , '<STR_LIT>' , None ) : <EOL> return [ out ] , optimized_vars <EOL> node = out . owner <EOL> if hasattr ( node , '<STR_LIT>' ) : <EOL> return node . outputs , optimized_vars <EOL> for idx , inp in enumerate ( node . inputs ) : <EOL> if inp in optimized_vars : <EOL> nw_in = optimized_vars [ inp ] <EOL> else : <EOL> if inp . owner : <EOL> outs , optimized_vars = local_recursive_function ( <EOL> list_opt , <EOL> inp , <EOL> optimized_vars , <EOL> depth + <NUM_LIT:1> ) <EOL> for k , v in zip ( inp . owner . outputs , outs ) : <EOL> optimized_vars [ k ] = v <EOL> nw_in = outs [ inp . owner . outputs . index ( inp ) ] <EOL> else : <EOL> nw_in = inp <EOL> optimized_vars [ inp ] = inp <EOL> node . inputs [ idx ] = nw_in <EOL> results = node . outputs <EOL> for opt in list_opt : <EOL> ret = opt . transform ( node ) <EOL> if ret is not False and ret is not None : <EOL> assert len ( ret ) == len ( node . outputs ) <EOL> for k , v in zip ( node . outputs , ret ) : <EOL> optimized_vars [ k ] = v <EOL> results = ret <EOL> if ret [ <NUM_LIT:0> ] . owner : <EOL> node = out . owner <EOL> else : <EOL> break <EOL> return results , optimized_vars <EOL> if out . owner : <EOL> out_index = out . owner . outputs . index ( out ) <EOL> else : <EOL> out_index = <NUM_LIT:0> <EOL> final_outs , optimized_nodes = local_recursive_function ( <EOL> list_optimizations , out , { } , <NUM_LIT:0> ) <EOL> return final_outs [ out_index ] </s>
