查找所有周期


9

我有一个有限集,一个函数,总阶数在。我想找到中不同周期的数量。Sf:SS<SS

对于的给定元素我可以使用弗洛伊德(Floyd)算法(或布伦特等)来查找重复应用将发送到的周期的长度。稍加努力,我就可以确定该周期(例如,通过其 -minimal元素)。解决该问题的一种不好的方法是重复每个元素,对产生的最小元素进行排序,丢弃重复的元素,然后返回计数。但这可能涉及对相同元素的多次传递以及较大的空间需求。sSfs<

哪些方法具有更好的时空性能?我什至不知道测量所需空间的最佳方法是什么-如果是恒等函数,那么任何存储所有周期的方法都将使用空间。fΩ(n)


4
测量空间的自然方法之一是将S视为n位字符串的集合,将f视为预言。然后,您描述的朴素算法需要指数空间。人们可能会寻求一种仅使用多项式空间的算法,但这对我来说似乎不太可能。
伊藤刚(Tsuyoshi Ito)

这就是我的意思,“我不知道什么是测量空间的最佳方法”。可能我应该以O(poly(n)+ y)为目标,其中y是输出,因此只要y足够小,使用的空间就是多项式。
查尔斯

您的函数f是否有任何可用的属性?如果实际的答案是该算法将花费时间和空间都以S的基数为顺序,那么按照您偏好的表示输入大小的方式,该算法是多项式还是指数式将有些争议。
Niel de Beaudrap 2011年

@Niel de Beaudrap:我不确定哪些属性会有用。我希望不同周期的数量很少,但是Øñ3; 这就是为什么我建议一个功能ÿñ 而不只是 ñ。如果需要,我愿意在输出位数上使用空间指数。
查尔斯

Answers:


7

如果您只想计算周期数,则可以使用2 |来完成。S | 位(加上更改)的空间。除非Sf具有一些特别方便的属性,否则您似乎似乎不可能做得更好。

从存储整数{0,1,2}(S的每个元素一个)的数组A开始,初始化为零;我们将指出这些作为(unexplored)(partially explored)(fully explored)。将循环计数器初始化为零。对于每个元素小号  ∈  小号按顺序执行以下操作:

  1. 如果A [ s ] =  (fully explored),请跳至步骤6。
  2. 设置A [ s ]←  (partially explored),并设置迭代器j  ←  f(s)
  3. 当A [ j ] =时  (unexplored),设置A [ j ]←  (partially explored),并设置j  ←  f(j)
  4. 如果A [ j ] =  (partially explored),我们已经关闭了一个新循环;将c递增1。(如果要保留某个代表该循环的记录,则j的当前值将作为任意选择;当然,这不一定是您首选的循环中的最小元素order <。)否则,我们有A [ j ] =  (fully explored),这意味着我们发现了一个已探索的轨道,该轨道以已经计数的周期结束;不要增加c
  5. 为了表明已经完全探索了从s开始的轨道,请设置j  ←  s
    当A [ j ] =时  (partially explored),设置A [ j ]←  (fully explored)并设置j  ←  f(j)
  6. 继续到下一个元素小号  ∈  小号

因此,由f引起的轨道中的每个周期将被计数一次;您记录为代表的任何元素将是不同周期的元素。内存要求为2 | S | 对于数组A,O(log | S |)用于循环计数,以及其他奇数。

每个元素小号  ∈  小号将至少被访问两次:当A的值[一旦小号 ]从改变(unexplored)(partially explored),而一旦以使更改(fully explored)。节点被重新访问后被重新访问的总(fully explored)次数以查找失败的新循环的尝试次数为上限,最多为| |。S | —由遍历S的所有元素的主循环引起。因此,我们可以预期此过程最多包含3 |。S | 遍历节点,计算访问或重新访问节点的所有时间。

如果要跟踪周期的代表元素,并且确实希望它们是最小元素,则可以将节点访问的数量限制为4 |。S |,如果您在第4步添加了一个额外的“圈数”,则找到了一个比闭环小的代表。(如果下轨道˚F包括的周期,这种额外的工作可能是可以避免的,但是这不是任意的真˚F)。


太好了,这对傻瓜有所改善 Ø|小号|日志|小号|我想到的空间算法。我实际上不需要代表。我介绍了<以防万一对某些算法有用。
查尔斯

我想知道是否有一种方法可以在总周期很少而又不使用多项式空间的情况下使用更少的空间。啊,没关系;这将满足我的需求。
查尔斯

1
在我看来,这应该在#L中(使用矩阵供电)。这可以是#L困难的吗?
卡夫

@Charles:请参阅我最近的答案,如果您知道#cycles∈o| S |),它将为您带来改善。它的用途不止是polylog | S |。空间,但是如果您愿意在空间和时间之间进行权衡,那么对您来说可能会更好。
Niel de Beaudrap 2011年

@Niel de Beaudrap:谢谢!两者均为+1。只要数据适合内存,该算法就显得最好。一旦溢出,我会考虑使用另一个。(如果我可以将所有内容都放入高速缓存中,则另一个可能会更好,但这可能太麻烦了。)
Charles

5

如果循环的次数很少,这是一种算法,它将占用较少的空间,但终止时间会更长。

[编辑]我之前的运行时分析忽略了确定我们访问的节点是否在先前采样的节点中的关键成本;该答案已经过一些修改以纠正此问题。

我们再次遍历S的所有元素。在我们探讨的元素的轨道小号  ∈  小号,我们从我们访问过的节点样,为了能够检查,如果我们再次遇到他们。我们还维护了以前访问过的“组成部分”(即以共同周期终止(因此等于周期)的轨道的并集)的样本列表。

初始化组件的空列表complist。每个组件由该组件的样本集合表示;我们还维护了一个搜索树samples,其中存储了所有被选作某个组件或其他组件样本的元素。令G为一个整数序列,最高可达n,可以通过计算一些布尔谓词有效地确定其隶属度;例如,2次或完美权力p 某些整数幂p。对于每个小号  ∈  小号,做到以下几点:

  1. 如果s在中samples,请跳至步骤#5。
  2. 初始化一个空列表cursample,一个迭代器j  ←f(s)和一个计数器t  ←1。
  3. 虽然Ĵ是不是在samples
    -如果牛逼  ∈  ,插入Ĵ到两个cursamplesamples
    —递增t并设置j  ←  f(j)
  4. 检查j是否在中cursample。如果不是,则我们遇到了先前探讨过的组件:我们检查j属于哪个组件,并将的所有元素插入cursample到的适当元素中complist以进行扩充。否则,我们会重新遇到当前轨道上的某个元素,这意味着我们至少经过了一个循环,而没有遇到以前发现的循环的任何代表:将cursample作为新发现的分量的样本集合插入到中complist
  5. 继续到下一个元素小号  ∈  小号

对于n  = | S |,令X(n)是描述预期循环数的单调递增函数(例如 X(n)n 1/3),令Y(n) = y(n)  log(n)∈Ω(X(n)  log(n))是确定内存使用目标的单调递增函数(例如 y(n)n 1/2)。我们需要y(n)  ∈Ω(X(n)),因为它至少需要X(n)  log(n)空间来存储每个分量的一个样本。

  • 我们采样的轨道元素越多,我们越有可能在轨道末端的周期中快速选择一个样本,从而快速检测到该周期。从渐近论的角度来看,获得尽可能多的样本是有意义的:我们的内存范围允许:我们最好将G设置为具有小于n的期望y(n)元素。—如果期望S中轨道的最大长度为L,则可以让GL  /  y(n)的整数倍。—如果没有期望的长度,我们可以简单地每n  /  y(n)采样一次

    元素; 在任何情况下,这都是样本之间间隔的上限。

  • 如果在寻找新组件时,我们开始遍历先前访问过的S元素(从正在发现的新组件或已经找到其终端循环的旧组件开始),则最多需要n  /  y( n)迭代以遇到先前采样的元素;这就是次数的上限,对于每次尝试寻找新组件的操作,我们都会遍历冗余节点。因为我们使Ñ这样的尝试中,我们将然后冗余访问的元素小号至多Ñ 2  /  Y(N)中总次数。

  • 测试成员资格所需的工作samples为O(y(n)  log  y(n)),我们在每次访问时都会重复进行此工作:此检查的累积成本为O(n 2  log  y(n))。将样本添加到其各自的集合中也存在成本,其累积值为O(y(n)  log  y(n))。最后,每次我们遇到一个先前发现的组件时,我们都必须花费最多X(n)  log *  y(n)的时间来确定我们重新发现了哪个组件。由于最多可能会发生n次,因此涉及的累计功由n X(n)  log  y(n)限制

因此,在检查我们访问的节点是否在样本中时执行的累积工作支配了运行时间:这花费O(n 2  log  y(n))。然后我们应该使y(n)尽可能小,即O(X(n))。

因此,可以枚举O(n 2  log  X(n))来枚举O(X(n)  log(n))空间中的循环数(与那些循环中结束的组件数相同)。这样做的时间,其中X(n)是预期的循环数。


1

您可以使用联合集data-structure避免对同一元素进行多次传递。每个元素一遍s 合并包含的集合 s 与包含 Fs。这仍然会占用大量内存。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.