优化大向量的操作

2023-12-22

这是我的后续行动上一个问题 https://stackoverflow.com/questions/24278006/need-advice-on-optimising-haskell-data-processing关于处理 5.1m 边有向图的向量表示。我正在尝试实现 Kosaraju 的图算法,因此需要按照反向边缘上深度优先搜索(DFS)的完成时间的顺序重新排列我的向量。我的代码可以在小数据集上运行,但在完整数据集上无法在 10 分钟内返回。 (我不能排除大图会产生循环,但我的测试数据上没有任何迹象。)

DFS 需要避免重新访问节点,因此我需要某种“状态”来进行搜索(当前是一个元组,我应该使用 State Monad 吗?)。第一次搜索应该返回一个重新排序的向量,但我目前通过返回重新排序的节点索引列表来保持简单,以便我可以随后一次性处理该向量。

我认为问题在于dfsInner。下面的代码“记住”访问过的节点,更新每个节点的探索字段(第三个守卫)。尽管我尝试使其尾递归,但代码似乎使内存使用量增长得相当快。我需要执行一些严格的规定吗如果是这样,怎么办? (我有另一个用于单个搜索的版本,它通过查看堆栈上未探索的边缘的起始节点和已完成的节点列表来检查以前的访问。这不会增长得那么快,但是不会返回任何连接良好的节点。)

然而,它也可能是foldr', but 我怎样才能检测到?

这应该是 Coursera 作业,但我不再确定我可以勾选荣誉代码按钮!不过,学习更重要,所以我真的不想要复制/粘贴答案。我所拥有的并不是很优雅 - 它也有一种迫切的感觉,这是由保持某种状态的问题驱动的 - 请参阅第三个后卫。我欢迎对设计模式提出意见。

type NodeName = Int
type Edges    = [NodeName]
type Explored = Bool
type Stack    = [(Int, Int)]

data Node  = Node NodeName Explored Edges Edges deriving (Eq, Show)
type Graph = Vector Node

main = do
    edges <- V.fromList `fmap` getEdges "SCC.txt"
    let 
        maxIndex = fst $ V.last edges
        gr = createGraph maxIndex edges
        res = dfsOuter gr
    --return gr
    putStrLn $ show res

dfsOuter gr = 
    let tmp = V.foldr' callInner (gr,[]) gr
    in snd tmp

callInner :: Node -> (Graph, Stack) -> (Graph, Stack)
callInner (Node idx _ fwd bwd) (gr,acc) = 
    let (Node _ explored _ _) = gr V.! idx
    in case explored of
        True  -> (gr, acc)
        False ->
            let
                initialStack = map (\l -> (idx, l)) bwd
                gr' = gr V.// [(idx, Node idx True fwd bwd)]
                (gr'', newScc) = dfsInner idx initialStack (length acc) (gr', [])
            in (gr'', newScc++acc)

dfsInner :: NodeName -> Stack -> Int -> (Graph, [(Int, Int)]) -> (Graph, [(Int, Int)])
dfsInner start [] finishCounter (gr, acc) = (gr, (start, finishCounter):acc)
dfsInner start stack finishCounter (gr, acc)
    | nextStart /= start =                      -- no more places to go from this node
        dfsInner nextStart stack (finishCounter + 1) $ (gr, (start, finishCounter):acc)
    | nextExplored = 
-- nextExplored || any (\(y,_) -> y == stack0Head) stack || any (\(x,_) -> x == stack0Head) acc =
        dfsInner start (tail stack) finishCounter (gr, acc)
    | otherwise =
        dfsInner nextEnd (add2Stack++stack) finishCounter (gr V.// [(nextEnd, Node idx True nextLHS nextRHS)], acc)
--      dfsInner gr stack0Head (add2Stack++stack) finishCounter acc

    where
        (nextStart, nextEnd) = head stack
        (Node idx nextExplored nextLHS nextRHS) = gr V.! nextEnd
        add2Stack = map (\l -> (nextEnd, l)) nextRHS

简而言之:

了解时间复杂度。

优化有很多要点,其中很大一部分在日常编程中并不是很重要,但如果不了解渐近复杂性,程序通常会变得很糟糕。根本不起作用.

Haskell 库通常会记录复杂性,尤其是当它不明显或无效时(线性或更糟)。特别是,与这个问题相关的所有复杂性都可以在Data.List and Data.Vector.

性能被杀死V.//这里。向量是内存中装箱或拆箱的不可变连续数组。因此,修改它们需要复制整个向量。由于我们有 O(N) 这样的修改,整个算法是 O(n^2),所以我们必须复制大约 2 TB,其中 N = 500000。因此,在向量内标记访问过的节点没有多大用处。相反,建立一个IntSet根据需要的索引。

initialStack (length acc)看起来也很糟糕。使用它几乎从来都不是一个好主意length在大型列表上,因为它也是 O(n)。它可能没有那么糟糕//在您的代码中,因为它位于相对很少出现的分支中,但在我们更正矢量问题后,它仍然会导致性能下降。

此外,搜索实现对我来说似乎相当不清楚且过于复杂。旨在对伪代码进行字面翻译Wiki http://en.wikipedia.org/wiki/Kosaraju%27s_algorithm页面应该是一个好的开始。此外,没有必要将索引存储在节点中,因为它们可以根据向量位置和邻接列表来确定。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

优化大向量的操作 的相关文章

  • 面试问题 - 在排序数组 X 中搜索索引 i,使得 X[i] = i

    昨天面试时 我被问到了以下问题 考虑一个 Java 或 C 数组X它已排序并且其中没有两个元素是相同的 如何最好地找到索引i这样该索引处的元素也是i 那是X i i 作为澄清 她还给了我一个例子 Array X 3 1 0 3 5 7 in
  • 难以理解如何处理调车场算法的输出

    我一直在看维基页面 http en wikipedia org wiki Shunting yard algorithm http en wikipedia org wiki Shunting yard algorithm 我已经使用代码示
  • 如何生成排列?

    我的问题是 给定一个长度为 n 的列表 L 和一个整数 i 使得 0 对于任意 i 和任意 2 个列表 A 和 B perm A i 和 perm B i 都必须将 A 和 B 的第 j 个元素映射到 A 和 B 相同位置的元素 对于任何输
  • iOS心率检测算法

    我正在尝试在我正在开发的应用程序中实现心跳记录功能 首选方法是使用 iPhone 的摄像头 在灯亮的情况下 让用户将手指放在镜头上 然后检测视频源中与用户心脏相对应的波动 我通过以下堆栈溢出问题找到了一个非常好的起点here https s
  • 为什么 GeneralizedNewtypeDeriving 没有安全的 Haskell?

    来自 GHC 手册 第安全语言 http www haskell org ghc docs 7 6 2 html users guide safe haskell html safe language 模块边界控制 使用安全语言编译的 Ha
  • 应用交换律

    带有效果的应用程序编程 http staff city ac uk ross papers Applicative html麦克布莱德和帕特森的论文提出了互换法 u lt gt pure x pure f gt f x lt gt u 为了
  • 如何计算python 2D散点占用面积

    我使用 matplotlib 绘制了这两个 2000 个点的序列 从图片上看 前2000点占用的面积比后2000点要小 但如果我想定量计算2000个点的第一序列和第二序列占用了多少面积 该怎么办 我真的很感谢任何帮助 建议或意见 非常感谢
  • 计算 Adamic-Adar 的快速算法

    我正在研究图形分析 我想计算一个 N N 相似度矩阵 其中包含每两个顶点之间的 Adamic Adar 相似度 为了概述 Adamic Adar 让我从以下介绍开始 给定邻接矩阵A无向图的G CN是两个顶点的所有公共邻居的集合x y 两个顶
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • 表达式“ap zip tail”如何工作

    我想知道怎么写f x zip x tail x 点免费 所以我使用了pointfree程序 结果是f ap zip tail ap作为 Control Monad 的函数 我不明白点自由定义是如何工作的 如果我能从类型的角度去理解的话 希望
  • 如何在 Haskell 中枚举递归数据类型?

    这篇博文 http lukepalmer wordpress com 2008 05 02 enumerating a context free language 对于如何使用 Omega monad 对角枚举任意语法有一个有趣的解释 他提
  • Numpy:具有特定条件的线性系统。无负解

    我正在使用 numpy 编写 Python 代码 在我的代码中 我使用 linalg solve 来求解 n 个变量中的 n 个方程的线性系统 当然 解决方案可以是积极的 也可以是消极的 我需要做的是始终有正解或至少等于 0 为此 我首先希
  • 如何、为什么以及何时使用“.Internal”模块模式?

    我在上面看到了几个包裹hackage http hackage haskell org packages archive pkg list html其中包含模块名称 Internal作为他们的姓氏组成部分 例如Data ByteString
  • 找到不(必要)与二进制矩阵中的图像边界对齐的最大矩形

    我在用这个解决方案 https stackoverflow com questions 2478447 find largest rectangle containing only zeros in an nn binary matrix在
  • 列表理解:制作列表列表

    你好 我正在尝试在 haskell 中创建一个函数 该函数接受一个数字 a 使用列表 即数字 将其一部分4它会创造 1 1 1 1 1 1 2 1 3 2 2 4 我正在考虑使用列表理解来创建列表 x 然后使用 1 n 中的数字创建更多列表
  • 给定一个点向量(可能无序),找到多边形(不是凸包)

    我目前有一个点向量 vector
  • GHC 是否使用存在类型的动态调度?

    下面的代码是否使用了 C 或 Java 中所理解的动态调度 据我了解 在最后一行 编译器不可能在编译时知道要调用哪个 实现 但代码会编译并产生正确的结果 有人可以解释一下 这背后有什么样的实现 例如 vptr 吗 LANGUAGE Exis
  • 数组中最远的相等元素

    假设你有一个未排序的数组 你如何找到两个相等的元素 使它们成为数组中最远的元素 例如8 7 3 4 7 5 3 9 3 7 9 0ans 将是7 9 7 1 8 我想到了以下几点 initialise max 0 using hashing
  • 我应该使用镜头中的什么来按索引构建只读吸气剂?

    我有一个内部细节被隐藏的类型 我想提供某种镜头 可以在特定索引处读取所述类型的元素 但是not修改它们 一个Ixed我的类型的实例似乎没有做我想要的事情 因为它明确允许修改 尽管不允许插入或删除 如果我想允许只读索引 我不确定我使用什么 如
  • Haskell 测量函数性能

    在 Haskell 中 我如何 简单地 测量函数的性能 例如 运行需要多长时间 或者需要多少内存 我知道分析 但是 是否有一种更简单的方法不需要我对代码进行太多更改 测量运行需要多长时间以及需要多少内存是两个独立的问题 即 基准测试和分析

随机推荐

  • 自动滚动不适用于 vbox 布局

    我需要将表单面板居中对齐 所以我使用了vbox布局 使用后自动滚动不再像以前那样工作 代码如下 Usr VWPanel Ext extend Ext Panel id null rid null closable true autoScro
  • 无法访问类 jdk.xml.internal.JdkXmlUtils

    我正在更新 hybris SAP Commerce 2005 的旧公司实习生扩展 它是使用 API 的扩展 我不知道这个扩展有多少年了 然而 当将它应用到java 11时 我发现了这样的问题 Java 11 导入 javax xml ws
  • 编写 Jena 内置函数

    我正在尝试写一个耶拿内置 http jena apache org documentation inference RULEbuiltins从给定的算法返回一个值 然后与该值进行比较 例如 String rule exRule d rdf
  • 最好的 Python Cassandra 库/包装器? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 I found lazyboy https github com digg lazyboy and pycassa https github c
  • 需要密码才能禁用 Android 设备管理员

    我正在考虑一个具有设备管理员权限的安全应用程序 我想看看当用户尝试在 设置 gt 安全 gt 设备管理员 下以管理员身份取消选中该应用程序时 是否可能需要密码 这将增加一个障碍 不允许用户轻易卸载应用程序 因为他们首先需要从应用程序中删除管
  • PHP-解码 JSON

    我有以下脚本从 API 获取搜索结果 然后对数组进行切片并转储它 我在将 JSON 解码为数组时遇到问题 它返回Array 0 这是一个 WordPress 简码 以下是从 api 获取的 Json 示例 barcode 000015426
  • Java:如何获取xml节点路径

    我有以下 xml
  • 我如何知道 UdpClient 是否已关闭/处置?

    我通过通常的异步回调从 UdpClient 接收数据 private void OnUdpData IAsyncResult result byte data udpReceive EndReceive result ref receive
  • 将一个类的所有对象放入一个列表中

    我有一个 C 类 称为 C 当我执行该程序时 我创建该类的新对象 在某些时候 我需要创建一个列表List
  • 如何将 Ruby 数组从 Heroku 控制台导出为 CSV?

    我希望将数组从 heroku 控制台导出到本地 CSV 文件中 在我目前的情况下 我每天都有一个 rake 任务 它寻找谈论我的应用程序的推文 我想分析这些推文 看看它们是什么时间出现的 等等 heroku run console twee
  • 录制视频时的音频音量

    因此 经过大量搜索后 我找到了允许在录制视频的同时播放背景音频的代码块 我已将所述代码块粘贴在下面 fileprivate func setBackgroundAudioPreference guard allowBackgroundAud
  • 枚举内的枚举

    我想在 java 中的 sql 查询的枚举中创建一个枚举 比如我想说table create它会返回 CREATE TABLE 或database create它会返回创建数据库 我怎样才能做到这一点 enum SQL table ALTE
  • 未找到 Phonegap 3.0 IOS 插件

    我在 XCode 中收到此错误 2013 08 23 14 36 18 284 Tell The DJ 14955 c07 ERROR Plugin Device not found or is not a CDVPlugin Check
  • 我可以使用 UriTemplate 将非字符串传递给 WCF RESTful 服务吗?

    我可以执行以下操作吗 OperationContract WebGet UriTemplate foo id string GetFoo int id 我希望我的服务既可以作为 RESTful 服务 又可以作为 RPC 样式的 SOAP 服
  • 如何在C++中链接头文件

    我是使用头文件进行 C 编程的新手 这是我当前的代码 a h ifndef a H define a H namespace hello class A int a public void setA int x int getA endif
  • 如何在 Swift 中从文件夹中获取 UIImage 数组?

    我有一个像这样的普通 Xcode 项目 请注意 有一个名为 images 的文件夹 它是一个实际的文件夹 而不仅仅是一个组 它包含 25 个 png 图像 我想做的就是做一个array of UIimage与每一个图像 或者甚至是图像名称或
  • 使用 register_shutdown_function() 处理 PHP 中的致命错误

    根据对此答案的评论 https stackoverflow com questions 4409426 can i hook a method to my php file that if any page crashes should e
  • 模糊错误表明我的组件名称以零开头

    我收到一个晦涩的错误 我的组件名称为零 但我的组件中没有一个名称是零 这个错误很难追踪 任何人都知道问题可能是什么 这样我就可以朝着正确的方向前进来解决它 vendor js 66537 Vue warn 无效的组件名称 0 组件名称只能包
  • 无法将 Spring Security BASIC 身份验证集成到 Jersey/JAX-RS 和 Tomcat 中

    我正在尝试将 BASIC 身份验证添加到我使用 Jersey JAX RS 和 Tomcat Apache 7 0 创建的 RESTful Web 服务 将来我想在 WebSphere 上部署此 Web 服务 因此我选择在我的项目中使用 S
  • 优化大向量的操作

    这是我的后续行动上一个问题 https stackoverflow com questions 24278006 need advice on optimising haskell data processing关于处理 5 1m 边有向图