Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Python创建拉丁方程序_Python_Latin Square - Fatal编程技术网

用Python创建拉丁方程序

用Python创建拉丁方程序,python,latin-square,Python,Latin Square,我试图输入一个订单,然后左上角的数量,并让它从那里创建一个拉丁方。问题是,我不知道如何让它在行和列中计数。该程序仅将左上角的数字按大小顺序x排列成方格。拉丁方是一个NP完全问题(请参阅),与数独一样,只是去掉了一些限制条件 你需要(以某种方式)搜索给定顺序的拉丁方空间。您有几种可能性: 1.手动状态空间搜索 您可以使用一些状态空间搜索技术自己编写拉丁方解算器。初始状态为拉丁方,除左上角字段外,其余字段均为空白。然后,您可以一次查看一个字段,并尝试将其设置为满足约束条件的数字。如果存在,则转到下一

我试图输入一个订单,然后左上角的数量,并让它从那里创建一个拉丁方。问题是,我不知道如何让它在行和列中计数。该程序仅将左上角的数字按大小顺序x排列成方格。

拉丁方是一个NP完全问题(请参阅),与数独一样,只是去掉了一些限制条件

你需要(以某种方式)搜索给定顺序的拉丁方空间。您有几种可能性:

1.手动状态空间搜索 您可以使用一些状态空间搜索技术自己编写拉丁方解算器。初始状态为拉丁方,除左上角字段外,其余字段均为空白。然后,您可以一次查看一个字段,并尝试将其设置为满足约束条件的数字。如果存在,则转到下一个字段,否则返回到父状态

你可以在在线状态空间搜索中找到大量的资源。搜索关键字,如:回溯、DFS、BFS、分支和绑定、A*

2.转换到另一个组合问题并使用现有解算器 您可以将此问题转换为另一个经过充分探索的组合优化问题,并使用解算器解决该问题

此问题可以表示为图着色-您可以通过以下方式将其转换为图着色问题:

  • 正方形中的每个字段是图形中的一个节点,正方形中的每个数字是一种颜色
  • 如果两个节点位于同一行或同一列中,则它们之间有一条边
  • 解决着色后,用数字替换颜色
  • 事实上,拉丁方(或多或少)是图着色,只是使用了不同的术语:)

    图着色可以通过CSP(约束满足编程)求解器解决,也可以直接将问题插入CSP

    您可以使用ILP(整数线性规划)求解它。有一些优化的解决方案。是一个开源的,并且有python绑定(例如)

    3.使用元启发式方法
    如果您找到一种方法来表示由某些数字填充的某个正方形的错误(例如,违反约束的数量,即同一行或列中相同数字的对的数量),您可以使用一些随机元启发式方法,如或,使用该误差函数将解决方案转化为有效的解决方案。

    您可以使用Jacobson和p.Matthews方法

    M.T.Jacobson和p.Matthews,生成均匀分布 《随机拉丁方》,J.组合设计4(1996),405-437


    以a为例。

    关键思想是您可以创建一个有效的行并旋转该行以生成一个有效的正方形:

    # Highest number in square
    order_of_sq = int(input("Enter order of sq: "))
    
    # Number you want to start the square with
    top_left = int(input("Enter top left number: "))
    
    # Sets a placeholder for a variable called top_left_init
    top_left_init = 0
    
    # Sets the initial value of top_left to a new variable because the code will
    # change the value of top left later on
    top_left_init += top_left
    
    # Initialize the value of count
    count = 0
    
    # Add 1 to the highest value in latin square to account for the range function
    # (the ending number is always one less than the number you enter into the
    # range function)
    for values in range(1, order_of_sq + 1):
    
        # Prevents the program from adding too many characters to the line
        while count != order_of_sq:
    
            # Prints numbers with spaces after them in a horizontal manner
            print(top_left, sep=" ", end=" ")
    
            # Adds 1 to the top_left
            top_left += 1
    
            # Count is used to keep track of how many characters are in your line
            count += 1
    
            # Restarts the numbers in your line when you reach the highest number
            if top_left == order_of_sq + 1:
                top_left = 1
    
        # Creates a new row
        print()
        count = 0
    
        # Calls the initial value of top_left and adds 1 to it before beginning the
        # next row
        top_left_init += 1
    
        # Resets top_left_init to 1 if it reaches the highest number in the square
        if top_left_init == order_of_sq + 1:
            top_left_init = 1
            top_left = top_left_init
        else:
            top_left = top_left_init
    
    大小为4的正方形如下所示:

    def create_latin_square(n: int):
        row = [i for i in range(1, n+1)]
        return [row[i:] + row[:i] for i in range(n)]
    
    然后只需旋转第一行:

    [1, 2, 3, 4]  # row
    [2, 3, 4, 1]  # row, rotated by 1 to the left
    [3, 4, 1, 2]  # row, rotated by 2 to the left
    [4, 1, 2, 3]  # row, rotated by 3 to the left
    
    这个怎么样

    def create_latin_square(n: int, start_el: int=1):
        row = [i for i in range(1, n+1)]
        row = row[start_el-1:] + row[:start_el-1]
        return [row[i:] + row[:i] for i in range(n)]
    

    你到底想让你的代码做什么?用户输入左上角的数字(您可能应该检查该数字是否在1..order范围内),然后打印出填充的拉丁方?这应该包括对代码的解释,所有代码的答案都没有价值。@TristanWiley:我正要问“但是注释呢?”时,我意识到它们并不是一个很好的补充。尽管如此,代码还是有一个内置的解释,只是没有关注最有趣的部分。这些注释是为了帮助他/她从头到尾遵循程序。学生可以很容易地在谷歌上搜索拉丁方来加深对这个概念的理解。“拉丁方是一个NP完全问题”——并不总是这样。特别是当我的解决方案显示只有一个单元格被填充时。这里的问题是拉丁方构造,而不是拉丁方完成,所以它不是NP完全的。除了回溯,所有这些方法都是多余的。
    def create_latin_square(n: int, start_el: int=1):
        row = [i for i in range(1, n+1)]
        row = row[start_el-1:] + row[:start_el-1]
        return [row[i:] + row[:i] for i in range(n)]
    
    def latin_square(n, mod='ballanced'):
      import numpy as np
    
      mat = np.empty((n,n,))*np.nan
    
      mat[:,0] = range(1,n+1)
    
      if mod=='ballanced':
        shift = (.5-np.mod(np.array(range(1,n)),2))/.5*np.ceil(np.array(range(1,n))/2)
        shift = shift.astype(int)
      elif mod=='normal':
        shift = np.array(range(n-1, -1, -1))
    
      for col in range(1, n):
        mat[:, col] = np.roll(mat[:,0], shift[col-1])
        
      return(mat)
    
    
    latin_square(6)
    
    array([[1., 2., 6., 3., 5., 4.],
       [2., 3., 1., 4., 6., 5.],
       [3., 4., 2., 5., 1., 6.],
       [4., 5., 3., 6., 2., 1.],
       [5., 6., 4., 1., 3., 2.],
       [6., 1., 5., 2., 4., 3.]])