代码之家  ›  专栏  ›  技术社区  ›  nes1983

数学产量

  •  12
  • nes1983  · 技术社区  · 15 年前

    你能做些像蟒蛇的吗 yield 语句在 数学软件 ,以便创建生成器?参见 here 对于这个概念。

    更新 下面是一个例子,我的意思是,迭代所有排列,只使用 O(n) 空间:(Sedgewick的算法书中的算法):

    gen[f_, n_] := Module[{id = -1, val = Table[Null, {n}], visit},
      visit[k_] := Module[{t},
        id++; If[k != 0, val[[k]] = id];
        If[id == n, f[val]];
        Do[If[val[[t]] == Null, visit[t]], {t, 1, n}];
        id--; val[[k]] = Null;];
      visit[0];
      ]
    

    然后像这样称呼它:

    gen[Print,3] ,打印所有6个长度为3的排列。

    2 回复  |  直到 6 年前
        1
  •  5
  •   Sasha    13 年前

    如我之前所述,使用 Compile 将给出更快的代码。使用的算法来自 fxtbook ,以下代码生成词典排序中的下一个分区:

    PermutationIterator[f_, n_Integer?Positive, nextFunc_] := 
     Module[{this = Range[n]},
      While[this =!= {-1}, f[this]; this = nextFunc[n, this]];]
    

    以下代码假定我们运行版本8:

    ClearAll[cfNextPartition];
    cfNextPartition[target : "MVM" | "C"] := 
      cfNextPartition[target] = 
       Compile[{{n, _Integer}, {this, _Integer, 1}},
        Module[{i = n, j = n, ni, next = this, r, s},
         While[Part[next, --i] > Part[next, i + 1], 
          If[i == 1, i = 0; Break[]]];
         If[i == 0, {-1}, ni = Part[next, i]; 
          While[ni > Part[next, j], --j];
          next[[i]] = Part[next, j]; next[[j]] = ni;
          r = n; s = i + 1;
          While[r > s, ni = Part[next, r]; next[[r]] = Part[next, s]; 
           next[[s]] = ni; --r; ++s];
          next
          ]], RuntimeOptions -> "Speed", CompilationTarget -> target
        ];
    

    然后

    In[75]:= Reap[PermutationIterator[Sow, 4, cfNextPartition["C"]]][[2, 
       1]] === Permutations[Range[4]]
    
    Out[75]= True
    

    这显然比原来的好 gen 功能。

    In[83]:= gen[dummy, 9] // Timing
    
    Out[83]= {26.067, Null}
    
    In[84]:= PermutationIterator[dummy, 9, cfNextPartition["C"]] // Timing
    
    Out[84]= {1.03, Null}
    

    使用Mathematica的虚拟机并不慢:

    In[85]:= PermutationIterator[dummy, 9, 
      cfNextPartition["MVM"]] // Timing
    
    Out[85]= {1.154, Null}
    

    当然,这离C代码实现还差得远,但它比纯顶级代码的实现速度要快得多。

        2
  •  2
  •   dreeves    15 年前

    你可能是说这个问题更一般,但是你链接到的页面上给出的迭代排列的例子恰好内置于Mathematica中:

    Scan[Print, Permutations[{1, 2, 3}]]
    

    这个 Print 可以用任何功能替换。