CIS505 Assignment 6

8 points; due Thursday November 20

Question 1.

Here is a drawing of part of the Simpsons family tree, as taken from http://public.genoom.com/trees/Simpsons/Bart-Simpson, which (I believe) is based on the book, The Simpsons Uncensored Family Album (by Matt Groening, Harper Design, 2006).
===================================================

                                                        'Clancy Bouvier'=='Jacqueline Gurney'
'Carnival Woman'=='Abraham Simpson'                                     |  
                | 'Abraham Simpson'=='Penelope Olsen'   +------------------+--------------+
                |                  |                    |                  |              |
           'Herbert Powell'     'Homer Simpson'=='Marge Bouvier' 'Patricia Bouvier' 'Selma Bouvier'
                                               |                                          |
                                +-----------------+----------------+                'Ling Bouvier'
                                |                 |                |                 (adopted)
                             'Bart Simpson' 'Lisa Simpson' 'Maggie Simpson'

===================================================
(A==B means that A married B; their children are listed underneath the ==. Note that 'Abraham Simpson' married twice. If you are into this Simpsons thing, please accept my apologies that I omitted Amber Simpson from the tree --- it is just too weird to draw that she was married to both Homer and Abraham Simpson!

Part 1a.
Make a file named simpsons.pl to hold the Prolog clauses that model the above tree structure. Here is part of the coding; you do the rest:

===================================================

female('Carnival Woman').
male('Abraham Simpson').
female('Penelope Olsen').
male('Herbert Powell').
male('Homer Simpson').
male('Bart Simpson').
/* ...you do the remainder of the gender clauses;
   consult the above web link if you are unsure about any person's gender. */
female('Ling Bouvier').

/* predicate   parents(CHILD, FATHER, MOTHER)  asserts that 
   CHILD  has FATHER as its father and  MOTHER  as its mother:
*/
parents('Herbert Powell', 'Abraham Simpson', 'Carnival Woman').
parents('Homer Simpson', 'Abraham Simpson', 'Penelope Olsen').
parents('Bart Simpson', 'Homer Simpson', 'Marge Bouvier').
/* ...you do the remainder of the parent clauses up to this last one: */
parents('Ling Bouvier', none, 'Selma Bouvier')

/* sister(X, Y)  defines that  X  has  Y as a sister if
   Y is female,  X's and Y's parents are the same,  and  X != Y  */
sister(X,Y) :- female(Y),
               parents(X,Father,Mother), parents(Y,Father,Mother),
               X \= Y.
Run this test:
?- sister('Marge Bouvier', Z).
type semicolons till the prover prints False (or No). You should obtain:
Z = 'Patricia Bouvier' ;
Z = 'Selma Bouvier' ;
False

Part 1b.
Code these Prolog predicates and add them to simpsons.pl:

Test your definitions with at least these test cases:

?- aunt('Bart Simpson', Z).
Z = 'Patricia Bouvier' ;
Z = 'Selma Bouvier' ;
false.

?-  aunt(X, 'Patricia Bouvier').
X = 'Bart Simpson' ;
X = 'Lisa Simpson' ;
X = 'Maggie Simpson' ;
X = 'Ling Bouvier'.

?- aunt(X,Y).
(there should be a long list!)

?- brother(A,B).
A = 'Lisa Simpson',
B = 'Bart Simpson' ;
A = 'Maggie Simpson',
B = 'Bart Simpson' ;
false.

?- uncle(X,Y).
false.
Copy and paste your test cases and their outputs into a txt file named simpsons.txt.

Question 2

Copy and paste these clauses into a file named library.pl:

===================================================

/* Functor for defining book and dvd objects:
      ITEM ::=  book(TITLE, AUTHOR)  |  dvd(TITLE)
                       where TITLE and AUTHOR are strings

   Predicates that define ownership of an object
   and when an object is borrowed from the library:
      PRED ::=  owns(KEY, ITEM)  |  borrowed(KEY, PERSON, DUEDATE)
                      where KEY is an atom that begins with  k
                            ITEM is defined above
                            PERSON is an atom
                            DUEDATE is an int
*/
owns(k0, book('David Copperfied', 'Charles Dickens')).
owns(k1, book('Tale of Two Cities', 'Charles Dickens')).
owns(k2, book('Tale of Two Cities', 'Charles Dickens')).
owns(k3, dvd('Tale of Two Cities')).
owns(k4, book('Moby Dick', 'Herman Melville')).
owns(k5, dvd('Brothers Karamazov', 'Fyodor Dostoyevski')).
borrowed(k2, 'Homer', 10).
borrowed(k4, 'Homer', 20).
borrowed(k3, 'Lisa', 40).
borrowed(k0, 'Lisa', 45).
borrowed(k5, 'Homer', 90).

/* overdue  holds true when  ItemKey is borrowed (by  Who)  and is due earlier than  Today */
overdue(ItemKey, Today) :- borrowed(ItemKey, _, DueDate),
                           Today > DueDate.

/* fine  calculates the int value of  HowMuch  when  ItemKey  is overdue as of  Today */
fine(ItemKey, Today, HowMuch) :- overdue(ItemKey, Today),
                                 borrowed(ItemKey, _, DueDate),
                                 HowMuch is  Today - DueDate.

/* getBorrowed(Who, ItemList)  calculates a list of  KEYs
     of all the items  Who  has borrowed. */
getBorrowed(Who, ItemList) :- findall(Key, borrowed(Key, Who, _), ItemList).

===================================================

Part 2a.
Write this definition in Prolog and add it to library.pl:

/* getOverdue(Who, Today, ItemList)  calculates  ItemList,  which is a list of  KEYs
     of all the items  Who  has borrowed that are overdue as of  Today. */      
Hint: your answer will look a lot like getBorrowed's definition. Test your coding on at least these examples:
?- getOverdue('Homer', 25, List).
List = [k2, k4].

?- getOverdue('Lisa', 25, List).
List = [].

?- getOverdue(_, 50, List).
List = [k2, k4, k3, k0].
Copy your test cases and their outputs into the txt file, library.txt.

Part 2b.
Write this definition in Prolog and add it to library.pl:

/* totalfine(Who, Today, Amount)  calculates  Amount,  which is an int
   that states the total fine that  Who  owes due to overdue items as of  Today */
Hint: use this code to total the fine:
/* sum(L, T)  holds true when  T  is the sum of all the ints in list  L. */
sum([], 0).
sum([N|Rest], Total) :- sum(Rest, M), Total is N + M.
Test your coding on at least these examples:
?- totalfine('Homer', 25, Amt).
Amt = 20.

?- totalfine('Lisa', 25, Amt).
Amt = 0.

?- totalfine(_, 100, Total).
Total = 295.
Copy and paste your test cases and their outputs into library.txt.

Implementation

Study the examples in the lecture notes and the examples I posted on the CIS505 Lectures web page.

You download Prolog at http://www.swi-prolog.org/Download.html. (I am happy using an "old version", 5.4.7, but you are welcome to try a newer release.)

When you load a Prolog program, verify there are no errors! (Often an error is triggered by a missing period or comma on the previous line.) Use the listing and trace predicates to see what is happening inside Prolog when you use it.

Plan for several days to do the exercise, because if you get stuck, it might take a day to understand what to do.

Submission

When you are ready to submit, make a folder named YourFirstNameYourLastName6, and place into it
  1. simpsons.pl (Prolog clauses) and simpsons.txt (the test cases for all parts of Question 1)
  2. library.pl (Prolog clauses) and library.txt (the test cases for all parts of Question 2)
Zip the folder and submit at K-State Online. This is not a team assignment --- Please do your own work!