鱼C论坛

 找回密码
 立即注册
查看: 1029|回复: 0

[技术交流] 生成前n个正整数的置换: With/without numpy

[复制链接]
发表于 2021-11-28 22:02:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我写了两段代码,用于返回前 n 个自然数的置换全体:例如当 n = 2 时, 返回 [1,2], [2,1]; n = 3 时, 返回 [1, 2, 3], [1, 3, 2], [2, 1, 3],  [2, 3, 1],  [3, 1, 2],  [3, 2, 1]. 数学上采用同一个原理,区别是一个用numpy的数据结构和方法,另一个用 list.

两段代码如下:

用 numpy 的:
  1. # permutationGenerator

  2. # Author: Xing Gu
  3. # Date: 2021/11/23

  4. def permutation(n):
  5.     """For a positive integer n, returns all the permutations of n as a generator, each permutation being a list of n
  6.     integers. """
  7.     # Manually yield permutation(n) for n=1,2,3.

  8.     import numpy as np

  9.     if n == 0:
  10.         yield np.arange(0, dtype=int)
  11.     elif n == 1:
  12.         yield np.arange(1,2,  dtype=int)
  13.     elif n == 2:
  14.         for item in np.array([[1, 2], [2, 1]], dtype=int):
  15.             yield item
  16.     elif n == 3:
  17.         for item in np.array([[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]], dtype=int):
  18.             yield item
  19.     else:
  20.         # Recursively yield permutation(n) for n>3, the recursion step length being 3.
  21.         for i in range(n):
  22.             for j in range(n):
  23.                 if i == j:
  24.                     continue
  25.                 for k in range(n):
  26.                     if j == k or i == k:
  27.                         continue
  28.                     im123 = np.array([i + 1, j + 1, k + 1])
  29.                     # the image of 1,2,3 of the permutation sorted in ascending order
  30.                     im123Sorted = np.sort(im123)
  31.                     # To obtain im4plus, first acquire the permutation of n-3, and then change the values to skip the
  32.                     # images of 1,2,3.
  33.                     # the image of 4,..., n of the permutation
  34.                     im4PlusSorted = np.arange(1, n - 2) + np.concatenate((np.zeros(im123Sorted[0] - 1), \
  35.                                                     np.ones(im123Sorted[1] - im123Sorted[0] - 1), \
  36.                                                     np.ones(im123Sorted[2] - im123Sorted[1] - 1) * 2, \
  37.                                                     np.ones(n - im123Sorted[2]) * 3))
  38.                     for item in permutation(n - 3):
  39.                         im4Plus = im4PlusSorted[item - 1]
  40.                         yield np.concatenate((im123, im4Plus)).astype(int)


  41. if __name__ == '__main__':
  42.     import timeit

  43.     counter = 0
  44.     start = timeit.default_timer()
  45.     for item in permutation(10):
  46.         print(item)
  47.         counter += 1
  48.     stop = timeit.default_timer()
  49.     print('Counter: ', counter)
  50.     print('Time: ', stop - start)
复制代码


不用 numpy 的:

  1. # permutationGeneratorNieve

  2. # Author: Xing Gu
  3. # Date: 2021/11/23

  4. def permutation(n):
  5.     """For a positive integer n, returns all the permutations of n as a generator, each permutation being a list of n
  6.     integers. """
  7.     # Manually yield permutation(n) for n=1,2,3.
  8.     if n == 0:
  9.         yield []
  10.     elif n == 1:
  11.         yield [1]
  12.     elif n == 2:
  13.         for item in ([[1, 2], [2, 1]]):
  14.             yield item
  15.     elif n == 3:
  16.         for item in ([1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]):
  17.             yield item
  18.     else:
  19.         # Recursively yield permutation(n) for n>3, the recursion step length being 3.
  20.         for i in range(n):
  21.             for j in range(n):
  22.                 if i == j:
  23.                     continue
  24.                 for k in range(n):
  25.                     if j == k or i == k:
  26.                         continue
  27.                     im123 = [i + 1, j + 1, k + 1]
  28.                     # the image of 1,2,3 of the permutation sorted in ascending order
  29.                     im123Sorted = sorted(im123)
  30.                     # To obtain im4plus, first acquire the permutation of n-3, and then change the values to skip the
  31.                     # images of 1,2,3.
  32.                     # the image of 4,..., n of the permutation
  33.                     for item in permutation(n - 3):
  34.                         im4Plus = []
  35.                         for l in item:
  36.                             if l > im123Sorted[2] - 3:
  37.                                 im4Plus.append(l + 3)
  38.                             elif l > im123Sorted[1] - 2:
  39.                                 im4Plus.append(l + 2)
  40.                             elif l > im123Sorted[0] - 1:
  41.                                 im4Plus.append(l + 1)
  42.                             else:
  43.                                 im4Plus.append(l)
  44.                         # Yield a permutation of n.
  45.                         yield im123 + im4Plus


  46. if __name__ == '__main__':
  47.     import timeit

  48.     counter = 0
  49.     start = timeit.default_timer()
  50.     for item in permutation(10):
  51.         print(item)
  52.         counter += 1
  53.     stop = timeit.default_timer()
  54.     print('Counter: ', counter)
  55.     print('Time: ', stop - start)
复制代码



按理说 numpy相对于python自带的数据结构优化了许多,然而用以上两段代码分别返回前十个正整数的全体置换(3628800个arraies/lists)时,在同一台设备上,前者用时488.1秒,后者29.3秒。用numpy反而慢了十几倍!

问题:(1)当 n 很大时,第一段代码比第二段是否会有更好的表现?(2)在这个任务中是否有更合理的办法使用numpy?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-30 23:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表