format changes and addded block comments
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
from sqlite3 import Error
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
|
|
||||||
class SQL_Database:
|
class SQL_Database:
|
||||||
@ -15,6 +15,40 @@ class SQL_Database:
|
|||||||
self._database_name = 'database.db'
|
self._database_name = 'database.db'
|
||||||
|
|
||||||
|
|
||||||
|
#=====================================#
|
||||||
|
# Create Config and Data Table: #
|
||||||
|
#=====================================#
|
||||||
|
|
||||||
|
def create_all_tables(self, ga):
|
||||||
|
"""Create the database if it doenst exist and then the data and config
|
||||||
|
tables."""
|
||||||
|
|
||||||
|
# if the database file already exists.
|
||||||
|
try:
|
||||||
|
self.config = self.get_current_config()
|
||||||
|
|
||||||
|
# If the database does not exist continue
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Create the database connection
|
||||||
|
self.create_connection()
|
||||||
|
|
||||||
|
if self.conn is not None:
|
||||||
|
# Create data table
|
||||||
|
self.create_table(ga.sql_create_data_structure)
|
||||||
|
# Creare config table
|
||||||
|
self.create_table(self.create_config_table_string(ga))
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception("Error! Cannot create the database connection.")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#=====================================#
|
||||||
|
# Decorators: #
|
||||||
|
#=====================================#
|
||||||
|
|
||||||
def default_config_id(method):
|
def default_config_id(method):
|
||||||
"""Decorator used to set the default config_id"""
|
"""Decorator used to set the default config_id"""
|
||||||
|
|
||||||
@ -24,7 +58,6 @@ class SQL_Database:
|
|||||||
|
|
||||||
return new_method
|
return new_method
|
||||||
|
|
||||||
|
|
||||||
def format_query_data(method):
|
def format_query_data(method):
|
||||||
"""Decorator used to format query data"""
|
"""Decorator used to format query data"""
|
||||||
|
|
||||||
@ -43,42 +76,106 @@ class SQL_Database:
|
|||||||
|
|
||||||
return new_method
|
return new_method
|
||||||
|
|
||||||
|
#=====================================#
|
||||||
|
# Request information Queries: #
|
||||||
|
#=====================================#
|
||||||
|
|
||||||
|
|
||||||
def get_current_config(self):
|
def get_current_config(self):
|
||||||
"""Get the current config_id from the config table."""
|
"""Get the current config_id from the config table."""
|
||||||
return self.query_one_item("SELECT MAX(id) FROM config")
|
return self.query_one_item("SELECT MAX(id) FROM config")
|
||||||
|
|
||||||
|
def past_runs(self):
|
||||||
|
"""Show a summerization of the past runs that the user has done."""
|
||||||
|
|
||||||
def sql_type_of(self, obj):
|
query_data = self.query_all(f"SELECT id,chromosome_length,population_size,generation_goal FROM config;")
|
||||||
"""Returns the sql type for the object"""
|
|
||||||
|
|
||||||
if isinstance(obj, int):
|
print(
|
||||||
return 'INT'
|
tabulate(
|
||||||
elif isinstance(obj, float):
|
query_data,
|
||||||
return 'REAL'
|
headers = [
|
||||||
else:
|
'id',
|
||||||
return 'TEXT'
|
'chromosome_length',
|
||||||
|
'population_size',
|
||||||
|
'generation_goal'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_connection(self):
|
def get_most_recent_config_id(self):
|
||||||
"""Create a database connection to the SQLite database
|
"""Function to get the most recent config_id from the database."""
|
||||||
specified by db_file."""
|
|
||||||
|
|
||||||
|
return self.query_one_item("SELECT max(config_id) FROM config")
|
||||||
|
|
||||||
|
|
||||||
|
@default_config_id
|
||||||
|
def get_generation_total_fitness(self, config_id):
|
||||||
|
"""Get each generations total fitness sum from the database """
|
||||||
|
|
||||||
|
return self.query_all(f"SELECT SUM(fitness) FROM data WHERE config_id={config_id} GROUP BY generation;")
|
||||||
|
|
||||||
|
|
||||||
|
@default_config_id
|
||||||
|
def get_total_generations(self, config_id):
|
||||||
|
"""Get the total generations from the database"""
|
||||||
|
|
||||||
|
return self.query_one_item(f"SELECT COUNT(DISTINCT generation) FROM data WHERE config_id={config_id};")
|
||||||
|
|
||||||
|
|
||||||
|
@default_config_id
|
||||||
|
def get_highest_chromosome(self, config_id):
|
||||||
|
"""Get the highest fitness of each generation"""
|
||||||
|
|
||||||
|
return self.query_all(f"SELECT fitness, max(fitness) FROM data WHERE config_id={config_id} GROUP by generation;")
|
||||||
|
|
||||||
|
|
||||||
|
@default_config_id
|
||||||
|
def get_lowest_chromosome(self, config_id):
|
||||||
|
"""Get the lowest fitness of each generation"""
|
||||||
|
|
||||||
|
return self.query_all(f"SELECT fitness, min(fitness) FROM data WHERE config_id={config_id} GROUP by generation;")
|
||||||
|
|
||||||
|
|
||||||
|
#=====================================#
|
||||||
|
# Input information Queries: #
|
||||||
|
#=====================================#
|
||||||
|
|
||||||
|
def insert_config(self,ga):
|
||||||
|
"""Insert the configuration attributes into the config."""
|
||||||
|
|
||||||
|
# Structure the insert data
|
||||||
|
db_config_list = list(ga.__dict__.values())
|
||||||
|
|
||||||
|
# Clean up so the sqlite database accepts the data structure
|
||||||
|
for i in range(len(db_config_list)):
|
||||||
|
if callable(db_config_list[i]):
|
||||||
|
db_config_list[i] = db_config_list[i].__name__
|
||||||
|
elif type(db_config_list[i]) not in self.sql_type_list:
|
||||||
|
db_config_list[i] = str(db_config_list[i])
|
||||||
|
|
||||||
|
# Create sql query structure
|
||||||
|
sql = "INSERT INTO config (" \
|
||||||
|
+ ",".join(self.get_var_names(ga)) \
|
||||||
|
+ ") VALUES(" \
|
||||||
|
+ ( ",?"*len(db_config_list) )[1:] \
|
||||||
|
+ ") "
|
||||||
|
|
||||||
|
# For some reason it has to be in var = array(tuple()) form
|
||||||
|
db_config_list = [tuple(db_config_list)]
|
||||||
|
|
||||||
|
# Execute sql query
|
||||||
|
cur = self.conn.cursor()
|
||||||
try:
|
try:
|
||||||
self.conn = sqlite3.connect(self.database_name)
|
cur.executemany(sql, db_config_list)
|
||||||
except Error as e:
|
except:
|
||||||
self.conn = None
|
self.remove_database()
|
||||||
print(e)
|
cur = self.conn.cursor()
|
||||||
|
cur.executemany(sql, db_config_list)
|
||||||
|
|
||||||
|
self.conn.commit()
|
||||||
def create_table(self, create_table_sql):
|
self.config_id = self.get_current_config()
|
||||||
"""Create a table from the create_table_sql statement."""
|
return cur.lastrowid
|
||||||
|
|
||||||
try:
|
|
||||||
c = self.conn.cursor()
|
|
||||||
c.execute(create_table_sql)
|
|
||||||
except Error as e:
|
|
||||||
print(e)
|
|
||||||
|
|
||||||
|
|
||||||
def insert_chromosome(self, generation, chromosome):
|
def insert_chromosome(self, generation, chromosome):
|
||||||
@ -131,40 +228,28 @@ class SQL_Database:
|
|||||||
return cur.lastrowid
|
return cur.lastrowid
|
||||||
|
|
||||||
|
|
||||||
def get_var_names(self, ga):
|
#=====================================#
|
||||||
"""Returns a list of the names of attributes of the ga."""
|
# Functions: #
|
||||||
|
#=====================================#
|
||||||
|
|
||||||
# Loop through all attributes
|
def create_connection(self):
|
||||||
for var in ga.__dict__.keys():
|
"""Create a database connection to the SQLite database
|
||||||
|
specified by db_file."""
|
||||||
|
|
||||||
# Remove leading underscore
|
|
||||||
yield (var[1:] if (var[0] == '_') else var)
|
|
||||||
|
|
||||||
|
|
||||||
def create_all_tables(self, ga):
|
|
||||||
"""Create the database if it doenst exist and then the data and config
|
|
||||||
tables."""
|
|
||||||
|
|
||||||
# if the database file already exists.
|
|
||||||
try:
|
try:
|
||||||
self.config = self.get_current_config()
|
self.conn = sqlite3.connect(self.database_name)
|
||||||
|
except Error as e:
|
||||||
|
self.conn = None
|
||||||
|
print(e)
|
||||||
|
|
||||||
# If the database does not exist continue
|
def create_table(self, create_table_sql):
|
||||||
except:
|
"""Create a table from the create_table_sql statement."""
|
||||||
pass
|
|
||||||
|
|
||||||
# Create the database connection
|
|
||||||
self.create_connection()
|
|
||||||
|
|
||||||
if self.conn is not None:
|
|
||||||
# Create data table
|
|
||||||
self.create_table(ga.sql_create_data_structure)
|
|
||||||
# Creare config table
|
|
||||||
self.create_table(self.create_config_table_string(ga))
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise Exception("Error! Cannot create the database connection.")
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
c = self.conn.cursor()
|
||||||
|
c.execute(create_table_sql)
|
||||||
|
except Error as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def create_config_table_string(self,ga):
|
def create_config_table_string(self,ga):
|
||||||
"""Automate the table creation sql statement so that it takes all the
|
"""Automate the table creation sql statement so that it takes all the
|
||||||
@ -181,42 +266,6 @@ class SQL_Database:
|
|||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|
||||||
def insert_config(self,ga):
|
|
||||||
"""Insert the configuration attributes into the config."""
|
|
||||||
|
|
||||||
# Structure the insert data
|
|
||||||
db_config_list = list(ga.__dict__.values())
|
|
||||||
|
|
||||||
# Clean up so the sqlite database accepts the data structure
|
|
||||||
for i in range(len(db_config_list)):
|
|
||||||
if callable(db_config_list[i]):
|
|
||||||
db_config_list[i] = db_config_list[i].__name__
|
|
||||||
elif type(db_config_list[i]) not in self.sql_type_list:
|
|
||||||
db_config_list[i] = str(db_config_list[i])
|
|
||||||
|
|
||||||
# Create sql query structure
|
|
||||||
sql = "INSERT INTO config (" \
|
|
||||||
+ ",".join(self.get_var_names(ga)) \
|
|
||||||
+ ") VALUES(" \
|
|
||||||
+ ( ",?"*len(db_config_list) )[1:] \
|
|
||||||
+ ") "
|
|
||||||
|
|
||||||
# For some reason it has to be in var = array(tuple()) form
|
|
||||||
db_config_list = [tuple(db_config_list)]
|
|
||||||
|
|
||||||
# Execute sql query
|
|
||||||
cur = self.conn.cursor()
|
|
||||||
try:
|
|
||||||
cur.executemany(sql, db_config_list)
|
|
||||||
except:
|
|
||||||
self.remove_database()
|
|
||||||
cur = self.conn.cursor()
|
|
||||||
cur.executemany(sql, db_config_list)
|
|
||||||
|
|
||||||
self.conn.commit()
|
|
||||||
self.config_id = self.get_current_config()
|
|
||||||
return cur.lastrowid
|
|
||||||
|
|
||||||
|
|
||||||
@format_query_data
|
@format_query_data
|
||||||
def query_all(self, query):
|
def query_all(self, query):
|
||||||
@ -226,7 +275,6 @@ class SQL_Database:
|
|||||||
cur.execute(query)
|
cur.execute(query)
|
||||||
return cur.fetchall()
|
return cur.fetchall()
|
||||||
|
|
||||||
|
|
||||||
@format_query_data
|
@format_query_data
|
||||||
def query_one_item(self, query):
|
def query_one_item(self, query):
|
||||||
"""Query for single data point"""
|
"""Query for single data point"""
|
||||||
@ -235,62 +283,35 @@ class SQL_Database:
|
|||||||
cur.execute(query)
|
cur.execute(query)
|
||||||
return cur.fetchone()
|
return cur.fetchone()
|
||||||
|
|
||||||
|
|
||||||
def remove_database(self):
|
def remove_database(self):
|
||||||
"""Remove the current database file using the database_name attribute."""
|
"""Remove the current database file using the database_name attribute."""
|
||||||
os.remove(self._database_name)
|
os.remove(self._database_name)
|
||||||
|
|
||||||
|
def sql_type_of(self, obj):
|
||||||
|
"""Returns the sql type for the object"""
|
||||||
|
|
||||||
def past_runs(self):
|
if isinstance(obj, int):
|
||||||
"""Show a summerization of the past runs that the user has done."""
|
return 'INT'
|
||||||
|
elif isinstance(obj, float):
|
||||||
query_data = self.query_all(f"SELECT id,chromosome_length,population_size,generation_goal FROM config;")
|
return 'REAL'
|
||||||
|
else:
|
||||||
print(
|
return 'TEXT'
|
||||||
tabulate(
|
|
||||||
query_data,
|
|
||||||
headers = [
|
|
||||||
'id',
|
|
||||||
'chromosome_length',
|
|
||||||
'population_size',
|
|
||||||
'generation_goal'
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_most_recent_config_id(self):
|
def get_var_names(self, ga):
|
||||||
"""Function to get the most recent config_id from the database."""
|
"""Returns a list of the names of attributes of the ga."""
|
||||||
|
|
||||||
return self.query_one_item("SELECT max(config_id) FROM config")
|
# Loop through all attributes
|
||||||
|
for var in ga.__dict__.keys():
|
||||||
|
|
||||||
|
# Remove leading underscore
|
||||||
|
yield (var[1:] if (var[0] == '_') else var)
|
||||||
|
|
||||||
|
|
||||||
@default_config_id
|
|
||||||
def get_generation_total_fitness(self, config_id):
|
|
||||||
"""Get each generations total fitness sum from the database """
|
|
||||||
|
|
||||||
return self.query_all(f"SELECT SUM(fitness) FROM data WHERE config_id={config_id} GROUP BY generation;")
|
#=====================================#
|
||||||
|
# Setters and Getters: #
|
||||||
|
#=====================================#
|
||||||
@default_config_id
|
|
||||||
def get_total_generations(self, config_id):
|
|
||||||
"""Get the total generations from the database"""
|
|
||||||
|
|
||||||
return self.query_one_item(f"SELECT COUNT(DISTINCT generation) FROM data WHERE config_id={config_id};")
|
|
||||||
|
|
||||||
|
|
||||||
@default_config_id
|
|
||||||
def get_highest_chromosome(self, config_id):
|
|
||||||
"""Get the highest fitness of each generation"""
|
|
||||||
|
|
||||||
return self.query_all(f"SELECT fitness, max(fitness) FROM data WHERE config_id={config_id} GROUP by generation;")
|
|
||||||
|
|
||||||
|
|
||||||
@default_config_id
|
|
||||||
def get_lowest_chromosome(self, config_id):
|
|
||||||
"""Get the lowest fitness of each generation"""
|
|
||||||
|
|
||||||
return self.query_all(f"SELECT fitness, min(fitness) FROM data WHERE config_id={config_id} GROUP by generation;")
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
40
src/run.py
40
src/run.py
@ -3,49 +3,9 @@ import random
|
|||||||
|
|
||||||
#Create the Genetic Algorithm
|
#Create the Genetic Algorithm
|
||||||
ga = EasyGA.GA()
|
ga = EasyGA.GA()
|
||||||
password = input("""Please enter a word or sentence (Use only standard
|
|
||||||
characters such as letters, spaces and, punctuation marks): """)
|
|
||||||
ga.chromosome_length = len(password)
|
|
||||||
ga.fitness_goal = len(password)
|
|
||||||
|
|
||||||
ga.population_size = 50
|
|
||||||
ga.generation_goal = 1000
|
|
||||||
|
|
||||||
|
|
||||||
def password_fitness(chromosome):
|
|
||||||
|
|
||||||
fitness = 0
|
|
||||||
|
|
||||||
# For each gene in the chromosome
|
|
||||||
for gene, letter in zip(chromosome, password):
|
|
||||||
|
|
||||||
# If the gene letter matchs the password
|
|
||||||
if gene.value == letter:
|
|
||||||
fitness += 1
|
|
||||||
|
|
||||||
return fitness
|
|
||||||
|
|
||||||
|
|
||||||
ga.fitness_function_impl = password_fitness
|
|
||||||
|
|
||||||
ga.adapt_population_flag = False
|
|
||||||
ga.adapt_rate = 0
|
|
||||||
|
|
||||||
# Creates random genes utilizing the characters below
|
|
||||||
ga.gene_impl = lambda: random.choice([
|
|
||||||
"A","a","B","b","C","c","D","d","E","e",
|
|
||||||
"F","f","G","g","H","h","I","i","J","j",
|
|
||||||
"K","k","L","l","M","m","N","n","O","o",
|
|
||||||
"P","p","Q","q","R","r","S","s","T","t",
|
|
||||||
"U","u","V","v","W","w","X","x","Y","y",
|
|
||||||
"Z","z"," ",".","!","?"])
|
|
||||||
|
|
||||||
ga.evolve()
|
ga.evolve()
|
||||||
|
|
||||||
#Print your default genetic algorithm
|
#Print your default genetic algorithm
|
||||||
ga.print_generation()
|
ga.print_generation()
|
||||||
ga.print_population()
|
ga.print_population()
|
||||||
|
|
||||||
#Prints a graph of the genetic algorithm
|
|
||||||
ga.graph.highest_value_chromosome()
|
|
||||||
ga.graph.show()
|
|
||||||
|
|||||||
Reference in New Issue
Block a user