diff --git a/src/database/sql_database.py b/src/database/sql_database.py index d66d66f..4cbea44 100644 --- a/src/database/sql_database.py +++ b/src/database/sql_database.py @@ -1,6 +1,6 @@ import sqlite3 -from sqlite3 import Error import os + from tabulate import tabulate class SQL_Database: @@ -15,6 +15,40 @@ class SQL_Database: 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): """Decorator used to set the default config_id""" @@ -24,7 +58,6 @@ class SQL_Database: return new_method - def format_query_data(method): """Decorator used to format query data""" @@ -43,42 +76,106 @@ class SQL_Database: return new_method + #=====================================# + # Request information Queries: # + #=====================================# + def get_current_config(self): """Get the current config_id from the config table.""" 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): - """Returns the sql type for the object""" + query_data = self.query_all(f"SELECT id,chromosome_length,population_size,generation_goal FROM config;") - if isinstance(obj, int): - return 'INT' - elif isinstance(obj, float): - return 'REAL' - else: - return 'TEXT' + print( + tabulate( + query_data, + headers = [ + 'id', + 'chromosome_length', + 'population_size', + 'generation_goal' + ] + ) + ) - def create_connection(self): - """Create a database connection to the SQLite database - specified by db_file.""" + def get_most_recent_config_id(self): + """Function to get the most recent config_id from the database.""" + 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: - self.conn = sqlite3.connect(self.database_name) - except Error as e: - self.conn = None - print(e) + cur.executemany(sql, db_config_list) + except: + self.remove_database() + cur = self.conn.cursor() + cur.executemany(sql, db_config_list) - - def create_table(self, create_table_sql): - """Create a table from the create_table_sql statement.""" - - try: - c = self.conn.cursor() - c.execute(create_table_sql) - except Error as e: - print(e) + self.conn.commit() + self.config_id = self.get_current_config() + return cur.lastrowid def insert_chromosome(self, generation, chromosome): @@ -131,40 +228,28 @@ class SQL_Database: 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 - for var in ga.__dict__.keys(): + def create_connection(self): + """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: - 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 - 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.") + def create_table(self, create_table_sql): + """Create a table from the create_table_sql statement.""" + try: + c = self.conn.cursor() + c.execute(create_table_sql) + except Error as e: + print(e) def create_config_table_string(self,ga): """Automate the table creation sql statement so that it takes all the @@ -181,42 +266,6 @@ class SQL_Database: 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 def query_all(self, query): @@ -226,7 +275,6 @@ class SQL_Database: cur.execute(query) return cur.fetchall() - @format_query_data def query_one_item(self, query): """Query for single data point""" @@ -235,62 +283,35 @@ class SQL_Database: cur.execute(query) return cur.fetchone() - def remove_database(self): """Remove the current database file using the database_name attribute.""" os.remove(self._database_name) + def sql_type_of(self, obj): + """Returns the sql type for the object""" - def past_runs(self): - """Show a summerization of the past runs that the user has done.""" - - query_data = self.query_all(f"SELECT id,chromosome_length,population_size,generation_goal FROM config;") - - print( - tabulate( - query_data, - headers = [ - 'id', - 'chromosome_length', - 'population_size', - 'generation_goal' - ] - ) - ) + if isinstance(obj, int): + return 'INT' + elif isinstance(obj, float): + return 'REAL' + else: + return 'TEXT' - def get_most_recent_config_id(self): - """Function to get the most recent config_id from the database.""" + def get_var_names(self, ga): + """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;") - - - @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;") + #=====================================# + # Setters and Getters: # + #=====================================# @property diff --git a/src/run.py b/src/run.py index 737f01e..702f7b5 100644 --- a/src/run.py +++ b/src/run.py @@ -3,49 +3,9 @@ import random #Create the Genetic Algorithm 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() #Print your default genetic algorithm ga.print_generation() ga.print_population() - -#Prints a graph of the genetic algorithm -ga.graph.highest_value_chromosome() -ga.graph.show()