Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
tutorials:beginner:designators [2016/01/22 15:02] – [Using action designators] gkazhoyatutorials:beginner:designators [2016/03/04 14:24] (current) – old revision restored (2016/01/25 18:12) gkazhoya
Line 1: Line 1:
-====== Creating action designators for the turtlesim ======+====== Creating action designators for the TurtleSim ======
  
 **Description:** In this tutorial you will learn what designators are, and in particular, work with action designators: you will learn how to define one and how to use it. **Description:** In this tutorial you will learn what designators are, and in particular, work with action designators: you will learn how to define one and how to use it.
Line 27: Line 27:
 (Do not add this code to your tutorial files, it is meant simply for illustration here.) (Do not add this code to your tutorial files, it is meant simply for illustration here.)
  
-This line of code creates a location designator (''spy-location'') which 'knowsof the given object (''prime-minister'', which we assume is an already defined object designator), and knows that its purpose is to see the object. We do not actually specify a location in terms of coordinates at this moment. When we do want to find a suitable set of coordinates for this location, we would call+This line of code creates a location designator (''spy-location'') which "knowsof the given object (''prime-minister'', which we assume is an already defined object designator), and knows that its purpose is to see the object. We do not actually specify a location in terms of coordinates at this moment. When we do want to find a suitable set of coordinates for this location, we would call
  
 <code lisp> <code lisp>
Line 49: Line 49:
 </code> </code>
  
-In your ''cram-beginner-tutorial.asd'' file, on the '':depends-on'' line, add dependencies to ''cram-designators'' and ''cram-prolog''. Let's also create a new source file for the code in this tutorial, call it ''action-designators.lisp'', and add it to the '':components'' of the ''src'' module in your ''cram-beginner-tutorial.asd'' file, which should now look something like this:+In your ''cram-beginner-tutorial.asd'' file, on the '':depends-on'' line, add dependencies to ''cram-designators'' and ''cram-prolog''. Let's also create a new source file for the code in this tutorial (under ''src'' directory), call it ''action-designators.lisp''. We will need to add the file to the '':components'' of the ''src'' module in your ''cram-beginner-tutorial.asd'', which should now look something like this:
  
 <code lisp> <code lisp>
Line 64: Line 64:
 </code> </code>
  
-Finally, we add ''cram-designators'' namespace to the use list of our package, for convenience:+Finally, we add ''cram-designators'' namespace to the use list of our package, for convenience, and import some of the symbols of the ''cram-prolog'' package. We don't ''use'' ''cram-prolog'', as it causes conflicts with some of the similarly named symbols of the ''cram-language'' package:
  
 <code lisp> <code lisp>
 +(defpackage :cram-beginner-tutorial
 +  (:nicknames :tut)
   (:use :cpl :roslisp :cl-transforms :cram-designators)   (:use :cpl :roslisp :cl-transforms :cram-designators)
 +  (:import-from :cram-prolog :def-fact-group :<- :lisp-fun))
 </code> </code>
  
Line 74: Line 77:
 ==== Creating an action designator ==== ==== Creating an action designator ====
  
-Let's try to create an action designator in the repl command line:+Let's try to create an action designator in the REPL command line:
  
 <code lisp> <code lisp>
-TUT> (defparameter mydesig (make-designator 'action `((type shape) (shape triangle) (radius 3)))) +TUT> (defparameter my-desig (make-designator :action '((:type :shape) (:shape :triangle) (:radius 3)))) 
-MYDESIG +MY-DESIG 
-TUT> (desig-prop-value mydesig 'radius)+TUT> (desig-prop-value my-desig :radius)
 3 3
 </code> </code>
  
-As we can see, the make-designator function simply returns a designator object with the properties we specify. We can also read those already specified property values with the desig-prop-value function. So far, so good, but the interesting thing about designators is their resolution. Let's try that in the repl command line:+As we can see, the ''make-designator'' function simply returns a designator object with the properties we specify. We can also read those already specified property values with the ''desig-prop-value'' function. So far, so good, but the interesting thing about designators is their resolution. Let's try that in the REPL command line:
  
 <code lisp> <code lisp>
-TUT> (reference mydesig)+TUT> (reference my-desig)
 WARNING: WARNING:
    Trying to prove goal (ACTION-DESIG    Trying to prove goal (ACTION-DESIG
Line 93: Line 96:
                            {100A0907B3}>                            {100A0907B3}>
                          ?ACT) with undefined functor ACTION-DESIG.                          ?ACT) with undefined functor ACTION-DESIG.
-; Evaluation aborted on #<CRAM-DESIGNATORS:DESIGNATOR-ERROR "Cannot resolve action designator ~a." {1007447C53}>.+; Evaluation aborted on #<DESIGNATOR-ERROR "Cannot resolve action designator ~a." {1007447C53}>.
 </code> </code>
  
-This rather obscure error message is roslisp_repl's way of telling you there are no rules in place to resolve this designator, so let's try to provide a few such rules.+This rather obscure error message is CRAM's way of telling you there are no rules in place to resolve this designator, so let's try to provide a few such rules.
  
 +In case you were wondering why we use keywords in designator properties, that is because we would like to be able to specify rules to resolve designators in one package and create designators that are resolved through these rules in a different package. To avoid naming clashes between packages and huge import lists, we simply define all designator properties in the ''keyword'' package.
 ==== Defining inference rules for designators ==== ==== Defining inference rules for designators ====
  
-Append the following to your action-designators.lisp file:+Append the following to your ''action-designators.lisp'' file:
  
 <code lisp> <code lisp>
Line 109: Line 113:
   radius   radius
   edges)   edges)
-   + 
-  (cram-reasoning:def-fact-group shape-actions (action-desig) +(def-fact-group shape-actions (action-desig) 
-  ;; for each kind of shape, call make-turtle-shape with the right number of edges+  ;; for each kind of shape, call MAKE-TURTLE-SHAPE with the right number of edges
  
   ;; triangle   ;; triangle
-  (cram-reasoning:<- (action-desig ?desig (shape ?action)) +  (<- (action-desig ?desig (draw-shape ?action)) 
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape triangle)) +    (desig-prop ?desig (:shape :triangle)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 3  ?action))+    (lisp-fun make-turtle-shape :radius ?radius :edges 3 ?action))
  
   ;; square   ;; square
-  (cram-reasoning:<- (action-desig ?desig (shape ?action)) +  (<- (action-desig ?desig (draw-shape ?action)) 
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape square)) +    (desig-prop ?desig (:shape :square)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 4  ?action))+    (lisp-fun make-turtle-shape :radius ?radius :edges 4 ?action))
  
   ;; pentagon   ;; pentagon
-  (cram-reasoning:<- (action-desig ?desig (shape ?action)) +  (<- (action-desig ?desig (draw-shape ?action)) 
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape pentagon)) +    (desig-prop ?desig (:shape :pentagon)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 5  ?action))+    (lisp-fun make-turtle-shape :radius ?radius :edges 5 ?action))
  
   ;; hexagon   ;; hexagon
-  (cram-reasoning:<- (action-desig ?desig (shape ?action)) +  (<- (action-desig ?desig (draw-shape ?action)) 
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape hexagon)) +    (desig-prop ?desig (:shape :hexagon)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 6  ?action)))+    (lisp-fun make-turtle-shape :radius ?radius :edges 6 ?action)))
 </code> </code>
  
-Let's see what this code does. The defstruct declares a struct type to hold values resulting from the inference. It's an instantiation of our action in a space of (possibly) continuous parameters, which we deduce from a symbolic description of the designator via rules given in the def-fact-group.+Let's see what this code does. The ''defstruct'' declares a structure type to hold values resulting from the inference. It's an instantiation of our action in a space of (possibly) continuous parameters, which we deduce from a symbolic description of the designator via rules given in the ''def-fact-group''.
  
-As for the inference rules themselves, these are Prolog code embedded in Lisp, for it is Prolog that powers the inference behind designator resolution. To learn more about CRAM Prolog look at the [[cram_prolog|Using Prolog for reasoning]] tutorial. The def-fact-group is a collection of several rules, each of similar structure, so it helps to look at one of them in more detail:+As for the inference rules themselves, these are Prolog code embedded in Lisp, for it is Prolog that powers the inference behind designator resolution. To learn more about CRAM Prolog look at the [[cram_prolog|Using Prolog for reasoning]] tutorial. The ''def-fact-group'' is a collection of several rules, each of similar structure, so it helps to look at one of them in more detail:
  
 <code lisp> <code lisp>
-  (cram-reasoning:<- (action-desig ?desig (shape ?action)) +  (<- (action-desig ?desig (draw-shape ?action)) 
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape pentagon)) +    (desig-prop ?desig (:shape :pentagon)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 5  ?action))+    (lisp-fun make-turtle-shape :radius ?radius :edges 5  ?action))
 </code> </code>
  
-The first parameter to cram-reasoning:<- is the "rule head"+The first parameter to ''<-'' is the "rule head"
  
 <code lisp> <code lisp>
-(action-desig ?desig (shape ?action))+(action-desig ?desig (draw-shape ?action))
 </code> </code>
  
Line 163: Line 167:
  
 <code lisp> <code lisp>
-    (desig-prop ?desig (type shape)) +    (desig-prop ?desig (:type :shape)) 
-    (desig-prop ?desig (shape pentagon)) +    (desig-prop ?desig (:shape :pentagon)) 
-    (desig-prop ?desig (radius ?radius)) +    (desig-prop ?desig (:radius ?radius)) 
-    (cram-reasoning:lisp-fun make-turtle-shape :radius ?radius :edges 5  ?action)+    (lisp-fun make-turtle-shape :radius ?radius :edges 5  ?action)
 </code> </code>
  
-PROLOG's inference semantics is, in a nutshell, 'IF there is some assignment to variables such that all elements of the body are true, THEN use that assignment of variables to execute the head'. Notefor a symbol to be considered a variable, its name must begin with a '?'+Prolog's inference semantics is, in a nutshell, 'IF there is some assignment to variables such that all elements of the body are true, THEN use that assignment of variables to evaluate the head'. Note that in CRAM Prolog for a symbol to be considered a variable, its name must begin with a ''?''.  
 + 
 +For the example rule we've selected, Prolog looks at the designator and asks "does it contain a key-value pair that is ''(:type :shape)''?" (so no variables here except the designator itself). Assuming this is true, it then asks "does it contain a key-value pair that is ''(:shape :pentagon)''?" If still true, it asks "does it contain a key-value pair that is ''(radius <some variable value>)''?" This last question has the effect of extracting the value of the radius parameter that we created the designator with and making it available to Prolog. Finally, it "asks" Lisp to create a ''turtle-shape'' structure with the ''?radius'' value just discovered and the number of edges selected via the shape parameter, and store this in ''?action''.
  
-For this example rule we've selected, PROLOG looks at the designator and asks "does it contain a key-value pair that is (type shape)?" (so no variables here except the designator itself). Assuming this is true, it then asks "does it contain a key-value pair that is (shape pentagon)?" If still trueit asks "does it contain a key-value pair that is (radius <some variable value>)?" This last question has the effect of extracting the value of the radius parameter that we created the designator with and making it available to PROLOGFinally, it "asks" Lisp to create turtle-shape structure with the ?radius value just discovered, and the number of edges selected via the shape parameter, and store this in ?action.+If all of the above body rules are true (or can be executed sucessfullythen the head is itself evaluatedand what it does is glue the newly created ''?action'', the object containing the concrete values, to the designator ''?desig''Or in more concrete terms, it defines what the value of the ''action-desig'' predicate is if applied to ''?desig'', and that value is list containing the instruction ''draw-shape'' and the value of ''?action''.
  
-If all of the above body rules are true (or can be executed sucessfullythen the head is itself run, and what it does is glue the newly created ?action, the object containing the concrete values, to the designator ?desig. Or in more concrete terms, it defines what the value of the action-desig predicate is if applied to ?desig, and that value is a list containing the name 'shape' and the values of ?action.+If in any step of the inference Prolog stumbles upon ''false'' (or ''NIL'') it exists the current search branch and continues searching somewhere else.
  
-For this tutorial, the inference is very simple: in fact, it is just a conditional switch based on the shape parameter which translates a name like 'triangle' or 'pentagon' into the corresponding number of edges.+For this tutorial, the inference is very simple: in fact, it is just a conditional switch based on the shape parameter which translates a name like ''triangle'' or ''pentagon'' into the corresponding number of edges.
  
-Reload the tutorial package in roslisp_repl. This will also load the newly defined inference rules.+Reload the tutorial package in ''roslisp_repl''. This will also load the newly defined inference rules.
  
-Let's try to create, then reference a designator in the repl command line again:+Let's try to create, then reference a designator in the REPL command line again:
  
 <code lisp> <code lisp>
-TUT> (defparameter mydesig2 (make-designator 'action `((type shape) (shape triangle) (radius 5)))) +TUT> (defparameter my-desig-2 (make-designator :action '((:type :shape) (:shape :triangle) (:radius 5)))) 
-MYDESIG +MY-DESIG-2 
-TUT> (reference mydesig2+TUT> (reference my-desig-2
-(SHAPE #S(TURTLE-SHAPE :RADIUS 5 :EDGES 3))+(DRAW-SHAPE #S(TURTLE-SHAPE :RADIUS 5 :EDGES 3))
 </code> </code>