return generateKillerSudokuConstraints(N, killerRules, serialize)
+def getDomain(allPossible):
+ assert len(allPossible) > 0
+ domainNum = len(allPossible[0])
+ domain = [x[i] for x in allPossible for i in range(domainNum)]
+ return list(set(domain))
+
+def validateElements(elems):
+ for row in elems:
+ for elem in row:
+ assert elem != None
+
+def generateSumRange(domain1, domain2, totalSum):
+ range = set()
+ for d1 in domain1:
+ for d2 in domain2:
+ if (d1+d2) <= totalSum:
+ range.add(d1+d2)
+ return range
def generateKillerSudokuConstraints(N, killerRules, serialize):
csolverlb = ps.loadCSolver()
solver = csolverlb.createCCSolver()
- s1 = [ i for i in range(1, N+1)]
- set1 = (c_long* len(s1))(*s1)
- s1 = csolverlb.createSet(solver, c_uint(1), set1, c_uint(N))
- problem = np.array([[csolverlb.getElementVar(solver,s1) for i in range(N)] for i in range(N)])
+ problem = np.array([[None for i in range(N)] for i in range(N)])
elemConsts = [csolverlb.getElementConst(solver, c_uint(1), i) for i in range(1, N+1)]
csolverlb.addConstraint(solver,b);
def getElement(cage):
+ cageSum = cage[0]
+ cageSize = len(cage[1])
+ cageCells = cage[1]
+ cb = combinations([ii for ii in range(1, N+1)], cageSize)
+ f = lambda x : sum(x) == cageSum
+ comb = ifilter(f, cb) # all valid combinations
+ allPossible = list(chain(comb))
+ d1 = getDomain(allPossible)
+ set1 = (c_long* len(d1))(*d1)
+ s1 = csolverlb.createSet(solver, c_uint(1), set1, c_uint(len(d1)))
+ for i in range(len(cage[1])):
+ problem[cage[1][i][0]][cage[1][i][1]] = csolverlb.getElementVar(solver, s1);
elems = [ problem[cage[1][i][0]][cage[1][i][1]] for i in range(len(cage[1])) ]
+ #Elements in each cage shouldn't be identical
valid(elems)
- return elems
+ return elems, d1
- def generateSumConstraint(sumCage, elements):
- d = []
- for e in elements:
- d.append(csolverlb.getElementRange(solver, e))
- domains = (c_void_p *len(d))(*d)
+ def generateSumConstraint(sumCage, elements, domain):
+ assert len(elements) >1
+ parDomain = domain
+ parElem = elements[0]
overflow = csolverlb.getBooleanVar(solver, c_uint(2));
+ for i in range(len(elements)):
+ if i< len(elements) -1:
+ elem = elements[i+1]
+ set1 = (c_long* len(domain))(*domain)
+ s1 = csolverlb.createSet(solver, c_uint(1), set1, c_uint(len(domain)))
+ pS = (c_long* len(parDomain))(*parDomain)
+ parSet = csolverlb.createSet(solver, c_uint(1), pS, c_uint(len(parDomain)))
+ d = [s1, parSet]
+ domains = (c_void_p *len(d))(*d)
+ parDomain = generateSumRange(domain, parDomain, sumCage)
+ r = (c_long* len(parDomain))(*parDomain)
+ sumRange = csolverlb.createSet(solver, c_uint(1), r, c_uint(len(parDomain)))
+ f1 = csolverlb.createFunctionOperator(solver, ps.ArithOp.SATC_ADD, sumRange, ps.OverFlowBehavior.SATC_OVERFLOWSETSFLAG);
+ inp = [elem, parElem]
+ inputs = (c_void_p*len(inp))(*inp)
+ parElem = csolverlb.applyFunction(solver, f1, inputs, len(inp), overflow);
esum = csolverlb.getElementConst(solver, c_uint(3), c_long(sumCage))
setSum = csolverlb.getElementRange(solver, esum)
- f1 = csolverlb.createFunctionOperator(solver, ps.ArithOp.SATC_ADD, setSum, ps.OverFlowBehavior.SATC_OVERFLOWSETSFLAG);
- inputs = (c_void_p*len(elements))(*elements)
- added = csolverlb.applyFunction(solver, f1, inputs, len(elements), overflow);
-
- d = [setSum,setSum]
- domain = (c_void_p *len(d))(*d)
equals = csolverlb.createPredicateOperator(solver, c_uint(ps.CompOp.SATC_EQUALS))
- inp = [added,esum]
+ inp = [parElem,esum]
inputs = (c_void_p*len(inp))(*inp)
b = csolverlb.applyPredicate(solver,equals, inputs, c_uint(len(inp)))
csolverlb.addConstraint(solver,b);
if len(cage[1])==1:
problem[cage[1][0][0]][cage[1][0][1]] = csolverlb.getElementConst(solver, c_uint(7), c_long(sumCage))
continue
- elements = getElement(cage)
- generateSumConstraint(sumCage, elements)
-
+ elements, domain = getElement(cage)
+ generateSumConstraint(sumCage, elements, domain)
+ # Ensure there's no undefined element (for each cell we have a rule)
+ validateElements(problem)
# ensure each cell at least has one value!
for i,row in enumerate(problem):
for j, elem in enumerate(row):