C 所有对最短路径问题的最快实现?
我有一个加权图30k节点160k边,没有负权重。 我想计算从所有节点到其他节点的所有最短路径。 我想我不能假设任何特定的启发式方法来简化这个问题 我尝试使用Dijkstra C实现,即针对单个最短路径问题,为我的30个节点调用函数dijkstras()。正如你所能想象的,这需要时间。目前我没有时间自己编写和调试代码,我必须尽快计算这些路径,并将它们存储在数据库中,因此我正在寻找另一种更快的解决方案,您有什么建议吗 我必须在最新的macbook pro上运行它,使用8GB内存,我想找到一个不超过24小时完成计算的解决方案 提前多谢C 所有对最短路径问题的最快实现?,c,algorithm,implementation,dijkstra,shortest-path,C,Algorithm,Implementation,Dijkstra,Shortest Path,我有一个加权图30k节点160k边,没有负权重。 我想计算从所有节点到其他节点的所有最短路径。 我想我不能假设任何特定的启发式方法来简化这个问题 我尝试使用Dijkstra C实现,即针对单个最短路径问题,为我的30个节点调用函数dijkstras()。正如你所能想象的,这需要时间。目前我没有时间自己编写和调试代码,我必须尽快计算这些路径,并将它们存储在数据库中,因此我正在寻找另一种更快的解决方案,您有什么建议吗 我必须在最新的macbook pro上运行它,使用8GB内存,我想找到一个不超过2
Eugenio你的图有什么特殊的结构吗?图是平面图(或接近平面图) 我建议不要尝试存储所有最短路径,一个相当密集的编码(30k^2“下一步去哪里”条目)将占用7 Gig的内存
什么是应用程序?当你需要找到一条特定的最短路径时,你确定双向Dijkstra(或者a*,如果你有启发式的话)的速度不够快吗?算法怎么样?如果你可以将算法修改为多线程的,你可能可以在24小时内完成它
第一个节点可能需要1分钟以上的时间。但是,第15000个节点应该只需要一半的时间,因为您将计算到所有之前节点的最短路径。我查看了您在评论中发布的Dijkstra算法链接,我相信这是您效率低下的原因。在Dijkstra的内部循环中,它使用了一种非常未优化的方法来确定下一步要探索哪个节点(每一步对每个节点进行线性扫描)。有问题的代码出现在两个地方。第一个是此代码,它尝试查找下一个要操作的节点:
mini = -1;
for (i = 1; i <= n; ++i)
if (!visited[i] && ((mini == -1) || (d[i] < d[mini])))
mini = i;
mini=-1;
对于(i=1;i瓶颈可能是您使用存储路径的数据结构。如果您使用太多的存储,您的缓存和内存空间很快就会耗尽,导致快速算法运行非常缓慢,因为它获得了100(缓存未命中)或10000+(交换页面)的恒定乘数
因为您必须在数据库中存储路径,我怀疑这可能很容易成为瓶颈。可能最好先使用非常高效的存储模式(如每个顶点N位,其中N==每个顶点的最大边数)将路径生成到内存中。然后为每个可用于生成最短路径之一的边设置一位到。After生成此路径信息您可以运行递归算法,将路径信息生成为适合数据库存储的格式
当然,最可能的瓶颈仍然是数据库。您需要非常仔细地考虑用于存储信息的格式,因为在SQL数据库中插入、搜索和修改大型数据集的速度非常慢。如果数据库引擎能够成功地将多个插入路径设置为单个磁盘写入操作
更好的做法是将结果简单地存储在内存缓存中,并在不再需要时丢弃解决方案。然后,如果您碰巧再次需要它们,则再次生成相同的结果。这意味着您将仅在实际需要时按需生成路径。30k节点和160k边的运行时间应明显低于秒f或Dijkstra的单条所有最短路径运行
<最短路径算法>我一直选择C++。不应该有任何理由来说明C实现不会太简单,但是C++提供了STL容器的简化编码,这些代码可以在初始实现中使用,并且只有在稍后的基准和分析显示需要有一些东西时才实现优化的队列算法。比STL提供的更好
#include <queue>
#include "vertex.h"
class vertex;
class edge;
class searchnode {
vertex *dst;
unsigned long dist;
public:
searchnode(vertex *destination, unsigned long distance) :
dst(dst),
dist(distance)
{
}
bool operator<(const searchnode &b) const {
/* std::priority_queue stores largest value at top */
return dist > b.dist;
}
vertex *dst() const { return dst; }
unsigned long travelDistance() const { return dist; }
};
static void dijkstra(vertex *src, vertex *dst)
{
std::priority_queue<searchnode> queue;
searchnode start(src, 0);
queue.push(start);
while (!queue.empty()) {
searchnode cur = queue.top();
queue.pop();
if (cur.travelDistance() >= cur.dst()->distance())
continue;
cur.dst()->setDistance(cur.travelDistance());
edge *eiter;
for (eiter = cur.dst()->begin(); eiter != cur.dst()->end(); eiter++) {
unsigned nextDist = cur.dist() + eiter->cost();
if (nextDist >= eiter->otherVertex())
continue;
either->otherVertex()->setDistance(nextdist + 1);
searchnode toadd(eiter->othervertex(), nextDist);
queue.push(toadd);
}
}
}
#包括
#包括“vertex.h”
类顶点;
类边缘;
类搜索节点{
顶点*dst;
无符号长距离;
公众:
searchnode(顶点*目标,无符号长距离):
dst(dst),
距离(距离)
{
}
布尔算子b.dist;
}
顶点*dst()常量{return dst;}
无符号长途旅行()常量{return dist;}
};
静态空洞dijkstra(顶点*src,顶点*dst)
{
std::优先级队列;
搜索节点启动(src,0);
queue.push(启动);
而(!queue.empty()){
searchnode cur=queue.top();
queue.pop();
if(cur.travelDistance()>=cur.dst()->distance())
继续;
cur.dst()->setDistance(cur.travelDistance());
边缘*eiter;
对于(eiter=cur.dst()->begin();eiter!=cur.dst()->end();eiter++){
未签名的nextist=cur.dist()+eiter->cost();
如果(nextist>=eiter->otherVertex())
继续;
->otherVertex()->setDistance(nextList+1);
搜索要添加的节点(eiter->othervertex(),nextist);
排队推送(toadd);
}
}
}
那你有什么建议呢?我尝试了这段代码,从一个节点计算所有最短路径需要一分钟以上的时间。这需要做3万次,所以不可行。只是为了确定你编译这段代码时是否启用了优化标志,而不是在调试模式下?这不是调试模式,但我没有使用任何opt.flags,我不确定关于drawbacks@LastCoder这不是调试模式,但我没有使用任何opt.flags,我不确定其缺点,您建议进行什么优化?注意,您不必执行从所有节点到所有其他节点的Dijkstra操作-一旦您知道从A到B的最短路径,您也知道从B到A的最短路径。您还知道shortest从该路径上的每个节点到其他每个节点的路径
#include <queue>
#include "vertex.h"
class vertex;
class edge;
class searchnode {
vertex *dst;
unsigned long dist;
public:
searchnode(vertex *destination, unsigned long distance) :
dst(dst),
dist(distance)
{
}
bool operator<(const searchnode &b) const {
/* std::priority_queue stores largest value at top */
return dist > b.dist;
}
vertex *dst() const { return dst; }
unsigned long travelDistance() const { return dist; }
};
static void dijkstra(vertex *src, vertex *dst)
{
std::priority_queue<searchnode> queue;
searchnode start(src, 0);
queue.push(start);
while (!queue.empty()) {
searchnode cur = queue.top();
queue.pop();
if (cur.travelDistance() >= cur.dst()->distance())
continue;
cur.dst()->setDistance(cur.travelDistance());
edge *eiter;
for (eiter = cur.dst()->begin(); eiter != cur.dst()->end(); eiter++) {
unsigned nextDist = cur.dist() + eiter->cost();
if (nextDist >= eiter->otherVertex())
continue;
either->otherVertex()->setDistance(nextdist + 1);
searchnode toadd(eiter->othervertex(), nextDist);
queue.push(toadd);
}
}
}