diff --git a/src/macrogen/graph.py b/src/macrogen/graph.py index 75f66ea..9612d6d 100644 --- a/src/macrogen/graph.py +++ b/src/macrogen/graph.py @@ -75,7 +75,7 @@ def feedback_arcs(self, graph: nx.MultiDiGraph, method=None, light_timeline: Opt elif method == 'baharev': solver = FES_Baharev(graph, prepare_timeline_for_keeping(graph) if light_timeline else None) fes = solver.solve() - self.simple_cycles = solver.simple_cycles + self.simple_cycles |= solver.simple_cycles return list(expand_edges(graph, fes)) else: if light_timeline: diff --git a/src/macrogen/report.py b/src/macrogen/report.py index 6cbb906..a915f2a 100644 --- a/src/macrogen/report.py +++ b/src/macrogen/report.py @@ -21,7 +21,7 @@ from .config import config from .bibliography import BiblSource from .graph import MacrogenesisInfo, EARLIEST, LATEST, DAY -from macrogen.graphutils import pathlink, collapse_timeline +from .graphutils import pathlink, collapse_timeline, expand_edges, in_path from .uris import Reference, Witness, Inscription, UnknownRef, AmbiguousRef from .visualize import write_dot, simplify_graph @@ -650,7 +650,9 @@ def _report_conflict(graphs: MacrogenesisInfo, u, v): counter_path = [] try: counter_path = nx.shortest_path(graphs.dag, v, u, weight='iweight') + involved_cycles = {cycle for cycle in graphs.simple_cycles if in_path((u, v), cycle, True)} relevant_nodes = set(counter_path) + counter_desc = " → ".join(map(_fmt_node, counter_path)) counter_html = f'

Pfad in Gegenrichtung: {counter_desc}

' except nx.NetworkXNoPath: @@ -658,10 +660,16 @@ def _report_conflict(graphs: MacrogenesisInfo, u, v): except nx.NodeNotFound: logger.exception('Node not found!? %s or %s', u, v) counter_html = '' - subgraph: nx.MultiDiGraph = collapse_timeline(nx.subgraph(graphs.base, relevant_nodes)) + subgraph: nx.MultiDiGraph = nx.subgraph(graphs.base, relevant_nodes).copy() + for cycle in involved_cycles: + subgraph.add_edges_from(expand_edges(graphs.base, pairwise(cycle))) + subgraph = collapse_timeline(subgraph) + + if involved_cycles: + counter_html += f"

Teil von mindestens {len(involved_cycles)} einfachen Zyklen

" # Highlight conflicting edges, counter path and the two nodes of the conflicting edge(s) - for v1, v2 in [(u, v)] + list(pairwise(nx.shortest_path(subgraph, v, u))): + for v1, v2 in [(u, v)] + list(pairwise(nx.shortest_path(subgraph, v, u, weight='iweight'))): for k, attr in subgraph.get_edge_data(v1, v2).items(): attr['highlight'] = True subgraph.node[u]['highlight'] = True @@ -693,7 +701,7 @@ def report_conflicts(graphs: MacrogenesisInfo): for index, (u, v, k, attr) in enumerate(sorted(removed_edges, key=lambda t: getattr(t[0], 'index', 0)), start=1): reportfile = _report_conflict(graphs, u, v) table.edge(u, v, attr) - write_html(target / 'conflicts.php', table.format_table(), head='entfernte Kanten') + write_html(target / 'conflicts.php', table.format_table(), head=f'{len(removed_edges)} entfernte Kanten') def report_sources(graphs: MacrogenesisInfo):