def __init__(self, range): ''' 值范围 :param range: str,格式如[0:1] (0:1) [0:1:0.1] (0:1:0.1) uniform[0:1] normal[0,1],其中[]与()为数值区间 ''' self.rangeStr = range self.distributionName = 'uniform' self.begin = 0 self.includeBegin = True self.end = 1 self.IncludeEnd = True self.step = 0.1 self.__list = [] self.__stepMode = 'step' #m = re.compile('(\S*)').match('uniform') #m = re.compile('(\[|\(){1}').match('[') #m = re.compile('((\+|-)?\d+(\.\d+)?){1}').match('-30.0') #m = re.compile('\:').match(':') #m = re.compile('(\:(\+|-)?\d+(\.\d+)?)?').match(':-30.0') #m = re.compile('(\]|\)){1}').match(']') if not strs.isVaild(range): return m = Range.pattern.match(range) self.distributionName = m.groups()[0] self.begin = float(m.groups()[2]) self.end = float(m.groups()[5]) self.step = (self.end - self.begin) / 10 if m.groups()[9] is None else float( m.groups()[9]) #?有错误
def __repr__(self): ''' 用于调试打印详细信息 :return: ''' return self.name + '' if not strs.isVaild( self.description) else '(' + self.description + ')'
def getFullDirectory(dir): ''' 得到全路径,并以/结尾 :param dir: :return: ''' if (os.path.exists(dir)): return dir if not strs.isVaild(dir): return dir if dir.startWith('/') or dir.contains(':'): return dir p = os.path.dirname(os.path.abspath(__file__) + dir) if not p.endswith('/'): p += '/'
def register(self, obj, name=''): ''' 注册 :param obj: 注册对象 :param name: 对象名称,如果无效,则尝试调用strs.getName(obj)取得 :return: None ''' if obj is None: return if name == '': name = strs.getName(obj) if not strs.isVaild(name): return self.__tables__[name] = obj
def getFullFileName(filename, dir=''): ''' 取得全文件名 :param filename: 如果文件名是全路径,则结果不变,否则以py所在路径+dir为文件所在路径 :param dir: :return: ''' # 如果文件存在,仍返回文件名 if (os.path.exists(filename)): return filename # 如果文件名包含全路径,直接返回文件名(windows操作系统中是包含:,unix家族是/开始) if not strs.isVaild(filename): return filename if filename.startWith('/') or filename.contains(':'): return filename p = os.path.dirname(os.path.abspath(__file__) + dir) if not p.endswith('/'): p += '/' return p + filename
def find(self, name, default=None, setifnotexist=True): ''' 查找对象 :param name: str 对象名称 :param default: any 缺省对象 :param setifnotexist: 如果找不到,是否将default记录(下次就可以找到) :return: 注册的对象 ''' if not strs.isVaild(name): return default #if name in self.__tables__.keys(): if name in self.__tables__: return self.__tables__[name] if not setifnotexist: return default self.__tables__[name] = default return default
def _initModel(self): ''' 初始化计算模型:找到注册的计算模型,根据模型中的状态信息初始化神经系统元素状态, 并将计算模型中登记的变量克隆一份在元素对象中(计算模型中本身的变量只是模版,并不在实际计算中使用,这样可以使得计算模型成为单体对象) :return: ''' # 根据模型配置取得模型对象 if self.modelConfiguration is None: raise RuntimeError('初始化计算模型失败(NueralElement.initModel):模型配置无效') if len(self.modelConfiguration)<=0:return if not strs.isVaild(self.modelConfiguration.modelid): raise RuntimeError('初始化计算模型失败(NueralElement.initModel):模型配置中modelId无效') model = models.nervousModels.find(self.modelConfiguration.modelid) if model is None:raise RuntimeError('初始化计算模型失败(NueralElement.initModel):找不到模型:'+self.modelConfiguration.modelid) # 如果模型规定了要有初始状态,则设置初始状态 self.states = {} if model.initStates is None else copy.deepcopy(model.initStates) # 拷贝模型中规定的所有变量,并初始号变量的值 self.variables = [var.clone() for var in model.variables] self._initVariableValue()
def __repr__(self): #stateStr = collections.dicttostr(self.states) varStr = collections.listtostr(list(map(lambda v: v.__repr__(), self.variables))) return 'Synapse' + str(self.id) + '[' + str(self.fromId) + '->' + str(self.toId) \ + (',' + varStr if strs.isVaild(varStr) else '') + ']'
def __str__(self): varStr = collections.listtostr(list(map(lambda v: v.__repr__(), self.variables))) varStr = '[' + varStr + "]" if strs.isVaild(varStr) else '' return 'Synapse'+str(self.id)+'('+str(self.fromId)+'->'+str(self.toId)+')' + varStr
def __str__(self): #stateStr = collections.dicttostr(self.states) varStr = collections.listtostr(list(map(lambda v:v.__repr__(),self.variables))) return 'Neuron'+str(self.id)+'[layer='+str(self.layer) \ + (',' + varStr if strs.isVaild(varStr) else '') + ']'
def _getFeatureStr(self): r = collections.dicttostr(self.features) return '(' + r + ')' if strs.isVaild(r) else ''
def execute(self,session): # 执行算法选择个体 sel_inds = self.select(session) # 将要函数的个体删除 individuals = session.pop.inds totalSize = len(individuals) removeInds = [ind for ind in individuals if ind not in sel_inds] removeIndids = [ind.id for ind in individuals if ind not in sel_inds] removeInd_count = len(removeInds) session.monitor.recordDebug(NSGA2.name, '删除的个体', collections.mapreduce(removeIndids, reducefunc=lambda i, j: str(i) + ',' + str(j))) for removeInd in removeInds: session.pop.removeInd(removeInd) individuals = session.pop.inds # 对剩余的个体按照分别按照不同的适应度函数排序 sortedinds = {} for eva,i in enumerate(session.popParam.features): sortedinds[eva.key] = sorted(individuals,key=lambda x: x[eva.key] + 0.000001) featurekeys = [key for key,eva in session.popParam.features.items()] # 选择待交叉的个体 corssmeateInds = [] keyIndex = 0 for i in range(removeInd_count): if len(individuals) == 1: corssmeateInds.append((individuals[0], individuals[0])) elif len(individuals) == 2: corssmeateInds.append((individuals[0], individuals[1])) else: indspar = self.roulette(individuals,2,featurekeys[keyIndex]) keyIndex = 0 if keyIndex>=len(featurekeys)-1 else keyIndex + 1 corssmeateInds.append(indspar[0],indspar[1]) sdebug = '' for cross in corssmeateInds: if strs.isVaild(sdebug): sdebug += ',' sdebug += str(cross[0]) + '-' + str(cross[1]) session.monitor.recordDebug(NSGA2.name, '交叉的个体', sdebug) # region 第四步:对所有个体按照适应度从高到低排序,随机选择其中一部分作为变异个体 metateinds = [] # 计算变异个体数量 mutateCount = int(session.runParam.mutate.propotion) if session.runParam.mutate.propotion >= 1 else int( totalSize * session.runParam.mutate.propotion) if mutateCount <= 0: return True, '', (corssmeateInds, metateinds) # 对所有个体按照适应度从高到低排序 session.pop.inds.sort(key=lambda x: x['fitness'] + 0.000001 if x in session.pop.eliest else 0, reverse=True) # 选择候选变异个体(精英个体将被排除) candidateInds = collections.findall(session.pop.inds, lambda ind: ind not in session.pop.eliest) # 为每个个体计算一个选择概率(适应度越低的被选择的概率就高) if len(candidateInds) <= 0: max, avg, min, stdev = 0., 0., 0., 0. print('变异个体数量无效,' + str(session.pop.eliest)) return True, '选择操作完成,其中淘汰个体数量=' + str(len(removeIndids)) + ',交叉个体数量=' + str( len(corssmeateInds)) + ',变异个体数量=0', ( corssmeateInds, []) else: max, avg, min, stdev = collections.rangefeature(list(map(lambda ind: ind['fitness'], candidateInds))) # fitnesssum = sum(list(map(lambda ind:ind['fitness'],candidateInds))) mutateSelProb = [1 - ((ind['fitness'] - min) / ((max - min) if max != min else 1)) for index, ind in enumerate(candidateInds)] mutateSelProb = np.array(mutateSelProb) p = mutateSelProb / mutateSelProb.sum() np.random.seed(0) # p = np.array(mutateSelProb) mutateinds = np.random.choice(candidateInds, size=mutateCount, p=p.ravel()) session.monitor.recordDebug(NSGA2.name, '变异的个体', reduce(lambda i, j: i + ',' + j, map(lambda ind: str(ind.id), mutateinds))) return True, '选择操作完成,其中淘汰个体数量=' + str(len(removeIndids)) + ',交叉个体数量=' + str( len(corssmeateInds)) + ',变异个体数量=' + str(len(mutateinds)), ( corssmeateInds, list(map(lambda ind: ind.id, mutateinds)))
def execute(self, session): #region 第一步:规划每个物种中应有的个体数量 # 取得物种集合,并按平均适应度排序 species = session.pop.getSpecies() if collections.isEmpty(species): raise RuntimeError('NEAT选择操作失败:物种集合为空') species.sort(key=lambda s: s['fitness']['average'], reverse=True) # 根据物种的平均适应度在所有物种中占的比重,计算每个物种的目标个体数量 specie_total_fitness = sum( list(map(lambda sp: sp['fitness']['average'], species))) totalSize = 0 for i in range(len(species)): specie = species[i] # 根据物种适应度计算目标个体数量 speicesFitness = specie['fitness']['average'] specie.targetSize = int((speicesFitness / specie_total_fitness) * len(session.pop.inds)) totalSize += specie.targetSize # 如果所有物种的目标个体数量之和仍小于种群个体数量,将不足的部分加到适应度最高的物种上(按照上面计算,不会出现大于的情况) if totalSize < len(session.pop.inds): species[0].targetSize += len(session.pop.inds) - totalSize totalSize = len(session.pop.inds) session.monitor.recordDebug( 'neat_selection', '物种的目标个体数量', reduce(lambda x, y: x + "," + y, map(lambda s: str(s.id) + "=" + str(s.targetSize), species))) #endregion #region 第二步:遍历每个物种,如果物种中实际个体数量大于前面计算的每个物种的目标个体数量,则将适应度差的个体淘汰 removeIndids = [] for i in range(len(species)): specie = species[i] # 将物种中个体按照适应度由高到低排序,其中精英个体尽管排前面 specie.indids.sort( key=lambda indid: session.pop[indid]['fitness'] + 0.000001 if session.pop[indid] in session.pop.eliest else 0, reverse=True) # 实际个体数量不多于目标个体数量,不需要淘汰 if len(specie.indids) <= specie.targetSize: continue # 删除适应度最小的个体,直到实际个体数量与目标个体数量相等(这样的删除方法,有可能会导致精英个体也被删除) while len(specie.indids) > specie.targetSize: removeIndid = specie.indids[-1] removeInd = session.pop[removeIndid] removeIndids.append(removeIndid) del specie.indids[-1] # 从物种记录中删除 session.pop.inds.remove(removeInd) # 从种群记录中删除 session.monitor.recordDebug( 'neat_selection', '删除的个体', collections.mapreduce( removeIndids, reducefunc=lambda i, j: str(i) + ',' + str(j))) # 遍历所有物种,如果有物种个体数量为0,则将该物种删除 species = [s for s in species if len(s.indids) > 0] #endregion #region 第三步:对每个物种,随机选择需要交叉操作的个体 corssmeateInds = [] for specie in species: if len(specie.indids) >= specie.targetSize: continue for i in range(specie.targetSize - len(specie.indids)): if len(specie.indids) == 1: corssmeateInds.append((specie.indids[0], specie.indids[0])) elif len(specie.indids) == 2: corssmeateInds.append((specie.indids[0], specie.indids[1])) else: indexpair = random.sample(range(len(specie.indids)), 2) corssmeateInds.append((specie.indids[indexpair[0]], specie.indids[indexpair[1]])) # 有错误:session.monitor.recordDebug('neat_selection', '交叉的个体', reduce(lambda i, j: str(list(i)[0])+"-"+str(list(i)[1]) + ',' + str(list(j)[0])+"-"+str(list(j)[1]), corssmeateInds)) # reduce(lambda i,j:str(i[0])+'-'+str(i[1])+','+str(j[0])+'-'+str(j[1]),[(0,1),(2,3)]) ---> 0-1,2-3 # reduce(lambda i,j:str(i[0])+'-'+str(i[1])+','+str(j[0])+'-'+str(j[1]),[(0,1),(2,3),(4,5)]) ---> 0--,4-5 sdebug = '' for cross in corssmeateInds: if strs.isVaild(sdebug): sdebug += ',' sdebug += str(cross[0]) + '-' + str(cross[1]) session.monitor.recordDebug('neat_selection', '交叉的个体', sdebug) #region 第四步:对所有个体按照适应度从高到低排序,随机选择其中一部分作为变异个体 metateinds = [] # 计算变异个体数量 mutateCount = int(session.runParam.mutate.propotion ) if session.runParam.mutate.propotion >= 1 else int( totalSize * session.runParam.mutate.propotion) if mutateCount <= 0: return True, '', (corssmeateInds, metateinds) # 对所有个体按照适应度从高到低排序 session.pop.inds.sort(key=lambda x: x['fitness'] + 0.000001 if x in session.pop.eliest else 0, reverse=True) # 选择候选变异个体(精英个体将被排除) candidateInds = collections.findall( session.pop.inds, lambda ind: ind not in session.pop.eliest) # 为每个个体计算一个选择概率(适应度越低的被选择的概率就高) if len(candidateInds) <= 0: max, avg, min, stdev = 0., 0., 0., 0. print('变异个体数量无效,' + str(session.pop.eliest)) return True, '选择操作完成,其中淘汰个体数量=' + str( len(removeIndids)) + ',交叉个体数量=' + str( len(corssmeateInds)) + ',变异个体数量=0', (corssmeateInds, []) else: max, avg, min, stdev = collections.rangefeature( list(map(lambda ind: ind['fitness'], candidateInds))) #fitnesssum = sum(list(map(lambda ind:ind['fitness'],candidateInds))) mutateSelProb = [ 1 - ((ind['fitness'] - min) / ((max - min) if max != min else 1)) for index, ind in enumerate(candidateInds) ] mutateSelProb = np.array(mutateSelProb) p = mutateSelProb / mutateSelProb.sum() np.random.seed(0) #p = np.array(mutateSelProb) mutateinds = np.random.choice(candidateInds, size=mutateCount, p=p.ravel()) session.monitor.recordDebug( 'neat_selection', '变异的个体', reduce(lambda i, j: i + ',' + j, map(lambda ind: str(ind.id), mutateinds))) return True, '选择操作完成,其中淘汰个体数量=' + str( len(removeIndids)) + ',交叉个体数量=' + str( len(corssmeateInds)) + ',变异个体数量=' + str(len(mutateinds)), ( corssmeateInds, list(map(lambda ind: ind.id, mutateinds)))