Differences

This shows you the differences between two versions of the page.

Link to this comparison view

tutorials:beginner:cram_prolog [2015/05/29 21:19]
gkazhoya
tutorials:beginner:cram_prolog [2016/01/25 12:47] (current)
gkazhoya
Line 6: Line 6:
  
 CRAM has its own primitive Prolog interpreter written in Common Lisp which can work natively with the Lisp data structures (as opposed to, e.g., SWI Prolog, which would need a complex mechanism for passing around Lisp data structures and converting Prolog results back into Lisp). CRAM has its own primitive Prolog interpreter written in Common Lisp which can work natively with the Lisp data structures (as opposed to, e.g., SWI Prolog, which would need a complex mechanism for passing around Lisp data structures and converting Prolog results back into Lisp).
-It is implemented in the "​cram_reasoning" ​package, so, first of all, let's load the package:+It is implemented in the ''​cram_prolog'' ​package, so, first of all, let's load the package:
  
 <code lisp> <code lisp>
-CL-USER> (asdf:​load-system :cram-reasoning+CL-USER> (asdf:​load-system :cram-prolog
-CL-USER> (in-package :cram-reasoning)+CL-USER> (in-package :cram-prolog)
 </​code>​ </​code>​
  
 Executing Prolog queries is done by calling the ''​prolog''​ function, where its first argument is a list of symbolic data: Executing Prolog queries is done by calling the ''​prolog''​ function, where its first argument is a list of symbolic data:
 <code lisp> <code lisp>
-CRS> (prolog '​(member ?x (1 2 3)))+PROLOG> (prolog '​(member ?x (1 2 3)))
 (((?X . 1)) (((?X . 1))
  . #​S(CRAM-UTILITIES::​LAZY-CONS-ELEM :GENERATOR #<​CLOSURE # {100A55B86B}>​))  . #​S(CRAM-UTILITIES::​LAZY-CONS-ELEM :GENERATOR #<​CLOSURE # {100A55B86B}>​))
Line 24: Line 24:
  
 <code lisp> <code lisp>
-CRS> (force-ll (prolog '​(member ?x (1 2 3))))+PROLOG> (force-ll (prolog '​(member ?x (1 2 3))))
 (((?X . 1)) ((?X . 2)) ((?X . 3))) (((?X . 1)) ((?X . 2)) ((?X . 3)))
 </​code>​ </​code>​
Line 32: Line 32:
 We can also have queries with multiple unbound variables, e.g.: We can also have queries with multiple unbound variables, e.g.:
 <code lisp> <code lisp>
-CRS> (defparameter *some-list* '((1) (2 3) (4 5 6)))+PROLOG> (defparameter *some-list* '((1) (2 3) (4 5 6)))
 *SOME-LIST* *SOME-LIST*
-CRS> (force-ll (prolog `(and (member ?x ,​*some-list*) +PROLOG> (force-ll (prolog `(and (member ?x ,​*some-list*) 
-                             ​(length ?x ?x-len))))+                                (length ?x ?x-len))))
 (((?X 1) (?X-LEN . 1)) ((?X 2 3) (?X-LEN . 2)) ((?X 4 5 6) (?X-LEN . 3))) (((?X 1) (?X-LEN . 1)) ((?X 2 3) (?X-LEN . 2)) ((?X 4 5 6) (?X-LEN . 3)))
 </​code>​ </​code>​
Line 42: Line 42:
 If there are no solutions for the query Prolog returns NIL: If there are no solutions for the query Prolog returns NIL:
 <code lisp> <code lisp>
-CRS> (prolog '(and (member ?x (1 2 3)) +PROLOG> (prolog '(and (member ?x (1 2 3)) 
-                   ​(< ?x 0)))+                      (< ?x 0)))
 NIL NIL
 </​code>​ </​code>​
Line 49: Line 49:
 If there are no unbound variables in the query but the query itself is true, Prolog returns a list where bindings are NIL: If there are no unbound variables in the query but the query itself is true, Prolog returns a list where bindings are NIL:
 <code lisp> <code lisp>
-CRS> (force-ll (prolog '(> 4 0)))+PROLOG> (force-ll (prolog '(> 4 0)))
 (NIL) (NIL)
 </​code>​ </​code>​
  
-The CRAM Prolog interpreter finds solutions by performing a depth first search over the predicate tree, that it, it first searches for possible bindings for the first predicate, then branches into multiple search paths, one per each assignment and continues with the second predicate, and so on. The mechanism is the same as in any other Prolog implementation.+The CRAM Prolog interpreter finds solutions by performing a depth first search over the predicate tree, that it, it first searches for possible bindings for the first predicate, then branches into multiple search paths, one per each assignmentand continues with the second predicate, and so on. The mechanism is the same as in any other Prolog implementation.
  
 One difference between CRAM Prolog and conventional implementations is that some predicates can be proven by using a Lisp function and not through depth-first search over possible solutions. For that predicates ''​lisp-fun''​ and ''​lisp-pred''​ can be used: One difference between CRAM Prolog and conventional implementations is that some predicates can be proven by using a Lisp function and not through depth-first search over possible solutions. For that predicates ''​lisp-fun''​ and ''​lisp-pred''​ can be used:
 <code lisp> <code lisp>
-CRS> (force-ll (prolog '​(lisp-pred oddp 3)))+PROLOG> (force-ll (prolog '​(lisp-pred oddp 3)))
 (NIL) (NIL)
 </​code>​ </​code>​
Line 67: Line 67:
 Please note that in Prolog there can (and usually are) multiple ways of proving the same predicate (multiple implementations),​ which means that predicate implementations don't get overwritten but are always being added up. In order to be able to replace an old implementation with a new one CRAM Prolog has a notion of "fact groups"​ which are the basic "​compilation"​ units of the Prolog engine. Each time a fact group is being recompiled all the old implementations inside the group are being replaced with the new ones, whereas implementations of the same predicates from other fact groups stay valid as they were. Please note that in Prolog there can (and usually are) multiple ways of proving the same predicate (multiple implementations),​ which means that predicate implementations don't get overwritten but are always being added up. In order to be able to replace an old implementation with a new one CRAM Prolog has a notion of "fact groups"​ which are the basic "​compilation"​ units of the Prolog engine. Each time a fact group is being recompiled all the old implementations inside the group are being replaced with the new ones, whereas implementations of the same predicates from other fact groups stay valid as they were.
  
-We call predicate definitions //rules// or //facts//. For defining custom Prolog predicates CRAM Prolog uses the macro ''​def-fact-group'' ​and ''<​-'':​+We call predicate definitions //rules// or //facts//. For defining custom Prolog predicates CRAM Prolog uses the macro ''​def-fact-group'' ​with ''<​-'':​
  
 <code lisp> <code lisp>
-CRS> (def-fact-group family-predicates () +PROLOG> (def-fact-group family-predicates () 
-       ​(<- (grandparent ?​grandparent ?​grandkid) +          (<- (grandparent ?​grandparent ?​grandkid) 
-         ​(parent ?​grandparent ?x) +            (parent ?​grandparent ?x) 
-         ​(parent ?x ?​grandkid)))+            (parent ?x ?​grandkid)))
 </​code>​ </​code>​
  
Line 79: Line 79:
  
 <code lisp> <code lisp>
-CRS> (def-fact-group family-predicates ()+PROLOG> (def-fact-group family-predicates ()
  
-       (<- (grandparent ?​grandparent ?​grandkid) +          ​(<- (grandparent ?​grandparent ?​grandkid) 
-         ​(parent ?​grandparent ?x) +            (parent ?​grandparent ?x) 
-         ​(parent ?x ?grandkid))+            (parent ?x ?grandkid))
                
-       (<- (parent my-dad me)) +          ​(<- (parent my-dad me)) 
-       ​(<- (parent me my-kid)))+          (<- (parent me my-kid)))
 </​code>​ </​code>​
  
Line 94: Line 94:
  
 <code lisp> <code lisp>
-CRS> (force-ll (prolog '​(grandparent my-dad my-kid)))+PROLOG> (force-ll (prolog '​(grandparent my-dad my-kid)))
 (NIL) (NIL)
-CRS> (force-ll (prolog '(and (parent ?​parent-of-me me) +PROLOG> (force-ll (prolog '(and (parent ?​parent-of-me me) 
-                             ​(grandparent ?​grandparent-of-my-kid my-kid))))+                                (grandparent ?​grandparent-of-my-kid my-kid))))
 (((?​PARENT-OF-ME . MY-DAD) (?​GRANDPARENT-OF-MY-KID . MY-DAD))) (((?​PARENT-OF-ME . MY-DAD) (?​GRANDPARENT-OF-MY-KID . MY-DAD)))
 </​code>​ </​code>​