Files
EasyGA/src/database/sql_database.py
2020-11-16 11:35:31 -05:00

235 lines
6.7 KiB
Python

import sqlite3
from sqlite3 import Error
import os
class SQL_Database:
"""Main database class that controls all the functionality for input /
out of the database using SQLite3."""
sql_types_dict = [int, float, str]
def __init__(self):
self.conn = None
def create_connection(self, db_file):
"""Create a database connection to the SQLite database
specified by db_file."""
conn = None
try:
conn = sqlite3.connect(db_file)
return conn
except Error as e:
print(e)
self.conn = conn
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 insert_chromosome(self, generation, chromosome):
""" Insert one chromosome into the database"""
# Structure the insert data
db_chromosome = (generation, chromosome.fitness, '[chromosome]')
# Create sql query structure
sql = ''' INSERT INTO data(generation,fitness,chromosome)
VALUES(?,?,?) '''
cur = self.conn.cursor()
cur.execute(sql, db_chromosome)
self.conn.commit()
return cur.lastrowid
def insert_current_population(self, ga):
""" Insert current generations population """
# Structure the insert data
db_chromosome_list = [
(ga.current_generation, chromosome.fitness, '[chromosome]')
for chromosome in ga.population.get_chromosome_list()
]
# Create sql query structure
sql = ''' INSERT INTO data(generation,fitness,chromosome)
VALUES(?,?,?) '''
cur = self.conn.cursor()
cur.executemany(sql, db_chromosome_list)
self.conn.commit()
return cur.lastrowid
def create_all_tables(self, ga):
"""Create the data table that store generation data."""
try:
# Remove old database file if it exists.
os.remove(ga.database_name)
except:
# If the database does not exist continue
pass
# create a database connection
self.conn = self.create_connection(ga.database_name)
# create tables
if self.conn is not None:
# create projects table
self.create_table(ga.sql_create_data_structure)
self.create_table(ga.sql_create_config_structure)
else:
print("Error! cannot create the database connection.")
def insert_config(self,ga):
"""Insert the configuration attributes into the config."""
# Structure the insert data
db_config_list = [
ga.chromosome_length,
ga.population_size,
ga.chromosome_impl,
ga.gene_impl,
ga.target_fitness_type,
ga.update_fitness,
ga.parent_ratio,
ga.selection_probability,
ga.tournament_size_ratio,
ga.current_generation,
float(ga.current_fitness),
ga.generation_goal,
ga.fitness_goal,
ga.tolerance_goal,
ga.percent_converged,
ga.chromosome_mutation_rate,
ga.gene_mutation_rate,
ga.initialization_impl,
ga.fitness_function_impl,
ga.parent_selection_impl,
ga.crossover_individual_impl,
ga.crossover_population_impl,
ga.survivor_selection_impl,
ga.mutation_individual_impl,
ga.mutation_population_impl,
ga.termination_impl,
ga.database_name
]
# 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_types_dict:
db_config_list[i] = str(db_config_list[i])
# For some reason it has to be in var = array(tuple()) form
db_config_list = [tuple(db_config_list)]
# Create sql query structure
sql = f'''INSERT INTO config (chromosome_length,
population_size,
chromosome_impl,
gene_impl,
target_fitness_type,
update_fitness,
parent_ratio,
selection_probability,
tournament_size_ratio,
current_generation,
current_fitness,
generation_goal,
fitness_goal,
tolerance_goal,
percent_converged,
chromosome_mutation_rate,
gene_mutation_rate,
initialization_impl,
fitness_function_impl,
parent_selection_impl,
crossover_individual_impl,
crossover_population_impl,
survivor_selection_impl,
mutation_individual_impl,
mutation_population_impl,
termination_impl,
database_name) VALUES({(',?'*len(db_config_list))[1:]}) '''
# Execute sql query
cur = self.conn.cursor()
cur.executemany(sql, db_config_list)
self.conn.commit()
return cur.lastrowid
def query_all(self, query):
"""Query for muliple rows of data"""
cur = self.conn.cursor()
cur.execute(query)
return cur.fetchall()
def query_one_item(self, query):
"""Query for single data point"""
cur = self.conn.cursor()
cur.execute(query)
query_data = cur.fetchone()
return query_data[0]
def get_generation_total_fitness(self):
"""Get each generations total fitness sum from the database """
query_data = self.query_all("SELECT SUM(fitness) FROM data GROUP BY generation;")
# Format the fitness data into one list
formated_query_data = [i[0] for i in query_data]
return formated_query_data
def get_total_generations(self):
"""Get the total generations from the database"""
query_data = self.query_one_item("SELECT COUNT(DISTINCT generation) FROM data;")
return query_data
def get_highest_chromosome(self):
"""Get the highest fitness of each generation"""
query_data = self.query_all("select fitness, max(fitness) from data group by generation")
# Format the fitness data into one list
formated_query_data = [i[0] for i in query_data]
return formated_query_data;
def get_lowest_chromosome(self):
"""Get the lowest fitness of each generation"""
query_data = self.query_all("select fitness, min(fitness) from data group by generation")
# Format the fitness data into one list
formated_query_data = [i[0] for i in query_data]
return formated_query_data;