使用约束库的跨世界难题求解器

时间:2018-11-29 09:38:07

标签: python constraint-programming

enter image description here

我有这个问题要解决,如图所示。我已经尝试过下面给出的代码

    # -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
from constraint import *

problem = Problem()

problem.addVariable('oneACROSS',['HOSES','LASER','SAILS','SHEET','STEER'])

problem.addVariable('fourACROSS',['HEEL','HIKE','KEEL','KNOT','LINE'])

problem.addVariable('sevenACROSS',['AFT','ALE','EEL','LEE','TIE'])

problem.addVariable('eightACROSS',['HOSES','LASER','SAILS','SHEET','STEER'])

problem.addVariable('twoDOWN',  ['HOSES','LASER','SAILS','SHEET','STEER'])

problem.addVariable('threeDOWN',  ['HOSES','LASER','SAILS','SHEET','STEER'])

problem.addVariable('fiveDOWN',['HEEL','HIKE','KEEL','KNOT','LINE'])

problem.addVariable('sixDOWN',['AFT','ALE','EEL','LEE','TIE'])

problem.addConstraint(lambda oneACROSS,twoDOWN : oneACROSS[3]==twoDOWN[1])

problem.addConstraint(lambda oneACROSS,threeDOWN : oneACROSS[5]==threeDOWN[1]) 

problem.addConstraint(lambda fourACROSS,twoDOWN : fourACROSS[2]==twoDOWN[3])

problem.addConstraint(lambda fourACROSS,fiveDOWN : fourACROSS[3]==fiveDOWN[1])

problem.addConstraint(lambda threeDOWN,fourACROSS : fourACROSS[4]==threeDOWN[3])

problem.addConstraint(lambda twoDOWN,sevenACROSS : sevenACROSS[1]==twoDOWN[4])

problem.addConstraint(lambda sevenACROSS,fiveDOWN : sevenACROSS[2]==fiveDOWN[2]) 

problem.addConstraint(lambda threeDOWN,sevenACROSS : sevenACROSS[3]==threeDOWN[4])

problem.addConstraint(lambda sixDOWN,eightACROSS : eightACROSS[1]==sixDOWN[2])

problem.addConstraint(lambda twoDOWN,eightACROSS : eightACROSS[3]==twoDOWN[5])

problem.addConstraint(lambda fiveDOWN,eightACROSS : eightACROSS[4]==fiveDOWN[3])

problem.addConstraint(lambda threeDOWN,eightACROSS : eightACROSS[5]==threeDOWN[5])

solution=problem.getSolutions()

print(solution)

但这给了我这个错误

runfile('C:/Users/aliya/.spyder-py3/temp.py',wdir ='C:/Users/aliya/.spyder-py3') 追溯(最近一次通话):

文件“”,第1行,在     runfile('C:/Users/aliya/.spyder-py3/temp.py',wdir ='C:/Users/aliya/.spyder-py3')

文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ spyder_kernels \ customize \ spydercustomize.py”,行668,在运行文件中     execfile(文件名,命名空间)

exec文件中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ spyder_kernels \ customize \ spydercustomize.py”,第108行     exec(compile(f.read(),文件名,'exec'),命名空间)

文件“ C:/Users/aliya/.spyder-py3/temp.py”,第50行,在     solution = problem.getSolutions()

getSolutions中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,第271行     返回self._solver.getSolutions(域,约束,vconstraints)

getSolutions中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,行567     返回列表(self.getSolutionIter(域,约束,vconstraints))

getSolutionIter中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,行544     如果没有约束(变量,域,分配,pushdomain):

调用中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,第991行     self.forwardCheck(变量,域,赋值)

文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,forwardCheck中的第935行     如果不是自变量(变量,域,赋值):

调用中的文件“ C:\ ProgramData \ Anaconda3 \ lib \ site-packages \ constraint__init __。py”,行993     返回self._func(* parms)

TypeError:lambda()接受2个位置参数,但给出了8个

对此有任何帮助!

3 个答案:

答案 0 :(得分:1)

在所有以problem.addConstraint开头的行上,您都使用以数字开头的变量名,例如1ACROSS2DOWN。 Python不允许这样做。例如,尝试将它们称为ONEACROSSTWODOWNVAR1ACROSSVAR2DOWN,它应该会更好。

答案 1 :(得分:0)

Python解析器禁止以这种方式命名变量,以便分别解析数字和变量,因为命名变量1e1会造成混乱-是数字10.0还是变量{{1 }}?

“ Python,请为我输出1e1!” -“为什么是10.0?我在那里存储了100!”

但是变量实际上是以允许将以数字开头的字符串绑定到值的方式存储的,因为该功能在任何类型的哈希映射中都无害,因此使用此“技巧”可以实现所需的数字前缀名称变量,而不会损害解析器的可分割性。

从技术上讲,以这种方式命名变量与python准则不违反,但是强烈建议不要这样做,并且通常是不必要的。使用全局变量来注入变量是一种非常坏习惯,并且这种情况不应该是未解决的。

所以改变

1e1

收件人:

problem.addConstraint(lambda 1ACROSS,2DOWN: 1ACROSS in range((1,1),(1,5)) and 2DOWN in range ((1,3),(5,3)) and 1ACROSS[2]==2DOWN[0])
problem.addConstraint(lambda 3DOWN,1ACROSS: 3DOWN in range((1,5),(5,5)) and 1ACROSS[4]==3DOWN[0])
problem.addConstraint(lambda 4ACROSS,5DOWN: 4ACROSS in range((3,2),(3,5)) and 5DOWN in range ((3,4),(6,4)) and 4ACROSS[1]==2DOWN[2] and 4ACROSS[2]==5DOWN[0] and 4ACROSS[3]==3DOWN[2])
problem.addConstraint(lambda 6DOWN,8ACROSS: 6DOWN in range((4,1),(6,1)) and 8ACROSS in range((5,1),(5,5)) and 6DOWN[1]==8ACROSS[0])

答案 2 :(得分:0)

亲爱的填字游戏是一个非常复杂的问题,我对此作业有解决方案,但由Google用ortools库实现。 以下是使用此库的要求: 要求:

**Library:** ortools by google

**Requirements for this library:**


**1-you have to install/update your pip forcefully by 2 commands:**
    1- "conda config --add channels conda-forge"
    2- "conda insatll pip=18.0"


**2-you have to update or install protobuf library version=3.6.1 using following command:**
    1- "pip insatll protobuf=3.6.1"


**3-if protobuf cannot istall following libraries with it you have to also install them:**
   1- six 1.11.1 (Query: pip install six=1.11.0).
   2- setuptools 40.6.2 (Query: pip install setuptools=40.6.2)
   3- ortools 6.10.6025 (Query: pip install ortools=6.10.6025)
**"pywrapcp"** this function will help for the creation of the solver.
**.IntVar() **function is used to add the varriable and domains
**.Add()** function is used to add constraints.

以下是此问题的代码:

    ## Author: Ahsan Azeem
## Solution of Crossword using ortools library
from ortools.constraint_solver import pywrapcp
def main():
  solver = pywrapcp.Solver("Problem")
  alpha = "_abcdefghijklmnopqrstuvwxyz"
  a = 1
  b = 2
  c = 3
  d = 4
  e = 5
  f = 6
  g = 7
  h = 8
  i = 9
  j = 10
  k = 11
  l = 12
  m = 13
  n = 14
  o = 15
  p = 16
  q = 17
  r = 18
  s = 19
  t = 20
  u = 21
  v = 22
  w = 23
  x = 24
  y = 25
  z = 26
  num_words = 15
  word_len = 5
  AA = [
      [h, o, s, e, s],  # HOSES
      [l, a, s, e, r],  # LASER
      [s, a, i, l, s],  # SAILS
      [s, h, e, e, t],  # SHEET
      [s, t, e, e, r],  # STEER
      [h, e, e, l, 0],  # HEEL
      [h, i, k, e, 0],  # HIKE
      [k, e, e, l, 0],  # KEEL
      [k, n, o, t, 0],  # KNOT
      [l, i, n, e, 0],  # LINE
      [a, f, t, 0, 0],  # AFT
      [a, l, e, 0, 0],  # ALE
      [e, e, l, 0, 0],  # EEL
      [l, e, e, 0, 0],  # LEE
      [t, i, e, 0, 0]  # TIE
  ]
  num_overlapping = 12
  overlapping = [
      [0, 2, 1, 0],  # s
      [0, 4, 2, 0],  # s
      [3, 1, 1, 2],  # i
      [3, 2, 4, 0],  # k
      [3, 3, 2, 2],  # e
      [6, 0, 1, 3],  # l
      [6, 1, 4, 1],  # e
      [6, 2, 2, 3],  # e
      [7, 0, 5, 1],  # l
      [7, 2, 1, 4],  # s
      [7, 3, 4, 2],  # e
      [7, 4, 2, 4]  # r
  ]
  n = 8
  A = {}
  for I in range(num_words):
    for J in range(word_len):
      A[(I, J)] = solver.IntVar(0, 26, "A(%i,%i)" % (I, J))
  A_flat = [A[(I, J)] for I in range(num_words) for J in range(word_len)]
  E = [solver.IntVar(0, num_words, "E%i" % I) for I in range(n)]
  solver.Add(solver.AllDifferent(E))
  for I in range(num_words):
    for J in range(word_len):
      solver.Add(A[(I, J)] == AA[I][J])
  for I in range(num_overlapping):
    # This is what I would do:
    # solver.Add(A[(E[overlapping[I][0]], overlapping[I][1])] ==  A[(E[overlapping[I][2]], overlapping[I][3])])
    # But we must use Element explicitly
    solver.Add(
        solver.Element(
            A_flat, E[overlapping[I][0]] * word_len + overlapping[I][1]) ==
        solver.Element(
            A_flat, E[overlapping[I][2]] * word_len + overlapping[I][3]))
  solution = solver.Assignment()
  solution.Add(E)
  db = solver.Phase(E + A_flat,
                    solver.INT_VAR_SIMPLE,
                    solver.ASSIGN_MIN_VALUE)
  solver.NewSearch(db)
  num_solutions = 0
  while solver.NextSolution():
    print(E)
    print_solution(A, E, alpha, n, word_len)
    num_solutions += 1
  solver.EndSearch()
  print()
  print("num_solutions:", num_solutions)
  print("failures:", solver.Failures())
def print_solution(A, E, alpha, n, word_len):
  for ee in range(n):
    print("%i: (%2i)" % (ee, E[ee].Value()), end=' ')
    print("".join(["%s" % (alpha[A[ee, ii].Value()]) for ii in range(word_len)]))
if __name__ == "__main__":
  main()

希望您能得到答案