Computers & Geosciences Vol. 15, No. 5, pp. 809-823, 1989 Printed in Great Britain. All rights reserved
0098-3004/89 $3.00 + 0.00 Copyright © 1989 Pergamon Press plc
IDENTIFY: A PROLOG PROGRAM TO HELP IDENTIFY FOSSILS WM. R. RIEDEL
A-020 Scripps Institution of Oceanography, University of California at San Diego, La Jolla, CA 92093, U.S.A.
(Received 8 September 1987; revised 16 August 1988) Abstract--A program in Turbo Prolog assists the user to identify fossils consistently and expeditiously. The database includes information on variable character-states for each species, and the user is encouraged to input the variability of the form to be identified. Annotated sketches are associated with each taxon in the database. Although this working prototype is for a paleontological application, the same program can be used with other databases in a wide spectrum of disciplines in the natural sciences.
Key Words: Fossils, Variability, Identification, Prolog. INTRODUCTION Some disciplines of Earth science depend heavily on objects and relationships that inherently are variable (e.g, fossils, stratigraphic successions, and paleoenvironmental effects), whereas others are concerned with more readily quantifiable information (e.g. in geophysics, although even here variability is characteristic of the lithologic units revealed by seismic profiling, etc.). The number-oriented Earth sciences have benefited in many ways from the wide diffusion of computers and the power they bring to scientific analysis, but investigations based on paleontology, lithology, and stratigraphic succession have been less affected. A reason for this is that computers were developed originally for massive, serial, arithmetic processing, using procedural programming languages (FORTRAN, Pascal, C, etc.) designed to exploit this capability. Artificial intelligence workstations, optimized to handle nonprocedural languages concerned with nonnumeric things and their properties and relationships, have emerged more recently. An early success in applying artificial-intelligence techniques in geology was PROSPECTOR (Duda, Gaschnig, and Hart, 1979), an expert system that subsequently helped discover an ore-grade molybdenum deposit (Campbell and others, 1982). During the past few years, several well-established nonprocedural languages developed for artificial-intelligence programming (Lisp, Prolog, Smalltalk, OPS-5, etc.) have become available for use on conventional miniand even microcomputers. This note reports on IDENTIFY, a modest example of a paleontological application in Turbo Prolog developed on an IBM personal computer. The source code (or a compiled version) is available free from the author, on 5.25 in (360 kbyte) or 3.5 in (720 kbyte) diskettes. Paleontological studies provide the principal basis for interpretations of geologic age, paleogeography, and paleoenvironmental conditions, but records of fossils are subjective and of uneven reliability, and 809
thus constitute an uncertain foundation for future research. Uncertainties enter into records of fossils as a result of (I) The natural intraspecific variability of organisms, (2) Differing usage, among paleontologists, of vaguely defined morphologic terms used to describe fossil remains, and (3) The vagaries of preservation. Intraspecific variability is exemplified by Table 1, which shows the characters (in the column headings) and their states (the matrix entries) used to distinguish some of the species of the stratigraphically useful Eocene radiolarian genus Podocyrtis. Major skeletal characters for one of these species are indicated in Figure 1, and further detail is provided by Sanfilippo, Westberg-Smith, and Riedel (1985, p. 695-699). Variability of the species is the cause of most of the situations in which multiple character-states are entered in a single box in Table 1--for example, some specimens of P. aphorrna have their greatest abdominal width proximally and some have it medially. In a few examples, multiple states are entered in a single box because although the domain expert may have no difficulty deciding which of two character-states is represented in a particular specimen, a less experienced investigator may make a wrong determination, for example by interpreting an actually bladed horn as "conical". And finally, postdepositional corrosion of a skeleton may remove all traces of the terminal feet from an originally three-footed specimen of P. aphorm12.
The quality of paleontological records could be improved by a tool that would reduce the uncertainties introduced by any of these factors, and the program presented here attempts to cope with all of them to some extent. In the description of each fossil taxon in IDENTIFY's database, intraspecific variability is captured by using as many terms as necessary to indicate the range
810
WM. R. RmDEL Table 1. Some character-states of seven species of radiolarian genus Podocyrtis Character ft_num
abd_surf
por c i r c
ahd_por
horn
thor_long
wid abd
aepla
none
smooth
gtl3
gt20
conic
pron
med diet
aphorea
e3
seooth
~gtl3
gt20
blad conic
pron
prox eed
none chalara
none
smooth
It13
gt20
blad
unpron
diet
diaeesa
e3
smooth
gtl3
gt20
conic
pron
prox
dorue
gt3
smooth
gtl3
gt20
blad
pron
prox med diet
faeciolata
none
euooth ~ough
gtl3
igt20
blad conic
unpron
eed
goetheana
none
smooth
It13
It20
blad
unpron
diet
Explanation of abbreviations -
f t nue : number o f f e e t - three, g r e a t e r than three, n o n e abd_murf : surface o f a b d o n e n - smooth, rough por_circ : pores around g r e a t e s t circumference - l e s s than 13, sore than 13 a b d _ p o r : t o t a l abdominal p o r e s - l e s s t h a n 2 0 , m o r e t h a n 2 0 horn : bladed, conical thor_long : l o n g i t u d i n a l rows of t h o r a c i c pores - pronounced, not pronounced ¥id_abd : greatest width of abdomen - proximally, medially, d i s t a l l y
of states exhibited by each character. W h i l e entering descriptors for the unidentified form which is being worked, the paleontologist is e n c o u r a g e d to use as m a n y terms as necessary to describe the states o f each character, a n d in o r d e r to stabilize usage, sketches can be provided as templates for m o r p h o l o g i c terms. W h e n specimens are preserved poorly, b r o k e n , or partially obscured, the paleontologist, in effect, can pass over a c h a r a c t e r by entering all o f the states it could assume.
USING THE PROGRAM A t the c o m m e n c e m e n t of the identification-assisting p r o g r a m , the user enters one o f the characters, a n d the state(s) represented in the specimen(s). C o n t i n u e entering characters a n d character-states in this (operator-initiative) mode, or, w h e n e v e r desirable switch to the computer-initiative mode. W h e n the c o m p u t e r p r o g r a m has the initiative, it asks a b o u t the states of only those characters that will n a r r o w d o w n
Lt ~ ~ ,
zi Mic.ns I
Podoc rtis hscielatt
u Xm sbl, t, cemmly bladed. . . H lbt'acic pore longitudinally anigeed. Aklominalpms i m ~ i a r l y ol, longitudinally ~ g e d . Hide, poeoless ~ i s t e ~ .
Figure 1. Sketch of species Podoeyrtis fasciolata, with distinguishing characters noted, displayed by program IDENTIFY.
Identifying fossils the range of possible identifications at each step. Moreover, these questions are asked in order of decreasing dependability of the responses elicited, this judgement being built into the database by the domain expert who established it. At the end of the computer-interactive session, the user can be presented with an annotated sketch (Fig. 1, originally entered via a digitizing tablet, and accessed from an image file not included in the program listing) to confirm the identification if the search is narrowed down to one taxon, or with sketches of several taxa if more than one possibility remains. A typical session with I D E N T I F Y proceeds as follows. User has a number of specimens of Podocyrtis, which are judged to belong to a single variable species. The program invites an entry of one character from among those heading the columns of Table 1, and three states to express the variability--zz to be used to bring the number to three, if one or two states suffice. User enters por circ, gtl3, zz, zz. Program displays a list of the five species with this character-state (ampla, aphorma, diamesa, dorus, and fasciolata), and asks whether the initiative now is to be turned over to the computer program (c) or remain with the operator (o). User enters o. For the next character and its states, user enters wid_abd, reed, dist, zz. (The greatest width of the abdomen is medial in some specimens, distal in others.) Program displays a reduced list of four possible species (ampla, aphorma, dorus,fasciolata), and again asks whether the initiative is to be turned over to the computer program (c) or remain with the operator
(o). User enters c. Program asks about the number of feet. User enters none, zz, zz. Program lists three possible species (ampla, aphorma, fasciolata), and asks whether the abdominal surface is smooth or rough. User enters smooth, zz, zz. Program lists the same three possible species (the list would have been reduced to one if the user had entered rough, zz, zz), and asks whether the horn is bladed or conical. User enters blad, conic, zz, because it is not certain whether the horns of some specimens are bladed. There is no change in the list of possible species. Program asks whether the thoracic pores show pronounced longitudinal alignment. User enters pron, zz, zz. Program lists the two possible species (ampla, aphorrna), reports that no further narrowing is possible using the characters in the database, and asks whether the user would like to see illustrations of these two species in order to make an identification. User responds affirmatively, and the program dis-
811
plays sketches of ampla and aphorma, annotated to emphasize their distinguishing characters. As happened in this session, any real-world computer program of this type usually should narrow the search down to a few possibilities, and leave the final selection to the human operator. This eliminates the need to computerize the finest discriminating details, which are best judged by a person with the help of illustrations for comparison. A computer-based identification aid such as this has obvious advantages over a paper-based one. It can handle easily nonuniqueness of character-states at successive decision points, and thus the user is not inhibited from recording several possible states when it is impossible to settle on a single one. The user can safely "pass" on one or more characters--this is not possible with a paper-based key. Finally, because Prolog is the language used, built-in list-manipulating facilities are available to handle variability of characters, and parts of the program can be modified or supplemented without the entire edifice collapsing. The program presented here was developed on a microcomputer, and there is no obvious impediment to moving it up to a minicomputer as its databases grow. In practical operation, it will be necessary to subdivide a large database, possibly hierarchically, according to either taxonomy or morphology. The latter would seem to be preferable, because morphological descriptions may be more durable than a taxonomic classification--the taxonomic system would be a passive and nonessential component of the database, as anticipated by Riedel (1978), and implemented by Budai, Riedel, and Westberg (1980) and Brough and Alexander (1986).
THE PROGRAM In broadest outline, the program can be viewed as having three parts. The first establishes an initial list of species conforming to the first character and its states entered by the user. The second part narrows clown this list of possibilities as the user enters additional characters and their states. The third part evaluates characters not considered previously, avoiding those that do not narrow the current list of possibilities. It terminates after all characters have been considered, when the search has narrowed to a single possible species, or when it has accumulated a combination of character-states for which there is no match in the database. Further details on the execution are summarized in Figures 2A-2C, which are simplified versions of the type of A N D / O R trees used in Logicware's M P R O L O G manual (Young, 1986, p. 103 et seq.). The inference mechanism used by Turbo Prolog is described in Chapter 5 of Anonymous (1986). The database (Table 1, represented at the end of the program listing under the heading "the data") consists of a selection of the character-states useful in distin-
IDENTIPf
(A) I
I ESTABLISH_POSSIBLESPP
I
I
I
I
FIRST_ CHAR THREE_ STATES
1
NARROWED
,[, ,I,
I
FAIL
NARROWEST_ POSSISLE
I
I
NARROWEST_ POSSISLE
NARROWED_ DOWN
I
SUCCEED6 NARROW_ AS_POSSIBLE
t I
mini
/ //
I
NARROW BY OPERATOR I
NEXT_ CHAR
RE(XJCE CONDITIONS_NARROWEST IF FULFILLED POSSIBLE
THREE~ POSS/BL STATES ~j~ E
FAIL
~11~
NARROW_ BY_COMPUTER
SWITCH NARROW / AS~POSSIB-L E
] [ i SUCCEEDS
FAIL SUCCEEDS
NARROWBY_COMPUTER
I//
(B) "1 REMAKING _CHAR 0
FAIL
I
',
WHITTLE DOWN
I
I \
II I
I
I
ANOTHER_CHAR THREESTATES
REDUCE_IF - POSSIBLE
1
CONDITIONS _F~FILLED
NARROWEST - POSSIBLE
I
S~CEEDS
I
NARROW J BY_COMPUfER
FIND_ HELPFUL_CHAR
FAIL
SUCCEEDS FIND HELPFULCHAR
(c)
I
I
I
ESTAB_STAND_ POSS_SP
I
I
I [
I FAIL
SUCCEEDS
I
ESTAB OTHER POS~SPP
DO THE TESTING
I
SUCCEEDS
I
/
RETRACT STAND_ / POSSSP /
I CANCEL_OTHER_ POSS SPP
TEST
CHA[ 3)
I
SUCCEEDS I
I
I
STILL REMAIN~G O,~AR (A)
I
I
I
TEST_FOR_ STILL_ STILL DFFEPENC~ REMAINING_REMAJNle~i_ . . . . . . . ,I CHAR(8)
I
i
SUCCEEDS
DO_THE_j TESTIING
SUCCEEDS
I I
I
I
1
DIFFERENTSET
I
I
FAtL
\
I
I
I
Figure 2A-C. Summary diagram of interaction of rules in program IDENTIFY. Thick horizontal bars join conditions in rule. Thin horizontal bars join alternative rules or facts in definition.
813
Identifying fossils guishing species of the genus Podocyrtis, as mentioned. To help the reader not familiar with Prolog to follow the listing, comments on the program's components are assembled here into a narrative, instead of being dispersed through the program. Because the dialect of Prolog used is Borland's Turbo Prolog (Anonymous, 1986), an initialization section is required to specify the domains of objects, and to list predicates with their objects; such declarations are not required in the standard Prolog of Clocksin and Mellish (1984). Establish possible_species elicits an initial set of one or more states of a character of the operator's choice, and determines whether the number of corresponding species in the database is zero, one, or more. The key operation in determining whether the character-state(s) of the unknown match those of one of the species in the database, both here and in the reduce_if_possible rules, is the determination whether the set of character-states of the unknown has an intersection with a set of states of that same character in known species in the database. Execution then proceeds to narrow the list of candidates, in the narrowed_down part of the program. Prior to entering each character after the first, the user is given the opportunity to change from operator-initiative to computer-initiative mode (switch in narrowed_down), but once in the latter mode it remains there. Each time a character is entered in the operatorinitiative mode (narrowby_operator), the character and its states (next_char_three__states) are checked against the remaining possible species (reduce_if__possible) to determine whether information on additional character-states could narrow the list of possibilities (narrowest.possible). If further narrowing is possible, the user again is given an opportunity to switch to computer-initiative mode, and execution returns to
narrowas_possible. In the computer-initiative mode (narrow_bycomputer), the first rule establishes which characters have not been used yet (still_remaining_char), and proceeds to whittledown the possibilities. The find_helpful_char segment ensures that it will ask about only those characters that will reduce the current list of possible species. This rule operates by selecting one of the possible species as a standard (estab_stand..poss_sp) and checking, for each remaining character, whether any of the other possible species has a differentset of states from that present in the standard. After asking for the states of a character that could reduce the list of possible species, the response is checked to see whether such a reduction in fact does occur (reduce_if._possible). Execution then returns to narrow_by_computer, and the cycle of selecting and asking about potentially helpful characters is repeated until no further narrowing is possible. The program terminates (conditions_fulfilled and narrowest_.possible) by listing (with annotated sketches if requested) the one or more possible species reC~.GEO 1 5 : 5 - J
maining after all useful characters have been checked, or alternatively reporting that no species in the database has the combination of character-states entered. CONCLUSION I D E N T I F Y presently is only a working prototype, and substantial improvements probably will be possible through optimization of both the source code and the execution. The next steps in its development will be to test its performance on larger databases (the present database comprises only seven species), and to translate it to a dialect of Prolog that can be used on a minicomputer (e.g. M P R O L O G on a VAX 11/785). A substantial improvement will be to make it possible for a user to obtain help at any of several levels in an hierarchical identification scheme--using a taxonomic hierarchy as an example, a specialist in a particular fossil group may wish to enter the system at the generic level so as to obtain help in identifying species or subspecies, whereas a less knowledgeable worker might need to enter it at the family or higher level. The rudiments of such a capability are present in the data structure used here, in that each data item includes a list comprising a genus name (which however, is not yet exploited) as well as the species name. This work stems from an acute need in paleontology, but a program such as I D E N T I F Y could be applied appropriately to the identification of any types of objects that have variable characters, or that are described in nonnumeric terms. Lithologic units and stratigraphic successions have been mentioned, and it would seem to be applicable also to things as diverse as plants, rocks, and oceanic water masses - - a l l of which have characters that are not only variable, but also susceptible to imprecise description by observers. The entire program as listed (prior to the routines for displaying the images on the screen) will work on any database comprising objects, their names, characters, and character-states, arranged as in the species file shown near the end of the listing. Now that programs such as this (and other identification aids such as those by Barnett, Payne, and Yarrow, 1985; Brough and Alexander, 1986) are available, the main impediment to their widespread use is the scarcity of large-scale databases on which they can operate with practical benefit. In the assembly of such databases, it will be important to keep them as general-purpose as possible, so that they can be accessed by successive generations of improved identification programs that will be written in a diversity of present and future languages.
Acknowledgments--Several years ago, AMOCO financed the initial investigations that led to this application of nonprocedural programming. Subsequently, support has been provided by the National Science Foundation (grant OCE87-07708), and by Unocal Corp. David Fedchenko wrote the image-handling portion of the program, and throughout the course of this work I have benefited substantially from discussions with my colleague Linda E. Tway.
WM. R. RIEDEL
814
Helpful comments on an early draft of this paper were provided generously by M. E. Hill of Unocal Science and Technology Division and Peter Guth of the University of Nevada at Las Vegas, and by two anonymous reviewers.
REFERENCES
Anonymous, 1986, Turbo Prolog: Borland International Inc., Scotts Valley, California, 221 p. Barnett, J. A., Payne, R. W., and Yarrow, D., 1985, Yeast identification program: Cambridge Univ. Press, Cambridge, 40 p. + diskette. Brough, D. R., and Alexander, I. F., 1986, The fossil expert system: Expert Systems, v. 3, no. 2, p. 76-83. Budai, A., Riedel, W. R., and Westberg, M. J., 1980, A general-purpose paleontologic information device: Jour. Paleontology, v. 54, no. 1, p. 259-262.
Campbell, A. N., Hollister, V. F., Duda, R. O., and Hart, P. E., 1981, Recognition of a hidden mineral deposit by an artifical intelligenceprogram: Science, v. 217, no. 4563, p. 927-929. Clocksin, W. F., and Mellish, C. S., 1984, Programming in Prolog (2nd ed.): Springer-Verlag, Berlin, 297 p. Duda, R. O., Gaschnig, J. G., and Hart, P. E., 1979, Model design in the PROSPECTOR consultant system for mineral exploration, in Michie, D., ed., Expert systems in the micro-electronic age: Edinburgh Univ. Press, Cambridge, p. 153-167. Riedel, W. R., 1978, Systems of morphologic descriptors in paleontology: Jour. Paleontology, v. 52, no. l, p. 1-7. Sanfilippo, A., Westberg-Smith, M.J., and Riedel, W. R., 1985, Cenozoic Radiolaria, in Bolli, H. M., Saunders, J. B., and Perch-Nielsen, K., eds., Plankton stratigraphy: Cambridge Univ. Press, Cambridge p. 631-712. Young, R. J., 1986, Prolog: a primer for logic programming: Logicware Inc., Toronto, 487 p.
APPENDIX
Program Listing /*
program IDENTIFY.PRO (using Borland's Turbo Prolog) IJ~Ji.R. Riedel
A-020 Scripps I n s t i t u t i o n of Oceanography University of C a l i f o r n i a at San Diego La Jolla, Calif.9209] Image-handling routines: David Fedchenko Version 1.0 1.1 1.2 2.0
March, 1987 25 July, 1987 13 August, 1987 23 August, 1987
*/
code=4000 domains name_hierarchy = names(level name l i s t ) level_name_list = tevel name* level_name = lev_nam(string, s t r i n g ) / * Taxonomic_level, Name * / description = f e a t u r e s ( s L i s t t i s t ) / * a l i s t of Character and states l i s t s * / s t i s t = string* sListtist = stist* label = e n t ( s t r i n g , i n t e g e r , i n t e g e r , i n t e g e r , integer) / * Label Text,X_for_text,Y_for_text,X_for_point,Yfor_point * / i l i s t = integer* dlist = itist* / * List of tins coordinates * / l l i s t = label* / * List of tat)el entries */ database current char and s t a t e s ( s t r i n g , s t i s t ) / * Character, List of_states possibte_sp(string) initiative(string) solution found(string) remaining_char(string) still_remaining_char(string) helpful_char(string)
*/
Identifying fossils num poss_spp(integer) stand_poss_sp(string) other_poss_sp(string) image(string,string,string,dlist,llist) /* ID,Hame,Text,Sketch_info,Labei_info */ predicates f i r s t char three_states prompt_menu estabtish possibte_spp intersection(slist, s|ist, stist) member(string, slist) member(stist, s t i s t l i s t ) n~mber(tevelname, Level_name_List) species(ham_hierarchy, description) species_imge(string,string) next char three_states first_conditions second_conditions third_conditions identify switch i n i t i a l l i s t charscters(string) character_andstates(string, string) another char three_states(string) reduce_if_possible write_list write_species_list narrowed_doun narrow_aspossible narrow_by_operator narrow_by_computer conditions_fulfilled narrowest_possibte whittle_down different_set(stist, s l i s t , string) find_helpful_char estab_stand_poss_sp estab_other_poss_spp do_the_testing cancel_other_poss_spp test_char(string) test_for_difference(siist, stist, string) cleanup terminate
show_species show_toop show(string) draw_it(dtist) draw_iinas(itist) ptace_tabel(Itist) find_x(intnger, intnger,integer,integer) draw_box(integer, integer,integer, integer)
clauses identify :consultt"identify.img"), makewindow(1,7,112," IDENTIFY ..,0,0,24,80), esteblish.possibte_spp, narroued do~m, terminate. f i r s t char_three_stetes :write (" " ) , n l , write("Enter f i r s t character and three states. "),nL,
815
816
WM. R. RIEDEL ~ r i t e ( " Separate and end with carriage returns. " ) , n l , w r i t e ( " Enter zz i f second and/or t h i r d not applicable. " ) , n l , prompt menu, readln(Character), reedln(Char state1), reedln(Char_state2), reedln(Char_state]), initial list characters(), asserts( current charandstates(Character, [Char state1, Char state2, Char_state]]) ), retract(remaining_char(Character) ), asserts(num_poss_spp(O) ), asserts(solution_found(no) ), a s s e r t s ( i n i t i a t i v e ( o ) ). / * The next rute assembles an i n i t i a l , co¢lptete t i s t of characters, using the fact that any taxon has the same l i s t of characters (but not of character-states, of course) as any */ other taxon in the group being treated initie|
initial
list_characters(Name) :species(na~es(Levet_name_tist),festures(Descriptor member(N, Level name l i s t ) , H = Lev_naM(sp, Name), n~=fflber(N, Descriptor and_states l i s t ) , N = [Cheracterl_), not(remaining_char(Character) ), asserta(remaining_char(Character) ), fail. List characters(Name) :species(names(Levet name t i s t ) , member(M, Levet n a m e t i s t ) , H = lev_nam(sp, Name).
features(_)),
establish_possible_spp :f i r s t char_three_states, current char_endstates(Charecter, Unkstates), species(r~mes(Level name l i s t ) , f e a t u r e s ( D e s c r i p t o r ~mber(N, Level name l i s t ) , H = tev_nam(sp, Name), meld0er(N, Descriptor_and_states_list), N = [Cheracter[Knststes], not( possible sp(Name) ), intersection(Unkststes, Knstates, I ) , not ( l = [ ] ) , asserta(possible_sp(Name) ), num_possspp(X), Y = (X+I), retract(num_poss_spp(X) ), esserta( num_poss spp(Y) ), write("Possibte species is ",Name),nl, fail,hi. establish_possible_spp :num_poss_spp(X), x=l, narrouest_possib[ e. • stab[ i sh possible_spp :num poss spp( X), X:O, nar rowest possible. establ i sh jx)ss i ble_spp :hum pess_spp(X ), ~ r i t e (*' " ) , n l ,
end s t a t e s _ l i s t ) ) ,
and s t a t e s _ l i s t ) ) ,
Identifying fossils arite("Number of possibte spp is ",X),nl, narroued_down. narrouest_possibte :" f i r s t conditions, possibte_sp(Name), retract(solution_fourcl(no) ), a s s e r t a ( s o t u t i o n f o u n d ( y e s ) ), write(" "),nl, w r i t e ( " Your species is ,,,Name),nl, show_species, cleanup. narrowest_possibte :" second_conditions, Hrite(" " ) , n t , retract(sotution_found(no) ), asserta(solution_found(yes) ), write(" Your species is one of the following - " ) , n t , write_species_liSt,hi, shoe_species, cleanup. narrowest_possible :thlrdconditions, write(" " ) , n t , retract(sotution_found(no) ), asserta(sotution_found(yes) ), w r i t e ( " ! know of no taxon with"),nt, write(" that (co~binetion o f ) " ) , n t , write(" character-state(s)."),nt,nt, cteanup. narrowed_down :solution_found(no), SWitch, narrow as possible. narrowed, doun. narrow_as_possible :" initiative(o), narrow_by_~rator.
narrow_as~ssibte :initiative(c), narrow_by_c~tero narrow_by_operator :next_char_three_states, reduce_if_10ossibte, conditions_futfilted, narro~estpossibte. narrow_by_operator :switch, narrow as_possibte. narrow_by_computer :" remaining_char(A), asserta(still_remaining_char(A) ), retract(remaining_char(A) ), fair. narrow_by_computer :not (cond| t i ons_fut f i J.ted), ~ i t t t e_down. nar row_by_coq)uter :-
817
8| 8
WM. R RIEDEL conditions f u t f i t t e d , narrowest_possible. whittte_down :another char three_states(_), reduce if_possibte, narrow_by_computer. conditions_futfitted :firs[conditions. conditions f u l f i t t e d :second_condi t ions. conditions_fur f i t ted :third_conditions. next_char_three_states :r e t r a c t ( c u r r e n t c h a r a n d s t a t e s ( _ , _ ) ), write (" " ) , n t , write (='Enter next character and three states. " ) , n t , write(" Separate and end with carriage returns. " ) , n l , write(" Enter zz i f second and/or third not applicabte. "),ni, prompt_menu, readtn(Character), readtn(Char_statel), readtn(Char_state2), readtn(Char_state]), asserts( current char and_states(Character, [Char_state1, Char state2, Char_state]]) ), !. first_conditions :num_possspp(X), X:l. secondconditions :initiative(o), not( remaining char(_) ), num_poss_spp(X), X>l. secondconditions :initiative(c), not(stitt_remaining_char(_) ), not( hetpfut_char( ) ), r,Jm_poss_spp(X), X>l. third_conditions :num_poss_spp(X), X
Identifying fossils
819
readln(Char state1), readln(Char state2), readln(Char state3), asserta( current char_and_states(X, [Char_state1, Char_state2, Char_state3]) ), !. find_helpful_char :not( helpful_char( ) ), estab..stand_posssp, estab other_poss spp, do the testing. find_helpful char. estab_standposs_sp :possibte_sp(Name), asserta(stand_poss_sp(Name) ). estabother_poss_spp :possible_sp(A), not(standj0oss_sp(A) ), asserta(other_poss_sp(A) 1, fail. estab_other_poss_spp. do the testing :test c h a r ( ) , retract(stand_poss_sp(_) ), cancel_other_poss_spp. cancel_other~possspp :other_pesssp(A), retract(other_poss_sp(A) ), fail. cancet_otherpossspp. test_char(A) :stilt_remaining_char(A), other_posssp(B), species(names(Level name tistX), features(Descriptor and states t i s t X ) ) , ilmlltber(N, Level name listX), M = tev_nam(sp, g), member(N, Descriptor_and_stateslistX), N = [AlStatesB], stand_posssp(S), species(names(Level name listY), features(Descriptor and states t i s t Y ) ) , member(P, Level name listY), P = lev._nam(sp, S), member(Q, Oescriptor_and_stateslistY), Q = [AlStatesS] , test_for._difference(StatesS, StatesB, A). test_char(A) :stilt_remaining_char(A), still_regaining_char(B), A <> B, retract( s t i l t remaining_char(A) 1, do the testing. test_char(A) :not(helpful_char(_) 1, still_remaining char(A), retract(still_remainingchar(A)
).
test for difference(Char_states$, Char_statesB, A) :-
820
W M R RIEDEL not(helpful_char(_) ), stltl_remalnlng char(A), different_set{Char statesS, Char_statesB, A), asserta(helpful_char(A) ), retract(still_remaining_char(A) ). different_set(Char statesS, Char statesB, ) member(M, Char statesS), not( member(M, Char_statesB) ).
:-
different_set{Char_statesS, Char_statesB, _) :member(M, Char statesB), not( member(M, Char statesS} ). reduce_if_possible :initiative(o), current_char and_states(Character, Unkstates), retract(remaining_char(Character) ), possiblesp(Name), species{names{Levet_name_iist),features(Descriptor and s t a t e s _ l i s t ) ) , member{M, Level name l i s t ) , M = lev_nam(sp, Name), member(N, Descriptor and states l i s t ) , N = [CharacterlKnstates] , intersection{Unkstates, Knstates, 1), l : [], retract(possibte_sp(game) ), num_poss_spp(X), Y = (X-l}, retract( num_poss_spp(X} }, asserta( num_poss spp(Y) ),
fail.
reduce if_possible :initiative(c}, current char and states(Character, Unkstates), helpful_char(Character}, retract(helpful_char(Character) ), possible_sp{Name),
spocies(names(Level name l i s t ) , f e a t u r e s ( O e s c r i p t o r _ a n d s t a t e s t i s t ) } , member(M, Lever_name_list), M = (ev_nam(sp, Name), member(N, Oescriptor_andstates_tist}, N = [Characterlgnatates] , intersection(Unkstates, Knstates, I ) , I = [3, retract(possibIe_sp(Name) ), num_poss_spp(X}, Y = (X-l), retract(num_poss_spp(X) ), asserta(numposs_spp(Y) ), fail. reduce_if possible :num_poss_spp(Y), write(" " ) , n [ , write("No, of possible spp is now ",Y),nl,
write_list. write l i s t :possibtesp{Name}, write("Possibtespecies is ",Name),nt, fail, write l i s t . write species_list :possibt e_sp(Name),
Identifying fossils write(" fail.
821
",Name),nL,
w r i t e species_List. cleanup cleanup cleanup cleanup cleanup cleanup cleanup cleanup
::::::::-
retract(current_char_andstates(_,_)),fait. retract(posa{ble_sp(_)),fait. retract(initiative( )),fail. r e t r a c t ( s o l u t i o n found( ) ) , f a i l . retract(remainingchar(_)),fait. retrest(stitt_remaining_char()),fait. r e t r a c t ( h e l p f u l char( ) ) , f a i l . retract(numposs spp( ) ) , f a i l .
cleanup :* r e t r a c t ( s t s n d p o s s _ s p ( ) ) , f a i l . cleanup :- r e t r a c t ( o t h e r poes s p ( _ ) ) , f s i t . cleanup :- r e t r a c t ( i m a g e ( , _ , . . . . . ) ) , f a i l . cleanup, terminate :wr~te(" Press any key to t e r m i n a t e . " ) , reedchar(_). member(X, [XI_]). n~-=mber(X, [_(Ta~t]) :- men/~er(X, T a i l ) . i n t e r s e c t i o n ( [ ] , _, [ ] ) . intersection([X~R], Y, [XlZ]) :member(X, Y), !, i n t e r s e c t i o n ( R , Y, Z). i n t e r s e c t | o n ( [ _ J R ] , Y, Z) :- i n t e r s e c t i e n ( R , Y, Z). p r o ~ t ,~nu :write (" "),tit r w r i t e ( " f t null - e3, gt3, ~ : nlxt~ber of feet - three, >3, none. " ) , n t , urite("abcl surf - maooth, r ~ h : surface of atx:~oa~n - ~ t h , ro~;Ih. " ) , n t , ~ r i t e ( " p o r _ c i r c - it13, gt13 : pore no. around greatest circumference - <13, >13. " ) , n l , w r i t e ( " a b d J ) o r - it20, gt20 : t o t a l ~ . of abdominal pores - <20, >20. " ) , n l , w r i t e ( " h o r n - bled, conic : horn - bl=K/ed, c o n i c a l . " ) , n t , w r i t e ( " t h o r _ l o n g - pron, ur4oron : Longitudinal rous of thoracic pores - , ) , n t , write(" pronounced, not pronounced. " ) , n t , write("uid_abd - prox, mad, d i s t : greatest width of abdomen - p r o x i m a l l y , " ) , n l , write(" medially, d i s t a l l y . " ) , n t . character and s t a t e s ( f t hum, "For number of f e e t , enter e3 and/or none and/or gt3 (or zz to make 3 s t a t e s ) . , ' ) . chsracter_ancl_ststes( mlx:l_surf , "For akxJominat surface, enter rmagh and~or sax~th and zz to make 3 s t a t e s ) . " ) . chsrac ter_arw:l st stes(por_c | rc, "For pores arour~ greatest circumferer~=e, enter gt13 and/or lt13 (and zz to make 3 s t a t e s ) . " ) . charac ter_and states( abd_por, "For t o t a l rK). sl:x:Jominat pores, enter tt20 characterandstates(horn, "For horn, enter btKI and/or conic (end zz character ar~:l states( thor_tor~i, "For t o n g i t , rows of thoracic rmres, enter character and states(tH d allxl, "For greatest width of s l 0 d ~ n , enter prox
and/or gt20 (and zz to make 3 s t a t e s ) . " ) .
to make 3 s t a t e s ) . " ) . pron and/or Lx~pron (and zz to make 3 s t a t e s ) . " ) . and/or ~
and/or d i s t (arK:l zz to make 3 s t a t e s ) . " ) .
/ * below are the routines f o r drawing the images on the screen * / showspecies :~ r | t e ( " \ n P r e s s an), key to see image(s) of s p e c i e s . " ) , reedchar(_), show t ~ , t . sho~_toop :possl bt e sp(Ni=ae),
WM. R. RIEDEL
822
species_image(Name,Title), show(Title), fait,!. show_loop. show(Id)
:image(Id,Name,Text,Sketch,Labets), graphics(2,0,15), line(16080,200,16080,31800,1), line(16080,B1800,30080,31800,1), 1ine(30080,31800,]0080,200,1), line(30080,200,16080,200,1), str_len(Name,L), Xl=40-(L/2), makewindow(9,15,0,'"',12,Xl,l,L), window_str(Name), makewindow(lO,7,0,"",13,1,10,78), makewindow(11,7,0,"",O,O,12,80), draw_it(Sketch), ptace_labet(Labets), shiftwindow(10), display(Text), retllovewi rK~OW, shiftwindow(9), removewindow, shiftwindow(11), removewinclow° text,!.
draw_it(t]) :- !. draw_it([HIT]) :draw_tines(H), draw_it(T). draw_tines([_,_[[]]) :- !. draw_lines([Xl,YllT]) :T=iX2,Y21_], line(YI,Xl0Y2,X2,7), draw_lines(T). place_label(t]) :- !. ptace_labeli[HlT]) :H=ent(S,Tx,Ty,Px,Py), cursor(Ty,Tx), write(S), str_ten(S,L), X1=Tx*400-lOO,Y1=Ty*1280-320, X2=Xl+L*400+200,Y2=Y1+1760, YB=Yl+800, find_x(Xl,X2,Px,X]), draw_box(Xl,Yl,X2,Y2), [ine(Y3,X],Py0Px,7), place_label(T). find_x(W,_,Y,Z) :- YX,Z=X. draw box(X1,Y1,X2,Y2) :tine(Yl,Xl,Yl,X2,7), line(Yl,X2,Y2,X2,7), tine(Y2,X2,Y2,Xl,7), tine(Y2,Xl,Yl,Xl,7).
/* the data */ species (names ([[ev_nam(gen, podocyrtis), lev_nam(sp, ampta)]), features (lift_hUm, none], (abd_surf, smooth], [por_cir¢, gt13]0
Identifying fossils (abd por, gt20], thorn, conic], [thor_tong, pron], [wid_abd, med, d i s t ] ] )). species [names ( [ l e v nam(gen, podocyrtis), lev_nam(sp, aphorma)]), features ( [ [ f t nun, e3, none), [abd_surf, smooth), [por_circ, gt13], [abd_por, 9t20], [horn, brad, conic], [thor_long, pron], [wid_abd, prox, ned] ] )). species (na~es ([tev_nam(gen, podocyrtis), lev nam(sp, chalara)] ), features ( [ [ f t nun, none], [abd_surf, smooth], [por_circ, lt13], [abd por, gt20], thorn, blad], [thor long, unpron], [wid abel, d i s t ] ] )). ;pecies (names ([tev_nam(gen, podocyrtis), tev nam(sp, diamesa)]), features ([[ft_num, eS], [abd surf, smooth], [por circ, gt13], [abcl_por, gt20], thorn, conic], [thor long, pron], [wid_abcl, p r o x ] ] ) ) . ;pecies (names ([lev_nam(gen, podocyrtis), lev_nam(sp, dorus)]), features ( l i f t _ n u n , gt3], [sbd_surf, smooth), [por circ, gt13], [abd_por, gt20], thorn, blad], [thor long, pron], [wid abd, prox, ned, d i s t ] ] )). ;pecies (names ([tev_nam(gen, podoeyrtis), lev namtsp, f a s c i o l a t a ) ] ) , features ( t i l t nun, none), [abd_surf, smooth, rough), [por circ, 9t13], [abcl_por, gt20], thorn, blsd, conic], [thor_long, unpron], [wid_abd, med]] )). species (names ( [ l e v na~(gen, podocyrtis), [ev nam(sp, goetheana)]), features ( [ [ f t nun, none], [abd_surf, smooth]. [por_circ, I l l S ) , [abd por, it20), thorn, brad), [thor tong, unpron], [wid abd, d i s t ] ] ) ) o
spec i e s i moge(ampta, "Podocyr t i s ampla" 1. spec +e s image( aphormo,"Podocyr t i s aphorma" ). spec ~e s image(cha l ara, "Podocy r t i s_cha t ara" ). spec 1e s image(di amesa,"Podocyr t i s_di amosa"). spec 1es i mage(dorus, "Podocyr t i s_dorus" ).
spec~es_imoge(fasciolata,"Podocyrtis fasciolata"). spec 1e s image[ goetheana, "Podocyrt i s goet heana" ).
823