Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.envrc/
.env/
.envrc
.venv/
.vscode/
*local.*
__pycache__/

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ authors = [
]
description = "Tool for visualising results of evolutionary computation conducted with the ecrs library"
readme = "README.md"
requires-python = ">=3.9"
requires-python = ">=3.10"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
Expand Down
17 changes: 17 additions & 0 deletions src/ectoolkit/individual.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import json

class Individual:
__slots__ = ('chromosome', 'fitness')

def __init__(self, chromosome=None, fitness=None) -> None:
self.chromosome = chromosome
self.fitness = fitness

@staticmethod
def from_json(json_str: str) -> 'Individual':
print(f"Parsing json: {json_str}")
return json.loads(json_str)

@staticmethod
def from_dict(obj: dict[str]) -> 'Individual':
return Individual(obj['chromosome'], obj['fitness'])
116 changes: 115 additions & 1 deletion src/ectoolkit/main.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,116 @@
import os
import os.path as path
import csv
import json

import numpy as np
import matplotlib.pyplot as plt

from records import *
from individual import Individual

EVENT_TYPE_NEW_GEN = 'new_gen'
EVENT_TYPE_INIT_GEN = 'init_gen'
EVENT_TYPE_NEW_BEST = 'new_best'
EVENT_TYPE_END = 'end'

def average_fitness_in_pop(population: list[Individual]) -> float:
return np.average(list(map(lambda idv: idv.fitness, population)))

def plot_avg_fitness_in_pop(generation_records: list[tuple[int, int, list[Individual]]], axes: plt.Axes):
first_gen = generation_records[0][1]
last_gen = generation_records[-1][1]

x_data = np.arange(first_gen, last_gen + 1, 1)
y_data = [average_fitness_in_pop(record[2]) for record in generation_records]

axes.plot(x_data, y_data)


def dispatch_record(record: list[str],
new_gen_list: list,
init_gen_list: list,
new_best_list: list,
end_list: list):
# print(record)
match record:
case ['new_gen', dur, gen, *population]:
print(EVENT_TYPE_NEW_GEN)
print(type(population), len(population), type(population[0]))
# raise ValueError
population = json.loads(population[0])
individuals = [Individual.from_json(idv_json) for idv_json in population]
new_gen_list.append((int(dur), int(gen), individuals))
raise ValueError

case ['new_best', dur, gen, indiv]:
print(EVENT_TYPE_NEW_BEST)

case ['init_gen', *population]:
print(EVENT_TYPE_INIT_GEN)

case ['end', dur, gen, best, *population]:
print(EVENT_TYPE_END)

case _:
raise ValueError(f"Unhandled record type: {record[0]}")



def parse_csv_probe_output(filename: str) -> list:
new_gen_list = [ ]
with open(filename, 'r') as input_file:
reader = csv.reader(input_file, delimiter='|')

# I assume here there are no headers
for line in reader:
dispatch_record(line, new_gen_list, None, None, None)

return new_gen_list


def main():
# Read input file name
input_file = "local.data/local.input"

if not path.isfile(input_file):
print(f"Provided input file path: {input_file} does not point to a valid file")
print(f"cwd: {os.getcwd()}")
return 1

# Read output directory
output_dir = "local.data"

if not path.isdir(output_dir):
print(f"Provided output directory path: {output_dir} does not point to a valid directory")
print(f"cwd: {os.getcwd()}")
return 1

individual = Individual([0, 0, 0], 42)

print(json.dumps({
"chromosome": [0.0, 1.0, 2.0],
"fitness": 42
}))
return

# Read & parse input file
new_gen_list = parse_csv_probe_output(input_file)

fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(12, 7))

plot_avg_fitness_in_pop(new_gen_list, axes)

fig.show()

# Pass records to visualizer

# Run visualizer

# (Optional) Print some summary

pass


if __name__ == "__main__":
print("Hello world")
main()
31 changes: 31 additions & 0 deletions src/ectoolkit/records.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# EVENT_TYPE_NEW_GEN = 'new_gen'
# EVENT_TYPE_INIT_GEN = 'init_gen'
# EVENT_TYPE_NEW_BEST = 'new_best'
# EVENT_TYPE_END = 'end'


# class Record(object):
# __slots__ = ('type')

# def __init__(self, type: str) -> None:
# self.type = type


# class NewGenRecord(Record):
# def __init__(self) -> None:
# super().__init__(EVENT_TYPE_NEW_GEN)


# class InitGenRecord(Record):
# def __init__(self) -> None:
# super().__init__(EVENT_TYPE_INIT_GEN)


# class NewBestRecord(Record):
# def __init__(self) -> None:
# super().__init__(EVENT_TYPE_NEW_BEST)


# class EndRecord(Record):
# def __init__(self) -> None:
# super().__init__(EVENT_TYPE_END)