Home > Blockchain >  Python Genetic Algorithm: Setting Functions for Usage
Python Genetic Algorithm: Setting Functions for Usage

Time:10-27

I am experimenting with python about genetic algorithm. In other words, I want to make a program to simulate random process and control come parts (like experiment) to play around with variables and outcomes.

For my program, I am simulating rat reproduction and controlling its population to create superior (in my case, heavier) rats at the end. In specific, I want to have starting population of rats, randomly pair two for reproduction (in which offspring will have average weight of two parent rats) and control offspring population and so on. In simple words, I will have x population of rats (initial and constant), create offsprings, list them by weight, kill from the bottom (lightest rats) to lower the offspring population == initial population and repeat the process to eventually create heavier rats.

I know this experiment does not reflect real-life example but I want to initialize with this program and maybe make modifications or applications to other usages.

Sorry for the long introduction. Now, before writing the actual program, I want to create functions (using def command) to make actual codes easier to write. So far, I've come up with this:

import random

#Variables (Stop at (1) period of time or (2) above standard)
#number_rats = #initial population (standard)
min_offspring = 2
max_offspring = 10
#weight_rat = #Avg. of parents' weight (consider as single gender)
#mutation = #Randomly reduce the weight of small number of offspring (how many and how 
much)

def breeding(female, male):
    #random # of offspring and random weight for each
    offspring = []
    number_offspring = random.randint(min_offspring, max_offspring)
    for i in range(0, number_offspring, 1):
         offspring.append(random.triangular(female, male))
    return offspring

def #random pair

def # cut offspring population to number_rats (list from highest weight to lowest and 
cut light rats)

def # negative mutation (maybe inside breeding function) 10% chance of mutation that 
decreases weight by 10%.

I have tried to complete the function for breeding to take 2 rats (I labeled male and female but I decided that any 2 rats are fine to lessen the complication) and they would produce random numbers of offsprings.

However, I am stuck on creating function for (1) taking random pairs from number_rats, (2) cutting huge number of offsprings to == number_rat, and (3) creating negative mutation when reproducing. It would help me a lot to help me write these functions in concise ways.

I know this is long post with incomplete work but helping me with this initial stage would greatly help me. I am sorry if this is not advanced work.

Anyways, thanks in advance.

CodePudding user response:

Try this, you can experiment on the initial number of rats and generations etc. There is a class Rat that defines a rat with name and weight used to track down the weight.

code

import random
import string


num_rats = 20
min_offspring = 2
max_offspring = 10
init_weight_min = 1
init_weight_max = 10
mutation_chance_rate = 10  # %
mutation_weight_decrease = 10  # %
generations = 4


alphabet = string.ascii_lowercase   string.digits
def random_name():
    """Generates random chars for rat names."""
    return ''.join(random.choices(alphabet, k=8))


def print_population(population):
    for i, r in enumerate(population):
        print(f'no. {i 1:02d}, name: {r.name}, weight: {r.weight}')


class Rat:
    def __init__(self, name, weight):
        self.name = name
        self.weight = weight


def breeding(p1, p2):
    """
    Create offsprings from parents p1 and p2.
    Randomize number of offsprings and weight is based on parents weight.
    """
    offspring = []
    w1 = p1.weight
    w2 = p2.weight
    meanw = (w1 w2)/2

    number_offspring = random.randint(min_offspring, max_offspring)
    for _ in range(1, number_offspring):
        name = random_name()
        weight = meanw
        offspring.append(Rat(name, weight))  # Create Rat object as new pop

    return offspring


def random_pair():
    pass


def cut_offspring_population(population):
    """
    population is a list of rats.
    Cut offsprings to orignal number of rats, preserve heavier rats.
    """
    new_population = sorted(population, key=lambda x: x.weight, reverse=True)  # sort rats weights descending
    return new_population[0:num_rats]  # Cutoff


def negative_mutation(population):
    """
    10% chance of mutation that decreases weight by 10%.
    """
    new_population = []

    for p in population:
        current_name = p.name
        current_weight = p.weight

        if random.randint(1, 100) <= mutation_chance_rate:
            current_weight = current_weight * (100 - mutation_weight_decrease) / 100
            new_population.append(Rat(current_name, current_weight))
        else:
            new_population.append(Rat(current_name, current_weight))

    return new_population


def main():
    # (1) Create rats
    orig_rats = []
    for _ in range(num_rats):
        orig_rats.append(Rat(random_name(), random.randint(init_weight_min, init_weight_max)))

    random.shuffle(orig_rats)

    tmp_rats = orig_rats.copy()

    for i in range(1, generations   1):
        # (2) Breeding
        new_offs = []

        while tmp_rats:
            # Select 2 rats as parents.
            a = tmp_rats.pop()
            b = tmp_rats.pop()

            offs = breeding(a, b)
            new_offs = new_offs   offs  # save all new offsprings in a list.

        # (3) Reduce population.
        reduced_pop = cut_offspring_population(new_offs)

        # (4) Mutation
        mutated_pop = negative_mutation(reduced_pop)
        print(f'gen: {i}')
        print_population(mutated_pop)
        print()

        tmp_rats = mutated_pop.copy()  # for next gen


if __name__ == "__main__":
    main()

Output after 4 generations

Offsprings weight is the average of parents weight. Rat name is just random.

gen: 1
no. 01, name: gzqru5c7, weight: 10.0
no. 02, name: ngpqx75q, weight: 10.0
no. 03, name: 3f2f8ua9, weight: 10.0
no. 04, name: uitaftbs, weight: 9.0
no. 05, name: dkr2dmyg, weight: 9.0
no. 06, name: lq350zck, weight: 8.0
no. 07, name: 4l08ks0t, weight: 8.0
no. 08, name: 1sl64mzl, weight: 7.5
no. 09, name: 88umsinn, weight: 7.5
no. 10, name: 3f30jp8m, weight: 7.5
no. 11, name: y1gbmbyn, weight: 7.5
no. 12, name: j7w7fr9y, weight: 7.5
no. 13, name: 3x5gl7zt, weight: 7.5
no. 14, name: 7mus480j, weight: 7.5
no. 15, name: 8yaifbuf, weight: 7.5
no. 16, name: t14n1qyq, weight: 7.5
no. 17, name: pqtieh8h, weight: 7.0
no. 18, name: 2eb1rhax, weight: 7.0
no. 19, name: ekfhcwye, weight: 7.0
no. 20, name: gdmeu1td, weight: 7.0

gen: 2
no. 01, name: nod75vx3, weight: 10.0
no. 02, name: pbe2z04b, weight: 10.0
no. 03, name: 1gn30dch, weight: 9.0
no. 04, name: txj11vza, weight: 10.0
no. 05, name: eonla5xu, weight: 9.0
no. 06, name: kwh5uffh, weight: 10.0
no. 07, name: pcvw8djm, weight: 10.0
no. 08, name: 7upmw4bu, weight: 9.0
no. 09, name: 3yb36bfr, weight: 10.0
no. 10, name: sjp0m8n8, weight: 10.0
no. 11, name: yj5oyuwd, weight: 9.5
no. 12, name: hsnbhyy7, weight: 9.5
no. 13, name: 40bpj2jw, weight: 9.5
no. 14, name: 4cdsgb4l, weight: 9.5
no. 15, name: 4lutoxh7, weight: 9.5
no. 16, name: s1111jrc, weight: 9.5
no. 17, name: le2m1x6w, weight: 7.65
no. 18, name: m2t9tfas, weight: 8.5
no. 19, name: r1gzn6a7, weight: 8.5
no. 20, name: lmvntp28, weight: 8.5

gen: 3
no. 01, name: 6g42b95g, weight: 10.0
no. 02, name: end7366f, weight: 10.0
no. 03, name: ccivuw0g, weight: 9.0
no. 04, name: rpf9pd51, weight: 10.0
no. 05, name: 94qkveea, weight: 10.0
no. 06, name: x1p9rd00, weight: 10.0
no. 07, name: v4d39x6t, weight: 10.0
no. 08, name: z3miwqoy, weight: 10.0
no. 09, name: vmkkrkqt, weight: 10.0
no. 10, name: ii8is1xp, weight: 10.0
no. 11, name: uadfjnng, weight: 10.0
no. 12, name: 5349eie7, weight: 10.0
no. 13, name: ikpoyce6, weight: 10.0
no. 14, name: yqqgsm9p, weight: 10.0
no. 15, name: ykkq03jv, weight: 10.0
no. 16, name: i3zzdab2, weight: 10.0
no. 17, name: 1m7kjzom, weight: 9.0
no. 18, name: vqatmrar, weight: 10.0
no. 19, name: 6ddudyf7, weight: 9.5
no. 20, name: 5b9dhzwp, weight: 9.5

gen: 4
no. 01, name: mm0iggdw, weight: 10.0
no. 02, name: u6evuhn8, weight: 9.0
no. 03, name: e0jo12tu, weight: 9.0
no. 04, name: wbage11q, weight: 10.0
no. 05, name: 4zlf1gvx, weight: 10.0
no. 06, name: 1c2hr5dd, weight: 10.0
no. 07, name: hbyzhpfn, weight: 10.0
no. 08, name: avf5ptk5, weight: 10.0
no. 09, name: hgurh5l0, weight: 10.0
no. 10, name: crqyuao0, weight: 10.0
no. 11, name: vjxkf3qf, weight: 10.0
no. 12, name: myzdj95e, weight: 9.0
no. 13, name: 8v4g3wxz, weight: 10.0
no. 14, name: l0z17ijw, weight: 10.0
no. 15, name: 1z3brmra, weight: 10.0
no. 16, name: r261q7pr, weight: 10.0
no. 17, name: ovl7vla5, weight: 10.0
no. 18, name: f2mvcvyw, weight: 10.0
no. 19, name: u1x8b7il, weight: 9.0
no. 20, name: l5k43dut, weight: 10.0
  • Related