- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我有一个Ruby1.9.3中的程序,它构造了一个RubyTree。我的数据最好被描述为一个Directed Acyclic Graph(dag);请注意,它不是一个polytree。好吧,至少数据应该是DAG,尽管用户尽最大努力用坏数据来屏蔽我的程序。
我通过解析xml文档动态构建dag。XML文档没有显式地指定树结构,但提供了整数ID的交叉引用,这些ID在文档中的元素之间建立链接。
我需要确保rubytree不包含任何循环。源数据可能(错误地)有一个循环,如果有,我的程序需要知道它,而不是进入无限循环或崩溃。为了实现这一点,我将ruby标准库的TSort模块混合到rubytree的Tree::TreeNode
类中。这使用tarjan算法在每次添加节点时对图执行拓扑排序。在拓扑排序过程中,如果检测到一个循环,就会引发异常——这正是我想要的。
例如:
module Tree
class TreeNode
include TSort
def tsort_each_node(&block)
self.each(&block)
end
def tsort_each_child(node, &block)
node.get_children().each { |child| yield child }
end
def add(child, at_index = -1)
#The standard RubyTree implementation of add goes here
begin
self.tsort()
rescue TSort::Cyclic => exce
self.remove!(child)
raise exce
end
return child
end
end
end
Tree::TreeNode#to_s()
以返回
Tree::TreeNode#name
)
TSort::Cyclic
,如果我试图添加一个导致循环的节点,那么该节点将被删除,并且我可以将该问题记录到一个报告中,以便以后处理(通过修复源数据)。
O(|V| + |E|)
,在我的例子中是
O(2*|V|)
,但是每次我调用
add()
,
|V|
都会增加1,因为我一个节点一个节点地构建图形。我不能简单地在结尾调用tarjan's,因为在read-compare-add循环期间,我可能需要遍历该图或其中的一部分,并且任何遍历尝试都可能挂起程序,或者在实际上存在循环的情况下使其崩溃。(不用说,我的代码是单线程的;如果不是,我们会遇到一个巨大的问题。从目前的情况来看,我依赖于这样一个事实:如果存在一个循环,则
add()
永远不会返回,而不会引发异常;即使存在一个循环,节点也会被移除,以便在
add()
返回之前清除该循环。)
ruby-perf
的结果来看,仅仅表演Tarjan的节目就已经占据了大部分的演出份额。在rubytree
each
实现中,我尝试从数组切换到链表,但通过移除
Array#concat
调用的负载,它只减少了大约1%的运行时间。
require 'tree'
a = Tree::TreeNode.new('a', nil)
b = Tree::TreeNode.new('b', nil)
c = Tree::TreeNode.new('c', nil)
a.add(b)
a.add(c)
puts "First time"
b.add(c)
puts "Second time"
b.add(a)
puts "Third time"
c.add(b)
puts "Fourth time"
c.add(a)
puts "Fifth time"
puts "Done"
TSort
块中做一些事情来记录发生的周期,并大声抱怨创建这些周期的人类罪犯。
require 'tree'
require 'tsort'
module Tree
class TreeNode
include TSort
def tsort_each_node(&block)
self.each(&block)
end
def tsort_each_child(node, &block)
node.get_children().each { |child| yield child}
end
def to_s
name
end
def get_children()
return @children
end
def add(child, at_index = -1)
unless child
raise ArgumentError, "Attempting to add a nil node" # Only handles the immediate child scenario
end
if self.equal?(child)
raise TSort::Cyclic, "Cycle detected: [#{child.name}, #{child.name}]"
end
# Lazy man's unique test, won't test if children of child are unique in this tree too.
if @children_hash.include?(child.name)
raise "Child #{child.name} already added!"
end
if insertion_range.include?(at_index)
@children.insert(at_index, child)
else
raise "Attempting to insert a child at a non-existent location (#{at_index}) when only positions from #{insertion_range.min} to #{insertion_range.max} exist."
end
@children_hash[child.name] = child
child.parent = self
#CYCLE DETECTION - raises TSort::Cyclic if this caused a cycle
begin
self.tsort()
rescue TSort::Cyclic => exce
self.remove!(child)
raise exce
end
return child
end
end
end
a = Tree::TreeNode.new('a', nil)
b = Tree::TreeNode.new('b', nil)
c = Tree::TreeNode.new('c', nil)
a.add(b)
a.add(c)
puts "First time"
b.add(c)
puts "Second time"
begin
b.add(a)
rescue
end
puts "Third time"
begin
c.add(b)
rescue
end
puts "Fourth time"
begin
c.add(a)
rescue
end
puts "Fifth time"
puts "Done"
最佳答案
ruby的Plexusgem似乎解决了我最糟糕的问题。我以前试过gratr,但它不会加载,因为它与ruby 1.9.3不兼容,但是plexus是gratr的一个分支,可以与1.9.3兼容。
我的问题是我使用的数据结构(rubytree)不是设计用来处理循环的,但是plexus有向图实际上可以继续处理循环。api的设计考虑到了它们。
我采用的解决方案非常简单:基本上,现在我的图形数据结构不依赖于循环,我可以在图形生成例程的末尾调用tarjan的算法——实际上,有一个很好的wrapperacyclic?
方法,但它只是在幕后调用topsort()
,并使用tarjan的强连接组件算法实现拓扑排序,非常类似于ruby的stdlibTSort
。不过,它确实使用自己的实现,而不是TSort
。我不确定为什么。
不幸的是,现在我面临着开发一个实现minimum feedback arc set problem(最小fas问题)的np难的挑战。最小fas问题是必需的,因为我需要删除图中最少侵入的弧数以使其非循环。
我现在的计划是从plexus中获取强连接组件列表,这是一个数组数组;如果任何二级数组包含多个元素,则该数组根据强连接组件的定义,使用循环来描述元素。然后我必须(使用最小fas或近似值)移除边和/或顶点以使图无循环,并迭代运行tarjan's,直到每个scc子数组的长度为1。
我认为暴力可能是解决最小fas的最佳方法:我不需要太聪明,因为我的数据集中任何scc中的节点数几乎永远不会超过5或6。指数在5或6是好的。我严重怀疑我是否会有一个由数百个节点组成的scc集,其中包含数十个不同的周期;这将是一个极端病态的最坏情况,我认为这种情况不会发生。不过,如果是这样的话,运行时间会很长。
基本上,我需要尝试删除图的弧的幂集,一次删除一个子集,子集按子集大小升序排序,然后“猜测并检查”图是否仍然是循环的(tarjan的),然后如果该幂集不能修复循环,则添加边。
如果边和节点的数量小于20个左右(这几乎是可以保证的),则不会占用大量运行时间。
去掉迭代的tarjan绝对解决了我在happy path中的复杂性问题(没有周期或者只有一个小周期),这真的是让我最心痛的地方——不是花25分钟来构建图表,而是花了15秒。
经验教训:如果你的程序很慢,可能是因为你做了很多不必要的工作。在我的例子中,不必要的工作是在每次向图中添加新顶点时执行tarjan的拓扑排序,这只是因为我最初选择对数据建模的库的实现细节而需要的。
关于ruby - 有向无环图中的循环检测更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26246177/
我想填充 3D 等高线图 (contour3(X,Y,Z)),就像 2D 等高线填充图 (contourf(X,Y,Z))。但我无法弄清楚如何实现这一目标。 contour3 和 surf 的组合不是
我有一个 c3.js 折线图,表示 2 个值的演变。我需要折线图的工具提示是饼图(工具提示 = 另一个 c3.js 图形)。 这是我成功的: http://jsfiddle.net/owhxgaqm/
我有具有结构的 Pandas 数据框: A B 0 1 1 1 2 1 2 3 4 3 3 7 4 6 8 如何生成 Seaborn Violin 图,每列作为其自己的单独
我正在使用 D3DXSPRITE 方法将我的 map 图 block 绘制到屏幕上,我刚刚添加了一个缩放功能,当您按住向上箭头时会放大,但注意到您现在可以看到图 block 之间的间隙,这是一些屏幕截
1、系统环境如下图: 2、为该系统添加一块新的虚拟硬盘,添加后需重启虚拟机,否则系统不识别;如下图,/dev/sdc 是新添加的硬盘; 3、fdisk /dev/sdc为新硬盘创建分区:
1、nagios简介 nagios是一款开源的电脑系统和网络监视工具,能有效监控windows、linux和unix的主机状态,交换机路由器等网络设置,打印机等。在系统或服务状态异常时发
越来越多人开始习惯用手机上网,浏览网页、查看邮件···移动化已经成为互联网发展必然趋势,包括facebook在内的很多互联网公司都将移动广告作为下一个淘金地
1.图片处理 1.圆角图片 复制代码 代码如下: /** * 转换成圆角 * &n
Microsoft SQL Server Management Studio是SQL SERVER的客户端工具,相信大家都知道。我不知道大伙使用导入数据的情况怎么样,反正我最近是遇到过。主要是因为没
debian6系统: 首先先安装mysql吧: 打开终端(root)用户登入 apt-get purge mysql-server-5.5 安装完成后: 默认情况下Mysql只允许本地登录
fedora16英文环境下支持中文输入法的方法 fedora16英文环境下支持FCITX的中文输入法: $ im-chooser 就会出现选择界面,选择第二个就行了。
Net预编译命令 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -? 显示说明 我们需要选择的命令为&n
有的时候电脑出现一些故障有的时候通过将其修改bios设置的方法来解决故障,那么在bios上设置能不能将电脑恢复出厂设置呢?其实也是可以的。方法也很简单的,只要会进入电脑的bios懂的上面英文的意思就
笔者曾介绍过Deepin 将对龙芯进行全面支持,打造最优美龙芯电脑桌面。现在Deepin团队移植工作取得了突破性的成果,Deepin桌面已经在龙芯3A和龙芯3B电脑上成功运行起来了。 以下为龙芯3
在安装一些软件之后,我们的电脑总是会发生一点小变化,不是桌面上多了几个网址图标,就是IE浏览器的默认主页被篡改成乱七八糟的网址。最可气的是,在IE设置中将默认主页改回来后,下次启动Win7后又变了回
“注册表编辑器怎么打开”虽说不是很难的问题,但是对于对电脑常识不是很擅长的网民来说,当电脑出现问题或需要更改设置时,着实还是件头疼的问题。因为需要打开注册表进行操作解决。那么如何打开注册表编辑器呢?
这篇文章重点介绍10个重要的WordPress安全插件和技巧,用来保护WordPress网站或者博客。 1. WP Security 人工帮助你修复被黑客入侵的网站,只要按照他们网站上的联系电话
其实运用object和javascript调用外部文件,也能实现不同栏目调用不同友情链接,即相当于调用不同栏目友情链接文件, {dede:field.typeid/}来获取当前栏目的ID。
我有一个复值矩阵。 如果我发出命令: plot(myMatrix) 然后它在图形设备上显示一种散点图,X 轴标记为 Re(myMatrix),Y 轴标记为 Im(myMatrix)。这显示了我正在寻找
关闭。这个问题需要更多focused .它目前不接受答案。 想改善这个问题吗?更新问题,使其仅关注一个问题 editing this post . 4年前关闭。 Improve this questi
我是一名优秀的程序员,十分优秀!