在python中创建一个Latin Square程序

时间:2014-09-22 23:45:39

标签: python latin-square

order=input('Input the order of a Latin Square: ')
top_left=input('Input the top-left number: ')
int_order=int(order)
int_top_left=int(top_left)
for order in range(int_order):
    for top_left in range(int_order):
        print(int_top_left, end = ' ')
    print()

所以我想输入一个订单,然后输入一个左上角的数量并让它从那里创建一个拉丁方,问题是我不知道如何让它在行和列中计数,这个程序仅将左上角数字排列在方形网格中,大小顺序为x阶。任何帮助表示赞赏。

5 个答案:

答案 0 :(得分:3)

拉丁方是一个NP完全问题(参见http://en.wikipedia.org/wiki/Latin_square#Mathematical_puzzles),就像数独一样,只有一些约束被删除。

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

1。手动状态空间搜索

您可以使用一些状态空间搜索技术自己编写Latin Square解算器。您的初始状态将是拉丁广场,除了左上角字段之外​​的所有字段都是空白。您可以一次查看一个字段并尝试将其设置为满足约束条件的数字。如果有,请继续进入下一个字段,否则回溯到父状态。

您可以在线状态空间搜索中找到巨大数量的资源。搜索关键字:回溯,DFS,BFS,分支和界限,A *

2。转换为另一个组合问题并使用现有的求解器

您可以将此问题转换为另一个经过深入研究的组合优化问题,并使用解算器。

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

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

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

    您可以使用ILP(整数线性编程)解决它。有调整解决方案。 GLPK是开源的,并且有python绑定(例如PyGLPK

    3。使用元启发式方法

    如果你想办法如何表达一些由某些数字填充的方格的错误(例如,约束违规的数量,即同一行或列中相同数字的对数),你可以使用一些随机数像Simmulated AnnealingEvolutionary Algorithms这样的metaheuristics使用该错误函数将解决方案驱动为有效的解决方案。

答案 1 :(得分:1)

您可以使用Jacobson和P. Matthews方法。

  

微米。 T. Jacobson和P. Matthews,生成均匀分布   随机拉丁方,J. Combinatorial Design 4(1996),405-437

选择look

答案 2 :(得分:1)

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

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)]

4号正方形看起来像这样:

[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)]

答案 3 :(得分:1)

这是什么?

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.]])

答案 4 :(得分:0)

#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

main()的