计算多条路径时 Dijkstra 算法失败
Dijkstra algorithm fails when calculating multiple paths
我正在尝试为多个节点实施 Dijkstra 算法。例如,我有 x 个要访问的节点,我需要在不更改顺序的情况下创建一条路径来访问每个节点,如果有比这更短的路径也没关系。一开始似乎一切正常,但在超过 2 个节点后,它无法计算路由并耗尽内存。我假设我在这里做了一些糟糕的事情。
对于这个不清楚的问题,我深表歉意,但我不确定如何缩短它。
编辑:问题是当 'verticesToVisit' 列表中添加了 3 个或更多顶点时,Java 在 Java 堆中抛出内存不足 space 异常在 'getShortestPath 方法中,确切的行在下面用注释标记。
无论如何这是我的 类:
Vertice
private List<Edge> adjencies;
private double minDistance = Double.POSITIVE_INFINITY;
private Vertice previous;
public Domicile() {
adjencies = new ArrayList<Edge>();
previous = null;
}
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
}
// sets and gets..
边缘
private Vertice target;
private Vertice source; // Not used in algorithm, just for debugging
private double weight;
public Edge(Vertice argSource, Vertice argTarget, double argWeight) {
source = argSource;
target = argTarget;
weight = argWeight;
}
public Edge(){}
// sets and gets
算法:
public void computePaths(Vertice source) {
source.setMinDistance(0.);
PriorityQueue<Vertice> vertexQueue = new PriorityQueue<Vertice>();
vertexQueue.add(source);
while(!vertexQueue.isEmpty()) {
Vertice u = vertexQueue.poll();
for(Edge e : u.getAdjencies()) {
Vertice v = e.getTarget();
double weight = e.getWeight();
double distanceThroughU = u.getMinDistance() + weight;
if(distanceThroughU < v.getMinDistance()) {
vertexQueue.remove(v);
v.setMinDistance(distanceThroughU);
v.setPrevious(u);
vertexQueue.add(v);
}
}
}
}
///////////////////////
// This method fails //
///////////////////////
public List<Vertice> getShortestPathTo(Vertice target) {
List<Vertice> path = new ArrayList<Vertice>();
for(Vertice vertex = target; vertex != null; vertex = vertex.getPrevious()) {
path.add(vertex); // Java runs out of memory "Java heap size" here
}
Collections.reverse(path);
return path;
}
public void resetAllVertices() {
for(Vertice dom : graph) {
dom.reset();
}
}
public List<String> getRoute() {
List<Vertice> verticesToVisit = dbd.getAllVertice(); // Gets them from database. This part is working.
Collections.sort(verticesToVisit);
List<String> result = new ArrayList<String>();
if(verticesToVisit.isEmpty()) {
return null;
}
else if(patients.size() < 2) {
result.add(verticestoVisit.get(0).getName());
} else {
for(int i = 0; i < verticesToVisit.size()-1; i++) {
Vertices graphDomStart = findFromGraph(verticesToVisit.get(i).getLocationId()); // finds vertice in graph (in db they dont have edges)
Vertice graphDomGoal = findFromGraph(verticesToVisit.get(i+1).getLocationId()); // finds vertice in graph (in db they dont have edges)
computePaths(graphDomStart); // exception is tracked from here
result.add(formatAddress(getShortestPathTo(graphDomGoal)));
resetAllVertices();
}
}
return result;
}
private Domicile findFromGraph(int locationId) {
for(Domicile dom : graph) {
if(dom.getLocationId() == locationId) {
return dom;
}
}
return null;
}
谢谢你,抱歉代码太长了。
在你的重置函数中:
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
}
我建议你也重置以前的
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
this.previous = null;
}
否则在向后追踪路径时会出现无限循环。
我正在尝试为多个节点实施 Dijkstra 算法。例如,我有 x 个要访问的节点,我需要在不更改顺序的情况下创建一条路径来访问每个节点,如果有比这更短的路径也没关系。一开始似乎一切正常,但在超过 2 个节点后,它无法计算路由并耗尽内存。我假设我在这里做了一些糟糕的事情。
对于这个不清楚的问题,我深表歉意,但我不确定如何缩短它。
编辑:问题是当 'verticesToVisit' 列表中添加了 3 个或更多顶点时,Java 在 Java 堆中抛出内存不足 space 异常在 'getShortestPath 方法中,确切的行在下面用注释标记。
无论如何这是我的 类:
Vertice
private List<Edge> adjencies;
private double minDistance = Double.POSITIVE_INFINITY;
private Vertice previous;
public Domicile() {
adjencies = new ArrayList<Edge>();
previous = null;
}
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
}
// sets and gets..
边缘
private Vertice target;
private Vertice source; // Not used in algorithm, just for debugging
private double weight;
public Edge(Vertice argSource, Vertice argTarget, double argWeight) {
source = argSource;
target = argTarget;
weight = argWeight;
}
public Edge(){}
// sets and gets
算法:
public void computePaths(Vertice source) {
source.setMinDistance(0.);
PriorityQueue<Vertice> vertexQueue = new PriorityQueue<Vertice>();
vertexQueue.add(source);
while(!vertexQueue.isEmpty()) {
Vertice u = vertexQueue.poll();
for(Edge e : u.getAdjencies()) {
Vertice v = e.getTarget();
double weight = e.getWeight();
double distanceThroughU = u.getMinDistance() + weight;
if(distanceThroughU < v.getMinDistance()) {
vertexQueue.remove(v);
v.setMinDistance(distanceThroughU);
v.setPrevious(u);
vertexQueue.add(v);
}
}
}
}
///////////////////////
// This method fails //
///////////////////////
public List<Vertice> getShortestPathTo(Vertice target) {
List<Vertice> path = new ArrayList<Vertice>();
for(Vertice vertex = target; vertex != null; vertex = vertex.getPrevious()) {
path.add(vertex); // Java runs out of memory "Java heap size" here
}
Collections.reverse(path);
return path;
}
public void resetAllVertices() {
for(Vertice dom : graph) {
dom.reset();
}
}
public List<String> getRoute() {
List<Vertice> verticesToVisit = dbd.getAllVertice(); // Gets them from database. This part is working.
Collections.sort(verticesToVisit);
List<String> result = new ArrayList<String>();
if(verticesToVisit.isEmpty()) {
return null;
}
else if(patients.size() < 2) {
result.add(verticestoVisit.get(0).getName());
} else {
for(int i = 0; i < verticesToVisit.size()-1; i++) {
Vertices graphDomStart = findFromGraph(verticesToVisit.get(i).getLocationId()); // finds vertice in graph (in db they dont have edges)
Vertice graphDomGoal = findFromGraph(verticesToVisit.get(i+1).getLocationId()); // finds vertice in graph (in db they dont have edges)
computePaths(graphDomStart); // exception is tracked from here
result.add(formatAddress(getShortestPathTo(graphDomGoal)));
resetAllVertices();
}
}
return result;
}
private Domicile findFromGraph(int locationId) {
for(Domicile dom : graph) {
if(dom.getLocationId() == locationId) {
return dom;
}
}
return null;
}
谢谢你,抱歉代码太长了。
在你的重置函数中:
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
}
我建议你也重置以前的
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
this.previous = null;
}
否则在向后追踪路径时会出现无限循环。