Commits

Pierre Carbonnelle committed 5d03eb6

add the multi-threaded MultiModel example. Fix bugs of crosstalk between threads.

  • Participants
  • Parent commits d1462de

Comments (0)

Files changed (3)

pyDatalog/Logic.py

     def __new__(cls, logic=None):
         if isinstance(logic, cls):
             Logic.tl.logic = copy.copy(logic) 
-        elif not hasattr(Logic.tl, 'logic'):
+            Logic.tl.logic.Subgoals = {}
+            Logic.tl.logic.Tasks = None
+            Logic.tl.logic.Stack = []
+            Logic.tl.logic.Goal = None       
+        elif not (logic) or not hasattr(Logic.tl, 'logic'):
             Logic.tl.logic = object.__new__(cls)
         return Logic.tl.logic
     

pyDatalog/examples/multiModel.py

+'''
+Created on 7 October 2013
+
+@author: pcarbonn
+'''
+
+from pyDatalog import pyDatalog, Logic
+import copy
+import random
+import threading
+import time
+
+pyDatalog.create_atoms('N,X0,X1,X2,X3,X4,X5,X6,X7')
+pyDatalog.create_atoms('ok,queens, next_queen')
+
+def add_logic(n):
+    ok(X1, N, X2) <= (X1!=X2) & (X1!= X2+N) & (X1!=X2-N)
+    
+    queens(X0)                      <= (X0._in(range(n)))
+    queens(X0,X1)                   <= queens(X0)                   & next_queen(X0,X1)
+    queens(X0,X1,X2)                <= queens(X0,X1)                & next_queen(X0,X1,X2)
+    queens(X0,X1,X2,X3)             <= queens(X0,X1,X2)             & next_queen(X0,X1,X2,X3)
+    queens(X0,X1,X2,X3,X4)          <= queens(X0,X1,X2,X3)          & next_queen(X0,X1,X2,X3,X4)
+    queens(X0,X1,X2,X3,X4,X5)       <= queens(X0,X1,X2,X3,X4)       & next_queen(X0,X1,X2,X3,X4,X5)
+    queens(X0,X1,X2,X3,X4,X5,X6)    <= queens(X0,X1,X2,X3,X4,X5)    & next_queen(X0,X1,X2,X3,X4,X5,X6)
+    queens(X0,X1,X2,X3,X4,X5,X6,X7) <= queens(X0,X1,X2,X3,X4,X5,X6) & next_queen(X0,X1,X2,X3,X4,X5,X6,X7)
+    
+    next_queen(X0,X1)                   <= queens(X1)                       & ok(X0,1,X1)
+    next_queen(X0,X1,X2)                <= next_queen(X1,X2)                & ok(X0,2,X2)
+    next_queen(X0,X1,X2,X3)             <= next_queen(X1,X2,X3)             & ok(X0,3,X3)
+    next_queen(X0,X1,X2,X3,X4)          <= next_queen(X1,X2,X3,X4)          & ok(X0,4,X4)
+    next_queen(X0,X1,X2,X3,X4,X5)       <= next_queen(X1,X2,X3,X4,X5)       & ok(X0,5,X5)
+    next_queen(X0,X1,X2,X3,X4,X5,X6)    <= next_queen(X1,X2,X3,X4,X5,X6)    & ok(X0,6,X6)
+    next_queen(X0,X1,X2,X3,X4,X5,X6,X7) <= next_queen(X1,X2,X3,X4,X5,X6,X7) & ok(X0,7,X7)
+
+def check_logic(thread_name, n):
+    query = pyDatalog.ask("queens(%s)" % (",".join("X%s" % i for i in range(n))))
+    answers = query.answers if query else [] 
+    result = "OK" if len(answers) == [1,0,0,2,10,4,40,92][n-1] else answers
+    print("%s : n = %d %s " % (thread_name, n, result))
+
+def queen(thread_name, logic8, logic, n):
+    print("start %s" % thread_name)
+    Logic(logic8)
+    check_logic(thread_name, 8)
+    Logic(logic)
+    check_logic(thread_name, n)
+
+# create queen resolution logic for N = 1 to 8
+logic = []    
+for i in range(8):
+    logic.append(Logic())
+    add_logic(i+1)
+
+Logic(logic[7])
+check_logic("Main", 8)
+
+Logic(logic[4])
+check_logic("Main", 5)
+
+# start 20 threads, each with a randomly-chosen logic    
+for i in range(20):    
+    n = int(random.random() * 8) + 1 # 1 to 8
+    t = threading.Thread(target=queen,args=("thread %02d" % i, (logic[7]), logic[n-1], n))
+    t.start()
+

pyDatalog/pyParser.py

             return LazyListOfList.__str__(self)
         return ' & '.join(list(map (str, self.literals)))
 
-    def literal(self, permanent=False):
+    def literal(self):
         """ return a literal that can be queried to resolve the body """
-        if permanent:
-            literal = Literal.make('_pyD_query' + str(Body.counter.next()), 
-                                   list(self._variables().values()))
-        else:
-            literal = Literal.make('_pyD_query', list(self._variables().values()))
-            literal.lua.pred.reset_clauses()
+        literal = Literal.make('_pyD_query' + str(Body.counter.next()), list(self._variables().values()))
         if len(self.literals)==1: # determine the literal prearity
             base_literal = self.literals[0]
             if not base_literal.predicate_name.startswith('~'):
         
     def __invert__(self):
         """unary ~ means negation """
-        return ~(self.literal(permanent=True))
+        return ~(self.literal())
 
     def ask(self):
         """ resolve the query and determine the values of its variables"""
                     arg.todo = None
                     result.append(transposed[i])
             self._data = list(zip(*result)) if result else [()]
+        - (literal <= self) # delete the temporary clause
         return self._data
 
 def add_clause(head,body):