Download
#!/usr/bin/python
"""
Magic hexagon in Numberjack.

Prob023: Magic Hexagon
http://www.comp.rgu.ac.uk/staff/ha/ZCSP/prob023/prob023.pdf
http://www.cse.unsw.edu.au/~tw/csplib/prob/prob023/
'''
A magic hexagon consists of the number 1 to 19 arranged in a hexagonal pattern:

   A,B,C
  D,E,F,G
 H,I,J,K,L
  M,N,O,P
   Q,R,S

We have a constraint that all diagonals sum to 38. That is,
   A+B+C = D+E+F+G = ... = Q+R+S = 38, A+D+H = B+E+I+M = ... = L+P+S = 38,
   C+G+L = B+F+K+P = ... = H+M+Q = 38.
'''

Compare with the following models:
* SICStus Prolog: http://www.hakank.org/sicstus/magic_hexagon.pl
* ECLiPSe: http://www.hakank.org/eclipse/magic_hexagon.ecl

This model was created by Hakan Kjellerstrand (hakank@bonetmail.com)
See also my Numberjack page http://www.hakank.org/numberjack/

"""
from Numberjack import *

class MyAllDiff(Predicate):
    
    def __init__(self, vars):
        Expression.__init__(self, "MyAllDiff")
        self.set_children(vars)

    def decompose(self):
        return [var1 != var2 for var1, var2 in pair_of(self.children)]


def model(libs):

    N = 19
    LD = VarArray(N, 1, N, 'LD')
    a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s = LD

    model = Model (
        AllDiff(LD),
        # MyAllDiff(LD), # FIX!
        a + b + c ==  38,
        d + e + f + g ==  38,
        h + i + j + k + l ==  38, 
        m + n + o + p ==  38, 
        q + r + s ==  38, 
        a + d + h ==  38, 
        b + e + i + m ==  38, 
        c + f + j + n + q ==  38, 
        g + k + o + r ==  38, 
        l + p + s ==  38, 
        c + g + l ==  38, 
        b + f + k + p ==  38, 
        a + e + j + o + s ==  38, 
        d + i + n + r ==  38, 
        h + m + q ==  38, 
        a < c,
        a < h,
        a < l,
        a < q,
        a < s,
        c < h
        )

    print model

    for library in libs:
        solver = model.load(library) # Load up model into solver
        print ''
        if solver.solve():
            solver.printStatistics()
            print 'LD:', LD
            print ''
            num_solutions = 1
            while solver.getNextSolution() == SAT: 
                num_solutions += 1
                print 'LD:', LD
                print ''
            print 'Number of solutions: ', num_solutions
            print 'Nodes:', solver.getNodes(), ' Time:', solver.getTime()
            print 'getPropags:', solver.getPropags()
            print 'getBacktracks:', solver.getBacktracks()
            print 'getFailures:', solver.getFailures()
        else:
            print 'No solution'
        print ''


model(['Mistral'])