From e22a2736096393f7d6b480455e87b0626fc1f654 Mon Sep 17 00:00:00 2001 From: paumann Date: Sun, 16 Jul 2023 00:40:47 +0200 Subject: [PATCH] viz --- Abschlussprojekt/genome.py | 7 ++++- Abschlussprojekt/neat.ipynb | 48 +++++++++++++++++++---------- Abschlussprojekt/requirements.txt | 1 + Abschlussprojekt/visualization.py | 51 ++++++++++++++++++++----------- 4 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 Abschlussprojekt/requirements.txt diff --git a/Abschlussprojekt/genome.py b/Abschlussprojekt/genome.py index 645d3cd..f59c64d 100644 --- a/Abschlussprojekt/genome.py +++ b/Abschlussprojekt/genome.py @@ -80,6 +80,11 @@ class Genome: for _ in range(outputs): genome.add_node(node_type=NodeType.OUTPUT) + # Fully connect + for i in range(inputs): + for o in range(inputs, inputs + outputs): + genome.add_connection(i, o, weight=1) + return genome @@ -112,7 +117,7 @@ def _mutate_add_node(genome: Genome) -> None: # Find connection to split try: - connection = choice(list(genome.connections.values())) + connection = choice([node for node in genome.connections.values() if not node.disabled]) except IndexError: return connection.disabled = True diff --git a/Abschlussprojekt/neat.ipynb b/Abschlussprojekt/neat.ipynb index 57d1ec3..09215d3 100644 --- a/Abschlussprojekt/neat.ipynb +++ b/Abschlussprojekt/neat.ipynb @@ -6,7 +6,7 @@ "metadata": {}, "outputs": [], "source": [ - "from genome import Genome\n", + "from genome import Genome, mutate\n", "import visualization" ] }, @@ -15,16 +15,9 @@ "execution_count": 2, "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ConnectionGene(nodes=(0, 4), weight=0.5, innovation_no=0, disabled=False)\n" - ] - }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -34,15 +27,38 @@ } ], "source": [ - "\n", "g1 = Genome.new(3, 2)\n", - "g1.add_node()\n", - "g1.add_node()\n", - "g1.add_node()\n", - "g1.add_connection(g1.nodes[0], g1.nodes[4], 0.5)\n", "\n", - "visualization.genome(g1)\n", - "\n" + "visualization.genome(g1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ConnectionGene(nodes=(0, 4), weight=1, innovation_no=1, disabled=False)\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mutate(g1)\n", + "\n", + "visualization.genome(g1)" ] } ], diff --git a/Abschlussprojekt/requirements.txt b/Abschlussprojekt/requirements.txt new file mode 100644 index 0000000..1b35143 --- /dev/null +++ b/Abschlussprojekt/requirements.txt @@ -0,0 +1 @@ +pygraphviz \ No newline at end of file diff --git a/Abschlussprojekt/visualization.py b/Abschlussprojekt/visualization.py index 1b25709..d372b12 100644 --- a/Abschlussprojekt/visualization.py +++ b/Abschlussprojekt/visualization.py @@ -1,3 +1,5 @@ +import itertools + import matplotlib.pyplot as plt import networkx as nx import numpy as np @@ -5,8 +7,17 @@ import numpy as np from genome import Genome, NodeType, mutate +def _find_layer(g: nx.DiGraph, hidden_node: int, inputs: list[int]) -> int: + paths = [] + for input_node in inputs: + paths += list(nx.all_simple_paths(g, input_node, hidden_node)) + + path_lengths = [len(path) for path in paths] + return max(path_lengths) + + def genome(genome: Genome): - graph = nx.Graph() + graph = nx.DiGraph() # Add nodes for node in genome.nodes.keys(): @@ -20,33 +31,37 @@ def genome(genome: Genome): from_node, to_node = connection.nodes graph.add_edge(from_node, to_node, weight=connection.weight) - # Make sure that input and output nodes are fixed - pos = nx.spring_layout(graph) - x = [v[0] for v in pos.values()] - min_x, max_x = min(x), max(x) - y = [v[1] for v in pos.values()] - min_y, max_y = min(y), max(y) + inputs = [node.id for node in genome.nodes.values() if node.type == NodeType.INPUT] + hidden = [node.id for node in genome.nodes.values() if node.type == NodeType.HIDDEN] + outputs = [node.id for node in genome.nodes.values() if node.type == NodeType.OUTPUT] - inputs = [node for node in genome.nodes.values() if node.type == NodeType.INPUT] - outputs = [node for node in genome.nodes.values() if node.type == NodeType.OUTPUT] + for input_node in inputs: + graph.nodes[input_node]["layer"] = 0 - for node, y in zip(inputs, np.linspace(min_y, max_y, len(inputs))): - pos[node.id] = np.array([min_x * 1.5, y]) + max_layer = 1 + for hidden_node in hidden: + layer = _find_layer(graph, hidden_node, inputs) + max_layer = max(layer, max_layer) + graph.nodes[hidden_node]["layer"] = layer - for node, y in zip(outputs, np.linspace(min_y, max_y, len(outputs))): - pos[node.id] = np.array([max_x * 1.5, y]) + for output_node in outputs: + graph.nodes[output_node]["layer"] = max_layer + 1 plt.subplot() - nx.draw_networkx(graph, pos) + pos = nx.multipartite_layout(graph, subset_key="layer") + nx.draw_networkx_nodes(graph, pos, nodelist=inputs, label=inputs, node_color="#ff0000") + nx.draw_networkx_nodes(graph, pos, nodelist=hidden, label=hidden, node_color="#00ff00") + nx.draw_networkx_nodes(graph, pos, nodelist=outputs, label=outputs, node_color="#0000ff") + nx.draw_networkx_edges(graph, pos) if __name__ == "__main__": g1 = Genome.new(3, 2) - g1.add_node() - g1.add_node() - g1.add_node() g1.add_connection(0, 4, 0.5) - mutate(g1) + mutate(g1) + mutate(g1) + + # mutate(g1) genome(g1) plt.show()