小编典典

良好的图遍历算法

algorithm

抽象问题:我的图表大约有250,000个节点,平均连通性约为10。找到节点的连接是一个漫长的过程(可以说10秒)。将节点保存到数据库也需要大约10秒钟。我可以非常快速地检查数据库中是否已存在节点。允许并发,但一次不能超过10个长请求,您将如何遍历图形以最快的速度获得最高覆盖率。

具体问题:我正在尝试抓取网站用户页面。为了发现新用户,我从已知的用户中获取朋友列表。我已经导入了大约10%的图形,但是我一直陷在周期中,或者使用太多的内存来记住太多的节点。

我当前的实现:

def run() :
    import_pool = ThreadPool(10)
    user_pool = ThreadPool(1)
    do_user("arcaneCoder", import_pool, user_pool)

def do_user(user, import_pool, user_pool) :
    id = user
    alias = models.Alias.get(id)

    # if its been updates in the last 7 days
    if alias and alias.modified + datetime.timedelta(days=7) > datetime.datetime.now() :
        sys.stderr.write("Skipping: %s\n" % user)
    else :
        sys.stderr.write("Importing: %s\n" % user)
        while import_pool.num_jobs() > 20 :
            print "Too many queued jobs, sleeping"
            time.sleep(15)

        import_pool.add_job(alias_view.import_id, [id], lambda rv : sys.stderr.write("Done Importing %s\n" % user))

    sys.stderr.write("Crawling: %s\n" % user)
    users = crawl(id, 5)
    if len(users) >= 2 :
        for user in random.sample(users, 2) :
            if (user_pool.num_jobs() < 100) :
                user_pool.add_job(do_user, [user, import_pool, user_pool])

def crawl(id, limit=50) :
    '''returns the first 'limit' friends of a user'''
    *not relevant*

当前实施中的问题:

  • 陷入我已经导入的小组中,从而浪费时间,并且导入线程处于空闲状态。
  • 他们将指出更多内容。

因此,欢迎边际改进以及完全重写。谢谢!


阅读 223

收藏
2020-07-28

共1个答案

小编典典

要记住您已经访问过的用户的ID,您需要一个长度为250,000整数的映射。这远非“太多”。只需维护这样的地图,并且仅遍历通向那些尚未被发现的用户的边缘,然后在找到这样的边缘时将他们添加到该地图中即可。

据我所知,您即将实现广度优先搜索(BFS)。检查谷歌有关此算法的细节。而且,当然,不要忘记互斥锁-您将需要它们。

2020-07-28