Skip to content
This repository has been archived by the owner on Jan 2, 2024. It is now read-only.

Commit

Permalink
Merge pull request #750 from Avaiga/feature/fix_is_consistent
Browse files Browse the repository at this point in the history
Fix is_consistent bug on sequence
  • Loading branch information
jrobinAV authored Sep 7, 2023
2 parents 8052ba8 + 71629d5 commit 4dd7fe8
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 53 deletions.
1 change: 0 additions & 1 deletion src/taipy/core/scenario/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,6 @@ def get_simple_label(self) -> str:

def _is_consistent(self) -> bool:
dag = self._build_dag()

if dag.number_of_nodes() == 0:
return True
if not nx.is_directed_acyclic_graph(dag):
Expand Down
30 changes: 9 additions & 21 deletions src/taipy/core/sequence/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,30 +128,18 @@ def properties(self):

def _is_consistent(self) -> bool:
dag = self._build_dag()
if dag.number_of_nodes() == 0:
return True
if not nx.is_directed_acyclic_graph(dag):
return False
if dag.number_of_nodes() != 0 and not nx.is_weakly_connected(dag):
if not nx.is_weakly_connected(dag):
return False
for left_node, right_node in dag.edges:
if (isinstance(left_node, DataNode) and isinstance(right_node, Task)) or (
isinstance(left_node, Task) and isinstance(right_node, DataNode)
):
continue
return False

current_node_type: Any = None
for nodes in nx.topological_generations(dag):
for node in nodes:
if not current_node_type:
if isinstance(node, Task):
current_node_type = Task
elif isinstance(node, DataNode):
current_node_type = DataNode
else:
return False
if not isinstance(node, current_node_type):
return False

if issubclass(current_node_type, Task):
current_node_type = DataNode
elif issubclass(current_node_type, DataNode):
current_node_type = Task
else:
return False
return True

def _get_tasks(self) -> Dict[str, Task]:
Expand Down
75 changes: 44 additions & 31 deletions tests/core/sequence/test_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,55 +111,68 @@ def test_check_consistency():
assert sequence_1._is_consistent()

input_2 = InMemoryDataNode("foo", Scope.SCENARIO)
output_2 = InMemoryDataNode("foo", Scope.SCENARIO)
task_2 = Task("foo", {}, print, [input_2], [output_2], TaskId("task_id_2"))
output_2 = InMemoryDataNode("bar", Scope.SCENARIO)
task_2 = Task("tfoo", {}, print, [input_2], [output_2], TaskId("task_id_2"))
sequence_2 = Sequence({}, [task_2], "name_2")
assert sequence_2._is_consistent()

data_node_3 = InMemoryDataNode("foo", Scope.SCENARIO)
task_3 = Task("foo", {}, print, [data_node_3], [data_node_3], TaskId("task_id_3"))
task_3 = Task("tfoo", {}, print, [data_node_3], [data_node_3], TaskId("task_id_3"))
sequence_3 = Sequence({}, [task_3], "name_3")
assert not sequence_3._is_consistent() # Not a dag

input_4 = InMemoryDataNode("foo", Scope.SCENARIO)
output_4 = InMemoryDataNode("foo", Scope.SCENARIO)
task_4_1 = Task("foo", {}, print, [input_4], [output_4], TaskId("task_id_4_1"))
task_4_2 = Task("bar", {}, print, [output_4], [input_4], TaskId("task_id_4_2"))
output_4 = InMemoryDataNode("bar", Scope.SCENARIO)
task_4_1 = Task("tfoo", {}, print, [input_4], [output_4], TaskId("task_id_4_1"))
task_4_2 = Task("tbar", {}, print, [output_4], [input_4], TaskId("task_id_4_2"))
sequence_4 = Sequence({}, [task_4_1, task_4_2], "name_4")
assert not sequence_4._is_consistent() # Not a Dag

class FakeDataNode:
config_id = "config_id_of_a_fake_dn"

input_5 = DataNode("foo", Scope.SCENARIO, "input_id_5")
output_5 = DataNode("foo", Scope.SCENARIO, "output_id_5")
task_5_1 = Task("foo", {}, print, [input_5], [output_5], TaskId("task_id_5_1"))
task_5_2 = Task("bar", {}, print, [output_5], [FakeDataNode()], TaskId("task_id_5_2"))
sequence_5 = Sequence({}, [task_5_1, task_5_2], "name_5")
assert not sequence_5._is_consistent()

intermediate_6 = DataNode("foo", Scope.SCENARIO, "intermediate_id_6")
output_6 = DataNode("foo", Scope.SCENARIO, "output_id_6")
task_6_1 = Task("foo", {}, print, [], [intermediate_6], TaskId("task_id_6_1"))
task_6_2 = Task("foo", {}, print, [intermediate_6], [output_6], TaskId("task_id_6_2"))
sequence_6 = Sequence({}, [task_6_1, task_6_2], "name_6")
assert sequence_6._is_consistent()

input_7 = DataNode("foo", Scope.SCENARIO, "output_id_7")
input_6 = DataNode("foo", Scope.SCENARIO, "input_id_5")
output_6 = DataNode("bar", Scope.SCENARIO, "output_id_5")
task_6_1 = Task("tfoo", {}, print, [input_6], [output_6], TaskId("task_id_5_1"))
task_6_2 = Task("tbar", {}, print, [output_6], [FakeDataNode()], TaskId("task_id_5_2"))
sequence_6 = Sequence({}, [task_6_1, task_6_2], "name_5")
assert not sequence_6._is_consistent() # Not a DataNode

intermediate_7 = DataNode("foo", Scope.SCENARIO, "intermediate_id_7")
task_7_1 = Task("foo", {}, print, [input_7], [intermediate_7], TaskId("task_id_7_1"))
task_7_2 = Task("foo", {}, print, [intermediate_7], [], TaskId("task_id_7_2"))
output_7 = DataNode("bar", Scope.SCENARIO, "output_id_7")
task_7_1 = Task("tfoo", {}, print, [], [intermediate_7], TaskId("task_id_7_1"))
task_7_2 = Task("tbar", {}, print, [intermediate_7], [output_7], TaskId("task_id_7_2"))
sequence_7 = Sequence({}, [task_7_1, task_7_2], "name_7")
assert sequence_7._is_consistent()

input_8 = DataNode("foo", Scope.SCENARIO, "input_id_8")
output_8 = DataNode("foo", Scope.SCENARIO, "output_id_8")
input_9 = DataNode("foo", Scope.SCENARIO, "input_id_9")
output_9 = DataNode("foo", Scope.SCENARIO, "output_id_9")
task_8_1 = Task("foo", {}, print, [input_8], [output_8], TaskId("task_id_8_1"))
task_8_2 = Task("foo", {}, print, [input_9], [output_9], TaskId("task_id_8_2"))
sequence_7 = Sequence({}, [task_8_1, task_8_2], "name_7")
assert not sequence_7._is_consistent()
input_8 = DataNode("foo", Scope.SCENARIO, "output_id_8")
intermediate_8 = DataNode("bar", Scope.SCENARIO, "intermediate_id_8")
task_8_1 = Task("tfoo", {}, print, [input_8], [intermediate_8], TaskId("task_id_8_1"))
task_8_2 = Task("tbar", {}, print, [intermediate_8], [], TaskId("task_id_8_2"))
sequence_8 = Sequence({}, [task_8_1, task_8_2], "name_8")
assert sequence_8._is_consistent()

input_9_1 = DataNode("foo", Scope.SCENARIO, "input_id_9_1")
output_9_1 = DataNode("bar", Scope.SCENARIO, "output_id_9_1")
input_9_2 = DataNode("baz", Scope.SCENARIO, "input_id_9_2")
output_9_2 = DataNode("qux", Scope.SCENARIO, "output_id_9_2")
task_9_1 = Task("tfoo", {}, print, [input_9_1], [output_9_1], TaskId("task_id_9_1"))
task_9_2 = Task("tbar", {}, print, [input_9_2], [output_9_2], TaskId("task_id_9_2"))
sequence_9 = Sequence({}, [task_9_1, task_9_2], "name_9")
assert not sequence_9._is_consistent() # Not connected

input_10_1 = DataNode("foo", Scope.SCENARIO, "output_id_10_1")
intermediate_10_1 = DataNode("bar", Scope.SCENARIO, "intermediate_id_10_1")
intermediate_10_2 = DataNode("baz", Scope.SCENARIO, "intermediate_id_10_2")
output_10 = DataNode("qux", Scope.SCENARIO, "output_id_10")
post_10 = DataNode("quux", Scope.SCENARIO, "post_id_10")
task_10_1 = Task("tfoo", {}, print, [input_10_1], [intermediate_10_1], TaskId("task_id_10_1"))
task_10_2 = Task("tbar", {}, print, [], [intermediate_10_2], TaskId("task_id_10_2"))
task_10_3 = Task("tbaz", {}, print, [intermediate_10_1, intermediate_10_2], [output_10], TaskId("task_id_10_3"))
task_10_4 = Task("tqux", {}, print, [output_10], [post_10], TaskId("task_id_10_4"))
task_10_5 = Task("tquux", {}, print, [output_10], [], TaskId("task_id_10_5"))
sequence_10 = Sequence({}, [task_10_1, task_10_2, task_10_3, task_10_4, task_10_5], "name_10")
assert sequence_10._is_consistent()


def test_get_sorted_tasks():
Expand Down

0 comments on commit 4dd7fe8

Please sign in to comment.