【问题标题】:Generating reversible permutations over a set在集合上生成可逆排列
【发布时间】:2014-07-13 11:39:24
【问题描述】:

我想以非顺序方式遍历集合 Q = [0, 2^16) 中的所有元素。为此,我需要一个函数 f(x) Q --> Q,它给出了对集合进行排序的顺序。例如:

f(0) = 2345   
f(1) = 4364   
f(2) = 24   
(...)

要恢复顺序,我需要反函数 f'(x) Q --> Q 输出:

f(2345) = 0
f(4364) = 1
f(24) = 2
(...)

函数必须是双射的,对于 Q 的每个元素,函数唯一地映射到 Q 的另一个元素。

我怎样才能生成这样的函数,或者是否有任何已知的函数可以做到这一点?

【问题讨论】:

  • 注意:您不仅需要 Q 的排列。您还需要 cyclic derangement;没有固定点且不能分解为多个独立循环的排列。
  • ...哦,笨蛋,我认为f(x) 是“x 之后的内容”,但您可能认为它是“x 位置的内容”。

标签: function permutation algebra bijection


【解决方案1】:

编辑:在以下答案中,f(x) 是“x 之后的内容”,而不是“x 位置的内容”。例如,如果您的第一个数字是 5,则 f(5) 是下一个元素,而不是 f(1)。回想起来,您可能认为 f(x) 是“位置 x 中的内容”。如果用作“x 位置的内容”,则此答案中定义的函数要弱得多


Linear congruential generators 满足您的需求。

线性同余生成器由方程定义

f(x) = a*x+c (mod m)

对于一些常量acm。在这种情况下,m = 65536

如果以下属性成立,则 LCG 具有完整周期(您想要的属性):

  1. cm 是相对质数。
  2. a-1 可以被 m 的所有质因数整除。
  3. 如果m 是4 的倍数,则a-1 是4 的倍数。

我们会选择a = 5c = 1

为了反转 LCG,我们根据 x 求解 f(x)

x = (a^-1)*(f(x) - c) (mod m)

我们可以通过extended Euclidean algorithm 找到 5 mod 65536 的倒数,或者因为我们只需要这一计算,我们可以将其插入 Wolfram Alpha。结果是 52429。

因此,我们有

f(x) = (5*x + 1) % 65536
f^-1(x) = (52429 * (x - 1)) % 65536

【讨论】:

    【解决方案2】:

    有很多方法可以解决这个问题。

    由于您的集合大小很小,因此生成函数及其逆函数的要求可以简单地通过内存查找来完成。因此,一旦您选择了排列,您就可以将正向和反向存储在查找表中。

    创建排列的一种方法是映射出数组中的所有元素,然后随机交换它们“足够”的次数。 C代码:

    int f[PERM_SIZE], inv_f[PERM_SIZE];
    int i;
    
    // start out with identity permutation
    for (i=0; i < PERM_SIZE; ++i) {
        f[i] = i;
        inv_f[i] = i;
    }
    
    // seed your random number generator
    srand(SEED);
    
    // look "enough" times, where we choose "enough" = size of array
    for (i=0; i < PERM_SIZE; ++i) {
        int j, k;
        j = rand()%PERM_SIZE;
        k = rand()%PERM_SIZE;
        swap( &f[i], &f[j] );
    }
    
    // create inverse of f
    for (i=0; i < PERM_SIZE; ++i)
        inv_f[f[i]] = i;
    

    享受

    【讨论】:

    • 2^16 是一个小测试用例。随着问题规模的增加,这种解决方案很快就会变得难以处理。
    • 当然,如果您想要的东西不限于表达问题的约束,不是这样。但是,另一种选择来自密码学。分组密码是键控双射映射,其中两个方向都可以很容易地计算给知道密钥的人。有很多方法可以构造它们,但Feistel ciphers 是一个很好的起点。它们将比 LCG“更随机”。每个键对应一个不同的双射(对于选择好的函数)。
    猜你喜欢
    • 1970-01-01
    • 2020-04-04
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 2012-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多