Skip to content

Commit fc2de9d

Browse files
committed
to classes
1 parent 3b94c6b commit fc2de9d

File tree

2 files changed

+38
-204
lines changed

2 files changed

+38
-204
lines changed

.gitignore

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
/.vscode
2-
/trabajo2.pdf
3-
/__pycache__
4-
.gitignore
1+
/.idea/
2+
/.vscode/
3+
/__pycache__/
4+
__pycache__/ga.cpython-39.pyc
5+
algorithms/__pycache__/__init__.cpython-39.pyc
6+
7+
algorithms/__pycache__/abstractga.cpython-39.pyc
8+
utils/__pycache__/__init__.cpython-39.pyc
9+
__pycache__/ga.cpython-39.pyc

ga.py

+29-200
Original file line numberDiff line numberDiff line change
@@ -1,201 +1,30 @@
11
# -*- coding: utf-8 -*-
2-
3-
import os
4-
import sys
5-
import random
6-
import re
7-
from math import ceil
8-
9-
10-
_password = "Toc, toc, toc... Open up. It's me! Who if not?"
11-
12-
###############################################################################
13-
# Command line options
14-
###############################################################################
15-
_pop_size = 100
16-
_elite_rate = 0.2
17-
_mutate_prob = 0.8
18-
_max_generations = 10000
19-
_verbose, _print_all, _static_print, _matrix = True, False, True, False
20-
_version = 0 if os.path.split(__file__)[-1] == os.path.split(sys.argv[0])[-1] else sys.argv[0][-4]
21-
for arg in sys.argv[1:]:
22-
if re.compile('^-[vasVAS]+').search(arg):
23-
if 'v' in arg: _verbose = True
24-
if 'V' in arg: _verbose = False
25-
if 'a' in arg: _print_all = True
26-
if 'A' in arg: _print_all = False
27-
if 's' in arg: _static_print = True
28-
if 'S' in arg: _static_print = False
29-
if 'm' in arg: _matrix = True
30-
if 'M' in arg: _matrix = False
31-
elif re.compile('^--pop-size=[-\+\d]+').search(arg): _pop_size = int(arg.split('=')[1])
32-
elif re.compile('^--elite-rate=[-\+\d]+').search(arg): _elite_rate = float(arg.split('=')[1])
33-
elif re.compile('^--mutate-prob=[-\+\d]+').search(arg): _mutate_prob = float(arg.split('=')[1])
34-
elif re.compile('^--max-generations=[-\+\d]+').search(arg): _max_generations = int(arg.split('=')[1])
35-
elif re.compile('^--password=.+').search(arg): _password = arg.split('=')[1]
36-
elif re.compile('^[^-]{2}.+').search(arg): _password = arg
37-
elif re.compile('^--verbose=[\d]+').search(arg): _verbose = bool(int(arg.split('=')[1]))
38-
elif re.compile('^--all=[\d]+').search(arg): _print_all = bool(int(arg.split('=')[1]))
39-
elif re.compile('^--static=[\d]+').search(arg): _static_print = bool(int(arg.split('=')[1]))
40-
elif re.compile('^--version=[-\+\d]+').search(arg) and os.path.split(__file__)[-1] == os.path.split(sys.argv[0])[-1]: _version = arg.split('=')[1]
41-
if sum([1 for i in [_elite_rate, _mutate_prob, _pop_size, _max_generations] if i < 0]):
42-
sys.exit("Error: Invalid parameters")
43-
44-
###############################################################################
45-
46-
def get_password_len():
47-
""" Return the length of the current password, for simulation purposes """
48-
return len(_password)
49-
50-
51-
def get_fitness(guess):
52-
""" Return the number of character's in guess string mismatching the same position of the password """
53-
return sum(1 for expected, actual in zip(_password, guess) if expected != actual)
54-
55-
56-
def gene_set():
57-
""" Return the feasible characters of the password """
58-
return " 0123456789áéíóúabcdefghijklmnñopqrstuvwxyzÁÉÍÓÚABCDEFGHIJKLMNÑOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>¿?@[\\]^_`{|}"
59-
60-
###############################################################################
61-
62-
def initial_population(pop_size, chromosome_len):
63-
""" Create a initial population """
64-
population = []
65-
for _ in range(pop_size):
66-
population.append( ''.join(random.choice(gene_set()) for _ in range(chromosome_len)))
67-
return [[i, get_fitness(i)] for i in population]
68-
69-
70-
def mutate(chromosome):
71-
""" Mutate randomly one gen of the chromosome, which is a string with the characters of the password """
72-
pos = random.randint(0, get_password_len() - 1)
73-
chromosome[0] = chromosome[0][:pos] + random.choice(gene_set()) + chromosome[0][pos+1:]
74-
chromosome[1] = get_fitness(chromosome[0])
75-
return chromosome
76-
77-
78-
def crossover(chromosome1, chromosome2):
79-
""" Perform a one point crossover of the chromosomes """
80-
if random.random() < 0.5: chromosome1, chromosome2 = chromosome2, chromosome1
81-
split = random.randint(0, get_password_len() - 1)
82-
hybrid = chromosome1[0][:split] + chromosome2[0][split:]
83-
return [hybrid, get_fitness(hybrid)]
84-
85-
86-
def ga(pop_size=_pop_size, elite_rate=_elite_rate, mutate_prob=_mutate_prob, max_generations=_max_generations, fun_next_gen=None):
87-
""" Genetic Algorithm driving the search of the password """
88-
pop = initial_population(pop_size, get_password_len())
89-
for i in range(max_generations):
90-
pop.sort(key=lambda x: x[1])
91-
print_generation(elite_rate, mutate_prob, the_fitest=pop[0], generation=i+1, pop=pop)
92-
if pop[0][1] == 0:
93-
return pop[0][0]
94-
pop = fun_next_gen(pop, pop_size, elite_rate, mutate_prob)
95-
print("Password not found")
96-
return False
97-
98-
99-
###############################################################################
100-
101-
def roulette(players, num_winners=1):
102-
""" Return the winners of the roulette wheel selection """
103-
selection_mode = num_winners < len(players)/2 # True if it is preferable to select than delete.
104-
players = players.copy() # Avoid modifying the original list
105-
players.sort(key=lambda x: x[1], reverse=selection_mode)
106-
winners = [] if selection_mode else players
107-
for _ in range(num_winners if selection_mode else len(players) - num_winners):
108-
domain = gauss_form(len(players))
109-
tirada = random.randint(1, domain)
110-
if selection_mode: winners.append(players.pop( winner(tirada) ))
111-
else: winners.pop( winner(tirada) )
112-
return winners if num_winners != 1 else winners[0]
113-
114-
115-
def gauss_form(n):
116-
""" Return the sum of 1..n natural numbers """
117-
return (n*(n+1)) // 2
118-
119-
120-
def inverse_gauss_form(a):
121-
""" Return the inverse function of the gauss_sum """
122-
return ((8*a+1)**0.5 - 1) / 2
123-
124-
125-
def winner(value):
126-
""" Return the winner of the roulette wheel selection """
127-
return ceil( inverse_gauss_form(value) ) - 1
128-
129-
130-
###############################################################################
131-
# Printing methods
132-
###############################################################################
133-
134-
def print_generation(elite_rate, mutate_prob, the_fitest, generation, pop):
135-
msg = ""
136-
if _static_print:
137-
msg += "\033[1;1f"
138-
if _verbose: msg += _print_verbose(elite_rate, mutate_prob, the_fitest, generation, pop)
139-
else: msg += _print_non_verbose(the_fitest, generation)
140-
if not _static_print and _verbose and not _print_all: msg += _separator_line()
141-
if _print_all: msg += _str_print_all(pop)
142-
if not _static_print and _print_all: msg += _separator_line()
143-
if _matrix: msg += _print_bests_solutions(pop)
144-
print(msg)
145-
146-
147-
def _str_print_all(pop):
148-
lst = "\n\nOrdered fitness list of the entire population:\n\033[0;0m"
149-
for i in range(len(pop)):
150-
lst += str(f'\033[0;31m{pop[i][1]:4}\033[0;0m')
151-
if (i+1) % 20 == 0: lst += "\n\033[0;0m"
152-
return lst
153-
154-
155-
def _separator_line():
156-
return "\n" + "-"*80 + "\n\033[0;0m"
157-
158-
159-
def _print_verbose(elite_rate, mutate_prob, the_fitest, generation, pop):
160-
ret = "Version: \033[0K\033[5;33m" + str(_version) + "\033[0;0m"
161-
ret += "\nPassword length: \033[0K\033[5;33m" + str(get_password_len()) + "\033[0;0m"
162-
ret += "\nPopulation Size: \033[0K\033[5;33m" + str(len(pop)) + "\033[0;0m"
163-
ret += "\nElite Rate: \033[0K\033[5;33m" + str(elite_rate) + "\033[0;0m"
164-
ret += "\nMutate Probability: \033[0K\033[5;33m" + str(mutate_prob) + "\033[0;0m"
165-
ret += "\n\nGeneration: \033[0K\033[5;33m" + str(generation) + "\033[0;0m"
166-
ret += " best-fitness: \033[0K\033[5;33m" + str(the_fitest[1]) + "\033[0;0m"
167-
ret += "\n \033[0K\033[5;32m" + str(the_fitest[0]) + "\033[0;0m"
168-
return ret
169-
170-
171-
def _print_non_verbose(the_fitest, generation):
172-
ret = "\033[0;0mGeneration: " + "\033[0K\033[5;33m" + str(generation) + "\033[0;0m"
173-
ret += "\033[0;0m best-fitness: " + "\033[0K\033[5;33m" + str(the_fitest[1]) + "\033[0;0m"
174-
ret += " \033[0K\033[5;32m" + str(the_fitest[0]) + "\033[0;0m"
175-
return ret
176-
177-
178-
def _print_bests_solutions(pop):
179-
ret = "\n"
180-
for i in range(40):
181-
ret += f" \033[5;33m{i:3}\033[0;0m:\033[5;36m{pop[i][1]:4}\033[0;0m | \033[5;32m" \
182-
+ str(pop[i][0]) + "\n\033[0;0m"
183-
return ret
184-
185-
186-
###############################################################################
187-
# Version selection
188-
###############################################################################
189-
190-
if os.path.split(__file__)[-1] == os.path.split(sys.argv[0])[-1]:
191-
if _version:
192-
if _static_print: print("\033[2J\033[1;1f")
193-
exec(open('ga_v{}.py'.format(_version)).read())
194-
else:
195-
print("\nRun the corresponding version file, or indicate the version you want to run.",
196-
"Examples:",
197-
"> python3 ga_v1.py",
198-
"> python3 ga.py -vasm --version=1\n", sep="\n")
199-
exit(0)
200-
201-
# print("fin ga.py")
2+
# Path: ga.py
3+
4+
5+
from algorithms.genetics import GeneticAlgorithmV3, GeneticAlgorithmV1, GeneticAlgorithmV2, GeneticAlgorithmV4, \
6+
GeneticAlgorithmV5, GeneticAlgorithmV6
7+
from utils import args, separator_line
8+
9+
args = args()
10+
11+
if int(args['version']) == 1:
12+
ga = GeneticAlgorithmV1(vars=args)
13+
elif int(args['version']) == 2:
14+
ga = GeneticAlgorithmV2(vars=args)
15+
elif int(args['version']) == 3:
16+
ga = GeneticAlgorithmV3(vars=args)
17+
elif int(args['version']) == 4:
18+
ga = GeneticAlgorithmV4(vars=args)
19+
elif int(args['version']) == 5:
20+
ga = GeneticAlgorithmV5(vars=args)
21+
elif int(args['version']) == 6:
22+
ga = GeneticAlgorithmV6(vars=args)
23+
else:
24+
raise Exception("Error: Invalid version")
25+
26+
ga.run()
27+
28+
print(f"{separator_line()}\nEnd of version {ga.version}\n")
29+
ga.print_stats()
30+
print(f"{separator_line()}\n")

0 commit comments

Comments
 (0)