def __setitem__(self, key, time): if self.unrestricted_number_chunks and key not in self: for x in key: if utilities.splitting(x[1]).values and utilities.splitting( x[1]).values in self.unrestricted_number_chunks: self.unrestricted_number_chunks.update( [utilities.splitting(x[1]).values]) if self.restricted_number_chunks and key not in self: for x in key: if utilities.splitting( x[1]).values and (x[0], utilities.splitting( x[1]).values) in self.restricted_number_chunks: self.restricted_number_chunks.update([ (x[0], utilities.splitting(x[1]).values) ]) if isinstance(key, chunks.Chunk): if isinstance(time, np.ndarray): self._data[key] = time else: try: self._data[key] = np.array([round(float(time), 4)]) except TypeError: self._data[key] = np.array(time) else: raise utilities.ModelError( "Only chunks can be added as attributes to Declarative Memory; '%s' is not a chunk" % key)
def decmem(self, value): try: self.dm = value except ValueError: raise utilities.ModelError( 'The default harvest set in the retrieval buffer is not a possible declarative memory' )
def __init__(self, environment=None, **model_parameters): self.chunktype = chunks.chunktype start_goal = goals.Goal() self.goals = {"g": start_goal} self.__buffers = {"g": start_goal} start_retrieval = declarative.DecMemBuffer() self.retrievals = {"retrieval": start_retrieval} self.__buffers["retrieval"] = start_retrieval start_dm = declarative.DecMem() self.decmems = {"decmem": start_dm} self.__similarities = {} self.model_parameters = self.MODEL_PARAMETERS.copy() try: if not set(model_parameters.keys()).issubset( set(self.MODEL_PARAMETERS.keys())): raise (utilities.ModelError( "Incorrect model parameter(s) %s. The only possible model parameters are: '%s'" % (set(model_parameters.keys()).difference( set(self.MODEL_PARAMETERS.keys())), set(self.MODEL_PARAMETERS.keys())))) self.model_parameters.update(model_parameters) except TypeError: pass self.__env = environment
def makechunk(nameofchunk="", typename="", text_value="", criterion="", **dictionary): if not nameofchunk: nameofchunk = "unnamedchunk" if not typename: typename = "undefined" + str(Chunk._undefinedchunktypecounter) Chunk._undefinedchunktypecounter += 1 if not criterion: criterion = "criterion" if not text_value: text_value = "no_text" for key in dictionary: if isinstance(dictionary[key], Chunk): pass elif isinstance(dictionary[key], utilities.VarvalClass): pass else: try: temp_dict = utilities.stringsplitting(str(dictionary[key])) # print(temp_dict) except utilities.ModelError as e: raise utilities.ModelError( "The chunk value %s is not defined correctly; %s" % (dictionary[key], e)) loop_dict = temp_dict.copy() for x in loop_dict: if x == "negvariables" or x == "negvalues": val = tuple(temp_dict[x]) else: try: val = temp_dict[x].pop() except KeyError: val = None temp_dict[x] = val dictionary[key] = utilities.VarvalClass(**temp_dict) created_chunk = Chunk(typename, text_value, criterion, **dictionary) created_chunk._chunks[nameofchunk] = created_chunk return created_chunk
def retrieve(self, time, otherchunk, actrvariables, buffers, extra_tests, model_parameters): """ Retrieve a chunk from declarative memory that matches otherchunk. """ model_parameters = model_parameters.copy() model_parameters.update(self.model_parameters) if actrvariables == None: actrvariables = {} try: mod_attr_val = { x[0]: utilities.check_bound_vars(actrvariables, x[1], negative_impossible=False) for x in otherchunk.removeunused() } except utilities.ModelError as arg: raise utilities.ModelError( "Retrieving the chunk '%s' is impossible; %s" % (otherchunk, arg)) chunk_tobe_matched = chunks.Chunk(otherchunk.typename, **mod_attr_val) max_A = float("-inf") retrieved = None for chunk in self.dm: try: if extra_tests["recently_retrieved"] == False or extra_tests[ "recently_retrieved"] == 'False': if self.__finst and chunk in self.recent: continue else: if self.__finst and chunk not in self.recent: continue except KeyError: pass if model_parameters[ "subsymbolic"]: # if subsymbolic, check activation A_pm = 0 if model_parameters["partial_matching"]: A_pm = chunk_tobe_matched.match( chunk, partialmatching=True, mismatch_penalty=model_parameters["mismatch_penalty"]) else: if not chunk_tobe_matched <= chunk: continue try: A_bll = utilities.baselevel_learning( time, self.dm[chunk], model_parameters["baselevel_learning"], model_parameters["decay"], self.dm.activations.get(chunk), optimized_learning=model_parameters[ "optimized_learning"]) # bll except UnboundLocalError: continue A_sa = utilities.spreading_activation( chunk, buffers, self.dm, model_parameters["buffer_spreading_activation"], model_parameters["strength_of_association"], model_parameters["spreading_activation_restricted"], model_parameters["association_only_from_chunks"]) inst_noise = utilities.calculate_instantanoues_noise( model_parameters["instantaneous_noise"]) A = A_bll + A_sa + A_pm + inst_noise # chunk.activation is the manually specified activation, potentially used by the modeller if utilities.retrieval_success( A, model_parameters["retrieval_threshold"]) and max_A < A: max_A = A self.activation = max_A retrieved = chunk extra_time = utilities.retrieval_latency( A, model_parameters["latency_factor"], model_parameters["latency_exponent"]) if model_parameters["activation_trace"]: print("(Partially) matching chunk:", chunk) print("Base level learning:", A_bll) print("Spreading activation", A_sa) print("Partial matching", A_pm) print("Noise:", inst_noise) print("Total activation", A) print("Time to retrieve", extra_time) else: # otherwise, just standard time for rule firing, so no extra calculation needed if chunk_tobe_matched <= chunk and self.dm[chunk][ 0] != time: # the second condition ensures that the chunk that was created are not retrieved at the same time retrieved = chunk extra_time = model_parameters["rule_firing"] if not retrieved: if model_parameters["subsymbolic"]: extra_time = utilities.retrieval_latency( model_parameters["retrieval_threshold"], model_parameters["latency_factor"], model_parameters["latency_exponent"]) else: extra_time = model_parameters["rule_firing"] if self.__finst: self.recent.append(retrieved) if self.__finst < len(self.recent): self.recent.popleft() return retrieved, extra_time
def __init__(self, typename, text_value, criterion, **dictionary): self.typename = typename self.criterion = criterion self.text_value = text_value self.boundvars = {} #dict of bound variables self.dict = dictionary kwargs = {} for key in dictionary: #change values (and values in a tuple) into string, when possible (when the value is not another chunk) if isinstance(dictionary[key], Chunk): dictionary[key] = utilities.VarvalClass(variables=None, values=dictionary[key], negvariables=(), negvalues=()) elif isinstance(dictionary[key], utilities.VarvalClass): for x in dictionary[key]._fields: if x in {"values", "variables"} and not isinstance( getattr(dictionary[key], x), str) and getattr( dictionary[key], x) != self.__emptyvalue and not isinstance( getattr(dictionary[key], x), Chunk): raise TypeError( "Values and variables must be strings, chunks or empty (None)" ) elif x in { "negvariables", "negvalues" } and (not isinstance(getattr(dictionary[key], x), collections.Sequence) or isinstance(getattr(dictionary[key], x), collections.MutableSequence)): raise TypeError( "Negvalues and negvariables must be tuples") elif (isinstance(dictionary[key], collections.Iterable) and not isinstance(dictionary[key], str)) or not isinstance( dictionary[key], collections.Hashable): raise ValueError( "The value of a chunk slot must be hashable and not iterable; you are using an illegal type for the value of the chunk slot %s, namely %s" % (key, type(dictionary[key]))) else: #create namedtuple varval and split dictionary[key] into variables, values, negvariables, negvalues try: temp_dict = utilities.stringsplitting(str(dictionary[key])) except utilities.ModelError as e: raise utilities.ModelError( "The chunk %s is not defined correctly; %s" % (dictionary[key], e)) loop_dict = temp_dict.copy() for x in loop_dict: if x == "negvariables" or x == "negvalues": val = tuple(temp_dict[x]) else: try: val = temp_dict[x].pop() except KeyError: val = None temp_dict[x] = val dictionary[key] = utilities.VarvalClass(**temp_dict) #adding _ to minimize/avoid name clashes kwargs[key + "_"] = dictionary[key] try: for elem in self._chunktypes[typename]._fields: if elem not in kwargs: kwargs[ elem] = self.__emptyvalue #emptyvalues are explicitly added to attributes that were left out dictionary[ elem[: -1]] = self.__emptyvalue #emptyvalues are also added to attributes in the original dictionary (since this might be used for chunktype creation later) if set(self._chunktypes[typename]._fields) != set(kwargs.keys()): chunktype( typename, dictionary.keys() ) #If there are more args than in the original chunktype, chunktype has to be created again, with slots for new attributes warnings.warn("Chunk type %s is extended with new attributes" % typename) except KeyError: chunktype(typename, dictionary.keys() ) #If chunktype completely missing, it is created first warnings.warn( "Chunk type %s was not defined; added automatically" % typename) finally: self.actrchunk = self._chunktypes[typename](**kwargs) self.__empty = None #this will store what the chunk looks like without empty values (the values will be stored on the first call of the relevant function) self.__unused = None #this will store what the chunk looks like without unused values self.__hash = None, self.boundvars.copy( ) #this will store the hash along with variables (hash changes if some variables are resolved)