是否可以使用JGrapht在有向边加权图中找到负循环?我查看了Javadocs并发现我可以使用CycleDetector
来检测周期,但不是特定的负周期。 CycleDetector找到周期,但是如果不以某种方式探索它们,你无法判断它们是否是否定的。谢谢!
答案 0 :(得分:2)
您可以尝试使用BellmanFordShortestPath
,但是如果您查找从一个顶点到自身的路径,它将找不到循环,因为每个顶点都以权重0
隐式连接到自身。
DefaultDirectedWeightedGraph<String, DefaultWeightedEdge> directedGraph = new DefaultDirectedWeightedGraph<>(DefaultWeightedEdge.class);
...
BellmanFordShortestPath<String, DefaultWeightedEdge> algorithm = new BellmanFordShortestPath(graph);
GraphPath<String, DefaultWeightedEdge> path = algorithm.getPath(node1, node1);
int length = path.getLength(); // returns 0
double weight = path.getWeight(); // returns 0.0
我能找到的最好的是org.jgrapht.alg.cycle
中的算法,这些算法可以为您提供所有周期,然后您必须计算周期内路径的总重量。
private boolean hasNegativeLoop(DefaultDirectedWeightedGraph<String, DefaultWeightedEdge> graph){
SzwarcfiterLauerSimpleCycles<String, DefaultWeightedEdge> cycleDetector = new SzwarcfiterLauerSimpleCycles<>(graph);
List<List<String>> cycles = cycleDetector.findSimpleCycles();
for (List<String> cycle : cycles){
double cycleWeight = getCycleWeight(graph, cycle);
if(cycleWeight < 0) return true;
}
return false;
}
private double getCycleWeight(DefaultDirectedWeightedGraph<String, DefaultWeightedEdge> graph, List<String> cycle) {
double totalWeight = 0;
for(int i = 1; i < cycle.size(); i++){
double weight = graph.getEdgeWeight(graph.getEdge(cycle.get(i-1), cycle.get(i)));
totalWeight += weight;
}
double weightBackToStart = graph.getEdgeWeight(graph.getEdge(cycle.get(cycle.size()-1), cycle.get(0)));
return totalWeight + weightBackToStart;
}
与Bellman Ford负循环检测相比,这种方式效率更低,但可以作为实施的参考。
答案 1 :(得分:1)
一般情况下,您可以使用BellmanFordShortestPath
来检查图表中的负循环,尽管不存在最短路径只会告诉您是否存在至少一个负循环。我没有正确看待JgraphT中的BellmanFordShortestPath
实现,因此我无法为您提供代码。
除此之外,在https://cs.stackexchange.com/questions/6919/getting-negative-cycle-using-bellman-ford中有一篇简洁的论文。 该论文的工作链接应为:
所以如果其他所有方法都失败了,你至少可以使用像DefaultDirectedWeightedGraph