def factory(node, length): ''' Cerca un LengthTestNode che e' possibile condividere oppure ne crea uno nuovo con le informazioni a disposizione e lo inserisce nel Network ''' #print "Cerco un LengthTestNode per: "+str(length) for child in node.get_children(): # controllo che nn ci sia gia un nodo che mi controlla la stessa cosa # se c'e' provvedo semplicemente ad usare quello if isinstance(child, LengthTestNode) \ and child.get_length() == length: # il nodo di confronto e' lo stesso # posso condividerlo return child # non abbiamo trovato nessun nodo che verifica le stesse # caratteristiche ctn = LengthTestNode(node, length) node.add_child(ctn) #print "Creo un ConstantTestNode "+repr(ctn)+" (linkandolo a: "+repr(node) #NetworkXGraphWrapper.i().add_node(ctn, node) EventManager.trigger(EventManager.E_NODE_ADDED, ctn) EventManager.trigger(EventManager.E_NODE_LINKED, ctn, node, 0) # il ctn non conserva wme, quindi non devo aggiornarlo return ctn
def retract_fact(self, wme): ''' Ritratta un fatto dal network @param wme: WME una wme gia presente nella rete ''' if not isinstance(wme, WME): # la cerco nel dizionario wme wme = self.__wmes_map[self._get_fact_dict_key(wme)] assert isinstance(wme, WME), \ "wme non e' un WME" # rimuovo dalla mappa wme -> id # (questo mi assicura che la wme ci sia) del self.__wmes_map[self._get_fact_dict_key(wme.get_fact())] #import sys #print >> sys.stderr, "Sto ritrattando: ", wme wme.remove() EventManager.trigger(EventManager.E_FACT_RETRACTD, wme) del wme
def execute(self, token): # devo linearizzare il token # ed eseguire le azioni EventManager.trigger(EventManager.E_RULE_FIRED, self, token) wmes = token.linearize() variables = self._resolve_variables(wmes) #from pprint import pprint #from icse.actions import Action as ActionProxy #pprint(variables) #pprint(self.__actions) for (action, args) in self.__actions: action.execute(args, variables, self.__reteNetwork, assertFunc=self.__assertFunc, retractFunc=self.__retractFunc, addProductionFunc=self.__addProduction, removeProductionFunc=self.__removeProduction )
def factory(parent, tests): assert isinstance(parent, ReteNode), \ "Un FilterNode deve avere per forza un parent ReteNode" assert isinstance(tests, list), \ "tests non e' una list" for child in parent.get_children(): # escludo che un join node possa essere condiviso da un # NegativeNode con gli stessi test e alpha-memory if isinstance(child, JoinNode) and not isinstance(child, NegativeNode): if child.get_tests() == tests: # stessi test, testa amem... condivido il nodo return child # non posso condividere un nuovo gia esistente # con queste informazioni, quindi ne creo uno nuovo # e lo aggiunto alla rete fn = FilterNode(parent, tests) parent.add_child(fn) EventManager.trigger(EventManager.E_NODE_ADDED, fn) EventManager.trigger(EventManager.E_NODE_LINKED, fn, parent, -1) return fn
def factory(parent): if parent == None: return None for child in parent.get_children(): from icse.rete.PNode import PNode if isinstance(child, BetaMemory) \ and not isinstance(child, PNode): # semplicemente un beta memory node # e un contenitore senza condizioni: # cio che discrimina il contenuto e' # il join-node padre. # quindi se ho gia un nodo betamemory # figlio dello stesso padre, semplicemente # lo condivido return child # non ho trovato nessun beta-memory # figlio del padre, quindi ne aggiungo # uno nuovo bm = BetaMemory(parent) parent.add_child(bm) parent.update(bm) EventManager.trigger(EventManager.E_NODE_ADDED, bm) EventManager.trigger(EventManager.E_NODE_LINKED, bm, parent, -1) #NetworkXGraphWrapper.i().add_node(bm, parent, -1) return bm
def factory(parent, conds, earlier_conds, builtins, alpha_root): #assert isinstance(parent, ReteNode), \ # "parent non e' un ReteNode" assert isinstance(earlier_conds, list), \ "earlier_conds non e' una list" # costruisce le sotto condizioni della NccCondition # come se fossero normali condizioni (e non interne ad una NCC) # in modo da poterle condividerle con altre condizioni positive # se presenti (o aggiunte in futuro) from icse import rete last_node = rete.network_factory(alpha_root, parent, conds, earlier_conds, builtins ) assert isinstance(last_node, ReteNode) # controllo che non sia il primo beta-node if parent != None: for child in parent.get_children(): # c'e' gia un figlio che e' un NCC # e il cui partner mangia dalla stessa sottorete # che rappresenta le condizioni di questa NCC if isinstance(child, NccNode) \ and child.get_partner().get_parent() == last_node: # la condivido! return child # nada, niente da condividere (almeno a livello di NCC) ncc = NccNode(parent, last_node, len(conds)) # inserisco i vari riferimenti dei figli nei padri parent.append_child(ncc) last_node.add_child(ncc.get_partner()) # completare l'aggiornamento # prima devo aggiornare l'NccNode e dopo il partner # per evitare che si crei confusione nel buffer nel partner parent.update(ncc) last_node.update(ncc.get_partner()) EventManager.trigger(EventManager.E_NODE_ADDED, ncc) EventManager.trigger(EventManager.E_NODE_ADDED, ncc.get_partner()) EventManager.trigger(EventManager.E_NODE_LINKED, ncc, parent, -1) EventManager.trigger(EventManager.E_NODE_LINKED, ncc.get_partner(), ncc) EventManager.trigger(EventManager.E_NODE_LINKED, ncc.get_partner(), last_node, -1) #NetworkXGraphWrapper.i().add_node(ncc, parent, -1) #NetworkXGraphWrapper.i().add_node(ncc.get_partner(), last_node, -1) #NetworkXGraphWrapper.i().add_edge(ncc.get_partner(), ncc) return ncc
def changeStrategy(self, strategy): EventManager.trigger(EventManager.E_STRATEGY_CHANGED, strategy) if self._strategy != strategy: self._strategy = strategy if not self.isEmpty(): # devo rioirdinare le attivazioni # in base alla nuova strategia for per_saliance_list in self._activations.values(): self._strategy.resort(per_saliance_list)
def factory(node, field, value, predicate): ''' Cerca un ConstantTestNode che e' possibile condividere oppure ne crea uno nuovo con le informazioni a disposizione e lo inserisce nel Network ''' assert isinstance(node, AlphaNode), \ "node non e' un AlphaNode" assert issubclass(predicate, Predicate), \ "predicate non e' un Predicato, "+str(predicate) #print "Cerco un CostantTestNode per: ", #print "campo: {0}, predicato: {1}, valore: {2}".format(field, predicate, value) for child in node.get_children(): # controllo che nn ci sia gia un nodo che mi controlla la stessa cosa # se c'e' provvedo semplicemente ad usare quello if isinstance(child, ConstantTestNode) \ and child.get_field() == field \ and child.get_predicate() == predicate \ and child.get_value() == value: # il nodo di confronto e' lo stesso # posso condividerlo return child #else: #print "Stavo valutando: ", #print "campo: {0}, predicato: {1}, valore: {2}".format(child.get_field(), child.get_predicate(), child.get_value()) # child.get_field() != field: #print "I campi erano diversi: ({0} vs {1})".format(child.get_field(), field) #elif child.get_predicate() != predicate: #print "I predicati erano diversi: ({0} vs {1})".format(child.get_predicate(), predicate) #elif child.get_value() != value: #print "I valori erano diversi: ({0} vs {1})".format(child.get_value(), value) # non abbiamo trovato nessun nodo che verifica le stesse # caratteristiche ctn = ConstantTestNode(node, field, value, predicate) node.add_child(ctn) #print "Creo un ConstantTestNode "+repr(ctn)+" (linkandolo a: "+repr(node) #NetworkXGraphWrapper.i().add_node(ctn, node) EventManager.trigger(EventManager.E_NODE_ADDED, ctn) EventManager.trigger(EventManager.E_NODE_LINKED, ctn, node, 0) # il ctn non conserva wme, quindi non devo aggiornarlo return ctn
def delete(self): ''' Esegue le operazioni comuni di pulizia dei nodi della BetaNetwork in modo che le classi che estendono possono semplicemente chiamare questa funzione per eseguire la pulizia base. Esegue: - rimozione del riferimento dalla lista di figli del padre - rimozione di tutti i nodi sopra questo che non abbiano utilita' ''' EventManager.trigger(EventManager.E_NODE_LINKED, self, self._parent) self._parent._remove_child(self) self._parent._delete_useless()
def remove(self, pnode, token): ''' Rimuove una attivazione dalla lista delle attivazioni e degli attivabili ''' # print "----- REGOLA NON PIU' ATTIVA:" # print "\tnome: ", pnode.get_name() # print "\tper token: " # import icse.debug as debug # debug.show_token_details(token, indent=12, explodeWme=True, maxDepth=4) salience = pnode.get_property('salience', 0) EventManager.trigger(EventManager.E_RULE_DEACTIVATED, pnode, token) try: same_salience_queue = self._activations[salience] # print # print "---" # print same_salience_queue # print pnode.get_name() # print token.linearize() same_salience_queue.remove((pnode, token)) # se non ci sono altre attivazioni # rimuovo if len(same_salience_queue) == 0: del self._activations[salience] except (KeyError, ValueError): #print e # non c'e' nessuna attivazione disponibile? # allora da dove viene questo token? # non c'e' questa attivazione nell'agenda # suppongo che stia provando a rimuovere # l'attivazione della stessa regola che ha # attivato l'azione di rimozione pass # una volta rimosso dagli attivabili # devo anche prendermi cura delle attivazioni eseguite # e ancora eseguibili, rimuovendolo da quella lista try: self._fired_activations[pnode.get_name()].remove((pnode, token)) except (KeyError, ValueError): pass
def delete(self): ''' Esegue la rimozione del nodo dalla rete ''' EventManager.trigger(EventManager.E_NODE_UNLINKED, self, self._parent, 0) #il parent di questo e' per forza un ConstantTestNode self._parent._remove_child(self) if self.has_alphamemory(): EventManager.trigger(EventManager.E_NODE_UNLINKED, self, self._alphamemory, 0) # rimuovo l'eventuale riferimento all'alpha memory self._alphamemory = None
def __init__(self): ''' Constructor ''' self.__wmes_map = {} self.__id_fact_map = {} self.__rules_map = {} self.__agenda = Agenda() self.__wme_nextid = 0 self.__alpha_root = AlphaRootNode(self) #self.__beta_root = BetaRootNode(self, self.__alpha_root) #self.__alpha_root.get_alphamemory().add_successor(self.__beta_root) EventManager.trigger(EventManager.E_NODE_ADDED, self.__alpha_root)
def remove_production(self, pnode_or_rulename): ''' Rimuove una produzione dal network @param pnode_or_rulename: PNode ''' if not isinstance(pnode_or_rulename, PNode): pnode_or_rulename = self.__rules_map[pnode_or_rulename] assert isinstance(pnode_or_rulename, PNode) del self.__rules_map[pnode_or_rulename.get_name()] pnode_or_rulename.delete() EventManager.trigger( EventManager.E_RULE_REMOVED, pnode_or_rulename)
def delete(self): ''' Esegue la cancellazione del nodo propagando la cancellazione all'alpha-memory se non e' condivisa con altri nodi ''' self._amem.remove_successor(self) EventManager.trigger(EventManager.E_NODE_UNLINKED, self, self._amem) if self._amem.is_useless(): self._amem.delete() ReteNode.delete(self)
def delete(self): ''' Esegue la rimozione del nodo dalla rete (a seguito della rimozione di una produzione) L'eliminazione tiene provoca la rimozione del partner (e dei padre inutile del partner) ''' self.get_partner().delete() EventManager.trigger(EventManager.E_NODE_UNLINKED, self.get_partner(), self) # chiamo la rimozione di BetaMemory (che se la vedra' # per quanto riguarda la rimozione dei token) # e poi chiamera' ReteNode.delete() per la pulizia # generica BetaMemory.delete(self)
def delete(self): ''' Cancella questo nodo e propaga la cancellazione al padre se il padre non e' condiviso con altri nodi ''' while len(self._items) > 0: item = self._items.pop(0) item.remove_alphamemory(self) #TODO propagazione al ConstantTestNode a cui si riferisce # questa amem # probabilmente mi servira' un riferimento verso l'alto parent = self.get_parent() assert isinstance(parent, ConstantTestNode), \ "parent non e' un ConstantTestNode" EventManager.trigger(EventManager.E_NODE_REMOVED, self) EventManager.trigger(EventManager.E_NODE_UNLINKED, self, parent) parent.delete()
def assert_fact(self, fact): ''' Asserisce un nuovo fatto nel network @param fact: Fact ''' try: wme = self.get_wme(fact) # se l'ho trovato (e quindi niente eccezione # significa che e' un duplicato # ergo non propago nulla EventManager.trigger(EventManager.E_FACT_ASSERTED, wme, False) return (wme.get_factid(), wme, False) except KeyError: # se non l'ho trovato, devo asserire realmente fact_dict_key = self._get_fact_dict_key(fact) wme = WME(fact) # e' un nuovo WME, quindi incremento l'id... self.__wme_nextid += 1 # inserisco nella map wme -> ID self.__wmes_map[fact_dict_key] = wme wme.set_factid(self.__wme_nextid) self.__id_fact_map[self.__wme_nextid] = fact_dict_key EventManager.trigger(EventManager.E_FACT_ASSERTED, wme, True) # ...e propago self.__alpha_root.activation(wme) return (self.__wme_nextid, wme, True)
def insert(self, pnode, token): ''' Inserisce la nuova attivazione di una regola su una sequenza di wmes fra gli attivabili e fra quelli in attesa di attivazione ''' from icse.rete.PNode import PNode assert isinstance(pnode, PNode) salience = pnode.get_property('salience', 0) EventManager.trigger(EventManager.E_RULE_ACTIVATED, pnode, token) try: same_salience_queue = self._activations[salience] except KeyError: # non c'e' ancora nessuna regola con quella salience # non c'e' bisogno di riordino self._activations[salience] = [(pnode, token)] return #devo inserire nella posizione giusta nella lista self._strategy.insert(pnode, token, same_salience_queue)
def factory(parent, amem, tests): assert isinstance(amem, AlphaMemory), \ "amem non e' una AlphaMemory" assert isinstance(tests, list), \ "tests non e' una list" if parent != None: for child in parent.get_children(): # escludo che un join node possa essere condiviso da un # NegativeNode con gli stessi test e alpha-memory if isinstance(child, JoinNode) and not isinstance(child, NegativeNode): #assert isinstance(child, JoinNode) if child._amem == amem: if child.get_tests() == tests: # stessi test, testa amem... condivido il nodo return child # non posso condividere un nuovo gia esistente # con queste informazioni, quindi ne creo uno nuovo # e lo aggiunto alla rete jn = JoinNode(parent, amem, tests) parent.add_child(jn) else: # perche non cercare anche fra le amem # per un dummy node che condivida la stessa amem? for succ in amem.get_successors(): # escludo che un join node possa essere condiviso da un # NegativeNode con gli stessi test e alpha-memory if isinstance(succ, DummyJoinNode): #assert isinstance(child, JoinNode) if succ.get_tests() == tests: # stessi test, testa amem... condivido il nodo return succ jn = DummyJoinNode(amem, tests) # questo lo fa indipendentemente da questto che # trova (se join normale o dummy) amem.add_successor(jn) EventManager.trigger(EventManager.E_NODE_ADDED, jn) EventManager.trigger(EventManager.E_NODE_LINKED, jn, amem, 1) if parent != None: EventManager.trigger(EventManager.E_NODE_LINKED, jn, parent, -1) #NetworkXGraphWrapper.i().add_node(jn, amem, 1) #if parent != None: #NetworkXGraphWrapper.i().add_edge(parent, jn, -1) return jn
def add_production(self, production): ''' Aggiunge una nuova produzione al network (solo se un'altra con lo stesso nome non sia gia stata definita, nel qual caso viene restituito un riferimento al vecchio PNode) @param production: Production ''' if self.__rules_map.has_key(production.get_name()): import sys print >> sys.stderr, "Redefinizione di una regola gia definita: ", production.get_name() return self.__rules_map[production.get_name()] symbols = {} last_node = rete.network_factory(self.__alpha_root, None, production.get_lhs(), builtins=symbols) #from pprint import pprint #pprint(symbols, indent=4) pnode = PNode(last_node, production.get_name(), production.get_rhs(), production.get_properties(), symbols, self, onActive=self.__agenda.insert, onDeactive=self.__agenda.remove, assertFunc=self.assert_fact, retractFunc=self.retract_fact, addProduction=self.add_production, removeProduction=self.remove_production ) assert isinstance(last_node, ReteNode), \ "last_node non e' un ReteNode" last_node.add_child(pnode) last_node.update(pnode) #NetworkXGraphWrapper.i().add_node(pnode, last_node, -1) self.__rules_map[production.get_name()] = pnode EventManager.trigger( EventManager.E_NODE_ADDED, pnode) EventManager.trigger( EventManager.E_NODE_LINKED, pnode, last_node, -1) EventManager.trigger( EventManager.E_RULE_ADDED, production, pnode) return pnode
def factory(parent, amem, tests): assert isinstance(amem, AlphaMemory), \ "amem non e' una AlphaMemory" assert isinstance(tests, list), \ "tests non e' una list" # controllo che non sia il primo elemento della # beta-network if parent != None: for child in parent.get_children(): if isinstance(child, NegativeNode): if child._amem == amem: if child._tests == tests: # stessi test, testa amem... condivido il nodo return child # non posso condividere un nuovo gia esistente # con queste informazioni, quindi ne creo uno nuovo # e lo aggiunto alla rete njn = NegativeNode(parent, amem, tests) parent.add_child(njn) else: # cerco se la alphamemory ha gia degli elementi # uguale a quello che andrei a creare e # lo condivido se c'e' for succ in amem.get_successors(): if isinstance(succ, NegativeNode) \ and succ.get_tests() == tests: return child # creo un nuovo DummyNegativeNode njn = DummyNegativeNode(amem, tests) amem.add_successor(njn) # aggiorna: aggiorna da sinistra se ho un padre if parent != None: parent.update(njn) else: # se non ho padre, allora sono un dummy # quindi devo provvedere a leggere solo # dall'alpha memory e attivare # per tutti gli elementi for w in amem.get_items(): # in questo modo gli elementi dell'alpha # vegono trasferiti e preparati # (tramite negativejoinresult) # nella memory di questo nodo (che integra # una beta-memory) njn.rightActivation(w) EventManager.trigger(EventManager.E_NODE_ADDED, njn) EventManager.trigger(EventManager.E_NODE_LINKED, njn, amem, 1) if parent != None: EventManager.trigger(EventManager.E_NODE_LINKED, njn, parent, -1) #NetworkXGraphWrapper.i().add_node(njn, amem, 1) #if parent != None: #NetworkXGraphWrapper.i().add_edge(njn, parent, -1) return njn
def executeImpl(self, triggerName, *args): args = self._resolve_args(False, True, *args) EventManager.trigger(triggerName, args)
dir_type, dir_arg = item if dir_type == 'include': # inclusione di file al termine della lettura di questo import os module_path = os.path.realpath( os.path.dirname(current_file) + '/' + dir_arg ) if isfile( module_path ): parseQueue.append(module_path) #print "Modulo preparato alla lettura: ", os.path.dirname(filepath) + '/' + dir_arg else: print "File non valido: ", module_path elif dir_type == 'debug': #argomenti di debug nella forma: # chiave=valore,chiave2=valore2,ecc try: debug_infos = dict([tuple(x.strip().split('=')) for x in dir_arg.strip().split(',')]) EventManager.trigger( EventManager.E_DEBUG_OPTIONS_CHANGED, debug_infos, rete) except Exception, e: #ignora la direttiva se il formato non e' corretto print e print >> sys.stderr, "Direttiva debug ignorata: ", dir_arg parsedItems = [] if len(parseQueue) > 0: pmodule = parseQueue.pop(0) if not parsedModuleCache.has_key(pmodule): parsedModuleCache[pmodule] = True stats_modules += 1
def factory(c, node): ''' Factory di AlphaMemory: costruisce un nuovo nodo AlphaMemory solo se non e' possibile utilizzare un nodo gia presente condividendolo @param c: la condizione che rappresenta il nodo (espressa come lista di atomi [condizioni su singoli campi]) @param node: la radice della alpha-network @return: AlphaMemory ''' #TODO riferimento: # build-or-share-alpha-memory(c: condition) pagina 35 #print c field_index = None tmp_c = c.items() if isinstance(c, dict) else enumerate(c) for field_index, (atom_type, atom_cont) in tmp_c: if not issubclass(atom_type, (Variable, Function)): # filtra tutte le variabili node = ConstantTestNode.factory(node, field_index, atom_cont, atom_type) # a questo punto devo aggiungere # un nodo condizione sulla lunghezza # MA: mi assicuro che la wme non sia un template # e che c non sia nulla if isinstance(field_index, int): node = LengthTestNode.factory(node, field_index + 1) # al termine del ramo di valutazione costante, l'ultimo nodo ha gia una # alpha-memory: condividiamo quella if node.has_alphamemory(): return node.get_alphamemory() # altrimenti ne aggiungiamo una nuova am = AlphaMemory(node) # provvedo a collegarla ad un test-node node.set_alphamemory(am) # a questo punto devo forzare l'aggiornamento dell'intera rete # ora capisco perche il factory aveva come condizione l'intera rete di condizioni... EventManager.trigger(EventManager.E_NODE_ADDED, am) EventManager.trigger(EventManager.E_NODE_LINKED, am, node, 0) # ricostruisco semplicemente la sequenza di test node che porta a questa alpha-memory stack = [] tree_cursor = node while not isinstance(tree_cursor, AlphaRootNode): stack.insert(0, tree_cursor) tree_cursor = tree_cursor.get_parent() # tree_cursor e' un RootNode assert isinstance(tree_cursor, AlphaRootNode) network = tree_cursor.get_network() # a questo punto devo testarli tutti per tutte le wme :( wmes = network.get_wmes() for w in wmes: isValid = True for t in stack: assert isinstance(t, ConstantTestNode), \ "t no e' un ConstantTestNode" if not t.is_valid(w): isValid = False break if isValid: # la wme ha passato tutti i test # triggo questa alpha-memory come se fosse # stata appena aggiunta normalmente am.activation(w) #NetworkXGraphWrapper.i().add_node(am, node) return am