From 24031a87b60ab08fd3aed74e552aeda2c2e64c4c Mon Sep 17 00:00:00 2001 From: khansadaoudi <hk_daoudi@esi.dz> Date: Fri, 3 Jan 2025 15:00:41 +0100 Subject: [PATCH] fix detect cycle algorithm based on dfs algorithm --- app/trees/controller.py | 2 +- app/trees/service.py | 44 ++++++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/app/trees/controller.py b/app/trees/controller.py index fda6f9b..2f0909f 100644 --- a/app/trees/controller.py +++ b/app/trees/controller.py @@ -202,7 +202,7 @@ def post(self, project_name: str): else: #for the moment if sud we check only the cycles cycle_nodes = TreeService.check_cycle(data) if cycle_nodes: - error_message = 'Non tree structure, tokens: ' + ', '.join([str(tuple_nodes) for tuple_nodes in cycle_nodes]) + ' form a cycle' + error_message = 'Non tree structure, tokens: ' + ', '.join([str(list_nodes) for list_nodes in cycle_nodes]) + ' form a cycle' return { "message": error_message, "passed": False } else: return { "message": '', "passed": True } diff --git a/app/trees/service.py b/app/trees/service.py index 90fa0e0..fc3d509 100644 --- a/app/trees/service.py +++ b/app/trees/service.py @@ -13,6 +13,7 @@ class TreeService: """this class contains all methods that deal with trees""" + @staticmethod def check_cycle(conll): """check if there is a cycle in the graph @@ -21,27 +22,52 @@ def check_cycle(conll): conll (str): user tree Returns: - cycle_nodes (List[Tuple(node1, node2)]) + cycle_nodes (List[List[str]]): list of cycles nodes """ sentence_json = sentenceConllToJson(conll) nodes_json = sentence_json['treeJson']['nodesJson'] nodes_children_list = {} for index in nodes_json: + if index not in nodes_children_list.keys(): + nodes_children_list[index] = [] token_head = str(nodes_json[index]['HEAD']) if token_head not in nodes_children_list.keys(): nodes_children_list[token_head] = [index] else: nodes_children_list[token_head].append(index) + print(nodes_children_list) + + # check if there is a cycle in the tree using recursive dfs + def dfs_recursive(first_node, visited, stack, path): + visited.add(first_node) + stack.add(first_node) + path.append(first_node) + + for child in nodes_children_list[first_node]: + if child not in visited: + if dfs_recursive(child, visited, stack, path): + return True + elif child in stack: + path.append(child) + return True + stack.remove(first_node) + path.pop() + return False - cycle_nodes = [] - for node, list_children in nodes_children_list.items(): - for child in list_children: - if child in nodes_children_list.keys() and node in nodes_children_list[child]: - cycle_nodes.append((child, node)) - - return list(set(tuple(sorted(nodes_tuple)) for nodes_tuple in cycle_nodes)) - + visited = set() + stack = set() + cycle_nodes = [] + + for node in nodes_children_list: + if node not in visited: + path = [] + if dfs_recursive(node, visited, stack, path): + cycle_start_index = cycle_nodes.index(path[-1]) if path[-1] in cycle_nodes else 0 + cycle_nodes.append(path[cycle_start_index:]) + + return cycle_nodes + @staticmethod def samples_to_trees(sample_trees, sample_name): """