From 3028faf0c0fab15dc4afdf4522ca09ec2e04bb51 Mon Sep 17 00:00:00 2001 From: Thorsten Vitt Date: Mon, 10 Sep 2018 23:08:29 +0200 Subject: [PATCH] Adding back edges that are removed by Eades but that do not induce a cycle in the DAG --- graph.py | 17 ++++++++++++++--- report.py | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/graph.py b/graph.py index 5b46f0c..7d1a6cc 100644 --- a/graph.py +++ b/graph.py @@ -282,16 +282,27 @@ def macrogenesis_graphs() -> MacrogenesisInfo: len(selfloops), ", ".join(str(u) for u, v, k, attr in selfloops)) all_conflicting_edges.extend(selfloops) - logger.info('Marking %d conflicting edges for deletion', len(all_conflicting_edges)) - mark_edges_to_delete(base, all_conflicting_edges) - logger.info('Building DAG from remaining data') dag = working.copy() dag.remove_edges_from(all_conflicting_edges) + if not nx.is_directed_acyclic_graph(dag): logger.error('After removing %d conflicting edges, the graph is still not a DAG!', len(all_conflicting_edges)) cycles = list(nx.simple_cycles(dag)) logger.error('It contains %d simple cycles', len(cycles)) + else: + logging.info('Double-checking removed edges ...') + for u, v, k, attr in list(all_conflicting_edges): + dag.add_edge(u, v, **attr) + if nx.is_directed_acyclic_graph(dag): + all_conflicting_edges.remove((u,v,k,attr)) + logging.info('Added edge %s -> %s back without introducing a cycle.', u, v) + else: + dag.remove_edge(u, v) + + logger.info('Marking %d conflicting edges for deletion', len(all_conflicting_edges)) + mark_edges_to_delete(base, all_conflicting_edges) + logger.info('Removed %d of the original %d edges', len(all_conflicting_edges), len(working.edges)) diff --git a/report.py b/report.py index 47159e7..375fc68 100644 --- a/report.py +++ b/report.py @@ -377,7 +377,7 @@ def __init__(self, **table_attrs): .column('XML', _fmt_xml)) def edge(self, u: Reference, v: Reference, attr: Dict[str,object]): - classes = [attr['kind']] if 'kind' in attr else [] + classes = [attr['kind']] if 'kind' in attr and attr['kind'] is not None else ['unknown-kind'] if attr.get('ignore', False): classes.append('ignore') if attr.get('delete', False): classes.append('delete') self.row((