P. 1
Visual Prolog 7

Visual Prolog 7

|Views: 281|Likes:
Published by henripe21

More info:

Published by: henripe21 on Nov 17, 2011
Copyright:Attribution Non-commercial


Read on Scribd mobile: iPhone, iPad and Android.
download as DOCX, PDF, TXT or read online from Scribd
See more
See less





Visual Prolog 7.

3 for Tyros
Eduardo Costa

This book started as a personal project. My intention was simply to write a tutorial on Logic Programming for my son. The success of the book, however, was immense, and I received many suggestions on how to improve the text, or the code, and encouragement to continue with the work. Mail came from Saudi Arabia, China, Russia, Spain, France, Brazil, Canada, and many other places. Although the space is too short to list everyone who wrote me about the book, I want to acknowledge the collaboration and enthusiasm of the following persons: • Elena Efimova, who made many corrections on the text, and in the historical background of Mathematics and Logics. • Mark Safronov, who translated the book to Russian, and made many corrections on the contents of the original. By the way, the Russian translation has a much better layout than the English original. • Thomas W. de Boer, who prepared a parallel edition of the book, with longer explanations, and a text appropriate to rank beginners. • Stuart Cumming. I often give examples that show what one should avoid from the point of software engineering. Stuart pointed out that people could be misled by these examples; he suggests that, whenever an implementation is not robust, I should emphasize its weak points. Although I agree with Stuart, I thought it better to remove the negative examples altogether. • Rose Shapiro, who corrected my Latin, and my description of many historical events. • Yuri Ilyin, who helped me with his expertise; without him, this book would not be written. • Reny Cury, who went through the manuscript correcting typos. • Philippos Apolinarius who helped me with his knowledge of Botanical Latin, and Chinese. • Thomas Linder Puls and Elizabeth Safro, from PDC, for support and encouragement. • Benjamin Emer from Kenosha, Wisconsin. Masters in Teaching, elementary school teacher and teacher of English. He helped with the grammar, editing and fluency of this book.

I Savoir-faire 11
13 13 14 14 16 16 17 17 17 18 22 22 24 27 31 31 32 34 34 35 37 37 38 39 40 43 43 1 Introduction 1.1 Creating a project in VIP ............................................................. 1.1.1 Create a new GUI project: name ..................................... 1.1.2 Compile and execute the program ...................................... 1.2 Examples ...................................................................................... 1.3 Notions of Logics: Ancient Greeks ................................................. 2 Forms 2.1 Create a form: folder/name ............................................................. 2.2 Enable the task menu: e.g. File/New option ................................... 2.3 In CodeExpert, add code to project tree item ................................ 2.4 Example .......................................................................................... 2.5 Notions of Logics: Aristotle‘s Syllogistic .................................... 2.5.1 Valid syllogisms ............................................................... 2.6 Distribution ..................................................................................... 3 Mouse events 3.1 Add code to MouseDownListener ............................................... 3.2 onPaint ......................................................................................... 3.3 Examples ...................................................................................... 3.4 Notions of Logics: Boolean algebra ............................................ 3.5 Argument forms .............................................................................. 4 Less Figures 4.1 Task menu ....................................................................................... 4.2 Project Tree ..................................................................................... 4.2.1 Code Expert ...................................................................... 4.3 Create Project Item .......................................................................... 4.4 Create a new class: folder/name .................................................... 4.5 Edit field contents ........................................................................... 1

2 4.6 4.7

CONTENTS Examples ...................................................................................... 44 Notions of Logics: Predicate calculus ............................................. 44 45 45 46 46 50 51 52 53 53 55 57 57 60 60 61 61 63 68 72 75 75 75 75 76 76 76 77 78 83 85 86 87 89 90 90

5 Horn Clauses 5.1 Functions ...................................................................................... 5.2 Predicates ........................................................................................ 5.3 Solutions .......................................................................................... 5.4 Multi-solutions ............................................................................. 5.4.1 A program that uses multi-solution predicates ................. 5.5 Logical junctors ............................................................................... 5.6 Implication ................................................................................... 5.7 Horn Clauses ................................................................................ 5.8 Declarations ..................................................................................... 5.9 Drawing predicates .......................................................................... 5.10 GDI Object ...................................................................................... 5.11 Examples ...................................................................................... 5.12 Notions of Logics: Meaning of Horn clauses ................................. 6 Console Applications 6.1 Cut ................................................................................................... 6.2 Lists ................................................................................................. 6.3 List schemes .................................................................................... 6.4 Reasoning about programs .............................................................. 6.5 String operations ............................................................................. —Parsing into tokens: fronttoken ........................................................... —String concatenation: concatList ....................................................... —String concatenation: concat/2 and concat/3 ........................................ —Term to String conversion: toTerm ................................................... —Term to String conversion: hasdomain ............................................... —Term to String conversion: toString ..................................................... —Term to String conversion: format ....................................................... —String processing: Useful predicates ................................................. 6.6 Notions of Logics: Grammar for Predicates ................................... 7 Grammars 7.1 Parsing grammar ............................................................................. 7.2 Generating grammar ........................................................................ 7.3 Why Prolog? ................................................................................ 7.4 Examples ...................................................................................... 7.5 Notions of Logics: Natural deduction .............................................

CONTENTS 8 Painting 8.1 onPainting ....................................................................................... 8.2 Custom Control ............................................................................... 8.3 Notions of Logics: Resolution principle .........................................

3 93 94 97 99

9 Data types 101 9.1 Primitive data types ...................................................................... 101 9.2 Sets ............................................................................................... 103 9.3 Sets of numbers ............................................................................... 103 9.4 Irrational Numbers .......................................................................... 106 9.5 Real Numbers .................................................................................. 108 9.6 Mathematics .................................................................................... 108 9.7 Format ............................................................................................. 108 9.8 domains ........................................................................................... 110 9.8.1 Lists .................................................................................... 110 9.8.2 Functors .............................................................................. 110 9.9 Notions of Logics: Horn clauses ..................................................... 114 10 HowtosolveitinProlog ....................................................................... 115 10.1 Utilities .......................................................................................... 116 11 Facts 135 11.1 Class file .......................................................................................... 138 11.1.1 Reading and writing a string ................................................ 138 11.2 Constants ....................................................................................... 139 12 Classes and Objects 141 12.1 Object facts ...................................................................................... 143 12.2 Generic Interfaces ........................................................................... 144 12.3 Interfaces ...................................................................................... 146 12.4 Generic Utilities .............................................................................. 148 13 Giuseppe Peano 151 13.1 Turtle graphics ............................................................................. 151 13.2 Turtle states ..................................................................................... 152 13.3 Recursion ....................................................................................... 154 13.4 Peano‘s curve .................................................................................. 155 13.5 Latino Sine Flexione .................................................................... 155 13.6 Quotations from Key to Interlingua ................................................ 156 13.7 Examples ...................................................................................... 161

.....................................................................................................1 Class draw ............................................................................5 A MIDI player ..........................................................................2 Non-procedure inside a procedure ................3 How the program works ..............3 Handling Chinese ....................................................................................1 Famous programs ...1 Type error ............................1 Object Facts ..................................................................................4 Regular expressions .... 178 17 Text Editor ............................................................. 166 15 Games ................. 201 19........3 Non-determ condition ...... 179 17...................4 CONTENTS 14 L-Systems 163 14.................. 209 20........................................................................................................................................................................ 194 19........................................................................2 Handling the timer ..................2 Examples ............................................................................... ..................... 188 19................................4 Impossible to determine the type .......................... 176 16...................... 180 18 Printing 183 19 Tab forms and other goodies 185 19.......................... 174 16 Animation 175 16... 210 20......2 Botany ...................................... 210 20............ 198 19..... 178 16.. 186 19....................5 Flow pattern ................................................................... 164 14................................................................... 167 15.............................................1 Saving and Loading files ....... 208 20..................................................................1 dopaint ...................................................6 Midi format ........ 203 20 Bugs 207 20...............................................................................................

................................ 217 21................................................... 221 22............................................2 Databases .....................................3 The database manager ...................................................................................1 Grammars ............... 222 ... 222 22.... 219 22 Books and articles 221 22.......................................3 Programming Techniques .................1 Database manager .............................................................2 btr class .. 213 21...........................212 21AData Base Manager 213 21.................................................................

....................................5 Heuristic search .......................... 252 24.............. 256 .CONTENTS 5 II Artificial Intelligence 225 23 Search 227 23......................................................................................................................... 247 24............................................................... 253 25 Alpha Beta Pruning 255 25........................... 246 24.................3 Running the two layer neural network .....4 A Historical Perspective .................... 235 24 Neural Networks 241 24....................2 Implementation of a multi-layer network ...................................1 States ................................1 Move generation ............................................. 230 23........................................................................ 227 23...................................................................3 Breadth First Strategy ................................. 234 23......................1 Neuron description ..4 Depth First Strategy ......................... 228 23..................2 Search tree ...


...................................3 1............................................. mapDataBase/draw..........................2 4............................. 44 Interesting predicates ...... Project Tree/Task Menu ...............3 5................pro ........................ 47 49 50 54 55 59 6.......2 5.............................. Create a new form ....................................5 2............................................................................................................... 13 14 14 15 15 18 19 19 20 20 21 21 22 25 26 PaintResponder ...........1 1..........................................................................................................................................2 2...................... Project tree ........................................................................1 5. mapDataBase/draw...............................................8 2........................................6 Task menu: New Project ......................................................................................1 4...........................List of Figures 1....... Enabling the Task Menu ........................................ Pop-up Form ....................1 2..............................................................................pro ... Dialog and Window Expert .....................1 Reduce in Prolog ........................... 34 Create a new package ................................................. Building the project .............................................. draw.....................................................6 2.............7 2..................................2 1......................................................................................................... 33 Paint Responder .......................................2 4..4 1.... Darii ... Utah cities ......... Class draw ...4 5.............. Resizing the form window ............... Going to the Code Expert .................................................... Barbara ................................................................................. Adding a new item to the Project Tree .............. An empty application ..............................................................................................4 2.................. 41 A form with an edit field .........9 2.. Project Settings ...........3 2...............................................................................................1 3....3 5.............................................5 2....cl and draw.....................cl ....... 41 The fn class ......................................10 3.....................................................5 5...... 69 7 ..........................

......................................................................................8 6................................................... Inserting a file into an editor ....... 134 11........................6 162 ..........................1 Reading a string from file 139 13...................................3 156 13..................................................cl ........................................................................................................ 173 16..............................cl and draw............................................ 168 15.....................1 90 8...................................... 172 15........................................... . ............................................ turtle................................2 dopaint.....................pro ........................................................ A thinking Greek .........1 Lawn form ....... A form with a custom control ..........................................................2 111 Zip in Prolog LIST OF FIGURES ..5 161 13........................ 15................ Peano‘s curve ....... A dictionary of ―difficult‖ LsF words ..........1 click class handles the timer ................................................................................................... was der Fall ist.. 177 .......................... List declaration ...........cl and curve..........................................pro 153 13..............................2 155 13....1 98 9..............1 Minmax tree ..................... Die Welt ist alles.....4 157 13.....................1 Files curve. ........................................................................... 10......... File turtle................................. 176 16.......pro ....pro .........2 draw.....................2 71 7................3 objstate ..1 107 9....................

...................2 A bug caused by a non deterministic predicate ..... .............. 211 23.............................................17........................................................... 209 20. 211 20.....................2 Puzzle ...........1 A buggy program .........................................................................6 182 The insert custom control button ......pro ....................... 228 23................................................................. 19......................................................... Code for onSave ............................................................... 196 19............................... 229 ...............................1 180 17..........3 Midi generator ..............2 180 17.................................................. User control properties .........................................................1 listEdict methods ....................... Code for onLoad .............1 A search tree . 206 20................................ Choose Custom Control dialog ...2 File: ideograms............................ 193 19...............................5 182 17...............................................4 181 17..................3 Deterministic predicate required.............................................. A form with Edit Control ... .................3 181 17...........................................

...........................3 A neural network that can learn how to calculate a xor-gate ..1 A three input perceptron ............LIST OF FIGURES 9 24. 247 ......................... 246 24...................2 A three input perceptron ............................. 242 24......................


Part I Savoir-faire 11 .


1 Creating a project in VIP Let us create an empty project. The environment that you will use to develop your programs is called IDE.Chapter 1 Introduction Figure 1. to which you will add functionality later on. we will refer to the menu of the IDE as the task menu. or GUI for short. When you enter the Visual Prolog IDE. 13 . you will get an environment like the one shown in figure 1.1. The system of windows and dialog boxes that you will create to communicate with potential users of your programs is called a Graphical User Interface. which is the acronym for Integrated Development Environment.1: Task menu: New Project 1.

To execute it.3). Choose the option Project/New from the task menu. as shown in figure 1. Then.3: Project tree 1. choose the option Build/Build from the task menu.1 Create a new GUI project: name This step is quite easy.2.4) .1.1. Figure 1.14 Introduction 1. fill in the Project Settings dialog box as in figure 1.2 Compile and execute the program To compile the program. choose Build/Execute (see figure 1.2: Project Settings Figure 1. Press the button OK and you will get the project tree (figure 1.4. as shown in figure 1.1.

Figure 1. if you prefer.1. and a window like the one in figure 1.5: An empty application . choose the File/Exit option of the application task menu. In order to exit the program.5 will pop up on the screen.1 Creating a project in VIP 15 from the task menu. all you have to do is click on the X-shaped button that appears on the upper right-hand corner of the Window frame.4: Building the project Figure 1.

lots. As for the Greeks. class considerations not being allowed to interfere with merit. when they did so. If we look to the laws. the laws and political decisions were proposed by citizens for whom feats. crowd psychology. or a king‘s deputy. . Therefore. Pericles described the situation as: Our constitution does not copy the laws of neighboring states. and political actions. In this kind of society. In other civilizations. and flattery were among the Greek methods of winning a debate. this book will focus solely on Logics. he would need to convince others.3 Notions of Logics: Ancient Greeks The Ancient Greeks devised a kind of society that was very different from anything that existed before them. Of course they developed other methods of winning an argument besides Logics: the art of telling lies. decisions of political or legal nature were made by a king. advancement in public life falls to reputation for capacity. if someone wanted to advance his interests or make inroads for his views. a small group of aristocrats. they afford equal justice to all in their private differences. 1. this is why it is called a democracy. The proposition was voted and enforced only if the majority of the voters supported it. Its administration favors the many instead of the few.2 Examples The example in this chapter shows how to run an application.16 Introduction 1. which means that you will make the corresponding application do something useful. nor again does poverty bar the way: If a man is able to serve the state. or life experience won the right to a seat in an assembly or in a court of law. the science of disguising a fallacy. ornate language. we are rather a model to others than imitators ourselves. these people could commit to writing the basis for their decisions. and is in directory proj1. prove that he was right and win debates or disputes. However. they would refer the resulting codex to a god. he is not hindered by the obscurity of his condition from proposing laws. necessity forced the Greeks to invent Logics. you will add functionality to the proj1 project. In the next chapter. or to a traditional hero. if no social standing.

as in figure 2. Since you have chosen the option New in New Package. You may want to change the size of the window rectangle. edit fields that you can use to input text. as you do when you resize a normal window. After you press the Create button in the Create Project Item dialog.g. as in figure 2. File/New option When you ran the empty application. 2. 2. The new form name is query. the IDE will display a prototype of the new form. open the tree that appears in the lower part of the TaskMenu dialog and remove the tick from the radio button Disabled that corresponds to the &New\tF7 option. click and hold the mouse at the lower right corner and drag it. double click on the TaskMenu. A form is a window pane where you can add components like buttons that trigger actions.5. Then.2. making it slightly larger than the prototype.mnu branch of the Project tree. 17 . and canvas where you can draw things. choose the File/New in New Package option from the task menu.1 Create a form: folder/name To create a form.3. as in figure 2. another way to get the same result is to right click on the TaskMenu.Chapter 2 Forms In this chapter. you will add a form to the empty project that you have created in chapter 1.1. Visual Prolog will create the query form in a package named after the form.mnu branch. you certainly took notice of the fact that the File/New option was disabled. as in figure 2. and choose the open option. To enable it. Select Form from the left pane and fill in the Create Project Item dialog as in figure 2.4. In order to do this.2 Enable the task menu: e.

whenever you choose the File/New option.1: Adding a new item to the Project Tree .3 In CodeExpert. which opens a floating menu. press the Add button (refer to figure 2. Build the program again. and double click on the branch id_file_new->onFileNew.18 Forms 2.win branch of the project tree with the right button of the mouse.4._X= query::display(W).6). Choose the option Code Expert (figure 2. Figure 2. choosing the Build/Build option from the task menu. as in figure 1.7. _MenuTag) :. click on the TaskWindow. click on the Menu/TaskMenu/id_file/id_file_new option of the Code Expert tree. This will open a text editor with the following snippet: clauses onFileNew(_Source. add code to project tree item To add code to the File/New option. _MenuTag). Build the application and then modify this snippet to: clauses onFileNew(W.7). Execute the program and you will see that. As in figure 2. Finally. a new form is created.

3 In CodeExpert. add code to project tree item 19 Figure 2.3: Resizing the form window .2: Create a new form Figure 2.2.

20 Forms Figure 2.4: Project Tree/Task Menu Figure 2.5: Enabling the Task Menu .

6: Going to the Code Expert Figure 2.3 In CodeExpert.2. add code to project tree item 21 Figure 2.7: Dialog and Window Expert .

which means what (or whom) the proposition is about. Surprisingly. he is considered the father of ophthalmology and of preventive medicine. then filling in the Create Project Item dialog. In his popular book Thesaurus Pauperum (Medical Thesaurus of the Poor People).22 Forms 2. Figure 2. ‗not every‘). with a quantifier (‗every‘. Peter of Spain was one of the first doctors to offer advice on birth control.8: Pop-up Form 2.4 Example The example in this chapter shows how one creates a form by choosing the option File/New. a proposition consists of two terms: a subject and a predicate.5 Notions of Logics: Aristotle‘s Syllogistic For Aristotle. before being elected pope under the name of John XXI. medical doctor and mathematician Pedro Juliao (also known as Peter of Spain) made important contributions to many fields of knowledge. ‗no‘. For instance. Subject comes from the Latin rendering of the Greek term biioxzi\xz\o\(hypokeimenon). for a man who would soon be elected pope. The Portuguese Logician. Predicate is what the preposition talks about the subject. ‗some‘. .

i and o are subcontraries. a and e are contraries.5 Notions of Logics: Aristotle’s Syllogistic 23 he gives recipes for contraception and explains how to provoke menstruation.2. and ii. P and Q cannot both be false. P and Q cannot both be true. and subcontraries. Propositions are classified in contraries. Besides being the author of a few medical books. Two propositions P and Q are contradictories if and only if i. • Some — The proposition is true for some members of the domain. c. • No — The proposition is never true for a member of the domain. Here are the definitions of each one of these classes: a. contradictories. b. or Q is true. Types a and o are contradictories. necessarily. P and Q are subcontraries if and only if i. P and Q can both be true. Peter of Spain wrote a very influential treatise of Logics (Summulae Logicales) and is credited with introducing the following abbreviations for the Logical quantifiers: Quantifier a e i o Type Universal affirmative Universal negative Particular affirmative Particular negative Abbreviation PaQ PeQ PiQ PoQ Example Every P is Q No P is Q Some P is Q Some P is not Q By the way. and ii. P and Q can both be false. P and Q cannot both be true. logical quantifiers are words that determine the range of a proposition over a domain. either P. Interestingly enough. Examples of logical quantifiers: • Every — The proposition is true for every member of the domain. . P and Q are contraries if and only if i. the same happens to e and i. modern doctors have found that many of his recipes are quite effective. and ii.

Permutations are different ways to build lists of things. and six moods in the . The premise containing P is called the major premise. o}. combinations are groups of things. i. . it is called the middle term.. we are dealing with permutations. e. then the number of possible permutations is given by n×n×n×. a}. ‗i‘. the number of possibilities grows to 256. conclusion}. the premise containing S is the minor premise. Aristotle called these terms the extremes. On the other hand. Aristotle recognized four valid moods for each of the first and second figures. If you have n things to choose from. First Figure M ∗P S ∗M P ∗S Second Figure Third Figure Fourth Figure M ∗P P ∗M P ∗M M ∗S M ∗S S ∗M P ∗S P ∗S P ∗S When we replace each asterisk with a quantifier. and S the subject of the conclusion (minor term). 2. the syllogisms are classified in four figures. and you choose p of them. a.5. In this case. one has to choose three quantifiers from the set {a. Since the order of the quantifiers in a syllogism does matter. each distinct tuple ({a. Let P represent the predicate of the conclusion (major term). we get a tuple of propositions: {major premise.. in a list. or mood. there are 43 = 64 possibilities for each figure. According to Peter of Spain. Therefore. M represents the term that is common to the premises but is absent in the conclusion. o} . minor premise. i.) constitutes a modus.24 Forms A syllogism is an argument consisting of exactly three propositions (two premises and a conclusion) in which there appear a total of exactly three terms. ‗o‘). ‗e‘. specifically. since we have four figures. We need to permute three elements from a set of four elements. p times N n =nP -----------------v -------------- In the present case. {a.1 Valid syllogisms Not all candidates for syllogism are logically valid. In order to calculate how many moods exist. Let an asterisk ∗ represent any of the four quantifiers (‗a‘. repetition is not disallowed. the order matters. and the order of the elements of a group does not matter. each of which is used exactly twice. . we need to review our lessons of combinatorics.

Peter of Spain invented Latin mnemonics to help us remember the valid moods. o} – Bocardo {e. Here are the valid moods for the first and second figures: First figure {a. i. a } . therefore. a. Consequently. a. i. i} – Disamis {a. Even so. e} – Cesare {a. The second premise says that All S is M. in his scheme.9: Barbara According to [Lewis Carroll].9 illustrates Venn‘s method for Barbara. For instance. i} – Datisi Figure 2. a. the vowels indicate the mood. one shades the part of M that is not in P (left hand side of the figure). where a word like C/ESARE was spelled CESARE. one must shade the part of S that is outside M. o} – ferio Second figure {e. e} – celarent {a. e. therefore.5 Notions of Logics: Aristotle’s Syllogistic 25 case of the third figure. and pronounced accordingly. Figure 2. o} – baroco Third figure {o. a . a} – Barbara {e. i. The first premise of Barbara says that all M is P. o} – Festino {a. i. one can conclude that All S is P. i. a. that says ∀P is M ∃M is S ∃S is P . e} – Camestres {e. which is a valid mood for the first figure. Classical Scholars will notice that the names are based on the Medieval Latin pronunciation. MaP SaM SaP Let us now consider the Datisi syllogism. The remaining unshaded part of S is entirely inside P. o} – Ferison {i. BARBARA indicates { a . i} – Darii {e. Modern Logics recognizes four modes each for all three figures. a. Venn proposed a diagram to check whether a syllogism is valid. o.2.

The example below is from the Game of Logics. No philosophers are conceited. Venn himself: The Minor Premiss says that some of the constituents in my’ must be saved — mark them with a cross. he and his friend Scott sat and wrote a very good one. . When he noticed that no quality Greek-English dictionary existed. Therefore some not-gamblers are not philosophers. He also hired [Lewis Carroll] as a teacher of Logics for his two daughters. Figure 2. So. The next step is to place the ∃ symbol in the area corresponding to the premise ∃M that the ∃ symbol ˜ shows is S. and ∃ means Some. we put the ∃ symbol on the line. In order to make his classes interesting.10: Darii Alice Liddell‘ s father wanted to give her a very good education.10.26 Forms where the symbol ∀ means All. Venn claims that the universal premise should be met before diagramming a particular premise. erase it. Then as some my’ is to be saved. Figure 2.10 could be in the SMP area or in the SPM area. Some conceited persons are not-gamblers. Since we do not know exactly which area it is in. we have shaded the area of P that is not on M. as required by the premise ∀P is M. one that almost all students of Greek use with pleasure and profit. The Major declares that all xm must be destroyed. [Lewis Carroll] wrote two books for the children: Alice in the Wonderland and the Game of Logics. The conclusion is that Some S is P. The following solution to the above syllogism has been kindly supplied to me by Mr. at the left hand side of figure 2.

No other term is distributed. In other words. we can determine when a syllogism is valid. That is. The rules that show whether or not a term is distributed are: 1. it is not distributed. Besides this. 3. eliminating m. y’x’. 2. if all individual members that it describes are accounted for. Law of the distributed middle: The middle term must be distributed at least once. In common phraseology. The predicate of all negative propositions (E and O) is distributed. to be sure that all members of that term are accounted for. Let us examine the validity of a few figures. Now that we know what a distributed term is. a term is said to be distributed. the conclusion must be negative as well. Three term rule: All syllogisms must have exactly three terms. there must exist my’x’. it must be distributed at least in one of the two premises. You will see that term distribution is a tool for determining the validity of syllogisms that is much easier to use than Euler-Venn diagrams.6 Distribution 27 it must clearly be my’x’. 4. Some not-gamblers are not philosophers. Conclusion with a distributed term: If a term is distributed in the conclusion. A term is distributed when it applies to all elements of a given class. 3. At most one negative premise: A syllogism cannot have two negative premises. 4. These rules mean that if a term is not the subject of a universal proposition (A and E) or the predicate of a negative proposition (E and O). 2. or. It is much easier to code into Prolog programs too. this time using term distribution.6 Distribution The modern method of determining the validity of a syllogism is based in the distribution of each term present in the syllogism. 2. . The rules are: 1. The subject of all universal propositions (A and E) is distributed. A fallacy is a faulty syllogism disguised as a valid inference.2. term distribution is a good method of detecting and exposing fallacies to a wide audience. and if a premise is negative.

No reptiles have fur.28 Forms BARBARA-1 This figure does not have negative premises. By the way. therefore. Since a . in fact. therefore. it is distributed in the minor premise. the middle term is the subject of the first premise. and the conclusion is negative as well. it fulfills rule-3. according to the law of the distributed middle. since it is also the predicate of the first premise. it is distributed in the first premise. since it is the subject of a universal negative proposion. An example of this kind of syllogism: All men are mortal. The middle term (―trustworthy‖) is distributed in the first premise. Since it belongs to the first figure. it does not breach the rule. Therefore. MaP SaM SaP The subject in the conclusion is distributed. (SeP) CESARE-2 This kind of syllogism has only one negative premise. therefore it must be distributed in one of the premises. which is negative. (MeP) All snakes are reptiles. Danaans were a people that belonged to one of the Micenean tribes that fought against the Troyans. that forbids two negative premises. it is distributed in the first premise too. They appear in the poems of Homer and Virgil. (SaM) No snakes have fur. therefore. therefore CESARE-2 satisfies rule-4. The middle term of the first premise is distributed. it fulfills the third rule. the conclusion is negative. which is a universal proposition. No Danaan is trustworthy. it fulfills the law of the distributed middle. (SaM) All Athenians are mortal. it obeys rule-4. (SaP) CELARENT-1 Only the first premise is negative. (PeM) All Spartans are Danaans. (MaP) All Athenians are men. The predicate of the conclusion is a distributed term. thus. where it is the subject of a universal proposition. (SeP) ―Trustworthy‖ is distributed in the conclusion. (SaM) No Spartans are trustworthy. as required by the law of the distributed middle.

Trivia: Virgil‘s sentence is quoted by Sean Connery in The Rock. (SiP) FERIO-1 The first premise is negative. and Odysseus. or faulty syllogism. since it is the most difficult to diagnose. (MeP) Some Greeks are Spartans. (MaP) Some men are Greeks. based on the modern view that the Miceneans were Greeks. The middle is distributed in the first premise. DARII-1 The middle term is distributed in the first premise. or be structured after syllogisms and other logic patterns. it fulfills rule-3. since the conclusion is negative too. we will deal with this last kind of fallacy. which obscure the argument. in Homer) has built the Trojan Horse. take advantage of social relationships between people (argument from authority). All Greeks are wise. Modern translators render the word Danaan as Greek. because it has more than three terms: Nothing is better than the food at Maxim‘s. In this section. A fallacy may arise by accident or design. which fulfills the law of the distributed middle. ―Coward‖ is distributed in the conclusion. it may exploit deep emotions in the listener or interlocutor (appeal to emotion). Virgil wrote: Timeo Danaos et dona ferentes (I fear the Greeks even when they bring gifts). Here is one example of fallacy that breaks the first rule of distribution. However. Detecting a fallacy. (SoP) Many people think that designing fallacies is much funnier than constructing valid syllogism. Then a sandwich from McDonald‘s is better than food at Maxim‘s. this kind of syllogism obeys rule-4. we will not study fallacies for the fun of it. A fallacy is a misconception resulting from incorrect argumentation.6 Distribution 29 Danaan (whose name was Ulysses. which fulfills the law of the distributed middle. The other rules do not apply to this kind of syllogism. in Virgil. and in the first premise too.2. No Spartan is coward. is useful for anyone who refuses to be mislead. . therefore. A sandwich from McDonald‘s is better than nothing. (SiM) Some men are wise. (SiM) Some Greeks are not coward.

because it does not appear in the conclusion. Therefore. A fallacy that breaks the second rule ( which states that the middle term must be distributed at least once) is much harder to detect and less humorous. The second premise is particular affirmative.30 Forms The above syllogism has four terms because nothing has one meaning in the first premise (where it means that no food exists) and another meaning in the second premise (where it means to go without eating). Then none of its terms are distributed. it is not distributed. The middle term is carnivores. In the first premise. and some carnivores are fierce. then all bears are fierce. which is not valid according to the first rule. Since all bears are carnivores. Since the middle term is not distributed in either of the two premises. . The two meanings of nothing. food at Maxim’s and sandwich at McDonald’s add up to four terms. the syllogism is not valid. the middle term is not the subject of the universal proposition: it is the predicate.

from the application menu. as shown on the figure below. that pops up whenever you choose the option File/New.Chapter 3 Mouse events In the first two chapters of this document. as shown on figure 2.1 Add code to MouseDownListener Double click on the query. you learned how to build an application with a form. This should open an Event list.3. Press the Events tab of the Properties-dialog.frm branch of the project tree in order to reopen the query form. 3. 31 .

Y. 2. to ProjTree/Taskwindow.awt. the program will plot a famous greeting expression.Graphics g) Of course. X. Build the program. There are programmers that do not think this is a good idea. _MenuTag) :-_Q= query::display(S). and replace the onMouseDown/4 procedure with the following code: clauses onMouseDown(S. vpi::drawText(W. "Hello. Point= pnt(X. whose name is plot0. 1. a very popular one. 4. Java is one of these languages. then execute it. World!"). Create a project. Build the application. _ShiftControlAlt.32 Mouse events Double click on the MouseDownListener event. one should do all paintings and drawings inside the following method: public abstract void doPaint(java. let us learn how to put all drawing activities inside the event handler onPaint/3. Anyway. and add the snippet: clauses onFileNew(S. Enable the task menu option File/New. In fact. Y). Add a new query form in a new query package. Choose the option File/New to create a new form. . even in Java. In Java. Whenever you click at any point within the form.2 onPaint You have used the event handler onMouseDown/4 to paint something on the form. 3. _Button) :-W= S:getVPIWindow(). 3.win/Menu/TaskMenu/id_file/id_file_new. Point. there are languages that make this approach very difficult. by the way. one can get around this restriction.

2 onPaint The next step is to add the following snippet to the MouseDownListener: class facts mousePoint:pnt := pnt(-1. invalidate(R). When does a painting become invalid? When the window is covered completely or partially by another window. Press the Event button of the Properties-dialog (see figures 3. You will learn at the appropriate time. and the idea of a global variable. This new approach requires you to understand a lot of new things.3. Y-8. clauses onMouseDown(_S. The rectangle is described by the coordinates of its upper left angle. . Y).1: PaintResponder if-then-else construction. X+60. Y+8) You have probably noticed that the event handler onMouseDown/4 invalidates a rectangular region around the mouse click.3. and 2. predicates onMouseDown : drawWindow::mouseDownListener. you will find the PaintResponder in the list of events that will appear on the Properties-dialog. R= rct(X-8. and its lower right angle. _ShiftControlAlt. Y-8. X+60. _Button) :-mousePoint := Point. page 19). For now. The event handler onPaint will be called whenever a rectangular region of the form becomes obsolete or invalid. From the Project Tree. The event handler onPaint will act on this invalid region by repainting it. where R is a rectangle. like the Figure 3.2 to the PaintRe-sponder. add the snippet of figure 3. click on the query. Point. do not worry about about them these things. To bring this into effect. or when you invalidate it using the predicate invalidade(R). Point= pnt(X. R= rct(X-8. Y+8). 33 Now you are ready to implement the event handler onPaint for query. -1).frm branch.1.

and 0 represents false. p ^q. Truth tables. then q is true as well. such as a left click. the formula p V q means p or q. if p is true then q is true. p A q is true only if both p and q are true.. i. Any member of the α-Set is a well formed formula. X>0 then mousePoint := pnt(-1. If p is a formula. in general. If p and q are formulæ.34 predicates onPaint : drawWindow::paintResponder. The α-Set contains atomic formulæ which are. GDIObject) :-if pnt(X.4 Notions of Logics: Boolean algebra Propositional Calculus is a formal system in which formulæ representing propositions can be formed by combining atomic propositions using logical connectives. p ->■ q means that p implies q. 2. p is true if p is false. Figure 3. and false otherwise. p = q means that p is equivalent to q: If p is true. _Rectangle. then p is a formula. pAq (logical conjunction). If 1 represents the constant true. 3. Finally. lowercase letters.e. Consider the well formed formula p A q. -1) else succeed() end if. The symbol represents the logical negation.2: Paint Responder 3. one often resorts to truth tables. Y)= mousePoint.p = qare also formulae. then p is also true. and if q is true. of logical . Semantically. and is true if either p or q is true. then p V q (logical disjunction). World!". 3. -1). In order to establish the truth value of a formula. Therefore. "Hello. A formula of the PC obeys the following grammar rules: 1. Let us learn about truth tables through examples. Mouse events clauses onPaint(_Source. the truth table of the negation(p). GDIObject:drawText(pnt(X. Y).3 Examples This chapter shows how to handle a mouse event.

5 Argument forms A conjunction(p 35 disjunction(p ∨ q) is given by p q 0 0 0 ∧ q).5 Argument forms Logical programmers often use a kind of argument called modus tollendo ponens. this simple and very useful argument form is written thus: p∨q h q where ⊢ represents the logical assertion. the formula p → q means that 1 0 0 1if p is true. . we are told that either p or q is true. 1 p 0 0 1 1 q 1 0 1 1 0 p 0 0 1 p 1 0 1 V q p→q 1 1 0 1 3. let us 1 verify this assertion. then we are told that p is not true. In logical operator notation. and of the logical V p 1 1 p∧q 0 0 0 1 p∨q 0 1 1 1 1 0 Informally. then q is also true A reasonable truth table that conveys 1 such a meaning is given below. so we infer that it has to be q that is true. p 0 0 q0 10 1 p→q 1 1 0 1 It is possible to prove that P ->■ Q is equivalent to the formula P V Q. Roughly speaking.3.

In fewer words. the first line of the argument says that q is true. the second line says that p is true. Therefore. q^p p You have learned that p ->■ q means if p then q. Let us consider a concrete example. happy(Man) <.. It is important because it drives Prolog‘s inference engine. i. if p is true.p means that q is implied by p.36 Mouse events A very important argument form is the modus ponens.hearsSocrates(Man) hearsSocrates(plato) h happy(plato) Another valid argument is called modus tollens: p ^ q \-p . then man or machine can infer that q is true.e. q <r. p implies q. or q if p.

Version Information. Build Options. 37 . File Templates. It has six forms.Chapter 4 Less Figures Before going ahead. to wit: General.1). you need to fill in only the General form. we shall learn a way to describe our projects without having to resort to figures. Directories. The notation A/B refers to one of its options.1. For instance. Do it mutatis mutandis.1 Task menu The task menu shown in figures 1. General Project Name: factorial Project Kind: (*) GUI application ( ) Console application ( ) DLL Base Directory: C:\vispro Sub-Directory: factorial When you find the instructional step. In most cases.1). since your computer may not have space available on drive C:. use the option Project/New of the task menu to create a new project (figure 1.4 is the main menu of VIP IDE. Create a new GUI project: factorial (section 1.1 and 1. you should enter the Project Settings dialog (by choosing the Project/New option of the VDE task menu) and fill in the General form as shown above. and Run Options. or you may want to put your programs in a directory different from C:\vispro. 4.

win.win(section 2.. it will open and present its contents.. If you click on an item with the right button of the mouse.win branch of the project tree to deploy the floating menu. if it is closed. Click on the TaskWindow folder to open it. which has the following options: Attributes Code Expert Open Delete Properties. 3. If I want you to go to the code expert and add a snippet to the TaskWindow. I would say: In CodeExpert.3) To carry out this instruction. .2 Project Tree The easiest way to navigate through files and resources is to click on the corresponding item of the Project Tree: If you left click on a folder. add code to TaskWindow/TaskWindow. Right click on the TaskWindow. go to the project tree and do the following: 1. as shown in the figure. a floating menu opens. choose the option Code Expert. Finally. 2.38 Less Figures 4.

together with the Properties-dialog. buttons and edit fields. In the case of forms. e. you will get a list of the | Title 19 events that corresponds to the selected X .3). you had the opportunity to work with two event handlers.1 Code Expert Like the Project Tree.AI Y ■40 50 component. click on the leaf again to reach the code. 8 Menu <unset> ^ insert code. In past chapters. HB^ . If you want the code expert to add a prototype on a leaf. More on that later. left-click on the appropriate branches of the tree. Then.4. you will get a menu of events to choose from. If you left click the branch of the form on the Project Tree. there is a shortcut to the Code Expert. If you select one of these components and press the Properties Events Events-button. choose the option Code Expert from the floating menu. the Code Expert also has a tree shape. Forms have components. To reach the Code Expert.2. you must right click on the item of the project tree to which you want to add code. the MouseDownListener (page 31) and the PaintResponder (page 33). there is a list box for V Form: query selecting these components. Width 240 To navigate through the Code Expert Height 120 tree and reach the point where you want to Font Tahonna. into the many files of your project. As its name reveals. or snippets. and another for Layout schemes (see figure 2. If you press the button Events on the Properties-dialog. Then. click on the leaf and press the button Add that will appear at the bottom of the dialog. a prototype of the form will pop up. the Code Expert is used to insert code.g. and two component boxes: one for Controls.2 Project Tree 39 4. On the top of the Properties Properties-dialog.

4. 2. and choosing the option File/New in Existing Package from the task menu (section 2. _MenuTag) :. Refer to figures 2. be sure that the package folder is selected before going to File/New in Existing Package.1). 2.6). and to sec. you could choose a name like canvasFolder.40 If one asks you: ―In CodeExpert.3. For instance. In the example below. _MenuTag) :.7. Add the requested code to the file TaskWindow. If you want to insert the item into an existing package. Always choose names that mean something.6. if it contains queries. choose File/New in New Package from the task menu. Example: • Create a new package on the root of the factorial-project (figure 4. by selecting the branch corresponding to the formcontainer-package in the Project Tree. Let the name of the package be formcontainer. if your package holds computer graphics.‖ here are the steps that you must follow: • Project tree — Open the folder TaskWindow of the project tree. one places the package containing the query form on the root of factorial.3) Less Figures clauses onFileNew(W. • Code Expert— Click on Menu. .win to open its menu and choose the option Code Expert (figure 2. 2.pro. to TaskWindow. right click on TaskWindow. a good name is formcontainer.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new. add (section 2. Be sure to place the new item into the desired folder. choose the option File/New in Existing Package.3 Create Project Item To add an item to the project tree you have two options: 1. and so on. In order to put the window inside a package. • Create a new form (query) inside the formcontainer-package.1). then on TaskMenu and finally on id_file._S= query::display(W). Select id_file_new and press the button Add to generate prototype code. Finally. click on id_file_new->onFileNew. clauses onFileNew(W.S= query::display(W). If you want to place the item inside a new package named after it.

1: Create a new package When you create a form.2).mnu. You can take the opportunity to resize the window and add an edit field (handle: edit_ctl) and a button (handle: factorial_ctl). It is also possible .4. Figure 4.5.2: A form with an edit field If you ―double-click‖ on ProjectTree/TaskMenu. as shown in the figure.3 Create Project Item Figure 4. the IDE shows the Form Window dialog (see figure 4. You may also need to enable the menu File/New option. You can also reach the Form Window dialog by left clicking on the form name in the project tree. as in section 2. you get a dialog like the one shown in figure 2. You can unfold the tree of this menu specification by clicking on its option branches. as already mentioned.2.

and add (section 2. as in figure 4. _MenuTag) :. Create a new form: formcontainer/query (section 4. Enable the TaskMenu File/New option.3). Enable File/New (section 2. S:show().2).win/Menu/TaskMenu/id_file->id_file_new->onFileNew.S= query::new(W).42 Less Figures to create a new menu entry.1).3): clauses onFileNew(W.1. The symbol & in the &File entry makes F a shortcut key. As you can see from the figure. Create a new GUI project: factorial (section 1. Build the application to insert the new classes into the project. to TaskWindow. To see what we can do with fewer figures and check whether we have a terse description of a VIP project. the new option is enabled from the beginning. Add a new package to the project tree: factorial/formcontainer. As shown in the figure below.2. Add an Edit Field (edit_ctl ) and a Button (factorial_ctl) to it. let us start a new project from scratch. . I have pressed the button (icon) labelled New Item and created the entry Drawing Tools by filling in the dialog.

that contain a prototype of the fn class. To make things somewhat easier. Then. However.4. I must say that it offers the easiest access to controls. build the application once more to guarantee that Visual Prolog inserts the fn-class into the project. etc. Select the option Class from the Project Item dialog. When you press the Create button. To do justice to Visual Prolog. This is true for Visual C. and click on the ClickResponder entry of the Event-list. press the Event-button. Be sure to untick the Create Interface box.cl. . then add the following snipet to the factorial_ctl button code: clauses onFactorialClick(_S) = button::defaultAction() :-fn::calculate(edit_ctl:getText()). VIP will display the files fn. 4. To see how to make good use of this convenience.frm by clicking on its branch in the project tree.pro and fn. It is our job to add functionality to these files by replacing the contents of listing on page 44 for them. Choose the button:factorial_ctl from the Properties-dialog list box. as compared to other languages.4 Create a new class: folder/name 43 4.4 Create a new class: folder/name To create a new class and put it inside the package formcontainer. open the query. Build and run the program. the IDE stores a handle to the edit field window in a fact variable. Clean. and fill in the class Name field with fn. select the folder formcontainer in the Project Tree and choose the option File/New in Existing Package from the IDE task menu. it is still tricky.5 Edit field contents It is quite tricky to retrieve the contents of an edit field. Delphi.

Let us see how Aristotle‘s propositions look like in the modern Predicate Calculus notation.7 Notions of Logics: Predicate calculus Propositional calculus does not have variables or quantifiers. clauses classInfo("forms/fn".6 Examples In this chapter. integer) procedure (i. fact(N. "1.fact(N-1. %File: fn. Later modern notation was introduced by Giuseppe Peano.!.N= toterm(X). calculate(X) :. calculate:(string) procedure. "\n").cl class fn predicates classInfo : core::classInfo. end class fn % File fn. This problem was fixed when Friedrich Ludwig Gottlob Frege revealed Predicate Calculus to mankind. fact(0. end implement fn Figure 4. However.pro implement fn open core class predicates fact:(integer.0"). All a is b Some a is b ->• b(X)) Ab(X)) . which implements the factorial function. You have also learned how to access the contents of the edit field.44 Less Figures 4. 1) :. fact(N. you have learned how to create a form with a button (factorial_ctl) and an edit field (edit_ctl).3: The fn class 4. F). N*F) :. Below is the fn-class. stdio::write(F. F).o). Frege‘s notation was hard do deal with.

For instance. Mathematicians say that 45 . that is a tuple of values.: sin(X) is a function. A function has a functor (the name of the function). it is not a function. Consequently. Another function is mod(X. If you want the sinus of π/3. It is possible that you may not know the mathematical definition of function. if you want to find the remainder of 13 divided by 2. 2) into your calculator (if it has this function. that gives the remainder of a division. the argument of max(5. if a calculation produces more than one value. you substitute constant values for the variables (arguments). Mathematicians insist that a function must produce only one value for a given argument. Then. E. For instance. and arguments. but you do have a feeling for functions.1416/3).Y) takes two arguments. 2) is the pair (5. In this case. Image is the set of calculation results. In the case of the sinus function. of course). the elements of the domain are the set of real numbers. Thus. 2). the function max(X.g. When you want to use a function. you can type sin(3. However.1 Functions I am sure you know what a function is. acquired by the use of calculators and computer programs or by attending one of those Pre-Algebra courses. Domain is the set of possible values for the argument. What about functions of many arguments? For example. and returns the greatest one. y4 can be 2 or -2. There is an important thing to remember. you can type mod(13. you can consider that it has only one argument. One could say that functions are maps between possible values for the argument and a value in the set of calculation results. Y). you can force it into the straightjacket of the function definition by saying that only values greater or equal to zero are part of the image. the square root of a number is not a function.Chapter 5 Horn Clauses 5.

many people. For instance. or. One could say that such a predicate acts like an adjective. falsum}. 7). or even by a student who is taking Pre-Algebra.txt"): true if file "bb. This is the case of the arithmetic operations. ~X is true if X is false. There are functions whose functor is placed between its arguments.3 Solutions Suppose that you have a predicate city(Name. pnt Position). false}. the relationship is the equality between X and Y. where one often writes 5 + 7 instead of +(5. In C. false otherwise X < Y is true if X less than Y . In the case of X = Y .46 Horn Clauses the domain of such a function is the Cartesian product R × R. if you do not like the Latin names used by logicians. false otherwise exists("bb. 5. Prolog is a computer language that was invented to fulfill such a need. Point) that gives the coordinates of a city on a map. The city/2 predicate has the domain: city:(string Name. It would be interesting to have a programming language with predicates stating attributes and relationships other than the few offered by calculators and main stream computer languages. you can always opt for the English equivalent: {true. false otherwise A predicate with more than one argument shows that there exists a relationship between its arguments.txt" exists. In all computer languages. 5.1. . there are predicates equivalent to this one. during their lifetime.2 Predicates Predicates are functions whose domain is the set {verum. and false otherwise. especially the third one. have felt a compelling need for the prediction of one of the predicates listed in figure 5. false otherwise A predicate with one argument tells of an attribute or feature of its argument. Here they are: X > Y is true if X greater than Y . There are a few predicates that are well known to any person who tried his hand at programming. More examples of one slot predicates: positive(X): true if X is positive. false otherwise X = Y is true if X equal to Y .

For instance rain(100.2. and 90% of relative humidity. However. 40)) → true city("Logan". when one is not sure about it. 90) returns true if it is likely to rain when your instruments show 100oF. 100)). If it is uppercase or starts with the underscore sign(_). Wh. Pressure.1: Interesting predicates . city("Salt Lake". 200)). Standard-Deviation. 120)). pressure. pnt(30. B. you are dealing with a variable. 200)) → false city("Provo". pnt(100. Rate. invest(Rate. pnt(30. Temperature. Risk) Given a return Rate. 200)) → true There is no question that you could find a use for such a predicate. a predicate that returns the coordinates of a city. Humidity) is true if it is likely to rain at a given temperature. would be even more useful. check its first letter. positive(X) is true if X is positive. and humidity. Here are some queries that could be posed to the city/2 predicate. rain(Temperature. Humidity. pnt(100. P) → P= pnt(30.3 Solutions 47 It can be implemented as a database of facts: city("Salt Lake". and acceptable Risk. Who. A. Y. 40) In this new kind of predicate. 40)). pnt(100. city("Logan". false otherwise. pnt(200. city("Yellowstone". Examples of variables: X. Figure 5. symbols that start with uppercase are called variables. This predicate checks whether the given position of a city is correct. Xs. Therefore. given the name. city("Provo".5. 1. this predicate returns true if you should choose an investment. 1. if you want to know whether a symbol is a variable. pnt(100. StandardDeviation.2 atmospheres. city("Salt Lake".

The form window must have a sufficient size to show our ―map‖. Enter the Project Settings dialog by choosing the option Project/New from the VDE task menu. Enable File/New. nor fail to keep pace with it. Window Edit. Resize the new form rectangle. 40). Sophocles said that your hand should not be faster than your mind. Leave a generous empty space in the center of the form. Fill in the dialog: Name: map Add the following buttons to the new form: Logan. to Menu/TaskMenu/id_file/id_file_new/onFileNew. General Project: mapDataBase Kind: GUI application Location: C:\vispro\mapDataBase\ Author: MICRO\User Copyright: Copyright Create Project Item: Form. . Select the root node of the Project Tree. and fill it in. P). Project Tree/TaskMenu. Provo. _MenuTag) :-X= map::new(S). X:show(). Therefore. select Build/Build to pre-compile the project. otherwise the system will indicate an error in the next step. In the Create Project Item dialog. Salt Lake. Add clauses onFileNew(S. let us implement the city/2 predicate. Project Settings. P) true. select the option Form.mnu. The answer is P= pnt(30. Select Build/Build to perform the final compilation of the project. Choose the option File/New in New Package from the task menu. Build/Build From the task menu.win/Code Expert. as P in the query city("Salt Lake".48 Horn Clauses When you use a variable. Project Tree/TaskWindow. you want to know what one must substitute for P in order to make the predicate city("Salt Lake".

Build the project in order to insert a prototype of the new class into the project tree. Whenever you click on a button.cl and draw. choose the option File/New. P= Parent:getVPIWindow(). In the new application. A new form will pop up.3 Solutions % File: draw. In the Properties-dialog. select the root of the Project Tree and choose the option File/New in New Package from the IDE task menu. Don‘t forget to change the names of the buttons to logan_ctl and provo_ctl. If you do not remember how to build and execute the program. and saltlake_ctl respectively. as explained in section 4. end class draw 49 Figure 5. drawThem:(vpiDomains::windowHandle.2 and 5.5. choose the logan_ctl button from the component list box.4. .2: mapDataBase/draw. draw::drawThem(P. the program draws the corresponding city. string) procedure. also change the city name "Logan" in "drawThem" to "Provo" or "Salt Lake". To call the drawThem predicate using the city-buttons. To create a new class.frm form. edit draw. if it is not already open. Then.1.cl Create class. vpiDomains predicates classInfo : core::classInfo. Repeat the operation for "Salt Lake" and "Provo".cl class draw open core. "Logan").pro as shown in figures 5. go to the project tree and open the map.3. Build the project and execute the program. take a look at section 1. Create a draw class. press the Event button and add the following snippet clauses onLoganClick(S) = button::defaultAction() :-Parent= S:getParent(). to the ClickResponder. The class name is draw and the Create Interface box is unticked.2.

Y2= Y1+20.pro 5. pnt(30. drawThem(_Win. X2= X1+20. 120)). color_red). pnt(100. city("Logan". the predicate city/2 is used to retrieve only one solution. Y1). 100)). class facts city:(string. Horn Clauses drawThem(Win. Name) :. 200)). pnt(100. 100)). P). _Name). vpiDomains. clauses classInfo(className. Y2)). In the example.3: mapDataBase/draw.pro implement draw open core. conn(pnt(30. pnt(200. you used predicates not only for checking whether a relationship is true or false.50 % File:draw. end implement draw Figure 5. city("Yellowstone". Y1.B= brush(pat_solid. However. 40). but also for attributing solutions to their variable. city("Provo". P= pnt(X1. 120). pnt(100. 120)). city("Salt Lake". classVersion = "". . vpi::drawEllipse(Win. pnt(100. pnt(200. classVersion). 40)). vpi constants className = "draw". there are situations that call for more than a single solution.4 Multi-solutions In the last section. X2. vpi::winSetBrush(Win. conn(pnt(100. !. city(Name. 80)). Let conn/2 be a predicate that establishes a connection between two cities. 40). conn(pnt(30. B). pnt). rct(X1.

and fill it in. Name: map Package: plotter. 40). as the example shows: conn(pnt(30. 40).4. 120)/Y=pnt(100. 200) X=pnt(30. a feature that it does not share with other languages.mnu. → → → Consider the query: conn(pnt(30. 40)/Y=pnt(200. 100)) 5. 100).120). Select the drawMap node of the project tree. 40)/Y=pnt(100. W= pnt(100. Project Tree/TaskMenu. Y). Project Name: drawMap UI Strategy: Object-oriented GUI (pfc/gui) Create Project Item: Package. . In the Create Project Item dialog. 120) X= pnt(100. Enable File/New. Choose the option File/New in New Package from the task menu.5.4 Multi-solutions 51 You can use it to retrieve all connections between cities. From the task menu. W)? The answer could be W= pnt(100. select Package and fill in the form: Name: plotter Parent Directory: Create Project Item: Form. 120) W=pnt(200. Enter the Project Settings dialog by choosing the option Project/New from the IDE task menu. Choose the option File/New in Existing Package from the task menu. select the option Form. choose Build/Build. and fill it in.1 A program that uses multi-solution predicates Let us create a program to demonstrate how nice the multi-solution feature of Prolog is.pack (plotter\) Include the form. 100) X=pnt(30. but it could also be W= pnt(200. W). Project Settings. In the Create Project Item dialog. → → conn(X. Select the plotter node of the project tree.

4. Create a draw class inside the package plotter. that appears in languages like C or Pascal: if ((X > 2) && (X < 4)) {. .F= map::new(S). draw::drawThem(W). Untick the box Create Interface. In C. as explained in section 4. X<4 The logical and is called a junctor.4. 5. F:show(). the predicates of a conjunction are separated by commas. whenever you press File/New. you should obtain a window with a map. Build the application. In Prolog. Add Horn Clauses clauses onFileNew(S. (X>2) && (X<4) is a conjunction. Put class code in files draw. the expression ―P1 and P2‖ is true if both P1 and P2 are true.pro.. _GDIObject) :-W= S:getVPIWindow(). _MenuTag) :. A sequence of predicates linked by logical and-s is called conjunction. If you build and run this program. such as the one in figure 5.win/Code Expert.} If P1 and P2 are predicates. the expression (X>2) && (X<4) becomes X>2. _Rectangle.frm Open the map. to Menu/TaskMenu/id_file/id_file_new/onFileNew Create class.cl and draw. as shown in figure 5.5.frm and add the following snippet to the PaintResponder: clauses onPaint(S. Then.52 Project Tree/TaskWindow..5 Logical junctors I guess that you have had contact with the logical and. ProjectTree/map.

5. means that you drawThem on Win if you draw connections on Win and drawCities on Win. drawCities(Win) A set of Horn clauses with the same head defines a predicate.. is an instance of Horn clause. the part that comes before the :sign is called the head. the head is drawThem(W). A Horn clause can also take the form H :.sign is the tail. For instance. 120)). that means if. drawCities(Win). Thus. the four city Horn clauses define the city/2 predicate.6 Implication 53 5. pnt(200. 200)). and the tail is connections(Win).connections(Win). city("Yellowstone". The part that comes after the :. in the listing below. T2.connections(Win). defines drawThem/1. 100)). . each pair containing the name of the city and its coordinates. pnt(30. where Ti and H are predicates.connections(Win).7 Horn Clauses A Horn clause can be a sole predicate. city("Provo". there are four one predicate Horn clauses. and drawThem(Win) :. In the example. drawCities(Win). The domain of these predicates is a set of pairs. 40)).6 Implication An implication is a junctor represented by the symbol :-. In the example. Therefore.. pnt(100. drawCities(Win).T1.5. One predicate Horn clauses are called facts. city("Salt Lake". In a Horn clause. city("Logan". drawThem(Win) :. T3. pnt(100. the facts state a relationship between a city and its coordinates. drawThem(Win) :. For instance.

pnt(100. 40)). clauses city("Salt Lake". drawText(W. N). Y1). conn(pnt(30. fail. Y1. 40) . P2). Y2= Y1+10. end implement draw Figure 5. conn(pnt(100. class predicates connections:( windowHandle). drawThem(Win) :. P= pnt(X1. drawEllipse(W. end class draw % File: draw.city(N. vpiDomains predicates drawThem:(windowHandle) procedure. city("Provo". fail. 100)). conn(pnt(30. drawCities(_Win).54 % File: draw. Horn Clauses drawCities(W) :. pnt(100. city("Yellowstone". pnt(100. P). drawCities(Win). 40). rct(X1. drawLine(Win.cl class draw open core. 100)). pnt Position).pro . connections(Win) :.pro implement draw open core. P2). X1. city("Logan".conn(P1. P1. X2.connections(Win). pnt). connections(_Win). X2= X1+10. conn:(pnt. pnt(200. vpi class facts city:(string Name.4: draw. 160)). Y2)). 120). 120)). vpiDomains. drawCities:(windowHandle). pnt(200. pnt(30. 120)). Y1.cl and draw. 160)). pnt(100.

pnt).8 Declarations 55 Figure 5. it will issue an error message and you can add a mode declaration.5: Utah cities 5. the predicate inputs data from its argument. it is declared as class predicate. The mode declaration states that the argument of drawThem/1 must be an input.5. drawCities:(windowHandle). Here is the type and flow (or mode) declaration of drawThem/1. Examples: class predicates connections:( windowHandle). If it fails to perform the inference. . pnt Position). predicates drawThem:(windowHandle) procedure (i). In this case. One predicate Horn clauses may be declared as facts. you do not need to provide mode declaration. For example: class facts city:(string Name. The compiler will infer the modes.. it is a constant. not a free variable.e. conn:(pnt. The type declaration says that the argument Win of drawThem(Win) is of type windowHandle. In general. i. If a predicate is supposed to be used only inside its class.8 Declarations The definition of a predicate is not complete without type/flow pattern declaration.

The arguments of conn/2 are a pair of pnt values. conn:(pnt. This kind of predicate always succeeds. fail. Consider the Horn clause: connections(Win) :. drawLine(Win. To use it in class draw. and accept the following declaration: class facts city:(string Name. or else. The type pnt is defined in class vpiDomains. and one of its solution fails to satisfy a predicate in a conjunction. The facts city/2 and connection/2 are nondeterm. A determ predicate can fail. and has many solutions. or succeed in many ways.conn(P1. I can spell out the class to which pnt belongs class facts conn:(vpiDomains::pnt. Prolog backtracks. connections(_Win). drawCities:(windowHandle) procedure (i). and has a single solution. and offers another solution in an effort to satisfy the conjunction. and could have been declared thus: class predicates connections:( windowHandle) procedure (i). A multi-predicate never fails. pnt) nondeterm. nondeterm. P2). you will see that facts can be asserted or retracted from the data base. I can open that class inside draw.4 are procedures. . A nondeterm predicate can fail. vpi Determinism declarations To declare that a predicate has a single solution. P2). vpi::Domains::pnt). or many solutions. or succeed with only one solution. one uses the following keywords: determ. The predicates connections/1 and drawCities/1 defined in figure 5. pnt Position) nondeterm. I have two options. vpiDomains.56 Horn Clauses Later on. P1. If a predicate has many solutions. multi. procedure. I have chosen the second option: open core.

fail. P2) provides two points that are used by the procedure drawLine(Win. and X2. P2) draws a line from P1 to P2 on the window Win. They require a handle1 to a window that will support figures and plots. P1. P2) to draw a straight line. In the draw class. the handle W is passed around. drawCities(Win). _Rectangle. Y2 are the coordinates of the lower right corner. P2). then it tries the second clause of connection/1. Another predicate that you are acquainted with is drawEllipse(W. _GDIObject) :-W= S:getVPIWindow(). it may be a good idea to use methods from the so called GDI Object. If you share the same opinion. as its name shows. Y2). you must learn drawing predicates in depth.5. drawings.conn(P1. Therefore. 5. X2. The ellipse is inscribed inside the rectangle rct(X1. and tries another solution. P1. where it is the first argument of drawLine/3: connections(Win) :. where X1. 5. Prolog tries to satisfy the predicate fail. Y2)) that draws an ellipse on the window W. 1 You do not need to know what a handle is for the time being. The predicate drawLine(Win. For instance. This is how you may obtain the handle: clauses onPaint(S. Then. etc. The example that follows shows how this works. Y1. which always succeeds. X2. P1 and P2 are points. P2). until it runs out of options. graphics. draw::drawThem(W). which always fails.9 Drawing predicates 57 The nondeterm fact conn(P1. such as pnt(10. rct(X1. P1.10 GDI Object In the last example. Prolog backtracks.connections(Win).9 Drawing predicates My nineteen-year-old son thinks that the only use for computer languages is games. in the clause drawThem(Win) :. 20). Y1. When this happens. it is passed to connections/1. drawLine(Win. As you know. . Y1 are the coordinates of the upper left corner. the drawing is performed from inside the onPaint event handler.

win/Code Expert. to Menu/TaskMenu/id_file/id_file_new/onFileNew Create class. _Rectangle. Create a form inside plotter: map. Build the application.6.frm. Horn Clauses Project Tree/TaskMenu. in order to include the map form into the project. Add clauses onFileNew(S. to the PaintResponder of the map.mnu. Create the following project: Project Name: drawMapObj UI Strategy: Object-oriented GUI (pfc/gui) Target type: Exe Base Directory: C:\vispro Create a package: plotter. _MenuTag) :-F= map::new(S). Enable File/New.58 Project Settings. Build the application. GDIObject) :-draw::drawThem(GDIObject). Add clauses onPaint(_S.‖ You will find the new version of class draw in figure 5. Create a draw class inside package plotter. F:show(). Project Tree/TaskWindow. . Remember to untick ―Create Interface.

conn(pnt(30. end class draw % File: draw. fail. end implement draw 59 Figure 5. pnt(100. Y2)). X2= X1+10. fail. 160)). Y2= Y1+10. conn:(pnt. Y1). pnt). pnt(100. connections(_W).connections(Win). 40)). 120).city(N. class predicates connections:( windowGDI). conn(pnt(100. city("Logan". N). drawCities(W) :. drawCities(Win). 120)). P). pnt(100. 120)). 40) . drawCities(_Win). pnt Position).conn(P1. X2. drawThem(Win) :.5. pnt(100. W:drawText(pnt(X1. W:drawLine(P1. Y1. clauses city("Salt Lake". city("Provo". W:drawEllipse(rct(X1.pro implement draw open core.6: Class draw . P2). P= pnt(X1. vpi class facts city:(string Name. 160)). Y1). drawCities:(windowGDI).10 GDI Object %File: draw. P2).cl class draw open core predicates drawThem:(windowGDI). connections(W) :. vpiDomains. pnt(30.

3. then H is also true. To finish our study of the Prolog connectives.. You have seen before that this statement is equivalent to H is true or the conjunction T1&T2&T3 . . and -> stands for if.12 Notions of Logics: Meaning of Horn clauses A Horn clause has the form H : -T1. the semicolon stands for or. .60 Horn Clauses 5. and the minus sign stands for the logical negation.. when one presses the appropriate button. Then. then.. This last interpretation sheds light on the meaning of the neck symbol. H : -T means: H is true. 5. drawMapObj is the GDI version of drawMap. is not true.11 Examples There are three examples in this chapter: 1. . drawMap draws a coarse road map of Utah. or not T. are true. where the semicolon stands for the connective or. let us remind you that the comma stands for and.T2. . mapDataBase draws the position of the three main cities of Utah. The meaning of this clause is If T1&T2&T3 . 2. ..T3 .

The exclamation mark is called cut. F1). In other words.1) Using Horn clauses. The cut prevents Prolog from trying the second clause for N = 0. if you pose the query fact(0. the system interrupts its search for new solutions. 6. However.Chapter 6 Console Applications Since people like graphic applications. let us see a few basic programming schemes without resorting to a graphic interface. F)? 61 . Mathematicians define factorial as: factorial(0) ->■ 1 factorial(n) ->• n x factorial( n . After finding the exclamation mark. we started with them. We will illustrate the use of cuts with an algorithm that is very popular among Prolog programmers. Thus. fact(N.1 Cut What should you do if you don‘t want the system to backtrack or try another clause after finding a solution? In this case. Let us assume that you want to write a predicate that finds the factorial of a number. you insert an exclamation mark at a given point in the tail of the Horn clause. N*F1) :.fact(N-1. these applications may add details that sway your attention from what really matters. !. 1) :.N<1. this definition becomes: fact(N.

pro as shown below.fact(N-1. Without the cut. and returns F = 1. stdio::nl. Choose the option Build/Build from the task menu to add a prototype of class facfun into the project tree. Write a number to the prompt.console::init(). Then. clauses classinfo("facfun". run():. as such. fact(N. and execute it using Run in Window. F). not Execute. N*F) :. follow this directive: Create a New Project. Edit facfun. it would try to use it and would go astray. %File: main. 1) :.0"). To implement the factorial function. The cut ensures that factorial is a function and. end implement main goal mainExe::run(main::run).62 Console Applications the program succeeds in using the first clause for N = 0. integer Res) procedure (i. use Run in Window. F). maps each value in the domain to one and only one value in the image set. "1. stdio::write(F). Build. Build the project again.o). . not GUI. fact(stdio::read(). Choose the option Project/New and fill the Project Settings dialog thus: General Project Name: facfun UI Strategy: console Pay attention to the fact that we will use the console strategy. NB: To test a console program.N<1. fact(N.pro implement main class predicates fact:(integer N. !. and you will get its factorial. it would assume that the second clause of the definition also provides a solution.

4. [F irst|Rest] and [P |Q] are More equivalent patterns.X2 X1 = 3.6 Xs=[2. 6. 5.3] X = 2.X2 = 5 X1 = 2.3] Head 3 "wo3" 4 3. X2|Xs] [X1. 7] ["ni3". a list is put between brackets. Xs Xs = [2. i. [A|B]. [X|L]. 2.3 Xs = [] [X|Xs] Does not match. X matches the head of the list and Xs matches the tail. X2|Xs] [X1. 5.3] X = 3. [] [X|Xs] As you can see.6.2 Lists 63 6. 2.6. In Prolog.2 Lists There is a book about Lisp that says: A list is a an ordered sequence of elements. Here is a pattern that only matches lists with at least two elements: Pattern [X1.4. 6. "ta1"] [] [5. X2|Xs] [X1. 2. 2.X2 = 7 Does not match.6. 7] Xs=[] [] . 5. 5.4 and Xs = [5. and is supposed to have a head and a tail: List Type integer [3. where ordered means that the order matters. Does not match.6.4 Xs = [5.e. the pattern [X|Xs] only matches lists with at least one element. 7] ["wo3". examples of matches for the pattern [X|Xs]: List X Xs Pattern [3.3] [X|Xs] [2. "ni3".6.4 Tail [4.6. you can use another pair of variables instead of X and Xs in the pattern [X|Xs]. 5. 2. 5.6. 7] [2.3] you will get X = 3.2.4. 2. [Head|T ail]. if you match [X|Xs] with the list [3.6.. For instance.3].3] [X|Xs] [5. X2|Xs] List [3.3] You can match a pattern of variables with a list. 7] [7] X1.4. 2. Thus.3] X = 5. "ta1"] string* integer* [4] real* [3. Of course.

As in the case of factorial. as before. real) procedure (i. clauses classInfo("avg". Execute using Run in Window. List= read(). hasdomain(rList. that inputs a list from the first argument. % Output the length. write(A). 0) :. len(List. o). The first thing that you have done is to create a list domain: domains rList= real*. % Read List from console. write(A). console domains rList= real*. end implement main goal mainExe::run(main::run).0+S) :. len(List. nl.len(Xs. . /* File: main. you define a predicate len/2. % Create a rList variable. len([_X|Xs].console::init(). len([].pro */ implement main open core. edit avg. 1. A).pro as shown below. and outputs its length to the second argument. Finally. General Project Name: avg UI Strategy: console Build the project to insert the avg class into the project tree.0").64 Console Applications Let avg be a small project that calculates the length of a list of real numbers. Let us examine the concepts behind this short program. run():. make sure that avg is a console application. class predicates len:(rList. % Find the length of List. "1.!. % Initialize the console. nl. Then. S).console::init(). List= read(). List). A). Then. you define a run() predicate to test your program: run():.

0"). clauses classInfo("avg".2 Lists 65 The domain declaration is handy if you are dealing with complex algebraic data types. List= read(). len([_X|Xs]. hasdomain(real_list. console class predicates len:(Element*. len([]. nl. /* File: main. len([].console::init(). len(L. This program has one minor drawback: One can use len/2 only for calculating the length of a list of reals. o). clauses classInfo("avg". nl.len(Xs. end implement main goal mainExe::run(main::run). write(A). A). However. . write(A). 1. len([_X|Xs].console::init(). This should be possible if one substitutes a type variable for real*. A). console class predicates len:(real*.!.!. 1. However. 0) :.0"). 0) :. it is necessary to devise a way of informing L= read() which will be the eventual type of the input list. L= read(). o). len(List. implement main /* in file main. L). it is not required for such a simple structure as a list of reals. and feed the information to len/2. run():.0+S) :. You will discover below how to use it. S).pro */ implement main open core. there is a predicate that creates a variable for any given type. Fortunately. before checking whether this scheme really works. S).0+S) :. "1. "1. end implement main goal mainExe::run(main::run).6. run():. It would be nice if len/2 could take any kind of list. real) procedure (i.len(Xs.pro */ open core. real) procedure (i. Below you will find the same program without the domain declaration.

the computer must roll back to the start of the computation.6. 0) :.3]) 3. 0+3.!. . A. S[5.4) :. add([2. matches sum([X|Xs]. 0. A.6.6.sum(Xs. X+A.4. S[5.add(Xs.3].3. with X=5.add(Xs.6) :. S+X) :.6.add(Xs. S[] + 2.3]) 2.sum([2. sum([X|Xs]. Here is a definition that uses an accumulator to add up the elements of a list: add([]. 2.0) yielding S[] = 0. in order to perform the addition S + X when it rolls back.6.pro. sum([3. 2.3]. S+X) :.3].3].6.3].3. matches sum([X|Xs]. 2. A. S). sum([].3]. with X=3. S+X) :. yielding sum([5.0+3.4+5. S) yielding add([2.3].4+5.3]. S+X) :. 2. S) :. S). S) :. 5. 2. add([5. X+A.4.3. S) matches add([X|Xs].3] + 5. 2.add(Xs. S) :. S). A). S).3) :.6.sum(Xs.6. sum([2. S). Xs=[5.2.4. 2. S[5. S) yielding add([ ]. 0+3.3].3] + 3.3]. 0. A.2. 5.3]) matches sum([X|Xs].6.4.sum(Xs. add([X|Xs]. Xs=[2.66 Console Applications The next step in our scheme of things is to insert sum/2 clauses to main. 1.6+2.6. yielding sum([2. Xs=[].sum([].3].3]. S[]) matches sum([].3]. S) matches add([X|Xs].6. S) 2. 0. What is worse. S).6.3]. A. S) :. sum([5. S[2. with X=2.4. 5. sum([]. S) 3.3]). S). The traditional way to prevent the roll back is to use accumulators.4. S) that matches add([].0+3.4. 2. 0+3. 1. 0. 2.6. Let us examine what happens if one calls sum([3. X+A.sum(Xs. After reaching the bottom of the list. X+A. yielding sum([3.3]. S[]) 4. A. S) matches add([X|Xs].0.sum([5. A) yielding S = 11.6.6. S) yielding add([5.3].6. it must store the values of every X that it finds on its way down. S[2. 2. 5.2. S[2. Let us see how the computer calculates this second version of list addition. add([3.4+5.

0. A). S). L. List= read(). end implement main goal mainExe::run(main::run). L.pro implement main open core. "1. 0. A) :-avg( Xs. and the other for the number of elements. 67 The above program goes through the list twice. S. A) :. run():. real. avg(List.add(Xs. A). %addXtothe sum acc % increments the length acc A). console class predicates avg:(real*. S) :. first to calculate the sum.console::init(). A. len([]. i.len(Xs.6. write(A). S. avg([X|Xs]. avg(Xs. L+1. Using two accumulators. avg([]. A/L) :. o). S). A. you can calculate the length and the sum of the list simultaneously.!. L).sum(Xs. S) :. %File: main. S/L).0+S) :. X+S.0. 1. S).2 Lists You could use add/3 to calculate the average value of a list of numbers. len(Xs. len([_X|Xs].0. nl. real) procedure (i. and second to calculate the length. . sum(Xs.0"). i.!. add([X|Xs]. real. The above listing shows a program to calculate the average value of a list of real numbers. X+A. add([]. 0. 0) :. clauses classInfo("avg".add(Xs. One makes use of two accumulators: one for the sum.

S). while the other has X*A. [Wadler & Bird] and [John Hughes] suggest that one should capture this kind of similarity in higher order functions. Reduction The scheme used to calculate the sum of the elements of a list is called reduction. 0) :. red([X|Xs]. 0. red([X|Xs]. S) :. %Recursive reduction class predicates sum:(real*.0. o). A) :.red(Xs. %Iterative reduction red([]. I thought it was obvious that I didn‘t invent these schemes. instead of performing an addition. Assuming that. S). S). sumation(Xs. S+X) :. S) :.68 Console Applications 6. S) :. An iterative program goes through the code again. real) procedure (i. product(Xs. sum([X|Xs]. S). as it reduces the dimension of the input. 0. except for a single detail: one of them has X+A in the second argument of the iterative call of the predicate red/3. and the sum is a zero-dimensional datum.!. and [Wadler & Bird]. There are two ways of performing a reduction: recursive and iterative. you want to perform a multiplication. A.red(Xs. X+A. road.!.!. X*A. you can write the following program: %Iterative reduction red([]. and again. clauses sum([]. The two pieces of code are identical. since a few persons wrote me asking questions about their origin.0. A. S). A. You can also imagine that it comes from ITER/ITINERIS= way. that means again. A. S) :.red(Xs. lists can be thought of as one-dimensional data. A) :. I added two entries to the reference list: [John Hughes].red(Xs. In fact. In this case. Before them. However. . The term iterative comes from the Latin word ITERUM.3 List schemes Here are a few important schemes of list programming.sum(Xs.

"\n"). I have declared the red/4 predicate that captures the structure of the reduction operation. B}. L). "=". L. B. "=". L= [1.3.1: Reduce in Prolog Consider foldr. S. stdio::write("Reverse of ". F.C= [X|Xs]}.0"). stdio::write("Sum of ".6.console::init(). the first argument of the function has type L. 0. B. and the list is [1. Pay special attention to the way of declaring an argument of type function{L. Xs). Y)= C :. L*) -> B. [John Backus] made the same proposition.C= P(X. foldr(P. You can think of it as a function that inserts a two place operation between the elements of a list. Xs)). B}. while the second has type B. that returns a value of type B. Y)= C :. implement main open core class predicates foldr:(function{L. Prod.4]. end implement main goal mainExe::run(main::run). clauses classInfo("main". R).3. foldr produces 1+2+3+4. foldr(P. The type of its first argument is a two place function. Prod= foldr({(X. L).C=red(P. Acc. "=". Acc). [X|Xs])= C :.C= X+Y}. In the program of figure 6. red:(function{L.3 List schemes 69 when he received the Turing award. When the operation is addition. run():. red(_. stdio::write("Prod of ". Figure 6. L).C= F. [X|Xs]) = C :. L. L.2. 1. B. red(P. foldr(_P. L*) -> B. P(X. [])= C :. Let us see that one can use this prestigious method of programming in Visual Prolog.4].2. B. Xs)= C :. B.1. . R= red({(X. F. "\n"). as defined in figure 6. []. Acc. [])= C :. "1. S= foldr({(X.1. B}.C= Acc.C= X*Y}. F.

in order to perform the dot product of two lists. clauses dotproduct([].Z= P(X. we can close each clasp of the zipper with the help of the same type of functions that we have used to perform a reduction step. In figure 6. that doctors and nurses need special training to deal with it. Ys. In the expression X*Y+R. my goal is to avoid subjects that present steep learning curves to beginners. The fourth argument contains the output of the operation. [Y|Ys]. _. zip(_P. [X|Xs]. After all. Otherwise. []. the examples in figures 6. People who want to explore the possibilities of higher-order Logics and functions may refer themselves to books like [Wadler & Bird]. []) :. []. However. As). The example shows a zipping scheme followed by a reduction step. []) :. o). 0) :. the same way we have captured the reducing scheme. In fact. Ys. I cannot provide an in-depth treatment. zip(P.!. or papers like [John Hughes].!. We can capture the zipping scheme in a higher-order predicate. real*.dotproduct(Xs. you can find a [not very efficient] definition of zip in Prolog. 0) :. [Z|As]) :.2.2 should be enough for showing how to write higher-order predicates in Visual Prolog. The first argument is a two-place function. dotproduct(_. If either input list becomes empty. real) procedure (i. zip(P. the third clause . X*Y+R) :. R). Unfortunately. [Y|Ys]. In listing 6. class predicates dotproduct:(real*. The device drives one crazy when it does not work. producing the empty list as output. Y).1 and 6. and is the cause of so many accidents with young boys. I added this listing because more than one person wrote me requesting for an in-depth treatment of this important topic.!. The predicate zip has four arguments. The definition of zip/4 is simple: zip(_P. but you can define others. i. one uses the multiplication to close one clasp of the zipper. _.70 Console Applications ZIP There is a device used for continuous clothing closure invented by the Canadian electrical engineer Gideon Sundback. dotproduct([X|Xs]. []. since this would go beyond the scope of this book. Xs. I provide two of such functions.!. the first or the second clause stops the recursion.2. The second and third arguments contain the lists to be zipped together. _.

real*. []. []) :. [Y|Ys]. i. X). Xs.zip(prod. _. prod(X. real) procedure (i. zip:(pp2.Z=X+Y. implement main open core domains pp2 = (real Argument1. zip(_P. and proceeds to the rest of the input lists. red(P. red(_P. Xs. i. real*. V2. class predicates sum:pp2. I believe that this should be enough for a starting point.!.Z= P(X.Z=X*Y. clauses classInfo("main". D). _.!. real) procedure (i.3 List schemes 71 clasps the heads of the two input lists. real Argument2) -> real ReturnType. real*.red(P. Y)= Z :.2. red(sum. "zip").4. Ys. Ans) :. Ys.2. dotprod( V1. A) :. V2= [2. zip(_P. A. real*. [X|Xs]. stdio::nl. run():. i. Y).3.6. i.2: Zip in Prolog . D) :. Ys. dotprod(Xs. o). zip(P. []) :. clauses sum(X.2]. Ans).!. A. red:(pp2. Xs. prod:pp2. real. Y)= Z :. []. A). o).2.2. P(X. [].console::init(). end implement main goal mainExe::run(main::run).5]. 0. i. As). dotprod:(real*. [Z|As]) :. zip(P. real*) procedure (i. Figure 6. [X|Xs]. Z). Z. stdio::write(X). V1= [1. o).

we could try to use the foldr function. In what follows. [])= C :. F. I will rely on [Wadler & Bird]‘s book. [’ ’|untok(tl(LC))]) %Eq 4 end if.C= F. etc. I knew at least two of these gifted minds. F. control and safety of nuclear reactors. avionics. Haskell. natural language processing. foldr(P. The most popular of them depends heavily on the use of a computer language with a mathematical background.g. There are many methods that one can use to design a correct algorithm. It is the starting point for people who want to work with compiler construction. biomedical engineering. class predicates foldr:(function{L. By the way.). Scheme. List_of_chars) %Eq 1 tokens(untok(Xss))= Xss %Eq 2 untok(LC) = C :if LC= [Xs] thenC=Xs %Eq 3 else C= append(hd(LC). [X|Xs])= C :. There are many ways to write a string tokenizer. Even John Backus admits that proving a program correct requires knowledge of heavy topics in mathematics and logic and is beyond the scope of most amateurs who work outside this specialized field.C= P(X. and data mining. like Prolog. Xs)). B. F. Proving a program correct is essencial in applications where an error could be catastrophic ( e. One of them is David [Gries]. Prolog has areas in which it excels and one of these areas is writing programs that one can prove to be correct. A tokenizer is a program that breaks a list of chars into words. who happened to be my professor at Cornell University. 1 . foldr(P. For instance. I do not accept research money if there is the slightest possibility that the result of my work could be used by the Army. clauses foldr(_P. etc. Nevertheless. We need to search for a function Wop with the following properties: tokens(List_of_chars)= foldr(Wop. B.4 Reasoning about programs I tried really hard not to include advanced topics in this book. there are bright logicians who can design real world applications whose total correctness is a theorem. It is a sad note that most of applications in these areas are written in C. A. OCAML. B}.72 Console Applications 6. military weaponry1. L*) -> B. Clean. On the other hand. by people who are not sure about what they are doing.

one gets the following equation from the first property of foldr and equation %Eq 1: tokens([])= foldr(Wop. I bet you can do it in a more elegant. foldr(Wop.4 Reasoning about programs 73 In order to discover the Wop function. tokens(Xs)) Let us try to discover a few more facts about the Wop function. Xss)= tokens(append([X|hd(Xss)]. [’ ’|untok tl(Xss)])) Wop(X. Equation %Eq 2 gives us the following equalities: Wop(X. Xss)= tokens([X|append(hd(Xss). the above equation becomes: tokens(untok([[]])))= F From equation %Eq 2. foldr(Wop. [’ ’|untok(tl(LC))])) Wop(’ ’. Xss)= Wop(X. and feeded . It is created on the fly. the definition of tokens(L) uses an interesting new feature of Visual Prolog: Anonymous functions. F. As you can see.Xss)= [[]|Xss] %Eq 5 Equation %Eq 5 gives Wop(X.6. tokens(untok Xss))= tokens([X|untok(Xss)]) Wop(’ ’. we know that untok([[]])= []. and less confusing way (after consulting [Wadler & Bird]. F. [])= F 2. [’ ’|untok tl(Xss)])) Wop(X. [])= F But from the definition of untok (%Eq 3). [X|Xs])= Wop(X. F. we shall make use of the following facts about foldr: 1. of course). we obtain the value of F. which is: tokens(untok([[]])))= F= [[]] tokens([])= [[]] tokens([X|Xs])= Wop(X. the Wop function has neither predicate declaration nor functor. Xss)= tokens(append([]. F. Xss) when X= ’ ‘. Xss)= tokens([’ ’|untok(Xss)]) Wop(’ ’. foldr(P. In any case. Xss)= tokens(untok([[]|Xss])) Wop(’’. Then. For X =‘ ‘. Xss)= tokens([X|untok([hd(Xss)|tl(Xss)])]) Wop(X. Xss)= [[X|hd(Xss)]|tl(Xss)] I certainly am not good at doing such a chore. Xs)) If List_of_chars= []. we have: Wop(X.

foldr(P. hd(Xs)= C :. F. Xs)).console::init(). you must place it between braces. "1.if [_|R]=Xs then C=R else C=[] end if.if [X|_] = Xs then C=X else C= [] end if. ’\n’]) then C= [[]|XSS] else if list::isMember(X. thy beauty is to me". XSS) = C :-if list::isMember(X. [X|Xs])= C :. F. string::createFromCharList). tokens(List_of_chars)= Words :-Wop= {(X. ToHelen= "Helen. L= string::toCharList(ToHelen). [])= C :. A good exercise would be deriving Wop for the case of punctuation marks.0"). Words= foldr( Wop . [’. ’. B. hd:(L**) -> L*. foldr(P. F. List_of_chars). implement main open core class predicates foldr:(function{L. [[]].[X]|tl(XSS)] else C= [[X|hd(XSS)]|tl(XSS)] end if end if}. end implement main goal mainExe::run(main::run).C= P(X. stdio::nl. In the definition of Wop. foldr(_P.’]) then C=[[]. tokens:(char*) -> char**. S= tokens(L).’. stdio::nl. B}. [’ ’. clauses classInfo("main".74 Console Applications to foldr. tl(Xs)= C :. L*) -> B. tl:(L**) -> L**. B. . stdio::write(Words). I added code to handle punctuation marks.C= F. Words= list::map(S. run():. In order to create a function when and where it is needed.

if you execute frontToken("break December".6. []). In this case. string class predicates tokenize:(string. stdio::write(R1). end implement main goal mainExe::run(main::run). UCase= toUpperCase(S). In the example below.console::init(). a call to hasdomain(real. run():. Ucase). . R1= string::concat("It is ". "bleak ". One often has to transform a string representation of a term into an operational representation. s/he can use the function toTerm. "December!"]. clauses classInfo("main". RR). in a process called lexical analysis. implement main open core. stdio::nl. R). tokenize(R. T. One uses it to break a string into tokens. L= ["it ". "was ".5 String operations You will find a few examples of string operations below. "the ". R) you will get T="break". You can find more operations using the help of Visual Prolog. S= concatList(L). and R=" December". stdio::write(Us). stdio::nl. !. string_list) procedure (i. "upper ". because it is a very useful predicate. "string_example").5 String operations 75 6. For instance. RR= string::concat("case: ". Sx= stdio::readLine() reads a string from the command line into Sx. tokenize(_. Us). IX) makes sure that toTerm will yield a real number. tokenize(S. Ts). "in ". Then toTerm transforms the string representation into a real number. T. o). [T|Ts]) :-frontToken(S. tokenize(R1. These examples should be enough to show you how to deal with such data structures. Try to understand how frontToken works.

Xs= [3. implement main clauses classInfo("main". to transform a term to its string representation. 5. end implement main goal mainExe::run(main::run). You have learned how to transform a string representation of a data type to a Prolog term. Unfortunately. run():. If you need the standard representation of a term.console::init(). Str= toString(Xs)..console::init(). Xs= toTerm(stdio::readLine()).e. 8]. run():. Now. 2. end implement main goal mainExe::run(main::run). Therefore. stdio::write(Xs). Xs). Str).console::init(). run():. IX= toTerm(Sx). then you can use the predicate toString. Sx= stdio::readLine(). end implement main goal mainExe::run(main::run). "toTerm_example"). hasdomain does not accept the star notation for list types. implement main clauses classInfo("main". stdio::write(IX^2). or use a pre-defined domain. hasdomain(real.4. stdio::nl. you must declare a list domain. hasdomain(core::integer_list. "toString_example"). as you can see below. stdio::nl. Console Applications This scheme works even for lists and other complex data structures. let us see how to do the inverse operation. Msg= string::concat("String representation: ". like core::integer_list. "hasdomain_example").76 implement main clauses classinfo("main". . i. stdio::write(Msg). IX).

In the above example. 18). The format "%10. Below. Str1= string::format("%8.5 String operations 77 If you want to format numbers and other simple terms nicely into a string. 18). "formatting"). end implement main goal mainExe::run(main::run). e formats real numbers in exponential notation (such as 1.234e+002). and the number must be represented with three digits of precision.0). 18. Str2= string::format("%d\n %10d\n". implement main clauses classInfo("main". run():.1e\n" specifies scientific notation for real numbers. you can use the string::format function. 456. 35678. unless another precision is specified. Str3= string::format("%-10d\n %010d\n".console::init(). you can see the output of the example. f formats real numbers in fixed-decimal notation (such as 123. The format "%-10d\n" specifies the representation of a left justified integer on a field of width 10.4).1e\n". 3.3f\n means that I want to represent a real number. the format "%8. the field empty positions must be filled in with zeroes. you will find a listing of the data types accepted by the format string. d — a signed decimal number.457 3. . The format "%010d\n" requires an integer right justified on a field of width 10. The minus sign assures left justification (right justification is the default).6. u — an unsigned integer.3f\n %10. 3. an example is given below.6e+004 456 18 18 0000000018 Next. Str3). The field width is 8. Str2. Note that when converting real values into a text representation they are truncated and rounded with 17 digits. and a carriage return.45678. g formats real numbers in the shortest of f and e format. stdio::write(Str1.

casePreserve(). adjustSide Side) -> string AdjustedString. adjustLeft : (string Src. adjustBehaviour. s — a string. charCount FieldSize) -> string AdjustedString. string Padding) -> string AdjustedString. charCount FieldSize. cutRear(). R — a database reference number. adjustSide. Console Applications Below you will find a listing of string predicates that you may find useful in the development of applications. charCount FieldSize. . adjust : (string Src. string Padding. caseInsensitive(). B — a Visual Prolog binary type. right(). adjust : (string Src. caseSensitivity = caseSensitive(). adjustLeft : (string Src. adjustSide = left(). adjustRight : (string Src. charCount FieldSize) -> string AdjustedString.78 x — a hexadecimal number. cutOpposite(). charCount FieldSize. c — a char. P — a procedure parameter. o — an octal number. adjustSide Side) -> string AdjustedString. and caseSensitivity can be considered as having the following definitions: domains adjustBehaviour = expand().

concat : (string First.i).5 String operations adjustRight : (string Src. run():. charCount FieldSize. end implement main goal mainExe::run(main::run).console::init(). createFromCharList : (core::char_list CharList) -> string String. charCount FieldSize. "*". 60.i). concatWithDelimiter : (core::string_list Source. 79 adjustRight : (string Src. stdio::write(Str). string Delimiter) -> string Output procedure (i. Str= string::adjust(FstLn. create : (charCount Length. "adjust_example"). string Padding) -> string AdjustedString. *****Rage -. sing the rage of Peleus’ son Achilles. sing the rage of Peleus’ son Achilles. adjustBehaviour Behaviour) -> string AdjustedString.i).Goddess.Goddess. FstLn= "Rage -. . string Last) -> string Output procedure (i. string Padding.6.". create : (charCount Length) -> string Output procedure (i). string Fill) -> string Output procedure (i. /********************************* Project Name: adjust_example UI Strategy: console ***********************************/ implement main clauses classInfo("main". string::right). concatList : (core::string_list Source) -> string Output procedure (i). stdio::nl.

80 /********************************* Project Name: stringops UI Strategy: console ***********************************/ implement main clauses classInfo("main". stdio::nl.console::init(). Console Applications run():. that cost the Achaeans countless losses ----------------equalIgnoreCase : (string First. frontToken : (string Source. string Remainder) determ (i. "doomed". frontChar : (string Source. stdio::write(Rule). SndLn= [ "murderous".o.o). string Last) determ (i. string Last) procedure (i. string Prefix. string Token. charCount Position. doomed.o). string Rest) determ (i. Rule= string::create(20. murderous.o. Str= string::concatWithDelimiter(SndLn. string First. getCharValue : (char Char) -> core::unsigned16 Value. ". hasDecimalDigits : (string Source) determ (i). char First. stdio::write(Str).i).o). string Second) determ (i. front : (string Source.i. hasAlpha : (string Source) determ (i).o. end implement main goal mainExe::run(main::run).i. "-"). . "stringops").o). "). hasPrefix : (string Source. getCharFromValue : (core::unsigned16 Value) -> char Char. stdio::nl. "that cost the Achaeans countless losses"].

i).o). isUpperCase : (string Source) determ (i).i.5 String operations hasSuffix : (string Source. charCount HowLong) -> string Output procedure (i. string Separators) -> string_list. /* Convert string characters to lowercase */ . string LookFor.i). string First. string Rest) determ (i. length : (string Source) -> charCount Length procedure (i). string Delimiter) -> core::string_list List procedure (i. search : (string Source. isLowerCase : (string Source) determ (i).6. string LookFor) -> charCount Position determ (i. string ReplaceWith.o).i).o. toLowerCase : (string Source) -> string Output procedure (i). caseSensitivity Case) -> charCount Position determ (i. string ReplaceWith) -> string Output. split : (string Input. caseSensitivity Case) -> string Output procedure replaceAll : (string Source. isWhiteSpace : (string Source) determ. replaceAll : (string Source.i. search : (string Source. string ReplaceWhat. split_delimiter : (string Source. string ReplaceWhat. charCount Position. string ReplaceWith. lastChar : (string Source. replace : (string Source.i). char Last) determ (i.i. caseSensitivity Case) -> string Output. 81 subString : (string Source. string Suffix. string ReplaceWhat.

*/ /********************************* Project Name: trim_example UI Strategy: console ***********************************/ implement main clauses classInfo("main". /* Removes both leading and trailing whitespaces from the string. stdio::nl. stdio::write(T). murderous. doomed . /* Removes groups of whitespaces from the Source line. T1= string::trimInner(T). */ trimFront : (string Source) -> string Output procedure (i). "trim_example"). doomed ". run():. /* Removes leading whitespaces from the string. */ trimInner : (string Source) -> string Output procedure (i). stdio::nl.82 Console Applications toUpperCase : (string Source) -> string Output procedure (i). /*Removes trailing whitespaces from the string. end implement main goal mainExe::run(main::run). T= string::trim(Str). */ trimRear : (string Source) -> string Output procedure (i). Str= " murderous. doomed murderous.console::init(). /* Convert string character to uppercase */ trim : (string Source) -> string Output procedure (i). stdio::write(T1).

Numerals. and no universal quantifier inside parentheses.. or negations of literals. .Functional symbols.b.) A . • If P and Q are formulae. A formula consisting of a sole literal is called an atomic formula. as a disjunction of conjunctions.. P is tr are both formulæ.. ..x..) A (L31 V L12 V L13 . • The symbol p( t 1. one can substitute π for X: sin(X) = 0 Clausal form Any sentence of the predicate can be rewritten into the clausal form.) where LtJ are literals. a term can be: . and t 1 < t2 are literals.x2.6 Notions of Logics: Grammar for Predicates Let us define informal grammar rules for the Predicate Calculus. We have already seen how to remove existential quantifiers from a formula. then t 1 = t2. . p/n is a n-place symbol distinct from all other symbols of the language.tn) is called literal... Let us examine the remaining necessary steps to obtain the clausal formula. any formula can be rewritten as VXVYVZ. symbols of the form f(x1. Therefore.( (L11 V L12 V L13 . and tt are terms. • If t 1 and t2 are terms. . and rose can be functional symbols. P V Q. with no existential quan-tifier(3). . One can remove all existential variables of a formula by substituting constants for them. which means that a. Besides this.. VX(P) (for any X.6 Notions of Logics: Grammar for Predicates 83 6. In a literal.. P A Q. if P is a formula. .. In the example.tn-1. and one can use them to create formulæ. then P. i. the variable X in the formula 3X(sin(X) = 0) is an existential variable. A functional symbol may have arity zero..t2. • A variable introduced by the symbol 3 is called an existential variable. and P = Q (for any X. and A A B is a conjunction. t 1 >t2.xn). P is true) and 3X(P) (there exists X. and characters can also be terms.) A (L21 V L12 V L13 ..e.6.e. that makes P true) are formulæ. t 1 > t2. i. t 1 < t2.. P ->■ Q. Since A V B i s a disjunction. strings. and X is a variable.

X)) 4.84 1. Remove implications and equivalences. whose method of removing existential variables was named after him. E. Distribute conjunctions using the following rewrite rules: (α A β) V γ (αAβ) (α V β) A (β V γ) αVβ . Thoraf Albert Skolem (1887-1963) is a Norwegian mathematician. use these results to make the following rewriting operations: (αVβ) (α Aβ) αAβ αVβ 3.X))) p(so) VX(man(X) -+ loves(w(X). Skolemization substitutes constants for existential variables. 3X(p(X)) VX(man(X) -+ 3W(loves(W. α ->■ β α=β Console Applications αvβ (α A β) V (α A β) 2. Use truth tables to prove that (α Vβ) = α Aβ and that (αAβ) = αVβ Then. g. Distribute negations.

tree= case(category. or broken? 85 ..e. integrity1. like position. and the silence node. A constructor has the shape of a function. etc. For example. Then. It is practically impossible to create a data structure to represent Wittgenstein‘s ideas on a computer. the state of a point can be given by its coordinates. in his Tratactus Logicus Philosophicus. Things and objects have attributes. string). tree). Here is a class whose sole use is to export the semantic domain of the Tratactus: class semantic open core domains category= art. end class semantic There is a novelty in this listing: The use of constructors of data structures. that data structure would certainly have three constructors: the world node. cop. 1 Is it whole. silence. if somehow devised by a linguistic genius. rel. i. that is the case. The first sentence of the Tratactus is: The world is all. The set of values that these attributes take is called a state. nom. the case node. thereof one must be silent. The last one is: Whereof one cannot speak. according to Euclid. However. expressed the opinion that the world is a state of things. color. it has a functor and arguments. predicates classInfo : core::classInfo.Chapter 7 Grammars The philosopher Wittgenstein. a point has no attribute other than position. world(tree.

o). For instance. o). string*. "Welt"). Thus. string*. ""). ["ist"|R1]. string*) nondeterm (o. i. copula:(tree. article(case(art. i. the parser has consumed part of the list. To understand this point. string*) nondeterm (o.86 Grammars For instance. the result of an act is a change of state. string*. R). string*) nondeterm (o.1 Parsing grammar Acting is to change the attributes of the objects. R). 7. noun:(tree. In the final state. you can write a more powerful class to parse the whole book. %File: german. . ""). Using it as a model. ["Welt"|R].0"). nounphr:(tree. phr:(tree. "ist"). Rest). we will create a German class to parse the first sentence of the Tratactus. noun(case(nom. ["die"|Rest]. string*. o). string*) nondeterm (o. "Fall"). string*. the world will undergo a change of state. o). article(case(art. T). i. o). R) :-nounphr(T. string*) nondeterm (o. semantic predicates classInfo : core::classInfo. "1. the constructor case/2 has two arguments. R). ["der"|Rest]. article:(tree. R1. i. end class german %File: german. ["Fall"|R]. a grammatical category and a string representing a token. because the Tratactus is very short. It is a cinch. noun(case(nom. copula(world(case(cop. Rest).pro implement german open core. if a predicate parses a list of words.cl class german open core. i. semantic clauses classInfo("german".

o). noun(T2. "Welt"]. "ist". with Rest=["Welt". 7. "ist". It could be said that the node is the meaning of the sentence. or compiler construction. ""). nounphr( case(nom.2 Generating grammar 87 nounphr( world(T1. S1). "alles"].7. we can feed ["die". 2 . End). "Welt". let us feed S1= ["Welt". "alles"). End) The above call will match the first clause of noun/3. S1). "ist". article(T1. End) :-nounphr(T1. On the other hand. phr(world(T1. copula(T2. End). "alles"]. The definition of noun works exactly like article. S1). The English parser inputs the meaning and produces an English translation. ["alles"|R]. ["Welt". T2). parsing a noun phrase like ["die". copula/3 and phr/3 behave like nounphr. "Welt". S. "alles"] to article/3. The nounphr predicate makes these two calls in succession. e. This call will match the first clause of article/3. End) :-article(T1. "ist". the English parse (given below) takes a node in order to generate a sentence. The German parser consumes a German sentence and outputs its meaning. end implement german If you pay attention to the declaration of article. The output will be T2=case(nom. and End=["ist".2 Generating grammar The German parse takes a sentence and outputs a node. Next. The output will be T1= case(art.. "ist". take a look at a book about natural language processing. R). "ist". "alles"] to noun/3. i. noun(T2. with R=["ist". Start. i. you will notice that its flow pattern is (o. "Welt"). whichever pleases you most. T2). "alles"]. S. "alles"]. Start. S1. ["die". "alles"]. An example is worth a thousand words. "alles"]. and S1= ["Welt". S1. it inputs a list of words and outputs a parse tree2 and the partially consumed input list. If you do not know these linguistic terms.

Each English production rule outputs a list of words. phr:(tree. noun/2 and nounphr are examples of production rules. article(case(art. list::append(Start. R1)) :-nounphr(T. string*) nondeterm (i. noun(T2. copula(T2. T2). noun(case(nom.pro implement english open core. T). R1).o). "ist"). S1)) :-nounphr(T1. article:(tree. article/2. S1)) :-nounphr(T1.N)) :-article(T1. In the english class.88 %File: english. T2). nounphr( case(nom. Keeping this in mind. "Fall"). phr(world(T1.o)(o. ["all"]). copula(T2. noun(case(nom. S1). semantic predicates classInfo : core::classInfo. A).o)(o.o). ["all"]). noun:(tree.o). S1). end class english Grammars % File: english.o). phr(world(T1. noun(case(nom. "1. copula(world(case(cop.0").o)(o. ["world"]). string*) nondeterm (i. "Welt"). "alles"). o).cl class english open core. string*) nondeterm (i. ["the"]). nounphr( world(T1. copula:(tree.o)(i. ["case"]). nounphr:(tree. end implement english Horn clauses that yield a phrase according to the grammar of a given language are called production rules. semantic clauses classInfo("english". take a look at the production rule for phr/2. list::append(Start. Start). . list::append(A. ""). "alles"). list::append(["is"]. string*) nondeterm (i. Start). N). string*) nondeterm (o. T2).

or trees. S1) to concatenate a noun phrase with a copula. if you do not want to see a lot of errors. For instance. let‘s take a look at what we mean by higher productivity and artificial intelligence. Higher productivity. and build the application for the last time. yielding a phrase. . Prolog. you can insert the code for the main class. Although there is a consensus that Prolog meets these goals better than any other language.3 Why Prolog? 89 The second argument of the head of phr uses list::append(Start. This means that you will find Prolog libraries for almost any AI algorithm.7. alongside with Lisp and Scheme. Parsing is another difficult subject that one cannot live without (by the way. Do not forget to untick the Create Interface box. data structures like lists and trees are needed everywhere.1. is very popular among people who work with Artificial Intelligence. To implement and test this program.3 Why Prolog? One of the goals of a high level computer language is to to increase the reasoning abilities of programmers. but are difficult to code and maintain in languages like C. Insert the classes german. The design of the application logic is also very unwieldy. The next step is to add the english class and rebuild the application. there are parts that require most of the programming effort. A productive programmer delivers more functionality in a shorter amount of time. parsing is what you have done in order to implement the small English grammar that you have learned in this chapter). there are several controversies surrounding these terms. Add the given code to the appropriate class files. Artificial Intelligence. Finally. Then implement the german class and build the application again. In a software project. there isn‘t anything easier than dealing with lists. or Java. if you want to test it from inside VIP IDE. use the option Build/Run in Window. create the tratactus console project. In Prolog. in order to achieve higher productivity and artificial intelligence. but I do not need to elaborate on this subject because Prolog has Logic even in its name. This important branch of science makes your programs highly adaptable to change and more user friendly. Therefore. start by introducing the semantic class and build the application. By the way. The testing program is given in figure 7. After compiling it. english and semantic into the project tree. 7.

5 Notions of Logics: Natural deduction Both [Gries] and [Dijkstra] propose that Logics can be used to build correct programs. write(T). _X). "Welt". Clean. one can use the Dijkstra/Gries system to program in a modern language.console::init(). since [Dijkstra]‘s method is based on Predicate Calculus. because the methods [Gries] and [Dijkstra] propose are based on Predicate Calculus. nl. "ist". because the languages (Pascal-like structured languages) used in their books are dated. one . Besides this. console. "tratactus"). Figure 7.90 Grammars 7. nl. semantic class predicates test:(). 7.4 Examples The example of this chapter (tratactus) shows how one could write a program that translates philosophical German into English. clauses classInfo("main". This may not be correct. test(). end implement main goal mainExe::run(main::run). Translation). /*********************************** Project Name: tratactus UI Strategy: console ************************************/ implement main open core. like Visual Prolog. test() :. english::phr(T.german::phr(T. or Mercury. ["die". "alles"]. test(). In fact. Many people say that these authors are dated. or to prove that a given program is correct. run():. that is unlikely to become dated.1: Die Welt ist alles. was der Fall ist. write(Translation). !.

like cuts. Temporal logic: Modal logic: A is true at time t. However. the given grammar for Propositional Calculus is informal. The steps of deduction are what constitutes a proof. • Prove that the introduction of control mechanisms does not change the semantic of the algorithm. In Logics. A is necessarily true or A is possibly true. Then the inference rules used to recognize a well formed formula of the Propositional Calculus can be written thus: A A prop A prop F B prop (71) A prop AF (7. there are formation rules for the appropriate calculus. and if-then-else structures. Epistemology says that a judgment is something that one can know. for instance. In a formal treatment. A V B prop .A = B prop In the Natural Deduction system. To prove that a program is correct. Natural Deduction is an approach to proof theory that tries to provide a more natural model for logical reasoning than the one proposed by Frege and Russel. with one rule of insertion and one rule of elimination for each . We have seen how to proffer a judgement of the kind A is a proposition. Something is evident if one can observe it. A ->■ B prop .7. evidence is not directly observable but rather deduced from basic judgments. and are represented by A F. [Gries] proposes that one specifies the program with Predicate Calculus. [Cohn] and [Yamaki] have devised a very simple procedure to do just this: Write the specification of your algorithm in clausal form. or Predicate Calculus. The grammar rules given on pages 34 and 83 provide inference rules for deciding whether a string of symbols is a valid formula of Propositional Calculus.2) A A B prop . grammar rules are called formation rules. global warming is evident because scientists have records that show it happening.5 Notions of Logics: Natural deduction 91 can apply it more easily to a Prolog dialect than to a Pascal dialect. and prove its correctness using a method known as Natural Deduction. A is false and A is a proposition. Many times. An object is evident if one in fact knows it. There are many kinds of judgements: Aristotelic judgement: A is true. In fact. • Transform the specification into a Prolog program by introducing control mechanisms.

.. and h Q as Q is a theorem.92 Grammars one of the logic connectives present in the calculus being worked with. 4 In the proof shown above. In an inference rule. one calls prosthesis the expressions above the line. Here are a few inference rules from the Natural Deduction system that can be used with Predicate Calculus sentences in the clausal form: A /I : E11AE22. disjunction (PVQ). Let‘s play a little with our new toy. En_1 V En E1VE2. p A (r V q) is true because of the A/I inference rule. . implication (P ->■ Q). you will not need the rules corresponding to the quantifiers. The turnstile symbol h is not a part of a well-formed formula. but a meta-symbol..En n and Insertion Ei Ei E1VE2.. 2.. One can see P h Q as meaning P entails Q. . in line 5.E1 E1^EE1A E1 E 21 /I : EE V /I : V E1AE2^E Modus Ponens not Insertion Modus Ponens /E : Since we intend to work with the clausal form. Prove t h a t p A q h p A ( r V q ) : pAqhpA(rVq) hpA(rV 1 premise 1 pAq A/E. For instance.E1^E. . and apodosis what comes below the line. and the lines on which it was used. 1 2 p A/E.En E . and existential quantification (3X(P)).E2^E and Elimination A E E1. conjunction (P A Q). universal quantification(VX(P)).. equivalence (P = Q). there are insertion and elimination rules for negation (P). 1 3 q 4 V/I. 3 A rVq 5 pA(rVq) A/I. each step always contains the inference rule.EE1AE2. and because of lines 2 and 4.E .E2\-E /E : or Insertion or Elimination /E : implication Insertion ->■ /I : h E.. If one is working with Predicate Calculus.

_MenuTag) :-X= canvas::new(S). and add clauses onFileNew(S.Chapter 8 Painting In this chapter. I would draw something on canvas. you will learn how to draw pictures using the onPaint event handler. the above predicate will be executed. After this step. • Enable the option File/New of the application task menu. • Create a project: Project Name: painting Object-oriented GUI (pfc/gui) • Create paintPack package attached to the root of the Project Tree. This window will be the child of the task window S. where you will draw things. to TaskWindow/Code Expert/Menu/TaskMenu/id_file/id_file_new. 93 . What will you do next? If I were you. if you compile and run the program.frm inside paintPack. Start by creating a project with a form. X:show(). The command X:show() sends a message to the object X to show the window. whenever you choose the File/New option of the application task menu. The command X= canvas::new(S) creates a new X object of class window. Build/Build the application. • Put canvas. to create an interesting background.

Let us understand what the method bkg(W) does. _Rectangle. Therefore. • Go to the Properties-dialog of the canvas.94 Painting 8. it sends a message to the object W. • Add the code below to dopaint. • Create a class dopaint inside paintPack.80). 0) is a point on (0. 100)]. it calls the event handler onPainting. P holds a list of points. they will be executed. asking it to draw a polygon whose vertices . and add the following code to the PaintResponder: onPaint(_Source.cl class dopaint open core predicates bkg:(windowGDI). If the canvas. % File dopaint. that draws things on the window pointed to by GDIObj.cl and dopaint. W:drawPolygon(P). whenever the window needs painting. if you add instructions to onPainting. GDIObj) :-dopaint::bkg(GDIObj).pro.pro implement dopaint open core. The class dopaint has a bkg(GDIObj) method. 0). pnt(150. As you can see. Untick Create Interface. pnt(10. it calls onPaint.frm is closed. pnt(0. press the Events-button. vpiDomains clauses bkg(W) :-P= [pnt(0.1 onPainting Whenever a window needs painting. end implement dopaint • Build/Build the application to add the class dopaint to the project. click on its branch in the Project Tree. that calls dopaint::bkg(GDIObj). As I said before. For instance.0). end class dopaint %File: dopaint.frm. Every point is defined by its coordinates. When bkg(W) calls W:drawPolygon(P).

100)].1 onPainting 95 are given by the list P. bkg(W) :. pat_Horz: Horizontal hatch. W:pictDraw(P. and clears a green rectangle inside it. Finally. pat_FDiag: 45-degree downward hatch. The red color is given by the integer 0x000000FF. color_Green). 8. green. 4. color Color). B. Let us improve method bkg(W). W:clear(R1. 90. brush = brush( patStyle PatStyle. 200). rop_SrcCopy).Brush= brush(pat_Solid. is a modification of bkg(W) that provides a red triangle: bkg(W) :. In hexadecimal. For instance. 140. 3. C. 10). 130). A brush is a two argument object. and blue palettes. you can get a lot of colors by combining red. F. green. W:setBrush(Brush). The last thing that you will learn in this chapter is how to add a bmp picture to your window. R1= rct( 60. E. Here is how to modify method bkg(W): bkg(W) :. 150. pat_Vert: Vertical hatch. 2. It draws a white triangle on the pane of canvas. D.bmp").0). color_Red represents the red color. Colors are represented by integers that specify the amount of red. and blue. W:drawEllipse(R). Compile the program. here is a version of bkg(W) that draws an ellipse. Let us represent the integers in hexadecimal basis. pnt(150. To make the triangle red. as you can guess.8.P= vpi::pictLoad("frogs. Representing colors by integers is fine. pnt(10. 6.80). 60. 9. pnt(10. 5. where 0x shows that we are dealing with the hexadecimal basis. As you probably know. P= [pnt(0. A. color_Red). There are also identifiers for patterns: • • • • Here pat_Solid: Solid brush. but you have the option of using identifiers. 1. numerals have fifteen digits: 0.R= rct(40. . W:drawPolygon(P). one must change the painter‘s brush. and check whether it will act exactly as said. 7.

removing the background of the small picture. The next step is to draw the eagle itself using rop_SrcInvert. pnt(10.96 Painting The first step is to load the picture from a file.pnt(50.cl class dopaint open core predicates bkg:(windowGDI). except for the definition of bkw(W). W:pictDraw(Mask. The next step is to draw the picture.pnt(50.rop_SrcInvert). * The program that put the eagle among the frogs is given below.bmp"). The paintEagle project is exactly alike painting.P= vpi::pictLoad("frogs. The first step is to draw a mask of the eagle using rop_SrcAnd. vpiDomains clauses bkg(W) :. The eagle must fit perfectly well onto its mask. The mask shows a black shadow of the eagle on a white back ground. Mask= vpi::pictLoad("a3Mask. W:pictDraw(P.bmp"). 50). end class dopaint %File: dopaint. of the examples. end implement dopaint . For instance. you may want to put an eagle among the frogs of the previous examples. rop_SrcCopy).pro implement dopaint open core. % File dopaint.bmp"). In the example. and is implemented in directory paintEagle.rop_SrcAnd). 10). the picture P is put at the point pnt(10. This is done by using the predicate pictLoad/1. One often needs to draw a small picture on top of another. W:pictDraw(Eagle. 50). Eagle= vpi::pictLoad("a3. 10).

Name: canvas New Package Parent Directory[ ] Leave the Parent Directory field blank.8. • A prototype of a canvas control will appear on the screen. and use it for painting. the canvas-control is the first one. as in the figure 8. After pressing the Create-button. you will obtain a prototype of the greetings-form.2 Custom Control 97 8. Choose File/New in New Package from the task menu. Project Name: customcontrol Object-oriented GUI (pfc/gui) • Choose the option File/New in New Package from the IDE task menu. Let the new form‘s name be greetings. However. select the Control tag from the left hand side pane. • Choose the key-symbol that appears on the Controls-dialog. . You can close it to avoid cluttering the IDE. Click on the pane of the greetings-form. it is a good idea to create a custom control. Build the application to include the new control. The name of the new custom control will be canvas. • Create a new project. Remove the Ok-button from the greetings-form.1. • Add a new form to the project tree. and replace a hi_ctl-button for it. Press the Create button.2 Custom Control We have been painting directly on the canvas of a form. and select the Form tag from the left hand side pane of the Create Project Item dialog. At the Create Project Item dialog. The system will show you a menu containing a list of custom controls.

to TaskWindow.98 Build the application.mnu → File/New choice. and a new form will appear. Y. Y= convert(integer. Choose the option File/New. Enable the TaskMenu. Add clauses onFileNew(S. _MenuTag) :-F= greetings::new(S). vpi::drawText(W.win/Code Expert/Menu/TaskMenu/id_file/id_file_new.1: A form with a custom control . math::random(100)). Whenever you click on the canvas control of the new form. Painting Go to the Properties-dialog of the hi_ctl-button. it will print warm greetings. Figure 8. Build and execute the application. F:show(). X . "Hello!"). math::random(100)). and add the following snippet to the ClickResponder: clauses onHiClick(_Source) = button::defaultAction :-W= custom_ctl:getVPIWindow(). Build the application again. X= convert(integer.

3 Notions of Logics: Resolution principle 99 8. for the divorce would mean losing her rich dowry. no man was inclined to divorce his wive. His defences and prosecutions are very interesting. You probably remember that angiosperms also have androecia (housing for males) and gynoecia (housing for females). proposed in 1963 by [Robinson]: PVQ.8. The other Greek custom was the dowry. and women lived in the gynoecium. she would take a handsome amount of money to the house of her husband. kill them. and two poor ones. Lysias defended a man who killed his wife‘s lover. However. He feigned a trip to his farm in the outskirts of the city. When Eratosthenes discovered that his wife was cheating him. or resident alien. he decided to kill her lover. nevertheless his family was very rich. and returned to his country to help restore the democracy. he did not have civil rights.3 Notions of Logics: Resolution principle The most important inference rule for Prolog programmers is the resolution principle. but returned on time to kill the . Lysias managed to flee. (a A b) V (a A c) = a A (b V c) A b) V (a A c) = a A (b V Let us take a concrete case of these laws. as Plato explains in the Republic. For instance. the rulers of country decided to take 8 rich metics. as such. and rob them. because this would entail returning the money to her family. we will need two syllogisms. that says (aVb)A(aVc)EaV(bAc) There is also a second distributive law. In another occasion. He was a metic. To understand his defence. Lysias and his brother Polemarchus were among those condemned to death. during the dictatorship of the thirty tyrants. Man and woman lived in different quarters: Man lived in the androecium. Therefore. that we are not going to use in the proof of Robinson‘s resolution principle. and to prosecute one of the tyrants that killed his brother. When the woman left her father‘s house. One of them is the first distributive law. he was the son of that Kephalos who entertains Socrates in Plato‘s Republic.PVR\-QVR To prove this principle. you need to know a few facts about the Greek society. Lysias was an Athenian lawyer that lived in the time of Socrates. the reason is that Carl von Linn´e named these parts of the vegetal physiology after the housing arrangements of the Ancient Greeks. In fact.

pVrhqVr VrhqV 1 pVqVr ∨/I premise 1 2 pVqVr ∨/I premise 2 3 (p V q V r) A (p \/q\/r) ∧/I. let us prove the resolution principle. 3 5 qVr Modus tollendo ponens . The prosecutor accepted the argument. or he was killed. using the first distributive law: He was on the altar. Since you know that he was killed. the prosecutor claimed that the ravenous husband killed the rival on the domestic altar. the jury would condemn him to death. to where he fled seeking the protection of Zeus. if he killed him on the bed. If Eratosthenes killed the man on the altar. Eratosthenes was acquitted. he was on the bed. or he was on the bed and he was killed. Then Lysias simplified it. 2 4 ( q V r ) V ( p p) first distributive law.100 Painting villain on the unfaithful woman‘s bed. Lysias‘s defense of his client was based on the following argument: He was on the altar or he was on the bed. 1. After this long digression. pVq. and he was on the altar. he would be acquitted of all charges. However.

1 Primitive data types Visual Prolog has a lot of primitive data types: integer : 3. 3. Standard Prolog does not check type until the faulty code is executed. By the way. not all language designers had the common sense to hardwire type checking into their compilers. 7. 9. Thus. C. they are stored differently. D. 3. 45. i. However. etc. I am sure that you are saying to yourself that this is the only reasonable thing to do. "John McKnight". This means that the compiler checks whether the data fed to a predicate or a procedure belong to the right type. For instance. 0x0000FA1B is an hexadecimal integer.6E-19. "Kalium". real : 3. 845.Chapter 9 Data types Most modern languages work with strongly typed data. A. I agree. p^q) work on integer. E.18E-18. "Natrium". etc.1416. symbol : "Na". The program fails when it is already in the computer of the final user. to these operations. For instance. and nothing else. F. 9. real or complex numbers. "Cornell University". string : "pencil".. x x y. etc. Symbols 101 . which has the following digits: 1. 8. a-b. a numeral expressed in basis 16. 65. and you try to divide a string by an integer. 2. B. However. 2. 1. 0x0000FA1B. the arithmetic operations (x + y. 6. 4. 34. If there is a logical mistake in your code. the compiler balks. "K".45. 5.e. You have seen that symbols look a lot like strings: Both are a sequence of UNICODE characters. the compiler makes sure that your program will feed numbers.

stdio::write("Na". run():. "unknown"). i. class predicates energy:(real. Therefore.102 Data types are kept in a look-up table and Prolog uses their addresses in the table to represent them internally. E2). classVersion). o). clauses classInfo(className. energy(4. real.E= -2. "alkaline metal") :. F). it will use less storage than a string. family:(symbol. 1. 1. family("Na".pro implement main open core constants className = "main". if a symbol occurs many times in your program. symbols. real) procedure (i. there is a very simple example of using real numbers. E) :. . Below. /******************************** Project Name: primtype1 UI Strategy: console *********************************/ % File main. and strings. classVersion = "primtype1". energy(2. DeltaE= E1-E2. E1). " is an ". F). clauses energy(N.console::init(). end implement main goal mainExe::run(main::run). stdio::nl. stdio::nl. string) procedure (i. family("Na". This example is taken from chemistry. stdio::write(DeltaE).!. o). family(_. Z. succeed().18E-19*Z*Z/(N*N).

only the Greeks could put forward a better author.3 Sets of numbers Mathematicians collect other things. he will willingly accept another drachma in his set.}. s/he will trade it for another item that s/he lacks in his/her collection. 1. After all. In few words. 4 . The high position of Paraguay in my list is solely due to the fact that Jos´e Asunci´on Flores was Paraguayan. Do you know what was his favorite subject? It was the Set Theory. there is an Argentinean that scholars consider to be the greatest writer that lived after the fall of Greek civilization. However.2 Sets 103 9.}. and slide rules. . 9. . 1. 0. but I can make an educated guess. -2. as he liked to call it. for those who do not know Jos´e . N is the set of natural integers. You know what is the best possible deal? It is to pay a fair price for Argentineans. and Paraguay. i. integers may have some strange name like Zahlen. besides coins. the two drachmas are not exactly equal. You may think that set theory is boring. It is possible that if your father has a collection of Greek coins. Please. no hard feelings. -1. after Greece. 2. If s/he has a repeated item. I mean. many people think that it is quite interesting.e. your country ranks fourth in my list of favorite countries. however. You certainly know that collections do not have repeated items. notwithstanding the opinion of the Chileans. and resell them at what they think is their worth.. For instance. one of them may be older than the other. 3.9. However. . 2. therefore you are supposed to learn a lot about sets of numbers. Z is the set of integers. 4 .3. Why is the set of integers represented by the letter Z? I do not know. Jorge Luiz Borges is the greatest writer who wrote in a language different from Greek. for instance. . You probably heard Chileans saying that Argentineans are somewhat conceited. The set theory was discovered by Georg Ferdinand Ludwig Philipp Cantor. France. if a guy or gall has a collection of stickers.2 Sets A set is a collection of things. or Der Mengenlehre. stamps. a Russian whose parents were Danish. s/he does not want to have two copies of the same sticker in his/her collection. 3. my Argentinian friends. . but who wrote his Mengenlehre in German! In this language. They collect numbers. . Here is how mathematicians write the elements of N: {0. Z = {. .

or else. The expression (x < 2) ∨ (x > 5) means x < 2 o r x > 5 . etc. If you want to say that x is a member of N on the condition that x> 10. Conjunction. {0.1. if he wants to state that -3 is not an element of N.104 Data types Asuncion Flores. he writes something like 3∈Z If he wants to say that something is not an element of a set. Disjunction. Eva Peron. Alberto Ginastera. In Mathematics. therefore x > 2 ∧ x < 5 means that x > 2 and x < 5. Dario Volonte. such that x is a member of N. . for instance. Luis Federico Leloir. When a mathematician wants to say that an element is a member of a set. youcanwrite{x||x∈N∧x>10}. Cesar Milstein. Double backslash. Veronica Dahl.. The weird notation {x 2 ||x ∈ N} represents the set of x2. Using the above notation. Che Guevara. 4. 25 . it is the fatherland of Bernardo Houssay. this expression means that a rational number is a fraction p such that p is a member of Z and q is also a member of N. you can define the set of rational numbers: Q = { p ||p∈Z∧q∈N∧q=0} In informal English. he writes: -3∈N Let us summarize the notation that Algebra teachers use.. Jose Cura.9. when they explain set theory to their students. and I am sure that you will put Paraguay in your map. Carolina Monard. Before I forget. submitted to the condition that q is not equal to 0.16. Adolfo Perez Esquivel. Jose Asuncion Flores lived in Buenos Aires.} Guard. Jorge Luiz Borges. Hector Panizza. Carlos Saavedra Lamas. But let us return to sets. Osvaldo Golijov. Juan Manuel Fangio. As for Argentina. Diego Maradona. listen to his song India. you can use a symbol ∧ to say and. Alberto Calderon.

stdio::nl. which he resigned in 1935 because he disapproved of Hitler‘s regime. "/". 5)].". Den. Another reason was that he invented the notation for set that we have been using. choose the option Project/New from the task menu. but you can use lists to represent sets. Den)= list::getMember_nd(Q) do stdio::write(Num. 4). Y) || X= std::fromTo(1. Build the project again. "zermelo"). Q= [tuple(X. stdio::nl. ") end foreach. and fill the Project Settings dialog thus: General Project Name: zermelo UI Strategy: console Pay attention that we are going to use the console strategy.pro as shown below. stdio::nl. You may wonder why I named the above program after the German mathematician Ernst Friedrich Ferdinand Zermelo. Y= std::fromTo(1. end implement main goal mainExe::run(main::run). 5)]. Y) || X= std::fromTo(1. not GUI. and execute it using Build/Run in Window. .9. Y= std::fromTo(1. Edit zermelo. One reason could be that he was appointed to an honorary chair at Freiburg im Breisgau in 1926. stdio::nl. stdio::write(Q). foreach tuple(Num.3 Sets of numbers 105 Visual Prolog does not have a notation for sets. Choose the option Build/Build from the task menu to put a prototype of class zermelo into the project tree. 4). For instance. run():-console::init() . Q= [tuple(X. implement main open core clauses classInfo("main".

Suppose that p is the result of measuring the side . Therefore. Ancient Greeks claimed that any pair of line segments is commensurable. and Y belongs to [1. . The next section is somewhat hard to digest. If the Greeks were right..5]} Data types In plain English. that produces an integer measure for the diagonal of the square. ") for each tuple (Num. Den. I will summarize the important results. feel free to do so. you can always find a meter.106 In Zermelo‘s notation.4 Irrational Numbers At Pythagora‘s time. Consider the square of figure 9.. so you won‘t miss anything worth the effort of understanding a whole page of nasty mathematics. possibly a very small one. The set of rational numbers is so named because its elements can be represented as a fraction like p q where p ∈ N and p ∈ N. In the section about Real Numbers. and another integer measure for the side. 4. 2. 9. 4] ∧Y {(X. The following example will help you understand the Greek theory of commensurable lengths at work. 3. 4].Y)\\X e AY G [1. Den. 5].. 2. . 3. "/". Den)= list::getMember_nd(Q) do stdio::write(Num.". Y ) such that X belongs to [1. such that the lengths of any two segments are given by integers.1. The snippet foreach tuple(Num. i. "/".e. Den) that is member of the list Q. if you want to skip it. this expression is written thus: Q= [1 .". Q is a list of pairs (X. I would be able to find a meter. ") end foreach tells the computer to write(Num.

9.1 shows that q is even.1: A thinking Greek The Greeks were a people of wise men and women. p and q cannot be integers in equation 9. 2 x = 2xn2 2×p2 = 4 xq2r.1) p2 + p2 = q2 ∴ 2p2 = q2 You can also choose the meter so that p and q have no common factors.. you get p = 10. you can substitute 2 × n for it in equation 9. But this is against our assumption that p and q are not both even. Therefore. and q = 9. q is even too. Thus let us assume that one has chosen a meter so that p and q are not simultaneously even. before doing anything useful. It was Hypasus of Metapontum. Figure 9. But if q2 is even. if both p and q were divisible by 2. E. (9.g. Hyppasus asked the Delphian priestess— the illiterate girl— what he should do to please Apollo. a Greek philosopher. By proving that the problem was impossible. Keeping with this tradition. This kind of number is called irrational. 2 × p2 = q2 = (2 × n)2 = 4 x n2 :.1.4 Irrational Numbers of the square. you could double the length of the meter.2 proves that p is even too. √ 2 ∈ Q.2) Equation 9. getting values no longer divisible by 2. if p = 20 and q = 18. . who proved this. i. You can check that the square of an odd number is always an odd number. Since q is even. one has that q2 is even. equation 9. and q is the result of measuring the diagonal. is not an element of Q.p2 = 2x (9. or else.1. which you can rewrite as p√ =2 q √ The number 2. and you double the length of the meter. Nevertheless they had the strange habit of consulting with an illiterate peasant girl at Delphi. But from equation 9. For instance.e.1. Hypasus discovered a type of number that can not be written as a fraction. that gives the ratio between the side and the diagonal of any square. The Pythagorean 2 107 theorem states that AC2 2 2 + CB2 = AB2. She told him to measure the side and the diagonal of the god‘s square altar using the same meter.

However. 3. However. etc. In this representation. "Hippasus". the fundamental colors become 0x00FF0000 (red).6 Mathematics I always thought it very hard to satisfy mathematicians. ’. after reading my text.7 Format The method format creates nice string representations of primitive data types for output. I hope that students of literature will find Borges‘ books easier to digest. By working knowledge. As a bonus. Here is a list of primitive types. A Visual Prolog real number belongs to the set real. a subset of R. In particular. integer — Integer numbers between -2147483648 and 2147483647.12". as shown below. There are other types besides integer. . "pen".5 Real Numbers The set of all numbers. irrational. and I have an appalling dificulty in keeping even a pretense of being formal. integer. Visual Prolog programmers say that x has type integer. etc.1416. since they are so picky. or making major contributions to number theory.’. and how type are related to Set Theory. 9. string — A quoted string of characters: "3. my definitions of the different numerical sets are not rigorous as most mathematicians would require. hence my Argentinian friends may forgive me for telling jokes about them. etc. or the set of real numbers. and 0x000000FF (blue). In Visual Prolog. ’3’. ’b’. Using string::format/n. For instance. although the set integer does not cover all integers. Z is called integer. 0x0000FF00 (green). ’ ‘. it is nice to represent colors using hexadecimal integers. and real. you will get them in the decimal basis. but enough of them to satisfy your needs. real — Reals must be written with a decimal point: 3.108 Data types 9. and rational is called R. I have no intention of writing for an AMS journal. I will be content if I am able to give non-mathematicians a working knowledge of the concepts involved. They also say that r has type real if r ∈ real. If x ∈ integer.4. 9. char — Characters between single quotes: ’A’. you will get a printout of the primitive colors in hexadecimal. if you try to print these numerals using stdio::write/n. I mean that I hope that my readers will be able to understand what a type is.

9.7 Format /******************************* Project Name: primtype2 UI Strategy: console ********************************/ % File main.pro implement main open core constants className = "main". classVersion = "primtype2". clauses classInfo(className, classVersion). class predicates color:(symbol, integer) procedure (i, o). clauses color("red", 0x00FF0000) :- !. color("blue", 0x000000FF) :- !. color("green", 0x0000FF00) :- !. color(_, 0x0). run():- console::init(), color("red", C), S= string::format("%x\n", C), stdio::write(S), stdio::nl, succeed(). end implement main goal mainExe::run(main::run).


The first argument of function format specifies how you want the printout. In the example, the argument is "%x\n": You want a hexadecimal representation of a number, followed by a carriage return (\n). The arguments that follow the first show the data that you want to print. Here are a few examples of formatting: S= S= S= S= string::format("Pi=%4.3f\n", 3.14159) string::format("%4.3e\n", 33578.3) string::format("Fac(%d)=%d", 5, 120) string::format("%s(%d)=%d", "f" 5, 120) S= 3.142 3.358e+004 S= "Fac(5)=120" S= "f(5)=120"


Data types

The format fields specification is %[-][0][width][.precision][type], where the hyphen (-) indicates that the field is to be left justified, right justification being the default; the zero before width pads the formatted string with zeros until the minimum width is reached; width specifies a minimum field size; precision specify the precision of a floating-point numeral; finally type can be f (fixed point numeral), e (scientific notation for reals), d (decimal integer), x (hexadecimal integer), o (octal). Strings are represented as "%s". You can add any message to the format specification; you can also add carriage returns ("\n").



You may need other data types besides the primitives provided by Visual Prolog. In this case, you need to specify the new data types that you will insert in your code. In previous chapters you have already learned how to declare domains; you also learned how to create complex data structures, like lists. Therefore, all we have to do in this section is to recall concepts already acquired, and to make a synthesis of what we have learned.



You have learned that a list is an ordered sequence of elements. You also know how to create list domains, and declare predicates on lists. For instance, here are a few list domains: domains reals= real*. % a list of reals integers= integer*. % a list of integers strings= string*. % a list of strings rr= reals*. % a list of lists of reals

Once you have a domain declaration, you can use it like any primitive type. In the case of list, domain declaration is not necessary, since one can use list types like real*, string* or integer* directly in the predicate declaration, as in the program of figure 9.2.



Predicate calculus, a branch of Logics, has a data type called functional symbol. A functional symbol has a name, or functor, followed by arguments.

9.8 domains
/******************************* Project Name: newdomains UI Strategy: console ********************************/ % File main.pro implement main open core class predicates sum:(real*, real) procedure (i, o). clauses classInfo("main", "newdomains"). sum([], 0) :- !. sum([X|Xs], X+S) :- sum(Xs, S). run():- console::init(), sum([1, 2, 3, 4, 5, 6], A), stdio::writef("The sum is %-4.0f", A). end implement main goal mainExe::run(main::run).


Figure 9.2: List declaration The arguments are written between parentheses, and separated from each other by commas. To make a long story short, they have exactly the same notation as functions. Here are a few examples of functional symbols: • author("Wellesley", "Barros", 1970) • book( author("Peter", "Novig", 1960), "Artificial Intelligence") • date("July", 15, 1875) • entry("Prolog", "A functional language") • index("Functors", 165) • sunday


Data types

The last example shows that a functional symbol can lack arguments. This said, let us see how to declare data types for a few functors. The example calculates the day of the week for any date between the years 2000 and 2099. It has the following domain declarations: DOMAINS Comments year= integer. year is synonym of integer. The use of synonyms makes things clearer. day= sun; mon;tue; wed; This domain has many functional symthu; fri; sat; err. bols without arguments. Each func tional symbol is separated from the next by semicolon, and represents a day of the week. month= jan;feb;mar;apr; Another domain (type) with more than may;jun;jul;aug;sep; one functional symbol. oct;nov;dec. month code= Here, one has a functional symbol with m(month, integer). two arguments. numberOfDays= Another type with two functional symnd(integer); bols; the first functional symbol has one february. argument; the second one has no argument at all. /******************************* Project Name: dayOfWeek UI Strategy: console ********************************/ % File: main.pro % This program calculates the day of the week % for the years between 2000 and 2099. implement main open core constants className = "main". classVersion = "dayOfWeek". domains year= integer. day= sun; mon;tue; wed; thu; fri; sat; err. month= jan;feb;mar;apr;may;jun;jul;aug;sep;oct;nov;dec. month_code= m(month, integer). numberOfDays= nd(integer); february.

9.8 domains


class predicates dayOfWeek:(integer, day) procedure (i, o). calculateDay:( string Month, integer Day_of_the_month, year Y, day D) procedure (i, i, i, o). class facts monthCode:(string, month_code, numberOfDays).

clauses classInfo(className, classVersion). monthCode("January", m(jan, 6), nd(31)). monthCode("February", m(feb, 2), february ). monthCode("March", m(mar, 2), nd(31)). monthCode("April", m(apr, 5), nd(30)). monthCode("May", m(may, 0), nd(31)). monthCode("June", m(jun, 3), nd(30)). monthCode("July", m(jul, 5), nd(31)). monthCode("August", m(aug, 1), nd(31)). monthCode("September", m(sep, 4), nd(30)). monthCode("October", m(oct, 6), nd(31)). monthCode("November", m(nov, 2), nd(30)). monthCode("December", m(dec, 4), nd(31)). dayOfWeek(0, dayOfWeek(1, dayOfWeek(2, dayOfWeek(3, dayOfWeek(4, dayOfWeek(5, dayOfWeek(6, dayOfWeek(_, sun) :mon) :tue) :wed) :thu) :fri) :sat) :err). !. !. !. !. !. !. !.

However. the designers of Prolog faced the fact that Horn clauses are not complete enough for most applications. into the Horn clauses. _). monthCode(Month. D).. 2005. where <. !. The form H <. their appeal is even greater for computer scientists. C). R). Year..T2. % place your own code here end implement main goal mainExe::run(main::run). _. stdio::write("Day of the week: ". S= Y+Y div 4+C+MD.. % Get functional symbol of the day calculateDay(_.+L11 A +L12 A +L13 .9 Notions of Logics: Horn clauses A Horn clause has at most one positive literal. % Get month code. MD. /* Day of the week as an integer between 0 (sunday) and 6 (saturday) */ dayOfWeek(R. R).. For mathematicians. stdio::nl. H3 <r.114 Data types calculateDay(Month.T3. . Horn clauses have interesting properties. is appealing because it resembles informal rules that people use to express knowledge: The rain is certain if swallows fly close to the ground. calculateDay("May". However. _. R= S mod 7.. % Last digits of Year. H2 <r.+L31 A +L12 A +L13 .. err).+L21 A +L12 A +L13 . and +Lij is the negation of the negative literals.T was given on page 34. 9.T1. This difficulty was solved with the introduction of control mechanisms. D) :Y= Year-2000. The proof that a clausal clause(page 83) HVT can indeed be put in the form H <.... 3. succeed(). From what you have seen. . like the cut... it is no wonder that the first trial to use Logic as programming language was focused on Horn clauses. m(_M.is the implication symbol. run():console::init()... because they can be put in the following form: H 1 <r.

115 . their discoveries. and the solutions are illuminating.console::init(). It is up to you to complete the red tape. Besides this. More important. proposed and solved by great programmers and computer scientists. I hope that it will see a new edition soon. their explorations. The whole thing is organized as a kind of FAQ. you must create a console project. where Helder Coelho works in Portugal. The problems are interesting. All programs in this chapter will be console applications. Coelho‘s book is a collection of short problems. since it shows the history of the creators of Logic Programming. but not as good as his first book. world!\n"). end implement main goal mainExe::run(main::run). For instance.Chapter 10 How to solve it in Prolog The title of this chapter is a homage to Helder Coelho. stdio::write("Hello. This book was printed by the Laboratorio Nacional de Engenharia Civil. "hello"). the book is also very amusing. I will only provide the listing of the main class implementation. clauses run():. that is good too. Coelho published Prolog by Example (see [Coelho/Cotta]). Later. if I give you the listing implement main open core clauses classInfo("main". the first author of the best book on Prolog ever written: [HowToSolveItWithProlog]. whose name is hello.

L= [2. "utilities"). . test(L). "b".console::init(). member(H. L). member(H. the program will print all elements of the list. As a result. T). S= ["a". test(L) :. and print all solutions of the nondeterm predicate member. The definition of test/1 uses the predicate fail to backtrack. run():. [H|_]). [_|T]) :.116 How to solve it in Prolog 10. fail or succeed(). test:(string*) procedure (i).5]. test:(integer*) procedure (i). "c"]. there is a definition of member/2 for string*. Logic program: implement main open core class predicates member:(integer. and another for integer*. test(S). The example shows that you can define a predicate with different domains. clauses classInfo("main". string*) nondeterm anyflow. end implement main goal mainExe::run(main::run).3. stdio::nl. integer*) nondeterm anyflow. For instance.4.member(H.member(H.1 Utilities Verbal statement: Search all members of a list L. member:(string. The same thing happens to test/1. stdio::write(H).

U). integer*. L. U). 4. U). length([]. 5]. o).memb(H. _L2. length([_|R]. T). tst(L1. U1. L1). isec(L1. !. L1= [3. 0) :. 6. U2. R= "no". LU= LS. L2. integer*) nondeterm anyFlow. I). L2. findsec([_|T]. memb(H. _. run():. write(Resp1. isec(L1. integer*. U2= [4. stdio class predicates isec:(integer*. L2. length(U. integer*) procedure (i.!.memb(H. Resp2). 6. integer*) nondeterm anyFlow. Resp1). [H1|T]) :. []). nl. LS). integer*. . L). R= "yes".console::init(). findsec(T. []). L. isec(_. integer) procedure (i. LU). end implement main goal mainExe::run(main::run). write(I). clauses classInfo("main". findsec([H|T]. o). "intersection"). i. findsec:(integer*. [H|U]) :. 5.H=H1.1 Utilities 117 Verbal statement: Check whether U is the intersection of lists L1 and L2.findsec(T. findsec(L1. U) :. integer*. L2. U). [H|U]) :. findsec(_L1. L2. L2. string) procedure(i. isec(L1. U. L2. nl.length(R. i. memb(H. L2. memb:(integer. 5]. L. implement main open core. U1= [4. tst:(integer*. length(S. S). Resp2). tst(L1. L). length:(integer*. tst(L1.10. i. R) :-findsec(L1. 3]. L+1) :. 6]. L2). ". ". o). memb(H. search the intersection of lists L1 and L2. !. !. L. L2= [4. !.

end implement main goal mainExe::run(main::run). test1(U) :. which perform two operations. test1/1 will find and print all ways of cutting the list ["a". test1(["a". "c". fail. "d"]). L2. clauses run():. stdio::nl. [4. " ++ ". concatenation. U). [H|U]) :. L2. " ++ ". L. If you run the program.app(L1. U). .app(T. app([]. stdio::write(L1. fail. 2. ": ". L. U). L. clauses classInfo("main". test2(L1. 3]. "b". i). "b". L). Both predicates use app/3. test2([1. U).118 How to solve it in Prolog Verbal Statement: Specify the relationship append/3 between three lists which holds if the last one is the result of appending the first two. test1(_). 5. test2/2 will concatenate two lists. 6]). test2(_. U). test1:(string*) procedure (i). stdio::write(L1. integer*) procedure (i. L2. implement main open core class predicates app:(Elem* L1. stdio::nl. "= ". Elem* L2. stdio::nl. "c". "append"). Elem* L3) nondeterm anyFlow.console::init(). test2:(integer*. and cutting down lists. "d"].app(L1. On the other hand. L2) :. L2. This problem is an all time favorite. _). app([H|T].

stdio::write("Reverse of". R) to Prolog. rev1([H|T]. 2. 3. it will succeed if it makes L=[1. R). [H|L1]. 4. L= [1. 2. run():. L.rev1(L.rev1(L. L) :. R) . R). L1. 3].!. "= ". L. end implement main goal mainExe::run(main::run). R) equal to the head of one of the Horn clauses that are in the program. rev(L. R). "reverse"). In the present case. Then the inference engine will try to make rev([1. /******************************* Project Name: reverse UI Strategy: console ********************************/ implement main open core 119 class predicates rev:(integer*. o). It is illuminating because it shows how to use accumulating parameters in a very efficient way. o). R) :. stdio::nl. integer*) procedure (i. R) :. 3]. rev1([]. Assume that you feed the goal rev([1. L) :. integer*) procedure (i. rev(L.rev1(T.console::init().2. integer*. rev1:(integer*. This program is useful and illuminating. clauses classInfo("main". [].1 Utilities Verbal Statement: Write a program that reverses a list. []. 5].10. L). 2.3] in the clause rev(L. i.

R).2. The product of unification is the tail of a Horn clause. R). • rev1([1.rev1(T.1]. L1=[2. one must prove the tail. []. because you must prove the tail.1]. .2.3]. For example. • rev1([3]. T=[] yielding rev1([].2.1]. you must prove that Y is father of Z.2.2. [1]. T=[3] yielding rev1([3].1]. that is. [ ]. L.2.2. [3.3].1]. L) unifies with rev1([].2. [3. []. R).! for L=[3. [].[H|L1].L)/ H=1. in order to prove the head of a Horn clause.L)/ H=3. 3]. If you want to prove that X is grandfather of Y.2.3]. L). R) unifies with rev(L.L) :. R) unifies with rev(L.1].3] yielding rev1([1.2. L).2. and one says that rev([1. L1=[].rev1(T. R) :.3] producing rev1(L.L) :.L1.L)/ H=2.L1.2. producing the result. L).rev1(T. L) unifies with rev1([H|T]. L) unifies with rev1([H|T].rev1([1. and Z is father of Y.[H|L1].L) :.3]. that is equal to rev1([1. L1=[1]. L) :. R) This process of making a goal equal to the head of a clause is called unification.3]. [].3].rev1(L. R). All this long discussion may be summarized thus • rev([1.rev1(L.3] producing rev1([2. R). []. for L=[1. R) unifies with rev1([H|T].[H|L1]. T=[2. L=[3.2. R) :. [].2.120 But if L=[1. in order to prove the head. since L=[1.3]. consider the following Horn clause in English notation: X is grandfather of Y if X is father of Z and Z is father of Y.1].2. • rev1([]. • rev1([2. [2. In fewer words. 3]. for L=[1.L1. R) :. this clause becomes How to solve it in Prolog rev([1.3].3]. [1]. [2.

H>P. S. split(5. ". that wanted a fast method for sorting lists and vectors. "c". S.10. !. stdio::write("Small=". i. if he was not lucky enough to put his hands on a Prolog compiler before you. 8. ["b". The S sublist contains all of L that are smaller of equal to P(ivot). []). stdio::write("Small=". "d". If you run this program. Big). for he was born before Laplace. end implement main goal mainExe::run(main::run).8] . B). that splits a list L in two sublists: S(mall) and B(ig). 5. split(P. run():. the computer will print Small=[3. S1. Small. stdio::nl. Le Marquis would discover the Celestial Mechanics before Newton. he implemented a split/4 algorithm. class predicates split:(E. B). split(P. ". B1). 7. split(P. "a". split(_. E*) procedure (i. Of course. The quick sort algorithm was invented by Tony Hoare. [H|B]) :. S1.console::init(). I suppose that you would write the quick sort algorithm before Van Emden.1 Utilities 121 Laplace used to say that Newton was not only the greatest scientist of all times and lands. [H|T]. clauses split(P. First of all. 2].2]. T.!. T. if he had the chance of doing so. o. This was a time when B+Trees did not exist. E*. The B sublist contains the elements that are larger than P. "f"].4. 4. Big= ". Big). stdio::nl. o). E*. [H|S]. "quicksort"). []. B) :. [H|T]. B1). Here is how Van Emden implemented the split/4: implement main open core clauses classInfo("main". []. Big=[7. Let us see how Van Emden explained his algorithm to his friend Coelho.5. Big= ". [3. but also a very lucky man. S. split("c". Small. and the only way to perform a fast search in a list of customers was to have it sorted.

integer_list. all we need is a vanilla concatenation.8]. • Append Sorted_Small to [Pivot|Sorted_Big]. you can insert a cut after the first clause of app/3. U).122 How to solve it in Prolog which is what it should do. You will get the sorted list: [2. integer_list) procedure (i. Let us assume that you have the list [5. it will be more useful with a lists of strings. let us understand the idea behind the quicksort algorithm. app([H|T]. This algorithm needs a predicate that appends one list to another. Therefore.5.3.!. Of course.4. L. which we do not need.5. that algorithm is nondeterm. o). 3. 4.5. that you learned on page 118. Declare app as a procedure with two input arguments. app:( integer_list. and one output. we are going to use a list of integers. L. . you will get Sorted_Small= [2.7. • Take the first element of L= [5.2] and Big=[7. since we do not need the functionality of cutting a list in two. However.app(T. 5] • Sort Big and get Sorted_Big= [7. 5. app([]. 3. L) :. To test the algorithm. L. You can use app/3. i. and you want to sort it. [H|U]) :. 8. 7. 3.8]. 4. 4.8]. 8. and split it in Small=[3. 5. Now. • Sort Small using the same algorithm.4. 2] as pivot. 2]. 7.

app:(E*. clauses split(P. B).H>P. "c"]. []). QSmall). Small. sort(Small. sort(Strs.10. [P|QBig]. sort(Big. stdio::nl. "a". sort(L. E*) procedure (i. stdio::write("Qs= ". L. class predicates split:(E. []. L. T. app([]. split(P. 123 . 2]. U).!. L. split(P. S= ". L) :. S). [H|T].console::init(). sort([].app(T. L= [5. [H|B]) :. QBig). sort:(E*. [H|T]. stdio::write("L=". split(P. B).1 Utilities implement main open core clauses classInfo("main". 8. o). stdio::nl. end implement main goal mainExe::run(main::run). o). E*.!. S). 3.!. split(_. split(P. []. S. S) :. o. !. app([H|T]. 4. [H|U]) :. S. "quicksort"). B) :. 7. []). run():. Qs). Strs= ["b". Qs). E*) procedure (i. E*) procedure (i. S). 5. T. [H|S]. S. o). Big). i. i. E*. app(QSmall. sort([P|L]. L . L. E*. ".

fail. stdio::write("Year ". T). and 2000? implement main open core class predicates no_of_days_in:(integer. [H|_T]). no_of_days_in(_Y. integer_list) nondeterm (o. How many days have years 1975."). otherwise it is 365. member(H. end implement main goal mainExe::run(main::run). N. Verbal Statement: The number of days in a year is 366 each four years. 366) :. 1976.0= Y mod 400. " days. no_of_days_in(Y.member(X. 365). " has ". member:(integer. His student Philippe Roussel implemented an interpreter. member(H. clauses classInfo("numdays". 1976.member(H. stdio::nl. Warren was the man who implemented the first Prolog compiler. . The problem below was proposed by this very same Warren. run():. i). "1. a French linguist. N).124 How to solve it in Prolog Prolog was invented by Alain Colmerauer. test([1975. not(0= Y mod 100). test:(integer_list) procedure (i). [_|T]) :. no_of_days_in(Y. L). o). no_of_days_in(X. !. integer) procedure (i. 366) :.0"). It seems that Roussel‘s wife gave the name Prolog to the computer language. test(L) :. test(_L). !.0= Y mod 4. X. 2000]).console::init().

The four color problem is interesting for two reasons. Finally. nb(C.10. such that no two adjacent regions have the same color. In test(L). generateColor(B). generateColor(C). generate colors for the six regions of the map. two mathematicians at the University of Illinois. . Then. the predicate calls generateColor(A). It will be admissible if there is no two neighboring countries painted with the same color. nb(B. nb(A. F). nb(C. He was one of the first persons to use Prolog for Artificial Intelligence. that states: Every map can be colored with four colors so that adjacent countries are assigned different colors. There is a very famous theorem. E). nb(B. C). The problem is a classical generate and test program. F). 2. Therefore. C). generateColor(D). 1. He is co-author of the book How to Solve it in Prolog. The generate and test scheme was one of the first Artificial Intelligence techniques. F)]. generateColor(E). generateColor(F). E). the program backtracks to generateColor(X) in order to get a new set of colors. nb(C. nb(B. If predicate aMap(L) fails. test(L) builds a the map as a list of neighboring countries: L= [ nb(A. B). nb(A. This theorem was proved in 1976 by Kenneth Appel and Wolfgang Haken. the proposed colors are not correct. nb(A. nb(B. Verbal statement: Write a program for coloring any planar map with at most four colors. D). the predicate aMap(L) checks whether L is an admissible map. D). F).1 Utilities 125 Luis Moniz Pereira is a Portuguese who works with Artificial Intelligence.

test(L). nb(A. class predicates aMap:(map) nondeterm anyFlow.console::init(). F). nb(C. stdio::write(L).126 implement main open core domains colors= blue.yellow. aMap(Xs). generateColor(C). nb(B. generateColor(B). nb(A. C). R= red. run():. generateColor(D). !. generateColor(F). E). F). D). F). aMap(L).X= nb(C1.generateColor(A). nb(B. F)]. D). generateColor(E). How to solve it in Prolog aMap([]). test(L) :. R= green. nb(A. map= neighbors*. test:(map) procedure anyFlow.green.R= blue. nb(B. stdio::nl. C). aMap([X|Xs]) :. clauses classInfo("main". nb(C. L= [ nb(A. end implement main goal mainExe::run(main::run). generateColor(R) :. nb(C. C2). L= []. generateColor:(colors) multi (o). nb(B. not(C1 = C2).red. neighbors= nb(colors. "fourcolors"). . colors). B). E). R= yellow.

1]. A position of the game of Nim can be visualized as a set of heaps of matches.1]] [[1]. First. e. and the board becomes [ [1. you make a valid move.10.[1.1. 1].1. alternate making moves. we will represent each heap as a list of integers.g.1]] [[1]][[1]. if you run the first program (next page). if you take three matches from the third heap.1.1]] [[1].1]] Two players. In the example. In fact.1. the lines that follow shows the many possibilities of splitting a list of heaps.1].1.[1].[1. As soon as a player is unable to make a move.1. [1.1. you will implement and test a program that appends two lists. you and the computer. and that player has lost.[1]. the set of heaps will be a list of lists. [1.[1]. Then the first program seems to be working properly.[1].[1].[1]. you need to test both possibilities. A move consists of taking at least one match from exactly one heap.1] Therefore. [ [1. you will get [[1]. [1. Since you are going to use this program both to split and to concatenate lists.1]][] The first line is the result of concatenating two sets of heaps.1 Utilities 127 Verbal statement: Write a program for the game of Nim. [1.1.[1]] [][[1].1.[1. we will use a programming technique called incremental development of systems. [1]] where you have removed three matches from the third heap. 1].[1]][[1. .[1].1.1.[1]. To implement this project. the game is over.

Y).[1. Z).[1]].1]. If you test the program. L). end implement main goal mainExe::run(main::run). "nimgame").1.1]. stdio::write(L).1]] [[1. E*) nondeterm anyFlow.[1].[1]. append([[1]. hs= ms*. Y. [U|Z]) :. stdio::nl. it will print the following result: [[1. clauses classInfo("main".1]] [[1.1.1]] [[1]. !. Y.1].[1]. E*.1]] NB: the first clause of takesome/3 makes sure that the predicate will not insert an empty heap into the set of heaps. [[1].[1. clauses run():-console::ini t(). append([U|X].[1]. The next step is to write a predicate that takes at least one match from a heap.1]] [[1. After removing one or more matches from the heap.[1]]. it can take more than one match. How to solve it in Prolog class predicates append:(E*. takesome/3 inserts the modified heap into a set of heaps.1. append([].append(X.[1. of course.[1.128 implement main open core domains ms= integer*. Y. succeed(). .

Resp). takesome([_X. V= [[1. "nimgame"). Z). 1. clauses classInfo("main".1].console::init(). hs= ms*. end implement main goal mainExe::run(main::run).1]] [[1]. it will produce the following screen: Possible moves from [[1. class predicates append:(E*. you are ready to generate all possible moves from a given position. V. V.1]] [[1. Y.1.[1.1]. succeed().[1.1]] [[1. clauses run():.[1. 1.[1]] [[1. Y). Y. V). takesome:(ms.1]]: [[1. test().append(X. [U|Z]) :.1]] . V. test:() procedure. V. 129 Now. 1]. Y) :takesome(T.L= [1. 1.1. append([U|X].1]]. Y. E*) nondeterm anyFlow.1. takesome(L.1].1 Utilities implement main open core domains ms= integer*. takesome([_X].10. hs. [[X1|Y]|V]). E*. X1|Y]. stdio::nl. Y). hs) nondeterm anyFlow. If you run the test program. test() :. stdio::write(Resp). V. takesome([_X|T]. fail. append([].

takesome([_X]. 1. Y). V. "nimgame"). Z). move(X. R. 1]. stdio::write(Resp).takesome(T. V. 1]]. move:(hs. hs= ms*. hs) nondeterm anyFlow. R).130 How to solve it in Prolog implement main open core domains ms= integer*. Y) :. end implement main goal mainExe::run(main::run). append([]. [X1|V]. append(U. Y.console::init(). V). Y). Y. takesome([_X. Y) :. Y). X). stdio::nl. run():.append(X. X1|Y]. Y. E*) nondeterm anyFlow. stdio::write("Possible moves from ". append([U|X]. succeed().append(U. [[X1|Y]|V]). stdio::nl. fail. V. hs) nondeterm anyFlow. V. takesome(X1. class predicates append:(E*. takesome([_X|T]. takesome:(ms. ": "). Resp). clauses classInfo("main". E*. hs. L. [U|Z]) :. . V. L= [[1. move(L. [1.

append([U|X]. move(X. move:(hs. R). Y). succeed(). Y) :. takesome([_X|T]. hs) nondeterm (i. [U|Z]) :. S). takesome([_X. hs) nondeterm anyFlow. [[X1|Y]|V]). hs= ms*. [X1|V]. class predicates append:(E*. V). X1|Y]. R. If there is a winning strategy. takesome(X1. Y) :. S).console::init(). _)). Y. run():. 1]. o).move(X.append(U. V. Z). Y) :. winningMove(L. V. takesome([_X]. not(winningMove(Y.10.1 Utilities implement main open core domains ms= integer*. winningMove(X. _)). Y). clauses classInfo("main". Y). E*. Y. hs. takesome:(ms. [1. stdio::write("Winning move: ". end implement main goal mainExe::run(main::run). V. hs) nondeterm anyFlow. this amazing one line predicate will find it! You will find below an example of a game against the computer. append(U. Y.move(X. not(winningMove(Y. Y).takesome(T. stdio::nl. "nimgame"). V. V. append([]. L= [[1.append(X. the machine will take it. Y). if there is a chance of winning. Y) :. 1. X). E*) nondeterm anyFlow. As you can see. 1]]. 131 The heart of this program is the predicate winningMove(X. . winningMove:(hs. fail.

[1. you will create a class for the game itself.cl class nim open core domains ms= integer*. and the domains that you need to describe a game position. L= [[1. nim::game(L). predicates classInfo : core::classInfo. the main program is given below.console::init().[1. Then. nl.[1]] Your move: [[1]] My move: [] I win How to solve it in Prolog To implement the final program.132 [[1.1]] Your move: [[1]. write(L). % File: nim.pro implement main open core. ! .0"). game:(hs) determ (i). stdio clauses classInfo("main". 1]]. The class interface exports the method game/1. 1. "nimgame-1.1]. [1. succeed(). end class nim . run():. It is defined below. % File: main.1.1]] My move: [[1]. 1]. Let the name of this class be nim. end implement main goal mainExe::run(main::run). hs= ms*.

Y). hs.move(X. !. append([]. X1|Y]. _L2) :write("You win"). Y). append([U|X].append(X. write("I win"). hs. youwin(_L. iwin([]) :. !. takesome([_X].append(U. L2).write("Your move: "). Y. Y.pro implement nim open core. X).1 Utilities % File:nim. V. move(L1. youwin:(hs. stdio class predicates append:(hs. "1. hs) determ (i. write(L2). L= console::read(). V). takesome:(ms. nl. game(L1) :. V. V. end implement nim .10. youwin(L. youwin(L. Y). Y. clauses classInfo("nim". 133 move(X. move:(hs. hs) nondeterm anyFlow. iwin:(hs) determ (i). takesome([_X. winningMove:(hs. hs) nondeterm anyFlow. takesome(X1. nl. V. not(winningMove(Y. not(iwin(L2)). o). Z). [U|Z]) :. game(L2). L2) :. hs) nondeterm (i. V. _)). winningMove(X. R. R). Y) :. hs) nondeterm anyFlow. Y) :. fail.winningMove(L. Y) :takesome(T. L2).!. append(U. [[X1|Y]|V]). nl. Y). o). LTest).0"). write("My move: "). [X1|V]. L= LTest. takesome([_X|T].

In more complex games. that is called search tree. it tries to follow tree branches that leads to a winning position. In a simple game like Nim. where both have perfect knowledge of the game state. . the computer is able to find a path to sure victory. The algorithm can be applied to any game of two contenders. In the minmax strategy. or defeat. and Nim. Tic-Tac-Toe. this is not always possible. In this case. one must interrupt the search before being sure of winning the game.134 How to solve it in Prolog The strategy used in this very simple program is called minmax algorithm. It can also be used to control robots. there is a kind of filter based on the minmax algorithm that is similar to Kalman‘s. Go.1: Minmax tree a tree. On the other hand. the states of the game are organized in Figure 10. like chess. Checkers. Examples of such games: Chess. game strategists design functions that assign values to a position even when it is not a sure win. When it is the computer‘s turn. it generates states of minimum value for the opponent. in fact.

modified. assert(item(V. and increments the variable num. addItem(journal("AI in focus". When you have a new book. to the database. The predicate addItem/1 can be defined thus: class predicates addItem:(volume). Let us assume that you want to create a small database of publications. you want to add it to the database. The execution of addItem(journal("AI". "AldinePress")). An example will help you to understand why facts are necessary in Prolog. Facts can be asserted. item:(volume. The declaration class facts . creates the fact database bib.bib num:integer := 0. at runtime. "MIT Press")). and the variable is single. or retracted dynamically. clauses addItem(V) :-num := num+1. 135 . with a variable num and a predicate item/2. num)). integer) nondeterm. "AldinePress")) adds the clause item(journal("AI".Chapter 11 Facts A fact is a Horn clause without a tail. the predicate is nondeterm.

class predicates addItem:(volume).num := num+1. num)). stdio::nl.item(V. fail. author= n1(name). that will provide typing to the records of this small database. name). stdio::write(I. name). addItem(V) :. prtDataBase() :. . and how to save the fact database to a file. etal(name). integer) nondeterm. prtDataBase:(). title= string. "=". volume= journal(title. n2(name. % File main. "facttest"). publisher= string. author= n1(name). author). clauses classInfo("main". class facts . publisher). publisher= string. prtDataBase(). etal(name). author).pro implement main open core domains name= string. volume= journal(title. is defined as domains name= string.bib num:integer := 0. n2(name. book(title. publisher). V). title= string.136 Facts The domain volume. item:(volume. I). book(title. The program below shows how to define facts. assert(item(V.

you can use it in another program. stdio::nl. name). I). publisher= string.fac". item:(volume. book(title. class predicates prtDataBase:(). title= string. "factread"). addItem(book( "Databases in Prolog". end implement main goal mainExe::run(main::run). prtDataBase(). After creating the database and saving it to a file. publisher).137 clauses run():-console::i nit(). clauses classInfo("main". bib).bib num:integer := 0. etal(name). create a console project factread. integer) nondeterm.item(V. . prtDataBase(). volume= journal(title. addItem(journal("AI in focus". To test this possibility. prtDataBase() :. "=". class facts . "MIT Press")). n2(name. author). stdio::write(I. n1("Wellesley Barros"))). author= n1(name). file::save("bibliography. V). and add the following program to it: % File: main. fail.pro implement main open core domains name= string.

Both predicates have a version that does not require specifying whether the file is unicode.138 Facts clauses run():. boolean IsUnicodeFile) procedure (i. You will see that the program will read the database. and write it back.i). Nowadays. string Source. Prolog has two predicates to do this kind of job: readString:(string FileName. 11. the best approach to the problem is to read the whole file into a string. when computers did not have much memory. . Therefore. that you will learn in this section. even a personal computer memory capacity is on the order of gigabytes. do something to it. There are many other useful predicates in class file. string Source) procedure (i. and print it.fac created by facttest to factread\exe. You need to transfer the file bibliography. prtDataBase(). In the past. writeString:(string Filename. 11. writeString:( string Filename. and use the powerful string class to do the processing.o). run the program factread.1 Class file You have used class file to save facts to a file. end implement main goal mainExe::run(main::run).i). bib). boolean IsUnicodeFile) -> string String procedure (i.1 Reading and writing a string You often need to read a text file. readString:(string FileName) -> string String procedure (i). Then. it was necessary to read streams of characters.exe.fac".1. file::consult("bibliography.i.console::init().

Unicode). S_Upper.txt". succeed(). Visual Prolog represent these these handles to menu options by constants with meaningful names. clauses run():-console::init() .1: Reading a string from file Figure 11. Visual Prolog. file::writeString("upper. . but not as good for people. 11. stdio::write(Str). 139 Figure 11. In the example.11. % place your own code here end implement main goal mainExe::run(main::run). this representation is fine for the computer.txt".2 Constants %File: main. Unicode). Str= file::readString("test.1 shows an example of using these predicates. and write the uppercase version to another file. converts it to uppercase. I believe that you will be able to figure out all the functionality of class file from the help menu.pro implement main open core constants className = "main". S_Upper= string::toUpperCase(Str). Therefore.2 Constants In order to learn how to use constants. clauses classInfo(className. I will not linger on this topic. classVersion). and most other languages as well. represent menu options by integer numbers. Therefore. let us build a form with a task menu. who will analyze the program. one reads the string from a file. classVersion = "filetest".

the door of the year is mensis januarius. Enable the File/New option of the Taskmenu. Project Name: janua UI Strategy: Object-oriented GUI (pfc/gui) Facts By the way.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new. and add the snippet clauses onFileNew(S. to TaskWindow. let the form be named txtWin. onMenuItem(_Source. or janella. stdio::write("Hello"). From the Properties-dialog. window is a small door. janua is the Latin word for door. M) :-Item= resourceIdentifiers::id_help_contents. • Build the project.140 • Create a new project. X:show(). _M) . or january. _MenuTag) :-X= txtWin::new(S). add a TaskMenu to txtWin. . !. M= Item. Use the Events-tab of the Properties-dialog to introduce the following snippet into the MenuItemListener: clauses onMenuItem(_Source. • Create a New Form in New Package.

i as shown: % File:account. Create a new class: account.i interface account open core predicates ssN:(string SocialSecurity) procedure (o). in order to get a better understanding on how classes and objects work. untick the Create Interface box. For example. end interface account Do not Class account will produce a new account object whenever you call the method A= account::new() You can send messages to this object. • Modify the file account. deposit:(real). 141 . • Create a new console project. Project Name: classexample UI Strategy: console Build/Build the application.Chapter 12 Classes and Objects Let us create an exploratory console project. setSocialSecurity:(string SSN) procedure(i). you may set the SocialSecurity Number of the customer: A:setSocialSecurity("AA345").

For instance. assert(personalData( N. etc.pro implement account open core facts . stdio::write(SocialSecurity). stdio::nl. for passwords. ssN(SS) :.personalData(_. % File: account.0. end implement account • Modify run/0 in file main. • Modify account. An account needs other methods.funds := funds+Value. clauses classInfo("account".0").customer funds:real := 3.pro as shown below. you will need methods for deposits. _). "").142 Classes and Objects Afterwards.i. SS). personalData("". you may retrieve this very same Social Security Number. An interesting addition would be methods for cryptography. "1. A= account::new(). A:ssN(SocialSecurity). I will leave to your immagination the creation of these methods. deposit(Value) :.personalData(N. personalData:(string Name. setSocialSecurity(SSN) :. which is in file account. . besides the ssN/1 and setSocialSecurity/1. Both ssN/1 and setSocialSecurity/1 must be declared in the interface.pro. SSN)). in order to test the new class. run():. A:setSocialSecurity("AA345").console::init(). A:ssN(SocialSecurity). string SocialSecurity) single.

object facts. The Fortune chooses with her dice what will happen. and by these begin • For the totality of facts determines both what is the • case. The world is the totality of facts. • the German original. • • The object is simple.1 Object facts 143 12. However. • =Die Welt ist die Gesamtheit der Tatsachen. The world divides into facts. The Latin word casus means fall. From now on. the fact. Pay attention that Wittgenstein takes into consideration both facts that happen (what is the case). The philosopher Wittgenstein was very fond of facts. that can be used to hold their state. nicht der Dinge. what is falling in the world? The dice of Fortune are falling. • In Visual Prolog. the philosopher used the word Fall: Die Welt ist alles. The world is everything that is the case. and also those that are mere possibilities (all that is not the case). In the example. and variables are used to represent the state of an object.12. is the existence of atomic facts.Iwill spare The world is all the facts. was der Fall ist. which explains the translations. Did you remarked how Wittgenstein liked facts? Later on. What is the case.1 Object facts Objects have facts. The world is determined by the facts. you will see that he thought that facts must have states. An atomic fact is a combination of objects. and also all that is not the case. One can see that the idea of classes and objects is an old idea in Western Philosophy. The possibility of its occurrence in atomic facts is the • form of the object. but the point remains. 2. and state of things. the state objects . Let us take a look at the first few sentences of his Tractatus Logico-Philosophicus. Objects contain the possibility of all states of affairs. not of things. The same goes for states. In German. At least. 1. Do you remember that Julius Cesar said Alea jacta est? I know! He said it in Greek. There are a lot of possible events. and Suetonius had it translated to Latin. this is what the Romans believed.

A classical example is a stack that can deal with integers. Dr. like Clean and Haskell. and a variable: facts . 12. My knowledge of the subject does not go to such a depth. his/her Social Security Number. Do not untick the Create Interface box. end interface account About eight persons wrote me saying the name of Wittgensteing book should be ―Tratactus Logicus-Philosophicus‖.i interface account open core predicates ssN:(string SocialSecurity) procedure (o).0. % File:account. strings. . etc.2 Generic Interfaces In object oriented languages. the password. Interface predicates are used to access the facts that give the state of the object. the name of the account holder. and other data types. Mary Rose Shapiro went into a long discussion on the differences between Classical and Philosophical Latin. Project Name: generic_stack UI Strategy: console Build/Build the application.string SocialSecurity) single. • Create a new console project. setSocialSecurity:(string SSN) procedure(i). Create a new class: stack. when he translated the book into English. personalData:(string Name. his/her name. She claims that the name as I wrote it was a mistake commited by Ogden.144 Classes and Objects are individual accounts.customer funds:real := 3. This state is represented by a fact. deposit:(real). but I decided to keep the title as it is in every bookshelf. interfaces and classes can be parametrized with type parameters so that they can be used for processing different data types. The state of the account (our object) specifies the funds.

clauses push(Value) :.cl as shown below. pop : () -> @Elem Value determ. !. For example.retract(stack_fact(Value)). You can send messages to this object.i. you may push an integer into stack A: A:push(17). end implement stack %File: stack.pro and stack. As in the case of non-generic classes. %File: stack.i interface stack{@Elem} predicates push : (@Elem Value). clauses pop() = Value :.cl class stack{@Elem} : stack{@Elem} end class stack .asserta(stack_fact(Value)). end interface stack 145 Class stack will produce a new stack object whenever you call the method A= stack::new() It will infer the type of the object from the context.i as shown: %File: stack. Afterwards. Modify stack.12.2 Generic Interfaces Modify the file stack. you may pop the integer that is on the top of stack A: X= A:pop().pro implement stack{@Elem} facts stack_fact : (@Elem Value). which is in file stack. methods push/1 and pop/0 must be declared in the interface.

0"). str_stack(_S).console::init(). in order to test the new class. Classes and Objects run():. stdio::write(X). In the example. one uses the acronym LIFO (Last In. 12. stdio::write(S:pop(). "!"). called the top. "1.pro. Therefore. str_stack(SS). Q:push(8). the type is {string}. X= Q:pop(). !.3 Interfaces An interface does not need to have the same name as the class that uses it. the last value that was pushed into the stack will be popped out first. end implement main goal mainExe::run(main::run). Q = stack::new(). where elements can be added or taken off from only one end. implement main open core class predicates str_stack:(stack{string}). . The predicate str_stack:(stack{string}) shows how to declare a stack in order to pass it as argument to the clauses that will deploy it: one must inform the type of its elements. clauses classInfo("main".146 • Modify file main. A few points deserve comments. str_stack(S) :-S:push("Hello"). stdio::nl. SS = stack{string}::new(). S:push("World"). !. Q:push(17). First Out) to refer to the method of storing and retrieving data from a stack. run(). Method push(Value) uses asserta/1 to insert a Value into the top of the data base. In computer science.

Untick the Create Interface box. in the new definition.i.12. end interface stack As you can see. Therefore.cl class stackClass{@Elem} : stack{@Elem} end class stackClass Create a new interface inside the package stackClass: stack. the interface is not named after the class. choose the option Interface from the left hand side menu. in the Create Project Item dialog. clauses push(Value) :-asserta(stack_fact(Value)).3 Interfaces Create a new console project. However. The name of the new interface is stack.pro implement stackClass{@Elem} facts stack_fact : (@Elem Value). the new definition of stack works like the previous one. Modify the file stack. .pro and stackClass.i interface stack{@Elem} predicates push : (@Elem Value). Create a new class in a new package: stackClass.cl as shown below. clauses pop() = Value :-retract(stack_fact(Value)).i as shown: %File: stack. pop : () -> @Elem Value determ. end implement stackClass %File: stackClass. Modify stackClass. %File: stackClass. !. one could possibly use the same interface for more than one class definition. Open the option File/New in Existing Package. Project Name: stack_interface UI Strategy: console 147 Build/Build the application.

!. stdio::write(X). end implement main goal mainExe::run(main::run). clauses classInfo(className. classVersion). . S:push("World"). stdio::write(S:pop(). SS = stackClass{string}::new(). class predicates str_stack:(stack{string}). implement main open core constants className = "main". str_stack(S) :-S:push("Hello"). classVersion = "". stdio::nl.pro. Q = stackClass::new(). !. "!").1. 12. run():-console::init() . str_stack(SS). in order to give a further example of generic interface. succeed(). Q:push(8). in order to test the new class. str_stack(_S). Q:push(17).4 Generic Utilities Let us rewrite the member and app predicates given on section 10. X= Q:pop().148 Classes and Objects Modify file main. run().

Rest).i interface gmember{@Elem} open core domains list= @Elem*. search(H. [_|T]) :. %File: gmember. %File: gmember. Project Name: genmember UI Strategy: console 149 • Create a new class at the root of the project.4 Generic Utilities • Create a new console project. L. app([X|Xs]. i. @Elem*) nondeterm(i. end interface gmember • Modify the gmember.i). i).12. %File: gmember. o). T).app(Xs. L. [X|Rest]) :. • Modify the gmember. @Elem*) nondeterm (o. Select the genmember node of the project tree and choose the option File/New in New Package from the task menu. search:(@Elem Value. L. predicates search:(@Elem Value.search(H.!. Do not untick the Create Interface box. list) procedure (i. list.cl class gmember{@Elem} : gmember{@Elem} open core end class gmember • Implement the generic predicates search/2 and app/3 as shown below.cl prototype class declaration. app([].pro implement gmember{@Elem} open core clauses search(H.i prototype interface as shown below. The name of the new class is gmember. app:(list. L) :. [H|_] ). end implement gmember .

stdio::write(E). [1. Flowers=gmember::new(). stdio::nl. clauses run():-console::init(). [2.3. implement main open core constants className = "main". "tulip"]).150 Classes and Objects All that remains to be done is to write a main.pro implementation. fail.2. Ints= gmember::new(). stdio::write(N). stdio::write(N). Flowers:search(E. X:search(N. stdio::write(L). [4. clauses classInfo(className. X= gmember::new(). . "daisy". stdio::nl. 4]). Ints:search(N. 2.6].5. end implement main goal mainExe::run(main::run).0".4]). stdio::nl. classVersion = "gmember 1. ["rose". R:app([1.3]. L). stdio::nl. % place your own code here run() :. and test the generic predicates. classVersion).R= gmember::new().

and read Peano‘s book. a branch of Mathematics that gave origin to Prolog. he proposes to the world the modern notation for formal logics. Peano was another one. To this end.1). with the following project settings: General Project name: peano UI Strategy: Object-oriented GUI (pfc/gui) Target type: Exe • Create a New in New Package form: canvas (section 2. the language of science at the beginning of the last century. Peano wrote mostly in French. 151 . He also talks about other things. He wrote a small book whose title is Arithmetices Principia Novo Methodo Exposita From this. and it is at the root of the peano project. a very short book of 29 pages. The only thing he wrote in Latin was the Arithmetices Principia. Gauss was one of these few Mathematicians that could afford writing in Latin. Gauss wrote mainly in Latin. Not many people write things in Latin at this time and age. and recursion. There. 13. I strongly suggest that you learn Latin.Chapter 13 Giuseppe Peano Giuseppe Peano was one of the greatest mathematicians of all time. you can figure out how good he was. and in Italian. like number theory. his mother tongue. and find readers. create an Object-oriented GUI. let us implement turtle graphics in Prolog. The name of the form is canvas.1 Turtle graphics Before diving into Peano‘s contributions to science (and there are many). Of course.

X:show(). Build the application. Build and execute the project. choose the option File/New in Existing Package from the task window. and insert a class named turtle into it. • Create a package called turtleGraphics in the directory C:\vispro. Build the application.pro as in figure 13.3. The turtle is an object that moves on a window.win/CodeExpert/Menu/TaskMnu/id_file/id_file_new.2 Turtle states The class turtle implements a drawing turtle.1. • Add the following code to the PaintResponder of canvas. To accomplish this step.152 Giuseppe Peano • Create a class named curve: Go to the project window.pro. This way. _GDIObject) :-W= S:getVPIWindow().frm: clauses onPaint(S. choose the option File/New in New Package from the task menu. • Edit curve. Be sure to put the package turtleGraphics outside the project peano. Whenever you choose the option File/New from the application menu. and create the class. _Rectangle.cl and curve. a language created by Papert in an effort to forward the ideas of Jean Piaget. select the folder canvas. Build the application. curve::drawCurve(W). and choose the C:\vispro\ directory from the Set New Directory dialog. a window with a star will pop up on the screen. to TaskWindow. as shown in figures 13. Do not forget to check off the Create Interface box. Edit files turtle. when in Create project Item dialog. like in Logo.2 and 13. .mnu. 13. leaving a track behind itself. it will be easier to reuse it. Untick the Create Interface box.cl and turtle. click the Browse button for the Parent Directory. • Add the following code clauses onFileNew(S. _MenuTag) :-X= canvas::new(S). • Enable the File/New option of the application‘s TaskMenu.

star(Win. Facing). star(Win. P1= pnt(X1..13. 10.star(Win.!. vpiDomains. L). drawline(Win. N-1.cl and curve.turtle(P1. clauses turtle(pnt(200. 200). real. L). end class curve %File: curve. Y2). Facing)). integer) procedure (i. 3*pi/5. i. N. real) single. P1.pro implement curve open core. P2= pnt(X2.. _A. vpi. its position and the direction of its movement. Y1). 40). Y2= math::round(Y1+L*sin(Facing)). -pi/2).0"). assert(turtle(P2. Consider the predicate: forward(Win. A. clauses classInfo("plotter/curve".1: Files curve. drawCurve:(windowHandle). i.2 Turtle states % File: curve. X2= math::round( X1+ L*cos(Facing)). math 153 class predicates star:(windowHandle. 0. L) :. L) :. vpiDomains predicates classInfo : core::classInfo. turtle::forward(Win. _L) :.turtle::right(A)..cl class curve open core. i. star(_Win. A.pro A turtle has two state variables. . P2). These state variables are given by a fact: class facts turtle:(pnt. "1.e. drawCurve(Win) :. end implement curve Figure 13. integer. . i).

The first clause star(_Win. and go L pixels forward). L). _L) :. Cute. 13. turtle::forward(Win. Their implementations are straightforward.!.turtle::right(A).1 points. star(Win. L) :.1.1) (13. _A. If the turtle is at position P1=pnt(X1. L). Facing)) The predicate move/1 is similar to forward/2. . Predicates right/1 and left/1 turn the turtle to the right and to the left.1) under the light of Peano‘s postulate. says: You draw 0 points to a star if you do nothing. Finally. • Prove that it is true for 0. P2) (13. if it is true for N . but does not connect the new position of the turtle to the old one. A.154 Giuseppe Peano It implements the forward movement of the turtle. isn‘t it? In any case. information about the new position of the turtle is asserted into the database: assert(turtle(P2. let us examine the star/4 predicate(see figure 13. A. one can find its new position by projecting L on the X and Y axis: X2 = X1 +L×cos(F) Y2 = Y1 +L×sin(F) After getting the new position P2= pnt(X2. Y1). N. and it is written in English. • Prove that it is true for N. forward/2 uses drawline(Win.2) to connect point P1 to P2. The original runs towards ∞ and is in Latin. says: You draw N points to a star if you draw a point (turn A radians to the right. this version of the postulate runs towards 0.3 Recursion Peano‘s recursion postulate can be stated as follows: In order to prove that a predicate is true for any natural number. respectively. and moves a distance L in a direction that it is Facing. Of course. 0. and proceed to draw the other N . Y2). N-1. The second clause star(Win. P1.

In any case. The problem is that Latin is a difficult language. you could say that Peano brought two important contributions to Logic Programming. forward:(windowHandle. in this case. 13. Peano took care of this too: In his brand of Latin. he did not stop here.5 Latino Sine Flexione You have seen that Peano created the modern notation for Logic. He also came out with the idea of recursion. right:(real) procedure. vpiDomains predicates classInfo : core::classInfo. Prolog.4 Peano’s curve % File: turtle. then I decided to start with an easier example. was born of a project aimed not at producing a programming language but at processing natural languages. French (Colmerauer). which the mathematicians consider to be a very interesting property. move:(integer) procedure.cl 13. he eliminated all inflexions.1. to get Peano‘s curve. However.4 Peano‘s curve Peano designed a recursive curve that fills the space.pro given in figure 13. left:(real) procedure. Prolog was invented by Colmerauer for Natural Language Processing: The programming language.2: File turtle. Peano had an interesting proposal. integer) procedure.cl class turtle open core.4 for the file given in 13. end class turtle 155 Figure 13. why not use Latin for scientific communication? All you need to do is select Latin words that are common to the major European languages and you have a vocabulary large enough to express almost any idea. with all those declensions and verb forms. all you have to do is to replace curve. In the case of Natural Language. Let . Since most European languages have borrowed a large number of Latin words.13. Since recursion is a basic Prolog programming scheme. What I really wanted to draw when I created the peano project was the Peano‘s curve.

and therefore are easily comprehended by an English-speaking person. L) :. turtle(pnt(80. Russian. Italian.turtle(P1. Y2= math::round(Y1+L*sin(Facing)). Y2). right(A) :.pro implement turtle open core. "1. X2= round( X1+ L*cos(Facing)). Many of these . 80). and other sciences.6 Quotations from Key to Interlingua 1. assert(turtle(P2. P2). Every word has the form of the Latin stem or root or radical. Facing). real) single. drawline(Win. vpi. P2= pnt(X2. and every Anglo-Latin word. It includes all terms used in the scientific nomenclatures of botany. P1.turtle(P1. assert(turtle(P1. chemistry. move(L) :. P1= pnt(X1. 2. assert(turtle(P1.3: turtle. clauses classInfo("turtleGraphics/turtle".turtle(P1. zoology. French. Y1). Facing). Y2= round(Y1+L*sin(Facing)). NewAngle= Facing+A. -pi/2).156 % File: turtle. assert(turtle(P2. X2= math::round( X1+ L*cos(Facing)). Y2). vpiDomains. math class facts turtle:(pnt.pro us take a look at a few quotations from Key to Interlingua. The vocabulary of Interlingua is composed of a great many Latin words which have come into English. medicine.turtle(P1. Facing)). Spanish. end implement turtle Figure 13. NewAngle)). where Interlingua is the official name for Latin without inflexions. left(A) :. P1= pnt(X1. Portuguese. Interlingua adopts every word common to English. NewAngle= Facing-A. P2= pnt(X2. NewAngle)). Facing)). 13. Giuseppe Peano forward(Win. German. Y1). Facing).0"). Facing).

!. peano(_Win. integer) procedure (i. sed consiste de vocabulo internationale. i. et cetera. vpi. math class predicates peano:(windowHandle. Te programma in Prolog.4: Peano‘s curve terms are either Greek or Greco-Latin. to wit: Latino que de et sed isto illo illa me te nos vos id qui? que? omne English that of and but this. A. N-1. vpiDomains. integer.turtle::move(-60).turtle::right(A). N. id est Qui programma in Prolog? Te programma in que? Illo es omnepotente= He is omnipotent. that he. turtle::forward(Win.0"). peano(Win. Illa es Americana Me programma in Prolog. _A. peano(Win. H). drawCurve(Win) :. -A. real. end implement curve Figure 13. pi/2. 5). H). Germano. turtle::forward(Win. Latino habe praecisione de expressione. it she I.. -A. N-1. pro isto (because of this) Illo es Americano. which all Example Interlingua adopta vocabulo que existe in Anglo. peano(Win.6 Quotations from Key to Interlingua 157 implement curve open core. A. et al. clauses classInfo("plotter/curve". Nos programma in Prolog. _H) :. peano(Win. Vos programma in Prolog. turtle::left(A). 6. Franco et Russo. H). H). i. . Vocabulario de Latino non es formato ad arbitrio. N-1.N<1. me you we you guys it who? what. "1. A few necessary classical Latin words without international equivalents are a part of the vocabulary. H). H) :.e.13. i. i). peano(Win. N.

he gave his approval to an optional s-plural. in modo rapido (rapidly. nationale. if you discover a new plant. Then. In this century. commune (common). without modification. breve (short). the American economy surpassed the French. if we already have English? I think that we don‘t. Adjectives can be created from nouns with help of preposition de: • de fratre = fraternal • de amico = friendly. Germano. a few . In the XIX century. but they shifted to English not long ago. there are many words that are adjectives by nature: internationale. magno (large. French was the language of diplomacy. amicable Of course. Franco et Russo. Thus. people who propose Interlingua have a few interesting arguments to defend their project. For instance. you must describe it in Latin. People still use Latin to describe plants. In addi-tione Interlingua es de valore educationale nam (because) illo es de logico et naturale formatione. This was also the case of zoologists and anatomists. like Peano‘s Interlingua. Usu de Interlingua es indicato pro scientifico communicatione et pro com-merciale correspondentia. Usu de Interlingua in internationale congressu facilita intelligentia et economiza tempore. etc. You can also form adverbs using the word modo: in modo de fratre (fraternally). I guess that this is enough. humankind cannot let the international language change as economic hegemony and cultural prestige shift from one nation to the other. speedily). Why do we need an international language. and English became the international language. However. However. You can use these adjectives as adverbs. and since most people wanted to form the plural with s. There is an interesting story about this point. Interlingua adopta vo-cabulo que existe in Anglo. and will impose written Chinese to other nations. China will be the dominant superpower. The plural is formed by using the word plure as in: Plure vocabulo in Latino es in usu in Anglo The words of Latino are in use in English. Therefore. in modo de patre (paternally). big). Peano was a democrat. Here is an example of text in Latino sine flexione: Interlingua es lingua universale que persona in modo facile scribe et intellige sine usu de speciale studio.158 Giuseppe Peano Latino should not have any kind of inflection.

Add a new package to the project tree: LsF/editor. but in ten days he can write more than acceptable Latino. • • Create a new GUI project: LsF.pack Build the application. The problem is that the language they wanted was Chinese. and adopt a modern language in Botany too. The system will offer you a list of custom control names. thus I often go there to check his progress. and explains difficult words and expressions. Languages like French. not English! There is another argument in favor of Latin. Add the editorControl package to the project root. If this happens to Americans. browse for the Visual Prolog installation directory. Most of his fellow students cannot read. since the editorControl must be quite large. Resize the editor pane. • Create a new form: editor/txtWin. The custom control is the one represented by the icon of the key. and select the file \pfc\gui\controls\editorControl\editorcontrol. Very few Americans can come close to English written communication. English and Chinese are difficult to learn even by people that speak them as their mother tongues. choose the option File/Add from the task menu. what can I say about a Japanese who tries to learn English? Summary: Ten years is not enough to teach an American to read and write English prose. Add a custom control to the form.13. Resize the form window. To this end. Not many Frenchmen can write acceptable French. let alone write. . But let us leave this discussion to the wise. choose editorControl.6 Quotations from Key to Interlingua 159 botanists proposed to follow suit. My son is at the eighth grade in Mount Logan Middle School. and build a project that takes a text in LsF (Latino sine Flexione).

Txt=editorControl_ctl:getText(Start. create a file LsF. . %File: grammar. Build the application once more. End).txt in the \exe directory with the text below. end implement grammar Enable the File/New option. stdio::nl.cl class grammar open core predicates classInfo : core::classInfo. "1.pro files as shown below. End). modify the definition of predicate new as shown in figure 13. to ProjWin/TaskWindow.4.pro implement grammar open core clauses classInfo( "editor/grammar". end class grammar %File: grammar. Finally. If you do not remember how to do it. _MenuTag) :.pro).win/Code Expert/Menu/TaskMenu/id_file/id_file_new.X= txtWin::new(S).160 Giuseppe Peano • Build/Build the application. dic:(string).cl and grammar. dic(S) :stdio::write(S). Add the snippet clauses onHelpClick(_Source) = button::defaultAction :-editorControl_ctl:getSelection(Start. In the same file you added the last code for onHelpClick (txtWin.0"). X:show(). take a look at section 4. Add the snippet clauses onFileNew(S. Modify the grammar.frm. • Create an editor/grammar class with the Create Interface box unticked. of the application task menu. grammar::dic(Txt).5. to the ClickResponder of the help_ctl-button of txtWin.

editorControl_ctl:pasteStr(XX).6. you will echo the selected text on the message window. Usu de Interlingua in internationale congressu economiza tempore.6). o. new(Parent):.5: Inserting a file into an editor If you open a new txtWin from the application.6. fail). we start by breaking down the selection into a list of words. If you select part of the text. o). tryGetFileContent(PossibleName. !. "LsF.txt") :. The next step is to add dictionary entries to the selected text. FileName) :-trap(file::existFile(FileName).13. clauses tryGetFileContent( "". and outside the scope of this doc. _TraceId. tryGetFileContent(FileName. tryGetFileContent(FileName. you can start by adding more entries to the program of figure 13. If you want to learn the state of the art. 13. . this is done by the following predicate: strTok:(string. before writing it on the message window (see figure 13. _). generatedInitialize(). Figure 13. "". InputStr). "". FileName). InputStr. _FileName). class predicates tryGetFileContent:( string FileName. string InputStr. InputStr. and press the button Help from the TaskMenu of the application.!. XX=string::concat("Here: ". In figure 13.7 Examples 161 Interlingua es lingua universale que persona in modo facile scribe et intellige sine usu de speciale studio. string UpdatedFileName) procedure (i. !. Interlingua es indicato pro scientifico communicatione et pro commerciale correspondentia. To this end.txt". o). PossibleName= "LsF. string_list) procedure (i. and LsF. Natural Language Processing (NLP) is the most difficult branch of Computer Science.formWindow::new(Parent). the above text will appear in the window.7 Examples The examples of this chapter are in directories peano. InputStr= file::readString(FileName.

"without").frontToken(S. string). Meaning). []). !. ""). "1. string class predicates strTok:(string. entry("es". SList). was. L).162 Giuseppe Peano %File: grammar.0"). strTok(_S. o). string) procedure (i. Meaning). "of").6: A dictionary of ―difficult‖ LsF words . "am. dic(S) :. addExplanation(T. entry("sine". stdio::nl. were.strTok(S. strTok(S. are. to be"). "and"). addExplanation:(string. T. entry("de". "that"). Resp= concatList(SList). stdio::write(Resp). class facts entry:(string. string_list) procedure (i. o). T1). addExplanation(_T.entry(T. entry("que". entry("et". T. R= format("%s= %s\n". R) :. clauses classInfo( "editor/grammar". Rest). end implement grammar Figure 13. [T1|L]) :. !. addExplanation(T. strTok(Rest. is.pro implement grammar open core.

botanists spend a great deal of their time describing plant shapes. you will find a vast quantity of material on the subject. that you can use as a starting point to your own projects.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new. As you know. to TaskWindow. Add clauses onFileNew(S. Their descriptions are usually made in a simplified version of Latin. Build the project to insert the class into the project tree. • Add a class to aristid: draw. I will limit myself to an example. X:show(). Lindenmayer‘s method of describing plant shapes is based on the plotting turtle that you learned in section 13. invented by Carl Linaeus. • Create a GUI project: Lsys • Add a package to the root of the project tree: aristid • Add a form to package aristid: canvas. • Enable the option File/New of the TaskMenu. 163 .1 on page 151 . • Build the application. Untick the Create Interface box. Therefore.Chapter 14 L-Systems Aristid Lindenmayer was a Dutch botanist who invented a clever way to describe plant shapes. _MenuTag) :-X= canvas::new(S). On the internet.




Class draw

Then, edit the draw class as shown below. Build the application.
%File: draw.cl class draw open core, vpiDomains predicates classInfo : core::classInfo. tree:(windowHandle). end class draw

% File: draw.pro implement draw open core, vpiDomains, vpi, math clauses classInfo("plotter/draw", "1.0"). domains command = t(commandList); f(integer); r(integer); m. commandList= command*. class facts pos:(real Delta, real Turn) single. grammar:(commandList) single. class predicates move:(windowHandle, pnt, real, commandList) procedure (i, i, i, i). derive:(commandList, commandList) procedure (i, o). mv:(windowHandle, pnt, real, command, pnt, real) procedure (i,i, i, i, o, o). iter:(integer, commandList, commandList) procedure (i, i, o). clauses pos(4.0, 0.1745329). grammar([f(1)]). iter(0, S, S) :- !. iter(I, InTree, OutTree) :- derive(InTree, S), iter(I-1, S, OutTree).

14.1 Class draw

derive([], []) :- !. derive([f(0)|Rest], [f(0),f(0)|S]) :- !, derive(Rest, S). derive([f(_)|Rest], [f(0), t([r(1),f(1)]), f(0), t([r(-1),f(1)]), r(1), f(1)|S]) :- !, derive(Rest, S). derive([t(Branches)|Rest], [t(B)|S]) :- !, derive(Branches, B), derive(Rest, S). derive([X|Rest], [X|S]) :- derive(Rest, S). mv(Win, P1, Facing, f(_), P2, Facing) :- !, pos(Displacement, _Turn), P1= pnt(X1, Y1), X2= round( X1+ Displacement*cos(Facing)), Y2= round( Y1+Displacement*sin(Facing)), P2= pnt(X2, Y2), drawline(Win, P1, P2). mv(_Win, P1, Facing, m, P2, Facing) :- !, pos(Displacement, _Turn), P1= pnt(X1, Y1), X2= round( X1+ Displacement*cos(Facing)), Y2= round(Y1+Displacement*sin(Facing)), P2= pnt(X2, Y2). mv(_Win, P1, Facing, r(Direction), P1, F) :- !, pos(_Displacement, Turn), F= Facing+ Direction*Turn. mv(Win, P1, Facing, t(B), P1, Facing) :-move(Win, P1, Facing, B). move(_Win, _P1, _Facing, []) :- !. move(Win, P1, Facing, [X|Rest]) :-mv(Win, P1, Facing, X, P, F), move(Win, P, F, Rest). tree(Win) :- grammar(Commands), iter(5, Commands, C), Facing= -pi/2, Point= pnt(100, 250), move(Win, Point, Facing, C). end implement draw

166 Finally, add the snippet
clauses onPaint(S, _Rectangle, _GDIObject) :-draw::tree(S:getVPIWindow()).


to the PaintResponder. Build and execute the application. Open a canvas form by choosing the option File/New from the application menu. It will present a tree as shown in the figure on the left hand side.



The example of this chapter is in directory Lsys.

Chapter 15 Games
In this chapter, you will learn how to implement games in Visual Prolog. Of course, a good game is like a good poem. It is not enough to learn Russian, and versification rules in order to write like Pushkin. A poet, besides knowing the language in which he will write, needs imagination, creativity, etc. The same goes for a good game writer. You will need a lot of creativity to come up with something like Tetris or Space Invaders. I used these examples to show you that good games do not depend on fancy graphics or sound effects. The important features are suspense, continued tension and a sense of reward for good performance. Once, a young man asked Lope de Vega how to write a poem. The answer was: It is simple: Uppercase in the beginning of each verse, and a rhyme at the end. ―What do I put in the middle?‖, asked the boy. In the middle, ―hay que poner talento‖, stated Lope de Vega. This lesson has to do with a few techniques, like uppercase letters and rhymes. To get a good game, you will need to add talent to the recipe. The game you will implement is simple. There is a worm moving fast on the screen. The player must change its direction in order to prevent it from hitting obstacles and walls. You will need to implement the following items: 1. A window, where the worm will move. The window must have four buttons, to control the movement of the worm. 2. A state class, that describes the direction of the movement, and the position of the worm. It exports the predicates mov/0, to change the position of the worm, and turn/2, that can be used to turn it around. 3. A draw class, that draws a snapshot of the state of the worm. It exports the snapshot(Win) predicate. Pay attention to this detail: The predicate snapshot/1 cannot draw the worm directly onto the 167



Figure 15.1: Lawn form window. This would make the screen flicker. It must build a picture, and then draw it onto the screen. 4. A timer, that calls mov/0 and snapshot/1, at fixed intervals, in order to create an illusion of movement. We know what to do; let us do it. I have avoided creating objects until now. In fact, every time that you created a class, you were recommended to untick the Create Interface radio button. However, if we rigidly maintain this state of mind, our game will have a very nasty property. If you lose, quit the current game, and try to start another one, you will find out that the new game is not in the initial state. In fact, it is in the state where you lost the old one. The problem is that the variables used to describe a state have memory that lasts from one form to another. Objects were invented to prevent this kind of nasty behavior. Therefore, let us take this very good opportunity to learn how to create objects, and deal with object states. • Create a project: game.
Project Name: game UI Strategy: Object-Oriented GUI (pfc/vpi) TargetType: Exe Base Directory: C\vip70 Sub-Directory: game

Build the application. inside playground. X:show(). Build the application. Build the application in order to include the form. end implement click Build the application to include click into the project. refer to figure 15.169 Create a package: playground. %File: click.tm := W:timerSet(500). Insert code shown in figure 15. and add clauses onFileNew(S. Untick Create Interface. vpiDomains predicates bip:(window). kill:().1 for the design. Create class draw. kill() :.cl class click open core. and right_ctl. Do not untick Create Interface for the class objstate. end class click % File:click.3. down_ctl. Untick Create Interface. left_ctl. clauses bip(W) :.pro implement click open core class facts tm:vpiDomains::timerId := null. NB: Class objstate must have an interface in file objstate. Create a form: lawn. it is a good idea to change the names of the buttons from pushButton_ctl to up_ctl. Then enable File/New. Create a class click to hold the clock.2. You will add four buttons to the lawn form. Insert code of figure 15. Create class objstate inside playground. _MenuTag) :. to ProjWin/Code Expert/Menu/TaskMenu/id_file/id_file_new. .X= lawn::new(S).i. In the Properties dialog.vpi::timerKill(tm).

clauses onDownClick(_S) = button::defaultAction() :-stt:turn(0.stt:mov(). clauses onShow(Parent.frm. . stt:init().click::kill().frm. clauses onLeftClick(_S) = button::defaultAction() :-stt:turn(-10. Games to the DestroyerListener from the Properties-dialog of lawn. to ShowListener from the Properties-dialog of lawn. clauses onRightClick(_S) = button::defaultAction() :-stt:turn(10. _CreationData) :.frm. to TimeListener from the Properties-dialog of lawn.170 Add clauses onDestroy(_Source) :. 10. R= rct(10. -10). Add code for the ClickResponder corresponding to each of the buttons. 210). 0). invalidate(R). 10). clauses onTimer(_Source. 210.stt := objstate::new(). click::bip(Parent). 0). Add class facts stt:objstate := objstate::new(). clauses onUpClick(_S) = button::defaultAction() :-stt:turn(0. _TimerID) :.

If you draw figures at every tick of the clock. in Visual Prolog 5. !. The predicate W= pictOpen(Rectangle) opens a hidden window for you to draw things without worrying about a blinking animation. Alex Soares wrote the original game on which I based this tutorial. you will have created an animation. You can also put little apples for the worm to eat. and transfer it to the visible window only after it is ready for showing. W= pictOpen(Rectangle). the animation will blink. _Rectangle. it closes the window. at the same time. if you perform the drawings directly on a visible window. rop_SrcCopy) transfers the picture to a visible window. a library that has a lot of resources for 3D games. Win:pictDraw(Pict. Finally. you can write a 3D game. draw(W.2.frm.171 • Add clauses onPaint(_Source. 10). The solution for this problem is to perform the drawing on a hidden window. a window with a worm pops up. Let us keep to our study of drawing predicates. the predicate pictDraw(Win. using Direct X. pnt(10. pnt(10. S) :. The predicate Pict= pictClose(W) creates a picture from the contents of a hidden window. However. His game is in 3D. Finally. The segments have three coordinates. to the PaintResponder frm the Properties-dialog of lawn. 10). 200). rop_SrcCopy). The 3D game is very simple indeed. S). 0. It is up to you to improve this game. . If you info-fish using the Internet. Pict. You can add obstacles. like walls. After choosing the option File/New. you certainly will find formulae to calculate the perspective projection of a point. which is not very nice. Here is an example of code containing these three important predicates: snapshot(Win. You can control the worm using the four buttons. 200. stt). GDIObject) :-draw::snapshot(GDIObject. Pict= pictClose(W). Build and run the program. Rectangle= rct(0. and you must find their projections on the plane before drawing them.S:mov().

snapshot:(windowGDI Win. end implement draw Figure 15. It says that the system should copy the figure from the source to the destiny. S). clauses classInfo("playground/draw".pro implement draw open core. draw(_W. vpiDomains predicates classInfo : core::classInfo.cl and draw. • rop_PatInvert. snapshot(Win.172 Games The argument rop_SrcCopy specifies the mode of the raster operations. fail. 200. draw(W. and the background. You can use it for creating sprites. Win:pictDraw(Pict.2: draw. There are other modes of transferring figures from one window to another: • rop_SrcAnd. rop_SrcCopy). W= pictOpen(Rectangle).S:mov(). • rop_SrcInvert inverts the colors of the source. inverts the colors. vpi class predicates draw:(windowHandle. 0. objstate) procedure. end class draw %File draw. S) :. 200). "1. Pict= pictClose(W). 10). draw(W.pro . pnt(10. S) :. Rectangle). Rectangle= rct(0. !.S:segm(Rectangle). _S). %File draw. vpiDomains. performs a logical-AND between the bits of the figure. objstate).cl class draw open core. vpi::drawEllipse(W.0").

Y1). mov().retract(w(1. P1)). assert(w(3. assert(w(3. DY). P= pnt(X1. assert(w(1. % direction clauses init() :. integer) single. pnt(110.assert(w(1.173 %File:objstate.i interface objstate open core. P2)). assert(w(5. DY) :. vpiDomains predicates init:(). Y+10)) :. retract(w(2. P)). pnt(140. retract(w(5. pnt) nondeterm. assert(w(4.pro implement objstate open core. P)). assert(w(2. 100))). assert(w(5.w(_. Y. segm:(rct) nondeterm (o). P1= pnt(X1+DX. Y1+DY). 100))). d(DX. vpiDomains facts w:(integer. assert(w(2. _)). pnt(140. !. P4)).3: objstate . 100))). retract(w(3.assert(d(DX. integer). 100))). X+10. segm(rct(X. d(10. assert(w(4. pnt(X. P3)). 0). pnt(120. % worm d:(integer. end interface objstate %File:objstate. mov:(). turn:(integer. DY)). end implement objstate Figure 15. P3)). turn(DX.cl class objstate : objstate end class objstate %File:objstate. retract(w(4. P4)). 100))). Y)). mov() :. pnt(130. P2)).

Here is how to declare object facts: facts w:(integer. A class fact is shared by all objects of the class. he will find that the new worm is not in the initial state. 40)). pnt(30.174 Games 15. 120)). 100))). 100))). conn:(pnt. if an object predicate (a predicate declared in the interface) changes a fact. if you had kept the state of the worm in class facts. then there will be a private set of facts for each object. pnt). . 40) .3. pnt(140. pnt) nondeterm. d(10. conn(pnt(100. pnt(100. 120)). % direction clauses init() :. that appears on the next page. pnt(110. The solution is simple: Declare the facts without adding the keyword class to the head of the declaration. conn(pnt(30. assert(w(3. 120). 100))). assert(w(5. pnt(120. and plays another one. 100))). 160)). clauses city("Salt Lake". pnt(140. the game would have the following nasty feature: Nasty Game Property — Whenever the player loses a worm. This means that. In fact. assert(w(4. % worm d:(integer.assert(w(1. 0). pnt(100. city("Provo". it is changed for all objects of the class. 160)). quits the current game. city("Logan". assert(w(2. here is how a class fact is declared: class facts city:(string Name. This scheme of keeping an object state is implemented in the program of figure 15. the state of a class is established by class facts.1 Object Facts Pay careful attention to one particular detail: When dealing with classes that do not create objects. pnt(130. pnt Position). pnt(100. integer) single. pnt(100. it is in the state where he lost the old one. 100))). The problem is that the class facts used to describe the state of the worm have class memory that lasts from one form to another. Therefore. from one worm object to another.

• Create a new canvas form. Put it inside the snake package. • Build the application. 175 . which is dealt with in section 3. you may want to recall to memory the use of GDIObject. Use the code given in figure 16. where you will find material about invalidating a rectangle for painting as well. and let its name be snake. • Create a new package. Project Name: rattlesnake UI Strategy: Object-oriented GUI (pfc/gui) In this project. Enable File/New.1 to define and implement click. if you do not remember how to use the event painting. to TaskWindow. you will animate the famous rattlesnake that appears on the John Paul Jones‘ Don’t tread on me flag. add onFileNew(S. F:show(). this theme is also explained in chapter 8.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new. _MenuTag) :-F= canvas::new(S). • Create a project.2.Chapter 16 Animation Please. page 32. You will also need to use masks to create figures with a transparent background. click::bip(F). Untick Create Interface. Finally. • Create class click to hold clock events. page 93. Then. take a look at chapter 8.

%File: click.cl class click open core predicates bip:(window). kill:(window). end class click %File: click.pro implement click open core class facts tm:vpiDomains::timerId := null. clauses bip(W) :- tm := W:timerSet(1000). kill(W) :W:timerKill(tm). end implement click

Figure 16.1: click class handles the timer



Class dopaint will handle painting, and works more or less like the dopaint method in Java. Create a class, name it dopaint, and untick the Create Interface option. Here is the class definition:

%File: dopaint.cl class dopaint open core predicates classInfo : core::classInfo. draw:(windowGDI). invalidrectangle:(vpiDomains::rct) procedure (o). end class dopaint

Figure 16.2 shows the implementation of dopaint.pro. Build the application.

16.1 dopaint
implement dopaint open core, vpiDomains constants className = "snake/snakestate". classVersion = "". class facts yesno:integer := 0. class predicates flipflop:(picture Picture, picture Mask) determ (o, o). clauses classInfo(className, classVersion). flipflop(Pict, Mask) :- yesno= 0, yesno := 1, Pict= vpi::pictLoad("figs\\n0.bmp"), Mask= vpi::pictLoad("figs\\n0Mask.bmp"), !. flipflop(Pict, Mask) :- yesno= 1, yesno := 0, Pict= vpi::pictLoad("figs\\n1.bmp"), Mask= vpi::pictLoad("figs\\n1Mask.bmp"). draw(W) :-P= vpi::pictLoad("figs\\frogs.bmp"), W:pictDraw(P, pnt(10, 10), rop_SrcCopy), flipflop(Snake, Mask), !, W:pictDraw(Mask, pnt(40, 50), rop_SrcAnd), W:pictDraw(Snake, pnt(40, 50), rop_SrcInvert). draw(_). invalidRectangle(rct(40, 50, 100, 100)). end implement dopaint


Figure 16.2: dopaint.pro




Handling the timer
onDestroy(W) :- click::kill(W).

When you close canvas, you must kill the timer. To achieve this goal, add

to the DestroyListener of the Properties-dialog of canvas.frm. Then, add
onTimer(_Source, _TimerID) :-dopaint::invalidRectangle(R), invalidate(R).

to the TimeListener of the Properties-dialog of canvas.frm. Finally, add the event handler
onPaint(_Source, _Rectangle, GDIObject) :-dopaint::draw(GDIObject).

to the PaintResponder of the Properties-dialog of canvas.frm.


How the program works

The first thing that predicate draw(W) does is to paint a few frogs onto the background. The frogs are loaded by the following predicate:
P= vpi::pictLoad("figs\\frogs.bmp"),

Of course, you must have the file frogs.bmp in directory figs. Then, draw(W) obtains the picture and the mask of a rattlesnake. The flipflop(Snake, Mask) predicate is designed to alternate two snake paintings, in order to get the illusion of motion. To achieve the insertion of the snake onto the background, you must use masks. If you do not remember how to do it, read chapter 8 again.

Chapter 17 Text Editor
In this chapter, you will learn how to use the editControl class to create a text editor. • Create a new project.
Project Name: editor UI Strategy: Object-oriented GUI(pfc/gui)

• Add the editorControl package, that is found in the installation direc tory of Visual Prolog. Choose the task menu option File/Add and look for the package in
Visual Prolog 7.x\pfc\gui\controls\editorControl.

• Build the application. Then create a new form edform.frm at the project root, as shown in figure 17.3. To insert the editorControl into the form, choose the custom control option in the form prototype; it is the button that has a Yale key1 (figure 17.1); and then choose edi-torControl in the Dialog shown in figure 17.2. Change the name of the control to editorControl_ctl as shown in figure 17.4. Build/Build the application. • Enable File/New and add the snippet below to it.
onFileNew(S, _MenuTag) :- F= edform::new(S), F:show().

Yale invented this kind of key, that is very popular nowadays. Legend has it that soon after his invention, Houdini was able to break through the new device.




Text Editor

Figure 17.1: The insert custom control button

Figure 17.2: Choose Custom Control dialog


Saving and Loading files

Go to the project tree, and open edform.frm, if it is not already open. Use the Properties-dialog to add the snippet of figure 17.5 to the ClickResponder of button:save_ctl; then add the code shown in figure 17.6 to the ClickRe-sponder of button:load_ctl. This is about all you have to do in order to create an operational text editor.

4: User control properties .17.1 Saving and Loading files 181 Figure 17.3: A form with Edit Control Figure 17.

FName= vpiCommonDialogs::getFileName("*. _IsUnicodeFile). onSaveClick(_Source) = button::defaultAction(). ["Text".txt"]. Txt). file::writeString(FName. ["Text".182 Text Editor predicates onSaveClick : button::clickResponder. Str= file::readString(FName. clauses onSaveClick(_Source) = button::defaultAction() :-Txt= editorControl_ctl:getEntireText().6: Code for onLoad .5: Code for onSave predicates onLoadClick : button::clickResponder. "*.*". ". onLoadClick(_Source) = button::defaultAction(). _X).".txt"]. ". []. "Save". Figure 17. !. Figure 17. "Load". Str). !.*". "*. clauses onLoadClick(_Source) = button::defaultAction() :-FName= vpiCommonDialogs::getFileName("*. editorControl_ctl:pasteStr(1. file::existFile(FName). []. _X).".

as in figure 2. double click on the newly created id_file_new->OnFileNew branch. • Build the application. 183 . you will acquire introductory notions of printing.Chapter 18 Printing In the previous chapter. Open the folders Menu. as shown below.win. Select the branch id_file_new. double click on the branch TaskMenu. and enable the &File/&New/tF7 option from the menu prototype. _MenuTag) prototype with the snippet given below.6. TaskMenu.mnu. right click on the TaskWindow. finally. replace the onFileNew(_Source. you learned how to build a text editor. in order to insert prototypes of the Task Window onto the Project Tree. • On the Project Tree. and choose the option Code Expert from the floating menu. and id_file. and press the button Add. page 21. Then. • Create a project. The Dialog and Window Expert will pop up. • On the Project Tree. Project Name: testPrt UI Strategy: Object-oriented GUI (pfc/GUI) Target Type: Exe Base Directory: C:\vip\codeForTyros In this chapter.

.attr_printer_hres). you can use it to obtain information about the printer resolution. that looks good on print. _MenuTag) :-PW=vpi::printStartJob("Recoreco"). you can use any drawing predicate to produce a fine printed page. Finally.FNT).FNT). in order to print something. vpi::printEndJob(PW). FNT=vpi::fontCreate(ff_Fixed. 200. VRES*40 div V_SCR_RES). In fact.[]. "Before the sunset!"). PW=vpi::printStartJob("Recoreco") Once you have a window.attr_screen_vres). is to open a printer job window.[]. vpi::winSetFont(PW. vpi::drawText(PW.184 Printing clauses onFileNew(_Source. vpi::winSetFont(PW.attr_printer_vres). _HRES= vpi::winGetAttrVal(PW. and using information about the printer resolution. the first thing you do. "Before the sunset!"). _HRES = vpi::winGetAttrVal(PW. V_SCR_RES=vpi::winGetAttrVal(PW. vpi::printEndPage(PW). V_SCR_RES=vpi::winGetAttrVal(PW. 100. 100. vpi::printStartPage(PW). vpi::drawText(PW. The beauty of Visual Prolog printing scheme is that you deal with the printer as if it were a normal graphic window. By trial and error. VRES = vpi::winGetAttrVal(PW. 200.attr_printer_vres). VRES= vpi::winGetAttrVal(PW. you can define a font.attr_screen_vres).attr_printer_hres). VRES*40 div V_SCR_RES). FNT=vpi::fontCreate(ff_Fixed.

185 . Rename the button to button:yourname_ctl. Add the following snippet to the ClickResponder belonging to button:yourname_ctl: clauses onYournameClick(_Source) = button::defaultAction :-Name= edit_ctl:getText().pack New in Existing Package (forms): Create a Control with the name helloTab. File/Add: pfc\gui\controls\tabControl\tabControl. "!\n").Chapter 19 Tab forms and other goodies Create a new project: Name: tab_example UI Stategy: Object GUI New in New Package: Create a package with the name forms From the installation directory. in order to insert snippets for events. ". Name. stdio::write(Ans). Build the application. select the option Control on the left hand side pane. Ans= string::concat("Hello. to achieve this goal.

you will learn how to place both programs in a control with tabs. clauses fibo(N. Build the application again. I= toTerm(Num). world". Now. F= F1+F2 end if. let us create a form for the Fibonacci sequence. fibo(I. . F). predicates onFibClick : button::clickResponder. F2). Add the following snippet to the ClickResponder belonging to button:fib_ctl: class predicates fibo:(integer. Build the application. integer) procedure (i. You already created the form to hold the hello-application. and recursive Fibonacci. I. Ans= string::format("fibo(%d)= %d". rename the button to button:fib_ctl. to make sure that everything is working properly. o).186 Tab forms and other goodies 19. F) :-if N<2 then F=1 else fibo(N-1. F). F1). fibo(N-2. clauses onFibClick(_Source) = button::defaultAction :-Num= edit_ctl:getText().1 Famous programs There are two programs that one can call infamous: "Hello. edit_ctl:setText(Ans). • New in Existing Package (forms): Control with name fibTab. in order to insert code for events. In this chapter.

% Page1 = tabPage::new(). Page2:setText(Tab2:getText()). tabControl_ctl:addPage(Page1).pro. succeed. tabControl_ctl:addPage(Page2).1 Famous programs 187 • Create a New form in Existing Package (the existing package is forms) — Name it forms/tabs. generatedInitialize(). • Go to the file tabs. Tab1 = helloTab::new(Page1:getContainerControl()). Page1:setText(Tab1:getText()).19. • Enable the option File/New of the application file menu. generatedInitialize(). and replace the clause clauses new(Parent):-formWindow::new( Parent). Page2 = tabPage::new(). . Build the application. Tab2 = fibTab::new(Page2:getContainerControl()). Use the Yale key to insert a tabControl into the form. with the following snippet: clauses new(Parent):-formWindow::new( Parent). which you can access by clicking the corresponding branch of the project tree.

Let us enumerate them. Global warming is the most serious challenge facing us today. there are many reasons for cultivating this important branch of science. Saving the world. we must reduce . _MenuTag) :-W= tabs::new(S).2 Botany Your interest in Botany may be none. However.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new. To protect the planet for future generations. W:show(). Tab forms and other goodies to TaskWindow.188 Add the snippet clauses onFileNew(S. Cute. Build the application one last time. isn‘t it? 19.

I could say that Computer Scientist and Botanists can understand each other. at least in the realms of computer graphics. we need a climate policy iniative to reduce emissions from tropical deforestation. the most cherished book in our house was Maeterlinck‘s L’Intelligence des fleurs. however. French cuisine. Therefore. To tell you the truth. in order to check the decrease of bio-diversity. the Serbian Nero Wold was fond of wine. since there will be plenty of money for researchers and specialists in global warming. an exceptionally talented Swiss cook who prepares and serves all his meals. if saving the world is your vocation. They are objects of a cult that owes nothing to wine. but by how he will get the money necessary to maintain his expensive cults. You probably remember Bizet‘s song: Votre toast.19. In the chapter about Aristid Lindenmeyer you have seen that Botanists invented clever methods to create computer graphics depicting flowers. not from India) who with my father created an ecological sanctuary that we maintain until today. sen˜ors. car avec les soldats oui. Computer graphics. Orchids. I hope that a Belgian reader may shed light on this point. understand the dynamics of plant interdepen-dency. I remember that when I was a child. and bio-diversity. and select rapidly growing new vegetable species to replace forests that our lack of vision and direction destroyed in the past. I am proud to say that my family is very active in protecting nature. By the way. These exotic plants are among the most beautiful creations of Nature. It turns out that plants offer poetically the only viable way out of this trap that we set ourselves. Therefore. my grandmother was sure that he did. sen˜ors. If you read Wolf‘s books. I never found any evidence that Maeterlinck said such a sentence. He hires Fritz Brenner. an Indian woman (Native American. les toreros peuvent s’entendre. and speaks French when addressing him. and orchids. and practical solutions already at our disposal.2 Botany 189 the concentration of heat-trapping gases by using the technology. you will notice that the suspense is not created by how Wolf solves mysteries. the last man will die clinging to its trunk. I want to pay homage to my grandmother. an orchid expert who takes care of . My father used to make me repeat plusieurs fois Maenterlinck‘s famous saying: When the last tree has been thrown down. or French cuisine. je peux vous le rendre. here is a good place to start. I believe that saving the world is also good business. he also hires Theodore Horstmann.

German. notwithstanding Newton was good enough to write in Latin. you can use the underlying structure of the Latin program to write programs to teach Russian. but English scholars consider him to be the greatest scientist who ever lived. In order to teach you how to pronounce Latin. and wrote in Latin. and listEdit-controls. you will learn how to work with tab-controls. Rumanian. One of the most interesting features of Botany. Latin. Italian. • Declensiontab. a program to help them deal with this difficult language would give a head start to the goals of saving the world. as you remember. In this tab. Besides this. and Chinese. the most important of his employers is Archer Goodwin. The program to teach Botanical Latin is given in the skinner directory of the folder containing the examples that accompany this document. I am not sure whether you heard about this scientist. Therefore. and naming of plants. cultivating orchids. Latin has also a very complex verbal system. If you want to learn one of the Romance languages. that it passed down to the so called Romance Languages (Spanish. and Catalan). or German. and others took this saying literally. Peano. you can adapt the support provided for Latin. even if you do not think that Botanical Latin is useful enough to merit your attention. Russian. as compared with other sciences. There are languages where nouns change to show their function in a sentence. By the . Declension is not the only feature that Latin shares with German. the author of the book is a certain Isaac Newton. French. • Verbtab. I used excerpts from a very famous book called Philosophiae Naturalis Principia Mathematica. Sanskrit. who works as a detective to earn the money necessary to keep the expensive habits of his overweight boss. or French verbs. Polish are among these languages. that he would find readers. who speaks fluent Latin. The program contains three tab-controls: • Pronunciation tab. They certainly are exaggerating. and Ancient Greek. my son. Newton. Galician. Portuguese. Russian. In this section.190 Tab forms and other goodies the plant rooms. Gauss. English. I will see how such a program can be written. Ancient Greek. will read Newton for you. it that there is a special kind of Latin internationally used by botanists for the description. and find readers. when a scientist is very good. in order to study Spanish. or creating cool computer graphics. Since many Botanists do not know enough Latin. finally. one says that he could have written in Latin.

19. two read-only edit controls. choose the option New in New Package from the IDE task menu. In order to create a tab control. press the button Create. to show the tense. the package is called tabPackage. I suggest that you place all tab controls in the same package. let us concentrate our efforts on the design of the program. Spanish and Portuguese are much closer to Latin than other Romance languages. select the option Control from the left hand pane. that will hold the verb drilling list. in the example. and mount the following layout: The verbTab control contains a listEdit control. Consider the verb amare: Present amo amas amat amamus Latin Imperfect amabam amabas amabat amabamus Present amo amas ama amamos Spanish Imperfect amaba amabas amaba am´abamos Now. The Latin verbal system was transmitted to Spanish and Portuguese almost without alteration. that will compare the student‘s answer with a template. The main reason behind offering you this application is to show . and mood that the student will be practicing.2 Botany 191 way. and a button.

. 0.. 1). you must also add the code from figure 19. verbs:: get_verb_state(Tense.192 Tab forms and other goodies how to handle the listEdit control. 1). L). _Data). onShow(_Source. clauses onShow(_Source. and add the following snippet predicates onShow : window::showListener. . Mood). vpi::lboxSetSel(VerbList. vpi::lboxAdd(VerbList.. From the Properties-dialog. it shows also how to select an entry: VerbList= listVerb_ctl : tryGetVpiWindow().. to the showListener.1 to Events-onCheckClick. by giving its index : vpi::lboxDelete (VerbList. then you will learn a few other listEdit methods: Get the window associated with the control : VerbList= listVerb_ctl : tryGetVpiWindow() Get the selected index : IV= vpi::lboxGetSelIndex(VerbList) Delete entry. let us take a close look at the methods associated with this important kind of control.. !. tense_ctl:setText(Tense). mood_ctl:setText(Mood). therefore. IV) Obtain the number of entries : C= vpi::lboxCountAll(VerbList) . The snippet shows you how to add a list of options to the control. verbs::allVerbs(L). 0. _Data) :-VerbList= listVerb_ctl : tryGetVpiWindow(). you must press the Events-button. vpi::lboxSetSel(VerbList. vpi::lboxAdd(VerbList. L). From the Properties-dialog.

onCheckClick(_Source) = button::defaultAction. L. !. 1) else template::check_present(Txt. IV) . vpi::lboxAdd(VerbList. NewList) else succeed() end if. Ans) then editorControl_ctl:pasteStr(" "). it is necessary to synchronize two or more threads through a resource called monitor. NewMood). It triggers a Windows‘ tool called playSound in order to play a wave file.19. vpi::lboxSetSel(VerbList. Tense= tense_ctl:getText(). Since Prolog seems to deal with the thing automatically. 0. Mood. instead of the programmer having to access concurrency primitives explicitly. verbs::allVerbs(NewList). Verb= listVerb_ctl:getText(). vpi::lboxDelete (VerbList. L. if template::check_it(Txt. The pronunciationTab control has something new. Ans).1: listEdict methods . verbs::pres_root_conj(Verb. if C= 0 then verbs::next_verb_state(). VerbList= listVerb_ctl : tryGetVpiWindow(). that transparently inserts locking and unlocking code to appropriately designated procedures. Mood= mood_ctl:getText(). tense_ctl:setText(NewTense). Figure 19. Tense. verbs::get_verb_state(NewTense. IV= vpi::lboxGetSelIndex(VerbList). mood_ctl:setText(NewMood). editorControl_ctl:pasteStr(Ans) end if. C= vpi::lboxCountAll(VerbList). onCheckClick(_Source) = button::defaultAction :-Txt= editorControl_ctl:getEntireText().2 Botany 193 The declensionTab control works exactly like the verbTab-control. Since we are dealing with a shared resource. I will not elaborate. L).

Tradition Ideograms. 19. let us see how to deal with Chinese. into the clickResponder of the Play button. at least one third of the World‘s population has some knowledge of written Chinese. null. /* purge non-static events for task */ snd_application : soundFlag = 0x0080. /* look for application specific association */ Finally. soundFlag SoundFlag) -> booleanInt Success language apicall. /* play asynchronously */ snd_filename : soundFlag = 0x00020000. . the writing system used in Mandarin was adopted by other Chinese languages.194 Tab forms and other goodies Now. /* play synchronously (default) */ snd_async : soundFlag = 0x0001. As a result. that uses the Latin alphabet with Greek accents. constants snd_sync : soundFlag = 0x0000. let us declare a Prolog predicate that will be called whenever you want to trigger playSound. Mandarin itself has three writing system: Pinyin. by the Japanese. and a few necessary constants. introduce the snippet given below clauses onPlayClick(_Source) = button::defaultAction :-File= listEdit_ctl:getText(). /* name is file name */ snd_purge : soundFlag = 0x0040. besides this. and by the cultivated Koreans. _ = playSound(File. pointer HModule. class predicates playSound : (string Sound. and Simplified Ideograms. A Chinese dialect known in the West as Mandarin is the language with the largest number of speakers. /*snd_nodefault*/ snd_async+snd_filename).3 Handling Chinese After this incursion into Latin.

un-tick the Create Interface radio button. or Traditional Ideograms.2.cl class ideograms open core predicates classInfo : core::classInfo. at my request. You will find the class file below. _MenuTag) :-_ = multiMedia_native::sndPlaySound("howareu. • Create a package chineseforms. Of course. Therefore. • Add the editControl to its root. predicates onFilePronunciationHowAreYou : window::menuItemListener. You will find the snippet that he has used below. end class ideograms . he has used the multiMedia_native class to add sound to a couple of menu entries. Therefore it was not necessary to go through the red tape required to call an external routine. and the multimedia API provides an easy example of such an operation. but my son knows. • Create an ideograms class. % File: ideograms. string) procedure (i. browse the multimedia class to uncover additional resources.wav". • Add a chineseForm to chineseforms. one usually express his/her ideas in Pinyin. and a Word Processing Editor translates Pinyin into Simplified. my son used the multiMedia_native class. o). I do not know Chinese. ideograms:(string. and a Pinyin2Ideogram button. You may ask why he did not adopt the same solution for Latin and Chinese. The chineseForm has editControl. In the case of Chinese.3 Handling Chinese 195 When using a computer to write Chinese. The implementation is listed in figure 19.19. • Create a project: chinese. The point is that he wanted to show you how to call external routines from Prolog. clauses onFilePronunciationHowAreYou(_Source. multiMedia_native::snd_ASync ). as he has done in the case of Latin.

"\u55ce"). string) procedure (i. add the following snippet clauses onPinyinClick(_Source) = button::defaultAction :-Txt= editorControl_ctl:getEntireText(). converList([]. clauses pinyin("ni^". "\u4f60"). Rest). "\u6211"). converList:(string*. ideograms::ideograms(Txt. Idea). converList(L. string). pinyin("ma". editorControl_ctl:pasteStr(Ans). pinyin2ideogram(P.pinyin(P. converList([P|Ps]. converList(Ps.!. pinyin("ha^o".0"). Idea) :. Ans). Idea). pinyin2ideogram(P. "\u4f60"). . Acc) :.pinyin2ideogram(P. Rest). end implement ideograms Figure 19. P). "\u597d"). o). to the ClickResponder belonging to Pinyin2Ideogram-button. !. ideograms(S.2: File: ideograms.pro From the Properties-dialog.pideograms pinyin:(string. "") :. Idea) :. class predicates pinyin2ideogram:(string. pinyin("wo^". class facts . " \n"). "1. pinyin("Ni^".L= string::split(S. Idea).196 Tab forms and other goodies implement ideograms open core clauses classInfo("chineseforms/ideograms". Acc= string::concat(Idea. string) procedure (i. o).

. Windows assumes that you speak the most weird languages. _Data) :-editorControl_ctl:setFontDialog(). !. Therefore I often download Paraguayan songs. Anyway. your Unicode Font may not have the Chinese characters. whenever a new form is created.3 Handling Chinese The last step is the addition of the following snippet predicates onShow : window::showListener. Of course this program will work only if you have a Unicode font installed. except Chinese.19. I am pretty sure that Arial Unicode MS does have Chinese characters. However. or in Europe. or Korea. _Data). I have told you before that Paraguay is my favorite country. Japan. onShow(_Source. if you live in the United States. 197 to the ShowListener of the Pinyin2Ideogram-button. the result is that my computer often assumes that I speak one of the two official languages of that country. If you live in China. you must choose a Unicode font. clauses onShow(_Source. this is not a huge problem.

regular expressions are useful tools. the regular expression would be "[0-9]+". !. These are the two instances of regular expressions that I use. like the Boyer-Moore algorithm. s/he may want to find a pattern that describes an integer. stdio::nl. The plus sign is called positive Kleen closure. stdio::nl.198 Tab forms and other goodies 19. which means: A sequence of one or more digits. if the programmer wants to search a string for a substring. test( "There were 99 small Romans"). Str. There is also a reflexive Kleen closure. s/he can use traditional search methods. . clauses test(Str) :-regexp::search("-[0-9]+|[0-9]". "regexpr"). stdio::write(Pos). and indicates one or more repetitions. succeed(). Len). test(Str) :stdio::write("No integer found in ".4 Regular expressions Whenever one is dealing with languages. % place your own code here end implement main goal mainExe::run(main::run).prj UI Strategy: console ******************************************/ implement main open core clauses classInfo("main". for anything more complex I prefer the full power of Prolog. clauses run():-console::init( ). for instance. Pos. stdio::write(Len). /****************************************** Project Name: regexpr. that accepts the empty string: "[0-9]*". However. In fact. Str). stdio::nl. In this case. class predicates test:(string) procedure (i).

The rule for npr can be understood thus: npr→ article adjective noun A noun-phraseisdefined as an article followed by an adjective followed by anoun A language is regular if there is at most one non-terminal symbol at the right hand side of any one of the rules that describe it. Regular expressions were introduced in the 1950s by Stephen Kleene as a method of describing regular languages.19. if you do not remember what a clausal form is. Regular languages are good to describe tokens. in order to indicate a sequence of one or more members of the set. etc. A sequence of zero or more members of the set is indicated by an asterisk (the reflexive .g. In Chomsky-Schutzenberger formalism.. "[0-9]" matches any numeral representing a positive integer. the regular expression "[0-9]" is a pattern that matches any digit. and adjective are non-terminal symbols. adjective. and you will find something about the subject. article. noun Any symbol that appears on the right hand side of an arrow is a non-terminal symbol. noun. g. Therefore. go back to page 83. symbols that the grammar defines. e. lexical entries. a simple English noun phrase is described by the following set of rules: article → [the] noun → [iguana] adjective → [pretty] npr → article. Symbols that appears only on the right hand side of the rules are terminal symbols. [iguana]. In modern notation. besides this. i. npr. it is a good idea to learn what is a Chomsky-Schutzenberger hierarchy.e. the nonterminal symbol must be the rightmost one. Noam Chomsky (an American Linguist) and Marcel Paul Schutzenberger (a French Medical Doctor) proposed that languages should be described by grammar rules very similar to logical expressions in the clausal form. a member of a set of terminal symbols is represented by brackets around a description of the set. for instance. the programmer may uses the + sign (positive Kleene closure). like numerals.4 Regular expressions 199 For a deeper understanding of regular expressions. e.

console::init(). "--\\1--"). "-[0-9]+|[0-9]+" is a pattern that matches a negative numeral. "<H1\\b[^>]*>(."). then "[^a-z]" is the set of all characters that are not lowercase letters. for instance. The example replaces an HTML tag with its contents. one can add back references by enclosing the pattern in parentheses. run():. clauses classInfo("main". Anything between the tags is captured into the first back reference. stdio::write(Ans). Finally. or a sequence of digits without prefix "[^A-Z]" a character that is not an uppercase letter In replacements. "[0-9]" a member the set of all digits "[0-9]+" a sequence of one or more digits "[0-9]*" a sequence of zero or more digits "-[0-9]+|[0-9]+" a sequence of digits prefixed with minus. Alternation is indicated by a vertical | bar. !.*?)</H1>". one can use the hat character to represent characters that do not belong to a set. end implement main goal mainExe::run(main::run). test(Str) :-Ans= regexp::replace(Str. test( "<H1> Viatores in Roma </H1> etc. The question mark in the regular expression makes sure that the star stops before the first closing tag rather than before the last one. . "regexpr"). and using "\\1" to insert the matched string into the replacement. or an unsigned integer.200 Tab forms and other goodies Kleene closure). An example is given below. implement main open core class predicates test:(string) procedure (i).

vpi::lboxSetSel(SongList. 0. Add a listEdit box to it. In this section. and two buttons: play_ctl and stop_ctl. Let the form name be midiPlayer. Let us start by writing a program that executes MIDI files.5 A MIDI player 201 19. onShow(_Source. press the Events-button. and perform his/her work single-handedly. clauses onShow(_Source. _Data) :-SongList= listSongs_ctl : tryGetVpiWindow().5 A MIDI player Computers made it possible for a musician to create interesting songs. !. you will learn a few facts about MIDI. _Data). "Beethoven"].19. and add the following snippet predicates onShow : window::showListener. explore new artistic venues. a protocol that brings computer music to the concert hall. 1). to the showListener. From the Properties-dialog of the midiPlayer form. vpi::lboxAdd(SongList. L). L= ["Wagner". Project Name: midiplay UI Strategy: Object-oriented GUI(pfc/gui) • Add a New form in a new package. .

W:show(). _= multiMedia_native::mciSendString( Command. Null). 300. . " "). to it. clauses onPlayClick(_Source) = button::defaultAction :-Null = null. File= listSongs_ctl:getText(). string::create(300. add the snippet clauses onFileNew(S. Len. Len = 300. " "). The final step is to add code to the button that will interrupt the music. Command= string::format(C.202 Tab forms and other goodies Enable the File/New option of the application task menu. _Z= multiMedia_native::mciSendString( string::createCopy("Close mid"). _= vpi::processEvents(). if you decide to do something else. C= "open %s. Null).mid type sequencer alias mid". Null). _= multiMedia_native::mciSendString( "Play mid from 0". Buffer. " "). string::create(300. clauses onStopClick(_Source) = button::defaultAction :-Null= null. Buffer. The next step is to add the snippet below to the ClickResponder of the play_ctl-button. Then. Len. Build the application. Len. Buffer =string::create(300. File). _= multiMedia_native::mciSendString( string::createCopy("Close mid"). _MenuTag) :-W= midiPlayer::new(S). Null).

His programs analyze the work of great composers like Tchaikovsky. and write music according to the same musical style. the conductor of the Utah State University Symphony Orchestra. using his computers. who is an accomplished Prolog programmer. Sukorski program was something like a lie detector. he was able to play Mascagni‘s Cavalleria Rusticana single handedly. in fact. I studied Space Science. and singer. I included one of Lima‘s compositions in the examples. who is a pianist. Rebuild the application. I also knew Maestro Sukorski who created a very interesting work of art. my son. the beautiful sonata that I offer you in the skinner project was composed by my neighbor. I was raised next door to the house of a great composer. For instance. Notwithstanding. and asked him to show you how to create a simple MIDI file. and Classical Literature in Cornell. and mother didn‘t like music very much. is the best friend of Jos´e Bernal. open the folders $(Prodir)/pfc/gui/Controls/ Right click on the Controls folder. . the program was able to compose a music suited to the occasion. Using these data. Besides Maestro Dovicchi. and add the editorControl package to the Project Tree. Basically. I used the Internet to contact Maestro Lima. it seems that I have inherited Moog‘s table.6 Midi format My father. whose adviser was no other than the famous Hungarian composer Gyorgy Ligetti. Moog scribbled his name on the very same table that I used while in Cornell. I was lucky enough to know many great musicians. etc. Project Name: midiplay UI Strategy: Object Oriented GUI (pfc/gui) • Build the application in order to construct the Project Tree.19. before my arrival. What is more. by measuring skin resistance. I also know well Maestro Dovicchi. it was in Prolog!) that performes an analysis of the mood of a person. my office there had been occupied by Moog. another great expert in computer music is the composer Luciano Lima. heartbeat increases. Maestro Dovicchi researches methods of producing high quality computer music in the midi format. it may interest you to know that there exists a city named after that haunting piece of music. or Beethoven. Maestro Joubert de Carvalho. I happened to be present during this memorable performance. • From the Project Tree.6 Midi format 203 19. who happens to be the son of Sergio Bernal. he wrote a program in Prolog (yes. electromyograph signals.

[]. Rebuild the application.mid". • Rename the Save-button to save-ctl. midi::generate(FName. end class midi • Add the snippet below to the ClickResponder belonging to save_ctl. "*. ["Midi". FName= vpiCommonDialogs::getFileName("*. _X).mid"]. S). generate:(string.3. Enable the File/New option of the application task menu. clauses onSaveClick(_Source) = button::defaultAction :-Txt= editorControl_ctl:getEntireText(). .". and add the snippet below to it. "Save in MIDI format". !. class midi open core predicates classInfo : core::classInfo. string*) procedure (i.204 • Tab forms and other goodies Add a New in New Package form with the name midiform. You will find the class declaration below. clauses onFileNew(S. onSaveClick(_Source) = button::defaultAction. S= list::removeAll(string::split(Txt. • Create a class with the name midi. W:show(). and the implementation on figure 19. _MenuTag) :-W= midiform::new(S). "\n "). ". i). "").

doncella desnuda que habita el Guaira. beautiful blend of goddess and panther. The program of figure 19. you can easily complete the missing steps. Dance has bent her hips into the shape of the blue curves of the Parana river. The lyrics says: India. Collar de colmillos de tigres y pumas enjoya a la musa de Ybytyruzu´. The first step is to create an output stream file: P= outputStream_file::create(File. From the point of view of a musician. Arisca romanza curvo sus caderas copiando un recodo de azul Parana. A necklace from teeth of tigers and pumas is a jewel for the muse of Ybytyruz. For instance. her language is a wild honeycomb. . etc. you will find a more refined and complete version of the program listed in figure 19. However.3. the programs given in the examples are grossly oversimplified. Bravea en las sienes su orgullo de plumas. By the way. change the instruments.3 represents a good opportunity to learn how to write data to a file. P:close(). su lengua es salvaje panal de eirusu. India. stream::binary()) Then you can write a list of bytes to the file by using the foreach construction. the example in the figure is an oversimplified rendering of India. On her temples shine the pride of feathers. improve the resolution. as you can see below. you can add multiple tracks. the beautiful Guarania of Jos´e Asunci´on Flores. bella mezcla de diosa y pantera.19.6 Midi format 205 In the examples. naked girl that lives in Guaira. foreach X= list::getMember_nd (MidiCode) do P:write(X) end foreach.

[0. 0. 114. Y). 24. nt("G". tomidi:(string*. unsigned8) procedure (i. "1. I4). stream::binary()). 161. []). 1. MainHeader= [ 77. 0.144. !. generate(File. X3= convert(unsigned8. 69). mSz:(integer. 74). Y) :. clauses classInfo("midi/midi". duration(X. 107. 32. 24. nt("C5". nt("C#". foreach X= list::getMember_nd (H) do P:write(X) end foreach. unsigned8. X1. 255. !. nt("A#". 63).192. 60). X4= convert(unsigned8.Y= toTerm(X). 66). 8]. F1).tomidi(Music. 24). nt("E".3: Midi generator . N1= list::length(L). 88. duration(D. 0. unsigned8) procedure (i. !. 2. nt("D5". unsigned8. 6. 0.I4= S mod 256. o). unsigned8) procedure (i. Cnt= NC+ N1 + 4. X3. 67). 68). 3. 84. R). nt("Bb". I3). 0. note(_.47. D|Rs]. 0. 81. 2. nt("F". o). X4). X4]. 48. 0.128.N1. 84. tomidi(_. 65). unsigned8). unsigned8*) procedure (i. I3= S1 mod 256. 127. nt("C". o. 77. 0. class facts nt:(string. Y) :.nt(X. nt("B". L). duration:(string. nt("D#". Music) :. X3. tomidi(Rs. unsigned8. duration(_X. 0. o. nt("F#". 71). 70).N1. note(X. 100. 0. NC= list::length(Events). mSz(Cnt. mSz(S. 7. nt("A". N1). H= list::append(MainHeader. 64). 70).0]).0|R] ) :-/* guitar=24. X2. 0. 69). 4. 0. 62). P= outputStream_file::create(File.255. [0. 61). 104. nt("G#". Y < 128. 255. Events. end implement midi Figure 19. L. violin= 40 voice= 52 */ note(N. P:close(). 2. X1.0"). Events= [0. X4) :. 0. 255. nt("D". o). o. tomidi([N. X3.F1. S1= S div 256. 0.206 Tab forms and other goodies implement midi open core class predicates note:(string. 72). o). X2. 89.

but believe me.Chapter 20 Bugs Old computers were based on relays. in this chapter. Visual Prolog is good at pinpointing bugs. and unreliable. the Visual Prolog compiler frequently returns error messages. 1945. a moth flew into one of the relays of Harvard Mark II computer and jammed it. and seldom try to analyze the error messages. that are bulky electrical devices. you should be thankful to the designers of such a compiler that gives you a chance to clean up all the stains that can mar your program. except perhaps Clean. typically incorporating an electromagnet. Therefore. if you do not learn how to deal with its error messages. you will find debugging a random walk that almost never leads to success. you will learn how to interpret messages from the compiler. slow. on September 9th. As I have said. bug became the standard word to indicate an error that prevents a computer from working as intended. Therefore. Notwithstanding. which is activated by a current in one circuit to turn on or off another circuit. instead of generating code and running the corresponding programs. Due to bugs. In fact. 207 . Students don‘t appreciate this constant nagging about errors. From that time on. Computers made of such a thing were enormous. the Visual Prolog compiler gives more bug alerts than any other language.

class predicates fact:(unsigned) -> unsigned. stdio::write(fact(N)). binum(N. if you try to compile the program of figure 20. the compiler may refuse to comply. end implement main goal mainExe::run(main::run). P1= convert(unsigned. calculate a binomial number. you will get the following error message: error c504: The expression has type ’::integer’.if N < 1 then F=1 else F=N*fact(N-1) end if. stdio::write("N: "). if you need to use the unsigned integer which results from the factorial function in order to. stdio::nl. you must also convert the output of factorial to an integer. implement main open core clauses classInfo("main".1. "bugs"). which is incompatible with the type ’::unsigned’ The error will disappear if you explicitly convert each input argument of binum/3 to an unsigned integer. clauses fact(N) = F :. R = convert(integer. P.console::init(). however. N= stdio::read(). N).1 Type error The program below has no bugs. For instance. . P). say. fact(N1) div (fact(P1)*fact(N1-P1))).208 Bugs 20. run():. R) :-N1= convert(unsigned.

then you need to define a getweight/2 procedure. Therefore. that will retrieve the weight values. Below. clauses fact(N) = F :.1: A buggy program 20. weight/2 should act like a procedure. if you try to compile the program of listing 20. Visual Prolog declares certain predicates as procedures. .if N < 1 then F=1 else F=N*fact(N-1) end if. R). "bugs"). Use it as a model for getting around a situation.20. is actually ’nondeterm’ It is true that the weight/2 fact predicate is indexed by its integer argument. integer) procedure (i. stdio::write("P: ").console::init(). binum:(integer. run():. class predicates fact:(unsigned) -> unsigned. which is declared as ’procedure’. This is the case of the run() predicate that appears in all console programs.2. 209 Figure 20. binum(N. This means that you cannot call a nondeterm predicate from run(). integer. P= stdio::read(). N= stdio::read(). stdio::write("N: ").2 Non-procedure inside a procedure implement main open core clauses classInfo("main".2 Non-procedure inside a procedure There is another bug that poses many difficulties to beginners. P. o). you will get the following error message: error c631: The predicate ’nonprocedure::run/0’. P. This means that. R) :. stdio::write(R).R = fact(N) div (fact(P)*fact(N-P)). you can see how getweight can be defined. stdio::nl. where you need to call a nondeterm predicate from a procedure. i. binum(N. However Prolog is impervious to wishful thinking. given its integer argument. end implement main goal mainExe::run(main::run).

3 will issue an error message: error c634: The condition part of if-then-else may not have a backtrack point (almost determ) The error will disappear if you define member as a determ predicate: class predicates member:(string.console::init(). clauses member(X. end implement main goal mainExe::run(main::run). stdio::nl. real). real) procedure (i. 3. Bugs 20. type specification can be carried out by the procedure hasdomain(type. "nonprocedure"). getweight(1.4 Impossible to determine the type There are occasions when one needs to specify the type before the instantiation of a variable. X). weight(0. Xs). 20. ! or R=0. Var) . the program in figure 20. o). Therefore. the condition of an if-then-else construction must be a determ predicate. [_|Xs]) :.3 Non-determ condition Prolog has constructions that do not accept nondeterm predicates. R).!. [X|_]) :. stdio::write(X). 2. clauses classInfo("main". -1. weight(2. For instance.member(X. class predicates getweight:(integer. run():. R) :.0).0). weight(1. member(X.210 implement main class facts weight:(integer.weight(I. string*) determ. getweight(I.5).

console::init(). ["a". run():. [X|_]). member(X. "nonprocedure"). o). 3. string*) nondeterm.3: Deterministic predicate required.4 Impossible to determine the type implement main class facts weight:(integer.0"). Ans) :. run():console::init(). stdio::write(Ans).20. 2. "i".2: A bug caused by a non deterministic predicate implement main class predicates vowel:(string. .0). weight(1. real). Ans). stdio::write(X). clauses classInfo("main". weight(2.if member(X.5). -1. X). member(X.0). weight(0. end implement main goal mainExe::run(main::run). string) procedure (i. member:(string. "u"]) then Ans= "yes" else Ans="no" end if. "e". clauses classInfo("main". Xs). 211 Figure 20. Figure 20. "ifexample-1.member(X. weight(1. "o". end implement main goal mainExe::run(main::run). stdio::nl. vowel("e". [_|Xs]) :. vowel(X.

end implement main goal mainExe::run(main::run). X= stdio::read().0").console::init(). 1) :. you will get an error message. as in the example below. You can fix the bug by declaring factorial as an input/output procedure. 20. integer) procedure (i. F1). stdio::write(F). F). clauses classInfo("main". N*F1) :. s/he will get an error message stating that it is impossible to determine the type of the term X.212 Bugs In the useless program listed below. class predicates factorial:(integer. o). N= toTerm(stdio::readLine()). stdio::write(X.console::init(). "vartest-1. X). X. factorial(N.0"). factorial(0.factorial(N-1. implement main class predicates factorial:(integer. Since this simplified assumption is more often than not wrong. X). stdio::nl. "dataflow-1.!. end implement main goal mainExe::run(main::run).5 Flow pattern When you do not declare a flow pattern. Prolog assumes that all arguments are input variables. implement main clauses classInfo("main". if one removes hasdomain(integer. X). run() :. hasdomain(integer. . integer). run():. factorial(N.

let us describe the program. The main concept of a B+Tree database are: Indexes that are stored in a special data structure called B+Tree. All you need to know about B+Trees is that they store things in order (for instance. 213 . When things are in order. T). T= listEdit_ctl:getText().1 Database manager Databases are very useful in any commercial application. Domains give the register structure. string.Chapter 21 A Data Base Manager This chapter shows how to create a form with edit fields. After this brief introduction.Key= keyvalue_ctl:getText(). whose names you must discover. the contact domain is defined as domains contact= email(string. string). In our example. 21. However. it is easy to search for them. and use to handle the window. onSave(_Source) = button::defaultAction() :. I strongly recommend that you browse the Internet for a book on the subject. and use its contents to feed a data base. emails::insert_info(Key. Email= email_ctl:getText(). Email. in alphabetical order). References are pointers to the places where registers are stored. the most important thing that you will learn is how to access the fields from the form. as in the example below. like words in a dictionary. If you do not know much about databases. Edit field windows are stored as fact variables.

you will find the listing of emails. createNewDB(Fname) :. In the present step. Build the application. that is the name of the menu item. Build the application. This package is inside the folder pfc. • Create a class emails at the root of the Project Tree. and choose New from the pop up menu.mnu. in order to read a file name.mnu.214 A Data Base Manager • Create a project whose name is emailBook with Object-oriented GUI. On the TaskMenu dialog. createNewDB(Fname) :.cl and emails. You must develop your programs step by step. When the file selection dialog asks you for a file name. "Create".*". _). Untick the Creates Objects option. Build the application. write Create. to Project Window\TaskMenu. add the package chainDB. oncreate(_. ". go to the Project Tree window.emails::data_base_create(Fname). you have added a new Create menu item to TaskMenu. run it.file::existfile(Fname). "*. • Using the option File/Add from the task menu. that you should insert in the appropriate files. !. • Add a new item to the application task menu.pro. Build the application. In order to accomplish this task.win\Code Expert\Menu\id_create. • Add the following code class predicates createNewDB:(string FNAME). _MenuTag) :-FName= vpiCommonDialogs::getFileName("*. You have also inserted code into onCreate. and click on the Create option of the application menu. []. On the appropriate field. In section 21.".dbs"].2. clauses oncreate(_Source. !. . predicates oncreate : window::menuItemListener. right click the mouse. ["Email". checking whether each new step is correct before going forward. in the installation directory. createNewDB(FName). _X). and create a corresponding database. left click on TaskMenu.

choose the option File/New in New Package. !. and enable the &Open\tF8 menu item. Then. the program will create a mails. and insert the form below onto the root of the project. openDB(_). openDB(Fname) :. emails::data_base_open(Fname). Build the application.1 Database manager 215 type mails.win/Code Expert/Window/onDestroy. clauses onFileOpen(_Source. from the VDE task menu. before turning off the computer.".dbs"]. to ProjWin/TaskWindow.win/Code Expert/Menu/TaskMenu/id_file/id_file_open. predicates onFileOpen : window::menuItemListener.file::existfile(Fname). to Project Tree/TaskWindow. "Open". Now that you know for sure that nobody will forget to close the data base. . _). you must open it. you must close it.emails::data_base_close(). ". ["Email". From the Project Window.dbs file. []. "*. To make sure that we will not forget to close the data base before exiting the application. _MenuTag) :-FName= vpiCommonDialogs::getFileName("*. _X). let us add the snippet clauses onDestroy(_) :. Whenever you want to use a data base. click on TaskMenu. onFileOpen(_.21. !. you can proceed to open it. If everything follows the script.*". openDB(FName).dbs.mnu. After using it. Add the snippet class predicates openDB:(string FNAME).

Therefore. to the ClickResponder of button:list_ctl. _). _CreationData) :-WlboxHandle=listEdit_ctl:tryGetVpiWindow(). Email= address_ctl:getText(). "Commerce"]). !. The last step of this project is to add code to the Save.— _^ Cancel Help 111 The form has a list box. Enable the File/New option of the application task menu. Finally. to ClickResponder of button:save_ctl. X:show(). add clauses onListClick(_Source) = button::defaultAction :-emails::db_list(). _MenuTag) :-X= insertForm::new(S). In order to achieve this goal.216 insertForm [Xj —i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i _____________________________________________ A Data Base Manager = === ========================================== ========= | ====== EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE Save List ^. and that is it. to TaskWindow/Code Expert/Menu/TaskMenu/id_file/id_file_new. Build the application once more. . Email. and List buttons. to the ShowListener of listEdit:listEdit_ctl. T= listEdit_ctl:getText(). emails::insert_info(Key. vpi::lboxAdd(WlboxHandle. add onSaveClick(_Source) = button::defaultAction() :-Key= key_ctl:getText(). add the snippet onFileNew(S. onListEditShow(_. add the snippet clauses onListEditShow(_Source. ["Person". Therefore. T). it is necessary to add a list of options into it.

o. clauses classInfo("db/emails/emails". !. 1). end class emails %File: emails. ChainDB:bt_close(BTREE). ContactName)). chainDB::in_file). o). assert(dbase(ChainDB. data_base_close:(). ChainDB:bt_create("email". BTREE)). . ChainDB:db_close(). ContactName. chainDB::bt_selector) determ. data_base_open(FileName) :-ChainDB= chainDB::db_open(FileName. ChainDB:bt_open("email". 40. string Tipo) procedure (i. string). 21.0"). data_base_open:(string FileName). string Contact. string Contact. insert_info:(string Name. string. db_list:().21. data_base_create:(string FileName) procedure (i). "1. !. ContactName). ChainDB:bt_close(ContactName). chainDB::in_file).cl class emails open core predicates classInfo : core::classInfo.dbState dbase:(chainDB. del:(string). class facts . data_base_create(_). data_base_close(). data_base_create(FileName) :-ChainDB= chainDB::db_create(FileName. ChainDB:db_close(). string Tipo). data_base_close() :retract(dbase(ChainDB.2 btr class 217 21.2 btr class %File: emails.pro implement emails open core domains contact= email(string. data_base_search:(string Name.

_. ChainDB:term_delete("Contacts". clauses getInfo(ChainDB. !. o). RefNumber). "none"). ChainDB:ref_term(Ref. ". Email) :-ChainDB:ref_term(Ref. Ref). ChainDB:key_insert(BTREE. Name. !. stdio::write(Name. insert_info( _. getInfo(ChainDB.218 A Data Base Manager insert_info(Key. !. del(_Key). Tipo). stdio::nl. Term). ChainDB:key_first(BTREE. "none"). Email). dbLoop(). Term= email(Name. Email. Key. Email. Ref). ChainDB:key_search(BTREE. Ref). Term= email(Name. Tipo). string) procedure (i. _). Ref). "none". del(Key) :-dbase(ChainDB. chainDB::ref. !. Term).dbase(ChainDB. stdio::nl. class predicates getInfo:(chainDB. dbLoop:(). Email). Tipo) :. ChainDB:key_delete(BTREE. Ref). db_list() :-dbase(ChainDB. Tipo) :-dbase(ChainDB. Name. !. _). db_list() :. Email). Email. data_base_search(_Name. Ref). end implement emails . Ref. "none". dbLoop(). getInfo(ChainDB. Contact. stdio::write(Name. o. Key. Ref. _. BTREE). i. ChainDB:chain_insertz( "Contacts". Ref. ". string. Name. Contact. getInfo(_. Name. BTREE). ChainDB:key_next(BTREE. dbLoop() :. data_base_search(Name. Email). RefNumber). ". email(Key. ". Key.dbase(ChainDB. BTREE). ChainDB:key_search(BTREE. BTREE). dbLoop(). BTREE). stdio::nl. !.stdio::write("None").

21. and ChainDB. _).e. data_base_create(_). and the Btree pointer from the fact database. Finally. the object is stored in ChanDB. Tipo). we have been describing predicates that administrate the database. RefNumber). and closes both the BTree. The object is stored in ChainDB. one calls bt_create in order to obtain a BTree. ChainDB:bt_close(ContactName). Key. One opens the database with the help of a predicate that is nearly as simple as the one used to create it. ChainDB:bt_close(BTREE). the data_base_close predicate retracts the database manager. _. RefNumber). chainDB::in_file). Email. !. one closes both the BTree. teh BTree package instantiates the variable ContactName with a pointer to the BTree. BTREE)). which is used to open the email-Btree. chainDB::in_file). !. and returns an object that can be used to handle it. assert(dbase(ChainDB. ChainDB:db_close(). data_base_close(). Email. ChainDB:db_close(). assert(dbase(ChainDB. ContactName)). From ChainDB. ChainDB:bt_create("email". ChainDB:chain_insertz( "Contacts". and the database. 21. The predicate db_open opens the database stored inside FileName. insert_info(Key. ContactName)) When the user kills the application. Tipo) :. 1). . 40. data_base_open(FileName) :-ChainDB= chainDB::db_open(FileName. it creates a database inside FileName. ContactName.3 The database manager The function that creates the database is very simple: data_base_create(FileName) :-ChainDB= chainDB::db_create(FileName. Both ChainDB and the BTree pointer are stored in a fact predicate. insert_info( _. email(Key. i. Up to this point. BTREE).dbase(ChainDB. and returns an object to manipulate it. ChainDB:key_insert(BTREE. !. ChainDB:bt_open("email". The method db_create/2 does what it means.. for future references.3 The database manager 219 21. ContactName).retract(dbase(ChainDB. now we will describe the method that one can use to insert data into the database. data_base_close() :.

The chain_insertz predicate stores the portfolio onto the "Contacts" chain. once you know the basic principle of database management. the second argument contains an email. Contact. As any filing system. each one containing data that one wants to store. data_base_search(Name. Term). the chain of portfolios is named "Contacts". corresponding to a given Name. BTREE).220 A Data Base Manager The database is a filing system. Tipo). ChainDB:ref_term(Ref. one searches the BTree. string). "none"). and allows a potential user to discover where the desired information is stored. string. data_base_search(_Name. and I will not linger on it. To search a Contact-email. and the third argument informs the type of contact one has with the entity associated with the database entry. once in possession of the reference number. it has two components: a chain of portfolios. The predicate used to delete an entry is very easy to understand. "none".dbase(ChainDB. . that points to the different portfolios. Ref). Term= email(Name. The RefNumber will be stored in alphabetical order into the BTree. it is straightforward to obtain the portfolio. The predicate that lists the contents of the database in alphabetical order is much more complex. but not difficult to understand. !. Name. Contact. and returns a RefNumber to its location. In the example database. each portfolio has the following form: email(string. ChainDB:key_search(BTREE. The first argument of email holds the name of a contact. and an alphabetical index. Tipo) :. in order to find the reference.

Dr. Visual Prolog is used in large commercial and industrial critical systems. In fact. You bet that one cannot afford a failure in such a system due to type errors. In critical situations. you 221 . An old book. Wellesley Barros.1 Grammars Prolog excels in language processing. but you can easily improve it. that is slightly different from Visual Prolog. although programming in Visual Prolog. Most books deal with standard Prolog. and document preparation. was written by the Argentinean scientist Veronica Dahl(see [Abramson/Dahl]). and programming techniques. and out of print. In the mean time. In any case. compiler writing. the language was invented with language processing in mind. For instance. I will talk about a few books on Prolog. Another reason is that great computer scientists were very enthusiastic about Prolog in the eighties and nineties. since most students hope to get material like this tutorial from the Internet. has designed and programmed a large system for Hospital administration in Visual Prolog. His compiler is not a fully fledged tool. While standard Prolog was designed for fast prototype of small applications and for testing ideas. I cannot find any modern book that comes close to [Coelho/Cotta]. You will notice that the books are somewhat old. This compiler allows you to write applets in Prolog. for instance. These scientists wrote books that are hard to beat. One reason for this is that people do not buy technical books as often as before. Cedric de Carvalho wrote a Prolog compiler that generates Java byte-code. type checking and type declarations are very important. 22. one of the greatest modern linguists. you can profit from ideas presented in books based on standard Prolog.Chapter 22 Books and articles In this chapter. that you may find in your local library.

You can also port the compiler. Although I do not think that his version of Prolog is usable for serious applications. You can use the same approach to call it from Visual Prolog. if you like its features. a computer scientist. A book that is not specialized in Natural Language Processing. if you need to learn about databases. but you should get a used copy. and it is not typed. If you want to read an advanced book on the subject.cs.222 Books and articles will learn a lot about compilation. you should read the book The Art of Prolog (see [Sterling and Shapiro]). There you will find many good ideas on databases and Prolog.dk Another book on Natural Language Processing with many interesting approaches to grammar formalism is [Pereira/Shieber].2.2. you can call the XSB DLL from Visual Prolog! The XSB page shows how to call the DLL from Visual Basic. and [Pereira/Shieber] talk to students that are learning the difficult art of Language Processing. Non Deterministic Programming.pdc. at Stony Brook University. [Abramson/Dahl] wrote it for specialists. The address is http://netprolog. a database oriented Prolog. XSB provides a set of tools to export its functionality to other languages. List Operations. since it relies on other tools for building GUI. It is a classic.3 Programming Techniques If you are having a hard time with concepts such as Recursive Programming. The address is http://www. and tools to prototype them. and Parsing. to VIP 6. The book [Warren] is out of print.html By the way. In fact. Cuts. is the main proponent of using Prolog as a database engine. etc. This book is more didactic than [Abramson/Dahl]. but gives a good introduction to it is [Sterling and Shapiro]. a good option is the book by [Gazdar/Mellish]. 22. written in VIP 5. The ideas presented in this book can be easily ported to Visual Prolog. You can start reading Cedric‘s paper in [Cedric et all]. Java. it is not compiled (it is not easy to write a beautiful application in XSB). David Warren leads a team that develops XSB. 22. Therefore. I still strongly recommend a visit to the XSB page. In Visual .sunysb. parsing.edu/~sbprolog/xsb-page.2 Databases David Warren.

22.3 Programming Techniques 223 Prolog. you can even improve the original programs. This book deserves a new edition. It is also an anthology. Try. by [Coelho/Cotta]. It is a kind of FAQ: The authors state a problem. My favorite book on Prolog by far is Prolog by Example. and make a xerox copy. and try hard. to get a used copy. and present the solution. one of my students was able to create diagrams for the circuits described in Chapter 2 of [Sterling and Shapiro]. For instance. ask permission from the authors. If you are not able to get a copy. . The problems and solutions were proposed and solved by great computer scientists.

224 Books and articles .

Part II Artificial Intelligence 225 .


In fact. green. everything.e. Integrity Attitude Safety informs whether the object is whole.. claiming that search is ubiquitous. For instance. Each feature has one or more attributes. or unmounted.Chapter 23 Search Patrick Henry Winston. For example. wich are the coordinates of a 227 . let us start our study of Artificial Intelligence from search. 23. Euclid defined point as an entity whose sole feature is its position. can be reduced to search. However. Therefore. from robot motion planning to neural network. the expression problem solving refers to the analysis of how computers can use search to solve problems in well-circumscribed domains. it has a set of features that determines its situation at a given instant. i. author of a very famous book of LISP. says whether the object is protected against destruction. like Winston. in order to define the state of an object: Color: Red. Therefore. blue. one can use other features besides position. gives the direction the object is facing. Nothing could be closer to the truth. starts his exploration of Artificial Intelligence with search. the state of a punctual object is given by its coordinates. etc. An object has states. the position has three attributes. and values for the attributes.1 States In artificial intelligence. One question arises from this definition: What does an intelligent program inspect in its search for the solution to a problem? It inspects a maze of states connected by operations that cause feature transitions. in general.

and each possible transition from one state to another is described by a branch of an inverted tree.1 is the operator that changes state b into e. 23. k. The branches that connect two nodes are the operators that cause the transition from one state to another. The artificially intelligent program starts at an initial state and uses the allowable operators to move towards a goal state.1. the branch that is labeled 3 in figure 23. one can say that state is a snapshot in time. Figure 23. d.1. c. Each attribute that one can change to solve a problem is called degree of freedom. g. Then a point in a 3D space has three degrees of freedom. in a 2D space. therefore. i. For instance. f. 200) gives valid values for the position. j.228 Search point. e.2 Search tree Search tree is a popular diagram. Operator is a procedure that can be used to make the transition from one state to another. When a node X can be obtained from another node Y using only one . the nodes b. and m are the states that the object may go through. h. you can see a picture of a search tree. In figure 23.1: A search tree In figure 23. and all transitions that lead from one state to another is called state space. A set of all states that the objects under consideration can take. To make a long story short. the tuple (50. where each state is represented by a labeled node (identifier inside a circle). the position attributes can have values in the Cartesian product R × R.

and two white pieces are arranged as shown in the figure. and the most obvious way to find the path is to go from city to city until finding one that matches the goal. Therefore. The black pieces are separated from the white ones by a space. . The figure on the right hand side shows a step by step solution of this problem. The problem is solved when one finds a path that leads from the root to the goal. Two black pieces. This process is called search.2 Search tree 229 Figure 23.2: Puzzle operator. In figure 23. The relative positions of the pieces. When a node has no daughter. the node c is daughter of b. and the operators are similar to roads connecting the cities. and the empty space. since one can obtain c using the operator 1. The goal E5 is at the bottom of the figure. One wants to place the black pieces between the white pieces. the objects of interest are restricted to the four pieces.23. like the ones used in the game of checkers. define a state. A node that has no mother is the root of the search tree. and of the empty space. one says that X is daughter of Y. or that Y is mother of X. landing on an empty space.2. Two operations are available: (1) Slide a piece to an empty space. A more concrete example will help you to understand the concepts that we have studied above. One could say that the states are like cities on a map. The initial state E1 is shown at the top of the figure. you can see a search tree for the puzzle that was described above. In the problem that we want to solve. and (2) Jump over a piece. it is called a leaf.

3 Breadth First Strategy The search is said to be exhaustive if it is guaranteed to generate all reachable states before it terminates in failure. and ensures that the space of possible operations will be examined systematically. containing the nodes that are one branch away from the root. Finally. prtSolution:(path). o). "k")|_]. queue= path*.1. path) determ (i. string). . class facts operator:(integer. string). string. solved:(path) determ. The program that performs the search operation has a parameter called Queue. containing a list of candidate paths. path) nondeterm (i. one starts by examining section (c-d-e). "breath"). prtSolution(L) :-foreach P= list::getMember_nd(list::reverse(L)) do stdio::write(P). implement main domains node= r(integer. path= node*.L= [r(_. stdio::nl end foreach.230 Search 23. clauses classInfo("main". class predicates bSearch:(queue. solved(L) :. nextLevel:(path. string). Each path is represented by a list of nodes. In the tree of figure 23. this method is called the Breadth First Strategy. wich are two nodes away from the root. where a node has the form r(integer. the search engine visits section (k-m). o). One way to perform an exhaustive search is by generating all the nodes at a particular level before proceeding to the next level of the tree. Then one goes to section (f-g-h-i-i).

"e").Solution) :-if solved(T) then Solution= T else Extentions= [Daughter || nextLevel(T. "g". N)|Path]. Daughter). Solution) end if. operator(7. "c"). "d"). L) then prtSolution(L) else stdio::write("No solution!"). the robot has visited only one node. ExtendedQueue= list::append(Queue. operator(6. bSearch(ExtendedQueue. operator(8. "h"). "f"). L) At this point. operator(5. Then the extensions of node "c" are appended to the end of the Queue. "b")]]. "e". "b")]]. "k"). "c". Daughter). and the extensions are appended to the end of the Queue: bSearch([ [r(1. "b")]]. [r(3. nextLevel([r(Branch. [r(Op. "b". operator(9. to wit. end implement main /* breath*/ goal mainExe::run(main::run). "e". "b")].r(Branch. if bSearch([[r(0.3 Breadth First Strategy operator(1. "d"). bSearch([T|Queue]. operator(4. . "g". Extentions). "c". 231 run():. "g"). Daughter)]. "b". not(list::isMember(r(Op. "m"). operator(10. that starts and ends at the root: bSearch([[r(0.Path)). L) Since this path does not lead to the goal. "e"). N)|Path]):-operator(Op. "b". "b")]. the Queue has a single path.23.r(0. operator(3.r(0. it is extended to every daughter of "b". "c". "i"). Daughter).console::init(). [r(2. "c"). operator(2.r(0. "j"). N. stdio::nl end if. Initially. "b".

"f"). "b")]. "g"). "c"). and prints each one of its members.232 bSearch([ [r(2. "e"). [r(9. "c"). [r(5. L) Nodes "h". "b")]. "b")].r(3. [r(10. "m"). [r(5.r(3. "b")]. "c"). "e"). [r(5.r(0. [r(8. r(3. "f"). "c").r(0. "k"). r(3.r(3.r(0. "b")]. "e").r(0. r(5. "i").r(0. "h"). "b")]. "h"). "b")].r(0. "c"). [r(7. "g"). "i". "b")].r(0. "b")]]. "c").r(0. without leaving offspring. "c"). "e"). [r(6. stdio::nl end foreach. "j"). "c"). "e"). r(5.r(0.r(0.r(0. "g"). "h").r(0. reverse this path. "k"). "b")]. The search ends when the algorithm finds the path [r(9. [r(3.r(0. L) Search Node "d" is visited. "c").r(0. "c"). "b")].r(0. "b")].r(3. "b")]]. "e"). "h").r(0. [r(4. "c"). "b")].r(3. The daughters of "g" are added to the end of the Queue. "b")]]. L) Node "f" is removed from the Queue.r(3. "d").r(3. "g").r(0. "b")]]. "b")]. L) The daughters of "e" are appended to the end of the Queue: bSearch([ [r(4. "g"). "b")]. and "j" are visited in turns. "c").r(3. "g"). bSearch([ [r(6.r(0. The final result which comes on the screen is shown below. "j"). "c"). "b")] The procedure prtSolution(L) :-foreach P= list::getMember_nd(list::reverse(L)) do stdio::write(P). r(5. and removed from the Queue. bSearch([ [r(3.r(3. r(3. [r(6.r(0. "f"). [r(6. but since it has no daughter. [r(8. r(3. "i"). [r(7. "b")].r(3. it is simply removed from the Queue. . [r(4.r(0.r(3.r(3.r(3.

piece= e. stt) nondeterm (o. . path) nondeterm (i. st(B.C.B. st(A. st(e.w.D). implement slide domains node= r(string.C.b. nextLevel:(path."k") D:\vipro\aityros\aiprogs\breath\Exe>pause Press any key to continue. operator("jump".e. operator("jump".D)).e.e. st(A.D)).C. stt). piece)."b") r(1. prtSolution(L) :-foreach P= list::getMember_nd(list::reverse(L)) do stdio::write(P).3 Breadth First Strategy r(0.B.C.C..D).D).e.st(A. stt. 233 At this point.B.B."g") r(9. solved:(path) determ.D)).B. operator("slide". solved(L) :.B.e.C. path) determ (i.b.e.A.C. operator("slide".B. path= node*. you are ready to try the algorithm on a real problem. i. stdio::nl end foreach. queue= path*.B.C.C.A.st(A. stt= st(piece."c") r(5.B. the slide puzzle. o).D)). clauses classInfo("breath".A. piece.C. "1.e))|_].D).0").st(A.D)). st(A.L= [r(_.C.23. operator:(string.D)).A.e.C..e.C.b.e. piece. st(e.D). operator("slide". operator("slide".w. o).B. piece. operator("slide".D)). st(A.D).C. st(w.B. st(A. st(A.B.e. class predicates bSearch:(queue. prtSolution:(path).B. to wit.D).st(A. st(e.e. o).

e(). who has an Erdos number equal to one. The problem is that the Americans insist on writing it with a Z.e.e. end implement slide goal mainExe::run(slide::run).B.C.b().b())) r("slide".st(w().st(A.C.b().B.B.D).st(w(). operator("slide".e(). .D.Solution) :-if solved(T) then Solution= T else Extentions= [Daughter || nextLevel(T.st(w(). ExtendedQueue= list::append(Queue.w.e.B. st(w. N)|Path].4 Depth First Strategy Analyze1 figure 23.B.C.D.B.b(). 23. r("0".D)). Search nextLevel([r(Branch.st(A. operator("slide".B.b))]].st(A.w().b.D.st(A.D.1.e)).B. . N.b())) r("slide".st(A.b().b())) r("jump". [r(Op. bSearch([T|Queue].w(). I know that analyse should be written with an S.D)).b().e)). . since he worked directly with Paul Erdos. goes to its leftmost daughter.console::init().B.B.C.B.C. as printed by the computer.B.b())) r("jump". Only iYes. That makes me remember Professor Wolfgang Fuchs.b().D)).st(A. The solution of the puzzle.C.C.D). run():.e.st(e.st(A. if bSearch([[r("0". after visiting "b". operator("slide". operator("jump".e())) D:\vipro\aityros\aiprogs\slide\Exe>pause Pressione qualquer tecla para continuar. is presented below.C.C.w(). not(list::isMember(r(Op.w().st(A. Daughter). operator("jump". N)|Path]) :-operator(Op. After visiting "c". which is "c".r(Branch. Daughter)].st(w(). since it comes from dvdXuaic.e.st(A.A.st(A.D.D).e.e.e).B.st(w().w(). it goes to "f".e).st(A.C. Solution) end if.st(A.C)). The depth first strategy.e.C.B.D)).D).e. bSearch(ExtendedQueue.C. Extentions).e. Daughter).e().C. a Greek word.st(A.Path)).D). L) then prtSolution(L) else stdio::write("No solution!"). stdio::nl end if. Daughter). That makes my own Erdos number be as low as 2. operator("jump".e().234 operator("jump".

Solution) :-if solved(T) then Solution= T else Extentions= [Daughter || nextLevel(T. I also changed the name of the predicate to dSearch for obvious reasons. Daughter)]. Solution) end if. . However. Here is the only necessary modification made to the previous program: dSearch([T|Queue]. This weakness is corrected by the heuristic strategy. Queue). the only problem is the awful pronunciation that French people insist on maintaining. The evaluation function is given by the following formula: f(N) = g(N) + h(N) In this formula. ExtendedQueue= list::append(Extentions. that evaluates the cost of going from the root to the goal passing through the node N. instead of appending them to the tail. g(N) is the known cost of going from the root until the N node. He said that French is certainly the most beautiful and sweet sounding language in the world.23. To implement this kind of strategy. The heuristic strategy sorts the Queue in such a way that paths with lower values of f(X) are visited first. Let us use the heuristic strategy to find the path between two cities on the map below. Fuchs was my minor adviser. before jumping into N. because Dr. all you need to do is to append the children of a given node to the front of the Queue.5 Heuristic search 235 after visiting all descendants of "c". the depth first strategy visits "g". but to tell the opinion that Dr. 23. dSearch(ExtendedQueue. it is not to brag that I have a low Erd¨os number that I am writing this footnote. the function h(N) gives the estimated cost of going from N to the goal node.5 Heuristic search The search strategies that we have examined until now do not make any use of domain specific knowledge to choose a branch to investigate. Fuchs had about the French language.

5. After that long digression into the realms of translation. let us return to heuristic search. Pushkin from Russian into one of those second rate languages that I learned. an underpopulated country. where Γ is a letter of the Russian alphabet. but for people too. Dr. Pushkin tried to explain the rules of chess. 2. before starting. N. 6). The translator came out with the following rendering of the original: The knight moves along an upsidedown L-shaped path. A guy or gal has translated a book by a certain V. a second rate language spoken only in Paraguay. xy("b". "b" ). and have learned quite a few of them. Two place facts describe the one way roads that connect the cities: op("a".236 Search However. the Science of Creative Thought. . "f"). etc. "m"). op("m". The book‘s title was: Heuristics. Natural language processing is difficult not only for computers. in order to use the game as a test bed for Artificial Intelligence. The cities will be represented by their coordinates: xy("a". When I read Pushkin‘s book in translation. When I was a teenager. 4). Homeric Greek. specially if you do not know the subject treated in the text well. I would like to tell a story. I like obscure languages. I understood how difficult is to find a good heuristic function. Latin. op("b". he has said that the knight moves along a Γ-shaped path. Esperanto. For instance. and how much more difficult it is to translate a text from a language to another. I even studied Guarani. For instance. In his explanation. I know Ancient Egyptian.

solve: () procedure. o). string) -> real. Each path is represented by the structure shown below. tree=node*. node) nondeterm (i. .23.S):-if goalReached(T) then S= T else Extension= [E || toDaughter(T. The sorting algorithm has a comparing predicate as its first argument. the second argument gives the value of g(N). it). toDaughter: (node. theGoal: (string) procedure (o).E)]. node) -> compareResult. it) where the first argument gives the value of the heuristic function F for the node. real. it= item*. class predicates getXY:(string.Extension). string). integer. hn: (string) -> real. NewQueue= list::append(Queue. node=t(real. class facts xy: (string. S) end if. and was invented by Tony Hoare. cmp:(node. the queue must be sorted so that the most promising paths come forward. integer. integer) determ (i. implement main /*heureka*/ domains item=r(string. real.o). t(real. it) determ (i. and pushes the most promising branches to the front of the queue. The complete program is implemented below. search: (tree. init:(string) procedure (o).5 Heuristic search 237 You have learned that. prtSolution: (node) procedure (i). BestFirst= list::sortBy(cmp. node) determ (i. op: (string. search(BestFirst. not_in_circle: (string. in the heuristic search. search([T|Queue]. cost: (string.o). goalReached:(node) determ. NewQueue). string). The sorting algorithm that you will learn is very interesting. o. integer).i).

xy("g". "c"). init("a"). op("n". "d"). 7. 5. 4). theGoal("s").YF))) else C= 0. xy("f". hn(N) = HN :. 11. 13. "m"). xy("q". 7). !.theGoal(S). cost(No. getXY(M. X. _). "g"). op("d". _. 12. Path):-not(list::isMember(r("". Path)). Y) :. _) = less(). "s"). XS.6).0"). op("n". "g"). _. !. XN. _)) = greater() :. "p"). xy("b". xy("d". X. op("p". Stt). goalReached(t(_.A=B. t(B. YN). 8). 8. op("c". XF. YS). "n"). "heureka-1. 6). t(B. YF) then C = math::sqrt(((XN-XF)*(XN-XF)) + ((YN .M)|_])):. 1). op("m". op("f". op("b". 4. 2).xy(M. _)) = equal() :. XN. op("p". getXY(NoFilho. _.theGoal(R). 2. _. "q"). NoFilho) = C:-if getXY(No.0 end if. cmp(t(A. "q"). Y). 7. cmp(_. op("b". 2). xy("m".[r(_. if getXY(S._. not_in_circle(Stt. "h"). op("h".YF)*(YN . 2). op("d". "f"). getXY(N.A > B. xy("p". 9. op("a". "n"). "s"). _). xy("s". xy("c". xy("n". xy("a". YN) then HN= math::sqrt(((XN-XS)*(XN-XS)) + ((YN YS)*(YN . cmp(t(A. op("d". "b" ). .YS))) else HN= 0. 10.238 Search clauses classInfo("main". op("q". 6). 11. 3). 4). R=M. xy("h". !.0 end if.

[r("root". NewQueue= list::append(Queue. Child). search(BestFirst.23.S):-if goalReached(T) then S= T else Extension= [E || toDaughter(T. solve():.t(F1.Extension). Path). NewQueue ). end implement main /*heureka*/ goal mainExe::run(main::run). S) end if. N.G. run():. Child). not_in_circle(Child.G1. search([t(hn(E).5 Heuristic search 239 search([T|Queue].N)|Path])):-op(N. G1 = G + cost(N. prtSolution( t(_. F1 = G1 + hn(Child). stdio::nl end foreach.T)):-foreach X= list::getMember_nd(list::reverse(T)) do stdio::write(X)._. Op= string::format("%s to %s".if init(E).console::init(). .[r(Op.[r(B. solve().S) then prtSolution(S) else stdio::write("No solution") end if.0.E)]. BestFirst=list::sortBy(cmp.N)|Path]). toDaughter(t(_F. Child).E)])]. Child).r(B.

240 Search .

which give to each input source a weight that is effectively a positive integer. Their neuron is a binary device. At each 241 . Inhibitory inputs have an absolute veto power over any excitatory inputs.. a synapse converts neuron activity into electrical stimuli that inhibits or excites other neurons. In Europe. you will learn about one of them. whose synapses will activate other neurons. Warren McCullogh and Walter Pitts proposed the first mathematical model for a neuron. One of those countries is Serbia. If the intensity of the incoming signals goes beyond a certain threshold. By the way. In fact. Notwithstanding. at the end of each dendrite. So. and one of the Serbians who did not receive the Nobel Prize is Nikola Tesla. which means tree shoots in Greek. there are very few countries with less Nobel laureates than Spain.. In 1947. scientists believe that a given neuron receives inputs from other neurons through links called synapses.Chapter 24 Neural Networks Spain is not distinguished for its science. to sum up. there are families in France that have twice as many Nobel laureates in science than in all of Spain. Nowadays. the only two Spanish Nobel laureates are counted among the greatest scientists of all time. together with Newton and Archimedes. It receives multiple inputs from excitatory synapses. In this chapter. a neuron collects signals from others through a set of structures called dendrites. with a fixed threshold. Typically. synapse is the Greek word for link. The Spanish scientist Don Santiago Ram´on y Ca-jal studied the physiology of the nervous system and concluded that it was driven by cells that he dubbed neurons. the neuron fires and sends out electrical stimuli through a stem known as an axon. but a country that has the genius of Nikola Tesla does not need Nobel laureates. which splits into the branch-like dendrites.

The sigmoid is defined as: 1 ς(x) = 1+e-x In Prolog.0 2. This scheme was improved by feeding the weighted sum to a sigmoid function.2 0. In this case.8 0.5 . this definition becomes: sigmoid(X)= 1.1) One interesting feature of the perceptron is its learning abilities: You can train the perceptron to recognize input patterns. the neurons are synchronously updated by summing the weighted excitatory inputs and setting the output to 1 if and only if the sum is greater than or equal to the threshold.6 0.4 0. If you plot a sigmoid.1: A three input perceptron 1. Rosenblatt was a professor at Cornell University.0/(1. and x3. and if the result is greater than the threshold. since he passed away many years before my arrival at the university. Figure 24.5x2 + 2. o 3.0 6 Figure 24. it produces a non zero output.0 -6-4-2 0 246 The perceptron adds up the input signals multiplied by a weight (a different weight for each input signal). given enough examples. Let the inputs be x1. which happens to be my alma mater.0x1 .2. However.242 Neural Networks processing step.0 Output k^ a -1.1 above shows a perceptron with three inputs.0+math::exp(-X)). The next major advance in the theory of neural networks was the percep-tron. that is known as final sigma (hence the name sigmoid).0 0. x2. there is an algorithm that modifies the weights of the perceptron so . introduced by Frank Rosenblatt in his 1958 paper. it takes the shape of the Greek letter ς. I did not have the good fortune of knowing him. and taking the value returned as the output of the percep-tron. In fact. the output will be the result of the expression: ς(3x1 + 2.

0. 0. I_1. V) :-eg(E. clauses eg(0. The procedure getWgt has a very simple definition: getWgt(I. I_2. getWgt(1. In Prolog.5).8). predicted_out(E. V= sigmoid(X). weight(1. 0. W). !. .weight(I. The initial weights are fictitious. facts weight:(unsigned. getWgt(2. 1. that uses the formula (^ij) to predict the output value. Here are the examples: facts eg:(unsigned. The weights are stored in a database. 0). getWgt(_I. 1 0). the predicting procedure can be coded as shown below. real). 1. W_1).243 that it can discriminate between two or more patterns. . W_2). a two input perceptron can learn to tell when an and-gate will output 1. The true weights must be found through the learning algorithm.0). and when it will output 0. eg(2. 0. _). weight(2. For instance. 2. 1 1). X = W_0+W_1* I_1 + W_2* I_2. W) :. real. .0). 0). The learning algorithm of the perceptron must have a set of training examples. real). real. getWgt(0. Let us assume that it is learning the workings of an and-gate. clauses weight(0. eg(1. given a set of inputs. 0. W_0). The perceptron has a predicting procedure. 1. 1. eg(3.


Neural Networks

You may ask why one needs to define getWgt at all; it would be easier to use weight directly. The problem is that weight defines a nondeterm predicate, and we need a procedural weight retrieving predicate. By the way, one needs a procedure to retrieve the examples too: egratia(Eg, I1, I2, Output) :- eg(Eg, I1, I2, Output), !. egratia(Eg, I1, I2, Output) :- Ex = Eg rem 4, eg(Ex, I1, I2, Output), !. egratia(_Eg, 1, 1, 0). The learning algorithm is based on the calculation and correction of the error made by the predicting function. The error of a given example is calculated by the following predicate:
evalError(Obj, E) :- nn:predicted_out(Obj, VC), nn:egratia(Obj, _I1, _I2, V), E= (VC-V)*(VC-V).

What we really need is not the error of a given example, but the sum of the errors for each example. One can calculate this total error as shown below.
errSum(Exs, _Partial_err, Total_err) :- acc := 0.0, foreach Eg= list::getMember_nd(Exs) do evalError(Eg, Err), acc := acc + Err end foreach, Total_err= acc.

The computational scheme foreach will pick each example from the Exs list, calculate the corresponding error, and add the result of the calculation to the accumulator acc (which is stored in a global variable). class facts acc:real := 0.0. The weights will be updated through the gradient descent method in such a way as to reduce the error to a minimum. updateWeight(DX, LC, Exs) :- errSum(Exs, 0.0, Err0), PN= [tuple(I, W) || nn:getWgt_nd(I, W)], nn:setWeight([ tuple(P, NV) || tuple(P, V) = list::getMember_nd(PN), V1= V+DX, nn:assertWgt(P, V1), errSum(Exs, 0.0, Nerr), nn:popweight(P, V1), NV= V+LC*(Err0-Nerr)/DX]).

245 Gradient descent is an optimization algorithm that finds a local minimum of a function by taking steps proportional to the negative of the gradient of the function at the current point. At each step of the gradient descent method, the weight is updated according to the following formula: ωn+1 = ωn- γVerror(ω) In this formula, if γ > 0 is a small enough number, error(ωn+1) < error(ωn). If one starts with ω0, the sequence ω0, ω 1, ω2 ... will converge to a minimum. The minimum will be reached when the gradient becomes zero (or close to zero, in practical situations). Imagine that there is a terrain with mountains and valleys. A position on this terrain is given by the coordinates ω 1 and ω2; the heights of mountains, and the depths of valleys represent errors. The training algorithm moves the network from an initial position to a valley, i.e., to a position where the error reaches a local minimum. The ideal situation happens when the network reaches a global minimum. The Americans who serve in counter-espionage like to say that they are the best of the best. That is what one wants for the solution of any optimization problem: The best of the best. Nevertheless, gradient methods more often than not become trapped in a local minimum. This happens because when the network reaches a minimum, it doesn‘t matter whether the minimum is local or global, its gradient comes close to zero. In fact, the algorithm knows that it reached a minimum because the gradient reaches a value close to zero. The problem is that this criterium does not say whether the minimum is local or global. The dictionary says that a gradient gives the inclination of a road or railway. At the top of a mountain or at the bottom of a valley, the gradient is zero. If one uses a level at the top of a mountain or at the bottom of a valley, s/he will not detect any inclination at all. A neural network training algorithm updates the weights of a neuron, until the error stays in some small neighbourhood; then it stops. train(DX, LC, Exs) :- errSum(Exs, 0, Err0), if (Err0 < 0.1) then stdio::write("Total Err: ", Err0), stdio::nl else updateWeight(DX, LC, Exs), train(DX, LC, Exs) end if.


Neural Networks


Neuron description

A neuron like the one shown in figure 24.2 can be described by the following equation: ω1x1 +ω2x2 +ω0 = 0 This is the equation of a straight line. If one uses more entries, s/he will get straight lines in higher dimensions, but they will remain straight lines regardless. Let us plot a logical function known as or-gate. It has two inputs, x1 and x2.



Figure 24.2: A three input perceptron x2 1 The or-gate function produces 1, if either x1 = 1 or x2 = 1. It also produces 1, if both x1 = 1 and x2 = 1. The graphics of the figure 1 show the behavior of the or-gate. What the neural network of figure 24.2 does is to draw a straight line separating the points where the or-gate is 1 from the point where it is 0, as ] x1 you can see from the figure. Then, all that 1 a perceptron can do is to learn how to draw lines in a state space, in order to separate clusters of points with property. The problem is that one often cannot draw such straight a multidimensional space. xor-gate is much more useful than the or-gate for two reasons. First, inputs of the xor-gate can represent logic propositions such as:

0 straight a given lines in The the two

x1 = the machine is on;x2 = the machine is off x1 = the door is open;x2 = the door is closed Since the machine cannot be on and off at the same time, x1 = 1 and x2 = 1 cannot be true; x1 = 0 and x2 = 0 cannot be true either. To describe logical gates, one often uses truth tables that give the output value for all values of the input variables. Below, you can see a truth table for the xor-gate.

24.2 Implementation of a multi-layer network x1 1 1 0 0 x2 1 0 1 0 output 0 1 1 0


You can see from the figure that a single straight line cannot discriminate between the values of an xor-gate. x2 However, two straight lines can separate the values that happen to be zero 1 from values that happen to be 1, as you can see in the figure. Likewise, a single perceptron cannot learn how to calculate the output values of an xor-gate, but a network with more . . than one perceptron, like the one that you see in . x1 figure 24.3, can perform the task. In the next 0 1 paragraphs, you will learn how to use objects to implement a multi-layer neuron network in Prolog.

o k^

Input 1 Input 2

\ ^
/' ' '

XOR gate




^> ^

Figure 24.3: A neural network that can learn how to calculate a xor-gate


Implementation of a multi-layer network
Project Name: neurons UI Strategy: console

• Create a new console project.


Neural Networks

• Select the root of the Project Tree. Choose the option File/New from the VDE Task Menu. This will open the Create Project Item dialog. Select the Class tag from the left hand side pane; create a network class, that Creates Objects. Press the Create-button. Add the class specification to network.cl, network.i, and network.pro.
class network : network %File: network.cl predicates sigmoid:(real) -> real. end class network

Add the class interface to network.i:
%File: network.i interface network open core domains example= e(real, real, real). examples= example*. predicates setWeight:(tuple{unsigned, real}*) procedure. predicted_out:(unsigned, real) procedure (i, o). egratia:(unsigned, real, real, real) procedure (i, o, o, o). getWgt_nd:(unsigned, real) nondeterm (o, o). assertWgt:(unsigned I, real W) procedure (i, i). popweight:(unsigned I, real W) procedure (i, i). usit:( real*, real) procedure ( i, o). setExamples:(examples) procedure (i). getWgt:(unsigned, real) procedure (i, o). hidden:(unsigned, unsigned*, real) procedure (i, i, o). setEx:(unsigned, examples). end interface network

Add the listing below to network.pro. Build the application.
%File network.pro implement network open core constants className = "network/network". classVersion = "". facts weight:(unsigned, real). eg:(unsigned, real, real, real).

R) :.8]. foreach tuple(X. W_0). R) :. hidden(Obj.7. R)). 0). assertWgt(I. Output). W) :. Output).24. popweight(_._)). setWeight(Qs) :-retractall(weight(_. !.!.asserta(weight(I. I1.4. R)).weight(I. V= sigmoid(X)._)). _). setExamples(Es) :.0+math::exp(-X)).2 Implementation of a multi-layer network clauses sigmoid(X)= 1. V) :-hidden(Obj. I1. predicted_out(Obj. []) :. [e(I1. . !. popweight(I.0/(1. setEx(0. I1. Es). 1. egratia(Eg. I_1). !._. W)). I_2). Es). getWgt(0. setEx(N+1. egratia(Eg. !. 1. setEx(_N. I1. W) :. W). setEx(N.eg(Eg.R)|Es]) :-assertz(eg(N. [3. I2. X = W_0+W_1* I_1 + W_2* I_2.0). Output) :.retractall(eg(_. eg(Ex. getWgt(I. I1. [6. R). getWgt(2._. W_1).weight(I. 0. I2. WX)) end foreach.5]. getWgt_nd(I. I2. getWgt(1. W_2). I2. Output) :.retract(weight(I. egratia(_Eg. getWgt(_I. I2. I2. WX)= list::getMember_nd(Qs) do assert(weight(X.Ex = Eg rem 4.

Build the application. W_8). and Run in Window. updateWeight:(real DX. W_5). WA). W_4). WC). V2= sigmoid(X2). real Partial_err. getWgt(A. classVersion). unsigned* Exs) procedure (i. you will find the training program. I2].V) :. X2 = W_6 + W_7*I1 + W_8*I2. 0). nn:network := erroneous. usit( _. !. VX = W_0 + W_1*V1 + W_2*V2. V= sigmoid(VX). V) :-getWgt(0. real LC. clauses classInfo(className. Neural Networks usit( [I1. getWgt(1. W_6). getWgt(3. classVersion = "nnxor". class facts acc:real := 0. I_2.B. class predicates evalError:(unsigned Obj. getWgt(8. hidden(_. . In the main module. and a test run() predicate for the and-gate. W_2). o). _). X1 = W_3 + W_4*I1 + W_5*I2.C]. I_1. getWgt(6.eg(Obj.0. getWgt(2. getWgt(5. real Err) procedure (i.pro implement main open core constants className = "main". XX = WA+WB* I_1+WC* I_2. i). W_0). 0). _. %File: main.250 hidden(Obj. V=sigmoid(XX). i. o). getWgt(7. i. and also for the xor-gate. getWgt(B. W_7). W_1). getWgt(4. end implement network Objects of the network class can play the role of a neuron.[A. V1=sigmoid(X1). errSum:(unsigned* Exs. WB). W_3). real Total_err) procedure (i. !. getWgt(C.

1.0). Err0).nn := NN. Err0). nn:popweight(P. Exs) :.3. LC. train(0. if (Err0 < 0. V). class predicates training:(network. 0. E= (VC-V)*(VC-V).0. V1). WWW= [ tuple(0. foreach Eg= list::getMember_nd(Exs) do evalError(Eg.1. clauses training(NN. Total_err= acc.1. Nerr). 3.0)].nn:predicted_out(Obj. 0.acc := 0.tuple(1. 0]).errSum(Exs. acc := acc + Err end foreach. 2. NV) || tuple(P.tuple(2. clauses train(DX. stdio::nl else updateWeight(DX.0). 2. real) procedure (i. unsigned* Exs) procedure (i. errSum(Exs. tuple(3. W)]. tuple(6.2 Implementation of a multi-layer network 251 clauses evalError(Obj. nn:egratia(Obj. class predicates train:(real DX. real LC. E) :. V1). train(DX. NV= V+LC*(Err0-Nerr)/DX]).2). V1= V+DX.0. 3.0. i.errSum(Exs.001.[0. _I1. Err). i).0).tuple(8.tuple(5. V)= list::getMember_nd(PN). _Partial_err. nn:setWeight([tuple(P. _DX. i.0). LC. _I2.tuple(4. 1.0).1).24.1) then stdio::write("Total Err: ". LC. Exs). errSum(Exs. _LC) :. 0. Exs) end if. 0. W) || nn:getWgt_nd(I. updateWeight(DX. LC. Total_err) :. i).0). real. . nn:setWeight(WWW). VC). Err0).tuple(7.2. nn:assertWgt(P.0. Exs) :. PN= [tuple(I.

1].001.0. stdio::nl.0)]). stdio::nl. stdio::write("xor(1.001. XOR01). AND00).1). and running it.1)=". network::e(0. XOR00).1]. stdio::nl. you will get the following result: Total Err: 0. stdio::nl. XOR10). 0. stdio::nl. stdio::nl. XOR:usit( [1.console::init(). AND01).1). XOR10). stdio::write("xor(0.0. AND:usit( [0. AND:usit( [0. stdio::write("1&&0=". training(AND. AND = network::new(). stdio::nl. stdio::write("0&&0=". stdio::nl. stdio::write("1&&1=". stdio::nl.1. end implement main goal mainExe::run(main::run).0). 0. XOR:setExamples([ network::e(1. XOR:usit( [1.0)=". XOR11). network::e(0.1. XOR:usit( [0.5). stdio::nl.9194034557462105 . network::e(0. AND:usit( [1.1). 24. stdio::nl.1. stdio::nl. AND00). 0. AND:setExamples([ network::e(1.0].0).0.0).1].0)=0.3 Running the two layer neural network After building the neurons application. stdio::nl. AND10). stdio::nl.1. 0. AND10). XOR01). stdio::write("xor(0.08040475166406771 xor(1. AND:usit( [1.09983168220091619 Total Err: 0. network::e(0. XOR = network::new().1)=". XOR:usit( [0.09968265082000113 xor(1. AND11).0.5).0]. XOR00). network::e(1. stdio::nl.0]. stdio::nl. stdio::nl.1)=0. training(XOR.1]. network::e(1. AND11).0]. stdio::write("0&&1=". XOR11).252 Neural Networks run():. stdio::write("xor(1. AND01).0)]).0)=".

Minsky pratically demonstrated a theorem that neural network cannot learn how to do certain things.08891005182518963 0&&1=0. In fact. hoping to ruin Rosenblatt professionally and to cut off all funding for his research in neural nets. 24.1)=0. on the cover of Minsk‘s book (Percep-trons). and it does not matter whether the neural network is natural or artificial. This limitation is not exclusive to artificial neural networks.24.4 A Historical Perspective There are people who claim that. I was not lucky enough to know Rosenblatt. . though I know Minsky well (I interviewed him when I used to double as a newspaper reporter). the reader is challenged to discover whether the labyrinth interlaced walls are connected or not. when Rosenblatt introduced the concept of perceptron. including contacting every group who funded Rosenblatt’s research to denounce him as a charlatan.4 A Historical Perspective 253 xor(0. As I told you. .0922342035736988 1&&1=0. .8712088309977442 1&&0=0.009538209942478315 D:\vipro\aityros\aiprogs\neurons\Exe>pause Press any key to continue.8913291572885467 xor(0. there are things that even our natural neural network cannot learn. and I am sure that such slanders against Minsky simply aren‘t true. the learning algorithm converged to a behavior that is very close to the desired behavior of the xor-gate. Minsky crusaded against him on a very nasty and personal level.09297532089700676 0&&0=0. As you can see. Minsk claims that it is impossible to train a neural network to perform such a task. there is a labyrinth-like drawing. For example. What Minsky and his collaborator Papert did was to point out the weakness of the theory that the intelligence can emerge purely from the learning activities of a neural network.0)=0.

254 Neural Networks .

that are placed in and transferred between the holes during play. and also the seed that s/he would drop in that hole. the player that captures more seeds wins the game. all the seeds from a hole are dropped one-by-one into subsequent holes in a motion wrapping around the board. Two large holes at two ends of the board. In any case. In the process of sowing. Depending on the contents of each hole sown in a lap. the board has a series of holes arranged in two rows. The captured seeds go to the players store. and sows its seeds around the board.Chapter 25 Alpha Beta Pruning Mancala is a family of board games that are very popular in Africa and Asia. one for each player. pots. Mancala games play a role in many African and some Asian societies comparable to that of chess in the West. called stores. At the beginning of a player‘s turn. The holes may be referred to as pits. a player may capture seeds from the board. s/he selects a hole from his/her side. the player can capture its contents. beans. 255 . it is a count and capture game. If the hole contains less than 3 seeds. It is also popular in India. Playing pieces are seeds. are used for holding captured pieces. or stones. specially among the Tamil women. The game of this family best known in the Western world is Kalah. In the variant of Mancala that we are going to learn. or houses. The game also ends if one player has no seeds on his side of the board. The game ends if one player captures at least 10 seeds more than his/her opponent.

Project Name: kalahGame UI Strategy: console . In the analysis. a player is called the Maximizer. so the complexities of the game itself will not interfere with our strategic reasoning. in this case. When reasoning from the point of view of the Minimizer. a function that does not descend to the branches. all one needs to do is to invert the signal of the evaluation function. while the other is the Minimizer. I would like to point out that even in this kind o game.1. However. This process of skipping branches like I and J is called Alpha-pruning. we are going to keep the move generation as a separate class.1 Move generation The most cherished games are those where an oponent is pitted against the other. one does not use a tree. She knows that the Minimizer will play F. since F is the counter-move of least value. Therefore she concludes that B is worth 5 from her point of view. like the one in figure 10. To tell the whole story.. as you can check by reading The Jack of Spades. In order to accomplish it. and apply the same algorithm that was used in the case of the Maximizer. now she proceeds to the analysis of C. hence the name. she can suspend the search. skipping branches is called Beta-pruning. To understand why. let us suppose that the maximizer is analyzing the move B. therefore programmers need a tool to analyze the game. when she discovers that H=3. this tool is the minmax tree (see figure 10. because a move to C will be worth at most 3. Erast Fandorin always win.256 Alpha Beta Pruning 25. evaluation is performed by a static function. the minimizer tries to force the evaluation function to a minimum value. if the node is a leaf. of the tree below. Create a new console project. the Maximizer is supposed to achieve the maximum value for an evaluation funcion. In such a diagram. i.1). Finally. However. E=6 F=5 G=7 H=3 I A J Implementing a game of strategy is a difficult task. in a combat of brains. and she already has 5 in B. computers are not as lucky as the state counsellor.e.

I0). o). stateval:(board. integer. changeSides:(side. integer. stdio::write("Move: ". I1. board) nondeterm (i. positive. integer Pot. integer LastMove. integer. %File: mv.pro implement mv open core clauses prtBoard(t(S. sow:(integer. play:(board. o).!. I6. i. [I0. I4. I5. I1. board= none .cl class mv open core domains side= a. integer.o). I7). P1.i. P2. t( side. I5.o).i. stdio::writef(" %4d %4d %4d %4d\n".i.1 Move generation 257 Build the application in order to insert the main class into the Project Tree. stdio::nl. T). o). stdio::writef("%4d %4d %s\n". I3. newBoard:(side. predicates prtBoard:(board) procedure (i). integer.stdio::write("None\n"). integer) procedure (i. if S= a then T= "a" else T= "b" end if. integer. I4. integer. o. I3. integer Pot. I2. . stdio::writef(" %4d %4d %4d %4d\n".b. i. o). i. o). sowing:(side. board) procedure (i. side) procedure (i.i. prtBoard(_) :.25. I6. board. i. I7])) :. integer) procedure (i. P1. LM). LM. addPot:(side. integer. integer*. Then create a class mv by selecting the option New in New Package from the IDE task menu. end class mv %File: mv. integer* Brd). i. board) procedure (i. i. board) procedure (i. P2. I2.

0. addPot(a. . stateval(t(_.6. LM.list::nth(2. LM. S1). P1. t(Side. L) > 0. changeSides(b.list::nth(0. P1+C+1. 0). sowing(S. LM. _. BB. X). P1. P2. P1.N > 0. P2. P2. sowing(S. P1. PP2). P2. P1. sow(0.!. P2) :. LM. list::nth(K. sow(_. BA. P2. stateval(_.6. BA. PP1. sow(2. C. list::setNth(J. sowing(S. P1. PP2. P1. P2. PP1. NewBoard) :-J= I rem 8. sow(I. _LastMove. !. L) > 0. X). addPot(b. P2. play(t(a. list::setNth(K. L). J= (K+1) rem 8. BB. changeSides(a. Counts= list::nth(J. L) > 0. a). addPot(S. P1. sowing(S. P2-P1) :. list::setNth(K. L). P1. J. _. 0.6. t(a.N>0. LM. X) :. C < 3. P2. NuB). _. P2. t(a. P1. play(t(a. K. P1.!. BA) + 1. -1. t(Side. BA. play(t(a. _). BB. P1. X). BA). X) :. BB)) :-changeSides(S. C= list::nth(K. BB). P2+C+1). P1. P2. BA). Counts. 0. sowing(Side. P1. P2. LM. P2. !. LM. L). N. P2. 0. t(a.6. P1.258 Alpha Beta Pruning newBoard(Side. L). N. B).list::nth(1.6.!. NuB) :. LM. T). sowing(S. K. P2. BA. b) :. C. X) :. P2. !. C. J. LM. N-1. C > 0. K= (J+1) rem 8. P2. B. P1. N-1. BB). J. P2. B). P1. J= (K+1) rem 8. sow(1. t(S1. LM. K. L).6])). NewBoard). L). T. [6. LM. P1. NuB) :. LM. NuB). BA. 6.

i. implement main /* kalahGame */ open mv clauses classInfo("kalahGame". P1. integer) determ (i. LM. o). mv::board. Val). P2. LM. mv::board. integer. play(t(b. LM. mv::board. integer. sow(4. integer. i. clauses maxeval(Pos. bestMin:( mv::board*.25. Val) :-LookAhead > 0. P1. P2. integer. L) > 0. t(a. P)]. L). i. integer. integer. i. sow(7. o.list::nth(3. L) > 0. play(t(b. . P2.1 Move generation play(t(a. P1. X). L) > 0. ! . X) :. i. LookAhead. class predicates maxeval:( mv::board. i. i. mv::board. o).0"). P1. "1.list::nth(6. o. X). Lcs = [P || play(Pos. integer) procedure (i. alphaPruning:( mv::board*. Mov= none. L). L).list::nth(7. P1. P2. i. i. X). Mov. integer. integer. bestMax(Lcs. integer. t(b. LM. i. o. LM. o). sow(6. P1. L) > 0. LM. L). i. P1. bestMax:( mv::board*. play(t(b. play(t(b. X) :. integer. LM. Val). that will search the game-tree for the best move. L). i. integer) determ (i. integer. t(b. Alpha. i. L). P2. L). integer) procedure (i. L). i. P2. LM. i. X). integer. betaPruning:( mv::board*. integer. X) :. o. sow(5. i. X) :. integer. integer. integer. o). LM. t(b. LookAhead 1. i. mv::board. end implement mv 259 Now you are ready to implement the main class. Alpha. P2. P2. o). o. Beta. mv::board. i. LM. P1. o. L). integer.list::nth(5. integer. i. L). stateval(Pos. X). i. integer. i. Beta. integer) procedure (i. mineval:( mv::board. P1. Mov. o). mv::board. integer. i. mv::board. L) > 0. t(b. integer) procedure (i. X) :. P1.list::nth(4. P2. sow(3. P2.

alphaPruning([]. Alpha. LookAhead. Lnc. !. Alpha. Val. Val1 > Val then MLnc= Lnc1. Beta. LookAhead. LookAhead. BestMove. Beta. Val). Beta. ! . Beta. Beta. MLnc. MVal= Val end if. Lnc. alphaPruning(Lncs. Val) :-LookAhead > 0. Alpha. _. BestMove. Alpha. _. BestVal) :. Alpha.!.1. BestVal). Lnc. Lnc. alphaPruning(_. if bestMin(Lncs. Val1). Val. LookAhead. Lnc. BestMove. mineval(Lnc. _Beta. Val. Beta. LookAhead. MVal= Val1 else MLnc= Lnc. Lnc. if bestMax(Lncs. Beta. Beta. MVal= Val1 else MLnc= Lnc. Alpha. LookAhead.!. Val). BestMove. Val). mineval(Pos. Alpha. betaPruning([]. Val1). _. Lnc. Lnc. Val). _. LookAhead. _. Lnc1. Lnc. _.!. maxeval(Lnc. LookAhead. _Alpha. LookAhead. Val. Val) :. MVal= Val end if. BestVal) :. Mov= none. Mov. LookAhead. NewBeta. MVal) :-if Val < Beta then NewBeta= Val else NewBeta= Beta end if. Beta. Lnc. Alpha. _. Val. Alpha. bestMin([Lnc|Lncs]. betaPruning(Lncs. Val) :.!. Val) :. Alpha. LookAhead . Beta. Val. Val.Val < Alpha. LookAhead. Lcs = [P || play(Pos. bestMin(Lcs. Val) :. Val1 < Val then MLnc= Lnc1. MLnc. Beta. Lnc1. !. BestVal). . Val. Lnc. _. stateval(Pos.260 Alpha Beta Pruning bestMax([Lnc|Lncs]. betaPruning(Lncs.Val > Beta. Alpha. _. Mov. Lnc. Alpha. Beta. P)]. MVal) :-if Val > Alpha then NewAlpha= Val else NewAlpha= Alpha end if. NewAlpha. alphaPruning(Lncs. betaPruning(_. _.

10. announceWinner:(integer) procedure (i). I5 < 1. I5. _. I6. _P1. integer) procedure (i.stateval(X. sow(I1. BestVal). !. game(BestMove. _Val) :-readMove(Pos. Pos). -10. Val) :stdio::write("End game: ". game(Pos.1 Move generation 261 class predicates readMove:(board. [_I0. endGame:(board) determ (i). readMove(Pos. math::abs(V) > 10. board) procedure (i. X) > 0. prtBoard(X). endGame(t(b. Val). !. list::nth(I. I2 < 1. NewPos). endGame(X) :.endGame(X). announceWinner(V). legalMove:(core::positive. stdio::nl. BestVal). _P1. _P2. . [I0. game:(board. game(none. I6 < 1. ReadPos). BestMove. I7])) :-I4 < 1. _P2. i). _P1. game(X. I3|_])) :-I0 < 1. 10. _LM. Pos. board) determ. !. ReadPos) :-stdio::write("Something failed"). I1 < 1. stateval(X. readMove(Pos. _LM. !. I1. maxeval(NewPos. stdio::nl. announceWinner(Val). !. I < 4. I2. I7 < 1. _I3. fail). X)) :-I >= 0. stdio::nl. ReadPos). _I1. _Val) :. _LM. prtBoard(ReadPos). readMove(Pos.25. legalMove(I1. %stdio::write("Your move: "). endGame(t(a. _P2. !. I3 < 1. prtBoard(Pos). _I2. I4. !. t(a. V). V). trap(I1= toTerm(SR). clauses legalMove(I. o). SR= stdio::readLine(). ReadPos) :-stdio::write("Present situation: ").

announceWinner(Val) :. B).262 Alpha Beta Pruning announceWinner(Val) :. newboard(a. end implement main /* kalahGame */ goal mainExe::run(main::run). besides this. Val). stdio::write("\n I won!\n". and inevitably lost.stdio::write("\n It is a draw!\n"). I don‘t have his luck. Like Erast Fandorin. run():. stdio::write("\n You won!\n".console::init(). !.Val > 0. Here is the beginning of the game: Present situation: Move: -1 66 6 0 66 6 0 Move: 0 77 0 77 7 Present situation: Move: 7 88 8 0 88 7 1 Move: 1 99 2 99 8 Present situation: Move: 4 10 10 0 2 1 11 9 1 1 0 0 b 6 7 0 0 b 6 0 6 a 1 0 0 a 1 4 0 a . game(B. I don‘t like games. which means that I always loose. I pitted my wits against the computer. Val).Val < 0. Val). !. stateval(B. All the same. announceWinner(_Val) :. Val).

39 Coelho How to solve it. 171 pictOpen/1. 115 Colmerauer. 171 Botany. 56 domains list declaration. 95 Compiling a program. 57 pictClose/1. 95 setBrush(B). 179 263 . 56 userControl. 14 conjunction. 110 doPaint Java. 118 average. 43 contents. 217 background transparent. 53 Accumulator parameters. 155 color. 115 Prolog by Example. 57 getVPIWindow(). 168 class open. 124. 32 draw GDIObject. 172 drawing predicates drawEllipse/2. 124 determ. 171 ropSrcCopy. 213 handling. 213 Edit control fact variable. 64 B+Tree. 61 days in a year. 95 Building. 55 class predicates. 213 Edit field accessing. 96 backtrack. 141. 14 Class creating. 163 brush. 43 interface. 179 class facts. 18. 179 editorControl.Index :-. 169 with objects. 52 console Run in Window. 62 testing. 67 and. 61 cut. 43 editor. 171 pictDraw/4. 56 Blinking animation. 55 Code Expert. 175 append. 94 Drawing predicates. 52 animation. 62 console applications. 57 Edit Control getText().

61 facts class facts. 117 member. 94 show(). 163 Laplace. 53 head. 17 prototype. 180 saving. 156 International language. 17 form new(Window). 53 tail. 138 writeString. 147 Grammar books. 53 facts. 64 intersection. 40 creating. 138 readString. 53 implication. 167 GDIObject. 138 file (class). 118 average. 125 Appel and Haken. 110 of string. 125 Generic interface. 75 list append. 55 file. 129 Nim.264 loading. 37 Hoare. 221 grammar English parser. 108 Forms. 163 L-Systems. 64 domains. 145. 155 Linaeus. 163 Lindenmayer. 163 List domains. 87 German parser. 121 Latino Sine Flexione. 125 Functions definition. 93 onPainting. 52 L-Systems. 127 Games. 151 GUI Object-oriented. 171 Form create a new one. 116 INDEX . 171 Flickering animation. 93 Format. 94 generate and test. 158 iteraction. 32 junctors. 45 game minimax algorithm. 93 Executing a program. 131 move generation. 180 Enable File/New. 17 four colors. 17 Euclid. 14 factorial. 85 event onPainting. 138 Flickering elimination. 121 Horn clauses. 86 Grammars. 85 Graphics turtle. 67 Java doPaint. 53 Interlingua.

95 transparent. 152 pictDraw. 56 painting event handling. 96 pictDraw. 17 task. 93 paiting drawPolygon. 94 open class. 151 curve. 70 lists [X:Xs]. 167 LsF Latino sine Flexione. 31 event. 31 MouseDown. 50 Natural Language Processing. 68 schemes. 68 zip. 152 Lope de Vega. 55 definition of. 56 multi-solutions. 56 Object interface. 96 pictLoad. 125 Piaget. 152 pattern style. 96 polymorphism. 94 Papert. 121 Nim. 56 type/flow patterns. 52 logical if. 55 declarations. 68 reduction. 56 nondeterm. 96 member. 63 tail. 31 multi. 41 Mouse. 68 recusive reduction. 63 iterative reduction. 53 logical implication. 13 settings. 96 picture mask. 155 recursion postulate. 53 logical junctors. 63 logical and. 119 sort.INDEX reverse. 52 Logo. 95 pictLoad. 46 determ. 68 ZIP scheme. 14. 121 Lists. 154 Pereira Luis Moniz. 14 265 . 63 patterns. 40 creating. 155 Newton. 31 add code. 159 map four colors. 155 Latino Sine Flexione. 63 head. 56 multi. 55 procedure. 127 nondeterm. 95 Peano. 56 procedure. 56 Project building. 169 onPaiting. 15 Create item. 116 Menu Enable option. 116 predicates class predicates. 125 mask.

167 quicksort. 75 string format. 18 Prolog How to solve it. 154 recursion iteraction. 85 Turtle graphics.266 Project Tree. 46 Multi solutions. 85 writeString. 138 INDEX . 124 setBrush. 64 Reasoning. 108 Char. 50 sort. 94 Wittgenstein. 108 user control. 178 transparent background. 47 Warren. 108 Int. 179 Van Emden. 38 Project tree add code. 41 timer handling. 124 window GDIObject. 95 solutions. 108 from file. 151 Type. 75. 67 Roussel. 72 Recursion postulate. 70 systems Incremental development. 138 Sundback Gideon. 121 Hoare. 138 real*. 179 editorControl. 96 Tratactus. 127 Task menu. 121 readString. 121 String. 108 String. 108 frontToken. 115 Pushkin. 121 variables. 108 Real.

Sterling and Shapiro. pp. ‖Natural Language Processing in Prolog‖. Shieber. In: System Analysis Modeling Simulation. ‖Prolog and Natural-Language Analysis‖. ‖The Art of Prolog‖.M. C. M. and Cotta. 1987. de Carvalho. Helder Coelho. and da Silva Julia. Min-isterio do Equipamento Social. ‖Prolog by Example‖. 2006. L. Mellish. Springer Verlag. 1989. Laboratorio Nacional de Engenharia Civil. Costa Pereira. E. CSLI Publications. Carlos Cotta.S. Luis Moniz Pereira. Lewis Carroll. Vol 36. Pereira and S. Gazdar. A. H.N. G. R..Bibliography [Abramson/Dahl] Harvey Abramson and Veronica Dahl. J. ‖How To Solve It With Prolog‖. Addison-Wesley / January 1988. Addison-Wesley. Warren. 267 [Cedric et all] [Warren] [Lewis Carroll] [Sterling and Shapiro] [Coelho/Cotta] [HowToSolveItWithProlog] [Pereira/Shieber] [Gazdar/Mellish] . MIT Press / January 1986.. David S. (1988) Berlin: Springer-Verlag. ‖Data-flow Synthesis for Logic Programs‖. ‖Computing With Logic: Logic Programming With Prolog‖. 349-366. The Game of Logic. Hard Press.C. and C. ‖Logic Grammars‖. F. Coelho. 1999.

N.366p. 2004. 12. Why Functional Programming Matters. A. Introduction to Functional Programming. William T Stearn. Computer Journal. State University of Campinas. 1991. Expressivity versus Efficiency. G. Combining partial evaluation and automatic control insertion to increase the efficiency of Prolog programs.-X. The Science of programming — New York : Springer-Verlag. cop. [Wadler & Bird] [John Backus] [Gries] [Dijkstra] [Cohn] [Yamaki] Kimie Yamaki. 21(8):613-641. P. 10.1981. Mathematische Annalen. Theorem Proving on the Computer. Prentice Hall (1988). pages 98-107. August 1978. Journal of the Association for Computing Machinery. State University of Campinas. 1989. 32. number 2. Dijkstra. Logic Programming. David Gries. Feijen: A Method of Programming. E. Gerhard Karl Erich Gentzen. Timber Press. Addison-Wesley Publishing Company. J. Richard Bird and Philip Wadler.268 [John Hughes] BIBLIOGRAPHY John Hughes. Vol. vol. 112: 493-565. ‖Die Wider-spruchsfreiheit der reinen Zahlentheorie‖. Cohn. John Backus. [Gentzen] [Robinson] [William Stearn] . Botanical Latin. W. pp 163-174.(1936) Robinson. Can Programming be Liberated from the Von Newman Style? Communications of the ACM. Paperback edition. 1990.

i. P1. P1. LM. mv::board. P2. L). . LM. i. play(t(b. i. mv::board. P1. integer. LM. integer. P2. i. i. o). o. o. o).1. Beta. L) > 0. o. X) :. Beta. P2. integer. LM.list::nth(6. clauses maxeval(Pos. LM. o. i. i.list::nth(5. X) :. integer. i. Val) :-LookAhead > 0. integer. class predicates maxeval:( mv::board. integer. L). i. i. o). i. LM. integer.25. X). integer) procedure (i. betaPruning:( mv::board*. P2. integer) determ (i.list::nth(3. P1. integer) procedure (i. i. Val). i. end implement mv Now you are ready to implement the main class. LookAhead . P1. i. sow(4. sow(3. L) > 0. integer. i. L). integer.list::nth(4. ! . L). o). L). i. integer. that will search the game-tree for the best move. i. i. bestMax:( mv::board*. X). bestMax(Lcs. mv::board. integer) determ (i. Mov.0"). L) > 0. t(b. integer) procedure (i. X). sow(5. integer. X) :. P)]. play(t(b. Alpha. L). i. L). mv::board. integer. play(t(b. integer) procedure (i. LM. L). P2. t(b. P1. mv::board. mv::board. L) > 0. o. 259 implement main /* kalahGame */ ope n mv clauses classInfo("kalahGame". P1. LM. integer. Lcs = [P || play(Pos. P1. X). t(b. o). i. X) :. mv::board. integer. P2. integer. P2. integer. Mov= none.list::nth(7. X). play(t(b. integer. bestMin:( mv::board*. LM. Alpha. mineval:( mv::board. o). P2. Val). LookAhead. o. integer. sow(6. L) > 0. alphaPruning:( mv::board*. sow(7. i.1 Move generation play(t(a. P1. "1. integer. L). stateval(Pos. Mov. P1. LM. integer. t(b. X) :. P2. L). t(a. mv::board. P2. i.


Val. Lnc. Val1). LookAhead. Val). Lnc. MLnc. Alpha.Val > Beta. Mov= none. Mov.!. Lnc. Lnc. P)]. Val1). LookAhead. BestMove. Beta. LookAhead. _Alpha. LookAhead. Alpha. betaPruning(Lncs. Alpha. Beta. Lnc. Val) :. NewBeta. betaPruning(_. Lnc. NewAlpha. BestVal). Alpha.!. Beta. BestVal) :.260 Alpha Beta Pruning bestMax([Lnc|Lncs]. Lnc1. alphaPruning(Lncs. _Beta. betaPruning(Lncs. _. LookAhead. _. MLnc. MVal) :-if Val < Beta then NewBeta= Val else NewBeta= Beta end if. _.1. LookAhead. MVal= Val1 else MLnc= Lnc. Mov. BestMove. Lnc. LookAhead. MVal= Val1 else MLnc= Lnc. LookAhead . Alpha. betaPruning([].Val < Alpha. Beta. Beta. mineval(Lnc. Lnc. alphaPruning(Lncs. LookAhead. Val. LookAhead. Val. Val. _. Val) :. Beta. BestMove. Beta. alphaPruning([]. Lnc. mineval(Pos. Alpha. BestVal) :. Val. _. Val). Lnc1.!. Val). Val. !. if bestMin(Lncs. Val1 > Val then MLnc= Lnc1. Beta. Beta. if bestMax(Lncs. . MVal= Val end if. Alpha. MVal= Val end if. bestMin([Lnc|Lncs]. Alpha. _. MVal) :-if Val > Alpha then NewAlpha= Val else NewAlpha= Alpha end if. Val) :. Alpha. Lnc. Val1 < Val then MLnc= Lnc1. bestMin(Lcs. maxeval(Lnc. Alpha. LookAhead. Val. Val. BestMove. ! . Val) :. Lcs = [P || play(Pos. stateval(Pos. Lnc. Beta. LookAhead. Beta. !. Beta. _. Alpha. alphaPruning(_. _.!. Lnc. Val). BestVal). Val) :-LookAhead > 0. _. Alpha. _.

-10. stdio::nl. !. ReadPos) :-stdio::write("Present situation: "). announceWinner(V). BestVal). I6 < 1. legalMove:(core::positive. _LM. _P1. integer) procedure (i. endGame(t(b. _P1. I2.25. BestVal). !. I1 < 1. V). %stdio::write("Your move: "). !. board) procedure (i. [_I0. . _P2. fail). legalMove(I1. clauses legalMove(I. prtBoard(ReadPos). I2 < 1. maxeval(NewPos. announceWinner(Val). Val) :stdio::write("End game: ". I3| _])) :-I0 < 1. _I3. NewPos). prtBoard(Pos). _P2. _Val) :-readMove(Pos. game:(board. stateval(X. _P1. endGame:(board) determ (i). o). _I1. trap(I1= toTerm(SR).stateval(X. BestMove. ReadPos). I < 4. I1. !. _LM. I7])) :-I4 < 1. i). endGame(X) :. _Val) :. board) determ. sow(I1. I6. [I0. t(a. I4. I3 < 1. stdio::nl. announceWinner:(integer) procedure (i). list::nth(I. _. 10. _I2. Pos. game(Pos. readMove(Pos. X) > 0. ReadPos). _LM. Pos). Val). endGame(t(a. !. prtBoard(X). math::abs(V) > 10. ReadPos) :-stdio::write("Something failed"). game(none. V). I5. I7 < 1. stdio::nl. !. game(BestMove. !. game(X. X)) :-I >= 0.1 Move generation 261 class predicates readMove:(board. 10. _P2. readMove(Pos. readMove(Pos. I5 < 1.endGame(X). SR= stdio::readLine().

announceWinner(Val) :. which means that I always loose. announceWinner(_Val) :. I don’t like games. end implement main /* kalahGame */ goal mainExe::run(main::run). !. Like Erast Fandorin. game(B. stdio::write("\n I won!\n".Val > 0. newboard(a. I pitted my wits against the computer. I don’t have his luck. !. besides this. Val).stdio::write("\n It is a draw!\n"). run():. and inevitably lost.262 Alpha Beta Pruning announceWinner(Val) :.console::init(). Val). Here is the beginning of the game: Present situation: Move: -1 66 6 0 66 6 0 Move: 0 77 0 77 7 Present situation: Move: 7 88 8 0 88 7 1 Move: 1 99 2 99 8 Present situation: Move: 4 10 10 0 2 1 11 9 1 7 6 0 6 a 0 0 6 1 0 0 a b 0 0 1 1 0 b 4 a . All the same. stateval(B. Val). B). stdio::write("\n You won!\n". Val).Val < 0.

168 class open. 179 263 . 61 days in a year. 115 Prolog by Example. 57 getVPIWindow(). 179 class facts. 95 Building. 118 average. 171 ropSrcCopy. 56 Blinking animation. 57 pictClose/1. 172 drawing predicates drawEllipse/2. 169 with objects. 110 doPaint Java. 14 Class creating. 57 Edit Control getText(). 56 domains list declaration. 217 background transparent. 64 B+Tree. 18. 163 brush. 124. 124 determ. 95 Compiling a program. 179 editorControl. 175 append. 43 contents. 115 Colmerauer. 171 Botany. 67 and. 94 Drawing predicates. 55 class predicates. 171 pictDraw/4. 43 interface. 43 editor. 62 console applications. 95 setBrush(B). 61 cut. 62 testing. 96 backtrack. 56 userControl. 14 conjunction. 52 console Run in Window.Index :-. 213 Edit field accessing. 52 animation. 39 Coelho How to solve it. 213 handling. 213 Edit control fact variable. 32 draw GDIObject. 55 Code Expert. 155 color. 171 pictOpen/1. 53 Accumulator parameters. 141.

127 Games. 53 head. 167 GDIObject. 85 event onPainting. 32 junctors. 221 grammar English parser. 17 prototype. 93 Executing a program. 163 Lindenmayer. 180 saving. 125 Appel and Haken. 37 Hoare. 53 facts. 110 of string. 138 writeString. 67 Java doPaint. 14 factorial. 53 implication. 94 generate and test. 52 L-Systems.264 INDEX loading. 171 Form create a new one. 138 file (class). 163 L-Systems. 151 GUI Object-oriented. 53 Interlingua. 17 Euclid. 156 International language. 93 Format. 129 Nim. 145. 40 creating. 64 domains. 116 . 55 file. 163 List domains. 125 Functions definition. 118 average. 75 list append. 64 intersection. 158 iteraction. 17 four colors. 163 Laplace. 138 readString. 131 move generation. 180 Enable File/New. 94 show(). 108 Forms. 53 tail. 138 Flickering elimination. 125 Generic interface. 17 form new(Window). 147 Grammar books. 85 Graphics turtle. 93 onPainting. 155 Linaeus. 61 facts class facts. 87 German parser. 171 Flickering animation. 86 Grammars. 121 Latino Sine Flexione. 117 member. 121 Horn clauses. 45 game minimax algorithm.

63 logical and. 63 iterative reduction. 152 Lope de Vega. 53 logical implication. 40 creating. 13 settings. 68 schemes. 155 Latino Sine Flexione.INDEX reverse. 155 recursion postulate. 95 Peano. 55 declarations. 93 paiting drawPolygon. 121 Lists. 56 multisolutions. 63 head. 55 procedure. 167 LsF Latino sine Flexione. 169 onPaiting. 56 Object interface. 94 Papert. 151 curve. 14 265 . 56 nondeterm. 116 predicates class predicates. 55 definition of. 63 tail. 96 pictDraw. 56 procedure. 152 pattern style. 53 logical junctors. 68 zip. 14. 68 recusive reduction. 125 mask. 121 Nim. 116 Menu Enable option. 56 Project building. 95 transparent. 56 type/flow patterns. 154 Pereira Luis Moniz. 125 Piaget. 50 Natural Language Processing. 52 logical if. 56 multi. 17 task. 68 ZIP scheme. 31 multi. 95 pictLoad. 31 add code. 41 Mouse. 152 pictDraw. 94 open class. 96 picture mask. 155 Newton. 31 MouseDown. 119 sort. 46 determ. 56 painting event handling. 96 pictLoad. 63 patterns. 70 lists [X:Xs]. 127 nondeterm. 31 event. 96 polymorphism. 68 reduction. 96 member. 52 Logo. 15 Create item. 159 map four colors.

72 Recursion postulate. 46 Multi solutions. 179 Van Emden. 47 Warren. 121 String.266 INDEX Project Tree. 121 variables. 154 recursion iteraction. 50 sort. 18 Prolog How to solve it. 67 Roussel. 108 user control. 85 Turtle graphics. 121 Hoare. 41 timer handling. 138 Sundback Gideon. 151 Type. 94 Wittgenstein. 96 Tratactus. 178 transparent background. 95 solutions. 75 string format. 108 Char. 124 setBrush. 64 Reasoning. 115 Pushkin. 70 systems Incremental development. 108 frontToken. 179 editorControl. 108 Real. 124 window GDIObject. 138 . 85 writeString. 75. 38 Project tree add code. 121 readString. 167 quicksort. 108 Int. 138 real*. 108 from file. 108 String. 127 Task menu.

A. 2006. MIT Press / January 1986. Helder Coelho. Luis Moniz Pereira. L. Springer Verlag. Vol 36. G. ”How To Solve It With Prolog”. ”Prolog by Example”. AddisonWesley. 267 . Sterling and Shapiro. Costa Pereira. Shieber. CSLI Publications. Hard Press. David S.. ”Data-flow Synthesis for Logic Programs”. ”Logic Grammars”. Coelho. and C. E.Bibliography [Abramson/Dahl] [Cedric et all] Harvey Abramson and Veronica Dahl. Ministerio do Equipamento Social. 1999. Mellish. The Game of Logic. Pereira and S. pp. AddisonWesley / January 1988.N. R. ”Prolog and Natural-Language Analysis”. Laboratorio Nacional de Engenharia Civil. C. ”The Art of Prolog”. H. [Warren] [Lewis Carroll] [Sterling and Shapiro] [Coelho/Cotta] [HowToSolveItWithProlog] [Pereira/Shieber] [Gazdar/Mellish] Gazdar. and da Silva Julia. 1989.M. and Cotta. (1988) Berlin: Springer-Verlag.C. Lewis Carroll. de Carvalho. ”Computing With Logic: Logic Programming With Prolog”. J. F. In: System Analysis Modeling Simulation. Warren. ”Natural Language Processing in Prolog”. M. Carlos Cotta. 349-366. 1987..S.

Timber Press. Computer Journal. August 1978. Introduction to Functional Programming. William T Stearn. ”Die Widerspruchsfreiheit der reinen Zahlentheorie”. 1991. N.-X. vol. Paperback edition. Richard Bird and Philip Wadler. 112: 493-565. Theorem Proving on the Computer. pp 163174. Feijen: A Method of Programming. Mathematische Annalen. Addison-Wesley Publishing Company. J. John Backus. number 2. 21(8):613-641. David Gries. 10. G. The Science of programming — New York : Springer-Verlag. A. 1989. [ G [ R [ W . Botanical Latin. 2004.366p. 1990. Expressivity versus Efficiency. State University of Campinas. Cohn. [Wadler & Bird] [John Backus] [Gries] [Dijkstra] [Cohn] [ Y Kimie Yamaki. Can Programming be Liberated from the Von Newman Style? Communications of the ACM. pages 98-107. E. 32. Journal of the Association for Computing Machinery. Logic Programming. P. W. cop. Why Functional Programming Matters.(1936) Robinson.1981. Dijkstra. State University of Campinas.268 [John Hughes] BIBLIOGRAPHY John Hughes. Combining partial evaluation and automatic control insertion to increase the efficiency of Prolog programs. 12. Gerhard Karl Erich Gentzen. Vol. Prentice Hall (1988).

You're Reading a Free Preview

/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->