Esempio n. 1
0
from pyDatalog import pyDatalog
from datalog import Datalog, kvp

fdb.api_version(300)
db = fdb.open()

# app is a subspace for an open directory
app = fdb.directory.create_or_open(db, ('app,'))
Datalog(app, 10)

############################
##   Relational Algebra   ##
############################

pyDatalog.create_atoms('q,r,s,X,Y,Z')

# Select
r(X,'foo')

# Project
q(X) <= r(X,Y)

# Join
q(X, Y, Z) <= r(X, Y) & s(X, Z)

###################################
##   Beyond Relational Algebra   ##
###################################

pyDatalog.create_atoms('closure,edge,Source,Target,Intermediate')
Esempio n. 2
0
from pyDatalog import pyDatalog
import time
from pyDatalog import pyEngine

pyDatalog.create_atoms('N,N1, X,Y, X0,X1,X2')
pyDatalog.create_atoms('ok,queens')

# when is it ok to have a queen in row X1 and another in row X2, separated by N columns
# this is memoized !
size = 7
ok(X1, N,
   X2) <= (X1._in(range(size))) & (X1 != X2) & (X1 != X2 + N) & (X1 != X2 - N)
queens(1, X) <= (X1._in(range(size))) & (X == (X1, ))  #TODO
queens(N, X) <= (N > 1) & (N1 == N - 1) & X0._in(range(size)) & queens(
    N1, Y) & ok(Y[0], N1, X0) & queens(N1, Y[1:] + (X0, )) & (X == Y + (X0, ))
print(queens(size, X))

# counting is 0-based, so this is actually the 8-queens solution
# there is a fixed penalty the first time around (JIT, ...), so let's measure performance the second time
start_time = time.time()
datalog_count = len(queens(size, X).data)
datalog_time = (time.time() - start_time)

# pure python solution found on http://rosettacode.org/wiki/N-Queens#Python, for comparison purposes

from itertools import permutations

n = 8
cols = range(n)

Esempio n. 3
0
"""
This file shows how to use pyDatalog using facts stored in datalog.

It has 3 parts:
    1. create facts for 2 employees in the datalog engine
    2. define business rules
    3. Query the datalog engine
"""
from pyDatalog import pyDatalog

""" 1. create facts for 3 employees in the datalog engine """
pyDatalog.create_atoms('salary', 'manager')

# John is the manager of Mary, who is the manager of Sam
+ (salary['John'] == 6800)

+ (manager['Mary'] == 'John')
+ (salary['Mary'] == 6300)

+ (manager['Sam'] == 'Mary')
+ (salary['Sam'] == 5900)

""" 2. define business rules """
pyDatalog.create_atoms('salary_class', 'indirect_manager', 'report_count', 'budget', 'lowest',
                       'X', 'Y', 'Z', 'N')
# the salary class of employee X is computed as a function of his/her salary
salary_class[X] = salary[X]//1000
    
# all the indirect managers of employee X are derived from his manager, recursively
indirect_manager(X,Y) <= (manager[X] == Y) & (Y != None)
indirect_manager(X,Y) <= (manager[X] == Z) & indirect_manager(Z,Y) & (Y != None)
Esempio n. 4
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms('has_field', 'bean_pair', 'str_cat', \
    'get_type', 'set_type')

+ has_field('o1', 'a', 't')
+ has_field('o1', 'b', 's')
+ bean_pair('o1', 'bean1')

+ bean_pair('o2', 'bean2')

+ str_cat('get-', 'a', 'get-a')
+ str_cat('get-', 'b', 'get-b')
+ str_cat('set-', 'a', 'set-a')
+ str_cat('set-', 'b', 'set-b')

+ get_type('t', '()->t')
+ get_type('s', '()->s')

+ set_type('t', 't->()')
+ set_type('s', 's->()')

##################################################
# Rules

pyDatalog.create_atoms('O', 'Bean', 'A', 'B', 'T', 'S')

# Bean should have 'field' if O has 'field'
Esempio n. 5
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms('str_cat', 'has_field', 'object', 'void_arrow')

+ str_cat('get-','a','get-a')

# void_arrow(s, t) if s = void -> t
+ void_arrow('s', 't')

# well formed
+ object('o')
+ has_field('o', 'a', 't')
+ has_field('o', 'get-a', 's')

# well formed
+ object('r')

# ill formed - missing getter
+ object('p')
+ has_field('p', 'a', 't')

# ill formed - getter without field to get
+ object('q')
+ has_field('q', 'get-a', 's')

# ill formed - getter has wrong type
+ object('u')
+ has_field('u', 'a', 't')
Esempio n. 6
0
from pyDatalog import pyDatalog
from datalog import Datalog, kvp

fdb.api_version(300)
db = fdb.open()

# app is a subspace for an open directory
app = fdb.directory.create_or_open(db, ('app,'))
Datalog(app, 10)

############################
##   Relational Algebra   ##
############################

pyDatalog.create_atoms('q,r,s,X,Y,Z')

# Select
r(X, 'foo')

# Project
q(X) <= r(X, Y)

# Join
q(X, Y, Z) <= r(X, Y) & s(X, Z)

###################################
##   Beyond Relational Algebra   ##
###################################

pyDatalog.create_atoms('closure,edge,Source,Target,Intermediate')
Esempio n. 7
0
"""
This file shows how to use pyDatalog using facts stored in datalog.

It has 3 parts:
    1. create facts for 2 employees in the datalog engine
    2. define business rules
    3. Query the datalog engine
"""
from pyDatalog import pyDatalog

""" 1. create facts for 3 employees in the datalog engine """
pyDatalog.create_atoms("salary", "manager")

# John is the manager of Mary, who is the manager of Sam
+(salary["John"] == 6800)

+(manager["Mary"] == "John")
+(salary["Mary"] == 6300)

+(manager["Sam"] == "Mary")
+(salary["Sam"] == 5900)

""" 2. define business rules """
pyDatalog.create_atoms("salary_class", "indirect_manager", "report_count", "budget", "lowest", "X", "Y", "Z", "N")
# the salary class of employee X is computed as a function of his/her salary
salary_class[X] = salary[X] // 1000

# all the indirect managers of employee X are derived from his manager, recursively
indirect_manager(X, Y) <= (manager[X] == Y) & (Y != None)
indirect_manager(X, Y) <= (manager[X] == Z) & indirect_manager(Z, Y) & (Y != None)
Esempio n. 8
0
# create table
Base.metadata.create_all(engine) 

# create rows for 3 employees
# John is the manager of Mary, who is the manager of Sam
John = Employee('John', None, 6800)
Mary = Employee('Mary', 'John', 6300)
Sam = Employee('Sam', 'Mary', 5900)

session.add(John)
session.add(Mary)
session.add(Sam)
session.commit()

""" 4. Query the objects using the datalog engine """
pyDatalog.create_atoms('X, Y, N, lowest')

# the following python statements implicitly use the datalog clauses in the class definition

# What is the salary class of John ?
print(John.salary_class) # prints 6

# who has a salary of 6300 ?
X = pyDatalog.Variable()
Employee.salary[X] == 6300 # notice the similarity to a pyDatalog query
print(X) # prints [Employee: Mary]
print(X.v()) # prints Employee:Mary

# who are the indirect managers of Mary ?
Employee.indirect_manager(Mary, X)
print(X) # prints [Employee: John]
Esempio n. 9
0
def StrToList(A):
    C = []
    for i in A:
        C.append(i)
    return C


x = '双眼病变'
a = StrToList(x)
y = '双眼发病'
b = StrToList(y)
c = SBS(a, b)
print(c)
from pyDatalog import pyDatalog

pyDatalog.create_atoms('N, N1, X, Y, X0, X1, X2, X3, X4, X5, X6, X7')
pyDatalog.create_atoms('ok, queens, next_queen, pred, pred2')

size = 8
ok(X1, N, X2) <= (X1 != X2) & (X1 != X2 + N) & (X1 != X2 - N)

pred(N, N1) <= (N > 1) & (N1 == N - 1)
queens(1, X) <= (X1._in(range(size))) & (X1 == X[0])
queens(N, X) <= pred(N, N1) & queens(N1, X[:-1]) & next_queen(N, X)

pred2(N, N1) <= (N > 2) & (N1 == N - 1)
next_queen(2, X) <= (X1._in(range(8))) & ok(X[0], 1, X1) & (X1 == X[1])
next_queen(N, X) <= pred2(N, N1) & next_queen(N1, X[1:]) & ok(X[0], N1, X[-1])

print(queens(size, (X0, X1, X2, X3, X4, X5, X6, X7)))
Esempio n. 10
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms('has_field', 'caja_output', 'str_cat')

# well formed
+ caja_output('c1')
+ has_field('c1', 'a', 't')
+ has_field('c1', 'a_v__', 't')
+ has_field('c1', 'a_w__', 'bool')
+ has_field('c1', 'b', 's')
+ has_field('c1', 'b_v__', 's')
+ has_field('c1', 'b_w__', 'bool')

# ill formed - missing b
+ caja_output('c2')
+ has_field('c2', 'a', 't')
+ has_field('c2', 'a_v__', 't')
+ has_field('c2', 'a_w__', 'bool')
+ has_field('c2', 'b_v__', 's')
+ has_field('c2', 'b_w__', 'bool')

# ill formed - a_v__ has wrong type
+ caja_output('c3')
+ has_field('c3', 'a', 't')
+ has_field('c3', 'a_v__', 's')
+ has_field('c3', 'a_w__', 'bool')
+ has_field('c3', 'b', 's')
+ has_field('c3', 'b_v__', 's')
Esempio n. 11
0
""" 3. create table and rows for 2 employees """
# create table
Base.metadata.create_all(engine)

# create rows for 3 employees
# John is the manager of Mary, who is the manager of Sam
John = Employee('John', None, 6800)
Mary = Employee('Mary', 'John', 6300)
Sam = Employee('Sam', 'Mary', 5900)

session.add(John)
session.add(Mary)
session.add(Sam)
session.commit()
""" 4. Query the objects using the datalog engine """
pyDatalog.create_atoms('X, Y, N, lowest')

# the following python statements implicitly use the datalog clauses in the class definition

# What is the salary class of John ?
print(John.salary_class)  # prints 6

# who has a salary of 6300 ?
X = pyDatalog.Variable()
Employee.salary[X] == 6300  # notice the similarity to a pyDatalog query
print(X)  # prints [Employee: Mary]
print(X.v())  # prints Employee:Mary

# who are the indirect managers of Mary ?
Employee.indirect_manager(Mary, X)
print(X)  # prints [Employee: John]
Esempio n. 12
0
from pyDatalog import pyDatalog
import time
from pyDatalog import pyEngine

pyDatalog.create_atoms('N,N1, X,Y, X0,X1,X2')
pyDatalog.create_atoms('ok,queens')

# when is it ok to have a queen in row X1 and another in row X2, separated by N columns
# this is memoized !
size=7
ok(X1, N, X2) <= (X1._in(range(size))) & (X1!=X2) & (X1!= X2+N) & (X1!=X2-N)
queens(1, X) <= (X1._in(range(size))) & (X==(X1,)) #TODO
queens(N, X) <= (N>1) & (N1==N-1) & X0._in(range(size)) & queens(N1, Y) &  ok(Y[0], N1, X0) & queens(N1, Y[1:]+(X0,)) & (X==Y+(X0,))  
print(queens(size, X))


# counting is 0-based, so this is actually the 8-queens solution
# there is a fixed penalty the first time around (JIT, ...), so let's measure performance the second time
start_time = time.time()
datalog_count = len(queens(size, X).data)
datalog_time = (time.time() - start_time)


# pure python solution found on http://rosettacode.org/wiki/N-Queens#Python, for comparison purposes

from itertools import permutations

n = 8
cols = range(n)
def queens():
Esempio n. 13
0
import itertools

import fdb
import fdb.tuple

from pyDatalog import pyDatalog, pyEngine

fdb.api_version(300)

db = fdb.open()

pyDatalog.create_atoms('kvp')


class Datalog(object):

    def __init__(self, subspace, max_arity):
        self.subspace = subspace
        self.max_arity = max_arity
        self._create_generic_fdb()

    #####################################
    ##   Generic FDB Predicates: kvp   ##
    #####################################

    @fdb.transactional
    def _get_generic_predicate(self, tr, prefix_tuple, partial_key):
        if partial_key:
            for k, v in tr[self.subspace.range(prefix_tuple)]:
                yield k, v
        else:
Esempio n. 14
0
from pyDatalog import pyDatalog
import time

pyDatalog.create_atoms('N,X0,X1,X2,X3,X4,X5,X6,X7')
pyDatalog.create_atoms('ok,queens0,queens1,queens2,queens3,queens4,queens5,queens6,queens7')

# when is it ok to have a queen in row X1 and another in row X2, separated by N columns
# this is memoized !
ok(X1, N, X2) <= (X1!=X2) & (X1!= X2+N) & (X1!=X2-N)

queens0(X0) <= (X0._in(range(8)))
queens1(X0,X1) <= queens0(X0) & queens0(X1) & ok(X1,1,X0)
queens2(X0,X1,X2) <= queens1(X0,X1) & queens1(X1,X2) & ok(X0,2,X2)
queens3(X0,X1,X2,X3) <= queens2(X0,X1,X2) & queens2(X1,X2,X3) & ok(X0,3,X3)
queens4(X0,X1,X2,X3,X4) <= queens3(X0,X1,X2,X3) & queens3(X1,X2,X3,X4) & ok(X0,4,X4)
queens5(X0,X1,X2,X3,X4,X5) <= queens4(X0,X1,X2,X3,X4) & queens4(X1,X2,X3,X4,X5) & ok(X0,5,X5)
queens6(X0,X1,X2,X3,X4,X5,X6) <= queens5(X0,X1,X2,X3,X4,X5) & queens5(X1,X2,X3,X4,X5,X6) & ok(X0,6,X6)
queens7(X0,X1,X2,X3,X4,X5,X6,X7) <= queens6(X0,X1,X2,X3,X4,X5,X6) & queens6(X1,X2,X3,X4,X5,X6,X7) & ok(X0,7,X7)

# counting is 0-based, so this is actually the 8-queens solution
print(queens7(X0,X1,X2,X3,X4,X5,X6,X7))
    
# there is a fixed penalty the first time around (JIT, ...), so let's measure performance the second time
start_time = time.time()
datalog_count = len(queens7(X0,X1,X2,X3,X4,X5,X6,X7))
datalog_time = (time.time() - start_time)

# pure python solution found on http://rosettacode.org/wiki/N-Queens#Python, for comparison purposes

from itertools import permutations
Esempio n. 15
0
"""
This file contains the code for the interactive online datalog tutorial.
https://sites.google.com/site/pydatalog/Online-datalog-tutorial
"""

from pyDatalog import pyDatalog
pyDatalog.create_atoms('parent,bill,ancestor,descendents,manager, X,Y,Z,N,F,  factorial,odd,even, _split')

+ parent(bill,'John Adams')

print(parent(bill,X)) # prints [('John Adams',)]

# specify what an ancestor is
ancestor(X,Y) <= parent(X,Y)
ancestor(X,Y) <= parent(X,Z) & ancestor(Z,Y)

print(ancestor(bill, X)) # prints [('John Adams',)]

# the manager of bill is John Adams. Bill has only one manager.
+ (manager[bill]=='John Adams') 

print(manager[bill]==X) # prints [('John Adams',)]

# use expressions and recursion to evaluate factorials
(factorial[N] == F) <= (N < 2) & (F==1)
(factorial[N] == F) <= (N > 1) & (F == N*factorial[N-1])

print(factorial[3]==N) # prints [(6,)]

# aggregate function
# calculate the list of descendents, sorted by their name, and separated by ','
Esempio n. 16
0
    assert result == [(John, 6800)]

    """
    result = Employee.p(John, Employee.salary[John]) # TODO
    print(result)
    result = (Employee.salary[X]==6800) & Employee.p(X, Employee.salary[X]) # TODO
    print (result)
    """
    
if __name__ == "__main__":
    test()
    #cProfile.runctx('test()', globals(), locals())
    
    """ In-line queries using create_atoms                    """
    
    pyDatalog.create_atoms('p', 'Y, eq, Z')
    +p('a')
    
    p(Y)
    assert (Y._value() == ['a',])
    
    X = pyDatalog.Variable()
    pyDatalog.create_atoms('X')
    p(X) & (X=='b')
    assert (X._value() == [])
    
    pyDatalog.create_atoms('p2')
    
    def test2():
        p2(X) <= p(X)
        p2(X)
Esempio n. 17
0
:Institucion: Instituto Tecnologico de Costa Rica
:Curso: Inteligencia Artificial
:Grupo: 2
:Semestre: I Semestre 2018
:Autores: Fernanda Alvarado Vargas,[email protected] /
          Minor Sancho Valverde,[email protected] /
          Freyser Jimenez Mena, [email protected] /
:Fecha: 06/17/2018
"""
# -----------------------------------------------------------------------
from pyDatalog import pyDatalog
import csv
from time import time
import numpy as np
pyDatalog.create_atoms('idioma_aportando,contar_palabras,padre,\
                        hermano,tio,primo,hijo,palabra_idioma,idioma_palabra,\
                        contar_palabras_comunes,listar_palabras_comunes,\
                        ancestro,descendiente,idioma,palabra_comun,P,X,Y,A,B')
lenguajes1 = ['idioma_x', 'idioma_y', 'idioma_z']

# -----------------------------------------------------------------------
################################### 1 ##################################
"""
Funcion que nos permite obtener los datos de cada linea del archivo.
"""


# -----------------------------------------------------------------------
def buscar_dos_puntos_mayor_rendimiento(lista):
    acum = []
    for i in lista:
        pos = i.find(':')
Esempio n. 18
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms("has_field", "spec", "model")

# well formed
+spec("spec1")
+has_field("spec1", "a", "t")
+has_field("spec1", "b", "s")
+has_field("spec1", "id", "string")

# ill formed - id has wrong type
+spec("spec2")
+has_field("spec2", "a", "t")
+has_field("spec2", "b", "s")
+has_field("spec2", "id", "t")

# well formed
+model("model1-1")
+has_field("model1-1", "attributes", "attrs1-1")
+has_field("model1-1", "cid", "string")
+has_field("model1-1", "id", "string")

+has_field("attrs1-1", "a", "t")
+has_field("attrs1-1", "b", "s")
+has_field("attrs1-1", "id", "string")

# ill formed - missing fields from attrs
+model("model1-2")
Esempio n. 19
0
# give me all the X that have a salary of 110
print(salary[X]==110)

# not Y?
print((salary[X]==Y) & ~(Y==110))


+(tax_rate[None]==0.33)
# give me the net salary for all X
print((Z==salary[X]*(1-tax_rate[None])))





pyDatalog.create_atoms('factorial, N, F') # gives datalog capability to these words

def run_program():

    N = pyDatalog.Variable()
    F = pyDatalog.Variable()
    file_in = open("sample_datalog_program.dl", 'r')
    mc = file_in.read()
    print mc
    @pyDatalog.program()
    def _(): # the function name is ignored
        pyDatalog.load(mc)
        #pyDatalog.load("""
        #+ (factorial[1]==1)
        #(factorial[N] == F) <= (N > 1) & (F == N*factorial[N-1])
        #""")
Esempio n. 20
0
from pyDatalog import pyDatalog
# OUT: pyDatalog version 0.12.0

# create some atoms. an atomic could a symbol, varaiable (and others)
pyDatalog.create_atoms('people, alice, bob')

# insert a fact
+ people(alice)

# 'people' is a symbol
print people
# OUT: <pyDatalog.pyParser.Symbol object at 0x93e744c>

# declare a variable
pyDatalog.create_atoms('X')

# query the instances of people
print(people(X))
# OUT: [('alice',)]
# it's a unary tuple

for i in people(X): print i
# OUT: ('alice',)

# add more instance of people
+ people(bob)
for i in people(X): print i
# OUT: ('alice',)
# OUT: ('bob',)

# you can see from below, an atom may be a symbol or a var
Esempio n. 21
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms('has_field', 'model')

+ has_field('spec1', 'a', 't')
+ has_field('spec1', 'b', 's')
+ has_field('spec1', 'id', 'string')
+ model('spec1', 'model1')

+ has_field('spec2', 'x', 'bool')
+ model('spec2', 'model2')

+ model('spec3', 'model3')

##################################################
# Rules

pyDatalog.create_atoms('Spec', 'Model', 'Attrs', 'A', 'B', 'T', 'S')

pyDatalog.create_atoms('attrs')
+ attrs('model1', 'attrs1')
+ attrs('model2', 'attrs2')
+ attrs('model3', 'attrs3')

# Model should have a 'cid' field
has_field(Model, 'cid', 'string') <= \
    model(Spec, Model)
Esempio n. 22
0
from pyDatalog import pyDatalog

##################################################
# Facts

pyDatalog.create_atoms('has_field', 'caja_pair', 'str_cat')

+ has_field('o1', 'a', 't')
+ has_field('o1', 'b', 's')

# caja_pair(o, c) if c = freeze(o)
+ caja_pair('o1', 'c1')

+ str_cat('a', '_v__', 'a_v__')
+ str_cat('b', '_v__', 'b_v__')
+ str_cat('a', '_w__', 'a_w__')
+ str_cat('b', '_w__', 'b_w__')

##################################################
# Rules

pyDatalog.create_atoms('O', 'C', 'A', 'B', 'T')

# 'field' is copied over
has_field(C, A, T) <= \
    caja_pair(O, C) & \
    has_field(O, A, T)

# 'field_v__' is added with same type
has_field(C, B, T) <= \
    caja_pair(O, C) & \
Esempio n. 23
0
                                             == N) & Employee.p(X, N)
    assert result == [(John, 6800)]
    """
    result = Employee.p(John, Employee.salary[John]) # TODO
    print(result)
    result = (Employee.salary[X]==6800) & Employee.p(X, Employee.salary[X]) # TODO
    print (result)
    """


if __name__ == "__main__":
    test()
    #cProfile.runctx('test()', globals(), locals())
    """ In-line queries using create_atoms                    """

    pyDatalog.create_atoms('p', 'Y, eq, Z')
    +p('a')

    p(Y)
    assert (Y._value() == [
        'a',
    ])

    X = pyDatalog.Variable()
    pyDatalog.create_atoms('X')
    p(X) & (X == 'b')
    assert (X._value() == [])

    pyDatalog.create_atoms('p2')

    def test2():
# -*- coding: utf-8 -*-
"""
Created on Thu Nov  7 10:49:15 2019

@author: Moi
"""

from pyDatalog import pyDatalog
pyDatalog.create_terms('factorial, N')

factorial[N] = N*factorial[N-1] 
factorial[1] = 1

print(factorial[3]==N)


pyDatalog.create_atoms('salary', 'manager')

# John is the manager of Mary, who is the manager of Sam
+ (salary['John'] == 6800)

+ (manager['Mary'] == 'John')
+ (salary['Mary'] == 6300)


Esempio n. 25
0
from pyDatalog import pyDatalog
import time

pyDatalog.create_atoms('N,X0,X1,X2,X3,X4,X5,X6,X7')
pyDatalog.create_atoms(
    'ok,queens0,queens1,queens2,queens3,queens4,queens5,queens6,queens7')

# when is it ok to have a queen in row X1 and another in row X2, separated by N columns
# this is memoized !
ok(X1, N, X2) <= (X1 != X2) & (X1 != X2 + N) & (X1 != X2 - N)

queens0(X0) <= (X0._in(range(8)))
queens1(X0, X1) <= queens0(X0) & queens0(X1) & ok(X1, 1, X0)
queens2(X0, X1, X2) <= queens1(X0, X1) & queens1(X1, X2) & ok(X0, 2, X2)
queens3(X0, X1, X2,
        X3) <= queens2(X0, X1, X2) & queens2(X1, X2, X3) & ok(X0, 3, X3)
queens4(
    X0, X1, X2, X3,
    X4) <= queens3(X0, X1, X2, X3) & queens3(X1, X2, X3, X4) & ok(X0, 4, X4)
queens5(X0, X1, X2, X3, X4, X5) <= queens4(X0, X1, X2, X3, X4) & queens4(
    X1, X2, X3, X4, X5) & ok(X0, 5, X5)
queens6(X0, X1, X2, X3, X4, X5, X6) <= queens5(
    X0, X1, X2, X3, X4, X5) & queens5(X1, X2, X3, X4, X5, X6) & ok(X0, 6, X6)
queens7(X0, X1, X2, X3, X4, X5, X6,
        X7) <= queens6(X0, X1, X2, X3, X4, X5, X6) & queens6(
            X1, X2, X3, X4, X5, X6, X7) & ok(X0, 7, X7)

# counting is 0-based, so this is actually the 8-queens solution
print(queens7(X0, X1, X2, X3, X4, X5, X6, X7))

# there is a fixed penalty the first time around (JIT, ...), so let's measure performance the second time