<s> import abc <EOL> import logging <EOL> from collections import deque , defaultdict <EOL> from fn import _ <EOL> from . technique import SearchTechniqueBase <EOL> log = logging . getLogger ( __name__ ) <EOL> class MetaSearchTechnique ( SearchTechniqueBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , techniques , log_freq = <NUM_LIT> , * pargs , ** kwargs ) : <EOL> super ( MetaSearchTechnique , self ) . __init__ ( * pargs , ** kwargs ) <EOL> self . techniques = techniques <EOL> self . request_count = <NUM_LIT:0> <EOL> self . log_freq = log_freq <EOL> self . logging_use_counters = defaultdict ( int ) <EOL> self . unique_names ( ) <EOL> def unique_names ( self ) : <EOL> names = set ( ) <EOL> for t in self . techniques : <EOL> while t . name in names : <EOL> t . name += '<STR_LIT>' <EOL> t . name = intern ( t . name ) <EOL> names . add ( t . name ) <EOL> def set_driver ( self , driver ) : <EOL> super ( MetaSearchTechnique , self ) . set_driver ( driver ) <EOL> for t in self . techniques : <EOL> t . set_driver ( driver ) <EOL> self . driver = driver <EOL> def desired_result ( self ) : <EOL> techniques = self . select_technique_order ( ) <EOL> for technique in techniques : <EOL> dr = technique . desired_result ( ) <EOL> if dr is not None : <EOL> if dr is False : <EOL> continue <EOL> self . driver . register_result_callback ( dr , <EOL> lambda result : self . on_technique_result ( technique , result ) ) <EOL> if self . log_freq : <EOL> self . logging_use_counters [ technique . name ] += <NUM_LIT:1> <EOL> self . debug_log ( ) <EOL> self . request_count += <NUM_LIT:1> <EOL> return dr <EOL> else : <EOL> self . on_technique_no_desired_result ( technique ) <EOL> return None <EOL> def on_technique_no_desired_result ( self , technique ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> def on_technique_result ( self , technique , result ) : <EOL> """<STR_LIT>""" <EOL> pass <EOL> @ abc . abstractmethod <EOL> def select_technique_order ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ ] <EOL> def debug_log ( self ) : <EOL> if self . log_freq and sum ( self . logging_use_counters . values ( ) ) > self . log_freq : <EOL> log . info ( "<STR_LIT>" , self . name , <EOL> str ( sorted ( self . logging_use_counters . items ( ) , key = _ [ <NUM_LIT:1> ] * - <NUM_LIT:1> ) ) ) <EOL> self . logging_use_counters = defaultdict ( int ) <EOL> class RoundRobinMetaSearchTechnique ( MetaSearchTechnique ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , techniques , ** kwargs ) : <EOL> techniques = deque ( techniques ) <EOL> super ( RoundRobinMetaSearchTechnique , self ) . __init__ ( techniques , ** kwargs ) <EOL> def select_technique_order ( self ) : <EOL> rv = list ( self . techniques ) <EOL> self . techniques . rotate ( <NUM_LIT:1> ) <EOL> return rv <EOL> class RecyclingMetaTechnique ( MetaSearchTechnique ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , <EOL> techniques_generators , <EOL> window = <NUM_LIT:100> , <EOL> factor = <NUM_LIT> , <EOL> ** kwargs ) : <EOL> if '<STR_LIT>' not in kwargs : <EOL> kwargs [ '<STR_LIT>' ] = None <EOL> techniques = deque ( ( g ( seed_cfg = None ) for g in techniques_generators ) ) <EOL> self . rename_i = <NUM_LIT:0> <EOL> for t in techniques : <EOL> self . rename_technique ( t ) <EOL> super ( RecyclingMetaTechnique , self ) . __init__ ( techniques , ** kwargs ) <EOL> self . best_results = defaultdict ( lambda : None ) <EOL> self . factor = factor <EOL> self . last_check = <NUM_LIT:0> <EOL> self . old_best_results = defaultdict ( lambda : None ) <EOL> self . technique_generators = deque ( techniques_generators ) <EOL> self . window = window <EOL> def rename_technique ( self , technique ) : <EOL> technique . name += "<STR_LIT>" % self . rename_i <EOL> self . rename_i += <NUM_LIT:1> <EOL> def on_technique_result ( self , technique , result ) : <EOL> """<STR_LIT>""" <EOL> if ( self . best_results [ technique ] is None or <EOL> self . driver . objective . lt ( result , self . best_results [ technique ] ) ) : <EOL> self . best_results [ technique ] = result <EOL> def technique_cmp ( self , a , b ) : <EOL> if not a . is_ready ( ) or not b . is_ready ( ) : <EOL> return cmp ( b . is_ready ( ) , a . is_ready ( ) ) <EOL> a = self . best_results [ a ] <EOL> b = self . best_results [ b ] <EOL> if a is None and b is None : <EOL> return <NUM_LIT:0> <EOL> if a is None : <EOL> return - <NUM_LIT:1> <EOL> if b is None : <EOL> return <NUM_LIT:1> <EOL> return self . driver . objective . compare ( a , b ) <EOL> def recycle_techniques ( self ) : <EOL> techniques = list ( self . techniques ) <EOL> techniques . sort ( cmp = self . technique_cmp ) <EOL> worst = techniques [ - <NUM_LIT:1> ] <EOL> if ( not worst . is_ready ( ) <EOL> or ( self . old_best_results [ worst ] is not None <EOL> and self . driver . objective . lt ( self . driver . best_result , <EOL> self . best_results [ worst ] ) ) ) : <EOL> techniques_new = deque ( ) <EOL> tn = None <EOL> for t , gen in zip ( self . techniques , self . technique_generators ) : <EOL> if t is worst : <EOL> tn = gen ( seed_cfg = self . driver . best_result . configuration . data ) <EOL> self . rename_technique ( tn ) <EOL> tn . set_driver ( self . driver ) <EOL> log . info ( "<STR_LIT>" , self . name , t . name , tn . name ) <EOL> techniques_new . append ( tn ) <EOL> else : <EOL> techniques_new . append ( t ) <EOL> self . techniques = techniques_new <EOL> else : <EOL> log . debug ( "<STR_LIT>" , self . name ) <EOL> self . old_best_results = self . best_results <EOL> self . best_results = defaultdict ( lambda : None ) <EOL> for t in self . techniques : <EOL> self . best_results [ t ] = self . old_best_results [ t ] <EOL> def select_technique_order ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . last_check + self . window < self . request_count : <EOL> self . last_check = self . request_count <EOL> self . recycle_techniques ( ) <EOL> rv = list ( self . techniques ) <EOL> self . techniques . rotate ( <NUM_LIT:1> ) <EOL> self . technique_generators . rotate ( <NUM_LIT:1> ) <EOL> return rv </s>
