string - How do I define a multiple characters as a single group in python? -


from fuzzywuzzy import fuzz import random import string  chars = ["t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "r1", "r2", "n1",          "n2", "g1", "g2", "g3", "h1", "h2", "h3", "k1", "k2", "k3", "k4", "d1",          "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9"]  class agent:      def __init__(self, length):         self.string = ' '.join(random.choice(chars) _ in xrange(length))         self.fitness = -1      def __str__(self):         return 'string: ' + str(self.string) + ' fitness: ' + str(self.fitness)  in_str = none in_str_len = none population = 20 generations = 10000  def ga():     agents = init_agents(population, in_str_len)      generation in xrange(generations):         print 'generation: ' + str(generation)          agents = fitness(agents)         agents = selection(agents)         agents = crossover(agents)         agents = mutation(agents)          if any(agent.fitness >= 100 agent in agents):             print 'threshold met!'             exit(0)  def init_agents(population, length):     return [agent(length) _ in xrange(population)]  def fitness(agents):     agent in agents:         agent.fitness = fuzz.ratio(agent.string, in_str)     return agents  def selection(agents):     agents = sorted(agents, key=lambda agent: agent.fitness, reverse=true)     print '\n'.join(map(str, agents))     agents = agents[:int(0.2 * len(agents))]     return agents  def crossover(agents):     offspring = []      _ in xrange((population - len(agents)) / 2):         parent1 = random.choice(agents)         parent2 = random.choice(agents)         child1 = agent(in_str_len)         child2 = agent(in_str_len)         split = random.randint(0, in_str_len)         child1.string = parent1.string[0:split] + parent2.string[split:in_str_len]         child2.string = parent2.string[0:split] + parent1.string[split:in_str_len]          offspring.append(child1)         offspring.append(child2)      agents.extend(offspring)     return agents   def mutation(agents):     agent in agents:         idx, param in enumerate(agent.string):             if random.uniform(0.0, 1.0) <= 0.1:                 agent.string = agent.string[0:idx] + random.choice(chars) + agent.string[idx+1:in_str_len]     return agents   if __name__ == '__main__':     in_str = 't1t3n1n2h1h2'     in_str_len = len(in_str)     ga() 

in code, using crossover function , mutate function develop stronger populations. but, need functions treat input charachters 1 whole unit. eg: while mutating, function replaces 1 or t 't1' or k or 1 'k1' need treat t1 , k1 single unit, rather string, , replace them whole other units t2, t3, t4 etc. suggestions or hints appreciated. thanking you.

as @evert , @user3080953 mentioned, problem lies in representation of chromosome.

what goal of genetic algorithm?

from code have provided, seems want population evolve towards given target string in_str. but, have addressed in question, strings invalid , should not considered (e.g. t1d8 valid chromosome whereas t18d not).

there couple of solutions potentially remedy issue:

approach #1 (as provided @user3080953)

wisely pick split point during crossover. since every valid gene length 2 string, split index must even. instead of:

split = random.randint(0, in_str_len) 

... write:

split = 2 * random.randint(0, in_str_len // 2)  

then, make similar changes in mutation() function.

approach #2 (as provided @evert)

encode each chromosome list of strings rather single string.

so, change:

self.string = ' '.join(random.choice(chars) _ in xrange(length)) 

... to:

self.string = [random.choice(chars) _ in xrange(length)] 

approach #3

this might overkill, if more scalability, should consider wrapping each gene object. example:

class gene:     # not literally, picture     gene._gene_set = set([...])      def __init__(self, gene_str):         formatted_gene_str = self._format(gene_str)         assert self._is_valid_gene_str(formatted_gene_str)          self._gene_str = formatted_gene_str      def _is_valid_gene_str(self, gene_str):         return gene_str in gene._gene_set      def _format(self, gene_str):         return gene_str.strip().upper()          def __str__(self):         return self._gene_str      def __eq__(self, other):         return type(other) gene , str(self) == str(other) 

also, there seems potential design flaw in code. wrote:

self.string = ' '.join(random.choice(chars) _ in xrange(length)) 

... inserts space between each gene; however, target string has no spaces. fuzz.ratio() uses levenshtein distance calculate differences between sequences.


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -