appendix a: a quick tour of turbo prolog what is tu~o prolog?978-3-540-46840-0/1.pdf · appendix a:...
TRANSCRIPT
APPENDIX A: A QUICK TOUR OF TURBO PROLOG
WHAT IS TU~O PROLOG?
PROLOG is an acronym for programming in logic. It was created in
1972 by the Faculty of Sciences, Luminy, in Marseilles, France.
Prolog as described in Clocksin and Mellish' book, "Programming
in Prolog', which is generally known as C&M Prolog, is widely
accepted as the standard version of Prolog. TURBO Prolog,
created by Bor!and Inc., is an IBM PC implementation of Prolog.
This creation is a fast running version of Prolog which is both a
subset and a superset of C&M Prologo The key features of this
implementation of Prolog are described in this Appendix°
PROGRAMMING IN PROLOG
Programming in Prolog consists of the following:
- Declaring some facts about objects and their
relationships,
- Defining some rules about these and their
relationships, and
- Asking questions (in the form of "goals") about these
objects and their relationships.
objects
The notions of facts, rules and goals may be stated as follows.
FACTS
83
Facts define relationships among objects. For example, a
fact may be stated as
teaches(smith, math)
which means that there is a relationship "teaches"
between objects "smith" and "math".
The order of objects (smith, math) is important in
stating a fact for the correct interpretation of that
fact.
The name of a fact is called a predicate and the objects
involved in the predicate are called arguments. In the
above example, "teaches" is a predicate and "smith" and
"math" are the arguments.
A collection of facts is called a database. A typical
Prolog database is shown below.
teaches(smith,math)
teaches(schriber,electronics)
teaches(prabhakar,prolog)
teaches(barua,unix)
teaches(smith,lisp)
Figure AI: A TYPICAL PROLOG DATABASE
GOALS
A goal has the same form as a fact. Whenever a goal is posed,
84
Prolog searches through its database to check if the goal is true
or false. This is done as follows. Two facts match if their
predicates as well as the corresponding arguments are identical.
If a match is found, Prolog comes back with the answer "true".
Otherwise it returns "false". For example, in reference to the
database of Figure AI, one may ask: teaches(smith,math).
Prolog will respond "true".
RULES
Rules may be compared to IF-THEN statements of conventional
programming
generalized
relationships.
the following.
languages. In Prolog terminology, rules are
statements about different objects and their
For example, the relationship "taught" may imply
Smith has taught anyone whose department is math and who has
credited OR. This relationship may be generalized into a rule:
Smith has taught X, where department of X is
math and X has credited OR.
This generalized rule may be written in Prolog as
taught(smith~x):- dept(x,math), credits(x,or)
One may easily note that the above rule has two parts: the head
taught(smithtx) and the body dept(x,math), credits(x,or).
The comma between goals dept and credits denotes the conjunction.
The comma implies that both goals must be satisfied for the
85
overall goal to succeed (i.e. be true). In general, the body of
a rule will be a conjunction of subgoals. The :- notation
implies that the left hand side is true if the right hand side is
true.
CLAUSES
The difference between a fact and a rule is that a fact does not
have subgoals. A "clause" in Prolog is a general term for a fact
or a rule. In the example of Figure AI, "taught" and "dept" are
both clauses.
VARIABLES
Variables allow us to pose generalized goals. For example, if we
wish to find which courses are taught by Smith, then instead of
taking each possible subject and trying it to match it with the
facts in the database, a generalized goal may be posed as
teaches(smith,X)
Note here the use of upper case X, which denotes a variable. On
encountering this goal Prolog will search its database and will
give a list of all "X" values in the database that satisfy this
goal, as follows.
X = math
X = lisp
86
At any time variables may be "instantiated" (bound to a certain
value, e.g. statistics) or "uninstantiated" (not bound to any
particular values)o
BACKTRACKING
In Prolog~ each goal keeps its own "place marker" in the
database° For example, in attempting to check the following goal
(to be true or false)
teaches(smith,X), credits(barua, X)
Prolog starts with an attempt to satisfy the first (sub)goal. If
this first goal is in the database, Prolog will mark the place of
this match in the database and then try to match the second goal
from the start of the database. If the second goal fails, Prolog
will go back to the place of last instantiation of X, i.e. the
place marker of the first goal and start searching through the
remainder of the database for another match.
If another match to the first goal is found, Prolog will attempt
to satisfy the second goal again with this second instantiated
value for X, from the start of the database (see Figure A2).
Thus in a chain of goals, if any one goal fails, Prolog
backtracks to the previous goal and tries to prove it again with
another variable binding (instantiation). Prolog moves
relentlessly forward and backward through the conditions, trying
every available binding in an attempt to get the goal to succeed
in as many ways as possible. The solution is displayed as a list.
87
IM ARKER = START OF DATABASE
TRY TO SATISFY THE LEFT-MOST GOAL FROM MARKER DOWN
!
PUT A MARKER AT SATISFIED GOAL. I INSTANTIATE APPROPRIATE VARS (X) I !
REMOVE THE FIRST GOAL FROM THE CONJUNCTION. RECURS
WITH REDUCED LIST.
NON-INSTANTIATE VARIABLES AT THIS GOAL. RESTART FROM PLACE MARKER
..... ~ y
N /~IS THERE A ~ N
Figure A2: BACKTRACKING MECHANISM IN PROLOG
CONTROL OF BACKTRACKING USING "CUT"
The primary purpose of "cut" is to prevent or stop backtracking
based on a specified condition. The cut predicate is specified
as an exclamation mark (!). It has no arguments and it always
succeeds. One it succeeds, two things happen:
1.
2.
88
There can be no backtracking on the goals towards the left
of the cut°
If there are other definitions of the predicate, other than
the current one, these are not tried.
For example~ consider a predicate "division" whose purpose is to
determine the grade for a student based on his percentage marks.
The clauses may be written as
grade(PERCENTAGE MARKS,GRADE):- PERCENTAGE MARKS>75, GRADE="A",!.
grade(PERCENTAGE MARKS,GRADE):- PERCENTAGE MARKS>60, GRADE="B",!.
grade(PERCENTAGE MARKS,GRADE):- PERCENTAGE MARKS>50, GRADE="C",!.
grade ( PERCENTAGE MARKS, GRADE ) : - GRADE=" F".
If this predicate is tried (ignoring the cut) with
PERCENTAGE MARKS=80, all the four rules will succeed and Prolog
will give four answers. But this is not desired. When a cut is
placed in the first rule, the moment that rule is satisfied (i.e.
PERCENTAGE MARKS>75) no further definitions are tried.
This is one way of using the cut~ There are many other ways in
which a cut may be used to control backtracking in Prolog.
DATA TYPES IN TURBO PROLOG
The basic data type in Prolog is a "term".
the different types which a term can take.
Figure A3 identifies
89
TERM
I VARIABLES
X,COURSE
I OBJECTS
I NON-VARIABLES
i i
LISTS
i OTHERS
I !
STRUCTURES
[a,b,c,d], [1,345,12]
f I ! .... I !
SYMBOL STRING INTEGER REAL CHAR FILE
address(street, city,zip)
barua, "hello" i, 45 23.89 "a", xoutput, smith "smith" "A" facts
Figure A3: BASIC DATA TYPES IN TURBO-PROLOG
LISTS
A list is an ordered sequence of terms. The components of a list
should be of the same data type. Examples of valid lists are
name, numbers, etc., where
name=[smith,barua,codd] numbers=If,2,25]
A list can be written in several alternate ways, by showing its
head and tail. For example, for list "name" one may have
equivalent lists:
name=[smith,barua,codd] name=[smith¶[[barua,codd]] name=[smith¶[[barua~f[codd]]]
90
One may freely use the above equivalent notations to build
predicates for basic list manipulations such as intersection,
union, membership functions~ etc.
BUILT-IN PREDICATES
TURBO Prolog contains a variety of built-in predicates. These
standard predicates support a variety of repeatedly used tasks
and functionsr such as controls data input and output, screen
handling, type conversionsr etc.
DATABASES IN TURBO PROLOG
As mentioned earlier, a Prolog program is a database; Prolog
acts as a very powerful query language that can handle the
contents of this database. For instance, Prolog permits the
selection of facts from a database. The program, however, is a
static database. This implies that the database does not change
with time. Once a Prolog program has been compiled, the
knowledge in this database is frozen.
Prolog also has a dynamic database in which facts related to the
current problem being solved are stored. This dynamic database
is stored in memory along with the static database. The dynamic
database can be saved to disk using the save predicate and read
back using the consult predicate.
91
THE GENERAL STRUCTURE OF A TURBO PROLOG PROGRAM
The four sections in a TURBO Prolog program are as follows:
DOMAINS
data type declarations
DATABASE
predicates of dynamic database should be defined here
PREDICATES
every predicate must be declared in this section
CLAUSES
contain facts and rules
TURBO PROLOG PROGRAMMING ENVIRONMENT
TURBO Prolog has a user friendly environment with bouncing bar
menus. This is an interactive support that makes program
development fast. A display shows the environment screen.
Various menu options are as follows:
RUN
COMPILE
EDIT
OPTIONS
FILES
SETUP
QUIT
For running a program
For compiling a program
To enter the editor
To select compiler options (produce OBJ/EXE files)
File operations such as copy, rename, delete, etc.
To change window sizes, colors, directories, etc.
To quit the programming environment.
92
In the display, the editor window shows a predicate that will
check the membership of an element in a list. When it is run
(after compilation~ as shown in the message window), the dialog
window is activated. Goals may now be posed and solutions
obtained as shown. The trace window would show a step by step
progress of execution if desired.
APPENDIX B: CHRONICLE OF A TYPICAL DATABASE DESIGN SESSION WITH THE SYSTEM
SCREEN 1
PRELIMINARIES
are similar to paper files that data is stored on magnetic I media rather than on paper, j
In a database the different pieces of related information are grouped at one place. For example, a database may contain :
Roll No Name Class Home Town 8678 Kasturi M.Tech. Madras 8760 Vijay B.Tech. Delhi
The individual data items in a database (Roll No, Name, etc.) are called attributes.
Press any key to continue ......
SCREEN 2
PRELIMINARIES
are similar to paper files that data is stored on magnetic I media rather than on paper. I
Soon, You will be asked some questions regarding the attributes (i.e. data items) that will appear in your database.
You should answer these questions thinking as if you are building ordinary paper files for storing data.
Press any key to continue ......
94
SCREEN 3
-Attributes [data items to be stored ]
As you start the process of building your database you may already have a good idea about the data files you would like to have.
For example, for a inventory manage- ment database, you might have :
- a master file of parts - a master file of vendors
DIALOC Can you already foresee the data files you will need (Y/N) ?N
SCREEN 4
Attributes-
I data items to be stored mechno skll_no skll_cat mech_name
-ATTRIBUTES IN FILE:
DIALOC > Input the attributes you wish to store
Give one attribute per line ... At end press Return
> MECH_NO > SKLL_NO > SKLL_CAT > MECH_NAME > MECB_AG~
95
SCREEN 5
i -Attributes . . . . I data items to be stored
EXAMPLE OF GROUPS
In a STUDENT database with attributes :
Name, Rollno, Class, Street, City, Zip
we might have the following logical groups:
GROUP I: Name, Rollno, Class GROUP 2: Street, City, Zip
mech_no skll_no skll_cat mech_name mechage shop_no city supv prof
• ATTRIBUTES IN FILE: ..............
' DIALOG ,, I> - If you can now 'group" the above
attributes in some logical way, that would reduce the number of questions you will need to answer in this dialog (see example)
Press any key to continue ...
l "d Attributes--~ ata items to be stored
SCREEN 6
mech_no skll_no skll_cat mech_name meeh_age shopno city supv prof
--'ATTRIBUTES IN FILE: ....
l! DIALOG ......
> Can you see any such attribute groups (Y/N)?Y
> Please type the group name > MECHANIC
96
SCREEN 7
Attributes data items to be stored
mechanic mechno ~mechname mechage shopno
skllno skllcat city supv prof
ATTRIBUTES IN FILE:
l
DIALOC ............ > For Group : mechanic > Enter one attribute per line ,..
When done, press Return > MECH_NO > MECH NAME > MECH_AGE > SHOPNO > SKLLNO
L Attributes t items to be stored
SCREEN 8
ATTRIBUTES IN FILE; shop mech age shop_no shop_no city skllno sUpV prof
skill skll_no skll_cat
mechanic meeh_no mechname
DIALOC > To begin with we will make one file
for each group.
Attributes which are not in any group will be put in a file named 'ungrouped'.
> Press any key to continue ....
97
SCREEN 9
i Attributes data items to be stored
--FILES ......... ! mechanic I skill shop 1
,ATTRIBUTES IN FILE: shop meeh_age shop_no shop_no city skll_no supv prof
skill skll_no skll_cat
mechanic mech_no mech_name
............. DIALOG ...... f> In these files, you might be able
to further group the attributes.
> Press any key to continue ....
Attributes I data, items to be stored
--FILES ................ mechanic skill shop
SCREEN i0
ATTRIBUTES IN FILE: mechanic prof skll_no shop_no mech_age seth_name mech_no
~DIALOG ....... > In File: mechanic > Can you see any such attribute
groups (Y/N)?N
98
SCREEN ii
Attributes- data items to be stored
--FILES
mechanic 1 skill shop
] supv I city
shopno
ATTRIBUTES IN FILE: shop
i!
DIALOC , NEXT STEP
I ED T THE DATA 1 PROCEED WITH DIALOG I
SCREEN 12
Attributes- data items to be stored
supv city shop_no
ATTRIBUTES IN FILE; shop
EXAMPLE OF KE~--
For a STUDENTS file~
ROLL NO NAME CLASS
8769 Kasturi M.Tech. 8734 Vijay B.Tech.
ROLL NO is unique for all the entries in this file.
Hence ROLL NO is a KEY.
-DIALOC > In every file/group there will
be an attribute or a group of attributes called:
KEY whose value is unique for all the entries in that file/group.
Press any key to continue ....
99
SCREEN 13
a ... Attributes. dat items to be stored
KEy - l attribute(s) that determine values of all attributes
FILES ...... I chanic ill op
i sUpv city shop_no
ATTRIBUTES IN FILE: shop .....
DIALOC > In general, there may be more than
one key in a file (or a group).
> Press any key to continue ....
SCREEN 14
Attributes-,, ,data items to be stored
KEY ' attribute(s) that determine values of all attributes
--FILES ~mechanic iskill ~shop
KEYS
ipro f ATTRIBUTES IN FILE; mechanic ...........
Iskll_no shop_no imech_age mech_name mech_no
I DIALOC > Now for file: mechanic > Enter the attributes that form a key,
Enter one attribute per line, I When done, press return .> MECH_NO I > SKLL_N I > Undeclared/Mis-spelt attribute I > SKLL_NO
--L
100
Attributes
i data items to be stored
KEY. I attribute(s) that determine values of all attributes
--FILES--- mechanic skill shop
~ K E Y S FILE: mechanic skll_no,mechno.
SCREEN 15
...... ATTRIBUTES IN FILE: mechanic-- prof skllno shopno mechage mech_name mech_no
• DIALOC ........ { When done, press return i> MECH_NO I} SKLL_N
Undeclared/Mis-spelt attribute SKLL_NO
I > > Any more attributes in the key (Y/N)? > Are there any more keys (Y/N) ?N
SCREEN 16
--KEY ATTRIBUTES---- NON KEY ATTRIBUTES
--FILES 7 mechanic skill
i
.DIALOC .. > Locate the window titled KEY ATTRIBUTES
on the screen (upper left corner) and Also the NON KEY ATTRIBUTES window (up) Proceed now keeping these two windows in mind.
> Press any key to continue ....
101
SCREEN 17
~ FILES chanic ill op ....
--KEY ATTRIBUTE~- NON KEY ATTRIBUTES
.DIALOC > Normally key attributes will determine
the values of non-key attributes.
However, there may be exceptions.
> Press any key to continue ....
~ FILES chanic ill op
SCREEN 18
• {--KEY ATTRIBUTES--]- !prof shop_no mech_age mech_name
NON KEY ATTRIBUTES ...........
DIALOG ...... > In above windows do you see any key
attribute whose value depends on some of the non-key attributes (Y/N)? N
102
SCREEN 19
NON KEY ATTRIBUTES
--'Multi valued attributes' EXAMPLE :
ROLL NO COURSES TAKEN 8785 IMET02,CSSOI,IME624 8766 IMES02,IME624,ME851 8767 IME602,IME673,IME621 8769 HSS730,EE450
Here, COURSE TAKEN can be seen to take several values for any given value of the key, ROLL NO.
~DIALOC > Now we need to know which among the
attributes listed can take several values for any given value of the key (see example).
> Press any key to continue ....
SCREEN 20
-~Keys---------7- [ skll no,mech no. ~ |prof
1 |shop_no |mech_age
~ ~ I I mech-name
--'Multi valued attributes' EXAMPLE :
• NON KEY ATTRIBUTES
ROLL NO COURSES TAKEN 8765 IME602,CS601,IME624 8766 IME602,IME624,ME651 8787 IME602,IME873,IME821 8769 HSS730,EE450
Here, COURSE TAKEN can be seen to take several values for any given value of the key, ROLL NO.
DIALOC > Is there any attribute above which can
take several values for a single value of the key (Y/N)? N
103
SCREEN 21
shop_n---------~ Keys
Example of part key ....
Roll No Name Course Grade
1267 ATUL CADS A 1267 ATUL DPS B 1267 ATUL OR C 1270 JOY CADS C 1270 JOY DPS B
Key is (Roll No, Course) Name depends on only a part of the key, i.e. Roll No.
-I supv city
NON KEY ATTRIBUTES
DIALO(}.. > Here we want to see if there are
some attributes which depend on only a part of the key (see example).
> Press any key to continue ...
I ;or Key Ys ......
skll no,mech no.
Example of part ke~..
Roll No Name Course Grade
1267 ATUL CADS A 1267 ATUL DPS B 1267 ATUL OR C 1270 JOY CADS C 1270 JOY DPS B
Key is (Roll No, Course) Name depends on only a part of the key, i.e. Roll No.
SCREEN 22
I prof shopno mechage mech_name
NON KEY ATTRIBUTES
.... DIALOG > For the Key shown in KEYS window:
Is there any attribute which is affected by only a part of the key (Y/N)?Y
104
SCREEN 23
~ K E Y S - - For Key : skl l_no, mech_no.
. --Example of part key- . .
Roll No Name Course Grade
1267 ATUL CADS A 1267 ATUL DPS B 1267 ATUL OR C 1270 JOY CADS C 1270 JOY DPS B
Key is (Roll No, Course) Name depends on only a part of the key, i.e. Roll No.
prof shop_no mech_age mechname
NON KEY ATTRIBUTES
DIALOG .......
Is there any attribute which is affected by only a part of the key (Y/N)?Y > Please enter the part key attributes
one by one. When done, press Return > MECH_NO >
> Any more attributes in part key (Y/N)?N
SCREEN 24
......... l - - -
skli no,mech no.~
~. ............. Example of part key
l I Roll No Name Course Grade
1267 ATUL CADS A 1267 ATUL DPS B 1267 ATUL OR C 1270 JOY CADS C 1270 JOY DPS B
Key is (Roll No, Course) Name depends on only a part of the key, i.e. Roll No.
prof shop_no mech_age mech_name
NON KEY ATTRIBUTES..
DIALOG .................. > Please enter the part key attributes i one by one. When done, press Return '> MECHNO ~>
'> Any more attributes in part key (Y/N)?N i> Please type the affected attribute '> MECH NAME > Any more such attributes (Y/N)?Y
105
SCREEN 25
NORMALIZING ........................ > Retracting FD: ['~mech_no"] -> ["mech_name"] > Closure of LHS: ["mech_no","mech_age'~,"shop no","city","supv "] > Does not contain RHS, Asserting again > Retracting FD: ['shop_no"] -> ["city"] > Closure of LHS: ["shop no","supv"] > Does not contain RHS, Asserting again > Retracting FD: ["shop_no"] -> ["supv"] > Closure of LHS: ["shop no","city"] > Does not contain RHS, Asserting again > Retracting FD: ["skll_no"] -> ["skll_cat"] > Closure of LHS: ["skll_no"] > Does not contain RHS, Asserting again > Retracting FD: ["skll_no","mech_no"] -> ["prof"] > Closure of LHS: ["skll no","mech_no","skll_cat","mech name","mech age","shop _no","supv","city"] ~> Does not contain RHS, Asserting again > Redundant F.D's eliminated
!> Loss-less Join guaranteed > Eliminating redundant relations > 3rd NF obtained > Press any key to continue ....
SCREEN 26
.NORMALIZINC > 3rd NF obtained > Press any key to continue .... > Decomposing into BCNF the relation : skll_no,mech_no,prof. > Finding Projections > Decomposed relation: skll no,mech no,prof.
> Decomposing into BCNF the relation : skllno,skll_cat. > Finding Projections > Decomposed relation: skll_no,skll_cat.
> Decomposing into BCNF the relation : shop no,supv,city. > Finding Projections > Decomposed relation: shop_no,supv,city.
> Decomposing into BCNF the relation : mech_no,mech_name,mech_age,shop_no. > Finding Projections > Decomposed relation: mech_no,mechname,mechage,shop_no.
> Checking for dependency preservation > Final filing scheme will be written to a file - 'OUTPUT',
which can be printed using 'TYPE' command
> Press any key to continue ....
106
SCREEN 27
OUTPUT Notes
RELATION SCHEME IN FOURTH NORMAL FORM
ATTRIBUTES IN THE RELATION: mech_no, mech_name, mech_age, shop_no.
KEYS: mech_no,
ATTRIBUTES IN THE RELATION: shop no, supv, city.
KEYS: shop_no.
--Scroll PgUp-PgDn-Page Fi-Print page F2-Prin% all
SCREEN 28
OUTPUT Notes
ATTRIBUTES IN THE RELATION: skll_no, skll cat.
KEYS: skll_no.
ATTRIBUTES IN THE RELATION: skll no, mech no, prof.
KEYS: skll_no, mech_no.
--Scroll PgUp-PgDn-Page FI-Print page F2-Print all
APPENDIX C
TURBO PROLOG PROGRAM LISTING
There are two types of ~ i l es in t h i s sof tware:
i ) F i l e s w i th extensions " . t x t ' i i ) F i l e s wi th extension ' . p r o '
' . t x t " F i l e s
These F i l es contain t ex t (such as d e f i n i t i o n s , examples, e t c . ) which is to be d isp layed during the d i a l o g .
There are 13 '.txt' Files. These are listed below:
INSIGNIA TXT TITLE TXT SCREENIA TXT SCREENIB TXT SCREENIC TXT OPEN_SCR TXT SCREEN2A TXT SCREEN~B TXT SCREEN2C TXT KEYS_DEF TXT KEYS_EG TXT MVD_EG TXT PARTFD TXT
The l i s t i n g 0¢ these F i l es is embedded in the l i s t i n g of ' . p r o ' F i l e s . E a c h F i l e appears at the place where i t is ca l l ed by the TURBO-PROLOG cede,
'.pro' Files
These ¢ i l e s conta in the TURBO PROLOG code,
There are 6 '.pro' Files, These are listed below:
UTILITY.PRO Contains utility predicates For opera t ions , such as: union, sub t rac t i on , e tc .
standard l i s~ i n t e r s e c t i o n ,
SCREENS.PRO Contains predicates For performing standard screen Funct ions, such as: d i s p l a y of l i s t s , d i sp lay of attributes, etc.,
108
INPFILE,PRO
FDS.PRO
UI.PRO
Predicates in t h i s sec t ion l e t the user input the data- i tems he wants to s tore in the database to be designed,
Predicates in t h i s sec t ion conduct tha t part of the dialog which infers the functional dependencies From the user.
Main program For the user i n t e r f a c e . Master con t ro l o~ the d ia log resides w i th the predicates in t h i s F i l e .
NORM.PRO Predicates in this tile implement the no rma l i za t i on a lgo r i t hms .
STEPS FOR COMPILING THE PROGRAM:
i . Check t ha t a l l ~,pro" and ' , t x t ' ~ i l es as l i s t e d above are in the same d i r e c t o r y ,
2, Enter the TURBO-PROLOG environment (vers ion 1.00). Set the defaul~ d i r e c t o r i e s same as the d i r e c t o r y in which a l l your ' . p r o ' and ' , t x t ' ~ i l e s are s tored,
3. Load the F i l e : UI.PRO and compile using 'OBJ' op t ion (For details refer pp, 202 oF reference [ 2 & 3 .
4. Load the t i l e : NORM.PRO and compile using 'OBJ' op t ion .
5, Create a small ' . B A T ' t i l e named 'NORMEX,BAT' w i th Fo l lowing DOS commands:
echo oFF ui norm echo on
6. Quit the TURBO-PROLOG environment,
7. Ensure that TURBO-PROLOG libraries :
PROLOG.DBJ !NIT.OBJ
are in the same directory in which the ',OBJ' ~iles generated in step 3 & 4 are placed. Also the MS-DOS l i n k e r 'LINR,COM' and a batch t i l e PL!NK.BAT (which comes wi th TURBO-PROLOG) should be in the same d i r e c t o r y
8. Link the compiled modules using the commands:
piink ui plink normex
This should crea~e two Files : ~i,exe and norm,exe,
9. You can run the program by typ ing 'norme×' on the t e r m i n a l .
109
STEPS FOR MAKING CHANGES IN THE PROGRAM:
i . Depending on the nature o~ the change, and using the desc r i p t i on o~ ' . p r o ' ~ i l es given above, t race the ~ i l e in which the concerned pred icate is l i k e l y ~o appear.
~. Using the 'comments' given in ~hat ~ i l e (o~ step I ) t race the sec t ion o~ i n t e r e s t .
3. Trace the execut ion , s t a r t i n g ~rom the top l e v e l pred icate and reach the po in t o¢ your i n t e r e s t . Now you can make the changes you des i re .
/~ LISTING OF VARIOUS FILES . /
/ * Each ' . p ro ' ~i le has various sections, each section beginning ~/ /~ with predicate declarations. Following have been specified ~or ~/ /~ each o? section: #/
/~ Purpose ~ / /~ Top-level Predicate ~/ / * ~/ /~ Screen Numbers ~/
I* ~i
Purpose/Role o~ the section The predicate which controls the ~low o~ execution in that section Screen Numbers (o~ Appendix B) to which this section corresponds
110
/ * F I L E : U I . P R O * / /* ./ /* Main program for the user */ / * in~erface. Master cont ro l of * / / * the d ia log resides wi th the * / / * predicates in th i s f i l e , * / I. ./
code=B000 DOMAINS
list=symbol* {ile=output
DATABASE
entity_strong<symbol) attribute_es(symbol,symbol) all_files(list) nfiles(integer) entity_weak(symbol,symbol) attribute_ew(symbol,symbol,symbol> key_es{list,list) key_ew(list,list,list) ~d(list~list) ~dmin(list~list> m v d ( l i s ~ , l i s t ) fdj(list,list) pj(list~list) attributes(list) key(list) user(string) schema_nf3(list) schema bcnf<list) dep_preserved(string)
include include include include
" u ~ i l i t y ~ pro" ~screens.pro" "i~ds. pro" " i n p ~ i l e , pro"
111
/ ~ ~ ~ ~ ~ ~ ~ ~ * ~ * ~ ~ /
/~ PURPOSE: ~IVES THE USER AN OPTION TO REVISE ~/ /~ OLD DESIGN ~/
/~ TOP LEVEL PREDICATE: inputdata ~here~ ~/
/~ SCREEN NUMBERS: No corresponding screen numbers in ~/ /~ Appendix B ~/
PREDICATES
inputdata_wherel inputdata_where2 inputdata where save~ds
CLAUSES
save~ds:- clearwindow, w r i t e ( " > Saving the dialogue in ~ i l e : " ) , user(X), write(X),nl,nl, write("> Please wait .... "),nl,nl, save<X), w r i t e ( " > Saving Complete, " ) , n l , n l , w r i t e ( " Press a key to continue . . . . " ) , r e a d c h a r ( ) , clearwindow.
inputdata where:- makewindow(6,2,11,"DIALOG",14,2,10,70), w r i t e ( " > Give a name For the database you want to design: " ) , readln(FILE1), not(FILE1="")~ asserta<user(FILEl)>, clearwindow, w r i t e ( " > The data requirements you input during th i s d i a l o g " ) , n l , w r i t e ( " w i l l be stored. This w i l l a l low you to revise t h e " ) , n l , w r i t e ( " design on some l a t e r date, i~ the need a r i s e s . " ) , n l , n l , w r i t e ( " > Press any key to continue . . . . " ) , r e a d c h a r ( ) , removewindow, screen2, inputda~a, !.
inputdata_where:- removewindow, inputdata where.
112
inputdata where2:- wr i te ( "> Enter the old design name : ~), readln(X), consult(X), !, asserta(user(X)), removewindow, makewindow(4,0,O,"",7,1,3,3), makewindow(5,52,7,"ATTRIBUTES",O,34,14,45), makewindow(3,2,11,"DIALOG",i5,35,10,45), display ~iles, shi~twindow(3), nextstep=
inputdata_where2:- wr i te ( "> No such design name e x i s t s " ) , n l , n l ~ wr i te ( "> Do you want to input again (Y/N)? " ) , readln(ANS)~ upper_lower("Y",ANS),nl ,nl , !, inpu~data where,.
inputdata where2:- removewindow, inputdata where.
inputdata where1:- makewindow(6,2,11,"DIALOG",14,2,10,70), clearwindow, wr i te ( "> Do you wish to revise an old design readln(ANS), u p p e r l o w e r ( " Y " , A N S ) , n i , n l , inputdata_where~, !.
inputdata_whe~e1:- removewindow, inputdata where.
(Y/N) ? " ) ,
113
I . e l /~ PURPOSE: MASTER CONTROL OF THE DIALOG * /
/~ go e/
I~ 1-26 e l /~ . I
TOP LEVEL PREDICATE
SCREEN NUMBERS:
PREDICATES main_control go s t a r t
CLAUSES
main_con t ro l : - s tar t~ i n t r oduc t i on , inputdata_wherel , save#ds, keys, nex t s tep , ~ds, save( "p ipe" ) .
s t a r t : -
goal
a s s e r t a ( a l l _ ~ i l e s ( [ 3 ) ) , asse r ta (nF i l es (O) ) .
main con t ro l .
go.
114
/~ FILE : NORM.PRO ~/
/~ The predicates in this ~ i le ~/ /~ implement various normalization ~/ /~ algorithms, ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
code=6000 DOMAINS
list=symbol~ Pile=output
DATABASE
entity_strong(symbol) a t t r i bu te es(symbol,symbol) a l l _ ~ i ! e s ( l i s t ) n~i les( integer) entityweak(symbol,symbol) attribute_ew(symbol,symbol,symbol) key_es ( l i s t , l i s t ) key e w ( l i s t , l i s t , l i s t ) ~ d < l i s t , l i s t ) f d m i n ( l i s t , l i s t ) mvd< l i s t , l i s t ) Cdj(list,list) pj(list,list) attributes(list) key(list) user(string) schema n~3(list) schema_bcnf<list) dep_preserved(string)
include " u t i l i t y . p r o " include "displays. pro"
115
I ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ I
/~ PURPOSE: TO FIND THE CLOSURE OF A SET ~/ /~ OF ATTRIBUTES ~/
/~ TOP LEVEL PREDICATE closure ~/
PREDICATES
c l o s u r e ( s t r i n g , l i s t , l i s t ) g e t F d ( s t r i n g , l i s t , l i s t )
CLAUSES
/~ c l o s u r e ( s t r i n g , l i s t i , l i s t 2 ) ~/ /~ Computes closure ( l i s t l ) o@ a t t r i b u t e s ( l i s t 2 ) /~ w . r . t . ~ .d 's denoted by s t r i n g ,
closure(S,A,APLUS):- get@d(S,LHS,RHS), subset(LHS,A), not (subset (RHS,A)), union(TEMP,A,RHS), closure(S,TEMP,APLUS), !.
closure(_,A,APLUS):- !,
APLUS=A.
/~ g e t f d ( l i s t i , l i s t 2 ) ~/ /~ Picks up one fd From the l i s t
getfd("F",LHS,RHS):- fd(LHS,RHS).
getfd("F",LHS,RHS):- Fdmin(LHS,RHS).
getfd("P",LHS,RHS):- pj(LHS,RHS).
of f , d ' s
116
/ * ./
I * PURPOSE: TO COMPUTE THE MINIMAL COVER OF * / / * A SET OF FUNCTIONAL DEPENDENCIES * / / * . / / * TOP LEVEL PREDICATE: minimum cover * /
/ * . / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
PREDICATES
reducefds reduce lhs l r e d u c e l h s 2 ( l i s t , l i s t , l i s t ) minimumcover
CLAUSES
/ * E l im ina tes redundant ~ .d ' s * /
reduce@ds:- w r i t e ( " > E l i m i n a t i n g Redundant F . D . ' s " ) , n l , ~ a i l .
reducefds~- ~d(LHS,RHS), no t (~d j (LHS,_ ) ) , retract(~d(LHS,RHS)), w r i t e ( " > Re t rac t ing FD: ",LHS~" -> " ,RHS),n l , closure("F",LHS,LHSPLUS), w r i t e ( " > Closure o£ LHS: ",LHSPLUS),nl, not (subset(RHS,LHSPLUS)), w r i t e ( " > Does not conta in RHS, Asser t ing a g a i n " ) , n l , asserta(~dmin(LHS,RHS)), ~ a i l .
reduce~ds:- r e t r a c t ( { d m i n ( X , Y ) ) , a s s e r t a ( f d ( X , Y ) ) , ~ a i l .
reduce@ds:- w r i t e< "> Redundant F.D's e l i m i n a t e d " ) , nl,nl.
/ * Minimise the number oF a t t r i b u t e s on Le~t Hand Side * /
reduce lhs1 : - ~d(LHS,RHS)~ w r i t e ( " > FD: ",LHS," -> " ,RHS),n l , ~educelhs~(LHS,RHS,REDLHS), not(eQuaI(LHS,REDLHS)), ~etract(~d(LHS,RHS)), asserta(~d(REDLHS,RHS)), ~ a i l .
117
reducelhs1:- !, wr i te ( "> LHS n l , n l .
minimised"),
reducelhs~(LHS,RHS,REDLHS):- member(ELEM,LHS), drop_elem(LHS,ELEM,LHSMI), closure("F",LHSMI,LHSMIPLUS), subset(RHS,LHSMIPLUS), !, reducelhs2(LHSMI,RHS,REDLHS).
reducelhs2(REDLHS,_,REDLHS).
minimum_cover:- reducelhsl, reduce#ds.
118
/ * PURPOSE: TO PROJECT A SET OF FD'S ON TO * / I * A SET OF ATTRIBUTES * / / * * /
/ * TOP LEVEL PREDICATE: p j l * / / * ~I I * . /
PREDICATES
pji(list) pj2(symbol)
CLAUSES
pj 1(_) :- re%rac~(pj (_~_)) {ail.
pj1(_):- ?d(X,Y), asser%a(pj(X,Y))~ #ail.
pjl(SET):- at%ributes(L}, member(E,L), not (member(E,SET)), pj2(E), Call.
pj I(_) .
pj~(E):- pj(LHSI,EE3)~ pj(LHS2,RHS2), member(E,LHS2), drop_elem(LHS2,E,TEMP), union(NEWLHS,TEMP,LHSI), asserta(pj(NEWLHS,RHS2)), #all.
pj2(E): - pj(LHS,RHS)~ member(E,LHS), retract(pj(LHS,RHS)), f a i l ,
p j2(E): - pj(LHS,RHS)~ member(E,RHS)~ retract(pj(LHS,RHS)), ~a i l .
pj2( ).
119
/4 PURPOSE: TO DETERMINE ALL THE KEYS OF A ~/ /~ RELATION ~/
/~ TOP LEVEL PREDICATE: t indal lkeys ~/
PREDICATES
CLAUSES
~ i n d k e y ( l i s t , l i s t ) ~indallkeys knownkey(list) ~indnewkey(list)
t indkey(_ ,_) : - retract(key(_>), t a i l .
~indkey(REL,KEY):- mvd(X,Y>, union(REL,X,Y), KEY=REL, asserta(key(KEY)), !.
findkey(REL,KEY):- reducelhs2(REL,REL,KEY), assertz(key(KEY)).
knownkey(K):- key(St, subset(K,S), !.
tindnewkey(K):- pj(LHS,RHS), minus(RHS,K,Z), union(S,LHS,Z), not (knownkey(S)>, asserta(key(S)), tindnewkey(S).
t i nda l l keys : - key(K>, tindnewkey(K), t a i l .
t inda l lkeys.
120
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/~ PURPOSE: TO OBTAIN THE THIRD NORMAL FORM ~/ /~ USING BERNSTEIN'S ALGORITHM ~/
/~ TOP LEVEL PREDICATE: n~3 ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
PREDICATES
combineFds makerel n£3 eiem conta inedins eqvkeys c o l l e c t a l l e q v ( l i s t , l i s t , l i s t ) col lectal leqv1(l ist , l ist , l ist) ; o l l e c t a l l e q v 2 ( l i s t , l i s t , l i s t ) a l r e a d y e x i s t s ( l i s t )
CLAUSES
combine£ds:- £d(LHSI,RHSI), w r i t e ( " > FD: " ,LHSI , " ~d(LHS2,RHS2)~ equaI(LHSI,LHS2), not(equal(RHSI,RHS~)), w r i t e ( " > FD: ",LHS2, " -> union(RHS,RHS1,RHS2), r e t r a c t ( F d ( L H S I , R H S l ) ) , r e t r a c t ( ~ d ( L H S 2 , R H S 2 ) ) , w r i t e ( " > Combining to w r i t e ( " > FD: ",LHS1, " asser ta( fd(LHSI,RHS)) , !, combine~ds.
=> " ,RHSI ) ,n l ,
" ,RHS2),n l ,
: " ) , n l , -> " , R H S ) , n l , n l ,
combineCdso
collectalleqv(LHS,A,R):- collectalleqv1(LHS,A,R1), collectalleqv2(LHS,RI,R).
121
colIectalIeqv2(LHS,A,R):- £d(LHS,RHS), union(ZI,LHS,RHS)~ union(R1,ZI,A)~ not(equal(R1,A)), !, collectalleqv(LHS,R1,R).
collectalleqv~(_,A,A).
collectalleqvl(LHS1,A,R):- ~dj(LHS1,LHS2), retract(~dj(LHSI,LHS2)), retract(~dj(LHS2~LHSq)), !, collectalleqv1(LHSI,A,R1), collectalleqv2(LHS2,R1,R).
collectalleqv1(_,A,A).
alreadye×ists(R):- schema_n~3(Z)~ equal(R,Z), !.
makerel | -
~dj(LHS1,LHS~), retract(~dj(LHSI,LHS2)), retract(?dj(LHS2,LHS1)), collectalleqv(LHSl,E3,R1), collectalleqv(LHS2,R1,R2), asserta(schema_n~3(R2)), #ail.
makerel:- ~d(LHS,_), collectalleqv2(LHS,[3,R), not (alreadyexists(R)), asserta(schema_n~3(R)), ?ai l .
makerel:- elem containedins, ?ai l .
makerel:- retract(schema_n?3(E3))~ ~ail.
makerel:- mvd(X,Y), union(Z,X,Y), asserta(schema_n~3(Z)), ~ail.
122
makerel.
elem_containedins:- schema_n~3(Zi), schema_n~3(Z2), subset(Z2,Z1), not (subset(ZI,Z2)), retract(schema nf3(Z2)), ~ail.
elem_containedins:- !.
eqvkeys:- fd(LHSi,_), #d(LHS2,_), not (equal (LHSI,LHS2)), closure("F",LHSi,LHSIP), closure("F",LHS2,LHS2P), subset(LHS2,LHSIP), subBet(LHSIP,LHS2P), not (~dj(LHSI,LHS2)), writelist_hz(LHS1)~ wri te(" and ") , writelist_hz(LHS2), write(" are equivalent keys."),nl, asserta(~dj(LHSI,LHS2)), asserta(#dj(LHS2,LHS1)), ?ail.
eqvkeys.
n~3:- consult("pipe"), #indall(X,attribute_es(_,X),L'|), {indall(Y,at%ribute_ew( .... Y),L~), union(L,LI,L2>, aseerta(attributes(L)), {all.
n~3:- write("> Finding minimum cover"),nl, minimum_cover, #all.
n£3:- write("> Finding equivalent keys"),nl, eqvkeys, write("> Finding cover ~or the second minimum_cover, {all.
n{3:- makerel, ~ail.
time")~nl,
123
n f 3 : -
nF3:-
nF3:-
a t t r i b u t e s ( L ) , Findkey(L,R), asserta(schema_n~3(R)), w r i t e ( " > Loss-less j o i n F a i l ,
guarant eed" ), n i ,
w r i t e ( " > E l im ina t ing elem_containedins, Fa i l ,
redundant r e l a t i o n s " ) , n l ,
w r i t e ( " > 3rd NF obta ined" ) , n l , w r i t e ( " > Press any key to continue readchar(_), !.
. . . . ") , n l ,
124
/ ~ PURPOSE: TO CHECK FOR THE PRESERVATION OF ~ / / ~ DEPENDENCIES ~ /
/ ~ TOP LEVEL PREDICATE: # d l o s ~ l ~ /
PREDICATES
~dlostl ~dlost2(lis~,list) isitlost(list,list,list)
CLAUSES
~dlost1:- wr i te ( "> Checking For dependency asser~a(dep_preserved("YES")), ~d(X,Y), ¢dlost2(X,Z)~ isitlost(X,Y,Z), ~ail.
preservation"),nl,
~dlost l .
Fdlost2(X,Z)~- schema bcnF(R), intersect(X,R,XlR), c l o s u r e ( " F " , X I R , X I R P L U S > , intersect(XIRPLUS,R,ADD), union(ZTEMP,ADD,X>, not (equal(ZTEMP,X)), !, Fdlost2(ZTEMP,Z).
?dlost2(X,X)~
isitlost(_,Y,Z):- subset(Y,Z>~ !.
i s i t l o s t ( X , Y , _ ) ~ - retract(dep_preserved(_)), asserta(dep_preserved("NO")), wr i te(X) , write( . . . . . >> " ) , write(Y),nl,
125
/~ PURPOSE: TO OBTAIN BOYCE-CODD NORMAL FORM ~/
/~ TOP LEVEL PREDICATE: bcn~top ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
PREDICATES
bcn~top bcn~(l ist)
CLAUSES
bcn~(REL):- wr i te("> Finding Pro3ections"),NL, p j i ( R E L ) , ~indkey(REL, ), ~indallkeys, ~a i l .
bcn£ (REL) : - p j ( X , Y ) , closure("P",X,XPLUS), no t (subse t (REL ,XPLUS) ) , !, w r i t e ( " > BCNF v i o l a t e d , Decomposing the r e l a t i o n " ) , n l , union(Z,X,Y), asserta(schema_bcn~(Z)), wr i te("> Decomposed re la t ion : ") , w r i te l i s t_hz (Z) ,n l , minus(NEWREL,REL,Y), bcn~(NEWREL).
bcn£(REL):- wr i te("> Decomposed re la t ion: ") , wr i te l ist_hz(REL),nl , asserta(schema bcn£(REL)).
bcn£top:- schema_n£3(REL), wr i te("> Decomposing w r i t e l i s t hz(REL), bcn£(REL), £a i l .
into BCNF the re la t ion : ") ,
b c n F t o p : - F d l o s ¢ l , ! .
126
1 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ t
/~ PURPOSE: PRINTING OF OUTPUTS ~/
/~ TOP LEVEL PREDICATE: w r i t e r e l ~/
PREDICATES writerel(string) writerela(list) writekeys
CLAUSES
wri~ekeys~- write('KEYS~ ">~nl, ~ail.
writekeys:- key(K), writelist_in~ile(output,K), Cail~
writekeys:- n l , n l , n l o
wri~erela(X)~- pit(X), Findkey(X, )~ ~indallkeys, write("ATTRIBUTES IN THE RELATION:"),nl, w r i t e l i s t _ i n ~ i l e ( e u t p u t , X ) , n l , writekeys.
writerel('BCNF"):- schema_bcnF(R), writerela(R), Cail.
writere I("NFS"):- schema_nf3(R), writerela(R), ~ail.
writerel(_),
127
************************************************************************
I* . I / * PURPOSE: MASTER CONTROL OF NORMALIZATION * / I* .I / * TOP LEVEL PREDICATE: normal ize , / I* .I I* . / ************************************************************************
PREDICATES normal ize p r i n t_ou tpu t
CLAUSES
p r i n t _ o u t p u t : - w r i t e ( " > F ina l ~ i l i n g scheme w i l l be w r i t t e n to a ~ i l e -
'OUTPUT',") ,n l , w r i t e ( " which can be p r i n ted using 'TYPE' command") ,n l ,n l , w r i t e ( " > Press any key to cont inue . . . . " ) . r e a d c h a r ( ) . openwrite(output,"OUTPUT"), w r i t e d e v i c e ( o u t p u t ) , n l , n l , n l , ~ail.
print_output:- dep_preserved("NO"), write(" RELATION SCHEME nl,nl, writerel("NF3"),nl,nl,nl,nl, tail.
IN THIRD NORMAL FORM"),NL,NL,
print_output:- write(" RELATION SCHEME nl,nl, writerel("BCNF"),nl,nl, tail.
IN FOURTH NORMAL FORM" ), NL, NL,
print_output:- dep_preserved("NO"), write("Data Dependencies Lost in the Decomposition"),nl, tdlostl, tail.
print_output:- close~ile(output), writedevice(screen), ~ail.
p r i n t _ o u t p u t : - $ i l e _ s t r ( " O U T P U T " , B ) , w r i t e ( B ) , nl,nl, write("} Press any key readchar(_).
to continue . . . . " ) ,NL ,
128
normalize:- make~indow(i,78,7,'NORMALIZING",O,O,25,80), n~3, bcn~top, ~ d l o s t i , print_output.
goal normalize~
129
/ * . /
/ * FILE : SCREENS.PRO * / / * . / / * Predicates in ~his ~ i l e perform some s~andard screen * / / * ~unc~ions, such as, d i s p l a y i n g l i s ~ s , d i s p l a y i n g f i l e * / / * names, d i sp l ay i ng a~t r ibu~es, e~c. * / / * . /
/ ~ ~ ~ ~ . ~ ~ ~ ~ ~ . ~ ~ /
/~ PURPOSE: TO DISPLAY OPENING SCREENS AND ~/ /~ INTRODUCE THE USER TO THE ~/ /~ PRELIMINARIES OF DATABASE DESIGN ~/
/~ TOP LEVEL PREDICATE i n t r o d u c t i o n ~/
/~ SCREEN NUMBERS I -4 ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
PREDICATES
opening_screen screenl screen~ z o o m ( i n t e g e r , i n t e g e r , i n t e g e r , i n t e g e r ) w a i t ( i n t e g e r ) i n s i g n i a i n t r o d u c t i o n
CLAUSES
/~ FILE: OPEN SCR,TXT ~/
I ~ # ~ ~ ~ ~ ~ ~ ~ I
He l lo !
We are here to ass i s t you in developing a
F i l i n g Scheme
For your database.
Press any key to cont inue . . . .
opening_screen:- makewindow(~,116,0,"",7,15,15,50), F i l e _ s t r ( " o p e n _ s c r . t x t " , A ) , w r i t e ( A ) , £ i e l d _ a t t r ( 6 , 1 7 , 1 3 , 7 9 ) , readchar(_), removewindow,
!30
/~ FILE : UTILITY.PRO * /
/ * The predicates in th is ~i les ~/ /~ perform standard l i s t operations ~/ /~ such as, union, in tersect ion,etc. ~/
predicates member(symbol~list) subset(list,list~ union(iist,list,list) minus(list,list,list) equal(list~list) drop elem(list,symbol,list) nth elemENT(integer,list,integer~symbol)
clauses
/~ membeF(symbol,list) ~/ /~ checks the membership o~ symbol in the l i s t ~/
Member(X~ZX~ 3). Member<X,[_~Tail3>:-
Member(X,Tail).
/~ subset(list1,1ist2) ~/ /~ Checks ~o see whether list4 is a subset o~ list~ ~/
subset(Z3~ >~- !.
subset(ZHEAD~TAILA3,B):- !, member(HEAD,B),subset(TAILA,B).
drop e lem( l i s t l , symbo l , l i s t2 ) ~/ subtracts symbol From l i s t4 to give l is~2
drop elem(EELEM~REDLHS3,ELEM,REDLHS):- !.
drop_elem(EA~LHS3,ELEM,[AIREDLHS3):- drop elem(LHS,ELEM,REDLHS).
/~ union(!is~i,list2,1ist3 ~/ /~ Returns union (list4) oF two sets (list2 and list3) ~/
union(A,A,Z3):-!. union(A,E3,A):-!. union(EHEADA~TAILU],EHEADAITAILA],B):-
member(HEADA,B),
drop elem(B,HEADA,B4), union(TAILU,TAILA,BI).
union<[HEADA~TAILU3,EHEADA~TAILA],B):- !,union(TAILU,TAILA,B).
131
/ * m i n u s ( l i s t l , l i s t 2 , 1 i s t 3 ) * / / * Subtracts l i s t 3 from l i s t 2 to give l i s t l * /
minus(SET,SET,C3):- !.
minus(SETDIFF,SETA,ZHEADB~TAILB3):- drop_elem(SETA,HEADB,TEMP), minus(SETDIFF,TEMP,TAILB).
/ * e q u a l ( l i s t l , l i s t 2 ) * / / * Checks equal i ty o~ two l i s t s l i s t l and l i s t~
equal<X,Y):- subset(X,Y>, subset(Y~X)~ !.
/* nth element( integer l , l is t , integer2,symbol) * / / * RetUrns the posit ion integer2, oF the
symbol in the l i s t counting Prom integer l * /
nth element(IN,EHEAD~ ],IN,HEAD):- !.
nth element(IN,C_~TAIL],N,X):- OUT=IN+I, nth_element(OUT,TAIL,N,X).
predicates i n t e r s e c t ( l i s t , l i s t , l i s t )
clauses
i n t e r s e c t ( [ ] , _ , [ ] ) . intersect(EHIT3,Y,EH~T2]):-
member(H,Y),!,intersect(T,Y,T2). in tersect ( [ ~T3,Y,Z):- intersect(T,Y,Z).
* /
132
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / . * I / * FILE : SCREENS.PRO * / I . . / I* Pred icates in t h i s f i l e perform some standard screen *I / * ~unct ions, such as, d i s p l a y i n g l i s t s , d i sp l ay i ng f i l e * / I * names, d i s p l a y i n g a t t r i b u t e s , e tc . * I I. *I
PURPOSE: TO DISPLAY OPENING SCREENS AND * I INTRODUCE THE USER TO THE * /
PRELIMINARIES OF DATABASE DESIGN
I* /* /* /. /. /* /. /*
TOP LEVEL PREDICATE
SCREEN NUMBERS
i n t r o d u c t i o n
1-4
*I *I *I *I *I
PREDICATES
opening_screen screenl screen2 zoom(integer,integer,integer,integer) wait(integer) insignia introduction
CLAUSES
/, */
I* FILE: OPEN_SCR.TXT */
I. *I I. *I
I . *I I. *I I. *I I. * I
/ . * /
Hello!
We are here to assist you in developing a
Filing Scheme
~or your database.
Press any key to continue ....
o p e n i n g s c r e e n : - makewindew(2.11&,O,"" .7,15,15,50) , f i l e _ s t r ( " o p e n _ s c r = t x t " , A ) . w r i t e ( A ) , ¢ield_attr(6,17,13,79), readchar(_), removewindow.
* /
133
I ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ I
I~ FILE: SCREENIA.TXT ~I
/~ An e f f i c i e n t database design assures that only minimal e ~ o r t and ~/ /~ time are expended in s to r ing , r e t r i e v i n g , rev is ing and manipulating ~/ /~ the information stored in the database. ~/
/~ This programme uses A r t i f i c i a l I n t e l l i g e n c e concepts to guide you ~/ /~ to achieve an e f f i c i e n t database design based on the r e l a t i o n a l ~/ /~ model of s to r ing the data, ~/
I~ Press any key to continue . . . . . . ~I
/ ~ ~ ~ w ~ ~ ~ w ~ w ~ ~ ~ ~ ~ /
/~ FILE: SCREENIB.TXT 4/
/~ In a database the d i f f e r e n t pieces of re la ted in@ormation are ~/ /4 grouped at one place. For example, a database may contain : ~/
/~ Rol l No Name Class Home Town ~/ I~ 8678 Kastur i M.Tech. Madras ~I /~ 8760 V i j ay B.Tech. Delhi ~/
/~ The i nd i v i dua l data items in a database (Rol l No, Name, e tc . ) 4/ /~ are ca l led a t t r i b u t e s . ~/
/~ Press any key to continue . . . . . . ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/~ FILE: SCREENIC.TXT ~/
/4 Soon, You w i l l be asked some questions regarding the a t t r i b u t e ~ ~/ /4 ( i . e . data items) that w i l l appear in your database. ~/
I~ You should answer these questions th ink ing as i~ you are bu i ld ing e l I~ ord inary paper ~ i les for s to r ing data. ~I
/~ Press any key to continue . . . . . . ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
134
s c r e e n l ~ - m a k e ~ i n d o ~ ( t , 1 5 , t 5 , " ' , O , O , 2 5 , 8 0 ) , cu rso r (2 ,36 ) , w r i t e ( " e x c e p t " ) , c u r s o r ( O , 3 2 ) , w r i t e ( "PRELIMINARIES" ) , makewindow ( 2, 116,15, "" ,2 2,4,34) write(" Files in a computer database'),nl, write(" are similar to paper ~iles"), makewindow(3,116,15 .... ,2 44,4 35) w r i t e ( " t ha t data is s tored on magnet ic " ) , write(" media rather than on paper."), makewindow(5r2,15, " " , 8 , 2 , 1 6 , 7 6 ) , ~ indow_a t t r (2 ) , ?ile_str("screenla.txt",A), ~rite(A), readchar(_), clear~indow, ~ i l e _ s t r ( " s c r e e n l b . t x t " , B ) , w i n d o w _ a t t r ( 2 ) , w r i t e ( B ) , ? i e l d _ a t t r ( 4 , 1 , 7 0 , 1 4 ) , ~ i e l d _ a t t r ( 9 , 1 6 , 1 1 , 1 " 1 ) , readchar(_) , clearwindow, ~ i l e _ s t r ( " s c r e e n l c . t x t " , C ) , write(C), readchar(), removewindow, removewindow, removewindow, clearwindow, shi~t~indow(1), m a k e w i n d o w ( 2 , 9 0 , 1 0 , " A t t r i b u t e s " , l , ~ , 3 , 3 1 ) , clearwindow, write("data items to be stored").
/~ FILE: SCREEN2A,TXT ~/
/~ As you start the process o~ building ~/ /~ your database you may a l ready have a ~/ /~ good idea about the data ~ i l es you ~/ /~ would l i k e to have, ~/ /~ ~or example: ~ /
/~ For example, ?or a i nven to ry manage- ~/ /~ ment database, you might have : ~/
/~ - a master file o~ parts ~/ /~ - a master ~ile o~ vendors ~/
135
screen2:- makewindo~(3,74,2,"",4,~6~15,47), ~ i l e_s t r< "sc reen2a . tx~" ,A) , ~ r i t e ( A ) , ~ ie ld a t t r ( 3 , 2 3 , 1 1 , 7 9 ) , # ie ld a t t r ( 1 0 , 1 , 3 5 , 7 9 ) , # ie ld a t~ r (11 ,1 ,35 ,79) , # a i l .
screen~:- make~indow(6,~,~1,"DIALOG",19,£,5,70), # a i l .
screen2.
wa i t< t000 ) : - !.
~ a i t ( N ) : - NO=N+I,
~ait(NO>.
/~ FILE: SCREEN~A,TXT ~/
/4 A TURBO-PROLOG IMPLEMENTATION OF NORMALIZATION ~/ /~ ALGORITHMS IN RELATIONAL DATABASE DESIGN ~/
/ ~ C o p y r i g h t 4 / /4 Vinay K Chaudhri ~/ /~ Tapan P. Bagchi 4/
/4 4/ /4 INDUSTRIAL AND MANAGEMENT ENGINEERING PROGRMME ~/ /~ liT KANPUR UP, 20801~ ~/
136
zoom(_,_,X, )~- X>15, ~ile_str("gigle,gxt",A),
!.
zoom(STXI,STYI,HTi,WIDTH!):- removewindow, makewindow(1,11,0,"",STXl,STYi,HTi,WiDTHl), STXO=STXI-I, STYO=STYI-5, HTO=HTI+2, WIDTHO=WIDTHI+IO, wait(O), !, zoom(STXO,STYO,HTO,WIDTHO),
insignia:- £ile str("insigniao~xt",A), makewindow(2,12,0,"",O,O,25,80), write(A), makewindow(1,90,O,"",11,37,3,3), zoom(11,38,3,3),wait(-31999),wait(-31999), removewindow, r e m o v e w i n d o w , !=
introduction:- insignia, opening_screen, s c r e e n l .
137
/ w ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/w PURPOSE: TO IMPLEMENT A POP UP MENU ~/
/~ TOP LEVEL PREDICATE menu ~ /
/~ SCREEN NUMBERS 14 ~/
DOMAINS ROW,COL,LEN = INTEGER ST=st r ing KEY = cr ; esc ; break ; tab ; btab ; del ; bdel ; ins ;
end ; home ; ftast(INTEGER) ; up ; down ; l e f t ; r i g h t ; c t r l l e ~ t ; c t r l r i g h t ; c t r l e n d ; c t r l home; pgup; pgdn; chr(CHAR) ; o therspec
PREDICATES readkey(REY) readkeyl(KEY,CHAR,INTEGER) readkey2(KEY,INTEGER)
CLAUSES
r e a d k e y ( K E Y ) : - r e a d c h a r ( T ) , c h a r i n t (T ,VAL ) , r eadkey I (KEY ,T ,VAL ) .
readkey1(KEY,_,O):-!,readchar(T),char int(T,VAL),readkey~(KEY,VAL). r e a d k e y i ( c r , _ , 1 3 ) ~ - ! . r e a d k e y l ( e s c , _ , ~ 7 ) : - ~ . r e a d k e y 1 ( c h r ( T ) , T , _ )
r e a d k e y 2 ( u p , 7 2 ) : - ! . r e a d k e y ~ ( d o w n , 8 0 ) : - l . readkey~(~tast (N) ,VAL): -VAL>58,VAL<70,N=VAL-SB,! . r e a d k e y ~ ( o t h e r s p e c , _ ) .
/~ menu(L ine ,Co l l um,Header ,L i s tO fCho ices ,Cho iceNr ) ~ / /~ The f o l l o w i n g keys can be used: ~/ /~ arrows up and down: s e l e c t choice ~/ /~ cr and FIO: a c t i v a t e choice ~/ /~ Esc: abo r t ~ /
PREDICATES ma×len(LIST~INTEGER~INTEGER) /~ Find l eng th of the l onges t s t r i n g ~ / l i s t len(L IST, INTEGER) /~ Find the l eng th o~ a l i s t ~ / writel ist<INTEGER,INTEGER,LIST> /~ Used by the menu p r e d i c a t e ~ / menu(ROW,COL,STRING,LIST,INTEGER) menuI(ROW,LIST,INTESER,INTEGER,INTEGER) menu~(ROW,LIST,INTEGER,INTEGER,INTEGER,KEy)
138
clauses
max!en(EH~TD,MAX,MAX1):- ST=H, sir Ien(ST,LEN), ~EN>MAX,!, maxlen(T,LEN,MAX1).
maxlen(E_)T],MAX,MAX1):-maxlen(T,MAX,MAX'I).
maxlen(E],LEN,LEN)=
listlen(E]~O).
listlen(E_IT],N):- listlen(T,X), N=X+I.
wriSelist(_~_,E])°
wri~elist(LENE,LONGEST_CHOICE,EHIT]):-~ield_str(LINE,O,LONGEST_CHOICE,H), LINEI=LINE+I,writelist(LINEI,LONGEST_CHOICE,T).
menu(LINE,KOL, TXT,LIST,ACTUAL_CHOICE):- maxlen<LIST,O,LONGEST_CHOICE), Iistlen<LIST,LEN),NCHOICE=LEN,LEN>O, HHI=NCHOICE+2,HH~=LONGEST_CHOICE+2, makewindow(3,7,7,TXT,LINE,KOL,HH1,HH~), HH3=LONGEST_CHOICE, writelist(O,HH3,LIST>,cursor(O,O), menul(O,LIST,NCHOICE,LONGEST_CHOICE,CHOICE), ACTUAL_CHOICE=I+CHOICE, removewindow.
menu'i(LINE,LIST,NCHOICE,LONGEST_CHOICE,CHOICE):- @ield at~r(LiNE,O,LONGEST_CHOICE,11~), cursor(LINE,O), readkey(KEY), menu2(LINE,LIST,NCHOICE,LONGEST_CHOICE,CHOICE,KEY).
menu~(_~ ~_,_~-l,esc):-~=
menu2(LINE,_,_,_,CHDICE,~ast(IO)):-~,CHOICE=LINE.
menu2(LINE ....... CHOiCE,cr):-!,CHOICE=LINE.
menu~(LINE,LIST,NCHOICE,LONGEST_CHOICE,CHOICE,up):- LINE>O,~, ~ield attr(LINE,O,LONGEST_CHOICE,7), LINEI=LINE-I, menuI(LINEI,LIST,NCHOICE,LONGEST_CHOICE,CHOICE).
menu~(LINE,LIST,NCHOiCE,LONGEST_CHOICE,CHOICE,down):- LINE<NCHOICE-I,!, ¢ield_attr(LINE,O,LQNGEST_CHOICE,7), LINEI=LINE+I, menuI(LINEI,LIST,NCHOICE,LONGEST_CHOICErCHOICE).
menu2(LINE,LiST,NCHOiCE,LONGEST CHOICE,CHOICE,_):- menuI(LINE,LIST,NCHOICE,LONGEST CHOICE,CHOICE).
139
/ * PURPOSE: TO DISPLAY ATTRIBUTES, F ILES AND * / / * KEYS * /
/ * TOP LEVEL PREDICATES display_~i les, d isp lay_at t r ibs , */~ /* display_keys * / /. */
PREDICATES
dispIay_Iist(LIST,INTEGER,ROW,INTEGER,STRING,INTEGER,INTEGER) move cursor<INTEGER,INTEGER,INTEGER,INTEGER) disp_list col(INTEGER,INTEGER,LIST) writelist hz(list) display attribs(symbol) display attribs ew(symbol,symbol) display_~iles display_keys<symbol) display keys_es1(symbol) display keys es~(symbol) display keys_ew1(symbol,symbol) display keys ew2(symbol,symbol) writelist_in~ile(File,list) ~indall a~t(symbol,symbol,list)
CLAUSES
~ inda l l_a t t (F ILE," " ,ALL) : - Findal l (P,attr ibute_es(FILE,P),ALL), !.
~indall_att(FILE,GROUP,ALL):- ~indall(P,attribute_ew(FILE,GROUP,P),ALL).
display_Iist(LIST,WINDO_NO,LINE,COLUMN,HEADER,SCR_ATTRIB,FRAME_ATTRIB): LONGEST CHOICE=IO, listlen(LIST,LEN),NCHOICE=LEN,LEN>O,
HHI=NCHOICE+2,HH2=LONGEST_CHOICE+2, HH3=LONGEST_CHOICE, shi~twindow<WINDO_NO), removewindow, makewindow(WINDO_NO,SCR_ATTRIB,FRAME_ATTRIB,HEADER,
LINE,COLUMN,HHI,HH2), writelist(O,HH3,LIST).
display_list(_,WINDO_NO . . . . . . . . , _ ) : - shiFtwindow(WINDO_NO), removewindow, makewindow(4,0,O,"",7,1,3,3).
m o v e _ c u r s o r ( l O , 3 3 . . . . _ ) : - c u r s o r ( 1 1 , 3 2 ) , w r i t e ( " S P A C E F U L L " ) , ~ i e l d _ a t t r ( 1 1 , 3 2 , 1 0 , b 7 ) , shi~twindow(3), !,
140
move_cursor(~,X,O,Y):- Y=X+~I, cursor(O,Y)~
move_cursor(×~Y,P,Y)~- P = X+i, cursor(P,Y), !o
disp list_col< ,_~E]):- !.
disp_Iist_coI(STY,STX,EHEAD[TAIL]):- write(HEAD), move_cursor(STY,STX,STYO,STXO), !, disp_list_col(STYO,STXO,TAIL).
disp_!is% col{ ..... )o
write!ist_hz(E]):- cursor(X,Y>, P=Y-I, cursor(X,P), write(".">,
!.
writelis~_hz(EH[T]):- write(H), write("~"), !, ~ritelis~_hz(T).
display_¢iles:- shi~twindow(3), retract(all ~iles(_)), ¢indall(X,entity_strong(X),FILE_LIST), asser~a(all_files(FILE_LIST)), not(equal(FILE_LIST,El)), display_Iist(FILE_LZST,4,8,1,"FILES",74,15), shi~twindow(3), [.
display_{iles~
display_attribs_ew~ ~GROUP}:- shi~window(5), clearwindow, not (GROUP= .... ), write{GROUP), ~ield_attr(O,O,10,79),nl, Call.
141
display_attribs ew(FILE,GROUP):- Findall_att(FILE,GROUP,ATTRIB_LIST), c u r s o r ( P , G ) , disp_Iist_coI(P,G,ATTRIB_LIST), shiFtwindow(3).
display_atCribs(FILE):- all_Files(LIST), nth_element(O,LIST,N,FILE), shiFtwindow(4), Field attr(N,O,10,75), Fai l .
display at tr ibs(FILE):- shiftwindow(5), removewindow, concat("ATTRIBUTES IN FILE: ",FILE,X), makewindow(5,52,11,X,O,34,14,45), clearwindow, ~ai l ,
display_attribs(FILE~):- entity_weak(FILEI,EW), cursor(M,N), w r i t e ( E W ) , F i e l d _ a C t r ( M , N , l O , 7 9 ) , move c u r s o r ( M , N , P , G ) , F i n d a l l ( X , a t t r i b u t e _ e w ( F I L E 1 , E W , X ) , A T T R I B _ L I S T ) , disp_list_col(P,G,ATTRIB_LIST), c u r s o r ( X , Y ) , move c u r s o r ( X , Y , _ , ) , Fail.
display attribs<FILE1):- ~indal l(X,attr ibute es(FILEI,X),REST), c u r s o r ( P , G ) , d i s p _ l i s t _ c o l ( P , G , R E S T ) , s h i F t w i n d o w ( 3 ) , Fai l .
d isplay_attr ibs(_):- !.
d i s p l a y k e y s ( ) : - shiFtwindow(7), clearwindow, Fail.
display keys(FILE1):- entity_weak(FILEI,X), display_keys_ewi(FILEI,X), Fai l .
display_keys(FILE~):- display keys_es1(FILE1), Fai l .
d i s p l a y k e y s ( ) : - shiFtwindow(3).
142
display_keys_ewl(FILEI,X):- key_ew(EFILE1],EX], ), cursor(P,G), w r i ~ e ( " G r o u p : " ) , wri%e(X),nl, ~ield_attr(P,G,18,26), !, display_keys ew~(FILEI,X).
display_keys ewi(_,_),
display keys ew2(FILEI,X):- Eey_e~(CFILEI],CX],KEYI), writelist_hz(KEY1), ~ail.
display_keys_ew2(_,_).
display keys_es1(FILEl):- key_es(CFILE13,_), cursor(P,G), write("FILE= "), write(FILE1),nl, f i e l d a t t r < P , G , 1 8 , ~ 6 ) , ! , display_keys_es~(FILE1).
display_keys esl(_),
display keys_es2(FILE1):- key_es(EFILE1],KEY1), writelist_hz(KEYi), £ail,
display keys_es2(_)
writelis~_in~ile(FILE,E]):- ~ilepos(FILE,-2,1), write("."),nl, !.
writelist_in~ile(FILE,EH)T]):- write(H), write(", "), !, writelist_in~ile(FILE,T).
143
/ * FILE : INPFILE.PRO * /
/ * Pred icates in ~his ~ i l e le~ ~/ / * the user ~he user inpu~ the * / / * d a ~ a - i ~ e m s he w i s h e s ~o s ~ e r e i n * / / ~ t h e d a t a b a s e ~o be d e s i g n e d * /
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/~ PURPOSE: TO TRUNCATE THE ATTRIBUTE NAMES ~/ /~ TO A LENGTH OF 10 CHARACTERS ~/
/~ TOP LEVEL PREDICATE chop_name ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
PREDICATES
chop_name(symbol,symbol)
CLAUSES
chop name(A,A):- s t r _ l e n ( A , L ) , L < I I , !.
chop_name(A,B):- £ron%str('10,A,B,_).
144
I ~ ~ ~ ~ ~ ~ . ~ ~ ~ . ~ ~ ~ I
/~ PURPOSE: TO ACCEPT THE INPUT OF WEAK ENTITIES ~/
/~ explaingroup ~/
I * 7-10 ~/
/ . ~ ~ ~ ~ ~ ~ ~ @ ~ ~ ~ ~ /
TOP LEVEL PREDICATE
SCREEN NUMBERS
PREDICATES
explaingroup(symbol) ask groups_es(symbol) ask groups es~(symbol) ask_attr ib_ew(symbol,symbol) ask a t t r i b_e~ (symbo l , symbo l ) checkdup l i ca tegroup(symbo l ,symbo l ) check n u l l group<symbol ,symbol , l is t ) check name_at~rib ewe(symbol,symbol,symbol) edi tkeys ew(symbol,symbol)
CLAUSES
I ~ ~ ~ ~ ~ ~ ~ ~ I
I~ FILE: SCREEN2B.TXT ~I
/~ In a STUDENT daCabase ~iCh ~/ /~ a t t r i b u t e s : ~I
i~ Name, Rollno~ Class, S t ree t , ~I /~ C i t y , Zip ~/
/~ ~e might have the go l lo~ ing ~/ I * l o g i c a l groups: * I
I~ GROUP 1: Name~ Rol lno, Class ~I i~ GROUP 2: S~reet, C i t y , Zip ~/
145
/ ~ ~ . ~ ~ ~ ~ ~ ~ /
/~ FILE: SCREEN~C.TXT ~/
/~ I~ you can now 'group' the above ~/ /~ attributes in some logical way, ~/ /~ %ha% would reduce the number o~ ~/ /~ questions you will need %o ~/ /~ answer in this dialog ~/ /~ (see example) ~/
/~ Press any key %o continue .,. ~/
explaingroup(FILE1):- clearwindow, ~ile str("screen2c.tx%",C), write(C), makewindow(7,26y7,"EXAMPLE OF GROUPS",8,0,16,35), ~ile_str("screenab.t×t",A), write(A), readchar(_), removewindow, shi~twindow(3), clearwindow, ask_groups_es(FILE1).
ask_groups_es(FILE1):- d isp lay_at t r ibs(FILE1) ,n l , clearwindow, not (FILEt=""), write("> In File: "), write(FILEt), ~ield_attr(0,15,~5,11), nl,£ail.
ask g r o u p s _ e s ( F I L E 1 ) : - w r i t e ( " > Can you see any w r i t e ( " g r o u p s ( Y / N ) ? " ) , readln(ANS), u p p e r l o w e r ( " Y " , A N S ) , a s k _ g r o u p s _ e s l ( F I L E 1 ) .
such a t t r i bu te " ) , n l ,
ask_groups_es().
ask._groups es4(FILE1):- wr i te( "> Please type the group name " ) , n l , wr i te ( "> " ) , readln(NANEU), not(NAMEU="")~ upper lower(NAHEU,NAMEL), chop_name(NAHEL,NAME), check duplicate group(FILEI,NAME), ~a i l .
146
ask_groups_esl(FILEl):- write("> Any more groups readln(ANS), u p p e r _ l o w e r ( " Y " , A N S ) , ! , a s k _ g r o u p s _ e s l ( F I L E 1 ) .
(Y /N)? " ) ,
ask_groups_esl().
check duplicate_greup(FILEI,NAME):- e n t i t y w e a k ( F l L E l , X ) , X=NAME, wri te("> Duplicate names not al lowed"),nl , !, ask groups_es1(FILEl).
check_duplicate group(FILE1,NAME):- asserta(entity_weak(FILEI,NAME)), ask_attrib_ew(FILEI,NAME).
e d i t k e y s _ e w ( F I L E t , N A M E ) : - key_es( , )~ !, clearwindow, write("> For file : "), write<FILE1),nl, ~ield attr(O,15,25,11), cursor(PP, )~ w r i t e ( " > For g roup : " ) , write(NAME), ~ield_attr(PP,15,~5,14),nl, ask_keysl(FiLEI,NAME), clearwindow~
editkeys_ew(_,_).
ask_attr ib ew(FILE1,GROUP):- clearwindow, cursor(R,_), w r i t e ( " > For Group : " ) , write(GROUP),nl, ~ield_attr(R,15,~5,14), wri te("> Enter one a t t r ibu te per l ine w r i t e ( " When done, press Return"),nl , a s k _ a t t r i b _ e w l ( F I L E t , G R O U P ) , Cail.
. . . " ) , n l ~
ask_attr ib ew(FILEI,GROUP):- wr i te("> Any more at t r ibutes (Y/N)? readln(ANS), ~pper_lower("Y",ANS), !, ask attrib_ew(FZLEI,GROUP).
ask_art r ib ew(FILEI,GROUP):- findaiI<X~attribute_ew(FILE1,GROUP,X),ATT_LIST), check nul l group(FILEI~GROUP,ATT_LIST), display_attr ibs(FILE1), editkeys_ew(FILE1,GROUP).
147
ask a t t r i b ewl(FILEI,GROUP):- display at t r ibs(FILE1), wr i te( "> ") , readln(NAMEU)~ not (NAMEU=""), upper_Iower(NAMEU,NAMEL), chop_name(NAMEL,NAME), check_name_attrib_ew1(FILEI,GROUP,NAME), !, ask_attrib_ew1(FILEI,GROUP).
ask_attr ib ewl(_,_).
check name_attrib_ew1(FILEI,GROUP,NAME):- retract(attr ibute_es(FILEI,NAME)), assertz(attribute_ew(FILEI,GROUP,NAME)), !.
check_name_attrib ewI(FILEI,GROUP,NAME):- attribute_ew(FILEl,_,NAME), assertz(attribute_ew(FILEI,GROUP,NAME)), !.
check_name_attrib_ew1( . . . . . ) : - wr i te ( "> Ondeclared/Misspelt a t t r i b u t e " ) , n l , wr i te ( " Please check and input a g a i n " ) , n l , n l .
check_null_group(FILEI,GROUP,E]):- wr i te( "> Empty groups not accepted") ,n l ,n l , wr i te ( "> Do you want to keep th is group (Y/N)? readln(ANS), u p p e r _ l o w e r ( " Y " , A N S ) , !, ask a t t r i b_ew(F ILE1 ,GROUP) ,
check_null_group(FILEI,GROUP,Z])=- retract(entity_weak(FILEI,GROUP)), !.
check_null_group( . . . . . ),
")t
148
/4 PURPOSE: TO ACCEPT THE INPUT OF STRONG ENTITIES #/ /4 4/ /~ TOP LEVEL PREDICATE ask_tilenames2 ~/
PREDICATES
a s k _ t i l e namesl ask_tile_names~ check_nu l l_ f i l e l ( symbo l ) check_null t i l e 2 ( s y m b o l , l i s t ) check_dupl icate_~i le(symbol) ask_attribs_esl ask attribs_es2<symbol) check_dupl icate_at t r ib_es(symbol ,symbol) editkeys_es(symbol)
CLAUSES
ask_a~tr ibs_es1:- ent i~y_streng(FILE1), d i s p l a y _ t i l e s , clearwindow, w r i t e ( " > Now For t i l e : " ) , w r i t e ( F I L E 1 ) , n l , ¢ i e ld a t t r (O ,15 ,25 ,11 ) , w r i t e ( " Enter one a t t r i b u t e per l i ne . . . " ) , n l , w r i t e ( " When done, press Re tu rn " ) , n l , makewindow(5,52~7,"ATTRIBUTES",O,34,14,45), display_tiles, display_attribs(FILE1), shit twindow(3)~ ask a t t r ibs_es2(FILE1) , Ca l l .
ask_attribs_esl.
ask_attribs es2(FILE1):- write("> "), readln(AU), not (AU=""), upper_lower<AU,AL), chop_name(AL,A), check_duplicate_attrib_es(FILEI,A), display_attribs(FILE1), !, ask_attribs es2<FILE1).
ask_art r ibs_es2(FILE'1 ) :- write<"> Any more attributes (Y/N>? "), readln (ANS), upper lower<"Y",ANS), w r i t e ( " Enter one a t t r i b u t e per l i ne . . . " ) , n l , w r i t e ( " When done, press R e t u r n " ) , n l , !, ask a t t r i b s es~(FILEI>.
149
ask a t t r i bs es2(FILEI):- check null_~ile1(FILE1), !, explaingroup(FILEl), editkeys_es(FILE1).
ask_attribs_es2(_).
check_duplicate_attrib_es(AFILE,NAME):- attribute_es(AFILE,X), X=NAME, wri te("> Duplicate names not a l lowed") ,n l , wr i te ( " Give some other name"),nl, !.
check_duplicate_attrib es(AFILE,NAME):- attribute_ew(AFILE,_,Z), Z=NAME, wri te("> Duplicate names not a l lowed") ,n l , wr i te ( " Give some other name"),nl, !.
check dupl icate_at t r ib es(AFILE,ATTRIB):- assertz(attribute_es(AFILE,ATTRIB)).
check nu l l_ f i le1(F ILE1) : - #indal l (X,attr ibute_es(FILEI,X),L2), f indal l (Y,at t r ibute_ew(FILE1,_,Y),L l ) , union(L,LI,L~), shi~twindow(3), check nul l_~i le2(FILEI ,L) .
check n u l i _ f i l e 2 ( F I L E l , [ ] ) : - wr i te("> You should give at least one a t t r i bu te " ) , n l , n l , wr i te("> Do you want to give at t r ibutes (Y/N)? ") , readln(ANS), upper lower("Y",ANS), wr i te ( " Enter one a t t r ibu te per l ine . . . " ) , n l , wr i te ( " When done, press Return " ) , n l , !, ask a t t r i bs es2(FILEI), f a i l .
check_nu l l _ f i l e2 ( " " , [ ] ) : - !, Fai l .
check nu l l f i l e 2 ( F I L E l , [ ] ) : - retract(ent i ty_strong(FILEt)) , display f i l e s , !, f a i l .
check nu l l_ f i le~(FILE1,_) : - display attr ibs(FILE1), shiftwindow(3).
150
ask_~ile_names1:- clearwindow~ w r i t e ( " > Enter below names of y o u r data ~ i l e s , " ) , n l , w r i t e ( " one per l i ne . . . " > , n l , w r i t e ( " When done, press R e t u r n " ) , n l , ask_~ile_names~.
ask_~ile_names2:- write("> "), readln(NAMEU), not (NAMEU= .... )~ upper_Iower(NAMEU,NAMEL), chop name(NAMEL,NAME), check_duplicate_file(NAME), !, ask_~ile_names2.
ask_?ile_names2:- write("> Any more files (Y/N)? "), readln(ANS>, upper_lower("Y",ANS), clearwindow, write("> Enter below names of your data files,"),nl, w r i t e ( " one per line . . . " ) , n l , write(" When done, press Re tu rn " ) , n l , !, ask_~ile_names2.
ask_~ile_names2.
c h e c k _ d u p l i c a t e _ f i l e ( F I L E i ) : - en t i t y_s t rong (X ) , X=FILEI,nl, w r i t e ( " > Dupl icate names not a l l o w e d " ) , n l , n l , w r i t e ( " > Press any key to continue . . . " ) , n l , readchar(_), !, ~ail.
c h e c k _ d u p l i c a t e f i l e ( T ) : - n~ i l es (X ) , Y = X+i, not (Y>i5) , a s s e r t z ( e n t i t y _ s t r o n g ( T ) ) , d i sp iay_~ i l es , r e t r a c t ( n ~ i l e s ( _ > ) , asserta(n~iies(Y)), !.
check_duplicate_{ile(_):- write("> Max. No of ~iles(15) exceeded"),nl, nl, write("> Press any key to continue ... "), readchar(_), !, ~ail.
editkeys es(FILE):- keyes(_,_), !, clearwindow, write("> Now For ~ile: "), write(FlLE),nl, Field_attr(0,15,25,14), ask_keys1(FILE~"").
editkeys es(_).
152
* * * * * * * * * * * * * * * * * * * * * * * * / * EDITOR ~/ * * * * * * * * * * * * * * * * * * * * * * * *
/ ~ PURPOSE: TO ALLOW THE USER TO CHANGE THE INPUTS ~ / / ~ HE HAS MADE ONCE ~ /
I~ ne×t s~ep ~I
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
TOP LEVEL PREDICATE
SCREEN NUMBERS
/ ~ ~ ~ ~ / / ~ SUB-SECTIONS OF EDITOR ~I f ~ ~ ~ ~ 1
/~ PURPOSE: EDITING OF FILES ~/
/~ TOP LEVEL PREDICATE edi t_#i les ~/
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ * ~ ~ /
PREDICATES
edi~_~iles edi t ~iles'1(integer) dele~e~ile1(symbol) delete~ile2(symbol) rename~ilel rename~ile2(symbol,symbol>
CLAUSES
edit ?iles:- clearwindow, write("> "), menu( 16,40, "EDIT FILES",
E"ADD A FILE", "DELETE A FILE", "RENAME A FILE", " Q U I T " 3 ,
CHOICE) , edit #ilesI(CHOICE),
edit_?iles1(O):= !.
153
ed i t _~ i l es1 (1 ) : - clearwindow, wr i te ( "> Input ~ i le name to add " ) , n l , wr i te ( "> " ) , readln(NAMEU), not (NAMEU= .... ), upper_lower(NAMEU,NAMEL), chop_name(NAMEL,NAME), check duplicate_file(NAME), entity_strong(NAME), w r i t e ( " Enter one a t t r i b u t e per l ine . . . " ) , n l , w r i t e ( " When done, press Return") ,n l , ask_attribs_es2(NAME).
ed i t_~ i lesJ(1) .
edit_¢iles1(~):- clearwindow, write("> Give the file name to delete"),nl, write("> "), readln(NAMEU), upper_Iower(NAMEU,NAME), not (NAME="")~ !, clearwindow, wr i te ( "> Deleting F i l e : " ) , write(NAME),nl,nl, write("> ~ CAUTION ~"),nl,nl, w r i t e ( " On delet ing the ~ i le a l l other r e l a t e d " ) , n l , w r i t e ( " information ( a t t r i bu tes , groups, keys)">,nl , w r i t e ( " w i l l also be 1 o s t " ) , n l , n l , w r i te ( "> Proceed with delete (Y/N)?"), readln(ANS), upper_lower("Y" ,ANS), d e l e t e £ i l e l ( N A M E ) .
e d i t _ ~ i l e s l ( 2 ) : - !,
ed i t_~ i l es1(3):- clearwindow, rename~ilel.
e d i t _ ~ i l e s l ( _ ) .
de le te~ i le1 (A) : - r e t r a c t ( e n t i t y s t r o n g ( A ) ) , !, delete~i le2(A).
de l e te~ i l e l ( >:- wr i te ( "> No such ~ i l e " ) , n l , n l , w r i te ( "> Press any key to continue . . . " ) , readchar ( ) , !.
154
de le te f i l e2 (A)~- retract(ent i ty_weak(A, ) ) , f a i l .
deletefile2(A):- r e t r a c t ( a t t r i b u t e es(A,_)), fail.
deletefile2(A):- retract(attribute ew(A,_,_)), fail.
de le te f i le2(A):- retract(key_es([A],_)), fail~
deletefile2( ):- display_files,
renamefi le1:- clearwindow, wr i te ( "> Give the name of f i l e write("> " ) , readln(NAMEU), upper_lower(NAMEU,NAME), entity_strong(NAME), !, wr i te ( "> Give the new name"),nl, w r i te ( "> " ) , readln(NAMEU1), upper_Iower(NAMEUI,NAMELI), chop_name(NAMELI,NAMEI), renamefile~(NAME,NAMEi).
to rename") ,nl,
renamefile1:- write("> No such file exists"),nl,nl, wr i te ( "> Press any key to continue . . , " ) , readchar(_).
renamefile2(A,B):- retract(entity_strong(A)), asserta(entity_strong(B)), fail.
renamefile~(A,B):- retract(entity_weak(A,X)), asserta(enti ty_weak(B,X)), fail.
renamefi le~(A,B):- re t rac t (a t t r i bu te_es (A ,X ) ) , asserta(attribute_es(B,X)), fail,
renamefile2(A,B):- re t rac t (a t t r ibu te_ew(A,X,Y) ) , asserta(at t r ibute_ew(B,X,Y)) , f a i l .
155
rename~ile2(A,B):- retract(key es([A],X)), asserta(key es([B],X)), ¢ai l .
rename~ile~(_, ) : - display_~iles.
156
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/~ PURPOSE: EDITING OF ATTRIBUTES ~/
/~ TOP LEVEL PREDICATE e d i t a t t r ib_menu ~/
PREDICATES conf irm e d i t _ a t t r i b 1 ( s y m b o l ) edit attrib menu edit~attribTinteger) delete_attrib_file1(symbol,symbol) delete attrib_file2(symbol,symbol) delete_attrib_file3(symbol,symbol) delete_attrib_file4(symbol,symbol) delete_attrib_file5(symbol) delete_attrib_group1(symbol,symbol) delete_attrib_group~(symbol,symbol,symbol) delete_attrib_group3(symbol,symbol,symbol) delete_attrib_group4(symbol,symbol,symbol) delete_attrib_group5(symbol,eymbol) edit_attrib_groupl(symbol,symbol)
CLAUSES
con f i rm : - w r i t e ( " > *~ CAUTION * * " ) , n l , n l , w r i t e ( " > A l l o ther r e l i e d i n fo rmat ion w i l l " ) , w r i t e ( " a lso be l os t w i th d e l e t e " ) , n l , n l , w r i t e ( " > Proceed w i th de le te Y/N? " ) , readln(ANS), upper IoweF("Y",ANS), !,
con f i rm : - f a i l .
e d i t _ a t t r i b i ( F I L E 1 ) ~ - clearwindow, w r i t e ( " > Please give the f i l e name whose" ) ,n l , w r i t e ( " a t t r i b u t e s you want to e d i t " ) , n l , w r i t e ( " > " ) , readln(FILEU), upper Iower(FILEU,FILEI), entitystrong(FILE'I), display attribs(FILE1), !.
ed i t a t t r i b 1 ( _ ) : - w r i t e ( " > No such f i l e " ) , n l , n l , w r i t e ( " > Press any key to cont inue . . . " ) , readchar(_>, f a i l .
157
edit_attrib_groupl(FILEI,GROUP):- wr i te("> Input the group name wri te("> ") , readln(GROUPU), upper_lower(GROUPU,GROUP), entity_weak(FILEI,GROUP), !.
of i n t e r e s t " ) , n l ,
edi t_at t r ib_groupl(_, ) : - wr i te("> No such group") ,n l ,n l , wr i te("> Press any key to continue . . . " ) , readchar(_), f a i l .
delete_attrib_group1(FILEI,GROUP):- clearwindow, wri te("> Give the a t t r ibu te to de le te" ) ,n l , wr i te("> ") , readln(NAMEU), upper_lower(NAMEU,NAME), attribute_ew(FILEI,GROUP,NAME), !, de le te_at t r ib group2(FILEI,GROUP,NAME).
delete_attr ib_group1(_,_):- wr i te("> No such a t t r i b u t e " ) , n l , n l , wr i te("> Press any key to continue readchar(_).
. . . " ) , n l ,
delete_attrib_group2(FILEI,GROUP,NAME):- clearwindow, wri te("> Deleting a t t r i bu te : ") , write(NAME),nl,nl, confirm, delete_at t r ib group3(FILEI,GROUP,NAME), !.
delete attrib_group2( . . . . . ).
delete attrib_group3(FILEq,GROUP,NAME):- retract(attribute_ew(FILEq,GROUP,NAME)), display_attr ibs(FILE1), findall(X,attribute_ew(FILEI,GROUP,X),L), check_null group(FILEI,GROUP,L), entity_weak(FILEI,GROUP), delete a t t r i b group4(FILEI,GROUP,NAME), !.
delete attrib_group3(FILEI,GROUP, ) : - display_attr ibs(FILEq), retract(key ew([FILEI3,[GROUP3, )), f a i l .
delete attrib_group3(FILE1 . . . . ) : - display_keys(FILEt), check nul l f i l e t (F ILE1) , !.
delete a t t r i b group3( . . . . . ).
158
dele~e_attrib group4(FILE1,GROUP,NAME)~- key_ew(EF!LEI3,EGROUP3,X), member(NAME,X), re t ract (key_ew(EFILEl3,EGROUP3,X)) , delete_attrib_greup5(FILEI,GROUP), ~ail~
delete_attrib_group4( ..... ).
delete_attrib_group5(FILE1,GROUP):- display_keys(FILE1>, key ew(EFILEI],EGROUP3,_), !.
delete_attrib_groupS(FILEI,GROUP):- write("> Group: "), write(GROUP),nl,nl, wr i te ( " Does not have any key a~ter d e l e t e " ) , n l , n l , write("> It must have at least one key"),nl, ask_keysl(FILEI,GROUP).
delete_attrib_file1(FILEI,NAME):- attribute_es(FiLEI,NAME), de le te_at t r ib ~ile2(FILEI,NAME), !.
d e l e t e _ a t t r i b _ f i l e l ( _ , _ ) : - wr i te("> No such a t t r i b u t e " ) , n l , n l , write("> Press any key to continue .... "), readchar(_).
delete_attrib_~ile2(FILEI,NAME):- clearwindow, write("> Deleting attribute: ">, write(NAME),nl,nl, confirm, retract(attribute_es(FILEI,NAME)). display_attribs(FILE1), !, check_null_~ile1(FILE1), delete_attrib_~ile3(FILEI,NAME).
delete_at~rib_~ile2<_,_).
delete_attrib_~ile3(F!LE1,NAME):- entity_strong(FILE1>, !, delete_attrib_~ile4(FILEI,NAME>.
delete_attrib_~ile3(FILE1,_):- delete~ile2(FILE1).
de!ete_attrib_file4(FILEI.NAME):- key_es(EFILE13,X), member(NAME,X), retract(key_es(EFILE13,X)), delete_attrib_~ile5(FILE1). ~ail.
delete_attrib_@ile4(_,_)o
159
delete_attrib_{ileS(FILEl):- display_keys(FILEl), key_es([FILE1],_), !.
delete_attrib_~ile5(FILE):- clearwindow, write("> File : "), write(FILE>,nl, write("> Does not has any key after delete"),nl,nl, write(" It must have at least one key"),nl, ask keys1<FILE,"").
edit_attrib_menu:- clearwindow, wr i te ( "> " ) , menu(16,40,"EOlT ATTRIBUTES",
["ADD TO A GROUP", "DELETE FROM A GROUP", "ADD TO A FILE", "DELETE FROM A FILE", "QUIT"],
CHOICE), edit_attrib(CHOICE).
edit_attrib(O):- !,
edit attrib(1):- edit attribl(FILE1), edit_attrib_group1(FILEI,GROUP), ask_attrib_ew(FILEI,GROUP), !.
ed i t_a t t r ib (1 ) : - !.
edit_attrib(2):- edit_attrib1(FILE1), edit_attrib_groupl(FILEI,GROUP), delete_attrib_group1(FILEI,GROUP), !.
edit_attrib(2):- !.
edit_attrib(3):- edit_attrib1(FILEl), clearwindow, write("> Input the attributes one by one"),nl, write(" At end press Return"),nl, ask_attribs_es2(FILEl), ).
edit_attrib(3):- !.
160
e d i t _ a t t r i b ( 4 ) : - edi t attr ib1{FILE1), clearwindow, wr i te("> Please give the a t t r ibu te write("> "), readln(NAMEU), upper lower(NAMEU~NAME), delete attrib_~ilei(FILEI,NAME),
edit_at~rib(4):- !.
to delete")~nl ,
161
/~ PURPOSE: EDITING OF GROUPS ~/
/# TOP LEVEL PREDICATE edit_groups ~/
PREDICATES
edit_groups edit_groupsl(integer,symbol) add_groupsl(symbol) deletegroup1(symbol,symbol) deletegroup2(symbol,symbol) renamegroup1(symbol) renamegroup2(symbol,symbol,symbol)
CLAUSES
edit_groups:- clearwindow, write("> Input the ?ile name o~ which "),nl, write(" you want to edit the groups "),nl,nl, write("> "), readln(NAMEU), upper_Iower(NAMEU,NAME), entity_strong(NAME), !, display_attribs(NAME), clearwindow, write("> "), menu(16,40, "EDIT GROUPS",
["ADD A GROUP", "DELETE A GROUP", "RENAME A GROUP", "QUIT"3,
CHOICE), edit groupsI(CHOICE,NAME).
edit_groups:- wr i te( "> No such ~ i l e " ) , n l , n l , wr i te( "> Press any key to continue . . . " ) , readchar( ) ,
edit_groups1(O, ):- !.
edit groupsl(1,FILE1):- add_groups1(FILE1), !.
162
edit_groupsi(2,FILE1):- clearwindow, wr i te("> Give the group name to de le te " ) ,n l , write("> "), readln(NAMEU), upper_lower(NAMEU,NAME), not (NAME = .... ), clearwindow, write("> Deleting Group: "), write(NAME),nl,nl, w r i t e ( " > * * NOTE * * " ) , n l , n l , wr i te ( " On delet ing the group, the a t t r i b u t e s " ) , n l , wr i te ( " w i l l not be deleted ~rom the ~ i l e " ) , n l , n l , wr i te("> Proceed with delete (Y/N)?"), readln(ANS), upper_Iower("Y",ANS), deletegroupi(NAME,FZLEi), !.
edit groups1(2, ) : - !.
edit_groupsl(3~FILE1):- clearwindow, renamegroupi(FILEl), !.
edit_groupsi(_,_).
add_groupsi(FILEi):- en t i t y strong(FiLEi), !, ask_groups_esi(FILEi).
add_groupsl( ):- write("> No such file"),nl,nl, write("> No such ~ile exists"),nl,nl, write("> Press any key to continue ..."), readchar().
deletegroupl(NAME,FILEl):- retract(entity_weak(FILEq,NAME)), !, deletegroup2(NAME,FILEl).
deletegroupi( , ):- write("> No such group"),nl,nl, wri te("> Press any key to continue readchar(_).
. . . " ) ,
deletegroup2(NAME,FILE):- retract(attribute_ew(FILE,NAME,X)), aseerta(at t r ibute es(FILE,X)), £a i l .
deletegroup2( ,FILE)~- display at t r ibs(FILE).
163
renamegroupl(FILEl):- wr i te("> Give the name of group to wr i te("> " ) , readln(NAMEU~, upper_lower(NAMEO,NAME), en t i ty weak(FILEI,NAME)~ !, wr i te("> Give the new name"),nl, wr i te("> " ) , readln(NAMEU1), upper_lower(NAMEUI,NAMELi), chop name(NAMELI,NAMEI), renamegroup2(NAME,NAMEI,FILEi).
renamegroupi( ) : - wr i te("> No such g r o u p " ) , n l , n l , wri te("> Press any key to continue readchar() .
renamegroup2(A,B,FILE1):- re t rac t (en t i t y weak(FILEI,A)), asserta(ent i ty weak(FILEI,B)), f a i l .
renamegroup2(A,B,FILEi):- re t rac t (a t t r ibu te ew(FILEI,A,Y)), asserta(attribute_ew(FILEI,B,Y)), f a i l .
renamegroup2( . . . . FILE):- display at t r ibs(FILE).
rename") ,n l ,
. . . " ) ,
t64
/~ PURPOSE: MAIN MENU FOR EDITING ~/
/~ TOP LEVEL PREDICATE ne×tstep ~/
/#~####~#######,#~#####~###~##~##~########~####~#####~#~#~##e~#*##~##~/
PREDICATES
e d i t l e d i t 2 ( i n t e g e r ) nextstep n e x t s t e p l ( i n t e g e r )
CLAUSES
editl:- menu(16~40, "Editing o~",
E "FILES", "GROUPS", "ATTRIBUTES ", "QUIT "], CHOICE),
edit2(CHOICE).
e d i t 2 < O ) : - ! .
edit2(1):- edit_£iles, !.
ed i t2 (2 ) edit_groups, !.
edit2(3) edit_art rib_menu, !.
edit2(_):- !.
165
nextstep:- clearwindow, wr i te( "> ") , menu( 16,40, "NEXT STEP",
["EDIT THE DATA", "PROCEED WITH D~ALOG"], CHOICE),
nex%s%epl(CHOICE).
nextstep1(O):- !,
nextstep1(1):- e d i t l , !, nextstep.
nextstep1(_).
166
/ . . / / * PURPOSE~ OVERALL CONTROL OF THE INPUT OF * / / * THE DIALOG THAT ACCEPTS THE USER * / I* INPUTS OF THE DATA ITEMS */ / . * /
/ * TOP LEVEL PREDICATE inpu tda ta * / I. */ /* SCREEN NUMBERS 5-13 */ /. */
PREDICATES
inputdata askesl askes2a
CLAUSES
inpu~data:- write("> Can you already Foresee readln(ANS)~ upper_lower("Y",ANS), !, askesl, nextstep.
the data ~ i l es you w i l l need
<Y/N) ?"
inputdata:- removewindow,removewindow, makewindow(3,2,11,"DIALOG",iS,35,10,45), clearwindow, write("> Input the attributes you wish to store"),nl, write(" Give one attribute per line ..."),nl, write(" At end press Return"),nl, makewindow(5,52,7,"ATTRIBUTES",O,34,14,45), shi~twindow(3) , ask attribs_es2( .... ), entity weak(,_), !, askes~a, ne×tstep.
inputdata:- makewindow(4,0,O,"",7,1,3,3), asserta(entity_strong("~lat file")), retract(attribute es( .... ,X)), asserta(attribute_es("#lat #ile",X)), #ail,
i npu tda ta . askes1:-
removewindow,removewindow, makewindow(3,2,11,"DIALOG",15,35,10,45), makewindow(4,0,O,"",7,1,3,3), shi~twindow(3) , ask f i l e_names l , f a i l .
167
askesl:- entity_strong(_), !, a s k _ a t t r i b s _ e s l .
/~ Checks ex is tence oF £ i l e s ~/
askes2a:- makewindow(4 ,0 ,O, " " ,7 ,1 ,3 ,3 ) , sh i£ twindow(3) , clearwindow, w r i t e ( " > To begin wi th we w i l l make one £ i l e " ) , n l , w r i t e ( " ~or each g r o u p . " ) , n l , n l , w r i t e ( " A t t r i b u t e s which are not in any g r o u p " ) , n l , w r i t e ( " w i l l be put in a F i l e named 'ung~ouped ' " ) , n l , n l w r i t e ( " > Press any key to continue . . . . " ) , readchar(_) , F a i l .
askes2a r e t r a c t ( e n t i t y _ w e a k ( " " , X ) ) , a s s e r t a ( e n t i t y _ s t r o n g ( X ) ) , F a i l .
askes2a ~m
r e t r a c t ( a t t r i b u t e _ e w ( " " , X , A ) ) , a s s e r t a ( a t t r i b u t e _ e s ( X , A ) ) , £ a i l .
askes2a:- ~ i n d a l l ( X , a t t r i b u t e _ e s ( " " , X ) , L ) , n o t ( e q u a l ( L , [ 3 ) ) , asse r t a (en t i t y_s t r ong (ung rouped ) ) , r e t r a c t ( a t t r i b u t e es( .... ,X ) ) , asse r t a (a t t r i bu te_es (ung rouped ,X ) ) , F a i l .
askes2a:- d isp lay_~ i les , . ~ a i l .
askes2a:- clearwindow, w r i t e ( " > In these ~ i l e s , you might be a b l e " ) , n l , w r i t e ( " t o F u r t h e r g r o u p t h e a t t r i b u t e s . " ) , n l , n l , w r i t e ( " > P r e s s a n y k e y t o c o n t i n u e . . . . " ) , r e a d c h a r ( _ ) , e n t i t y _ s t r o n g ( X ) , d i s p l a y _ £ i l e s , clearwindow, ask_groups_es(X), ~ a i l .
askes2a.
168
***************************************************************************
I* . / /* FILE : FDS.PRO */ / * . / / * The predicates in t h i s ~ i l e conduct the d ia log to * / / * in~er the #uct ienal dependencies * / /. * I ***************************************************************************
/@@@@@~@@@@@@@~.~@@@~@@@@@@@@@@@@@@@@@@@@@~@@@@@@~@~@@~@@@~@@@@@@@@@@@/ I. *I /* TO INFER THE FD'8 BASED ON KEY */ I* *I / * keys * / I. *I /* 15 -18 */ I. *I ************************************************************************
PURPOSE:
TOP LEVEL PREDICATE
SCREEN NUMBERS
PREDICATES
keys explain_key ask_keys ask keys_es(symbol) ask_keys_ew(symbol) ask_keys1(symbol,symbol~ ask_keys2(symbol,symbol) ask_keys3(symbol,symbol,lis~,list> ~heck_key(symbol,symbol,list) check existence(symbel,symbol,symbol,list,list)
CLAUSES
k e y s : - explain_key, a s k _ k e y s .
169
I# El /~ FILE: KEY_DEF.TXT ~/
/# > In every ~ i l e / g r o u p there w i l l be an #/ /# i d e n t i f i e r : an a t t r i b u t e or a group #/ /~ of a t t r i b u t e s ca l l ed the: ~/ /# KEY #/ /# whose vlaue is unique f o r a l l the ~/ /~ e n t r i e s in tha t ~ i l e or group ~/ /~ (see example). ~/
/~ Press any key to cont inue . . . #/
/~ FILE: KEY EG.TXT ~/
/~ For a STUDENTS f i l e : #/
/~ ROLL NO NAME CLASS ~/ /~ 8769 Kasturi M.Tech. ~/ /~ 8734 V i j a y B.Tech. #/
/~ ROLL NO is unique ~or a l l the #/ /# e n t r i e s in t h i s ~ i l e . ~/
/# Hence ROLL NO is a KEY. ~/
explain_key:- shi~twindow(3), clearwindow, f i l e _ s t r ( " k e y s d e ~ . t x t " , C ) , write(C), field_attr(3,15,3,79), field_attr(4,17,7,15), makewindow(9,26,7,"EXAMPLE OF KEY",8,0,16,35), file_str("keys_eg.t×t",B), w r i t e ( B ) , field_attr(3,1,7,79), field_attr(5,1,4,31), field_attr(6,1,4,31), readchar(_), removewindow, sh i f tw indow(3 ) , f a i l .
explain_key:- makewindow(6,90,10,"KEY",4,1,4,31), w r i t e ( " a t t r i b u t e ( s ) tha t d e t e r m i n e " ) , n l , write("values o~ all attributes " ) , shi~twindow(3), fail.
170
explain_key:- clearwindow, write("> In general, there may be more than"~,nl, write(" one key in a File (or a group)."),nl, nl,nl, write("> Press any key %o continue .... "),nl, readchar(_), ~ail.
explain_key:- !,
askkeys:- makewindow(7~3£,7,"KEYS',8,14,17,20), shi~twindow(3), ~ail.
ask_keys:- entity s~rong(FILEl), display_Files, shi~twindow(3)~ d i sp lay_a t t r i bs (F ILE1) , shi~twindow(3), ask_keys_es(FILE1~, ~ail.
ask_keys~
ask_keysl(FiLEI,GROUP):- ask keys2(FILE1,GROUP), write("> Are there any more keys readln(ANS1), upper_lower('Y",ANS1),
ask keysI(FILEI,GROUP).
(Y/N) 2 " ) ,
a s k _ k e y s t < F t L E l , " " ) : - key_es<EFtLE1] , ) , ! .
ask_keysl(FlLE1,""):-
write("> There must be at !, ask_keysl(FILE1,"">.
leas% one key " ) , n l ,
ask_keys1(FILEI,X):- key_ew(EFILEl],EX],_), !.
ask_keysl(FiLEI,GROUP):- nl, write("> There must be at !, ask_keysl(FiLE1,GROUP).
least one key " ) ~ n l ,
171
ask_keys2(FILEI,GROUP):- wr i te ( "> Enter the a t t r i bu tes that ~orm a k e y , " ) , n l , w r i t e ( " Enter one a t t r i b u t e per l i n e , " ) , n l , w r i t e ( " When done, press r e t u r n " ) , n l , ask_keys3(FILEI,GROUP,KEYI,[]), check_key(FILEI,GROUP,KEYI), display_keys(FILEl), !, w r i te ( "> Are there any more keys (Y/N) ?") , readln(ANS1)~ upper_lower("Y",ANS1), ask_keys~(FILE1,GROUP).
ask_keys2(_,_).
ask_keys3(FILE1,GROUP,KEYI,IN):- wr i te ( "> " ) , readln(NAMEU), not (NAMEU = .... ), upper_lower(NAMEU,NAME), !, check_existence(FILEI,GROUP,NAME,IN,OUT), ask keys3(FILEI,GROUP,KEYI,0UT).
ask_keys3(FILEI,GROUP,KEYI,IN):- wr i te ( "> Any more a t t r i bu tes in readln(ANS), upper_Iower("Y",ANS), !, ask keys3(FILEI,GROUP,KEYI,IN).
the key (Y/N)?"),
ask_keys3( .... KEYI,KEYI).
check_existence(FILE1,"",NAME,IN,OUT):- a t t r ibu te_es(FILEI ,X) , X=NAME, !, union(OUT,[NAME3,IN).
check_existence(FILEl,"",NAME,IN,OUT):- attribute_ew(FILE1,_,X), X=NAME, !, union(OUT,ENAME],IN).
check_existence(FILEI,GROUP,NAME,IN,OUT):- attribute_ew(FILEI,GROUP,X), X=NAME, !, union(OUT,ENAME3,IN).
check_e×istence(_,_,_,X,X):- wr i te ( "> Undeclared/Mis-spelt a t t r i b u t e " ) , n l , !.
172
check_key (F ILE l , " " ,KEY) : - key_es(EFZLEl ] ,X) , equal(X,KEY), write("> This key !.
is already known"),nl,
check_key(FILEI,GROUP,KEY):- key_ew(EFILEI],EGROUP],X), equal(X,KEY)~ write("> This key is already known ") ,nl,
check_key(_,_,E]):- write("> Key must J=
have at least one a t t r i b u t e " ) , n l ,
check key(FILEI,"",KEY1):- assertz(key_es(EFILE1],KEY1)),
check_key(FZLE~,GROUP,KEYi):- assertz(key_ew(EFILE1],EGROUP],KEY1)).
ask_keys_es(FILEl)~- clearwindow, ask_keys_ew(FiLEl), write("> Now ~or ~ile: ")~ write(FILE1),nl, ~ield_attr(O,15,25,11), display_attribs_ew(FILE1,""), ask_keysl(FILE1,"").
ask_keys_e~{FILE1):- entity_weak(FILEI,X), write("> For group : "), write(X),nl, field_a~tr(0,15,~5,14), write("> In ~ile : "), cursor (PP,_) , w r i t e ( F I L E 1 ) , ~ield_attr(PP,15,~5,11),nl, display_attribs_ew(FILEI,X), ask_keys1(FiLEI,X), ¢learwindow, Fail.
ask_keys_ew(_),
173
/ ~ ~ ~ ~ ~ . ~ ~ ~ ~ ~ * ~ /
/~ PURPOSE: TO INFER THE FD'S BASED ON A * / /~ PART OF THE REY ~/
/~ p a r t e d ~/
/ ~ ~ 3 - ~ 6 ~ /
I ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ I
TOP LEVEL PREDICATE
SCREEN NUMBERS
PREDICATES
explain part ial~d part ia l~d getkey(symbol,symbol,l ist) part ial~d1(symbol,symbol, l ist) part ial~d2(symbol,symbol, l ist) read_part k e y ( l i s t , l i s t , l i s t ) read part attrib(symbol,symbol,symbol) checkname pk e s ( l i s t , s y m b o l , l i s t , l i s t )
CLAUSES
getkey(FILE,"",REY):- ent i ty_strong(FILE), key es([FILE3,KEY).
getkey(FILE,GROUP,REY):- entityweak(FILE,GROUP), key ew(EFILE],EGROUP],KEY).
174
I* .I /* FILE: PARTFD.TXT ~/ I* *I /* Roll No Name Course Grade #/ I* *I /* 1267 ATUL CADS A */ /* 1267 ATUL DPS B */ /* 1267 ATUL OR C */ /* 1270 JOY CADS C * / 7" 1270 JOY DPS B */ /* .I I* ./ / # Key is (Ro l l No, Course) * / /~ Name depends on on ly a par t * / /* of the key, i.e. Roll No. */ I* ./ /@@~@@@@@~@@@@@~@@@@@@@@@@@~@~@@@@@@@@@@@~@@@@~/
explain_partialfd:- clearwindow, write("> Here we want to see if there are"),nl, w r i t e ( " some a t t r i b u t e s which depend on " ) , n l , w r i t e ( " on ly a part of the key (see e x a m p l e ) . " ) , n l , n l , w r i t e ( " > Press any key to continue . . . " ) , d i s p l a y _ f i l e s , makewindow(2,26,7,"Example of part key",8,0,16,35), nl, file str('partfd.txt",A), write(A), shiftwindow(3), readchar(_), m a k e w i n d o w ( 7 , 9 0 , 1 4 , " K E Y S " , O , 1 3 , 7 , 2 0 ) ~ partialfd, !.
partialfd:- getkey(FILEI,GROUP,EX~XT]), not (equal (XT,E])), dieplay_attribs_ew(FILEI,GROUP), shiftwindow(7), ¢learwindow, write("For Key :"),nl, writelist_hz(EXIXT]), partialfdl(FILEI,GROUP~EXIXT]), fail.
partialfd.
175
par t ia lFd1( . . . . . ) : - shiFtwindow(3), clearwindow, f a i l .
partialfd1(FILE1,GROUP,KEY):- clearwindow, w r i t e ( " > For the Key shown in KEYS w i n d o w : " ) , n l , n l , d i sp lay_a t t r i bs (F ILE1) , w r i t e ( " Is there any a t t r i b u t e which is a F f e c t e d " ) , n l , w r i t e ( " by only a part of the key (Y/N)?") , readln(ANS), u p p e r _ l o w e r ( " Y " , A N S ) , partialFd2(FILEI,GROUP,KEY).
partialFdl( . . . . . ) .
partial~d2(FILEI,GROUP,REY):- w r i t e ( " > Please enter the part key a t t r i b u t e s " ) , n l , w r i t e ( " one by one. When done, press R e t u r n " ) , n l , read_part_key(KEY,E3,KEYl), read_part_attrib(FILEI,GROUP,NAME), asserta(Fd(KEY1,[NAME3)), w r i t e ( " > Any more such a t t r i b u t e s (Y/N)?") , readln(A), upper_lower("Y",A) , !, partialFd2(FILEi,GROUP,KEY).
par t ia lFd2( . . . . . ) .
read_par t_at t r ib(FILE1,"" ,NAME): - w r i t e ( " > Please type the a f fec ted a t t r i b u t e " ) , n l , w r i t e ( " > " ) , readln(NAMEU)~ upper lower(NAMEU,NAME), attr ibute_es(FILEI,NAME), !.
read_par t_a t t r ib (F ILE i , " " ,NAME) : - w r i t e ( " > No such att r ibute") ,n l ,n l , w r i t e ( " > Do you want to give a f fec ted " ) , n l , w r i t e ( " a t t r i b u t e (Y/N)? " ) , readln(A), upper_lower("Y",A), !, read_part_attr ib(FILE1,"" ,NAME).
read_part a t t r i b ( _ , " " , _ ) : - !, f a i l .
r e ad_pa r t_a t t r i b ( FILE i , GROUP, NAME ) : - w r i t e ( " > Please input the a f fec ted a t t r i b u t e " ) , n l , w r i t e ( " > " ) , read in (NAMEU), upper_lower (NAMEU, NAME), a r t r ibute_ew(FILE1 ,GROUP ,NAME), !.
176
read_par t_a t t r i b (FZLE1 ,GROUP,NAME) : - w r i t e ( " > No such a t t r i b u t e " ) , n l , w r i t e ( " > Do you want to give a{ {ected ? " ) , n l , w r i t e ( " a t t r i b u t e (Y/N)? " ) , readln(A), upper lewer("Y"~A), !, read part attrib(FILEI,GROUP,NAME).
read p a r t a t t r i b ( . . . . . ) : - C a i l .
r e a d _ p a r t key (KEY,A ,KEYt )~ - w r i t e ( " > " ) , readln(NAMEU), upper lower(NAMEU,NAME), not (NAME= .... ) , checkname_pk_es(EEY,NAME,A,X), !, read_part_key(KEY,X,KEY1).
read p a r t k e y ( K E Y , A , E E Y i ) : - w r i t e ( " > Any more a t t r i b u t e s in pa r t key ( Y / N ) ? " ) , readln(ANS), u p p e r _ l o w e r ( " Y ' , A N S ) , ! , read_par t_key (KEY,A ,EEY1) .
read part key(KEY,E],KEY1):- w r i t e ( " > You should give at least one a t t r i b u t e ~ ' ) , n l , n l , w r i t e ( " > Do you want to g i v e the p a r t key ( Y / N ) ? " ) , readln(ANS), u p p e r _ l o w e r ( " Y ' , A N S ) , !, read pa r t key (KEY,E ] ,KEY I ) .
read_part key (_ ,E3 ,_ ) : - !, #ai l~
r e a d _ p a r t _ k e y { _ , A , A ) o
checkname pk_ee(KEY,NANE,A,X):- member(NAME,EEY), uniQn (X,ENAME],A), !,
checkname_pk_es (_,_,A,A) : - w r i t e ( " > I t is not a member !, n l , w r i t e ( " > Input a g a i n " ) , n l .
o# t h i s k e y " ) , n l ,
177
/#~##~#~##~.~####~#~###~#~#~###~###~##~#####~##~#~.~#~##~#/
/# PURPOSE: TO INFER THE FD'S IN WHICH A NON-KEY * / /~ ATTRIBUTE DETERMINES A KEY ATTRIBUTE #/
/~ nonkeyfd #/
/~ 19-20 ~/
TOP LEVEL PREDICATE
SCREEN NUMBERS
PREDICATES
nonkeyfd f i nda l l _key ( l i s t , symbo l , symbo l , l i s t ) r e a d n o n k e y ( l i s t , l i s t , l i s t ) r e a d n o n k e y l ( l i s t , l i s t , l i s t , s y m b o l ) n o n k e y f d 4 ( l i s t , l i s t ) nonkeyCd3(list,symbol) n o n k e y f d S ( l i s t , l i s t ) nonkeyfdl(symbol,symbol)
CLAUSES
nonkeyfd:- makewindow(7,90,14,"KEY ATTRIBUTES",O,13,7,80), shiftwindow(5), removewindow, makewindow(5,58,7,"NON KEY ATTRIBUTES",O,34,14,46), shi~twindow(3), clearwindow, wr i te ( "> Locate the window t i t l e d KEY ATTRIBUTES"),nl, field_attr(O,86,15,14)~ write(" on the screen (upper left corner) and"),nl, w r i t e ( " Also the NON KEY ATTRIBUTES window (up ) " ) , n l , w r i t e ( " Proceed now keeping these two windows"),nl, w r i t e ( " in mind.") , n l , n l , wr i te ( "> Press any key to continue . " ) - . . F
readchar(_), f a i l .
nonkey~d:- clearwindow, wr i te ( "> Normally key a t t r i bu tes w i l l determine") ,n l , w r i t e ( " the values of non-key a t t r i b u t e s . " ) , n l , n l , w r i t e ( " However, there may be excep t i ons . " ) , n l , n l , wr i te ( "> Press any key to continue . . . . " ) , readchar(_), f a i l .
nonkey~d:- en t i t y strong(FILE1), shi~twindow(3), clearwindow, nonkey~dl(FILEi,""), f a i l .
178
nonkeytd:- en%i%y_weak(FiLE1~GROUP), shi~twindow(3), clearwindow, nonkeyCdl(FILEI,GROUP), t a i l .
nonkey£d:- shittwindow(7)~ removewindow, shi~twindow(5), clearwindow, shi£twindow(3),
nonkeyFd1(FILEI,GROUP):- t i n d a l l att(FILEI,GROUP,ALL), Findall_key(E3~FILEI,GROUP,ALLKEY), minus(NONKEY,ALL,ALLKEY), not(equal(NONKEY,[3)), !, shittwindow(7), clearwindow, ~ritelist_hz(ALLKEY), shittwindow(5), clearwindow, cursor(T,R), diep_list_col(T,R,NONKEY), shittwindow(3), wr i te("> In above windows do you see any wr i te ( " a t t r i bu te whose value depends wr i te ( " some o~ the non-key at t r ibutes readln(ANS), upper_lower("Y",ANS), nonkeytd2(ALLKEY~NONKEY), tail.
key"),nl, on "),nl,
( Y / N ) ? " ) ,
nonkeytd1(_,_).
~indall_key(A,FILEi,"",ALLKEY):- key_es(EFILE1],L), union(M,L,A), not (equal (M,A)),
~indalI_key(M,FILEI,"",ALLKEY)~
findall key(A~_,"",A)=
nonkeytd2(KEY,NONKEY):- nonkeytd4(NONKEY,Q), nonkey£d3(NEY,P), asserta(td(G,EP3)).
nonkeytd2(KEY,NONKEY):- clearwindow, write("> Any more Key attribute whose value"),nl, write(" depends on Non-key attributes (Y/N)? "), read!n(ANS), upper lower("Y",ANS), ?, nonkey~d2(KEY,NONKEY).
179
nonkey~d2(_,_).
nonkey~d3(KEY,P):- wr i te("> Input the key a t t r i b u t e . " ) , n l , wr i te("> "), readln(NAMEU), upper_lower(NAMEU,NAME), member(NAME,KEY), P=NAME, !,
nonkeyfd3(KEY,P):- wr i te("> This a t t r ibu te wri te("> Do you want to readln(ANS), upper_lower("Y",ANS), !, nonkey~d3(KEY,P).
is not in key" ) ,n l ,n l , input again (Y/N)?"),
nonkey~d3(_,_):- !, ~a i l .
nonkey~d4(NONKEY,Q):- wr i te("> Input such non key at t r ibutes wr i te ( " When done press re tu rn . " ) , n l , readnonkey([3,NONKEY,Q).
one by
readnonkey(IN,NONKEY,OUT):- wri te("> ") , readln(NAMEU), upper_lower(NAMEU,NAME), not(NAME=""), readnonkeyi(IN,NONKEY,OUTI,NAME), !, readnonkey(OUTI,NONREY,OUT).
readnonkey(A,NONREY,B):- wr i te("> Any more at t r ibutes (Y/N) ?"), readln(ANS), upper_lower("Y",ANS), !, readnonkey(A,NONREY,B).
readnonkey(E3,NONEEY,B):- wr i te("> You should give at least one") ,n l , wr i te ( " a t t r ibu te " ) , n l , n l , wr i te("> Do you want to give (Y/N)?"), readln(ANS), upper_lower("Y",ANS), !, readnonkey(E],NONKEY,B).
readnonkey(E],_,_):- !, ~ail.
readnonkey(IN,_,IN).
one") ,n l ,
180
readnonkeyI(IN,NONKEY,OUT,NAME):- member(NAME,NONKEY), union(QUT,IN,[NAME]), !.
readnonkeyi( IN,_, IN, ) : - w r i t e ( " > I t is not a non key a ~ t r i b u t e " ) , n l , w r i t e ( " > Input a g a i n " ) , n l .
181
/~ PURPOSE: TO INFER MULTI VALUED DEPENDENCIES ~/
/ * mvd~ ~/
/ * 2 1 - 2 2 ~/
TOP LEVEL PREDICATE
SCREEN NUMBERS
PREDICATES
mvds explainmvd mvdl mvd2(symbol) mvd3(symbol,symbol) mvd4(symbol ,symbol , l i s t ) ask md_a t t r ( s ymbo l , s ymbo l , l i s t ) ask_md_at t r1 (symbol ,symbol ,symbol , l i s t ) ask md a t t r 2 ( s y m b o l , s y m b o l , s y m b o l , l i s t , l i s t ) check md a t t r (symbol ,symbol ,symbol )
CLAUSES
/~ FILE: MVD EG.TXT ~/
/~ EXAMPLE : ~/
/~ ROLL NO COURSES TAKEN #/ /~ 8765 IME602,CS60I,IME624 * / /# 8766 IME602,IME624,ME651 ~/ /# 8767 IME602,1ME673,IME621 #/ / * B769 HSS730,EE450 * /
/~ Here, COURSE TAKEN can be seen ~/ /~ to take severa l values fo r any * / /# given value of the key, ROLL NO. #/
explainmvd:- clearwindow, w r i t e ( " > Now we need to know which among the " ) , n l , write<" attributes listed can take several"),nl, w r i t e ( " values ~or any given value o~ the k e y " l , n l , w r i t e ( " (see e×ample). ") , n l , n l , makewindow(2,26,7 , " 'Mul t i valued a t t r i b u t e s ' " , B , O , 1 6 , 3 5 ) , f i l e _ s t r ( "mvd_eg. t x t " , B>, w r i t e ( B ) , shiFtwindow(3), w r i t e ( " > Press any key to continue . . . . " ) , readchar(_) .
182
?ail~
check md attr(FILE!,:~',NAME>~ - key_es(EFILE13,X>, member(NAME,X),
~rite("> This attribute is already in keyo"),nl, ~ail.
check: md at%r<FILE1,'",NAME)~- retract(attribute_es(FILEI,NAME)), {.
check md attr( , " " )~- ! , write("> Undeclared/Misspelt a~%ribute'),nl, ¢ail~
chec< md attr(FILEI,GROUP,NAME):- key_ew(EFILE13,EGROUPD,X), member(NAME,X),
write("> This attribute is already in key."),nl, Call.
check_m~_attr(FiLE1,GROUP,NAME):- retract(attribute_ew(FILE1,GROUP,NAME)),
check ma attr<_,_~_):- write("> Undeclared/Misspelt attribute"),nl, #ail.
ask md a~tr2(FILEJ,GROUP,MD,IN,OUT):- ~ r i % e ( " > " > , readln(NAMEU), upper_lo~er(NAMEU,NAME), ~heck md attr(FILEI,GROUP,NAME),
union(OUTI,IN,ENAME]), ask md attr2(FILEI,GROUP,MD,OUTI,0UT)o
ask: md a~tr2(FiLEI,GROUP,NAME,IN,OUT):- write("> Any more attributes whose value"),nl, write(" depends on the value o~ : "), cursor(P,8), ~rite(NAME), ¢ield attr(P,Q,14,12),nl, write(" (Y/N)? " ) , readln(ANS), upper_lower("Y",ANS),nl,
write("> Enter %he attributes one per line."),nl, ~rite("> When done, Press return."),nl, ask md at%r~(F!LEI,GROUP,NAME,IN,OUT).
ask md attr2( ,_ .... X,X).
183
ask_md_attrl(FILEI,GROUP,NAME,RHS):- clearwindow, w r i t e ( " > Are there any a t t r i b u t e s whose w r i t e ( " depends on the value o~ : " ) , cursor(P,G), write(NAME),nl, ~ ie ld_a t t r (P ,G,14 ,12) , w r i t e ( " (Y/N)? " ) , readln(ANS), u p p e r _ l o w e r ( " Y " , A N S ) , I F
w r i t e ( " > I n p u t such a t t r i b u t e s one p e r w r i t e ( " When done, press r e t u r n . " ) , n l , ask md_attr2(FILEI,GROUP,NAME,ENAME],RHS).
ask md attrl(_,_~NAME,[NAME]).
ask md attr(FILEI,GROUP,KEY):- w r i t e ( " > " ) , readln(NAMEU), upper_lower(NAMEU,NAME), check_md attr(FILEI,GROUP,NAME), ask md attrI(FILEI,GROUP,NAME,RHS), asserta(mvd(KEY,RHS)), ~ a i l .
ask md attr(FILEI,GROUP,KEY):- w r i t e ( " > Any more a t t r i b u t e s which can w r i t e ( " more than one value ~or same w r i t e ( " the key (Y/N>? " ) , readln(ANS), upper_lower(ANS,"Y"), i F
w r i t e ( " > Enter the a t t r i b u t e " ) , n l , ask md_attr(FILEI,GROUP,KEY).
mvd2(FILEi):- entity weak(FILEI,GROUP), mvd3(FILEI,GROUP), ~ail.
mvd2 (_) .
mvd4( . . . . . ) : - shi£twindow(3), clearwindow, ~ a i l .
mvd4(_,_,X):- shi~twindow(7), clearwindow, w r i t e l i s t _ h z ( X ) , ~ a i l .
value") , n l ,
l i n e . " ) , n l ,
take " ) , n l , value o~") ,n l~
184
mvd4(FILE!,GROUP,X)~- shi{twindow(3), write("> Is ~here any attribute above which can"),nl, write(" take several values ~or a single value"),n!, w r i t e ( " o f ~he key (Y/N)? " ) , readln(ANS), u p p e r _ l o w e r ( A N S , " Y " ) , clearwindow, write("> Enter the attribute"),nl, ask md attr(F!LEI,GROUP,X).
mvd3(FILEI,GROUP):- getkey(FILEI,GROUP,X)~ ~indalI_att(FiLEI,GROUP,ALL), ?indall key(E],FILEI,GROUP,ALLKEY), minus(NONKEY,ALL,ALLKEY), not(equal(NONKEY,E])), shi{twindow(5), clearwindow, cursor(T~R), disp_list_co1(T,R,NONKEY), shi~twindow(3), mvd4(FILEI,GROUP,X), Fail.
mvd3(_,_)o
mvd1:- entity_strong(F!LEl>, mvd2(FILEl), mvd3(FILEl,"'>, ?all.
mvdl.
mvds:- expiainmvd, makewindow(7,90,7,"Keys",O,13,7,20), mvdl, shi~twindow(2), removewindow, shi~twindaw<3).
185
/ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /
/~ PURPOSE: MAIN CONTROL FOR INFERENCE OF FD'S ~/
/# TOP LEVEL PREDICATE {ds ~/
PREDICATES
Fds asser~Fds
CLAUSES
f d s : - shiFtwindow(~), removewindow, shiFtwindow(6), removewindow, shi~twindow(7~, removewindow, shi f twindow(3~, F a i l .
Fds:- nonkeyfd, mvds, F a i l .
~ds:- getkey(_,_,E_~XT3), not (equal (XT,E3)), !, explain_partial~d, shi£twindow(2), removewindow, shi~twindow(7), removewindow, shi~twindow(3) , asser t fds .
Fds:- assertFds.
asser tFds : - key_es(EFILE3,X), a t t r i b u t e _ e s ( F I L E , Y ) , asserta(~d(X,[Y3)), ~ail.
assertFds:- key_ew<EFILE3,[GROUP],X), attribute_ew(FILE,GROUP,Y), asserta(Fd(X,EY3)), fail.