From 2e16473009176bc4f5a91cb58dbba179ef622a44 Mon Sep 17 00:00:00 2001 From: Neil Traft Date: Sat, 19 Nov 2022 22:32:48 -0500 Subject: [PATCH] Fix bug #255 and add corresponding unit tests. --- neat/graphs.py | 6 ++++++ tests/test_graphs.py | 28 +++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/neat/graphs.py b/neat/graphs.py index 0f3c6fc2..1b321fae 100644 --- a/neat/graphs.py +++ b/neat/graphs.py @@ -73,6 +73,12 @@ def feed_forward_layers(inputs, outputs, connections): layers = [] s = set(inputs) + # First, find any nodes which do not have inputs. + has_input = set(b for (a, b) in connections) # Get the set of all nodes with an incoming edge. + does_not_have_input = required - has_input # Get required nodes that do NOT have an incoming edge. + if does_not_have_input: + layers.append(does_not_have_input) + s = s.union(does_not_have_input) while 1: # Find candidate nodes c for the next layer. These nodes should connect # a node in s to a node not in s. diff --git a/tests/test_graphs.py b/tests/test_graphs.py index b8d1c9b2..94f10c2f 100644 --- a/tests/test_graphs.py +++ b/tests/test_graphs.py @@ -93,19 +93,26 @@ def test_feed_forward_layers(): outputs = [2] connections = [(0, 2), (1, 2)] layers = feed_forward_layers(inputs, outputs, connections) - assert [{2}] == layers + assert [{2}] == layers, f"actually got: {layers}" inputs = [0, 1] outputs = [3] connections = [(0, 2), (1, 2), (2, 3)] layers = feed_forward_layers(inputs, outputs, connections) - assert [{2}, {3}] == layers + assert [{2}, {3}] == layers, f"actually got: {layers}" inputs = [0, 1] outputs = [4] connections = [(0, 2), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] layers = feed_forward_layers(inputs, outputs, connections) - assert [{2}, {3}, {4}] == layers + assert [{2}, {3}, {4}] == layers, f"actually got: {layers}" + + # A graph with dangling input nodes: node 2 has no dependencies, yet some other nodes depend upon it. + inputs = [0, 1] + outputs = [4] + connections = [(1, 3), (2, 3), (2, 4), (3, 4)] + layers = feed_forward_layers(inputs, outputs, connections) + assert [{2}, {3}, {4}] == layers, f"actually got: {layers}" inputs = [0, 1, 2, 3] outputs = [11, 12, 13] @@ -114,8 +121,19 @@ def test_feed_forward_layers(): (8, 11), (8, 12), (8, 9), (9, 10), (7, 10), (10, 12), (10, 13)] layers = feed_forward_layers(inputs, outputs, connections) - assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers + assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers, f"actually got: {layers}" + + # Another graph with dangling input nodes (node 5). + inputs = [0, 1, 2, 3] + outputs = [11, 12, 13] + connections = [(0, 4), (1, 4), (2, 6), (3, 6), (3, 7), + (4, 8), (5, 8), (5, 9), (5, 10), (6, 10), (6, 7), + (8, 11), (8, 12), (8, 9), (9, 10), (7, 10), + (10, 12), (10, 13)] + layers = feed_forward_layers(inputs, outputs, connections) + assert [{5}, {4, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers, f"actually got: {layers}" + # A graph with dangling output nodes. inputs = [0, 1, 2, 3] outputs = [11, 12, 13] connections = [(0, 4), (1, 4), (1, 5), (2, 5), (2, 6), (3, 6), (3, 7), @@ -124,7 +142,7 @@ def test_feed_forward_layers(): (10, 12), (10, 13), (3, 14), (14, 15), (5, 16), (10, 16)] layers = feed_forward_layers(inputs, outputs, connections) - assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers + assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers, f"actually got: {layers}" def test_fuzz_feed_forward_layers():