Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:dss:rules:intro [2017/11/28 13:33] msl |
pl:dydaktyka:dss:rules:intro [2019/06/27 15:50] (aktualna) |
| |
===== Download ===== | ===== Download ===== |
Please download the following files containg simple knowledge bases about a family: | Please download the following files containing simple knowledge bases about a family: |
* CLIPS file: | * CLIPS file: {{ :pl:dydaktyka:dss:rules:family_en.clp.zip |}} |
* Prolog file: | * Prolog file: {{ :pl:dydaktyka:dss:rules:family_en.pl |}} |
* Manual for CLIPS: {{: en: didactics: rules: lab: labs: bpg.pdf | Basic Programming Guide}} [[http://clipsrules.sourceforge.net/documentation/v630/bpg.htm|version online]] | * Manual for CLIPS: {{:pl:dydaktyka:rules:lab:labs:bpg.pdf|Basic Programming Guide}}, [[http://clipsrules.sourceforge.net/OnlineDocs.html|version online]] |
| |
===== Knowledge Bases ===== | ===== Knowledge Bases ===== |
Defining deffacts: initial-facts | Defining deffacts: initial-facts |
Defining defrule: child +j | Defining defrule: child +j |
TRUE </ code> The ** TRUE ** is the most important part of this feedback. If ** FALSE ** appears, it means that loading failed. | TRUE </code> The ** TRUE ** is the most important part of this feedback. If ** FALSE ** appears, it means that loading failed. |
* Prolog: <code> [family]. </code> The succesful loading should display something similar to: <code> | * Prolog: <code> [family]. </code> The succesful loading should display something similar to: <code> |
% family compiled 0.01 sec, 9,232 bytes | % family compiled 0.01 sec, 9,232 bytes |
* What are the names of all the fathers: <code> father(Father, _). </code> | * What are the names of all the fathers: <code> father(Father, _). </code> |
* What sons does Dariusz have: <code> father(dariusz, Son), man(Son). </code> | * What sons does Dariusz have: <code> father(dariusz, Son), man(Son). </code> |
| |
| ===== 4. How to use Rules ===== |
| Both files contain a rule defines who/what is a ** child**. |
| * How to interpret these rules? |
| * Do they use the same notion of a **child**? |
| CLIPS failed to start this rule (previous point). In Prolog, we can query using this rule: <code>child(X, Y).</code> |
| * Run the above query and ... |
| * describe what happened? |
| * Has the situation been analogous to that in CLIPS? |
| * Does the rule in CLIPS failed because of the same reason? |
| |
| ===== 5. Creating Rules ===== |
| In order to run the **child** rule, we have to define: |
| * In CLIPS: a rule that adds a parent to the knowledge base (changing the knowledge base will trigger the next inference cycle): <code> |
| (defrule parent |
| (or (mother ?x ?y) (father ?x ?y)) |
| => |
| (assert (parent ?x ?y)) |
| )</code> |
| * In Prolog: a rule defining a relationship (child, parent): <code> |
| parent(X, Y) :- |
| father(X, Y). |
| parent(X, Y) :- |
| mother(X, Y). </code> It is worth noting that in the case of Prolog, we define two rules. One can assume that there is a conjuction (**OR**) between these two rules. |
| * Repeat steps: |
| * CLIPS: 1. and 3. (start with executing ''(clear)'' to clear the fact base) |
| * Prolog: 1 and 4. |
| * How many facts are there in the CLIPS database? |
| * What are the active rules in CLIPS? |
| * Why is the **child** rule inactive? |
| |
| ==== 5.1. Adding Knowledge to the KB ==== |
| === 5.1.1. Son and daughter === |
| We can try now to supplement the current KB with new rules, that define other relationships: |
| * Both tools can answer who is the child of which parent. How to extend the rules base of both tools with the help of the **child** concept so that they can tell who is the son and who is the daughter? |
| * Define the appropriate rules. |
| * Start the inference to check if the defined rule is correct. |
| * You can also try to simply display the facts in CLIPS. |
| |
| === 5.1.2. Marriage === |
| * The knowledge base can also be supplemented by a rule defining **marriage**. With existing facts and rules, you can define that two people are married if: |
| * are different sex, |
| * have a common child. |
| * This rule will cause the inference to omit the childless couples. In order to define the proper notion of **marriage**, KB would have to be supplemented with additional facts (what facts?) |
| |
| === 5.1.3. Other === |
| Knowing that the concepts **brother** is defined as follow: |
| * CLIPS: <code> |
| (defrule brother |
| (siblings ?x ?y) |
| (man ?x) |
| => |
| (assert (brother ?x ?y)) |
| )</code> |
| * Prolog: <code> |
| brother(X, Y) :- |
| siblings(X, Y), |
| man(X).</code> |
| Define the following rules: |
| * siblings(X,Y) --- two different people with a common parent; |
| * tip: ** (test (neq ?x ?y)) ** checks inequality of variables. |
| * question: why do you have to use ** test ** keyword? |
| * sister(X,Y) |
| * grandfather(X,Y) |
| * grandmother(X,Y) |
| * grandparent(X,Y) --- tip: use ** OR ** |
| * cousins(X,Y) --- two different people with a common grandparent. You can check this rule in Prolog with a query: <code>cousins(X,Y), parent(R,X), parent(R, Y)</code>, it should return **false** |
| * remember: siblings are not cousins! |
| * aunt(X,Y) and uncle(X,Y) in terms of sister, brother and parent. |
| * half-orphan(X) --- a person with only one parent. TIP: celina is the only half-orphan in the KB |
| * widow(X) (and widower(X)) --- assume that all the single-parents are single because of the spouse's death. TIP: tobiasz is the only widower in the KB, there are no widows. In CLIPS you may check results of the following rule: <code> |
| (defrule widower |
| ... |
| => |
| (assert (widower ?x)) |
| (printout t ?x " is widower" crlf) |
| )</code>. Do you get the expected result? |
| |
| ===== 6. Tracking the execution of the program ===== |
| Since CLIPS doesn't correctly find the widowers, it is necessary to track the execution of the program: |
| |
| === 6.1. Tracking the facts ===== |
| Allows you to track operations on facts: add, delete, change of the value. |
| - In the first step, we will start observing the **widower** rule to see what triggers it: <code> (watch rules widower) </code> |
| - We reset the fact base: <code> (reset) </code> |
| - Restart the inference: <code> (run) </code> |
| - Now we see the triggers and indexes of facts from which we started. |
| - Now check which fact triggered the inference: <code>(facts)</code> |
| |
| ===== 6.2. Rule tracking ===== |
| |
| Allows tracking of rules: firing, activation. |
| - Because we did learn nothing interesting tracing the fact, we will follow the **widow** rule and all the rules it depends on: **parent**, **marriage**: <code> |
| (unwatch all) |
| (watch rules marriage widow parent) |
| </code> |
| - Now we reset the fact base: <code> (reset) </code> |
| - Restart the inference: <code> (run) </code> |
| - What is the reason behind the malfunction of the **widower** rule? |
| - How can we fix it? |
| |
| === 6.3. Tracking in Prolog ===== |
| Prolog allows you to follow the program. To do so, you set the so-called. trace point. |
| |
| Trace points: |
| * ''trace/0'' - sets the trace point on all predicates, eg: |
| <code> |
| ?- trace, woman(K), parent(K, _). |
| </code> |
| * **trace/1** - sets the trace point at the indicated predicate, |
| * **trace/2** - modifies trace point of the specific events (call, redo, exit, fail), eg: |
| * remove the trace point from the specified predicate //something/1// <code> trace(something/1, -all) </code> |
| * set a trace point tracking only calls to the specified predicates //something// of arbitrary arity. <code>trace(something, call +)</code> |
| * Predicate ''debugging/0'' lists all the set trace points. |
| * The ''debug/0'' predicate activates debug mode. |
| * Predicate ''nodebug/0'' disactivates debug mode. |
| |
| Check following code: |
| <code> |
| ?- trace(parent). |
| [debug] ?- trace(mother). |
| [debug] ?- trace(father) |
| [debug] ?- parent(dariusz, tomasz). |
| [debug] ?- nodebug. |
| </code> |