Lab 13

Goal

To write logic programming rules for the + and * operations on monadic representations of the natural numbers and get first-hand experience with asserting them to the querysys.scm and asking queries to see how they do simple arithmetic on natural numbers.

Experiments

Although you will only write one define statement, you will have to test many cases before you can be confident that your rules are right, so I'll call these tests experiments. See below.

The natural numbers (0, 1, 2, 3, ...) can be represented very simply by lists of ones. Thus, () represents 0, (1) represents 1, (1 1) represents 2, (1 1 1) represents 3 and so on. In general, natural number n is represented by a list of n ones. Notice that if N is a list of n ones, representing n, the next larger natural number, 1 + n, will be represented by the list (1 . N) (which is equivalent to consing 1 onto the front of the list N). Thus, we can write a fact and a rule that defines the natural numbers as follows:

(number ())

(rule (number (1 . ?n)) (number ?n))
(The rule says that 1 + n is a number if n is a number.) (The order doesn't matter because facts are always used before rules.)

The + operation will be represented by the plus relation. This if m + n = s, and M is a list of m ones, N is a list of n ones, and S is a list of s ones, the fact that m + n = s will be represented by the logic programming fact (plus M N S). (For example, the mathematical fact that 2 + 3 = 5 is represented by the logic programming fact (plus (1 1) (1 1 1) (1 1 1 1 1)).) Two rules are needed to define the plus relation so that it corresponds to the + operation. Here is one of them (the easy one!):

(rule (plus () ?x ?x) (number ?x))
This just says that xero added to anything is that thing provided that that thing is a number.

The other rule shows how more complicated sums are defined in terms of simpler sums. In other words, when 1 + m is added to n, the sum is just 1 + the sum of m and n. (Recall above how 1 + something can be represented in our monadic representation of natural numbers.)

Similarly, the relation times will represent the relationship between the product of two numbers and those two numbers. In other words, if m * n = p, and M is a list of m ones, N is a list of n ones, and P is a list of p ones, the fact m * n = p will be represented by the logic programming fact (times M N P). (For example, the mathematical fact that 2 * 3 = 6 is represented by the logic programming fact (times (1 1) (1 1 1) (1 1 1 1 1 1)) Here is one of the two rules you will need:

(rule (times () ?x ()) (number ?x))
(This says that 0 times anything is 0 provided that thing is a number.) You have to write the other rule. This rule states in effect that (1 + m ) times n is n + (m times n). Note that you will have to use a plus relation and a times relation in the body of this rule. (You do not have to mention the number relation; that is already taken care of in the rule that I gave you above.)

To do the testing that you will want to do, I suggest that you do the following: create a file in which the following scheme definition appears.

(define rules '(

(assert (number ()))
(assert (rule (number (1 . ?n)) (number ?n)))

(Put assertions of the two rules for the plus relation here.)

(Put assertions of the two rules for the times relation here.)

))

Load this file directly into a DrScheme environment (or you can create the above define statement directly in an empty DrScheme environment if you don't want to create the file I just suggested). To test, open another DrScheme environment and load querysys.scm. Click on Run, then type (query-r-e-p) to start the query system. Now you can copy and paste (Ctrl-c and Ctrl-v) from the first Drscheme environement (with the define statement in it) to the Query input: prompt in the second DrScheme environment. Press the Return key to terminate the input. Copy just the assertions you want to test, not the (define rules '( line or the )) line at the bottom. These won't be needed until you are ready to submit to the Automated Tester.) You can copy all the assertions you want to input at one time; you don't have to copy them one at time.

Experiments with number

You do not have to do these experiments, but I thought you should know what to expect if the number assertions are loaded. A number query that contains no variable, e.g., (number (1 1 1)), will just return the query as the result, e.g., (number (1 1 1)). The query (number ?n), however, will return an infinite number of results, namely, all the natural numbers! Here is what it would look like:
(number ())
(number (1))
(number (1 1))
(number (1 1 1))
(number (1 1 1 1))
and so forth. You will have to click on the STOP button in DrScheme to stop this infinite output.

Experiments with plus

If you have the plus rule assertions properly written and in the proper order relative to each other, you should be able to get results from queries like the following:
(plus (1 1) (1 1 1) (1 1 1 1 1))
(plus ?n (1 1 1) (1 1 1 1 1))
(plus (1 1) ?n (1 1 1 1 1))
(plus (1 1) (1 1 1) ?n)
(plus ?m ?n (1 1 1 1 1))
The first four queries will return only one result and the query system will be ready for another input. The last query will return six results and then will prompt for the next input. If any of these don't return any result or if a result is returned and then the query system continues running, your rule assertions are in the wrong order, even if the rules themselves are correct. You will have to stop the query system with the STOP button if this happens.

The query (plus ?m ?n ?s) will return all possible sums, in a really odd order. Obviously, the Automated Tester is not going to test such a query!. Similarly, if there are two variables in the plus query and one of them is in the third argument position, the query system will go into an infinite loop. Little will be learned by doing this.

Experiments with times

For these experiments, you will have to cut and paste all of the assertions, for all three relations into the query system. The only queries using variables in a times query will be queries like (times (1 1) (1 1 1) ?n) where the one variable is in the third argument position. A variable in any other position will cause the query system to run forever. (This is due to limitations in the design of the query system. These limitations are removed in commercial logic programming systems, but it would be too complicated for us to remove them from our query system.)

However, you will want to try the following queries before submitting your solution to the Automated Tester:

(times ?n (1 1 1) (1 1 1 1 1 1))
(times (1 1) ?n (1 1 1 1 1 1))
If your rules are in the proper order, the query system will print out the proper answer (times (1 1) (1 1 1) (1 1 1 1 1 1))), and then will go into an infinite loop. If it goes into an infinite loop without first printing the proper answer, your rules are not in the right order. (Obviously, these queries will not be tested by the Automated Tester, but they are useful to you as a way to check that your rules are in the proper order.)

Submission

After you are satisfied that your assertions are correct and in the proper order, submit them to the Automated Tester by copying the (define rules statement, in its entirety, from the first DrScheme environment and pasting it into the Program text box on the submission form. Remember, the Automated Tester only works when it is given one or more define statements. Any other kind of expression will cause it to crash.

NOTE: The Automated Tester will run very slow on this lab assignment, taking 30 seconds or longer before it gives a reply. Be patient!

Suggestions

As stated before, if the query system goes into an infinite loop (either printing out an infinite sequence of results, or printing out nothing), you have to stop the process by clicking on the STOP button.

To start up the query system again, just type (query-r-e-p) to the DrScheme prompt. The query system will remember the asserted facts and rules that you gave it before you stopped it.

If you want to change your assertions or put them in a different order, do not input them to the query system after having already input similar assertions before. Having multiple copies of the rules will just slow done the query system and the order of the rules will be all messed up, so you will not get the results you want anyway. Instead, stop the query system by clicking on the STOP button, then click on the Run button to rerun the query system with an empty list of facts and rules. Type the (query-r-e-p) command again to the DrScheme prompt. Now, copying and pasting the assertions you want to test will produce useful results.

If you are maintaining your assertions in an external file as I originally suggested, and you make a change in it, you can reload it into the first DrScheme environment by clicking the Revert button. No need to go to the Open or Open recent option on the File menu.