Subsumption This example demonstrates some slightly complex subsumption queries. Welcome to PowerLoom 3.0.1.beta Copyright (C) USC Information Sciences Institute, 1997-2003. |= (demo 9) [ ... ] |= (defconcept PERSON (?p)) |c|PERSON |= (deffunction friends-of (?p) :-> (?f SET)) |f|FRIENDS-OF |= (defrelation has-parent ((?x PERSON) (?y PERSON))) |r|HAS-PARENT |= (defrelation male ((?p PERSON))) |r|MALE |= (defrelation has-father ((?p PERSON) (?f PERSON)) :<=> (and (has-parent ?p ?f) (male ?p))) |r|HAS-FATHER |= (ask (subset-of has-father has-parent)) TRUE ;;; Harder problems for the subsumption test: |= (assert (forall ((?x NUMBER) (?y NUMBER)) (<= (>= ?x ?y) (> ?x ?y)))) |P|(FORALL (?x ?y) (<= (>= ?x ?y) (> ?x ?y))) |= (defconcept Person-with-Friends (?p) :<=> (>= (cardinality (friends-of ?p)) 1)) |c|PERSON-WITH-FRIENDS |= (defconcept Person-with-Atleast-2-Friends (?p) :<=> (>= (cardinality (friends-of ?p)) 2)) |c|PERSON-WITH-ATLEAST-2-FRIENDS |= (defconcept Person-with-Exactly-2-Friends (?p) :<=> (= (cardinality (friends-of ?p)) 2)) |c|PERSON-WITH-EXACTLY-2-FRIENDS |= (defconcept Person-with-More-Than-2-Friends (?p) :<=> (> (cardinality (friends-of ?p)) 2)) |c|PERSON-WITH-MORE-THAN-2-FRIENDS |= (ask (subset-of Person-with-Exactly-2-Friends Person-with-Atleast-2Friends)) TRUE |= (ask (subset-of Person-with-Atleast-2-Friends Person-with-Exactly-2Friends)) UNKNOWN |= (ask (subset-of Person-with-More-Than-2-Friends Person-with-Atleast2-Friends)) TRUE |= (ask (subset-of Person-with-Atleast-2-Friends Person-with-More-Than2-Friends)) UNKNOWN |= (ask (subset-of Person-with-Atleast-2-Friends Person-with-Friends)) TRUE |= Finished demo `PL:sources;logic;demos;subsumption.ste'. |= Primitive and Defined Classes This PowerLoom™ example demonstrates some definition facilities for primitive and non-primitive (or defined) concepts, and how such concepts can be used in queries of various kinds. |= (demo 2) ;;; Reasoning with primitive and defined concepts ;;; ============================================= ;;; This file demonstrates some definition facilities for primitive ;;; and non-primitive or defined concepts, and how such concepts can ;;; be used in queries of various kinds. [...] ;; We start by defining the concept `Person' with the already familiar ;; `happy' relation and `age' function: |= (defconcept Person :documentation "The class of human beings.") |c|PERSON |= (defrelation happy ((?p Person))) |r|HAPPY |= (deffunction age ((?p Person)) :-> (?age Integer)) |f|AGE ;; ;; ;; ;; ;; ;; ;; Next we define a primitive subconcept of `Person'. It is called "primitive", since it is not fully defined in terms of other concepts and relations, hence, there are some characteristics of its members that are left implicit or primitive and are not further explained in the knowledge base. The superconcepts of `Warfighter' are listed following the concept name (with a syntax similar to subclassing a CLOS class in Common Lisp): |= (defconcept Warfighter (Person) :documentation "People involved in military operations.") |c|WARFIGHTER ;; The concept definition above is really only a shorthand that ;; expands into the following logically equivalent definition and ;; assertions (which we repeat here for exposition): ;; First, we define the concept term: |= (defconcept Warfighter) Redefining the `concept' named `WARFIGHTER' |c|WARFIGHTER ;; Second, we assert the subconcept relationship via a `subset-of' assertion ;; (which PowerLoom interprets as a universally quantified rule): |= (assert (subset-of Warfighter Person)) |P|(FORALL (?x1) (<= (PERSON ?x1) (WARFIGHTER ?x1))) ;; ;; ;; ;; ;; ;; ;; ;; Finally, we attach a documentation string via a `documentation' assertion. Note that the :documentation keyword used before is not anything special built into the `defconcept' command, rather it is a keyword axiom syntax where the name of the keyword is interpreted to be the name of a binary relation, the first argument is left implicit and taken to be the name of the defined entity and the second argument is the supplied value, thus, it gets expanded into the following assertion: |= (assert (documentation Warfighter "People involved in military operations.")) |P|(DOCUMENTATION WARFIGHTER "People involved in military operations.") ;; This also demonstrates that concepts and relations can participate ;; as arguments to assertions just like any "ordinary" instance. A ;; query like the following can then be used to lookup the documentation ;; of a term: |= (retrieve (documentation Warfighter ?doc)) There is 1 solution so far: #1: ?DOC="People involved in military operations." ;; Now let's define armed services and some particular service instances: |= (defconcept Armed-Service :documentation "The class of armed services, for example, the US Navy.") |c|ARMED-SERVICE |= (assert (Armed-Service US-Army)) |P|(ARMED-SERVICE US-ARMY) |= (assert (Armed-Service US-Navy)) |P|(ARMED-SERVICE US-NAVY) |= (assert (Armed-Service US-Airforce)) |P|(ARMED-SERVICE US-AIRFORCE) ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; Next we define a `service' function that maps warfighters to the branch of military service they operate in. Function inputs are defined via optionally typed KIF variables such as the variable `?p' below. Such variables can be listed simply by themselves or as a list where the second element is interpreted as the variable type. In the definition `?p's type is `Warfighter' which is taken to be the domain of the function. There could be more than one input argument, since PowerLoom allows n-ary functions and relations. The function output is its last argument which is again given as an optionally typed KIF variable separated via the :-> keyword. Below, the variable `?s' is typed as `Armed-Service' which defines the range of the function. Similar to concepts and relations, functions can have keyword axioms such as :documentation: |= (deffunction service ((?p Warfighter)) :-> (?s Armed-Service) :documentation "The armed service to which a warfighter belongs.") |f|SERVICE ;; Again, the `deffunction' syntax is a shorthand that expands into ;; the following logically equivalent definition and assertions: |= (deffunction service (?p) :-> ?s) Redefining the `function' named `SERVICE' |f|SERVICE |= (assert (nth-domain service 0 Warfighter)) |P|(NTH-DOMAIN SERVICE 0 WARFIGHTER) |= (assert (nth-domain service 1 Armed-Service)) |P|(NTH-DOMAIN SERVICE 1 ARMED-SERVICE) |= (assert (documentation service "The armed service to which a warfighter belongs.")) |P|(DOCUMENTATION SERVICE "The armed service to which a warfighter belongs.") ;; Functions can also be specified just like relations without the ;; special :-> keyword, for example, the following is yet another ;; equivalent definition: |= (deffunction service ((?p Warfighter) (?s Armed-Service)) :documentation "The armed service to which a warfighter belongs.") Redefining the `function' named `SERVICE' |f|SERVICE ;; The function `friends' maps a person to its set of friends: |= (deffunction friends ((?p Person)) :-> (?f SET) :documentation "The set of friends ?f of some person ?p.") |f|FRIENDS ;; ;; ;; ;; ;; ;; ;; ;; ;; ;; Next we define a non-primitive (or defined) subconcept of `Person' called `Civilian'. This is done by providing a bi-directional, if-and-only-if implication between the concept and a defining logical expression. In this case civilians are defined as people who are not warfighters. This time the list of superconcepts is preceded by a class variable `?p' which is needed so it can be referenced in the defining expression. In primitive concept definitions such as the ones above such variables can be ommitted. Note, that since the definition is if-and-only-if, every person who is not a warfighter is a civilian and vice versa. |= (defconcept Civilian (?p Person) :documentation "People who are not warfighters." :<=> (and (Person ?p) (not (Warfighter ?p)))) |c|CIVILIAN ;; The definition is a shorthand for the following logically equivalent ;; definition and assertions: |= (defconcept Civilian) Redefining the `concept' named `CIVILIAN' |c|CIVILIAN |= (assert (subset-of Civilian Person)) |P|(FORALL (?x1) (<= (PERSON ?x1) (CIVILIAN ?x1))) |= (assert (documentation Civilian "People who are not warfighters.")) |P|(DOCUMENTATION CIVILIAN "People who are not warfighters.") ;; The defining bi-directional implication rule is translated by ;; PowerLoom into three equivalent regular implications: |= (assert (forall (?p) (<=> (Civilian ?p) (and (Person ?p) (not (Warfighter ?p)))))) (|P|(FORALL (?p) (<= (NOT (WARFIGHTER ?p)) (CIVILIAN ?p))) |P|(FORALL (?x1) (<= (PERSON ?x1) (CIVILIAN ?x1))) |P|(FORALL (?p) (<= (CIVILIAN ?p) (AND (PERSON ?p) (NOT (WARFIGHTER ?p)))))) ;; ;; ;; ;; ;; ;; A note to Loom users: PowerLoom does not distinguish between definitional and non-definitional parts of a concept or relation definition. Any rule implying a concept or relation will be considered by the inference engine and classifier, regardless of whether it was part of the definition or asserted somewhere else outside. ;; Let us define two more specialized classes of warfighters for ;; particular service branches: |= (defconcept Army-Person (?p Warfighter) :<=> (and (Warfighter ?p) (= (service ?p) US-Army))) |c|ARMY-PERSON |= (defconcept Navy-Person (?p Warfighter) :<=> (and (Warfighter ?p) (= (service ?p) US-Navy))) |c|NAVY-PERSON ;; Some instances of the concepts defined above: |= (assert (Warfighter Buck)) |P|(WARFIGHTER BUCK) |= (assert (= (service Buck) US-Army)) |P|(= (SERVICE BUCK) US-ARMY) |= (assert (Person John)) |P|(PERSON JOHN) ;; We can use the built-in `member-of' relation to express set membership: |= (assert (member-of Buck (friends John))) |P|(MEMBER-OF BUCK (FRIENDS JOHN)) |= (assert (member-of John (friends Buck))) |P|(MEMBER-OF JOHN (FRIENDS BUCK)) |= (assert (Person Judy)) |P|(PERSON JUDY) ;; Since so far we only know that Judy is a person, the following two ;; queries cannot derive any definitive answers: |= (ask (Warfighter Judy)) UNKNOWN |= (ask (Civilian Judy)) UNKNOWN ;; So, let us assert that Judy is a member of the US-Navy: |= (assert (Warfighter Judy)) |P|(WARFIGHTER JUDY) |= (assert (= (service Judy) US-Navy)) |P|(= (SERVICE JUDY) US-NAVY) ;; Now we can successfully determine that she is a Navy-Person: |= (ask (Navy-Person Judy)) TRUE ;; The next query returns UNKNOWN, since (currently) PowerLoom does ;; not simultaneously try to answer a query and its negation with the ;; same effort (only "obvious" falsities are picked up): |= (ask (Civilian Judy)) UNKNOWN ;; However, if we ask the negated question explicitly, we get the ;; expected result: |= (ask (not (Civilian Judy))) TRUE ;; The same works in the opposite direction: |= (assert (Civilian Blimpy)) |P|(CIVILIAN BLIMPY) |= (ask (Civilian Blimpy)) TRUE ;; Note, that this query does find the negated answer, since it has ;; already been derived by forward inference: |= (ask (Warfighter Blimpy)) FALSE |= (ask (not (Warfighter Blimpy))) TRUE ;; Yet another warfighter: |= (assert (Warfighter Fred)) |P|(WARFIGHTER FRED) |= (assert (= (service Fred) US-Airforce)) |P|(= (SERVICE FRED) US-AIRFORCE) ;; Now, let us retrieve various sets of instances: |= (retrieve all (Person ?p)) There #1: #2: #3: #4: #5: are 5 solutions: ?P=JUDY ?P=JOHN ?P=BLIMPY ?P=FRED ?P=BUCK |= (retrieve all (Warfighter ?w)) There #1: #2: #3: are 3 solutions: ?W=FRED ?W=JUDY ?W=BUCK |= (retrieve all (and (Person ?p) (not (Civilian ?p)))) There #1: #2: #3: are 3 solutions: ?P=JUDY ?P=FRED ?P=BUCK |= (retrieve all (and (Person ?p) (not (Warfighter ?p)))) There is 1 solution: #1: ?P=BLIMPY ;; Retrieval of instances of defined classes: |= (retrieve all (Civilian ?p)) There is 1 solution: #1: ?P=BLIMPY |= (retrieve all (Army-Person ?w)) There is 1 solution: #1: ?W=BUCK |= (retrieve all (Navy-Person ?w)) There is 1 solution: #1: ?W=JUDY ;; Let us retrieve everybody who is either in the US-Navy or USAirforce: |= (retrieve all (and (Warfighter ?w) (or (= (service ?w) US-Navy) (= (service ?w) US-Airforce)))) There are 2 solutions: #1: ?W=JUDY #2: ?W=FRED ;; Alternatively, this can be done like this: |= (retrieve all (and (Warfighter ?w) (member-of (service ?w) (setof US-Navy USAirforce)))) There are 2 solutions: #1: ?W=JUDY #2: ?W=FRED ;; Retrieve all people and their friends: |= (retrieve all (and (Person ?p) (Person ?f) (member-of ?f (friends ?p)))) There are 2 solutions: #1: ?P=BUCK, ?F=JOHN #2: ?P=JOHN, ?F=BUCK ;; Retrieve all armed services with some members who have friends: |= (retrieve all (and (Armed-Service ?s) (exists (?p ?w) (and (Person ?p) (Warfighter ?w) (member-of ?p (friends ?w)) (= (service ?w) ?s))))) There is 1 solution: #1: ?S=US-ARMY |= Finished demo `PL:sources;logic;demos;classes.ste'. |= Constraint Propagation This example demonstrates the constraint propagation facility in PowerLoom™ which provides simple propositional forward inference and propagation of equality constraints. Welcome to PowerLoom 3.0.1.beta |= (demo 8) ;;; Version: constraints.ste,v 1.9 2000/07/15 02:33:02 hans Exp ;;; Constraint propagation ;;; ====================== ;;; ;;; ;;; ;;; ;;; ;;; This file demonstrates PowerLoom's constraint propagation facility which provides simple propositional forward inference and propagation of equality constraints. Truth-maintenance of constraint propagation inferences is still under construction, which means that the constraint propagation interface will most probably change in future versions of PowerLoom. [ ... ] ;; The already familiar `Person' class: |= (defconcept PERSON (?p) :documentation "The class of human beings.") |c|PERSON |= (defrelation happy ((?p PERSON))) |r|HAPPY |= (deffunction age ((?p PERSON)) :-> (?a INTEGER)) |f|AGE |= (assert (Person Fred)) |P|(PERSON FRED) ;; ;; ;; ;; In PowerLoom forward constraint propagation is performed on a per-instance basis. By default, it is turned on. So that we can get a feel for what it does, let us disable it unsetting the feature `:just-in-time-inference': |= (unset-feature :just-in-time-inference) |l|(:EMIT-THINKING-DOTS) ;; We start by asserting the following disjunction: |= (assert (or (happy Fred) (= (age Fred) 40))) |P|(OR (HAPPY FRED) (= (AGE FRED) 40)) ;; When we ask for one of the disjuncts, we do not get an answer, ;; since nothing is known about the individual disjuncts: |= (ask (= (age Fred) 40)) UNKNOWN ;; Now we assert the negation of the first disjunct. If just-in-time ;; inference were enabled, the falsity of the first disjunct would ;; cause the second disjunct to be asserted to be true. But, its not: |= (assert (not (happy Fred))) |P|(NOT (HAPPY FRED)) |= (ask (= (age Fred) 40)) UNKNOWN ;; Now we reenable just-in-time inference, and try the same question ;; again: |= (set-feature :just-in-time-inference) |l|(:JUST-IN-TIME-INFERENCE :EMIT-THINKING-DOTS) |= (ask (= (age Fred) 40)) TRUE ;; To show that no inference is necessary to answer this question, ;; we turn on goal-tracing of the inference engine: |= (set-feature trace-subgoals) |l|(:TRACE-SUBGOALS :JUST-IN-TIME-INFERENCE :EMIT-THINKING-DOTS) ;; Now the query below returns true. The goal trace shows that no ;; inference needs to be performed to get the answer, since the asked ;; proposition is available directly, just like a regular assertion: |= (ask (= (age Fred) 40)) PATTERN: [] | GOAL: (= (AGE FRED) 40) | SUCC: truth=T TRUE |= (unset-feature trace-subgoals) |l|(:JUST-IN-TIME-INFERENCE :EMIT-THINKING-DOTS) ;; ;; ;; ;; Forward constraint propagation picks up certain inferences much more efficiently than the backward chainer. Note that, currently, PowerLoom would have not been able to make the above inference without having constraint propagation turned on. ;; ;; ;; ;; ;; The system caches the results of just-in-time forward propagation in a special context. To insure soundness, this context gets blown away if a retraction occurs. That means that after the following retraction, constraint propagation has to be recomputed when the question is repeated: |= (retract (not (happy Fred))) |P?|(HAPPY FRED) |= (ask (= (age Fred) 40)) UNKNOWN ;; Below, we run a variation of the previous example that makes use of ;; the violation of an equality constraint: |= (assert (Person Fritz)) |P|(PERSON FRITZ) |= (assert (= (age Fritz) 25)) |P|(= (AGE FRITZ) 25) ;; So far, we don't know whether Fritz is happy: |= (ask (happy Fritz)) UNKNOWN ;; Now we assert a similar disjunction as used in the example above. ;; Since the second disjunct clashes with the age asserted above, ;; constraint propagation asserts the first disjunct to be true: |= (assert (or (happy Fritz) (= (age Fritz) 40))) |P|(OR (HAPPY FRITZ) (= (AGE FRITZ) 40)) ;; Now this query succeeds without any inference: |= (ask (happy Fritz)) TRUE ;; Propagation of equality constraints: |= (assert (Person John)) |P|(PERSON JOHN) |= (assert (Person Mary)) |P|(PERSON MARY) ;; John is the same age as Mary: |= (assert (= (age John) (age Mary))) |P|(= (AGE JOHN) (AGE MARY)) ;; We don't yet know Mary's age: |= (ask (= (age Mary) 25)) UNKNOWN ;; Now we set John's age to be 25: |= (assert (= (age John) 25)) |P|(= (AGE JOHN) 25) ;; This assertion got propagated through the previously asserted ;; equality, thus, now we also know that Mary's age is 25: |= (ask (= (age Mary) 25)) TRUE |= Finished demo `PL:sources;logic;demos;constraints.ste'. |= Reasoning with Recursive Rules This example demonstrates that PowerLoom™ automatically handles reasoning with recursive rules despite its use of a Prolog-style backward chainer (in Prolog, recursive rules rules have to be handled by carefully ordering them to avoid infinite recursion). The example uses parent and ancestor relations, since those naturally lend themselves to recursive formulations. Welcome to PowerLoom 3.0.1.beta Copyright (C) USC Information Sciences Institute, 1997-2003. PowerLoom is a trademark of the University of Southern California. PowerLoom comes with ABSOLUTELY NO WARRANTY! Type `(copyright)' for detailed copyright information. Type `(help)' for a list of available commands. Type `(demo)' for a list of example applications. Type `bye', `exit', `halt', `quit', or `stop', to exit. |= (demo 6) Now reading from `PL:sources;logic;demos;recursion.ste'. Type `?' at the pause prompt for a list of available commands. ;;; -*- Mode: Lisp; Package: STELLA; Syntax: COMMON-LISP; Base: 10 -*;;; Version: recursion.ste,v 1.9 2001/06/06 19:07:30 tar Exp ;;; Inference along parent and ancestor relations with recursive rules ;;; ================================================================== ;;; ;;; ;;; ;;; ;;; ;;; ;;; This file demonstrates that PowerLoom automatically handles reasoning with recursive rules despite its use of a Prolog-style backward chainer (in Prolog, recursive rules rules have to be handled by carefully ordering them to avoid infinite recursion). The example uses `parent' and `ancestor' relations, since those naturally lend themselves to recursive formulations. The file also demonstrates the use of `PowerLoom's `defrelation' command. ;;; ;;; ;;; ;;; ;;; The best way to view this file is by calling `(demo)' and selecting it from the menu of example demos. This demo assumes familiarity with some basic PowerLoom concepts which are described in the introductory demo (#1 on the demo menu) and other demos preceding this one. ;; Standard demo preamble: |= (in-package "STELLA") ------ pause ------c |= (defmodule "/PL-KERNEL/PL-USER/RECURSION") |MDL|/PL-KERNEL-KB/PL-USER/RECURSION |= (in-module "RECURSION") |= (clear-module "RECURSION") |= (reset-features) |l|(:EMIT-THINKING-DOTS :JUST-IN-TIME-INFERENCE) |= (in-dialect :KIF) :KIF ;; The already familiar `Person' class: |= (defconcept PERSON (?p) :documentation "The class of human beings.") |c|PERSON |= (defrelation happy ((?p PERSON))) |r|HAPPY |= (deffunction age ((?p PERSON)) :-> (?a INTEGER)) |f|AGE ;; ;; ;; ;; ;; ;; ;; ;; ;; Now we define two relations `has-parent' and `has-ancestor' with PowerLoom's `defrelation' command. `defrelation' is very similar to `deffunction' (see the `append' demo), with the main difference that it does not take a `:->' specification, since relations are boolean-valued. Similar to functions, relations are polymorphic (indexed on the type of their first argument) unless they were defined with `:polymorphic?' set to FALSE. Note again, that functions and relations must be defined before they can be used in any assertion or query. |= (defrelation has-parent ((?p PERSON) (?parent PERSON)) :documentation "True if `self' has `parent' as a parent.") |r|HAS-PARENT |= (defrelation has-ancestor ((?p PERSON) (?ancestor PERSON)) :documentation "True if `self' has `ancestor' as an ancestor.") |r|HAS-ANCESTOR ;; Rule 1: All parents are ancestors: |= (assert (forall ((?x PERSON) (?y PERSON)) (=> (has-parent ?x ?y) (has-ancestor ?x ?y)))) |P|(FORALL (?x ?y) (<= (HAS-ANCESTOR ?x ?y) (HAS-PARENT ?x ?y))) ;; Rule 2: Transitivity of ancestor relations: If `?y' is an ancestor of ;; `?x' and `?z' is an ancestor of `?y' then `?z' is also an ancestor of ;; `?x'. This rule is recursive, since its consequent (or head) defines a ;; `has-ancestor' relationship by recursively referencing `hasancestor' ;; in its antecedent (or tail). A naive backward chaining architecture ;; would backchain into the consequent and simply post the two new ;; `has-ancestor' subgoals from the rule's antecedent. However, these ;; subgoals might be duplicates of the original goal which could lead to ;; infinite subgoaling. This is actually the strategy used by Prolog, and ;; there rule recursion has to be handled by hand using knowledge of the ;; order in which rules and clauses are processed and carefully ordering ;; them to avoid infinite recursion. In PowerLoom the order of assertions ;; is completely irrelevant, and duplicate subgoals are detected ;; automatically. This is an important feature, since recursion is a very ;; natural and powerful way to formulate axioms or rules, and people often ;; write recursive rules without even realizing that they do: |= (assert (forall ((?x PERSON) (?z PERSON)) (=> (exists (?y PERSON) (and (has-ancestor ?x ?y) (has-ancestor ?y ?z))) (has-ancestor ?x ?z)))) |P|(FORALL (?x ?z) (<= (HAS-ANCESTOR ?x ?z) (EXISTS (?y) (AND (HAS-ANCESTOR ?x ?y) (HAS-ANCESTOR ?y ?z))))) ;; Let us create some people (note, that the top-level `and' gets optimized ;; away to leave only assertions of the individual conjuncts): |= (assert (and (Person Abby) (Person Benny) (Person Carla) (Person Debbie) (Person Edward) (Person Fred))) (|P|(PERSON ABBY) |P|(PERSON BENNY) |P|(PERSON CARLA) |P|(PERSON DEBBIE) |P|(PERSON EDWARD) |P|(PERSON FRED)) ;; Some parent and ancestor relationships we know about: |= (assert (has-parent Abby Benny)) |P|(HAS-PARENT ABBY BENNY) |= (assert (has-ancestor Benny Carla)) |P|(HAS-ANCESTOR BENNY CARLA) |= (assert (has-parent Carla Debbie)) |P|(HAS-PARENT CARLA DEBBIE) |= (assert (has-ancestor Debbie Edward)) |P|(HAS-ANCESTOR DEBBIE EDWARD) |= (assert (has-parent Edward Fred)) |P|(HAS-PARENT EDWARD FRED) ;; First, let us derive Abby's ancestors using PowerLoom's incremental ;; query machinery. Remember, that a `retrieve' without a specification ;; of a desired number of solutions generates at most one solution: |= (retrieve (?z PERSON) (has-ancestor Abby ?z)) There is 1 solution so far: #1: ?Z=BENNY ;; More solutions of the most recent query can be generated by calling ;; `retrieve' without the query arguments (a desired number of new ;; solutions can still be specified): |= (retrieve 2) There #1: #2: #3: are 3 solutions so far: ?Z=BENNY ?Z=CARLA ?Z=DEBBIE |= (retrieve) There #1: #2: #3: #4: are 4 solutions so far: ?Z=BENNY ?Z=CARLA ?Z=DEBBIE ?Z=EDWARD |= (retrieve) There #1: #2: #3: are 5 solutions so far: ?Z=BENNY ?Z=CARLA ?Z=DEBBIE #4: ?Z=EDWARD #5: ?Z=FRED |= (retrieve) There #1: #2: #3: #4: #5: are 5 solutions: ?Z=BENNY ?Z=CARLA ?Z=DEBBIE ?Z=EDWARD ?Z=FRED ;; Now let us retrieve all ancestors of all other people: |= (retrieve all (?z PERSON) (has-ancestor Benny ?z)) There #1: #2: #3: #4: are 4 solutions: ?Z=DEBBIE ?Z=CARLA ?Z=FRED ?Z=EDWARD |= (retrieve all (?z PERSON) (has-ancestor Carla ?z)) There #1: #2: #3: are 3 solutions: ?Z=FRED ?Z=EDWARD ?Z=DEBBIE |= (retrieve all (?z PERSON) (has-ancestor Debbie ?z)) There are 2 solutions: #1: ?Z=FRED #2: ?Z=EDWARD |= (retrieve all (?z PERSON) (has-ancestor Edward ?z)) There is 1 solution: #1: ?Z=FRED |= (retrieve all (?z PERSON) (has-ancestor Fred ?z)) No solutions. |= Finished demo `PL:sources;logic;demos;recursion.ste'. |=