Skip to content

Commit

Permalink
#130 Identifying backward edges in a cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
jimbethancourt committed Feb 11, 2025
1 parent 4321870 commit 20e2312
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.hjug.cycledetector;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.alg.cycle.TarjanSimpleCycles;

import java.util.*;

/*
Prompt:
provide a java implementation of an algorithm that will identify all backward edges in a cycle
identified by JGraphT that is part of a graph with weighted edges that have integer weights.
If there are multiple backward edges, order the backward edges in the order they should be removed.
*/
public class BackwardEdgesFinder<V> {

private final Graph<V, DefaultWeightedEdge> graph;

public BackwardEdgesFinder(Graph<V, DefaultWeightedEdge> graph) {
this.graph = graph;
}

public List<DefaultWeightedEdge> findBackwardEdges() {
TarjanSimpleCycles<V, DefaultWeightedEdge> tarjan = new TarjanSimpleCycles<>(graph);
List<List<V>> cycles = tarjan.findSimpleCycles();
List<DefaultWeightedEdge> backwardEdges = new ArrayList<>();

for (List<V> cycle : cycles) {
Set<DefaultWeightedEdge> cycleEdges = new HashSet<>();
for (int i = 0; i < cycle.size(); i++) {
V source = cycle.get(i);
V target = cycle.get((i + 1) % cycle.size());
DefaultWeightedEdge edge = graph.getEdge(source, target);
if (edge != null) {
cycleEdges.add(edge);
}
}

for (DefaultWeightedEdge edge : cycleEdges) {
if (isBackwardEdge(edge, cycle)) {
backwardEdges.add(edge);
}
}
}

backwardEdges.sort(Comparator.comparingDouble(graph::getEdgeWeight));
return backwardEdges;
}

private boolean isBackwardEdge(DefaultWeightedEdge edge, List<V> cycle) {
V source = graph.getEdgeSource(edge);
V target = graph.getEdgeTarget(edge);
int sourceIndex = cycle.indexOf(source);
int targetIndex = cycle.indexOf(target);
return sourceIndex > targetIndex;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.hjug.cycledetector;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleDirectedWeightedGraph;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.List;

class BackwardEdgesFinderTest {

@Test
void findBackwardEdges() {
Graph<String, DefaultWeightedEdge> graph = new SimpleDirectedWeightedGraph<>(DefaultWeightedEdge.class);

graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");

graph.setEdgeWeight(graph.addEdge("A", "B"), 1);
graph.setEdgeWeight(graph.addEdge("B", "C"), 2);
graph.setEdgeWeight(graph.addEdge("C", "D"), 3);
graph.setEdgeWeight(graph.addEdge("D", "A"), 4);
graph.setEdgeWeight(graph.addEdge("C", "A"), 5);

BackwardEdgesFinder<String> finder = new BackwardEdgesFinder<>(graph);
List<DefaultWeightedEdge> backwardEdges = finder.findBackwardEdges();

Assertions.assertEquals("(D : A)", backwardEdges.get(0).toString());
Assertions.assertEquals(4, graph.getEdgeWeight(backwardEdges.get(0)));

Assertions.assertEquals("(C : A)", backwardEdges.get(1).toString());
Assertions.assertEquals(5, graph.getEdgeWeight(backwardEdges.get(1)));
}

}

0 comments on commit 20e2312

Please sign in to comment.