You are on page 1of 68

Week #1 Objectives: Major aim of this lab task is: Introduction to Prolog How to use Turbo Prolog.

g. How to write & execute programs in Turbo Prolog. Introduction to Prolog -Stands for PROgramming in Logic -High-level interactive language. -It is a non procedural language Programming languages are of two kinds: Procedural (BASIC, ForTran, C++, Pascal, Java); Declarative (LISP, Prolog, ML). In procedural programming, we tell the computer how to solve a problem. In declarative programming, we tell the computer what problem we want solved. (However, in Prolog, we are often forced to give clues as to the solution method). What is Prolog used for? Good at Poor at: Repetitive number crunching, Representing complex data structures, Input/Output (interfaces). Grammars and Language processing, Knowledge representation and reasoning, Unification, Pattern matching, Planning and Search. i.e. Prolog is good at Symbolic AI.

Prolog Program Structure: 1. domains It is an optional section. This keyword is used to mark a section declaring the domains that would be used in the code. E.g.: person = symbol disease, indication = symbol 2. predicates This section contains the declarations of the predicates that would be later defined in the clauses section of the code. e.g.: father(person,person) symptom(disease, indication) 3. clauses It contains the actual definitions of the previously declared predicates.
1

4. goal This section is used to query prolog database Representing Facts, Rules, and Queries When we write in Prolog, we are typically constructing one of three things: 1. A FACT - something that we are asserting to be true. 2. A RULE - something that allows us to infer new knowledge from existing facts and rules. 3. A QUERY - a question to be answered based on existing facts and rules. A Prolog fact is simply a predicate or an atomic formula (an atom, or an atom, followed a parenthesized list of arguments followed by a period. Examples of facts & their representation in Prolog: In Plain English John is the father of Jim. Jane is the mother of Jim. Jack is the father of John. In Prolog father( john, jim ). mother( jane, jim ). father( jack, john ).

A Prolog clause is a rule if it contains a HEAD & BODY separated by :- symbol. Each head must be a predicate & each body is sequence of predicates followed by commas. HEAD may be inferred to be true if BODY is true. In plain English a rule can be written as: Person 1 is a parent of Person 2 if Person 1 is the father of Person 2 or Person 1 is the mother of Person 2. In prolog: parent( Person1, Person2 ) :father( Person1, Person2 ). parent( Person1, Person2 ) :mother( Person1, Person2 ). A Prolog QUERY has the form of a fact (i.e. it is an atomic formula), but is entered when the interpreter is in query mode, rather than appearing in a file that is consulted. It may also contain variables. 1. The interpreter reports whether the query is true (a fact, or can be inferred from one or more rules). 2. If the query contains one or more variables, the interpreter also reports the value(s) of the variable(s) that make the query true.

3. If the query contains one or more variables, the interpreter will allow the user to ask about other ways to satisfy the query by using different values for the variables. Examples: Demo Prolog Program 1: domains animal = symbol person = symbol predicates dog(animal) owns(person, animal) chases(animal, person) clauses dog(rocco). dog(odie). owns(arbuckle, odie). owns(alexander, rocco). chases(rocco, alexander). Chases(odie, Arbuckle). Note: Enter Following quries in the goal window dog(rocco). Response of interpreter: Yes dog(alexander). Response of interpreter: No owns(arbuckle, odie). Response of interpreter: Yes owns(odie, arbuckle). Response of interpreter: No (order of arguments is important) owns(X, odie). Response of interpreter: X = arbuckle owns(arbuckle, X). Responses of interpreter: X = odie X = garfield chases(D, C). Responses of interpeter: D = rocco C = alexander Demo Prolog Program 2: domains person = symbol
3

predicates father(person, person) mother(person, person) clauses father(bill, joe). father(jack, bill). mother(marry, bill). mother(kate, joe). -Add grandfather & grandmother facts in the sample program & test your program -Taking a hint from examples of query, write a program for those quries.

Week #2 Objectives: Major aim of this lab task is: Introduction to Prolog Rules Prolog Variables. Backtracking. A look at previous lab: A Prolog program may succeed or fail. Prolog programs consist of predicate definitions Predicate definitions consist of clauses Clauses consist of a head and (so far) a body A clause head has a predicate name and sometimes some arguments. A goal is a predicate name and sometimes some arguments. A goal matches against clause heads in order. If no clause matches, that goal fails. Successful matching may cause variables to be bound to values. If a variable in the top-level goal becomes bound, prolog compiler reports this. Prolog Rules: A Prolog clause is a rule if it contains a HEAD & rule BODY separated by :- symbol. Each head must be a predicate & each body is sequence of predicates followed by commas. HEAD may be inferred to be true if BODY is true. In plain English a rule can be written as: Person 1 is a parent of Person 2 if Person 1 is the father of Person 2 or Person 1 is the mother of Person 2. In prolog: parent( Person1, Person2 ) :father( Person1, Person2 ). parent( Person1, Person2 ) :mother( Person1, Person2 ). Backtracking: Backtracking gives prolog the capability to find several solutions to a problem. It is like searching a maze. Each time a fact or left-hand side of a rule is used to fulfill a goal (sub-goal), and there are more facts or rules that may give solutions, prolog sets: A pointer = BACKTRACK POINT Prolog can use any number of pointers. Predicates with several possibilities to search are called NON-DETERMINISTIC predicates. CUT is used to remove backtracking possibilities. Demo Program (A family tree example):
predicates offspring(symbol,symbol) mother(symbol,symbol) grandparent(symbol,symbol) 5

grandfather(symbol,symbol) predecessor(symbol,symbol) parent(symbol,symbol) female(symbol) male(symbol) clauses parent(pam, bob). parent(tom, bob). parent(tom, liz). parent(bob, ann). parent(bob, pat). parent(pat, jim). female(pam). male(tom). female(liz). female(ann). female(pat). male(jim). % Rules offspring(Y,X) :parent(X,Y). mother(X,Y) :parent(X,Y), female(X). grandparent(X,Z) :parent(X,Y), parent(Y,Z). grandfather(X,Z) :grandparent(X,Z), male(X). predecessor(X, Z) :parent(X,Z). predecessor(X, Z) :parent(X,Y), predecessor(Y,Z). Test the GOALs mother(X,Y). mother(X, pam). grandparent(X, _). grandfather(_,tom) offspring(_,_)

Variables in Prolog: Prolog has no assignment statement. Capital letters are used to indicate a variable in prolog rule or query. Variables in Prolog get their values by being unified with values. Until it gets a value, a variable is said to be free; when it gets a value, it becomes bound. When backtracking; variables become free again. Variables are used as part of the pattern-matching, process, not as a kind of information storage.

Anonymous Variables: The anonymous variable can be used in place of any other variable. The difference is that the anonymous variable will never get set to a value. GOAL parent(Parent, _). But it can also be used in facts ! owns(_, shoes). GOAL owns(bill,shoes). GOAL owns(jane,shoes). Exercise: 1. Consider the following predicates & clauses section of a prolog program:
PREDICATES can_buy(symbol, symbol) person(symbol) car(symbol) likes(symbol, symbol) for_sale(symbol) CLAUSES can_buy(X,Y):person(X), car(Y), likes(X,Y), for_sale(Y).

Complete the clauses section according to predicates section & test the following goals:
likes(judy, Y). likes(X, tennis). likes(X, Y). can_buy(judy,What) can_buy(who,hot_rod)

2. Translate the following English assertions into Prolog predicates and type them into a file.
peter was born in miami. miami is in florida. florida is in the usa. anyone born in the usa is a uscitizen. anything in florida is in the usa.

Here are some more facts and rules, expressed in English. Translate them into Prolog and enter them into a file.
corn is food. potato is food. bessie gives milk. leo has hair. leo eats meat. tweety flies. john likes anything that is food. 7

Anything that has hair is a mammal. anything that gives milk is a mammal. anything that is a mammal and eats meat is carnivore. john buys anything that is a bird.

Now type in the following queries (in Prolog):


Does john like potato? What does john like? Is tweety a bird? Does john buy tweety? What are all the mammals? Who is the carnivore?

3. Write a Prolog knowledge base specifying the following facts and rules: 1. 2. 3. 4. 5. Hints: 1. Harry is a wizard. This sentence assigns a property (being a wizard) to a specific individual (Harry). It hence states a fact. Properties are ususally encoded as Prolog predicates, and specific individuals as atoms. Remember that atoms cannot start with a capital letter; i.e., Harry is not an atom, while harry and 'Harry' are atoms. 2. Hagrid scares Dudley. This sentence says that a particular relation (scare) holds between two specific individuals (Hagrid and Dudley). Hence, it states a fact. 3. All wizards are magical. This sentence does not talk about a specific individual, but about all individuals with a certain property (all individuals with the property of being a wizard). It expresses a general rule about wizards. The sentence could be reformulated as if somebody is a wizard, then he/she is magical or as for all X, if X is a wizard, then X is magical. 4. Uncle Vernon hates anyone who is magical. This sentence states that a particular relation (hate) holds between a specific individual (Uncle Vernon) and any other individual with the property of being magical. You need a rule to express this. The sentence could be reformulated as for all X, if X is magical, then Uncle Vernon hates X. 5. Aunt Petunia hates anyone who is magical or scares Dudley. This sentence is very similar to the above. It states that Aunt Petunia hates anyone who is magical and in addition, she hates anyone who scares Dudley. This can be reformulated as follows: for all X, if X is magical or scares Dudley, then Aunt Petunia hates X, which is the same as saying for all X, if X is magical, then Aunt Petunia hates X, and for all X, if X scares Dudley, then Aunt Petunia hates X. That is, we express the disjunction by specifying two rules: one for each disjunct. Try the following queries after completing the program: Harry is a wizard. Hagrid scares Dudley. All wizards are magical. Uncle Vernon hates anyone who is magical. Aunt Petunia hates anyone who is magical or scares Dudley.

1. Does Aunt Petunia hate Hagrid? (The answer should be yes.) 2. Who does Uncle Vernon hate? (The answer should be Harry.) 3. Who does Aunt Petunia hate? (The answer should be Harry and Hagrid. Type semicolon to get the second answer). 4. Extend the following program so that X is a wizard if X's father or mother is a wizard?
father(albert,james). father(james,harry). mother(ruth,james). mother(lili,harry). wizard(lili). wizard(ruth). wizard(albert). wizard(X) :father(Y,X), wizard(Y), mother(Z,X), wizard(Z).

5. The following picture shows who is sitting at the Gryffindor table. Define the knowledge base to represent who is sitting right of whom. sits_right_of(X,Y) should be true if X is to the right of Y.

Test your implementation by asking queries. For example: 1. 2. 3. 4. 5. Is Lavender to the right of Parvati? Is Lavender to the right of Neville? Who is to the right of Hermione? Who is sitting at the table? Who is sitting two seats to the right of Hermione? Who is sitting between Neville and Fred?

10

Week # 3 Objectives: Major aim of this lab task is: Introduction to Recursive Rules Simple Input & Output. A look at previous lab: Backtracking gives prolog the capability to find several solutions to a problem. The = sign indicates unification what we have been calling matching. An unbound variable unifies with anything, and becomes bound to it. Anonymous variable (written _) does not retain a value. In unification, anonymous variables match anything. Consider the following clauses section:
parent(pete,ian). % Pete is a parent of Ian parent(ian,peter). parent(ian,lucy). parent(lou,pete). parent(lou,pauline). parent(cathy,ian). female(cathy). % Cathy is female. female(lucy). female(pauline). female(lou). male(ian). % Ian is male. male(pete). Male(grant). male(peter).

a) Define predicates section for the above clauses section. b) Also define the rule for mother such that for all X and Y, X is the mother of Y, if X is the parent of Y and X is female. c) Rule for fathers same except for female, use male. d) Grandparents are parents of parents. e) Siblings are people with the same parent. f) Introduce rules for both relations in the above program and find: a. all the siblings of grant; b. all the siblings of lisa; c. all the grandparents of lucy d. all the people who are grandparents g) Formulate queries to find: a. all the children of ian; b. all the parents of ian; c. all the males; d. all the people who are parents. h) Add a rule brother to the family tree program. Use this rule to find people who have a brother. i) Assume that an aunt is the sister of a parent. Add a rule for aunt (note you will first have to define sister) to the family tree program and use it in queries. The Predecessor Relation:
11

Consider the family tree program. Wed like to be able to define predecessor: a parent, or a parent of a parent, or a parent of a parent of a parent Can be defined as: predecessor(X,Z):parent(X,Z). predecessor(X,Z):parent(X,Y), parent(Y,Z). predecessor(X,Z):parent(X,Y1), parent(Y1,Y2), parent(Y2,Z). Problems: Lengthy (not important) If we take the first two of these (or three or four etc) we get a finite depth on our search for predecessors. Lets think... Offsprings point of view: A is Bs predecessor if either A is Bs parent, or A is a predecessor of Bs parent Predecessors point of view: X is predecessor of Y if X is Ys parent, or X is Zs parent & Z is Ys parent The predecessors point of view can be expressed as predecessor(X,Z):parent(X,Z). or predecessor(X,Z):parent(X,Y), predecessor(Y,Z). This type of definition is called a recursive definition. They are very important in Prolog. A set of clauses referring to the same relation is known as a procedure. Simple I/O in Prolog: readln predicate: It is a built in predicate which can be used to read a string or a symbol into a variable.
12

write predicate: This predicate is used to print string messages on the screen. New line: nl can be used for line break or write(\n) can also be used for line break.

Simple greeting program: domains person = symbol predicates worker(person) greet(person) clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X). Simple greeting program II: domains person = symbol predicates worker(person) greet(person) start clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X).

13

start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). Representing And & Or conditions in rules: If we use comma in rule body to separate different predicates in rule body than we are using and condition. For example, start rule of previous program uses three different predicates & each one of them is executed in the given order: start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). but if we want to insert an or condition for greeting different people with different messages than the for of rule will be: start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name); greet(grant).

Now, if you enter grant as your name than only grants greet rule will be executed. Check to see if it works or not? Exercises: Use appropriate messages using I/O predicates in family tree program. Last exercise of previous lab was:

Here are some more facts and rules, expressed in English. Translate them into Prolog and enter them into a file.
corn is food. potato is food. bessie gives milk. leo has hair. leo eats meat. tweety flies. john likes anything that is food. Anything that has hair is a mammal. anything that gives milk is a mammal. anything that is a mammal and eats meat is carnivore. john buys anything that is a bird. 14

Now type in the following queries (in Prolog):


Does john like potato? What does john like? Is tweety a bird? Does john buy tweety? What are all the mammals? Who is the carnivore?

Do the same program again with proper I/O messages.

15

Week # 4 Objectives: Major aim of this lab task is: Introduction to Recursive Rules Simple Input & Output. A look at previous lab: Backtracking gives prolog the capability to find several solutions to a problem. The = sign indicates unification what we have been calling matching. An unbound variable unifies with anything, and becomes bound to it. Anonymous variable (written _) does not retain a value. In unification, anonymous variables match anything. The not Predicate: Sometimes we can express in knowledgebase a particular fact which is not true. To do so, we can use the built-in predicate not. The not predicate cannot be used to express a fact or appear in the head of the rule. It can only be used in a premise. Consider the clauses section of the following example:
male(ian). % Ian is male. male(pete). male(grant). male(peter). married(pete). married(peter). % Rule to find out who is bachelor. bachelor(P) :male(P), not(married(P)), write(P, is a bachelor ).

j) Define predicates section for the above clauses section. k) Query the knowledge base to find out bachelors. The Predecessor Relation: Consider the family tree program. Wed like to be able to define predecessor: a parent, or a parent of a parent, or a parent of a parent of a parent Can be defined as: predecessor(X,Z):parent(X,Z). predecessor(X,Z):parent(X,Y), parent(Y,Z). predecessor(X,Z):16

parent(X,Y1), parent(Y1,Y2), parent(Y2,Z). Problems: Lengthy (not important) If we take the first two of these (or three or four etc) we get a finite depth on our search for predecessors. Lets think... Offsprings point of view: A is Bs predecessor if either A is Bs parent, or A is a predecessor of Bs parent Predecessors point of view: X is predecessor of Y if X is Ys parent, or X is Zs parent & Z is Ys parent The predecessors point of view can be expressed as predecessor(X,Z):parent(X,Z). or predecessor(X,Z):parent(X,Y), predecessor(Y,Z). This type of definition is called a recursive definition. They are very important in Prolog. A set of clauses referring to the same relation is known as a procedure. Simple I/O in Prolog: readln predicate: It is a built in predicate which can be used to read a string or a symbol into a variable. write predicate: This predicate is used to print string messages on the screen. New line: nl can be used for line break or write(\n) can also be used for line break.

Simple greeting program: domains


17

person = symbol predicates worker(person) greet(person) clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X). Simple greeting program II: domains person = symbol predicates worker(person) greet(person) start clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X). start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). Representing And & Or conditions in rules: If we use comma in rule body to separate different predicates in rule body than we are using and condition. For example, start rule of previous program uses three different predicates & each one of them is executed in the given order:
18

start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). but if we want to insert an or condition for greeting different people with different messages than the for of rule will be: start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name); greet(grant).

Now, if you enter grant as your name than only grants greet rule will be executed. Check to see if it works or not? Exercises: Use appropriate messages using I/O predicates in family tree program. Last exercise of previous lab was:

Here are some more facts and rules, expressed in English. Translate them into Prolog and enter them into a file.
corn is food. potato is food. bessie gives milk. leo has hair. leo eats meat. tweety flies. john likes anything that is food. Anything that has hair is a mammal. anything that gives milk is a mammal. anything that is a mammal and eats meat is carnivore. john buys anything that is a bird.

Now type in the following queries (in Prolog):


Does john like potato? What does john like? Is tweety a bird? Does john buy tweety? What are all the mammals? Who is the carnivore?

Do the same program again with proper I/O messages.

19

Week # 5 Objectives: Major aim of this lab task is: Introduction to Recursive Rules Simple Input & Output. A look at previous lab: Backtracking gives prolog the capability to find several solutions to a problem. The = sign indicates unification what we have been calling matching. An unbound variable unifies with anything, and becomes bound to it. Anonymous variable (written _) does not retain a value. In unification, anonymous variables match anything. The not Predicate: Sometimes we can express in knowledgebase a particular fact which is not true. To do so, we can use the built-in predicate not. The not predicate cannot be used to express a fact or appear in the head of the rule. It can only be used in a premise. Consider the clauses section of the following example:
male(ian). % Ian is male. male(pete). male(grant). male(peter). married(pete). married(peter). % Rule to find out who is bachelor. bachelor(P) :male(P), not(married(P)), write(P, is a bachelor ).

l) Define predicates section for the above clauses section. m) Query the knowledge base to find out bachelors. The Predecessor Relation: Consider the family tree program. Wed like to be able to define predecessor: a parent, or a parent of a parent, or a parent of a parent of a parent Can be defined as: predecessor(X,Z):parent(X,Z). predecessor(X,Z):parent(X,Y), parent(Y,Z). predecessor(X,Z):20

parent(X,Y1), parent(Y1,Y2), parent(Y2,Z). Problems: Lengthy (not important) If we take the first two of these (or three or four etc) we get a finite depth on our search for predecessors. Lets think... Offsprings point of view: A is Bs predecessor if either A is Bs parent, or A is a predecessor of Bs parent Predecessors point of view: X is predecessor of Y if X is Ys parent, or X is Zs parent & Z is Ys parent The predecessors point of view can be expressed as predecessor(X,Z):parent(X,Z). or predecessor(X,Z):parent(X,Y), predecessor(Y,Z). This type of definition is called a recursive definition. They are very important in Prolog. A set of clauses referring to the same relation is known as a procedure. Simple I/O in Prolog: readln predicate: It is a built in predicate which can be used to read a string or a symbol into a variable. write predicate: This predicate is used to print string messages on the screen. New line: nl can be used for line break or write(\n) can also be used for line break.

Simple greeting program: domains


21

person = symbol predicates worker(person) greet(person) clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X). Simple greeting program II: domains person = symbol predicates worker(person) greet(person) start clauses worker(ian). worker(grant). worker(rose). worker(phil). worker(rebecca). greet(grant):write(Hello grant!),nl, write(How are you today?). greet(X):write(How are you? , X). start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). Representing And & Or conditions in rules: If we use comma in rule body to separate different predicates in rule body than we are using and condition. For example, start rule of previous program uses three different predicates & each one of them is executed in the given order:
22

start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name). but if we want to insert an or condition for greeting different people with different messages than the for of rule will be: start:clearwindow, write(What is your name?), readln(Name),nl, greet(Name); greet(grant).

Now, if you enter grant as your name than only grants greet rule will be executed. Check to see if it works or not? Exercises: Use appropriate messages using I/O predicates in family tree program. Last exercise of previous lab was:

Here are some more facts and rules, expressed in English. Translate them into Prolog and enter them into a file.
corn is food. potato is food. bessie gives milk. leo has hair. leo eats meat. tweety flies. john likes anything that is food. Anything that has hair is a mammal. anything that gives milk is a mammal. anything that is a mammal and eats meat is carnivore. john buys anything that is a bird.

Now type in the following queries (in Prolog):


Does john like potato? What does john like? Is tweety a bird? Does john buy tweety? What are all the mammals? Who is the carnivore?

Do the same program again with proper I/O messages.

23

Week # 6 Objectives: Major aim of this lab task is: To practice all the concepts learned so far. Program 1: Develop a program to store facts regarding students, the courses in which they are registered and the course schedule. This information may be declared as following: students(rollnumber,name,age,city) registered(rollnumber,coursename) course_schedule(coursename,days,roomnumber) Develop the menu and supporting rules to enable the user to receive the following information: 1- Names and Roll numbers of all students 2- Names of the students registered in a particular course 3- Names of students belonging to a particular city 4- The time table of a particular course 5- Exit Use dummy names and data of your course. Solution: domains rollno = name = age = city = course = day = roomno Choice = integer symbol integer symbol symbol symbol = symbol integer

predicates student(rollno,name,age,city) registered(rollno,course) course_schedule(course,day,roomno) option(Choice) do clauses % facts


24

student(39,"Wajid",45,"Lahore"). student(19,"Tahir",40,"Lahore"). student(29,"Abdul Basit",35,"Lahore"). registered(39,"Maths"). registered(39,"Physics"). registered(19,"Physics"). registered(29,"Chemistry"). course_schedule("Maths","Sunday","R1"). course_schedule("Physics","Monday","R2"). course_schedule("Chemistry","Tuesday","R1"). % rules option(1):student(X,Y,_,_), write("Name: ",Y," fail. option(1). option(2):student(X,Y,_,_), registered(X,Z), write("Name: ",Y," fail. option(2). option(3):student(_,X,_,Y), write("Name: ",X," fail. option(3). option(4):course_schedule(X,Y,Z), write("Course: ",X," fail. option(4). option(5):exit(0). do:write("\n\n * * * * * * * * * * * * * Menu * * * * * * * * * * * * * * *"),nl, write("1.) Names and Roll Numbers of all Students"),nl, write("2.) Names of Students registered in a particular course"),nl, write("3.) Names of Students belonging to a particular city"),nl, write("4.) The time table of a particular course"),nl, write("5.) Exit"),nl, write("\n==>> Enter your choice: "),

Roll No: ",X),nl,

Course: ",Z),nl,

City: ",Y),nl,

Day: ",Y,"

Room: ",Z),nl,

25

readint(Choice),nl, option(Choice). 1. 2. Save & execute the program by typing do in goal window. What is the result? You can use F5 key to expand goal window. Modify the program so that after displaying particular result, the program will ask do you want to continue? If yes than display the menu again, execute the choice & continue till user enters no.

Program 2: Write a declarative program in PROLOG to enable the use of periodic table: The irst menu may be served as follows with subsequent prompts. 1)- Find an element & its associated properties by entering its atomic number 2)- Find an element & its associated properties by entering its symbol 3)- Find the members of a group of elements (1-8) 4)- Find elements as metals, non metals or noble gases 5)- Exit Given the following elements only: GroupNumber Type Symbol AtomicNumber AtomicWeight 1 (M) H 1 1.0079 1 (M) Li 3 6.491 2 (M) Be 4 9.012 3 (NM) B 5 10.811 4 (NM) C 6 12.011 5 (NM) N 7 14.007 6 (NM) O 8 15.999 7 (NM) F 9 18.998 8 (NG) He 2 4.0389 8 (NG) Ne 10 20.170 M = Metal NM = Non Metal NG = Noble Gases Solution: domains name atomic_number atomic_weight group_number type = = = = = symbol integer real integer symbol

predicates element(name,atomic_number,atomic_weight,group_number,type) do option(integer)


26

clauses % facts element("H",1,1.0079,1,"Metal"). element("He",2,4.0389,8,"Noble Gases"). element("Li",3,6.941,1,"Metal"). element("Be",4,9.012,2,"Metal"). element("B",5,10.811,3,"Non Metal"). element("C",6,12.011,4,"Non Metal"). element("N",7,14.007,5,"Non Metal"). element("O",8,15.999,6,"Non Metal"). element("F",9,18.998,7,"Non Metal"). element("Ne",10,20.170,8,"Noble Gases"). %rules do:write("\n\n* * * * * * * * * * * * * * * * * * * * Menu * * * * * * * * * * * * * * * * * * * *"),nl, write("1)- Find an element & its associated properties by entering its atomic number"),nl, write("2)- Find an element & its associated properties by entering its symbol"),nl, write("3)- Find the members of a group of elements (1-8)"),nl, write("4)- Find elements as metals, non metals or noble gases"),nl, write("5)- Exit"),nl, write("\nEnter Your Choice:"), readint(Option), option(Option), do. option(1):write("\nEnter the Atomic Number="), readint(AtomicNumber), element(Name,AtomicNumber,AtomicWeight,GroupNumber,GroupType),nl, write("Element Symbol: ",Name,"\nAtomic Weight: ",AtomicWeight,"\nGroup Number: ",GroupNumber,"\nGroup Type: ",GroupType),nl. option(2):write("\nEnter the Element Symbol:"), readln(Name), element(Name,AtomicNumber,AtomicWeight,GroupNumber,GroupType),nl, write("Atomic Number: ",AtomicNumber,"\nAtomic Weight: ",AtomicWeight,"\nGroup Number: ",GroupNumber,"\nGroup Type: ",GroupType),nl. option(3):write("\nEnter the Group Number (1-8):"), readint(GroupNumber), element(Name,AtomicNumber,AtomicWeight,GroupNumber,GroupType), write("\nElement : ",Name,"\nAtomic Number: ",AtomicNumber,"\nAtomic Weight: ",AtomicWeight,"\nGroup Type: ",GroupType),nl,
27

fail. option(4):write("\nEnter the Group Type (Metal,Non Metal,Noble Gases):"), readln(GroupType), element(Name,AtomicNumber,AtomicWeight,GroupNumber,GroupType),nl, write("\nElement Symbol: ",Name,"\nAtomic Number: ",AtomicNumber,"\nAtomic Weight: ",AtomicWeight,"\nGroup Number: ",GroupNumber),nl, fail. option(5):exit(0). 1. Save & execute the program by typing do in goal window. What is the result?

28

Week #7 Objectives: Major aim of this lab task is: To practice all the concepts learned so far. The Cut Predicate: Sometimes it is desirable to selectively turn off backtracking. Prolog provides a predicate that performs this function. It is called the cut, represented by an exclamation point (!). The cut effectively tells Prolog to freeze all the decisions made so far in this predicate. That is, if required to backtrack, it will automatically fail without trying other alternatives. Program 1: An Example of Using the Cut: Add predicate section for the following clauses section:
clauses holiday(friday,may1). weather(friday,fair). weather(saturday,fair). weather(sunday,fair). weekend(saturday). weekend(sunday). % We go for picnics on good weekends and May 1st picnic(Day) :- weather(Day,fair), weekend(Day). picnic(Day) :- holiday(Day,may1).

Write the following query in goal section:


picnic(When).

You should get three answers; make sure you understand where they come from! Note that in order to get this answer, Prolog had to work through exactly one unsuccessful instantiation of When with "friday", before getting it right the second time. The First Cut Now change the definition of picnic to the following:
picnic(Day) :- weather(Day,fair), !, weekend(Day). picnic(Day) :- holiday(Day,may1).

Now when we pose the query: Picnic(When) Prolog will try to satisfy the sub-goal:
weather(When,fair), !, weekend(When).

29

The first rule for weather is:


weather(friday,fair),

so the new sub-goal becomes:


....., !, weekend(friday).

Prolog passes the cut, and goes on to try to satisfy


weekend(friday)

which fails. Previously, it would have backtracked to the last choice point, and gone on with processing
weather(saturday,fair)

But now the presence of the cut stops it going back, so it is trapped between the cut and the end of the (failed) predicate. The answer now is simply:
No.

(Check that this is so...) Another Cut Change the definition of picnic for a second time to get:
picnic(Day) :- weather(Day,fair), weekend(Day), !. picnic(Day) :- holiday(Day,may1).

With the same query Prolog proceeds as before, until it gets to the sub-goal:
....., weekend(friday), !.

This time we go on to process:


weekend(friday)

which fails, and so we go back to the last choice point without meeting the cut. Since we also have:
weather(saturday,fair).

the new sub-goal becomes:


....., weekend(saturday), !.

This time the whole goal succeeds, and Prolog processes the cut. Since there is a successful answer, Prolog prints out:
30

When = saturday.

However, because it has met the cut, it cannot go back, and so it will not return any extra answers. (Check this...) Yet Another Cut Finally, change the definition of picnic once more, to get:
picnic(Day) :- !, weather(Day,fair), weekend(Day). picnic(Day) :- holiday(Day,may1). This time when we ask picnic(When) the first thing we do is to process the cut, and

Prolog puts down the "no going back" marker. Any solutions we get from now on have to come from between the "!" and the end of the clause. As before

weather(friday,fair)

fits, and so we try to satisfy:


weekend(friday)

which fails. We backtrack to the last choice point, which was for the goal:
weather(Day,fair)

Since we can get back here without passing the cut, we are free to consider the alternatives, and ultimately get:
When = saturday. When = sunday.

Note that the second attempt to get the answer friday never happens, because getting to the goal for this would involve crossing the cut, which we can't do. Thus there are only two solutions in this case.

31

Week #9 Objectives: This laboratory exercise introduces several basic elements of the LISP
programming langauge, including numbers, symbols, and functions. Starting Out When you run Lisp, you'll be in Lisp's command-line interpreter.You type expressions, it evaluates them and prints the values. For example: a. (+ 2 3 5) 10 b. 5 5 c. (print (+ 2 3 5)) 10

Elements of LISP 1. In LISP, processing proceeds by typing expressions into the LISP environment. After each expression is entered, LISP o reads the expression, o evaluates the expression to determine its value, and o prints the resulting value. This read-eval-print cycle forms the basis for all processing within LISP. Numbers are expressions, whose value or meaning is the number itself.

2.

Accuracy: Enter a read number with many digits. How many digits are printed in the answer for integers? For reals? 3. Fractions: Determine what happens when you enter a fraction. For example, what value is returned when you enter: 3/5 -18/19 10/34 How many digits are printed in the answer for rational numbers? 4. Numeric Procedures: In LISP, we apply operations to data using a prefix notation with parentheses. For example, the function f(x) would be written (f x). Also, all operation names are listed as the first component within the parentheses. Observe what happens when you type the following operations into LISP: (- 27 3) (/ 17 2) (/ 17 -2) (/ 17 2.0) (truncate (/ 17 4)) (round (/ 17 4)) (mod 17 3) (sqrt 4) 32

(sin 0.5) (sqrt -2) (gcd 12 15) (gcd 9 10) (+ (* 3 2) (/ 8 4)) 5. Symbols are LISP's analog of words; symbols are sequences of characters, such as hi TwoBeOrNot2Be This-is-a-symbol. In LISP, symbols may act as variable names, but they do not have a value until we give them one. Describe what happens when you type one of the above symbols into LISP. FIRST START What is the result of the following expressions? Solve them first on paper and then verify your result. 12 -12 1/3 ; Ratio (+ 12 45) (+ 12 45 78) ; Arbitrary number of arguments (+ 12 (- 45)) ; Unary minus (+ 12 (- 45 78)) ; Binary minus (1+ (* 2 3)) (1- (+ 2 3)) (/ 35 13) (/ 35.0 13.0) (/ 35 5) ; Integer (/ 34 5) ; Ratio (float (/ 34 5)) ; Floating point number (- (/ 1 (/ (+ 2 3) (* 4 5))) 6) Lists In LISP, a list is written by enclosing the elements of the list in parentheses. Here are some simple examples: (+ x y) (this is a list) (sqrt x) () These lists have 3, 4, 2, and 0 components, respectively. The list () with 0 components also is called the empty list or the null list. In LISP, the null list may be represented as either () or NIL. Any or all components of a list can, in turn, be lists: (* pi (expt r 2)) (+ (* x x) (* 3 x) 2) (all x (if (human x) (mortal x))) ( () ) ((())) ((()())()) In reviewing the second of these examples, (+ (* x x) (* 3 x) 2) is a list with four components: + 33

(* x x) (* 3 x) 2 List Extraction Functions: Parts of lists can be extracted by car and cdr: car returns the first element or component of a list. cdr returns the rest of a list after the first element is removed. Examples: (car '(a b c)) = a (car '((a) b c)) = (a) (car (car '((a) b c))) = a (car 'a) error: a is not a list. (car '()) error: () is not a pair. (cdr '(a b c)) = (b c) (cdr '((a) b c)) = (b c) (cdr (cdr '(a b c))) = (c) (cdr (car '((a) b c))) = () (cdr 'a) error: a is not a list. (cdr '()) error: () is not a pair. In each of these examples, note that car and cdr are applied to a list which is introduced with a quote. Since parentheses are used both to group data into a list and to call procedures, the LISP interactive interface needs to see a single quote at the front of a list literal, so that it will treat it as a datum instead of evaluating it. Since combinations of car and cdr are frequently used, all combinations up to four uses of car and cdr are defined as functions of the form cxxxr:

(caar x) = (car (car x)) (cadr x) = (car (cdr x)) (caddr x) = (car (cdr (cdr x))) Atoms Every Lisp object is either an atom or a list. Examples of atoms: numbers: 235.4, 2e10, #x16 2/3 variables: foo, 2nd-place, *foo* constants: pi, t, nil :keyword strings, chars: "Hello!" #\a arrays: #(1 "foo" A) #1A(1 "foo" A) #2A((A B C) (1 2 3)) structures: #s(person first-name dana last-name nau) For Lisp atoms other than characters and strings, case is irrelevant: foo = FOO = Foo = FoO = : : : pi = Pi = PI = pI 2e10 = 2E10 List Constructor Function: Two basic functions that construct new list structures are the functions cons and list. If y is a list, then we can think of (cons x y) as adding the new element x to the front of the list y. 34

(cons 'a '(b c)) = (a b c) (cons 'a '()) = (a) (cons '(a) '(b)) = ((a) b) The list function makes a list out of the elements that follow: (list 'a 'b 'c 'd) = (a b c d) (list 'a '(b c)) = (a (b c)) (list 'a '()) = (a ()) (list '(a) '(b)) = ((a) (b)) List Manipulation Functions append makes a new list consisting of the members of its argument lists. append takes any number of arguments. (append '(a) '(b)) = (a b) (append '(a b) '(c d)) = (a b c d) (append '(a) '(b) '(c)) = (a b c) reverse makes a new list that is the reverse of the top level of the list given as its argument. (reverse '(a b)) = (b a) (reverse '((a b)(c d))) = ((c d)(a b)) length returns the number of components in the [top level] of a list. (length '(a)) = 1 (length '(a b)) = 2 (length '((a b))) = 1 (length '(+ (* x x) (* 3 x) 2)) = 4 Exercises: 1. Type the following three expressions into LISP:

(length 5) (length '(+ 2 3)) (length (+ 2 3))

In each case, explain the result. 2. Consider the expression (all x (if (human x) (mortal x))). Write lisp expressions to extract each of the following:

all if human 3. Write a LISP expression that creates the list (a b c) out of the individual symbols a, b, and c, using the list functions. 4. Write a LISP expression that creates the list (a b c) out of the individual symbols a, b, and c and the null list NIL, using only the cons, car, and cdr functions. 5. Explain what happens when you apply reverse to the lists:

35

((a) (b c)) (+ (* x x) (* 3 x) 2) 6. Evaluate the following slightly tricky forms:

(append '(a b c) '( )) (list '(a b c) '( )) (cons '(a b c) '( )) In each case, explain why you received the result that you obtain.

36

Week #10 Objectives: The objective of this lab task is to:


Use relational operators of LISP. Use logical operators of LISP. Use conditional structures. Constructing & using user defined functions

Comparison and Equality Operators (= x y) is true iff x and y are numerically equal (equal x y) is true iff x and ys printed representation is equal (= 2 3) NIL (= 2 2) T (= 2 2.0) T (equal 2 2.0) NIL (= '(1 2 3) '(1 2 3)) // well see later why lists require *** - =: (1 2 3) is not a number (equal '(1 2 3) '(1 2 3)) T (equal '(1 2 3) '(1 2 5)) NIL The standard comparison operators are built in: >, <, <=, >= (> 1 2) NIL (< 1 2) T (<= 1 2) T (>= 1 2) NIL (>= 2 2) T (<= 2 2) T (<= 2 3) 37

T (<= 3 2) NIL null and not are two predicates that are used to test if a value is nil or () (which mean both empty list and false). null is commonly used if your context is checking if a list is empty, while not is commonly used if checking whether a value is false. (null nil) T (null ()) T (not (= 1 2)) T (not (= 1 1)) NIL (null '(1 2 3)) NIL and and or are built in, but they don't just return T or NIL as you might expect. and stops execution and returns nil as soon as it finds an argument that evaluates to nil. Otherwise, it returns the value of the last expression it evaluated. (and (= 1 2) (= 2 2)) NIL (and (= 3 3) (= 2 2)) T (and (= 3 3) (= 2 2) 5) // note that 5 doesnt evaluate to nil, so this and is true 5 or will stop executing once it finds its first non-nil argument and will return the value of evaluation of that argument. Only if all arguments evaluate to nil will a NIL be returned. (or (= 1 2) (= 2 2)) T (or (= 1 2) (= 3 2)) NIL (or 5 (= 1 2) (= 3 2)) 5 Defining Your Own Functions The syntax above describes how to use functions in Lisp. The syntax for defining your own functions is as follows: (defun <name> (<parameter-list>) <body>)

38

The parameter list should be a list of variable symbols, so it is contained within () to indicate where the variable list stops. The body is going to be an actual call to another function, so it will be in parentheses. As an example, here is the way to define the square function: (defun square (x) (* x x)) SQUARE (square 2) 4 (square 3.5) 12.25 Conditional Statements if statements are defined as follows: (if <test> <then> <else>) The components in brackets can be any Lisp item that can be evaluated. If the <test> returns any value other than nil, the <then> component is evaluated and returned as the value of the if statement. Otherwise, if a nil is returned, the <else> component is evaluated and its value is returned. Heres a definition of min for only two variables using an if statement: (defun min2 (x y) (if (< x y) x y)) MIN2 (min2 2 3) 2 (min2 3 2) 2 (min2 2 2) 2 A more complex conditional statement (similar to a case statement in C++) is the cond statement. cond allows multiple tests, and each test can be followed by a sequence of actions to be performed. Once a test is found to be true, the sequence of actions associated with that line is performed and the cond statement ends. If a test is found not to be true, the next test is tried. The general form is as follows: (cond (<testa> <form1a> <form2a> ... <resulta>) (<testb> <form1b> <form2b> ... <resultb>) ... (<testk> <form1k> <form2k> ... <resultk>)) Often times, the last case is used as the default case its test is just t (true). As an example, lets define absolute value with cond: (defun abs2 (x) (cond ((> x 0) x) (t (* -1 x)))) ABS2

39

(abs2 3) 3 (abs2 -3) 3 Recursive Statements Using if and cond, recursive statements are fairly straight-forward. The definition of factorial is as follows: (defun factorial (x) (if (> x 0) (* x (factorial (- x 1))) 1)) FACTORIAL (factorial 0) 1 (factorial 1) 1 (factorial 2) 2 (factorial 3) 6 Reading In Functions From Files: Definitions saved in a file can be loaded with the function load which has the syntax (load filename). (load "lab11.lisp") ;; Loading file lab11.lisp ... ;; Loaded file lab11.lisp T (factorial 2) 2 A comment can be added to a Lisp program by placing a semicolon on a line. Any text after the semicolon is considered a comment. Tracing and Debugging To trace the execution of a function, type (trace functionNameHere). To turn off tracing, type (untraced functionNameHere). To turn off tracing from all functions with one call, type (untrace). Given the function, (defun factorial (x) (if (> x 0) (* x (factorial (- x 1))) ; if x > 0, compute x * factorial (x-1), 1) ; else factorial(0) = 1 ) Heres an example of a factorial trace: (trace factorial) (FACTORIAL) (factorial 3) 1. Trace: (FACTORIAL '3) 2. Trace: (FACTORIAL '2) 40

3. Trace: (FACTORIAL '1) 4. Trace: (FACTORIAL '0) 4. Trace: FACTORIAL ==> 1 3. Trace: FACTORIAL ==> 1 2. Trace: FACTORIAL ==> 2 1. Trace: FACTORIAL ==> 6 6 List Functions The more interesting functions are the built-in list processing functions. They can be broken down into three broad categories: Making a new list: cons, list, append Quote: Making some parts of the list not be evaluated. Selecting parts from a list: first, rest cons takes two arguments, an atom and a list, and adds the atom to the front of a list (ie it does a pre-pending of an element): >(cons 1 nil) (1) >(cons 1 (cons 2 nil)) (1 2) Remember that each atom (i.e. each set of character symbols, i.e. each variable) is evaluated by the interpreter. The a is undefined before this statement, and thus evaluation of a will fail. In addition, remember that a list (set of parentheses) considers the first argument to be a function to call. So, if the interpreter got past a, the interpreter will try to call the function b. If b is not defined as a function, an error is raised. To work around this issue without having to calls cons multiple times, you can use the quote operator. A single quote is used to tell the Lisp interpreter that you dont want a value evaluated, but that instead you want to use the value directly. So, to allow a to have the meaning a (as in the character a), you would type a. Our failed example from above will work if re-written as follows: > (cons a (b c d)) // Note how the whole list is quoted by the () operation (A B C D) The list function takes an arbitrary number of arguments (atoms or list) and constructs a new list with each of the arguments as an element in the list in their original form. >(list 2 3 4) (2 3 4) >(list a (a s d f)) (A (A S D F)) The append function takes an arbitrary number of lists as arguments and constructs a new list with each element from the input arguments. (append '(a b) '(c d)) (A B C D) (append '(a b) '(c d) '(d e)) (A B C D D E) (append '(a b) '(c d) '(d '(e f))) (A B C D D '(E F)) 41

The selector functions first and rest act much like hd and tl in Erlang. first takes a list as an argument and returns the first element of the list. rest takes a list as an argument and returns the list that is the original list without the first element. (first '(a s d f)) A (rest '(a s d f)) (S D F) (first (rest '(a s d f))) S Other Useful Atom and List Functions Other useful built-in functions include length, which takes as a single argument a list and returns the number of items in that list: (length '(1 2 3)) 3 (length '(1 2 (2 3))) 3 atom, which takes a single argument and returns whether or not that argument is an atom . listp, which takes a single argument and returns whether or not that argument is a list. (atom 'a) T (atom '(1 2 3)) NIL (listp 'a) NIL (listp '(1 2 3)) T (atom (+ 1 2)) // what is this actually doing? T nth which takes two arguments and essentially performs array indexing, with 0 as the first entry (nth 0 '(3 4 5)) 3 (nth 1 '(3 4 5)) 4 (nth 3 '(3 4 5)) // note that this is indexing outside of the list NIL

42

Week #11 Objectives: The lab this week will continue to introduce you to new features of Lisp. Its main
focus is on variables, iteration, and arrays, and a little more on recursion: tail recursion. setq and setf Last week it was mentioned how an atom (a collection of one more character symbols) can represent a variable (we had to put an apostrophe in front of the atom to indicate an actual raw character or word). To set a variable to a particular value requires the use of the setq function. Think of setq as an assignment statement. This function has the following syntax: (setq atom value) As an example of its use, > (setq age 20) 20 > (setq legalToDrink (> age 21)) NIL > legalToDrink NIL > (setq age 25) 25 > (setq legalToDrink (> age 21)) T > legalToDrink T It is important to note that most functions acting on lists dont actually change the list but instead return an updated version of the list. Using the setq function can allow updates to the list. > (setq mylist '(1 2 3)) (1 2 3) > (cons '0 mylist) (0 1 2 3) > mylist (1 2 3) > (setq mylist (cons '0 mylist)) // setq is essentially an assignment statement (0 1 2 3) // mylist has now essentially become 0::mylist > mylist (0 1 2 3) What if you wanted to replace the 1 at the front of (1 2 3) with a 0? We could do that that with: > (setq mylist '(1 2 3)) (1 2 3) 43

> (setq mylist (cons 0 (rest mylist))) (0 2 3) > mylist (0 2 3) An alternative allowed in Lisp for updating particular spots in a list is to use the setf function which allows updating of components of a list data structure. I tend to think of setf as an array updating function. The syntax is as follows: (setf (pointer-to-position-to-update) new-value) Interpret (pointer-to-position-to-update) loosely you essentially need a function call here to put you over the right element to update first and nth are good functions for doing that. Examples include: > (setq mylist '(1 2 3)) (1 2 3) > mylist (1 2 3) > (setf (first mylist) '0) 0 > mylist (0 2 3) > (setf (nth 0 mylist) '2) 2 > mylist (2 2 3) > (setf (nth 2 mylist) '4) 4 > mylist (2 2 4) Functions with Multiple Body Statements The body of a function can be composed of an arbitrary number of statements, each in its own parentheses. The value that is returned from a function defined as a sequence of statements is the value of the last function that is evaluated. The ability to call other functions in this way allows side effects to occur. These side effects are used primarily to update variables (both global and local variables, which will be defined better below). Heres a (not very useful, but good example) function that makes use of multiple statements inside the function body: (defun addTwo (x) (setq y (+ 1 x)) (+ 1 y)) Note that this function, addTwo, has two statements that execute separately (one is not nested in the other). This function is equivalent to the C or Java function below.

44

int addTwo(int x) { y = x + 1; return y + 1; } When executed, we get the following results: > (addTwo 5) 7 Note that the value of the last statement that executes is what is returned -- the result of (+ 1 y). Local and Global Variables setq essentially defines global variables. A variable declared as an argument to a function or defined with a special let statement (discussed below) is considered as a local variable. Local variables will have priority over global variables when Lisp is looking to interpret a variable. As an example, look at the square function definition: (defun square (x) (* x x)) Even if there is an x variable declared at a higher level in the program, the only value that will be worked with is the argument passed in as the parameter x. When the square function finishes executing, the locally defined x goes out of scope (disappears). On the other hand, if a function uses a variable that it didnt declare locally, it will examine all global variables to see if a matching one exists. If the global variable cant be found or, if you try to read from it but it holds no value, the function fails. The function below: (defun y-plus (x) (+ x y)) will look for a global variable called y. Let Statement The let statement allows for explicit local variables to be defined within a function beyond the arguments. The syntax is as follows: (let ((<vbl1> <expr1>) ............... (<vbln> <exprn>)) <body>) Note that arbitrary numbers of local variable can be declared, and each set to a particular value (using an expression (the exprn slot)). If a value field is not present, the variable is set to nil initially. Note also that the parentheses in front of the let matches with the one after the body. This indicates those local variables can be only used within that body statement. If you need to make use of variables setup within the let definition in managing another later variable in the let definition, use let*. Otherwise, with just the plain let syntax, all variables are declared in parallel and they cant build on each other. (defun test () (let ((a 1) (b 1)) (* a b))) (defun test2 () (let ((a 1) (b a)) (* a b))) ; THIS SHOULD FAIL (defun test3 () 45

(let* ((a 1) (b a)) (* a b))) > (test) 1 > (test2) // this failed because of the parallel issue *** - EVAL: variable A has no value The following restarts are available: USE-VALUE :R1 You may input a value to be used instead of A. STORE-VALUE :R2 You may input a new value for A. ABORT :R3 ABORT > (test3) 1 Iteration Techniques Last week, we saw that with cond and if statements, recursion was fairly simple to implement. Several of the TakeHome problems used recursion to define list operations these all had the basic format of working on the head element and then calling a function recursively to process the remaining part of the list. The base case in list management was often times hitting the empty list. Other techniques besides recursion for performing an action multiple times are available in Lisp. The first such technique is dotimes, which acts much like a for loop. The syntax for dotimes is : (dotimes (<counter> <limit> <result>) <body>) counter is a variable you provide which the system will end up setting to 0. The counter variable will be updated by one after each time the body is called. The limit variable should be set as a positive integer. You can pass in limit as a hardcoded value, as a variable, or as the result of an expression. result is an optional field that becomes a local variable. If it is present, its value will be returned as the result of the dotimes function. Otherwise nil will be returned. The body function will be executed until counter = limit (the body does not run when counter=limit, just up to that point). Heres an example of a power(x,y) [xy, for y >= 0] function implemented recursively. (defun power2 (x y) (cond ((= y 0) 1) (t (* x (power2 x (- y 1)))))) Now, an example working iteratively using dotimes: (defun power3 (x y) (let ((result 1)) (dotimes (count y result) (setq result (* x result))))) The dolist function is similar to the dotimes function, but it iterates on the length of the target list passed in. Thesyntax is as follows: (dolist (<next-element> <target-list> <result>) <body>) result and body play the same role as they did previously. next-element is a local variable you provide which will be set to hold the current item the iterator is sitting on in the list. target-list should be set as the list you want to work within the argument list. An example of a function which can exploit dolist is counting the number of times an element appears in a list. Implemented recursively: (defun countRecursive (x mylist) 46

(if (= 0 (length mylist)) 0 (if (equal x (first mylist)) (+ 1 (countRecursive x (rest mylist))) (countRecursive x (rest mylist))))) And then iteratively: (defun countIterative (x mylist) (let ((result 0)) (dolist (e mylist result) (if (equal x e) (setq result (+ 1 result)) nil)))) Tail Recursion Remember that tail recursion is an approach to recursion that has some nice efficiency properties and which suggests for many problems using an accumulator variable to push along the answer while it is being generated instead of generating the answers during the backtracking phase (when the recursion is unwinding from the base case). An example of a tail recursive power function and its trace is shown below compared against the same function written without tail recursion. Without tail recursion: (defun power2 (x y) (cond ((= y 0) 1) (t (* x (power2 x (- y 1)))))) > (power2 2 3) 1. Trace: (POWER2 '2 '3) 2. Trace: (POWER2 '2 '2) 3. Trace: (POWER2 '2 '1) 4. Trace: (POWER2 '2 '0) 4. Trace: POWER2 ==> 1 3. Trace: POWER2 ==> 2 2. Trace: POWER2 ==> 4 1. Trace: POWER2 ==> 8 8 With tail recursion: (defun power4 (x y) (power4Accumulator x y 1)) (defun power4Accumulator (x y currentAnswer) (cond ((= y 0) currentAnswer) (t (power4Accumulator x (- y 1) (* x currentAnswer))))) > (power4 2 3) 1. Trace: (POWER4 '2 '3) 2. Trace: (POWER4ACCUMULATOR '2 '3 '1) 3. Trace: (POWER4ACCUMULATOR '2 '2 '2) 4. Trace: (POWER4ACCUMULATOR '2 '1 '4) 5. Trace: (POWER4ACCUMULATOR '2 '0 '8) 5. Trace: POWER4ACCUMULATOR ==> 8 4. Trace: POWER4ACCUMULATOR ==> 8 3. Trace: POWER4ACCUMULATOR ==> 8 2. Trace: POWER4ACCUMULATOR ==> 8 1. Trace: POWER4 ==> 8 8

47

Composite Data Structures We have already seen how lists can be thought of as arrays. With the use of the nth function, it is easy to retrieve a single element from an arbitrary position out of a list. > (setq arrayOne '(1 2 3)) (1 2 3) > (nth 0 arrayOne) 1 > (nth 1 arrayOne) 2 > (nth 2 arrayOne) 3 To emulate a 2 dimensional array, the following code would be required: > (setq arrayTwo '((1 2 3) (4 5 6))) ((1 2 3) (4 5 6)) > (nth 0 arrayTwo) (1 2 3) > (nth 1 arrayTwo) (4 5 6) > (nth 0 (nth 1 arrayTwo)) 4 This could be very tedious for multi-dimensional arrays. Instead of using lists, an explicit array creation and component access syntax in Lisp is as follows: To create an array, use the syntax: (setq <nameofArrayDesired> (make-array '(<dim1Size> <dim2Size> ))) As an example, the following code will create a 1-dimensional array of size 5 and a 2-d 3x3 array: > (setq vector1 (make-array '(5))) #(NIL NIL NIL NIL NIL) > (setq vector1 (make-array '(3 3))) #2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL)) To read from an array spot defined in this way, use the aref syntax: (aref <nameOfArrayDesired> <dim1Index> <dim2Index> ) See below for an example. Array indexing starts with 0. To write into an array spot, use the setf syntax combined with an aref call (remember how setf takes the explicit reference to the spot you are interested in writing into): > (setf (aref vector1 1 1) 25) 25 > vector1 #2A((NIL NIL NIL) (NIL 25 NIL) (NIL NIL NIL)) 48

> (aref vector1 1 1) // access first underlined item above 25 > (aref vector1 1 2) // access second underlined item above NIL It is possible to initialize an array with a value while its being created. If it isnt initialized, all the internal values will be set to nil. > (setf anArray (make-array '(3) :initial-contents '(1 2 3))) #(1 2 3) > anArray #(1 2 3) > (aref anArray 2) 3

49

Week #12 Objectives: This lab introduces two final new Lisp features - a general repetition structure and
ways of working with C++ struct/classlike data types. Another Looping Structure The two looping structures from last week were both dependent on known lengths (either a number you passed to the dotimes function or the length of a list passed to the dolist function). To me, these are essentially for loops. Another more general looping function is the do function. do has the following syntax: (do ( (<var1> <init1> <update1>) (<var2> <init2> <update2>) ... (<varN> <initN> <updateN>) ) (<test> <body1>) <body2> ) Note how the do syntax first consists of a set of variables. Each variable can be initialized, as well as specified with an optional update statement indicating how it should be updated after each iteration of the loop. The test is evaluated before each iteration and is the test for termination. If it passes, the sequence of statements in body1 is executed, returning the value from the last expression evaluated. The body2 component consists of functions that are executed on every iteration until the termination condition is met. If you intend on using updated values from an updateM statement in an updateN statement, where updateN happens after updateM, use do* instead of do (like we had to do with let and let*). Heres an example function written in C++ that we can translate to Lisp to show the use of the do function. This function computes mn using a while loop: int power(int m, int n) { result = 1; exponent = n; while (exponent > 0) { result = result * m; exponent= exponent 1; } return result; } The equivalent functions in Lisp using do: (defun power2 (m n) (do ((result 1) ; initialize result to 1 (exponent n)) ; initialize exponent to n ((= exponent 0) result) ; if exponent = 0, return the result (setq result (* result m)) ; otherwise, multiply result by m (setq exponent (- exponent 1)))) ; and subtract 1 from the exponent

50

You can further exploit the local variable update statements (not employed above) to simplify the function even further (defun power3 (m n) (do ((result 1 (* result m)) (exponent n (- exponent 1))) ((= exponent 0) result))) Composite Data Structures Structs in Lisp are much like their C++ counterpart s they are defined as data structures made up of multiple data holders, with each data holder associated with a name. The defstruct function is used to define a struct. The syntax is (defstruct typename attribute1 attribute2 attribute3 ) > (defstruct employee firstname lastname sex id) EMPLOYEE A struct definition essentially defines a type and allows instances of those types to be created. Default constructors and accessors are available after a struct has been defined. The make-X syntax shown below can be thought of as a constructor for the struct, as it will return an instance of the type. > (setq employee1 (make-employee)) #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID NIL) > employee1 #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID NIL) > (setq employee2 (make-employee)) #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID NIL) > employee2 #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID NIL) Accessing attributes of an instance requires the syntax: (typename-field instanceName) > (setf (employee-id employee1) 123) 123 > (setf (employee-id employee2) 456) 456 > employee1 #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID 123) > employee2 #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX NIL :ID 456) > (employee-id employee2) 456

51

Values can be passed in to the constructor with the following syntax: (setq employee2 (make-employee :attribute1 value1 :attribute2 value2 ) > (defstruct employee firstname lastname sex id) EMPLOYEE > (setq employee2 (make-employee :id 789 :lastname 'bar :firstname 'foo :sex 'male)) #S(EMPLOYEE :FIRSTNAME FOO :LASTNAME BAR :SEX MALE :ID 789) > (employee-lastname employee2) BAR Default values can also be set up to be assigned by the constructor. This requires a small modification to the defstruct syntax, putting parentheses around each attribute that has an associated default value: (defstruct typename (attribute1 value1) (attribute2 value2) attribute3 ) > (defstruct employee firstname lastname (sex 'male) (id 1)) EMPLOYEE > (setq employee3 (make-employee)) #S(EMPLOYEE :FIRSTNAME NIL :LASTNAME NIL :SEX MALE :ID 1) > (employee-id employee3) 1 Finally, given that youve defined a new type, you can then test if variables are of that type with two different built-in functions: (typep variablename typename) which tests whether a variable is of the type typename ( typep means typepredicate). > (typep employee3 'employee) T Alternatively, you can use a special type predicate which directly references the type name you defined. The syntax is: (typename-p variablename) > (employee-p employee3) T > (employee-p '(1 2 3)) NIL

52

Week #13 Objectives:


In this lab you will be using Neural Networks as an alternative tool for decision-making modeling. The majority of empirical studies show that neural networks perform better than traditional linear methods and therefore have great potential to replace traditional forecasting and decision-making models. To model the networks Matlab software would be used under the Unix platform. *Matlab is a tool for doing numerical computations with matrices and vectors. It can also display information graphically. Refer to following site if you want more basic Matlab info: http://www.math.utah.edu/lab/ms/matlab/matlab.html, http://www.math.ufl.edu/help/matlabtutorial/ 1. Download the data. a. Go the class website. (http://www.buffalo.edu/~sbaek3/geo564.htm) b. Extract zip file. c. There are four data files: datann.xls, inputt1, targett1, inputs1, targets1. d. There is a script file called: script1.m The files correspond to the training (inputt1, targett1) and simulation (inputs1, targets1) components of the sample. The target outputs are included in separate files for modeling purposes. You can look at the list of your data by typing the ls command. To see the data contents type:more <filename>. 2. Under the Programs menu, run the X-Win32 6.1 program. a. Once you run it, you will see and icon in the bottom left of your desktop, next to the clock. b. Right click on it. c. Select Sessions. d. Choose UbUnix 3. Log in. a. Use the same user and password as you do in the Ubunix system. 4. Upload data files into your web directory (Unix directory). a. Open ftp S/W Start>Programs>FileZilla>FileZilla b. Type in following. - address : ubunix.buffalo.edu - user: ubid - password:ub p/w c. Click Quick connect 53

d. Drag and drop all files from your local folder in explorer to unix folder on fileZiller . 5. Running Matlab on X-terminal a. Type Matlab & in the terminal window. b. You would see the Matlab window comes up. 6. Set the path to your working directory. a. Type in ls and enter if you want to see file list on the command window on Matlab. b. cd <folder name> if you want to enter into the folder. c. Edit it on your local computer and reupload it into unix directory If you want to edit script file. 7. The Script: a. The following code reads the training data set: input (independent variables) and target (mode choice selected). p=transpose(load('inputt1.txt')); t=transpose(load('targett1.txt')); Matlab reads all the inputs in a matrix format. Therefore matrix operations like transpose can be done to the inputs. The reason for transposing the data is to set it up in thecorrect structure needed by the neural network. b. The next set of functions define the Neural Network(NN) structure, the transfer functions between layers, the training algorithm, the number of neurons, the learning rate, the number of epochs, and the converging criteria. net=newff(minmax(p),[5,1],{'logsig','logsig'},'trainrp'); // Create a feed-forward backpropagation network net=init(net); net.trainparam.show=50; net.trainparam.lr=0.05; net.trainparam.epochs=5000; net.trainparam.goal=0.01; c. The following code defines the neural network and executes the training process. [net,tr]=train(net,p,t); d. Now that the network has been trained and the weights calculated to minimize the sum of square errors the simulation data set (validation data set/prediction data set) is read. ps =transpose(load('inputs1.txt')); ts=transpose(load('targets1.txt')); e. The inputs of the simulation data set are entered in the network and the outputs produced are calculated. y=sim(net,ps); f. The output is rounded in case the transformation function created a number that is not exactly zero or 1, the error is calculated and the outputs are printed on the screen. 54

yprime=round(y); e=ts-abs(yprime); ts yprime e error=sum(abs(e),1) g. Notice that this is just a loop that goes through the error vector which was the difference between the correct output and the predicted value. The variable right increase when error is equal to 0 to know how many times the NN predicted well. The number of correctly predicted is stored in the variable called right. The bigger right is the better prediction. right=0; for i=1: 400, if error(i) == 0 right= right + 1; end end right h. The following command displays the graph and closes the diary where the output of the process has been stored. plot(ts,y,db); hold off; diary off 8. Spend a couple of minutes understanding the script. For a complete list of function and command refer to the Matlab manual for Neural Networks Toolbox. (http://www.mathworks.com/access/helpdesk/help/toolbox/nnet/nnet.shtml ) 9. Running the script. a. To run the script type in the Command Window: script1 b. The script will execute. c. You will see the convergence process in the graph. This represents the training process, the time it takes the network to learn how to produce the given set of outputs. 10. Play with the number of neurons in the hidden layer. In the script the number of neurons is set to 5. Make sure you modify the graphs and output diary names. The diary can be openedusing any text editor. 11. You can change the training method, at this point which is set to trainrp, corresponding toresilient backpropagation. You can modify it to be: Gradient descent backpropagation: traingd Levenberg-Marquardt backpropagation: trainlm Gradient descent with adaptive learning rate backpropagation: traingda or some others. For a complete list refer to the Matlab manual for Neural Networks Toolbox (http://www.mathworks.com/access/helpdesk/help/toolbox/nnet/nnet.shtml ). Each method makes use of a different algorithm.

55

12. You can add additional hidden layers, by adding a third number to the newff command where between the 5 and 1 and add an additional transfer function for the layer. The number will indicate the neurons in that particular layer. e.g. 1) net=newff(minmax(p),[5,1],{'logsig','logsig'},'trainrp'); This network has two layers. The first layer has five logsig neurons and the second layer has one logsig neuron. e.g.2) net = newff([0 10],[5 1],{'tansig' 'purelin'}); The first layer has five tansig neurons and the second layer has one purelin neuron. e.g.3) net = newff([0 10],[5 3 1],{'tansig' 'tansig' 'purelin'}); The first layer has five tansig neurons, the second layer three transig neurons and the third layer one purelin neuron. 13. Test different topologies in terms of the number of hidden layers and the number of neurons in each hidden layer. Vary the training algorithm and given the results decide which network configuration predicts best. 14. Right click on the desktop and logout.

56

Week #14 Objectives:

57

58

59

60

Week #15 Objectives:

61

62

63

64

65

Week #16 Objectives:

66

67

68