View
232
Download
0
Category
Preview:
Citation preview
SATURA RĀDĪTĀJSIEVADS......................................................................................................................................81. DATU BĀŽU TEHNOLOĢIJAS..........................................................................................9
1.1. DATU BĀŽU TEHNOLOĢIJU APSKATS..................................................................91.2. RELĀCIJU MODELIS...................................................................................................91.3. RELĀCIJU ALGEBRA................................................................................................111.4. SQL VALODA.............................................................................................................131.5. DEDUKTĪVAS DATU BĀZES...................................................................................16
2. LOĢISKĀ PROGRAMMĒŠANA.......................................................................................202.1. ATTIEKSMJU LOĢIKA..............................................................................................202.2. LOĢISKĀ PROGRAMMĒŠANA...............................................................................222.3. PROLOG VALODA.....................................................................................................272.4. DATALOG VALODA.................................................................................................292.5. PROLOG UN DATALOG VALODU SALĪDZINĀJUMS.........................................302.6. DATALOG VALODAS SINTAKSE...........................................................................312.7. DROŠAS DATALOG PROGRAMMAS.....................................................................342.8. DATALOG VALODAS IZSKAITĻOŠANAS SEMANTIKA....................................35
3. DEDUKTĪVO DATU BĀŽU ARHITEKTŪRA.................................................................383.1. SASAISTE UN INTEGRĀCIJA..................................................................................383.2. FIZISKAIS LĪMENIS...................................................................................................413.3. LOĢISKAIS LĪMENIS................................................................................................423.4. DATUBĀZES PIEKĻUVES PROCEDŪRAS APRAKSTS.......................................433.5. DATUBĀZES INTERFEISS........................................................................................443.6. LOĢISKĀ LĪMEŅA INTERFEISS.............................................................................453.7. IZPILDES STRATĒĢIJU KOORDINĀCIJA..............................................................463.8. DEDUKTĪVO DATU BĀŽU UZLABOŠANAS TENDENCES................................46
4. DEDUKTĪVAS DATU BĀZES IZSTRĀDE......................................................................494.1. DEDUKTĪVAS DATU BĀZES SPECIFIKĀCIJA.....................................................494.2. PROGRAMMATŪRA..................................................................................................514.3. DEDUKTĪVAS DATU BĀZES ARHITEKTŪRA......................................................524.4. PROGRAMMATŪRAS DARBĪBAS ALGORITMI...................................................554.5. FAKTU TABULA........................................................................................................584.6. LIKUMU TABULAS...................................................................................................584.7. IZVADĪTO FAKTU TABULA....................................................................................60
5. IZSTRĀDĀTAS DEDUKTĪVAS DATU BĀZES PIELIETOJUMS.................................615.1. FAKTU DATU BĀZE..................................................................................................615.2. LIKUMU DATU BĀZE...............................................................................................625.3. IZPILDES PIEMĒRS...................................................................................................62
SECINĀJUMI...........................................................................................................................69TERMINU VĀRDNĪCA..........................................................................................................71LITERATŪRAS SARAKSTS..................................................................................................73PIELIKUMI..............................................................................................................................75PIELIKUMS 1..........................................................................................................................76PIELIKUMS 2..........................................................................................................................78PIELIKUMS 3..........................................................................................................................79PIELIKUMS 4..........................................................................................................................80PIELIKUMS 5..........................................................................................................................82PIELIKUMS 6..........................................................................................................................87
IEVADS
Viens no datoru izmantošanas pamata veidiem ir datu glabāšana un datu apstrāde. Datu
apjomi palielinās ļoti strauji, un nepieciešams veikt intelektuālo datu analīzi un secinājumus.
Viens no līdzekļiem, šādu problēmu risināšanai, ir deduktīvu datu bāžu izmantošana.
Deduktīvas datu bāzes, kā datu bāzes spēj glabāt un apstrādāt lielos datu apjomus, un kā
loģiskas programmas ar glabājamiem likumiem spēj iegūt jaunus datus no esošiem.
Deduktīvas datu bāzes pēc savas būtības ir datu bāzu un loģiskas programmēšanas
tehnoloģiju apvienojums. Deduktīvas datu bāzes ne tikai glabā datus, kā to dara relāciju datu
bāzes, bet glabā arī faktus, kuri sastāv no zināmiem datiem un glabā likumus, ar kuru
palīdzību var iegūt jaunus faktus no jau esošiem. Jauno faktu iegūšana tiek pamatota uz
loģisko programmēšanu, kad matemātisko loģiku izmanto aprēķinos un jauno faktu iegūšanai.
Loģisko vaicājumu izpildi nodrošina deduktīvas datu bāzes izveduma mehānisms.
Deduktīvas datu bāzes pēc uzbūves, dalās uz divām lielām kategorijām, saistītas un
integrētas. Saistītas deduktīvas datu bāzes darbojas kā loģiskas programmas un glabā visus
faktus un likumus ārējā datu bāzē. Integrētas sistēmas strādā kā datu bāzes, kurām ir definēta
loģiska vaicājumu valoda, kurā var aprakstīt likumus jauno faktu izveidei.
Darba galvenie mērķi ir apkopot dažādu autoru darbus par deduktīvo datu bāžu
tehnoloģiju, izstrādi un pielietojumu. Pēc apkopošanas tiek veikta kompleksa, sistemātiskā
analīze un deduktīvas datu bāzes projektēšana. Deduktīva datu bāze tiek izstrādāta, atbilstoši
definētai specifikācijai, pielietojot Java programmēšanas valodu ar Oracle datu bāzes vadības
sistēmu atbalstu. Deduktīvas datu bāzes funkcionēšanai un integrēšanai ar Oracle datu bāzes
vadības sistēmu tiek pielietota loģisko vaicājumu pārveidošana uz SQL vaicājumiem, kas
nodrošina plašas iespējas un elastīgumu.
Deduktīvai datu bāzei tiek implementēta Datalog vaicājumu valoda, kura tuvāk atbilst datu
bāžu vaicājumu valodām, un to ideoloģijai. Deduktīvas datu bāzes kodols tiek izstrādāts tādā
veidā, ka ļaus izpildīt citu lietotāju loģisko programmu plašu klāstu. Deduktīvas datu bāzes
kodola datu ievades un izvades pamatfunkcijas integrētas uz Oracle datu bāžu vadības
sistēmu.
8
1. DATU BĀŽU TEHNOLOĢIJAS
1.1. Datu bāžu tehnoloģiju apskats
Katra datu bāzes projektēšana sākas ar analīzi, kādiem datiem jābūt atspoguļotiem datu
bāzē, un kādas saites eksistē starp šiem datiem. Datu bāzes struktūra tiek izveidota izmantojot
kādu no datu bāzes izstrādes modeļiem, vai datu bāzes izstrādes valodām. Pēc projektēšanas,
saskaņošanas un precizēšanas, šis modelis tiek pārveidots tādā veidā, ka to var saprast Datu
Bāzes Vadības Sistēma (DBVS). Eksistē trīs datu bāzes realizācijas tehnoloģiju viedi.
1) Relāciju Datu Bāze, kura balstās uz relāciju modeli.
2) Objektorientēta Datu Bāze, kura balstās uz objektorientēto modeli.
3) Relāciju Objektu Datu Bāze, kura balstās uz objektu-relāciju modeli.
Relāciju modelim ir plašas iespējas, kuras atrod pielietojumu darba izpildei, tādēļ
apskatīsim relāciju modeļa būtību.
1.2. Relāciju modelis
Relāciju datu bāzēs dati tiek strukturizēti tabulās, kuras ir galīgu attieksmju atspoguļojums.
Efektīvai darbībai ar tādām tabulām ir paredzēta vaicājumu valoda SQL. Relāciju modelis
atspoguļo datus tikai ar vienu paņēmienu – ar tabulām, kur katra relācija ir definēta ar tabulas
palīdzību. Katrai tabulai ir sava noteikta atribūtu kopa. Katram atribūtam ir savs nosaukums.
Katram atribūtam parasti ir dažādu datu tipi un jēga. Katram atribūtam ir savs noteikts tips –
domēns.
Katra relācija sastāv no kortežiem. Katram kortežam ir definēta noteikta vērtība katram
relācijas atribūtam. Kāds korteža elements, kurš ir unikāls relācijas kopā, saucas par primāro
atslēgu. Šis elements ļauj viennozīmīgi identificēt visu kortežu attiecīgajā relācijā. Viens, no
noteikumiem, kuru izvirza relāciju modelis, ir tas, kā katram korteža elementam jābūt
atomāram. Un katram korteža elementam jāatbilst savam atribūtu domēnam.
Saites ir sakari starp realitātēm. Saites nosaka datu sasaisti, dažādās realitātēs. Eksistē trīs
veidu saites.
9
1) Saite viens-pret-viens eksistē tad, kad katra pirmās realitātes kortežs tiek sasaistīts
tikai ar vienu otrās realitātes kortežu.
2) Saite viens-pret-daudziem eksistē tad, kad katra pirmās realitātes kortežs tiek sasaistīts
ar vienu vai vairākiem otrās realitātes kortežiem.
3) Saite daudzie-pret-daudziem eksistē tad, kad viena vai vairāk pirmās realitātes korteži
tiek sasaistīti ar vienu vai vairākiem otrās realitātes kortežiem.
Relācijas nosaukums kopā ar atribūtu nosaukumiem pieņemts saukt par relācijas shēmu.
Relācijas shēmu kopa veido datu bāzes shēmu.
Katra relācija, pēc savas būtības nav statiska. Tā var mainīties. Pie relācijas var pievienot
jaunus kortežus, var dzēst jau esošos, var mainīt jau eksistējošos. Ir iespējamas arī tādas
izmaiņas, kuras ietekmē uz relācijas shēmu. Relācijas shēmā var pievienot jaunus atribūtus,
vai dzēst esošos, bet ieteicams tā projektēt datu bāzi, lai iespējamo izmaiņu skaitu
minimalizētu.
Ir viens interesants ieskats uz relāciju datu modeli, kā paradīts attēlā 1.1. Pēc savas būtības
to var izskatīt kā vienkāršo deduktīvo datu bāzi, jo tajā pastāv gan dati, gan fakti, gan likumi.
1.1. Att.: Relāciju datu modelis
Dati - definētas noteiktas vērtības katram relācijas atribūtam.
Fakti - lietotāju datu korteži, kuri glabās lietotāju noteiktās attiecībās.
Līkumi - noteikumi, kuri noteic datu bāzes veselības robežas, datu bāzes trigeri un
virtuālās attiecības.
10
Uz relāciju datu bāzēm eksistē jaudīgs izveduma mehānisms, SQL valoda ar rekursiju,
kura ļauj iegūt datus no relāciju datu bāzes.
Relācijas modeļa fundamentālais apraksts dots rakstā [5]. Relācijas modeļa mūsdienīgas
koncepcijas un pielietojumi ir aprakstīti grāmatās [12] un [17].
1.3. Relāciju algebra
Visas darbības, kuras izpildās relāciju modelī aprakstītas ar relāciju algebru, attēls 1.2.
Relāciju algebras metodes kopā ar relāciju modeli veido vieglus un uzskatāmus datu
glabāšanas, datu izmaiņas, datu apstrādes procesus un citas aktivitātes. Ar relāciju algebru var
viegli aprakstīt vaicājumu priekš relāciju datu bāzes.
1.2. Att.: Relāciju algebras darbības
Relācijas algebras pamatfunkcija ir jauno relāciju veidošana no jau esošām relācijām ar
noteiktām darbībām. Relācijas algebras operandi ir relācijas, un relācijas algebras
pamatdarbības var sadalīt uz četrām daļām.
1) Parastas darbības ar relācijām: apvienošana, pārklājums un starpība.
2) Relāciju daļu dzēšanas darbības: selekcija un projekcija.
3) Divu relāciju kortežu kombināciju darbības: Dekarta reizinājums, dabisks
savienojums, tēta savienojums un dalīšana.
4) Atribūtu un relāciju nosaukumu izmaiņu darbības: relācijas nosaukumu izmaiņa,
relācijas atribūtu nosaukumu izmaiņa.
Relācijas algebras darbības pieņemts nosaukt par vaicājumiem.
Apvienošana: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā ietilpst visi
elementi no relācijas R1 un visi elementi no relācijas R2. Katrs elements tiek ieslēgts relācijā
R tikai vienu reizi, pat ja viņš pieder pie relācijas R1 un relācijas R2. Pie tam shēmām
relācijām R1 un R2 jābūt vienādām, un atribūtiem jābūt sakārtotiem vienādā secībā [10].
11
Pārklājums: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā ietilpst elementi
no relācijas R1 kuri pieder arī relācijai R2. Pie tam shēmas relācijām R1 un R2 jābūt
vienādām, un atribūtiem jābūt sakārtotiem vienādā secībā [10].
Starpība: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā ietilpst visi
elementi no relācijas R1 kuri nepieder relācijai R2. Pie tam shēmas relācijām R1 un R2 jābūt
vienādām, un atribūtiem jābūt sakārtotiem vienādā secībā [10].
Selekcija: R = condition (R1). Darbības rezultātā tiek iegūta relācija R kurā ietilpst visi
elementi no relācijas R1, kuri atbilst nosacījumam condition [10].
Projekcija: R = a1, a2 (R1). Darbības rezultātā tiek iegūta relācija R ar atribūtiem a1 un
a2, kurā ietilpst visi elementi no relācijas R1 [10].
Dekarta reizinājums: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā katrs
elements sastāv no divām daļām. Pie tam pirmā daļa ir jebkurš elements, kurš pieder relācijai
R1, un otra daļa ir jebkurš elements, kurš pieder relācijai R2. Relācijas R shēma tiek iegūta,
apvienojot relāciju R1 un R2 shēmas. Relācijas R elementu skaits ir vienāds ar relāciju R1 un
R2 elementu skaitu reizinājumu [10].
Dabisks savienojums: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā
ietilpst elementi no relācijas R1 un elementi no relācijas R2, pie tam tiek iekļauti tikai tie
elementi, kuriem ir vienādas vērtības atribūtos, kopējas gan relācijai R1, gan relācijai R2.Un
elements, kurš iekļauts relācijā R, satur tikai vienu vērtību, katram atribūtam. Relācijas
shēmās relācijai R1 un R2 ir daudz vienādu atribūtu, tad visas vērtības atribūtos sakrīt [10].
Tēta savienojums: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā katrs
elements sastāv no divām daļām. Pie tam pirmā daļa ir jebkurš elements, kurš pieder relācijai
R1, un otra daļa ir jebkurš elements, kurš pieder relācijai R2. Un relācijā R tiek iekļauti tikai
tie elementi, kuri atbilst noteikumam . Relācijas R shēma tiek iegūta, apvienojot relāciju R1
un R2 shēmas [10].
Dalīšana: R = R1 R2. Darbības rezultātā tiek iegūta relācija R, kurā katrs elements
pieder pie relācijas R1 un visi elementu atribūtu vērtības sakrīt ar tādu pašu atribūtu vērtībām
relācijā R2 [10].
Relācijas nosaukumu izmaiņa: R = (R1). Darbības rezultātā relācijas R1 nosaukums
tiek izmainīts uz R nosaukumu [10].
12
Relācijas atribūtu nosaukumu izmaiņa: R = (a1, a2) (R1). Darbības rezultātā tiek iegūta
relācija R ar atribūtiem a1 un a2, kur relācijas R1 atribūtu nosaukumi bija izmainīti uz
nosaukumiem a1 un a2 [10].
Relācijas algebras pamata apraksts, kā arī minētais relācijas modelis dots rakstā [5].
1.4. SQL valoda
SQL valoda ir universāla relāciju datu bāžu vaicājumu valoda. Visus vaicājumus un
komandas, kas attiecas uz datu bāzi ir pieņemts aprakstīt ar šo valodu. Vaicājumu valoda SQL
atrodas ļoti tuvu priekš relācijas algebras ar papildu operandiem. SQL valodas vaicājumi
izpildes gaitā pārveidojas uz relāciju algebras darbībām. Relāciju algebras darbības izpildās
Relāciju datu bāzē, attēls 1.3.
1.3. Att.: Vaicājumu izpilde Relāciju datu bāzē
Ar valodu SQL var gan pievienot jaunus datus, gan izmainīt jau esošos datus, gan dzēst
tos. Arī ir iespēja mainīt datu bāzes shēmu. Eksistē daži standarti, kuri apraksta valodu SQL,
un to funkcijas un iespējas. Vaicājumus vaicājumu valodā SQL var sadalīt uz trim lielām
grupām, pēc izpildāmo funkciju.
1) Datu definēšanas vaicājumi.
2) Datu pārvaldības vaicājumi.
3) Datu iegūšanas vaicājumi
Katru vaicājumu SQL valodā apraksta ar slegvārdiem.
Datu definēšanas vaicājumiem ir nozīme, lai radītu datu bāzi un izveidotu tajā tabulas.CREATE DATABASE myDDB;
Vaicājums izveido jauno datu bāzi ar vārdu myDDB.
CREATE TABLE myDDBLog( Log_ID number primary key,
13
Log_Date date, Log_Text varchar(150));
Vaicājums izveido jaunu tabulu ar vārdu myDDBLog, ar atribūtiem Log_ID, Log_Date
un Log_Text, katram atribūtam ir savs datu tips.
DROP TABLE myDDBLog;
Vaicājums dzēš tabulu myDDBLog ar visiem datiem.
ALTER TABLE myDDBLog ADD Log_Type varchar(10) DROP Log_Text;
Vaicājums maina tabulu myDDBLog, pievienojot jaunu atribūtu Log_Type ar datu tipu
varchar(10) un dzēš lieko atribūtu Log_Text.
CREATE OR REPLACE TYPE TArg AS OBJECT( Arg_ID number, Arg_Type varchar(30), Arg_Value varchar(30));
Vaicājums izveido jauno datu tipu ar vārdu TArg, ar atribūtiem Arg_ID, Arg_Type un
Arg_Value, katram atribūtam ir savs datu tips.
Datu pārvaldības vaicājumiem ir nozīme pievienojot jaunus datus, izmainot jau esošos un
dzēšot vecos datus.INSERT INTO myDDBLog (Log_ID, Log_Text)
VALUES (‘1’, ‘Starting myDDB v.1.0’);
Vaicājums pievieno jaunus datus ‘1’ un ‘Starting myDDB v.1.0’ uz tabulu
myDDBLog.
UPDATE myDDBLog SET Log_Text=’Oracle 10g Database connected’ WHERE Log_ID = ‘1’;
Vaicājums maina datus tabulā myDDBLog atribūts Log_Text pieņem jauno vērtību
’Oracle 10g Database connected’, ja izpildās noteikums Log_ID = ‘1’.
DELETE FROM myDDBLog WHERE Log_ID = ‘1’;
Vaicājums izslēdz datus no tabulas myDDBLog ja izpildās noteikums Log_ID = ‘1’.
Datu iegūšanai ir lielāka nozīme SQL valodā. Visi vaicājumi, kuri saistīti ar datu iegūšanu
sākas ar valodu SELECT. Un SELECT tipa vaicājumi lieliski attēlo SQL valodas ļoti plašās
14
iespējas. Kā piemēri doti trīs vaicājumi, kuri tiek lietoti izstrādātā deduktīvā datu bāzē, tie labi
parāda iespējas, kuras nodrošina SQL vaicājumu valoda.1. SELECT R.Rule_Name, R.Rule_ID, R.Rule_Predicates FROM Rules R ORDER BY R.Rule_Name;2. SELECT COUNT(Deducted_ID) FROM Deducted;3. SELECT A.Arg_ID, A.Arg_Type, A.Arg_Value FROM Facts F, table(F.Fact_Args) (+) A WHERE F.Fact_ID IN ( SELECT F.Fact_ID FROM Facts F WHERE F.Fact_Name = ‘ancestor’) ORDER BY F.Fact_ID;
Pēc slegvārda SELECT ir aprakstīti lauki, kurus vajag iegūt. Pie tam, lauku apzīmējumiem
un izteiksmēm var izmantot dažus slegvārdus – ALL (iegūt visus rakstus), DISTINCTROW
(iegūt tikai unikālus, nedublējošus rakstus), DISTINCT (iegūt tikai rakstus ar unikālām lauka
vai izteiksmes vērtībām, TOP N(apskatīt tikai pirmos N atrastos rakstus).
Slegvārds FROM nosaka tabulas, kurās dati tiek meklēti. Un katrai tabulai var norādīt
nosaukuma sinonīmu.
Slegvārds WHERE nosaka noteikumus, kuriem jāatbilst meklētajiem rakstiem. Vairākus
noteikumus var sasaistīt ar AND, vai OR saitēm.
Slegvārds GROUP BY nosaka laukus un pēc to vērtībām raksti rezultātā tiek sagrupēti.
Slegvārds HAVING apraksta noteikumus rakstu grupām. Šeit tiek izmantotas funkcijas
SUM(), COUNT(), MIN(), MAX() un operatori IN, NOT IN, NOT EXISTS.
Slegvārds GROUP BY nosaka tādus laukus, pēc kuru vērtībām jāsakārto iegūtā rakstu kopa.
Vaicājumu valodas SQL-99 standartā parādījās hierarhiskie vaicājumi, kuri ļauj izmantot
rekursīvu faktu iegūšanu. Hierarhisko vaicājumu realizācija ļoti atkarīga no datu bāzes
vadības sistēmas. Kā piemēru, var minēt tādu hierarhisko vaicājumu.WITH RECURSIVE ceļš (no, uz) AS
(SELECT no, uz FROM nogrieznis)UNION
(SELECT ceļš1.no, ceļš2.uzFROM ceļš ceļš1, ceļš ceļš2
15
WHERE ceļš1.uz = ceļš2.no)SELECT * FROM ceļš;
Vaicājums izskaitļo visus iespējamos ceļus, no dotiem nogriežņiem un darbības beigās
izvada visus iegūtos ceļus.
Apraksts par pilno SQL valodas iespējām ir vesela grāmata, tāpēc bija aprakstīti vaicājumi,
kuri atrod pielietojumu darba izstrādē. Pilns vaicājumu valodas SQL-99 standarts bija
publicēts [3].
1.5. Deduktīvas datu bāzes
Deduktīva datu bāze (Deductive Database) paplašina relāciju datu bāzi, izmantojot loģisko
programmēšanu, un atbalsta plašākas datu apstrādes tehnoloģijas, attēls 1.4. Deduktīva datu
bāze ir kombinācija no datu bāzes, kura satur faktus, zināšanu datu bāzes, kura satur līkumus,
un izveduma mehānismu (inference engine), kurš spēj iegūt jaunus datus no jau esošiem
faktiem izmantojot definētus līkumus [2].
1.4. Att.: Deduktīva datu bāze
Deduktīvajā datu bāzē glabājas trīs veidu informācija, dati, fakti (fact) un likumi (rule).
Pirmā un otrā veida informācija skaidri raksturo reālās pasaules objektus. Tie ir tiešie fakti,
kurus lietotājs glabā datu bāzē. Trešā veida informācija kalpo deduktīvas datu bāzes vadībai,
izpildot vaicājumus, un izpildot jauno faktu izvadi, no jau esošiem faktiem.
16
1) Dati - mazākie nedalāmie informācijas gabaliņi tādā formā, ka tos var, saglabāt,
apstrādāt un pārsūtīt ar datu bāzes funkcijām.
2) Fakti - lietotāju datu korteži, kuri glabājas lietotāju noteiktās attiecībās, kas saista
dažādus datus kopā.
3) Likumi - noteikumi, kuri izvada jaunus datus no esošiem faktiem, un veido datu
savstarpēju sasaisti.
Fakts ir izteiksme, kurā apraksta vienu noteiktu daļu vai objektu no apkārtējās pasaules. Tā
kā fakts ir izteiksme, tad viņam vērtība ir PATIESĪBA. Fakti atšķiras no likumiem ar to ka
likumiem ir vērtība PATIESĪBA tikai tad, kad visām likuma mainīgām vērtībām ir
PATIESĪBA.
Lai glabātu faktus lietderīgi, glabašānai tiek izmantota relāciju datu bāze. Jo tajā ļoti
vienkārši glabāt viena tipa datus, un tos var apstrādāt ar jau izstrādātām, drošām un ātrām
metodēm. Zināšanu datu bāze ir zināšanu krājums, kur zināšanas tiek izteiktas kādā formālā
zinātņu attēlojuma valodā. Deduktīvas datu bāzes gadījumā zināšanas ir likumi. Šie likumi
pilnīgi balstās uz matemātisko loģiku. Līkumi aprakstā priekšmetiskās jomas semantiku.
Izveduma mehānisms parasti ir programma, kura izved jaunus faktus no jau esošiem
faktiem, izmantojot izveduma procedūru. Parasti izveduma mehānisms nepastāv, kā atsevišķa
daļa, bet jau ir iebūvēta zināšanu datu bāzē. Mehānisms kombinē zināmus faktus, lai iegūtu
jaunus faktus, izmantojot likumus, kuri glabājas zināšanu datu bāzē.
Deduktīvas datu bāzes sistēmas raksturo spēja vadīt lielus datu apjomus un veikt spriešanu
izmantojot šos datus. Deduktīva datu bāze sastāv no divām daļām:
1) Faktu datu bāze (Extentional Database), kura satur datus. Parasti tiek lietota relāciju
datu bāzes vadības sistēmā.
2) Zināšanu datu bāze (Intensional Database), kura satur jaunu datu loģiskas izvades
likumus no faktu datu bāzes daļas un lietotāja pieprasījuma pamatā. Tiek lietota
loģiska vaicājumu valoda, loģisko vaicājumu izpildei.
Zināšanu datu bāzes daļa sakumā satur tikai likumus. Un vaicājumu izpildes gaitā,
zināšanu daļa krāj jaunus, izvadītus faktus. Faktu iegūšana ir balstīta uz līkumiem, kuri ņem
sākotnējus faktus no faktu datu bāzes daļas.
Galvenā atšķirība deduktīvas datu bāzes, no relāciju datu bāzēm ir tas, ka datu bāzes
zināšanas daļas noteikumi un lietotāju pieprasījumi var saturēt rekursiju. Šī atšķirība, rekursiju
noteikumi un lietotāju pieprasījumu definīcija dod iespēju atrast problēmas vieglus
atrisinājumus deduktīvās datu bāzēs, kuras izsauc lielas problēmas relāciju sistēmās. No citas
17
puses, tieši rekursijas iespēja izsauc deduktīvas datu bāzes ļoti sarežģītu realizāciju. Ja likums
aprakstīts tādā veidā, ka izmanto rekursīvo izsaukumu, tad jauno faktu iegūšanai ir izmantoti
gan faktu datu bāzes fakti, gan jau izvadītie fakti, kuri glabājas zināšanas datu bāzes daļā.
No loģiskās programmēšanas viedokļa deduktīvās datubāzes var tikt vienlīdz apskatītas arī
kā loģiskās programmas, bet pastāv dažādas būtiskas atšķirības [1]:
1) Deduktīvajās datubāzēs glabātā faktu kopa parasti ir daudz lielāka par glabāto likumu
kopu.
2) Deduktīvajās datubāzēs predikāti tiek sadalīti divās kopās: faktu datu bāzes predikātu
(Extentional predicate) kopa un zināšanu datu bāzes predikātu (Intensional predicate)
kopa.
3) Deduktīvo datu bāžu valodas nesatur funkcijas, vai satur ļoti ierobežotu funkciju
skaitu.
4) Deduktīvās datubāzes atbalsta integritātes ierobežojumu definēšanu, kas ir svarīga
datubāzu sistēmu funkcija.
5) Tipiski datubāzes vaicājums meklē visus risinājumus, kuri apmierina vaicājuma
nosacījumus, bet mērķis loģiskajā programmā atrod tikai vienu no iespējamiem
risinājumiem.
Ir vairākas priekšrocības tam, lai lietotu pirmās kārtas loģiku kā deduktīvo datubāzu
teorētisko pamatu [1]:
1) Loģikai pašai par sevi ir labi saprotama semantika;
2) Loģika var tikt lietota kā unificēta valoda lai izteiktu faktus, likumus, vaicājumus un
ierobežojumus;
3) Labi formulētu loģikas teoriju var lietot, lai risinātu datu bāžu problēmas, piemēram,
tukšās vērtības un nenoteiktos datus;
4) Viena likuma lietošana var aizstāt daudzus izteiktos faktus.
Deduktīvajā datu bāzē ir iespējams daļu no likumiem glabāt iekšēji operatīvajā atmiņā un
pārējo daļu ārēji, datu bāzē. Likumi, pēc glabāšanas principa ir sadalīti divās grupās [1]:
1) Programmas predikāts, ir predikāts, kura likumi tiek pilnībā glabāti sistēmas darba
apgabala atmiņā.
2) Datubāzes predikāts, ir predikāts kura likumi tiek pilnībā glabāti ārējā datubāzē kad
notiek mērķu atrašana, šie likumi pēc vajadzības tiek aizgūti no datubāzes.
Šeit jāmin izņēmums, kas saistīts ar salīdzināšanas operatoriem un aritmētiskajām
funkcijām – predikātam ir jābūt vai nu programmas predikātam vai datubāzes predikātam, bet
18
ne abiem. Standarta salīdzināšanas operatori var tikt uzskatīti par tabulām relācijās ar diviem
atribūtiem, kas atbilst operandiem. N-vietīgas aritmētiskās funkcijas var tikt uzskatītas par
N+1 vērtīgām relāciju tabulām ar N atribūtiem operandiem un vienu atribūtu rezultātiem.
Tādējādi salīdzināšanas operatori un aritmētiskās funkcijas ir gan datubāzes predikāti gan
programmas predikāti.
1) Datubāzes fakts ir paplašināti definēts datubāzes predikāts.
2) Datubāzes mērķis ir likums ar tukšu galvu un tā ķermenis satur tikai datubāzes
predikātu izsaukumus.
3) Bāzes konjunkcija ir datubāzes mērķu konjunkcija.
Deduktīvajās datubāzēs sarežģītie mērķi var saturēt mērķus un datubāzes mērķus jebkādā
kārtībā. Ņemot vērā efektivitāti ir nepieciešams sasniegt pēc iespējas garākas bāzes
konjunkcijas. Tas ir vienmēr iespējas, nepieciešams pārkārtot programmas un datubāzes
mērķus [4].
19
2. LOĢISKĀ PROGRAMMĒŠANA
2.1. Attieksmju loģika
Loģiskā programmēšana ir balstīta uz attiecības loģikas pamatiem, uz pirmās kārtas
loģikas, predikātu izskaitļošanas pamatiem. Lai ilustrētu loģiskās programmēšanas būtību un
darbības principus bija uzrakstīta viena loģiska programma, kura apraksta vienas ģimenes
radniecības saites. Pilns loģiskās programmas pirmteksts dots pirmā pielikumā. Visi
aprakstītie piemēri balstās uz šo loģisku programmu.
Attieksmju loģika ir loģikas nodaļa, kura pēta attiecības un to īpašības starp dažādiem
objektiem [21]. Attieksmju loģiku var izmantot kā alternatīvu vaicājumu valodām, kuras
balstās uz relācijas algebras pamatiem. Attiecības loģikai ir arī otrs nosaukums, pirmās kārtas
loģika (First Order Logic).
Attieksmju loģikas alfabēts sastāv no sekojošām daļām.
1) Mainīgie, kurus apzīmē ar lieliem burtiem: X, Y, Z.
2) Konstantes, kuras apzīmē ar maziem burtiem: a, b, c.
3) Funkcionālie simboli, kurus apzīmē ar maziem burtiem: funkcija.
4) Predikātu simboli, kurus apzīmē ar maziem burtiem: predikāts.
5) Priekš definētas konstantes, kuras apzīmē ar patiesību vai aplamu: PATIESĪBA (True)
un APLAMS (False).
6) Loģiskas operācijas: negācija; konjunkcija; disfunkcija; implikācija.
7) Kvantori: universālkvantors; eksistences kvantors.
8) Palīgsimboli: iekavas (‘), (’); komats(,).
Lai varētu definēt kādas izteiksmes, tiek definēti vārdi, visām mainīgām, konstantēm,
funkcijām un predikātiem. Ar konstantēm parasti apzīmē konkrētus objektus. Īpašības definē
ar funkcionāliem simboliem, un attieksmes definē ar predikātu simboliem, kuras izteiktas
sasaistēs starp objektiem. Katru funkcionālo un predikātu simbolu apraksta ar to apjomu
(arity). Tādēļ vienkāršas konstantes var uzskatīt, kā funkcionālos simbolus, kurām apjoms ir
vienāds ar nulli.
Terms (Term) ir katra konstante, katrs mainīgais, katrs funkcionālais simbols un katrs
izteiciens no konstantēm, mainīgiem un funkcionāliem simboliem [15]. Pēc savas būtības visi
20
predikātu izskaitļošanas objekti ir termi. Un ja terms nesatur sevī mainīgos, tad to sauc par
konstantes termu.
Elementāra predikātu izskaitļošanas izteiksme ir vecāks(‘Jānis’, ‘Kārlis’), kur
vecāks ir predikātu konstante ar apjomu 2, un ‘Jānis’, ‘Kārlis’ ir termi. Tāda
izteiksme saucās par atomu.
Atomu sintakse atgādina funkcijas izsaukumu tradicionālā programmēšanas valodā. Atoms
vecāks(‘Jānis’, ‘Kārlis’) saņem vērtību PATIESĪBA, ja pāris ‘Jānis’,
‘Kārlis’ pieder pie attiecības vecāks. Šo izteiksmi var saprast āri kā ‘Jānis’ ir Kārļa
tēvs. Un pēc būtības predikāts ir funkcija, kurā atgriež vērtības PATIESĪBA vai APLAMS.
Kā piemēru var minēt īpašu teikumu, vīrietis(‘Jānis’). Predikātu apjoms ir vienāds
ar vieninieku. Šo teikumu var saprast tā, ka elementam ‘Jānis’ ir īpašība vīrietis. vai
tādā veidā, ka ‘Jānis’ ir vīrietis
Sarežģītas izteiksmes, veidojās no elementārām izteiksmēm, pielietojot loģiskas saites:
1) Negācija – loģiska operācija, ar kuru no esoša teikuma tiek iegūts jauns teikums, pie
tam ja esošā teikuma vērtība bija PATIESĪBA, tad jaunā teikuma vērtība ir APLAMS, ja
esošā teikuma vērtība bija APLAMS, jaunā teikuma vērtība ir PATIESĪBA. Negācija
tiek atzīmēta ar simboliem: ~, vai , vai ar vardu NOT [22].
2) Konjunkcija – loģiska operācija, ar kuru divi vai vairāki teikumi tiek apvienoti vienā.
Pie tam iegūtā teikuma vērtība būs vienāda ar PATIESĪBA tikai tad, ja visu apvienoto
teikumu vērtības ir PATIESĪBA. Konjunkcija tiek apzīmēta ar simboliem: &, vai , vai
ar vardu UN [20].
3) Disjunkcija – loģiska operācija, ar kuru divi vai vairāki teikumi tiek apvienoti vienā.
Pie tam iegūtā teikuma vērtība būs vienāda ar PATIESĪBA tikai tad, ja kaut vienam no
apvienotiem teikumiem vērtība ir PATIESĪBA. Disjunkcija tiek apzīmēta ar
simboliem: ||, vai , vai ar vārdu VAI [18].
4) Implikācija – loģiska operācija, ar kuru divi teikumi tiek apvienoti vienā. Implikācijas
būtību var aprakstīt ar konstrukciju JA-TAD. Implikācijas būtība ir nodefinēt jauno
teikumu, caur jau zināmo teikumu. Implikācija tiek apzīmēta ar simboliem: :-, vai ,
vai ar konstrukciju JA-TAD [19].
Aprakstītās attieksmju loģikas konstrukcijas ļauj darīt tikai konkrētus apgalvojumus par
kādiem elementiem. Lai dabūtu labāko efektivitāti izteiksmēs pielietoti mainīgie, kurus var
lietot konstantes vietā, un tādā veidā pārveidot izteiksmes par formulām. Tāda formula vairs
21
neizsāka konkrēto domu, un viņu arī var pārveidot par teikumu, lietojot kvantorus.
Tradicionāli predikātu izskaitļošanā tiek pielietoti divi kvantori:
1) Universāls kvantors nosaka to, ka visiem elementiem piemīt noteikta īpašība.
Universāls kvantors tiek atzīmēts ar simbolu: [21].
2) Eksistences kvantors nosaka to, ka kaut vienam elementam piemīt noteikta īpašība.
Eksistences kvantors tiek atzīmēts ar simbolu: [21].
Tagad ir iespēja aprakstīt sakarus starp predikātiem (predicate). Kā piemēru var apskatīt
tādu izteicienu, ka katrs cilvēks ir dzimis. Attieksmju loģikā šo izteikumu var uzrakstīt tādā
veidā, kā parādīts formulā 2.1.
X: cilvēks(X) => dzimis(X), (2.1)
kur X: cilvēks(X) – katrs objekts X;
cilvēks(X) – objektam X piemīt īpašība cilvēks;
dzimis(X) – objektam X piemīt īpašība dzimis.
2.2. Loģiskā programmēšana
Pēc attieksmju loģikas izskatīšanas var pāriet pie loģiskas programmēšanas. Ar loģisko
programmēšanu var izvadīt jaunus datus no jau esošiem, izmantojot loģiskos likumus un
rekursiju.
Literālis (literal) ir pozitīvs funkcionāls atoms vai negatīvs funkcionāls atoms. Atbilstoši
pozitīvs literālis un negatīvs literālis [15]. Horna izteiksme (Horn clause) ir literāļu disjunkcija
kur kaut viens literālis ir pozitīvs.
Horna izteiksmei ir sekojoša forma, ka paradīta formulā 2.2.
predikāts(terms) :- predikāts1(terms1), …, predikātsn(termsn), (2.2)
kur katrs predikātsi ir predikāts;
katrs termsi ir termu saraksts.
Horna izteiksmes parasti sauc par likumiem. Daļa pirms simbola “:-” tiek saukta par
Horna izteiksmes galvu, vai vienkārši likuma galvu. Daļa pēc simbola “:-” tiek saukta par
Horna izteiksmes ķermeņi, vai vienkārši likuma ķermeni. Simbols “:-” nozīmē to, ka
predikāts predikāts patiess ir tikai tad, ja likuma ķermenis ir patiess. Komatu, līkuma
22
ķermeni var uzskatīt par loģisko operatoru UN. Katrs mainīgais, kurš parādās likuma galvā, arī
parādās likuma ķermenī.
Visus likumus var sadalīt uz trim daļām:
1) Likums ar tukšu ķermeni ir fakts. Faktam nav neviena mainīgā Kā piemērs:
vīrietis(‘Jānis’).
2) Likums ar galvu un ķermeni, ir likums. Kā piemērs: pēctecis(A, B) :- vecāks(A, B).
3) Likums ar tukšu galvu ir mērķis. Katrs mērķis ir vaicājums. Kā piemērs: ? pēctecis(‘Māris’, A).
Predikāts ir likumu kopa ar kopēju predikāta simbolu un saistības simbolu.
Predikāts ir definēts faktu datu bāzes daļā ja tā definīcija sastāv tikai no faktiem. Kā
piemērs, ir predikāts vīrietis.
vīrietis(‘Māris’).vīrietis(‘Ivars’).vīrietis(‘Pēteris’).
Predikāts ir definēts zināšanu datu bāzes daļā ja tā definīcija sastāv no likumiem. Kā
piemērs, ir predikāts māte.
māte(A, B) :- vecāks(A, B), sieviete(A).
Likums ir rekursīvs ja tas savā ķermenī satur tādu pašu predikāta simbolu kā likuma galvā.
Predikāts ir rekursīvs, ja tas sastāv no rekursīviem likumiem. Rekursīvs predikāts ir predikāts
pēctecis.
pēctecis(A, B) :- vecāks(A, B).
pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B). Divi predikāti ir
savstarpēji rekursīvi ja pirmais predikāts savā likuma ķermenī satur otro predikātu un otrs
predikāts satur pirmo predikātu savā likuma ķermenī.
Izvades procesu var saprast šādā veidā, kā parādīts attēlā 2.1. Programma ir likumu kopa.
Datu bāze ir faktu kopa. Loģiskā programma ir likumu un faktu kopas apvienojums. Atbildi
uz vaicājumu var definēt sekojoši: ja ir dota programma, vaicājums un datu bāze, tad atbilde
uz vaicājumu ir pāra programma, vaicājuma uzlikšana uz datu bāzi.
23
2.5. Att.: Izvades procesa būtība
Funkcionāla procedūra darbojas kā matemātiska funkcija: saņem argumentu vai argumentu
sarakstu un atgriež stingri vienīgo rezultātu, priekš šā argumenta. Loģiska procedūra atbilst
matemātiskajam jēdzienam, attieksmei un tāpēc viņai ir lielāks elastīgums. Loģiska procedūra
var atgriezt jebkuru atbilžu daudzumu: nulli, kad nav atbildes, vienu rezultātu vai vairāk. Šis
elastīgums padara loģisko programmēšanu labi piemērotu priekš dažu uzdevumu klasēm,
piemēram priekš lielo datu apjomu apstrādi datu bāzēs.
Attieksmes definīcija neko nesaka par to, kādi ir sākuma argumenti, un kādi ir rezultāti, jo
dažādos vaicājumos vieni un tie paši argumenti var spēlēt dažādas lomas.
Lai parādītu loģiskās programmēšanas jaudu un elastīgumu veiksim loģiskās programmas
Ģimene analīzi [14]. Pilns loģiskās programmas teksts ir dots pirmā pielikumā.
Loģiskā programmā ir definēti daži fakti, kuri sadalās pa sešiem apgabaliem. Pirmā
attiecība vecāks(A, B) nosaka katram elementam A pēcteci B. Šo attieksmi var izmantot
priekš dažiem mērķiem. Pārbaudīt konkrēto apgalvojumu vai ‘Kārlis’ ir pēctecis Jānim:
vecāks(‘Jānis’, ‘Kārlis’). Atrast visus pēctečus Jānim: vecāks(‘Jānis’, A).
Vai atrast Kārļa priekštečus: vecāks(A, ‘Kārlis’). Un āri var atrast visu pāru
priekštečus–pēctečus: vecāks(A, B).
Otrā un trešā attiecība nosaka dzimumu cilvēkiem. Kā piemērus var apskatīt vīriešu:
vīrietis(‘Jānis’), un sieviešu: sieviete(‘Marta’). Programmā ir definēti arī citi
fakti, piemēram: karalis(‘Kārlis’). Un cilvēku īpašības, spoks(‘Kārlis’) un devīgs(‘Pēteris’).
Izejot no šīs faktu bāzes, pielietojot loģisko programmēšanu viegli atrast pēcteča pēctečus.
Likumi kuri atrod šos datus var aprakstīt, izmantojot rekursiju. Pirmais likums atrod visiem
elementiem A pēctečus B. Otrs likums atrod pēcteču pēctečus, tā, kā katram elementam A ir
pēctecis Z, un katram elementam Z ir pēctecis B, tādēļ elementa A pēcteča pēctecis būs
elements B. Likuma loģiskā programmēšana izskatīsies šādā veidā:
24
pēctecis(A, B) :- vecāks(A, B).pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B).
Ja ir nepieciešamība atrast kāda elementa bērnus, tad to var izdarīt sekojoša veidā. Ja
katram elementam A ir savs pēctecis B, tad šis elements B ir bērns elementam A. Loģiskās
programmēšanas likums būs aprakstīts šādā veidā:bērns(A, B) :- vecāks(B, A).
Nedaudz sarežģītāks piemērs, atrast mātes A visus bērnus. To var atrast sekojošā veidā,
katram elementam A ir savs pēctecis B, un ja elements A ir sieviete, tad viņa ir elementa B
māte. Loģiskās programmēšanas likums būs aprakstīts šādā veidā:māte(A, B) :- vecāks(A, B), sieviete(A).
Atrast tēvu var ar tādu pašu paņēmienu, un līkums būs šāds:tēvs(A, B) :- vecāks(A, B), vīrietis(A).
Daudz interesanti atrast ļauno karali. Ja elements A ir karalis, un viņš ir spoks, tad viņš
ir ļauns:ļauns(A) :- karalis(A), spoks(A).
Pieņemsim, ka mēs gribam apskatīt tādu pašu faktu datu bāzi funkcionālā valodā. Dabiski
definēt vecāks funkciju sekojoši:
vecāks(‘Jānis’) -> ‘Kārlis’.vecāks(‘Jānis’) -> ‘Māris’.
Ar šo funkciju viegli atrisināt pirmos divus uzdevumus: vecāks(‘Jānis’) =
‘Kārlis’ un X = vecāks(‘Jānis’). Bet lai atrisinātu atlikušos divus palikušos
uzdevumus, priekšteču atrašana, un visu pāru priekštecis – pēctecis noteikšanā ir vajadzīgi
palīglīdzekļi. Vēl viena problēma ir vecāks funkcijas izsaukums, kurai nav definēts rezultāts.
Kā piemērs: vecāks(‘Ivars’). Parasti tādos gadījumos atgriež speciālo vērtību, paziņojot
par to, ka arguments atrodas ārpus funkcijas definējumā.
Attieksmju izmantošanā aprakstītās problēmas nav, jo attiecība var izpildīties vai arī nevar
izpildīties. Viena no atšķirībām, starp loģiskās programmēšanas modeli un funkcionālās
programmēšanas modeli ir nedetermenisms, kurš ļauj apiet minētās problēmas.
Atrisinot uzdevumu, loģiskā programma darbojas pēc sekojoša principa: “izveidot un
pārbaudīt” atrast(X) :- izveidot(X), pārbaudīt(X).
Šī metode ir vispārīgs paņēmiens, kuru izmanto projektējot algoritmus un programmas.
25
Predikāts izveidot veido rezultātu daudzumu, kurš satur sevī atrisinājumu vai
atrisinājumus. Predikāts pārbaudīt pārbauda, vai piedāvātais atrisinājums atbilst uzdevumu
mērķim.
Predikāts izveidot ļoti bieži izmanto datu bāzes vaicājumus. Dažreiz viens un tas pats
predikāts var strādāt kā ģenerators un pārbaudītājs.
Loģisko programmu elastīgumam ir arī otra puse. Viņa var ļoti viegli kļūt par neefektīvu
programmu. Var izdalīt divus neefektivitātes avotus: pārpalikušais nedetermenisms un
ļaunprātīgas pārņemšanas izmantošana.
Daudzus uzdevumus var atrisināt, izmantojot pārņemšanas metodi. Parasti tādas
programmas, kuras izmanto metodi “izveidot un pārbaudīt”, izveidot vieglāk, nekā
programmas, kuras meklē tiešo atrisinājumu. Tā, kā uzdevumu risināšanai nav nepieciešams
algoritms, tad programmu var uzrakstīt ļoti ātri. Tālāk, ja datu apjoms nav liels vai
meklēšanas apgabals ir mazs, tad arī neefektīvs atrisinājums var būt piemērots. Pie tam,
eksperimenti uz nelieliem piemēriem palīdz dziļāk saprast problēmu un izveidot efektīvāku
algoritmu.
Lai uzlabotu algoritma efektivitāti, ir standarta paņēmiens. Izveidot tādu algoritmu, kura
pārbaude notiek ļoti dziļi izveidošanas procesā. Ideālā gadījumā optimizācijas rezultātā
izveidošanas process izveido tikai pareizus risinājumus.
Pirms loģiskās programmēšanas valodas apskates ir vērts dot datubāzes un loģiskās
programmēšanas iezīmes:
1) Datu bāzes. Loģiskās programmēšanas sistēmas vada nelielas vienam lietotājam
paredzētas, datu bāzes, kas glabājas datora operatīvajā atmiņā un satur gan
uzdevumiem nepieciešamos likumus gan pašu faktisko informāciju. Datu bāzu
sistēmas, turpretī, vada lielus koplietojamus datu apjomus kas atrodas ļoti lielos
atmiņas apgabalos un nodrošina tehnoloģijas, kas nepieciešamas efektīvai meklēšanai
un datu ilglaicīgai uzturēšanai, mainīšanai.
2) Vaicājumi. Loģiskajā programmēšanā vaicājums tiek sasniegts izmantojot loģisko
secinājumu ķēdes, kas izmanto likumus un faktisko informāciju lai pierādītu
apgalvojuma patiesību vai nepatiesību. Datu bāzu sistēmās vaicājums tiek apstrādāts,
lai spētu izgūt no lielā glabājamo datu apjoma piemērotāko informāciju.
3) Ierobežojumi. Loģiskajā programmēšanā ierobežojumi tiek panākti un kontrolēti
izmantojot universālus likumus kas tiek aktivizēti veicot kādas izmaiņas datubāzē.
Datubāzu sistēmās tikai neliela daļa no datiem tiek pakļauti ierobežojumu analīzei.
26
Lai arī datubāzes likumu un programmas likumu struktūra ir vienāda, tiek izšķirtas
vairākas atšķirības starp deduktīvajām datubāzu sistēmām un loģiskās programmēšanas
sistēmām.
Relāciju datu bāžu jēdzienu un to analoģiskie jēdzieni loģiskajā programmēšanā parāda cik
ir tuvu relāciju modelis loģiskai programmēšanai. Jēdzieni ir aprakstīti 2.1. tabulā.
2.1. Tabula
Datu bāzu un loģiskās programmēšanas jēdzieni
Datu bāžu jēdzieni Loģiskas programmēšanas jēdzieni
Attiecība Predikāts
Atribūts Predikāta arguments, Terms
Kortežs Fakts
Attēlojums Likums
Vaicājums Mērķis
Ierobežojums Mērķis, Loģiskais izteiciens
2.3. Prolog valoda
Prolog ir programmēšanas valoda, kas balstās uz Horna teikumiem. Prolog valoda ir čaula
kas nodrošina sadarbību starp lietotāju un zināšanu bāzi, kas glabā aprakstītās zināšanas.
Parasti zināšanas tiek strukturētas faktu veidā. Katrs likums apraksta nelielu, relatīvi
neatkarīgu zināšanu fragmentu. Jaunu likumu pievienošana notiek relatīvi neatkarīgi no citiem
likumiem. Zināšanu bāze ir viegli modificējama [11].
Valodā Prolog tiek atsevišķi izšķirta deklaratīvā un procedurālā jēga. Deklaratīva jēga
nosaka to, kas būs par programmas rezultātu. Procedurāla jēga nosaka to, kā šis rezultāts bija
iegūts.
Prolog programmas ir faktu deklarācija plus likumi, lai veiktu deduktīvus secinājumus.
Programmas izpilde iekļauj atbildi uz jautājumiem, kas atsaucās uz faktiem vai bija izvadīti
no tiem. Lietotājs dod aksiomas un Prolog mēģina pierādīt izvirzītās teorēmas.
Prolog veic datubāzes pārmeklēšanu izmantojot dziļuma meklēšanas algoritmu, cenšoties
pierādīt šo vaicājumu un izvada atbildi uz vaicājumu. Vaicājumi sistēmā sastāv no viena vai
27
vairākiem mērķiem. Vārds mērķis tiek izmantots tāpēc, ka Prolog sistēma uztver vaicājumus
kā mērķus kurus nepieciešams sasniegt.
Atbilde uz vaicājumu var būt vai nu pozitīva vai negatīva, atkarībā no tā vai izvirzītais
mērķis var tikt sasniegts vai nē. Pozitīvas atbildes gadījumā uzskata ka attiecīgais mērķis var
tikt sasniegts un ka tas ir sasniedzams. Pretējā gadījumā mērķis nav sasniedzams. Ja
jautājumam ir vairākas atbilstošās atbildes, Prolog parāda tik daudz atbildes cik prasa
lietotājs.
Prolog valodā ir realizētas valodas konstrukcijas, kurām nav saistības ar loģiskām
operācijām, bet kas padara to par vispārēji lietojamu programmēšanas valodu. Tiek ievadīti
papildus loģiskie predikāti kas domāti darbam ar zināšanu bāzi. Meta līmeņa predikāti –
parāda pierādījuma stāvokli, darbojas ar mainīgajiem kā ar valodas objektiem un ļauj
pārveidot datu struktūras par mērķiem. Ir ievadīti salīdzinājuma termi. Eksistē kontroles
predikāti, kuri ietekmē programmas procedūralo uzvedību. Specials predikāts, Atciršana (!),
apstādina tekošā teikuma izpildi.
Valoda Prolog var strādāt kā spēcīga valoda darbam ar datu bāzēm, taču tam ir virkne
nepilnību [13].
1) Apstrāde pa kortežiem. Tika sagaidīts, ka vaicājuma rezultātā no datubāzes tiks
atgriezta kortežu kopa, taču Prolog atgriež atsevišķus kortežus pa vienam.
2) Vaicājumu apstrāde atkarīga no likumu un faktu kārtības datubāzē un no predikātu
kārtības likuma ķermenī. Rakstot programmas Prolog šī īpašība bieži tiek izmantota,
lai veidotu efektīvākas programmas, tādējādi upurējot loģiskās programmēšanas
deklaratīvās iespējas par labu procedurālajām.
3) Prolog programma tiek vadīta izmantojot speciālos predikātus (piemēram ievades/
izvades organizēšanā, programmu noslīpēšanā vai rekursijas vadīšanā). Šeit slēpjas
nākamais svarīgais iemesls, kāpēc tiek pazaudētas valodas deklaratīvās spējas.
4) Prolog lieto funkcionālos simbolus lai lietotu rekursīvo funkciju definēšanā un
sarežģītu datu struktūru aprakstīšanā. Šīs funkcijas nav nepieciešamas darbā ar
parastajām viendimensiju relāciju datubāzēm.
28
2.4. Datalog valoda
Loģiska programmēšana nosaka daudz ieskatāmu vaicājumu veidošanu, un ierobežojumu
ieviešanu, salīdzinot ar populāriem datu bāžu vaicājumu valodām, piemēram kā SQL valoda.
Šīs loģiskās programmēšanas sistēmas nesatur sevī tehnoloģijas, kuras ļauj apstrādāt lielus
datu apjomus, neļauj glabāt lielas datu bāzes, nevar vadīt daudzu lietotāju kopējo darbību ar
datiem. Un kā izeja no minētām problēmām ir sistēma, kura balstās uz abiem paņēmieniem.
Viena no populārām loģiskās programmēšanas valodām, kura ir tuvu vaicājumu valodām
datu bāžu tehnoloģijās var uzskatīt Datalog valodu. Nosaukumu Datalog var sadalīt uz divām
daļām, Data un Logic, darbs ar datiem izmantojot matemātisko loģiku. Datalog valodu, var
uzskatīt kā alternatīvo datu bāzēs vaicājumu valodu [9]. Datalog valodu pasniedz kā
fundamentālo vaicājumu valodu, kurš piemērots apmācībai par vaicājumu optimālo
izpildīšanu. Datalog valoda ir ļoti tuva attieksmju loģikai, ar dažām sīkām izmaiņām, lai
atbalstītu ērtāko darbu ar datiem.
Datalog valodā tiek iebūvēta plašuma meklēšanas stratēģija, vaicājumu izpildei. Un
vaicājumu rezultāts ir kortežu kopa, un Datalog valoda, kā ari SQL valoda, spēj to nodrošināt,
jo Datalog valoda atgriež kortežus, kā kortežu kopu.
Datalog valodā nav jūtīguma priekš likumu kārtības. Un, kā zināms, datu bāžu valodās,
tādi kā SQL vai relāciju algebra, nav atkarīgi gan no meklēšanas predikātu kartības, gan datu
bāžu kortežu kārtības.
Datalog valodā nav iebūvēti ne speciālie predikāti, ne funkcionālie simboli, un Datalog
valoda apstrādā daudz kortežu vienā laikā.
Tajā pašā laikā, tādas īpašības ierobežo Datalog valodas jaudu, kā universālas
programmēšanas valodu. Tādēļ Datalog valoda izskatās kā laba abstrakcija, kura ilustrē
loģiskās programmēšanas valodas izmantošanu, kā datu bāžu valodu.
Datalog ir viena no parastajām loģiskās programmēšanas valodām. Un tā, kā Datalog
valoda atrodas ļoti tuvu relāciju modelim, no Datalog valodas izmantošanas, datu bāžu
valodas lomā ir daži labumi, kuri saistīti ar Datalog valodas īpašībām, īpaši ar rekursijas
iespējām.
29
2.5. Prolog un Datalog valodu salīdzinājums
Salīdzinot Prolog un Datalog valodas ir vērts pieminēt svarīgas izveduma īpašības, jo
sintaktiski Prolog un Datalog valodas atrodas ļoti tuvu viena otrai. Galvenās atšķirības atrodas
valodu iekšienē.
Kā alternatīvu valodai Prolog darbam ar relāciju datubāzēm var izmantot valodu Datalog,
kas veidota, lai novērstu aprakstītos Prolog trūkumus, tādējādi tā ir neprocedurāla, nejūtīga
pret kārtību un bez speciāliem predikātiem un funkcionālajiem simboliem. Datalog sintakse
līdzīga Prolog sintaksei. To izpildes rezultātā tiek atgrieztas kortežu kopas. Prolog valoda
atgriež kortežu pēc korteža, pa vienam, kas ir labi priekš programmēšanas, mākslīgo intelektu
izstrādei, bet datu bāžu gadījumā vajag saņemt kortežu kopu, kā to dara SQL valoda.
Datalog ir nejūtīgs pret likumu kārtību un predikātu kartību likumos. To pierāda piemērs:
Loģiskā programma 1:pēctecis(A, B) :- vecāks(A, B).pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B).
Loģiskā programma 2:pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B).pēctecis(A, B) :- vecāks(A, B).
Ieejas mērķis:? - pēctecis(A, B).
Abas no ilustrētajām programmām ir sintaktiski pareizas gan Prolog gan Datalog. Tā kā
Datalog ir nejūtīgs pret likumu un predikātu kārtību tas atgriezīs pareizo atbildi abos
variantos. Pretēji tam Prolog interpretators izvadīs sagaidāmos rezultātus tikai pirmajā
gadījumā, otrajā gadījumā izpildot vaicājumu iestāsies bezgalīgais cikls rekursijas dēļ. Tas ir
vēl viens no Prolog valodas trūkumiem – programmējot jādomā vai nepastāv iespēja
izveidoties bezgalīgiem cikliem.
No shēmas redzams, ka evolūcija no Prolog uz Datalog ir evolūcija no procedūrientētas
valodas uz neprocedurālu, kas balstīta uz kopu apstrādi. Šis process raksturīgs datubāzu
evolūcijā no hierarhiskām un tīkla veida datubāzēm uz relāciju datubāzēm un tālāk uz
relāciju-objektu un objektu. Kaut gan Datalog ir deklaratīva valoda un tās definīcija nav
atkarīga no izvēlētās pārmeklēšanas stratēģijas, Datalog mērķus parasti izskaitļo izmantojot
pārmeklēšanu plašumā, kas rada atbilžu kopu un nevis izmantojot Prolog pārmeklēšanu
30
dziļumā, kas rada atbildes izmantojot kortežus. Tas sasaucas ar vaicājumu valodu pamatpieeju
relāciju datubāzēm.
Datalog valodā nav definētu speciālo predikātu un nav funkcionālo simbolu. Prolog valodā
ir gan speciālie predikāti, gan funkcionālie simboli.
Vēl vairāk programmējot Datalog, programmētājs nav aizņemts ar datu piekļuves
procedūru veidošanu, tā ir sistēmas funkcija. Taču šīs īpatnības ierobežo Datalog, kā
programmēšanas valodas iespējas.
Izejot no minētā salīdzinājuma, tabula 2.2, var nākt pie secinājuma, ka Datalog valoda ir
piemērota tieši kā alternatīva datu bāzes vaicājumu valoda.
2.2. Tabula
Prolog un Datalog valodu salīdzinājums
Prolog valoda Datalog valoda
Pārmeklēšana dziļumā Pārmeklēšana plašumā
Apstrāde pa vienam kortežam Kopas apstrāde
Jūtība pēc likumu sakārtojuma Nav jūtības pēc likumu sakārtojuma
Definēti speciālie predikāti Nav speciālo predikātu
Definēti funkcionālie simboli Nav funkcionālo simbolu
2.6. Datalog valodas sintakse
Lielākais sintaktiskais un semantiskais Datalog valodas modulis ir programma.
Programmas teksts ir simbolu sakārtota secība, kuri tiek noformēti kā viens modulis. Teksta
elementi ir norobežotāji, rezervētie vardi un nerezervētie vārdi [8].
Norobežotāji ir tukšumzīme, tabulācijas zīme, jaunas rindas zīme, `’`, `(`, `)`, komats,
punkts un `:-`. Vardi ir simbolu secība, kuras tiek atdalītas ar norobežotājiem. Rezervētie
vārdi ir iepriekš definētas simbolu secības kuras nozīmē specifiskus valodu operatorus.
Nerezervētie vārdi ir simbolu secības, zīmes, un citi simboli, kuras tiek izmantotas lietotāju
vārdu un konstantu definēšanai. Ierobežojums uz vārdu garumu tiek noteikts ar Datalog
valodas konkrēto realizāciju.
31
Predikāts ir funkcija no viena vai vairākiem argumentiem, kura pieņem vērtību “patiesība”
vai “aplams” atkarībā, no savu argumentu vērtībām. Katrs terms, predikāta arguments ir
predikāta sfēras īpašums. Predikāta apjoms ir predikāta argumentu saraksts.
Mainīgais ir nosauktais predikāta arguments. Pieļauti anonīmie mainīgie. Anonīmā
mainīgā vārds ir simbols: “_”. Katrs anonīmais mainīgais ir unikāls. Terms bija mainīgais vai
konstante. Un šis terms tiek nosaukts, kā vienkāršs terms. Salikts terms ir terms, kurš ir
izteiksme no vienkāršu termu vai no saliktām termām. Tikai vienkāršie termi pieļauti
standartā Datalog valodā.
Atoms ir jebkura predikātu izmantošana loģiskā programmā. Atoms sastāv no predikātu
vārda un iekavās ierakstīto ar komatu sadalīto termu saraksta. Atomi ar tādu pašu vārdu atbilst
vienam un tādam pašam predikātam. Atoms nosaukts par pamata atomu, ja viņš satur tikai
konstantes. Katram atomam, jābūt piemērotam ar predikātu. Piemērotība ar predikātu nozīmē
sekojošo: predikātu apjomam un atomu apjomam jābūt vienādiem, ja atomu vārds ir tāds pats
kā predikātu vārds.
Literālis ir kāds atoms. Atoms nosaukts par pozitīvo literāļu. Atbilstoši negatīvs atoms ir
negatīvs liberāls. Fakts ir pozitīvs literālis. Pamats fakts nesatur sevi mainīgos.
Mērķis ir negatīvo literāļu kopa. Mērķis nosaukts par vienkāršo, ja viņš sastāv no viena
literāļa.
Likuma galva ir likuma pozitīvs literālis. Likuma ķermenis ir negatīvo literāļu kopa. Visus
mainīgos, kuri uzrakstīti likuma galvā, arī jāizmanto likuma ķermenī, kā predikātu
argumentus.
Lietotāju vārds ir nerezervēts vārds, kurš sākas no burta. Šos vārdus pielieto, lai
identificētu tādus nozīmīgas valodas vienības kā predikāts un arguments. Konstantes ir
nemainīgas vērtības kuras Datalog valodā prezentē kā simbolu secību, kuras sākas no mazā
burta un satur gan burtus, gan ciparus, vai simbolu secību, kuras sastāv no cipariem.
Piemēram: abc, ab23, 34 – konstantes.
Standarta Datalog sintaksē funkcionālo termu izmantošana ir aizslēgta. Likuma ķermenis
nevar saturēt negatīvo literāļu. Tas nozīme sekojošo – likums var saturēt tikai vienu pozitīvo
literāļu, kurš ir saistīts ar likuma galvu. Nav iebūvēts atkāpšanās mehānisms. Visi predikāti
tiek aprakstīti pašā programmā
Datalog likumam ir sekojoša sintakse:likums ::= galva :- ķermenis.galva ::= predikāts
32
ķermenis ::= predikāts [, ķermenis]predikāts ::= PREDIKĀTA_VĀRDS (argumentu_saraksts)argumentu_saraksts ::= arguments [, argumentu_saraksts]arguments ::= KONSTANTE | MAINĪGAIS | SKAITLISPREDIKĀTA_VĀRDS ::= [‘a’..’z’]MAINĪGAIS ::= [‘A’..’Z’] | _KONSTANTE ::= ‘ [‘a’..’z’] | [‘A’..’Z’] ’SKAITLIS ::= [‘0’..’9’]
Datalog faktam ir sekojoša sintakse:fakts ::= PREDIKĀTA_VĀRDS (termu_saraksts).termu_saraksts ::= TERMS [,termu_saraksts]TERMS ::= KONSTANTE | SKAITLIS
Datalog mērķim ir sekojoša sintākse:goal ::= ? PREDIKĀTA_VĀRDS (argumentu_saraksts).
Katrs programmas elements beidzas ar punktu. Piemērs, kurš iekļauts darbā pirmā
pielikumā ļoti labi ilustrē loģiskās programmas sintaksi un koncepcijas, kuras jau bija
aprakstītas. Līdzīgi kā loģiskajās programmās vaicājums Datalog ir reprezentēts kā mērķis.
Programma satur sevī divpadsmit predikātus: faktu datu bāzes predikāti ir vīrietis,
sieviete, vecāks, karalis, spoks, devīgs likumu datu bāzes predikāti ir pēctecis, bērns, māte, tēvs, labsirdīgs, ļauns.
6 fakti veido predikātu vīrietis.
3 fakti veido predikātu sieviete.
8 fakti veido predikātu vecāks.
2 fakti veido predikātu karalis.
1 fakts veido predikātu spoks.
2 fakti veido predikātu devīgs.
Predikāts pēctecis ir aprakstīts ar diviem likumiem.
Predikāts bērns ir aprakstīts ar vienu likumu.
Predikāts māte ir aprakstīts ar vienu likumu.
Predikāts tēvs ir aprakstīts ar vienu likumu.
Predikāts labsirdīgs ir aprakstīts ar vienu likumu.
Predikāts ļauns ir aprakstīts ar vienu likumu.
Piemērs satur sevī vienkāršu mērķi: ? pēctecis(‘Māris’, A).
33
Programma satur daudz konstantes, vārdi, pilsētas, datumi.
Mērķis satur gan konstantes, gan mainīgos.
Likumos tiek izmantoti tikai mainīgie.
Likums bērns(A, B) :- vecāks(B, A), nozīmē to, ka visiem A un B, A ir bērns
B, ja B ir vecāks A.
Likums māte(A, B) :- vecāks(A, B), sieviete(A), nozīmē to, ka visiem A un
B, A ir māte B, ja A ir vecāks B un A ir sieviete.
Tādai likuma definīcijai ir divas nopietnas īpašības:
1) Tai nav sakara ar konkrēto priekšmetisko jomu. Īpašība saka, ka predikātu rēķini tiek
izmantoti uzdevumu formalizēšanai
2) Tā ir piemērota visām priekšmetiskās jomas objektiem. Īpašība saka, ka visi mainīgie
ierobežoti ar universālkvanoriem.
Piemēram likumu māte(A, B) :- vecāks(A, B), sieviete(A) var pierakstīt
pirmās kārtas loģikas robežās sekojoši, kā paradīts formulā 2.3.
AB : (māte(A, B) (vecāks(A, B)) (sieviete(A))), (2.3)
kur AB - katram objektam A un B piemīt sekojošas īpašības;
māte(A, B) – objekti A un B atrodas attieksmē māte;
vecāks(A, B) – objekti A un B atrodas attieksmē vecāks;
sieviete(A) – objektam A piemīt īpašība sieviete.
2.7. Drošas Datalog programmas
Tikai drošas Datalog programmas iespējams pārveidot uz ekvivalentām relācijas algebras
operācijām. Drošībai, galvenokārt ir sintaktiska nozīme, bet tā arī ļauj izpildīt Datalog
programmas ar lielāku ātrumu un efektivitāti. Drošību Datalog programmā var nodrošināt
sekojoši [8]:
Droši predikāti. Predikāts programmā ir drošs, ja šis predikāts ir datu bāzes predikāts. Un
katrs likums, kurš definē šo predikātu ir drošs.
Droši mainīgie. Mainīgais kādā likumā ir drošs, ja
1) Šis mainīgais tiek izmantots kāda pozitīva atomā un predikāts, atvasināts no šī atoma
ir drošs.
34
2) Likums satur sevī kādu atomu, kurā šis mainīgais ir saistīts ar konstanti.
3) Likums satur sevī kādu atomu, kurā mainīgais ir saistīts ar drošu mainīgo.
Droši likumi. Likums ir drošs, ja visi likuma mainīgie ir droši.
2.8. Datalog valodas izskaitļošanas semantika
Loģiska programma Datalog valodā, ir vaicājums, kurš operē ar datiem no faktu datu bāzes
daļas, un kurš izskaitļo kādu rezultātu kopu. Loģiskās programmas rezultāts sastāv no
faktiem, kuri ir pēc savas būtības loģisko operāciju projektējums uz datu bāzes faktiem.
Loģiskajā programmēšanā programmas tiek lietotas, lai pierādītu dotās teorēmas patiesumu
vai nepatiesumu. Izpilde sastāv no pierādījuma atrašanās teorēmā izmantojot programmā
definētos likumus, definētos un izvadītos faktus.
DATALOG mērķis ir atrast visus risinājumus, DATALOG semantika sakrīt ar kopu
orientēto vaicājumu nozīmi datubāzēs. Šādu vaicājumu semantikas no apakšas uz augšu
(bottom-up) ir ērtākas par no augšas uz leju (top-down) semantiku. Mērķi loģiskajā
programmēšanā ir kortežu orientēti, tie ir bāzēti uz vienas atbildes sniegšanu no visas atbilžu
kopas. No apakšas uz augšu semantika ir vairāk piemērota datubāzu vaicājumiem, tomēr ir
vairāki trūkumi. Tā neņem vērā konstantes, kas parādās mērķī, tādejādi mērķa novērtēšanas
process var ģenerēt daudz lielāku faktu kopu nekā būtu jāsastāda, atbildot uz vaicājumu. Ir
izstrādātas dažādas optimizācijas tehnikas no apakšas uz augšu semantikai, lielākā to daļa ir
bāzēta uz oriģinālās DATALOG datubāzes pārrakstīšanu jaunā DATALOG datubāzē, kur no
apakšas uz augšu novērtēšana ģenerē daudz mazāk faktu.
Pierādījuma iegūšanas laikā tiek izmantota mainīgo saistīšana, kuras laikā katrs mainīgais
tiek piesaistīts termām. Substitūcija (substitution) ir saistītu mainīgo kopas piesaistīšana termu
kopai. Teikuma substitūcijas izpilde noved pie atsevišķas teikuma instances. Piemērs, kas
apraksta substitūcijas lietošanu, substitūcijas {B / ‘g’} izpilde teikumam
nogrieznis(‘c’, B) tiek rakstīts kā nogrieznis(‘c’, B) {B / ‘g’} un noved pie
nogrieznis(c, g).
Unifikācija (unification algorithm) ir process, kas izmantojot substitūciju padara divas
formulas sintaktiski pilnīgi vienādas. Ja eksistē tāda substitūcija tad eksistē arī vēl vispārīgāka
substitūcija. Piemērs, kas apraksta vispārīgās substitūcijas gadījumu:
35
Šādu divu teikumu nogrieznis (‘c’, B) un nogrieznis (A, ‘g’)vispārīgākā
substitūcija ir {A/c, B/g}.
Valodas interpretācijas noteic sekojošā veidā:
1) Salīdzinot vārdus ar sistēmas objektiem.
2) Salīdzinot vienkāršas konstantes ar elementiem
3) Salīdzinot funkcionālas konstantes ar funkcijām
4) Salīdzinot predikātu konstantes ar attieksmēm.
Tādā veidā, katrs teikums pārveidojas uz izteiksmi attiecībā uz sistēmas objektiem. Un ir
vērts teikt par to patiesību, vai nepatiesību.
Programmas izpilde var būt vai nu no augšas uz leju, vai no lejas uz, vai šo abu
kombinācija. Izpildē no augšas uz leju sākumpunkts ir mērķis, kas ir jāpierāda. Katrā izpildes
solī mērķis tiek aizvietots ar mērķa apakšmērķi, kas var tikt unificēts ar mērķi. Izpildē no lejas
uz augšu sākumpunkts ir faktu kopa. Katrā izpildes solī faktu kopa tiek salīdzināta ar likumu
galvām, kuru ķermeņi ir patiesi. Izpilde beidzas, ja sākotnēji dotais mērķis ir iekļauts
atvasināto faktu kopā.
Mērķis patiesībā var kļūt šaurāks katrā atvasināšanas solī. Ja teikums tiek izvēlēts no
programmas teikumiem, jaunais teikums saturēs vismaz tik pat daudz mērķu kā iepriekšējais
teikums. Ja tiks izvēlēts fakts, jaunais teikums saturēs mazāk mērķu nekā iepriekšējais, tāpēc
ka izvēlētais mērķis tiek dzēsts no teikuma un nav jaunu teikuma ķermeņu ko pievienot. Katrā
atvasināšanas solī tiek izskaitļota mainīgo saistība. Tāpēc jebkurš mainīgais mērķī var saņemt
piesaisti pierādīšanas laikā.
Rezolūciju var attēlot izmantojot rezolūcijas koku. Rezolūcijas koka sakne satur doto
mērķi. Virsotnes attēlo starp rezultātus un loki parāda atvasināšanas soļus. Katrā
atvasināšanas solī tieši viens no iespējamajiem mērķiem, kuru galvas var unificēt ar izvēlēto
mērķi, tiek izvēlēti izmantojot meklēšanas likumu. Katra virsotne rezolūcijas kokā ir nosaukta
par tekošo mērķi. Tiek izcelts izvēlētais mērķis nākamajam solim.
Ļoti vienkāršs piemērs, kas apraksta rezolūcijas koka izpildes gaitu ir attēlots attēlā 2.2.
36
2.6. Att.: Grafiks
Ir dota loģiskā programma, pirmteksts pielikumā divi. Tajā aprakstīti divi likumi, kuri
apraksta visus iespējamos ceļus šajā grafikā.ceļš(A, B) :- nogrieznis(A, B).ceļš(A, B) :- nogrieznis(A, Z), ceļš(Z, B).
Mērķis, ko vajag iegūt ir ? ceļš(A, ‘f’). Rezolūcijas koks, mērķa atrašanai ir parādīts
2.3 attēlā.
2.7. Att.: Rezolūcijas koks
Mērķim ceļš(A, ‘f’) ir divi iespējamie atrisinājumi {A/a}, un {A/b}. Risinājuma
lietošana tādējādi dod divus faktus ceļš(‘a’, ‘f’) un ceļš(‘b’, ‘f’).
37
3. DEDUKTĪVO DATU BĀŽU ARHITEKTŪRA
3.1. Sasaiste un integrācija
Sistēmas, kas lieto loģiku, lai attēlotu zināšanas faktus un likumus parasti orientējas uz
loģiskās programmēšanas tehnoloģijām. Šādas sistēmas ir paredzētas zināšanu attēlošanai un
apstrādei, un tām parasti pietrūkst datubāzu sistēmu pamatīpašības: stabilitātes, sekundārās
atmiņas vadības, paralēlas datu manipulācijas, vaicājumu optimālai izpildei.
Deduktīvo datu bāžu projektēšanai un izstrādei nepieciešams integrēt šīs divas tehnoloģijas
kopā, lai dabūtu optimālo rezultātu, un trūkumus vienā tehnoloģijā, aizvietot ar spēcīgām
pusēm otrā, un otrādi.
Atšķirības starp sasaistīšanu un integrāciju parāda deduktīvo datubāzu vispārīgu aprakstu.
Tās saista datubāzes un loģiskās programmēšanas sistēmas kā vienu veselumu un nav
pietiekami specifiskas, lai satvertu ne sistēmas arhitektūru ne sistēmas valodu.
Loģiskas programmēšanas un datu bāžu tehnoloģiju sasaistē ir trīs iespējami veidi [2]:
1) Vāja saistīšana: loģiskās programmēšanas valoda tiek paplašināta ar speciāliem
predikātiem, kuri atlasa no datubāzes faktus, kas ir nepieciešami loģikas programmai;
2) Cieša saistīšana: datubāzu vadības sistēmā tiek organizēts speciāls līmenis – likumu
interpretators, kas reprezentē attieksmes no datubāzes loģikas predikātu veidā;
3) Integrācija: datubāzu vadības sistēmā tiek iebūvētas valodas likumu rakstīšanai un
izveduma mehānismi.
Sasaistīšana ir interfeisa izstrāde starp loģiskās programmēšanas sistēmu un datubāzu
vadības sistēmu. Abas sistēmas saglabā individualitāti, jo interfeiss starp tām nodrošina datu
apmaiņu starp datu bāzi un loģiskās programmēšanas sistēmu.
Vājas sasaistīšanas gadījumā lietotājam ir pieejamas abas sistēmas. Loģiskās
programmēšanas valodā tiek rakstītas programmas, bet no datubāzes ar speciālu predikātu
palīdzību tiek atlasīti vajadzīgie dati. Iegūtie dati tiek pievienoti loģikas programmas faktiem,
tādējādi programma tiek modificēta katru reizi, kad notiek vēršanās pie datiem datubāzē.
Izņemot jaunas informācijas iegūšanu, loģikas programmu var izmantot arī datubāzes
modificēšanai. Šim nolūkam arī tiek izmantoti speciāli predikāti, kuriem kā argumenti tiek
norādīti programmas mainīgie vai konstantes.
38
Iekļaujot datubāzes piekļūšanas algoritmus programmēšanas valodā ļauj izvēlēties
programmēšanas valodu neatkarīgi no datubāzes valodas. Šī pieeja arī neprasa papildus
valodas kompilatora modifikāciju.
Var tikt definētas divas iekļaušanas formas tipu iekļaušana un valodas iekļaušana.
1) Tipu iekļaušana ir atkarīga no datubāzes shēmas tāpēc, ka tikai konkrētā datubāzes
shēma var tikt attēlota programmēšanas valodas datu struktūrās.
2) Valodas iekļaušana ir neatkarīga no shēmas un pati datubāzes valoda ir attēlota
izmantojot programmēšanas valodas konstrukcijas.
Ar vāji saistītām sistēmām ir zināmas problēmas. Loģiskās programmēšanas valodas
neizmanto tipus, un datubāzes piekļūšanas valoda ir loģiskās programmēšanas valodas
sastāvdaļa. Tipu pārbaude piekļūstot datubāzei tādējādi ne vienmēr ir iespējama. Loģiskajā
programmēšanā nav atšķirības starp programmu un datiem: programmas teikumi ir termi. Tas
atļauj datubāzes pieeju definēt dinamiski pašā programmēšanas valodā. Datubāzes piekļuves
rezultāta statiskā analīze nav pietiekama. Tā vietā ir jāinterpretē datubāzes pieprasījumi un
atgrieztie dati. Vājas sasaistīšanas arhitektūra paradīta attēla 3.1.
3.8. Att.: Vājas sasaistīšanas arhitektūra
Ciešas sasaistīšanas gadījumā lietotājam nav tiešas pieejas pie datu bāzes vadības sistēmas.
Dati no datubāzes tiek attēloti loģikas valodā predikātu formā un tādā veidā tiek piedāvāti
lietotājam. Datu pārveidošanu loģikas valodā veic likumu interpretators, kas ir realizēts kā
DBVS līmenis. Pirms interpretators veic pārveidošanu, tas ar vaicājuma palīdzību atlasa no
datubāzes datus, kas konkrētajā brīdī ir vajadzīgi programmai.
39
Cieši saistītās sistēmās, attēls 3.2, var piekļūt tikai pie iebūvētajam datubāzes
komponentam. Atkarībā no vaicājuma realizācijas tiek izdalīti divi ciešās sasaistīšanas veidi.
Statiski ciešā sasaistīšana risinās izmantojot priekšprocesoru. Lai realizētu šādu
sasaistīšanu, priekšprocesors veic programmas divkāršu novērtēšanu. Pirmā novērtēšana tiek
izdarīta kompilācijas laikā, pieņemot, ka visi datubāzes predikāti ir patiesi. Tas ļauj
priekšprocesoram ģenerēt vaicājumus, kas programmas izpildes laikā ļaus izgūt no datubāzes
nepieciešamos datus. Rindas, kuru sastāvā esošās konstantes neapmierina programmu, nemaz
netiek ievietotas pamatatmiņā. Otra programmas novērtēšana jau notiek programmas izpildes
laikā, kad likumi tiek interpretēti, aizvietojot mainīgos ar datiem no EDB;
Dinamiski cieša sasaistīšana tiek izpildīta atsevišķi katram konkrētam likumam. Šajā
gadījumā novērtēšana tiek veikta tikai vienu reizi. Faktiski, izsaucot katru no datubāzes
predikātiem, tiek iedarbināts vaicājums, kas novērtē predikātu. Tas ļauj glabāt operatīvajā
atmiņā tikai tos faktus no datubāzes, kas ir vajadzīgi konkrētajam likumam.
3.9. Att.: Ciešas sasaistīšanas arhitektūra
Integrēšanas gadījumā izveduma apakšsistēma ir pilnībā integrēta datu bāzes vadības
sistēmā un darbojas datubāzu iekšējos buferos, kā jau eksistējošo izveduma mehānismu
paplašinājums. Integrējot loģiskās programmēšanas valodu ar DBVS, tiek modificēts DBVS
pirmkods. Tajā tiek iekļauts likumu bāzes vadības mehānisms, deduktīvo vaicājumu
interpretators, īpašas kompilēšanas tehnikas un operatori, kas strādā ar rekursīviem likumiem.
Integrācija prasa programmēšanas valodas paplašināšanu iekļaujot tajā arī datubāzes valodas
konstrukcijas, un ietver programmēšanas valodas kompilatora un pašas datubāzes sistēmas
modificēšanu.
Šāda pieeja ļauj izstrādāt integrētās sistēmas, kas piedāvā lietotājam vienādu interfeisu
likumu un vaicājumu veidošanai. Integrētas sistēmas arhitektūra paradīta attēla 3.3.
40
3.10. Att.: Integrētas sistēmas arhitektūra
3.2. Fiziskais līmenis
Fiziskais līmenis ir sistēmas arhitektūra, līmenis nosāka loģiskās programmēšanas valodu,
datu bāzes vadības sistēmu un interfeisu starp šīm abām sistēmām [7].
Fiziskajā līmenī interfeiss starp sistēmu un datubāzi sastāv no pamata komponentiem -
koordinācijas mehānisma, sakaru kanāla un datu pārveidošanas mehānismiem.
Loģiskās daļas izpilde balstās uz kontroles stratēģiju, kura tajā ir iekodēta. Granularitāti
veido kortežu kopa. Izpildes stratēģija, kas balstās uz vienu kortežu tiek lietota tāpēc, ka tikai
viens kortežs no iegūtās kortežu kopas tiek uzskatīts par nākamo mērķi, kas jāatrisina.
Lietojot kopas izpildes stratēģiju par nākamo atrisināmo mērķi tiek ņemta kortežu kopa.
Kontroles stratēģija ir ierobežota ar meklēšanas un izskaitļošanas likumiem. Standarta
kontroles stratēģija paredz teikumu izpildi tā, kā to specificē programmas kods, izvēlēties
pirmo no atrastajiem mērķiem un iet tālāk dziļumā, vai kopas izpildes stratēģijas gadījumā
meklēt plašumā.
Datubāzes vadības sistēma realizē pamata datubāzes funkcijas, lai piekļūtu datubāzei un
iegūtu datus. Lietotāji piekļūst datubāzei izmantojot augsta līmeņa deklaratīvās datubāzes
valodas izmantojot jau iepriekš definētu interfeisu.
Datubāzei var piekļūt no dažādiem līmeņiem. Lietotāji piekļūst datubāzei izmantojot
augsta līmeņa vaicājumu valodas. Atgrieztā granularitāte atkarīga no interfeisa kuru
41
izmantojot piekļūts datubāzei. Lietotāja līmenī tā ir vesela relācija, bet programmēšanas
valodas līmenī tas ir atsevišķs ieraksts.
Efektivitāte apraksta vispārējo sistēmas efektivitāti, kas ir saistīta ar vispārējo datu plūsmas
procesu starp sistēmu un datubāzi. Šī datu caurlaide ir noteikta ar veidu kā dati tiek pārvietoti
starp datubāzi un sistēmu, un nepieciešamo sarežģītību izvēloties izpildes un koordinācijas
stratēģijas.
Fiziski cieši saistītās sistēmās faktiski nav datu pārvietošanas, nav datu pārveidošanas un
nepieciešama tikai neliela uzturēšana. Fiziski vāji saistītās sistēmās, dati ir jānogādā no
datubāzes komponentes sistēmai, un nepieciešama piepūle, lai pārveidotu datu formātus un
koordinētu izpildes stratēģijas.
3.3. Loģiskais līmenis
Deduktīvas datu bāzes loģisko līmeni veido programmatūra. Loģiskajā līmenī interfeiss
starp sistēmu un datubāzi sastāv no datubāzes piekļuves valodas. Loģiskajā līmenī deduktīvās
datubāzes tiek aprakstītas izmantojot pieejamās valodas [6]:
1) Valoda kurā veidota pati sistēma.
2) Datubāzes sistēmas valoda.
3) Valoda piekļuvei pie datubāzes.
Valodas, kas tiek izmantotas, lai piekļūtu datubāzei arī var tikt sadalītas datu definēšanas
valodā un datu manipulācijas valodā. Datu definēšanas valoda tiek lietota, lai aprakstītu
datubāzes struktūru. Datu manipulācijas valoda sastāv no vaicājumu, atjaunošanas un
transakcijas valodas, kas tiek lietotas manipulācijā ar datiem.
Datubāzes definēšanas valoda ir valoda, kas tiek lietota loģiskajā programmēšanā, lai
izteiktu pieeju datubāzei un satur nepieciešamās datu struktūras, lai saglabātu datus, kas ir
iegūti.
No loģiskā līmeņa redzes deduktīvas datu bāzes var sadalīt divās grupās:
1) Loģiski vāji saistītās sistēmās, vienlaicīgi eksistē divas atšķirīgas valodas. Abu valodu
sintakse un semantika ir atšķirīga, tāpēc izteiksme no vienas valodas var nebūt
attēlojama otrā.
42
2) Loģiski cieši saistītās sistēmās, datubāzes valoda ir tā pati loģiskās programmēšanas
valoda.
Programmas rakstīšana divās valodās noved pie tā ka tās ir grūti lasāmas un saprotamas.
Sistēmas rakstīšana vienā valodā padara to viegli lasāmu.
Taču, ja datu apjoms, kas iegūts no datubāzes var tikt samazināts izmantojot maksimāli
ierobežojošus vaicājumus un ja dati, kas ir iegūti no datubāzes tiek izmantoti efektīvi kopējā
fiziski vāji saistīto sistēmu efektivitāti stipri palielinās.
3.4. Datubāzes piekļuves procedūras apraksts
Vispārīgi datubāzes piekļuves procedūru var aprakstīt šādi [1]:
1) Sistēma veic pieprasījumu datubāzes vadības sistēmas interfeisam.
2) Pieprasījums caur sakaru kanālu tiek tālāk pārsūtīts datubāzei.
3) Datubāzes vadības sistēma izpilda saņemto pieprasījumu un caur sakaru kanālu atgriež
tā rezultātus programmai.
4) Saņemtie rezultāti tiek ievietoti programmas datu struktūrās.
Deduktīvajās datubāzēs piekļūšana datubāzei var notikt vai nu pirms sākts izpildīt
programmu vai arī pašā programmas izpildes laikā. Terminoloģijā lieto terminus statiskā un
dinamiskā piekļuve, lai aprakstītu, ka datubāzei attiecīgi pieslēdzas ielādes vai izpildes laikā.
Piekļūstot datubāzei programmas ielādes laikā programma tiek pārbaudīta, lai atrastu tajā
datubāzes predikātus, jau pirms sākts to izpildīt. Relāciju tabulas, kas atbilst atrastajiem
datubāzes predikātiem, tiek pievienotas programmai, pievienojot jaunus teikumus tās iekšējā
datubāzē. Statiskajā pieejā mērķim jābūt definētiem jau programmas ielādes laikā.
Dinamiskajā pieejā datubāzei piekļūst tikai brīdī, kad izpildes procesā tiek sastapts kāds
datubāzes predikāts. Dinamiskā pieeja tiek sasniegta izpildes laikā pārveidojot datubāzes
mērķus vaicājumu valodā.
43
3.5. Datubāzes interfeiss
Datubāzi un programmatūru savieno atsevišķs sakaru kanāls. Fiziski cieši saistītās sistēmās
šis komunikācijas kanāls ir sistēmas iekšējā maģistrāle. Fiziski vāji saistītās sistēmās šis
sakaru kanāls var būt operētājsistēma. Datu pārveide notiek pārveidojot tos no zema līmeņa
datu attēlojuma uz citu – augstāku. Fiziski cieši saistītajās sistēmās nav nepieciešamības pēc
datu pārveidošanas mehānismiem tāpēc ka programmas komponenti un datubāze lieto vienus
un tos pašus datus. Fiziski vāji saistītās sistēmās katra no sistēmas daļām lieto pati savus datus
un, lai varētu notikt sadarbība, nepieciešami datu pārveidojumi. Vispārīgi datu apmaiņa ir
ierobežota tādās vērtībās ko var attēlot abās sistēmās.
Datubāzes piekļuves mehānismi realizē piekļuvi datubāzei un datu iegūšanu izmantojot
datubāzes interfeisu. Procedurālajai pieejai tiek izmantots iekšējo ierakstu interfeiss, tas prasa
pieeju zema līmeņa informācijai datubāzē piemēram iekšējo relāciju vai atribūtu vārdiem vai
atribūtu vērtībām ierakstos. Procedurālā pieeja, izmantojot ierakstu interfeisu, prasa, lai tiktu
radīts un lietots kursora mehānisms. Neprocedurālā pieejā datubāzei tiek piekļūts izmantojot
vaicājumus, kas formulēti datubāzes vaicājumu valodā.
Koordinācijas mehānisms uzrauga kontroles plūsmu un koordinē datubāzi un programmas
izpildi. Šeit var izšķirt divas klases: granularitāte, ko izmanto sistēma un datubāze ir vienāda
vai tās atšķiras. Pirmajā gadījumā koordinācijas mehānisms vienkārši nodot datus no
datubāzes pa tiešo sistēmā, kā paradīts attēla 3.4.
3.11. Att.: Vienāda granularitāte
Ar atšķirīgām granularitātēm relācijas, kas tiek izgūtas no datubāzes tiek glabātas buferī,
no kurienes tās tālāk tiek dotas sistēmā pa kortežiem. Atšķirīga granularitāte ļauj samazināt
datu izgūšanas vaicājumu skaitu, attēls 3.5.
44
3.12. Att.: Atšķirīga granularitāte
3.6. Loģiskā līmeņa interfeiss
Tā loģiskās programmēšanas valodas daļa, kura tiek izmantota, lai piekļūtu datubāzei,
parasti ir vai nu tās papildinājums vai arī apakš valoda. Pirmajā gadījumā, datubāzes mērķos
tiek iekļautas speciāls valodas konstrukcijas, piemēram relāciju algebras operatori vai
eksistējošām datu struktūrām tiek piešķirta jauna semantika, piemēram, atomi attēlo
pieprasījumus datubāzei. Otrajā gadījumā datubāzes piekļuve tiek nodrošināta ierobežojot
loģiskās programmēšanas valodu tādējādi, ka tā ir ekvivalenta datubāzes valodai. Šis ir
Datalog gadījums, kur valoda ir ierobežota izslēdzot funkcionālos simbolus, lai to būtu
iespējams lietot kā valodu vaicājumos. Ja piekļuve notiek tikai vienai relācijai datubāzes
mērķis var piekļūt tikai vienai relāciju tabulai. Šajā gadījumā datubāzē var izpildīt tikai
selekciju un projekciju no relāciju algebras. Jebkādām citām relāciju operācijām ir jābūt
aprakstītām sistēmā vai izteiktām tikai ar šīm divām operācijām. Izmantojot datus datubāzē ir
iespējams izpildīt visas relāciju algebras operācijas.
Pastāv iespēja, ka loģikas valoda atļauj izteiksmes, kuras datubāze nesaprot, piemēram
rekursiju. Iespējama arī apgriezta situācija, ka datubāze lieto konstrukcijas, kuras loģiskā
sistēma nesaprot un nevar lietot, piemēram transakcijas kontroles komandas.
Lai pārvērstu Prolog vai Datalog par datu bāzu valodām, nepieciešams izstrādāt jaunas
sistēmas, kas sevī integrē loģiskās programmēšanas funkcijas un datubāzu sistēmas.
Piemēram viens no vienkāršākajiem interfeisiem starp Prolog sistēmu un relāciju datubāzi,
nodrošina SQL vaicājumu ģenerāciju pie katra mēģinājuma unificēt kādu datubāzes predikātu.
45
Neprocedurāla pieeja datubāzei tipiska fiziski vāji saistītām sistēmām. Tas ir tāpēc, ka gan
datubāze gan pati sistēma ir atsevišķi procesi un, lai strādātu ar skatiem no datubāzes, tiek
lietota datubāzes datu manipulācijas valoda.
Zema līmeņa procedurāla pieeja ir tipiska fiziski cieši saistītām sistēmām, tāpēc ka datu
fiziskais izvietojums sistēmā ir zināms gan datubāzes komponentam gan loģiskās valodas
komponentam. Apmaiņa ar datiem notiek izmantojot kursoru mehānismu. Valodas piekļuve
datubāzei izmantojot kursoru ir pa vidu starp procedurālo un neprocedurālo pieeju.
Loģikas līmenī, vāja saistība nozīmē, ka datubāzes valoda ir pati par sevi. Šis gadījums
raksturīgs loģiskās programmēšanas valodu papildinājumiem. Loģiski cieši saistītās sistēmās
datubāzes piekļuves valoda ir loģiskās programmēšanas valodas apakškopa, kas sevī ietver
dinamisku vaicājumu veidošanu un piekļūšanu datubāzei izmantojot skatus. Pa vidu šeit ir
sistēmas kurām valoda piekļūšanai datubāzei ir sajaukta ar loģiskās programmēšanas valodu.
3.7. Izpildes stratēģiju koordinācija
Izpildes stratēģiju koordinācija var tikt sasniegta ar diviem paņēmieniem: izmantojot ārējus
koordinācijas mehānismus, kas realizēti interfeisa līmenī vai izmainot izpildes stratēģijas
vienā no sistēmas komponentēm tā, lai tas sakristu ar otra komponenta stratēģiju.
Izpildes koordinācijas paņēmienu izstrāde ir šāda:
1) Relāciju pievienošanas programmas atmiņā.
2) Relāciju īslaicīga uzglabāšana buferī.
3) Procedurālas pieejas datubāzēm izmantošana.
4) Pilna integrācija ar vienotu izpildes stratēģiju.
Katrs no minētajiem izpildes koordinācijas paņēmieniem loģiski seko viens otram to
papildinot.
3.8. Deduktīvo datu bāžu uzlabošanas tendences
Efektivitātes uzlabošana ir koncentrējusies galvenokārt uz fizisko līmeni. Pamatā šīs pūles
saistītas ar datubāzes un loģikas valodas izpildes ciešāku sadarbību un datu pārveidošanas un
46
pārraides minimizēšanu. Kā arī ar pašas datubāzes uzlabošanu, lai tā spētu glabāt likumus.
Kādu daļu no izvedumu mehānismiem var iekļaut arī datubāzē piemēram glabātās procedūras
vai trigerus [1].
Datubāzē glabājamo predikātu ievietošana programmas atmiņā efektīvi noslēpj darbu, kas
notiek datubāzē no tā kas notiek pašā sistēmā. Vaicājuma izpildes rezultātā tiek atgriezta
relācija, kas kā programmas teikumu secībā tiek ievietota sistēmas atmiņā. Loģikas valoda
izpildes laikā nejūt nekādu atšķirību starp predikātiem kas jau bija tās rīcībā un jaunajiem, kas
tika pievienoti vaicājuma rezultātā. Rezultātu pievienošana atmiņā ir laiku un atmiņas vietu
prasošas operācijas tāpēc ka nepieciešams pastāvīgi atjaunot esošo predikātu sarakstu [1].
Bufera lietošanas galvenā priekšrocība ir tāda, ka datubāze parasti atgriež rezultātu kopu,
kas uzreiz var tikt ievietota atmiņas buferī, turpretim programma no bufera iegūst pa vienam
kortežam. Tas ļauj ekonomēt sistēmas resursus. Galvenā buferu problēma ir tāda ka tie ir
ierobežoti izmērā un skaitā. Šo problēmu varētu atrisināt piešķirot katram vaicājumam savu
buferi, kur glabāt rezultātus. Taču buferu skaits ir vienmēr galīgs un datubāzes pieprasījumu
skaits var pārsniegt pieejamo buferu skaitu. Tas ir īpaši iespējams lietojot rekursiju, kur
nekādi nav iespējams noskaidrot rekursīvo soļu skaitu jau iepriekš [1].
Pieeju datubāzei var sadalīt uz zemo līmeņa pieeju izmantojot iekšējos ierakstus vai pat
atmiņas segmentus un pieeju izmantojot datubāzes kursorus. Tiešā pieeja atgriež sistēmā
vienu atmiņas fizisko lappusi, no kuras ir jāiegūst prasītie ieraksti. Galvenā tiešās pieejas
problēma ir tāda ka atgriezto datu precizitāte ir zema. Datubāzes kursors nodrošina viena
ieraksta interfeisu datu izgūšanai no datubāzes. Katrs datubāzes predikāta izsaukums tiek
piešķirts kursoram. Tekošā kursora vērtība tiek atgriezta izmantojot datubāzes predikāta
argumentus. Galvenā kursoru problēma ir tāda, ka ir pieejams galīgs skaits kursoru kas noved
pie līdzīgām problēmām kā lietojot buferus [1].
Deduktīvā datubāze sastāv no divām daļām, loģiskās programmatūras un fiziskās datu
glabāšanas mehānisma. Tās izpildās kā divas atsevišķas daļas. Taču iespējams arī sistēmas
kurās šīs abas daļas apvienotas vienā. Tādas sistēmas datubāze un loģiskā valoda ir vienkārši
fiziski cieši saistītas vai integrētas sistēmas apakš komponentes. Fiziski cieši saistītas
sistēmas izpilde var būt vai nu uz kortežiem orientēta vai uz kopu orientēta. Vienota šo abu
sistēmas daļu izpilde neprasa nekādu papildus koordinācijas mehānismu izmantošanu un
tādējādi ir efektīva [1].
Sakaru kanāla efektivitāti nosaka datu pārraides ātrums un datu apjoms, kas var tikt
pārraidīts caur šo kanālu. Sakaru kanāls deduktīvajās datubāzēs ir vai nu ārējs, kas ir lēns ja
47
savieno divas atšķirīgas sistēmas vai arī ātrs ja tas ir realizēts kā sistēmas iekšējā maģistrāle.
Efektivitāti var palielināt samazinot pārraidāmo datu apjomu [1].
Datu pārveidošana. ir vienmēr nepieciešama tāpēc, ka tiek lietoti dažādi datu formāti. Datu
pārveidošanas izmaksas sistēmā parasti ir ļoti lielas tāpēc ir nepieciešams, lai datu
pārveidošana būtu pēc iespējas mazāka. Datu pārveidošanai vispiemērotākā vieta ir sakaru
kanāls vai nu datubāzes vai pašas sistēmas pusē. Sistēmās, kas aprakstītas iepriekš datu
pārveidošanas mehānismi ir atrodami loģiskās valodas pusē. Fiziski cieši saistītām sistēmām
nav nepieciešami datu pārveidošanas mehānismi jo dati ir vienādi gan priekš loģikas
komponentes gan priekš datubāzes [1].
Deduktīvās datubāzes neatkarība no izmantojamās datubāzes ir iespējama izmantojot tikai
neprocedurālu pieeju datubāzei. Pirmais paņēmiens ir moduļu interfeiss, kas ļauj pieslēgties
konkrētai datubāzei. Otrais paņēmiens ir pieprasījumi, kas izdalīti datubāzē pārveidošanai
augsta līmeņa vaicājumu valodās [1].
Izmantojot moduļu interfeisu tiek izveidots papildus slānis starp deduktīvās datubāzes
pamatsistēmu un pašu datubāzi. Izmantojot speciālus moduļus var piekļūt dažādām
datubāzēm. Patiesā piekļuve datubāzei tad tiek realizēta izmantojot šo moduli [1].
Datubāzes pieprasījumu pārveidošanas gadījumā, pieprasījumi tiek pārveidoti augsta
līmeņa datubāzes vaicājumu valodā neizmantojot nekādas papildus saskarnes. Katru reizi kad
tiek izsaukts datubāzes predikāts, atbilstošie mērķi tiek pārveidoti datubāzes vaicājumā vai
vaicājumu secībā, kas tiek izpildīts datubāzē. Pārveidošanas priekšrocība ir tāda, ka datubāzes
vaicājumi var tikt veidoti dinamiski un ka pārveidošanas procedūra pati par sevi var tikt
izveidota loģikas valodā. Galvenais trūkums šeit ir ka pārveidošana nepieciešama katram
datubāzes predikāta izsaukumam, kas var būt diezgan laikietilpīgi [1].
48
4. DEDUKTĪVAS DATU BĀZES IZSTRĀDE
4.1. Deduktīvas datu bāzes specifikācija
Deduktīvo datu bāzi var izstrādāt izmantojot vairākas arhitektūras. Darbā tiek apskatīts
risinājums ar integrētās deduktīvās datu bāzes izveidošanu.
Integrēšanas gadījumā izveduma apakšsistēma ir integrēta datu bāzes vadības sistēmā un
darbojas datu bāzes iekšējos buferos, kā jau eksistējošo izveduma mehānismu paplašinājums.
Datubāzu vadības sistēmā ir organizēts speciāls līmenis, datu ievadei un izvadei interpretators,
kas reprezentē attieksmes no datubāzes uz loģikas predikātu veidā. Ar šo pieeju integrētā
sistēma piedāvā lietotājam vienādu interfeisu likumu un vaicājumu veidošanai.
Lietotājam nav tiešas pieejas pie datu bāzes vadības sistēmas. Dati no datubāzes tiek
attēloti Datalog loģikas valodā predikātu formā un tādā veidā tiek piedāvāti lietotājam. Datu
pārveidošanu loģikas valodā veic likumu interpretators, kas ir realizēts kā loģiskas
programmēšanas līmenis. Pirms interpretators veic pārveidošanu, tas ar vaicājuma palīdzību
atlasa no datubāzes datus, kas konkrētajā brīdī ir vajadzīgi programmai.
Dinamiski cieša sasaistīšana tiek izpildīta atsevišķi katram konkrētam likumam. Izsaucot
katru no datubāzes predikātiem, tiek iedarbināts vaicājums, kas novērtē predikātu.
Ir pielietota heterogēna arhitektūra kura nosaka, ka datubāze izveidota izmantojot divas
atsevišķas apakšsistēmas: loģiskās programmēšanas sistēmu un relāciju DBVS. Loģiskās
programmēšanas sistēma izmantota, lai īstenotu deduktīvo secinājumu pieņemšanu, balstoties
uz līkumiem. Programmatūra izmanto relāciju DBVS faktu, līkumu, un izvadīto faktu
veidošanai, apstrādei, glabāšanai un vadībai.
Likumu un faktu attēlošanai izmantota viena un tā pati loģisko vaicājumu valoda
DATALOG. Gan dati, gan fakti, gan likumi, gan izveidotie jaunie fakti glabājas sekundārajā
atmiņā, no kurienes pirms programmas darbības izpildes tie tiek ielādēti operatīvajā atmiņā un
glabājas tur līdz programmas izpildes beigām. Likumu un faktu glabāšana primārajā atmiņā
neierobežo izmantojamās zināšanu bāzes apjomu atmiņas ierobežojumu dēļ. Likumi un fakti
atšķiras gan ar apjomu, gan ar veidiem.
Glabājot datus dažādās vietās un piekļūstot tiem atsevišķi ar dažādām piekļuves metodēm,
būs sasniegta labākā izvedumu veiktspēja.
49
Pieprasījumus pa tiešo pārveido uz augsta līmeņa datubāzes vaicājumu valodu SQL
neizmantojot nekādas papildus saskarnes. Katru reizi kad tiek izsaukts datubāzes predikāts,
atbilstošus mērķus pārveido uz datubāzes vaicājumu vai vaicājumu secību, kuri izpildās
datubāzē. Datubāzes predikātu pārveidošana no Datalog valodas uz definētām SQL valodas
procedūrām veikta Java sistēmā. SQL valodas procedūru izveidošanas vaicājumi doti
pielikumā pieci. Ar šīm procedūrām programmatūra saņem iespēju izpildīt SQL vaicājumus,
ar plašu ievades un izvades datu klāstu. Pārveidošanas priekšrocība ir tāda, ka datubāzes
vaicājumus var izveidot dinamiski un pārveidošanas procedūra pati par sevi var izveidot
loģikas valodu. Galvenais trūkums šeit ir ka pārveidošana nepieciešama katram datubāzes
predikāta izsaukumam, kas būs diezgan laikietilpīgi.
Loģiskās programmēšanas valoda ir Datalog valoda. Datu bāzes vadības sistēma ir Oracle.
Deduktīvas datu bāzes kodola darbību nodrošina izstrādāta Java klase ddbMain.class, kurā ir
definēti datu ievades, datu izvades funkcijas, kā āri realizēts deduktīvas izvades mehānisms.
Interfeiss sastāv no pamata komponentēm - koordinācijas mehānisma, sakaru kanāla un
datu pārveidošanas mehānismiem. Vaicājumu izpildei izmanto kopas izpildes stratēģiju.
Kontroles stratēģija ir ierobežota ar meklēšanas un izskaitļošanas likumiem. Standarta
kontroles stratēģija paredz teikumu izpildi tā kā to specificē programmas kods, izvēlēties
pirmo no atrastajiem mērķiem un tālāk meklēt plašumā.
Lietotāji piekļūst datubāzei izmantojot jau iepriekš definētu interfeisu. Vaicājumu valodas
sintakse ir aprakstīta pielikumā trīs.
Sistēma ir fiziski cieši saistīta, dati pa taisno tiek piegādāti datu bāzes komponentu
sistēmai, un nav vajadzības pārveidot datu formātus. Faktu, likumu un izvadīto faktu
glabāšanai izmanto speciālas struktūras. SQL vaicājumi, datu glabāšanas struktūru veidošanai
ir noradīti pielikumā četri.
Loģiskajā līmenī interfeiss starp sistēmu un datubāzi sastāv no datubāzes piekļuves
valodas. Valoda kurā izveidota pati sistēma ir Java valoda. Valoda kura nodrošina datu bāzes
datu apstrādi ir SQL valoda. Datu definēšanas valoda un datu manipulācijas valodā ir Datalog
valoda.
Datubāzes piekļuves procedūra ir tāda:
1) Sistēma veic pieprasījumu datubāzes vadības sistēmas interfeisam.
2) Pieprasījums caur sakaru kanālu pārsūtīts datubāzei.
3) Datubāzes vadības sistēma izpilda saņemto pieprasījumu un caur sakaru kanālu atgriež
tā rezultātus programmai.
50
4) Saņemtos rezultātus ievieto programmas datu struktūrās.
Deduktīvas datubāzēs piekļūšana datubāzei notiek pirms loģiskās programmas izpildes.
Savienojumu ar datu bāzi uzstāda programmas darbības sākumā, un aizver savienojumu tikai
tad, kad lietotājs beidz savu darbu.
Datubāzi un programmatūru savieno atsevišķs sakaru kanāls. Datu pārveide notiek
pārveidojot tos no zema līmeņa datu attēlojuma uz citu – augstāku. Katra no sistēmas daļām
lieto pati savus datus un nepieciešami datu pārveidojumi. Datu pārveidošanas vietas ir sakaru
kanāls, vaicājumu izpildei. Un pašas sistēmas pusē, jauno datu, likumu ievadīšanai.
Datubāzes piekļuves mehānismi realizē piekļuvi datubāzei un datu iegūšanu izmantojot
datubāzes interfeisu. Neprocedurālā pieejā datubāzei realizēta izmantojot vaicājumus, kuri ir
izteikti datubāzes vaicājumu valodā. Koordinācijas mehānisms uzrauga kontroles plūsmu un
koordinē datubāzi un programmas izpildi. Koordinācijas mehānisms vienkārši nodot datus no
datubāzes pa tiešo sistēmā.
Datubāzes piekļuve ir nodrošināta, ierobežojot loģiskās programmēšanas valodu tādējādi,
ka tā ir ekvivalenta datubāzes valodai. Datalog valoda ir ierobežota izslēdzot funkcionālos
simbolus, lai to būtu iespējams lietot kā valodu vaicājumos. Loģikas valodā ir atļautas
izteiksmes, kuras datubāze nesaprot, piemēram rekursiju. Par šo izteiksmju apstrādi ir
atbildīgs izveduma mehānisms.
Izpildes stratēģiju koordinācija ir sasniegta izmantojot ārējus koordinācijas mehānismus,
kas realizēti interfeisa līmenī. Izpildes koordinācijas paņēmienu izstrāde ir šāda - relāciju
pievienošanas programmas atmiņā un procedūralas pieejas datubāzēm izmantošana.
Deduktīvā datu bāze ir atkarīga no izmantojamās datubāzes, un programmatūras izstrāde
bija integrēta ar Oracle Datu bāzes vadības sistēmu.
4.2. Programmatūra
Pēc uzdevuma izpētes bija analizētas daudzas programmatūras veidu, kuros var izmantot
deduktīvas datu bāzes realizācijai. Pēc iepazīšanās ar dažiem produktiem bija pieņemts
risinājums, uzrakstīt pašam programmatūru, kuru nodrošina deduktīvas datu bāzes
funkcionēšanu.
51
Izstrādes mērķis bija izstrādāt tādu produktu, kurš ļauj izmantot Datalog valodu, kā
vaicājumu valodu. Pie tam ļauj izmantot faktus kurus glabās relāciju datu bāze. Izstrādāta
programmatūra tiek nosaukta ka myDDB – my Deductive Data Base.
Deduktīvas datu bāzes izstrādei bija izmantoti daudzi komponenti.
Oracle Database 10g Express Edition datu bāzes vadības sistēma. Oracle ir ļoti spēcīga
DBVS un gandrīz jebkurā augstā līmeņa programmēšanas valodas ir izstrādāti draiveri, lai
būtu ērtāk piekļūt datu bāzei un tā izstrādātā priekš daudzām platformām. Izstrādes laikā bija
izmantots - Oracle Database XE Server.
Piekļuvi pie Oracle datu bāzes vadības sistēmas no Java programmatūras ir vajadzīga viena
komponente - Oracle Database XE Client. Komponente āri izstrādāta priekš daudzām
platformām. Un nodrošina daudzu datu piekļuves tehnoloģiju funkcionēšanu, Oracle JDBC
draiveris, Oracle ODBC, Oracle Provider for OLE DB, Oracle Data Provider for .NET un
Oracle Services for Microsoft Transaction Server.
Java programmatūras izstrādei un kompilēšanai ir vajadzīgs produkts - Java Development
Kit. Šī komponente nodrošina interfeisu starp Java aplikācijām un Oracle JDBC.
Java programmatūras izpildei būs vajadzīgs viens produkts, Java virtuāla mašīna - Java
Runtime Environment.
Izstrādes rīks, kurš orientēts uz datu bāzes lietojumu izstrādi - Oracle JDeveloper.
Visu komponentu licencēšanas politika ir tāda, ka tos var izmantot bezmaksas, studijās
gaitā. Visi komponenti ir pieejami Internetā, pēdējās versijas var ielādēt no programmatūras
izstrādes kompāniju lapām.
4.3. Deduktīvas Datu Bāzes Arhitektūra
Programmatūras darbība ir balstīta uz dažiem paņēmieniem. Programmatūra strādā
interaktīvā režīmā. Lietotājs dod komandas, un programmatūra izpilda tās. Lietotājs var gan
rakstīt vaicājumus valodā Datalog, gan pievienot jaunus faktus un likumus.
Programmatūra saņem Datalog likumus, faktus un vaicājumus no ievades konsoles. Faktus
programmatūra var saņemt no lietotāja, gan no Datalog programmas, gan no relācijas datu
bāzes. Datus no relāciju datu bāzes programmatūra saņem ar JDBC rīku, pieslēgties un
izpildījot datu iegūšanas procedūras, kuras glabājas Oracle iekšējos buferos.
52
Programmatūra bija uzrakstīta, kā Java programma, izpildās Java vidē, jaunu faktu izveidei
izmanto plašuma meklēšanas stratēģiju. Rīks, Java valoda bija izvēlēta viena iemesla dēļ, tā ir
atbilstoša, labi strādājoša tehnoloģija, kuru ar dažiem izņēmumiem var izmantot Datalog
loģisko programmu izpildei. Kas arī bija izdarīts. Un vēl viens, ļoti svarīgs iemesls,
programmas, uzrakstītas Java valoda viegli integrēt ar Oracle datu bāzes vadības sistēmu.
Programmatūras myDDB Datalog valodas gramatika ir dota pielikumā trīs. Salīdzinot ar
standarta Datalog valodas sintaksi, attēls 4.1, tajā bija implementētas gandrīz visas funkcijas,
ar sīkiem izņēmumiem, galvenokārt uz termu un predikātu skaitu ierobežošanu.
4.13. Att.: Implementētas Datalog valodas funkcionalitāte
Programmatūras kodola pirmteksts dots pielikumā seši. Vaicājumi, kuri izpildās Oracle
vidē doti pielikumā pieci. Šie vaicājumi nodrošina izstrādātas programmatūras integritāti ar
Oracle datu bāzes vadības sistēmu. myDDB sistēmas arhitektūra ir parādīta attēlā 4.2.
53
4.14. Att.: myDDB Arhitektūra
Fakti, likumi un izvadītie fakti glabājas relāciju datu bāzē, iepriekš definētās datu
struktūrās. Relāciju datu bāzē arī atrodas programmatūras izpildes protokols. Ieraksti par katru
darbību ir ievadīti katrā funkcijas izpildes gaitā, kas ļauj kontrolēt izpildes gaitu, īpaši
deduktīva izvades mehānisma darbības gaitā. Dati par kļūdām glabājas iekšējās datu
struktūrās, un pieeju pie tiem var saņemt tikai programmatūras darbības laikā, pēc katras
funkcijas izpildes.
Programmatūras komponentes glabājas gan Oracle datu bāzes vadības sistēmā, gan ārējā
izpildāmā datnē. Programmatūras kodols sastāv no piecām komponentēm. Kodola
komponentes parādītas attēlā 4.3.
4.15. Att.: Programmatūras kodola arhitektūra
54
Izstrādes laikā, bija izveidotas divas sistēmas. Cieši saistīta, prototipa sistēma, bija
izveidota darbības sakumā. SQL valodas vaicājumi, darbības laikā bija integrēti uz Oracle
datu bāzi, tādā veidā, ka tie tikai atgriež datus. Strādājot ar divām sistēmām, uz vieniem un
tiem pašiem datiem bija iegūti kvalitatīvi darbības veiktspējas rezultāti, kurus var attēlot tādā
veidā, kā parādīts attēlā 4.4
4.16. Att.: Saistīto un Integrēto sistēmu kvalitatīvs salīdzinājums
4.4. Programmatūras darbības algoritmi
Programmatūrā ir implementēti divi svarīgie algoritmi. Programmatūrai, pēc uzdevuma,
jānodrošina loģisko programmu izpildi. Pirmais posms, loģiskās programmas analīze, un
likumu un faktu pievienošana deduktīvai datu bāzei. Otrs posms, jauno faktu iegūšana,
atkarībā no ievadītiem likumiem un faktiem.
Pirmais posms ir interpretēt jebkuru loģisko programmu, kura uzrakstīta atbilstoši Datalog
valodas sintaksei. Interpretācijas gaitā, visi likumi pievienojas likumu datu bāzei. Visi fakti
pievienojas faktu datu bāzei. Mērķis, ja tāds atradīsies, tiek atstāts uz algoritma beigām. Kad
visi fakti un likumi ir pievienoti deduktīvai datu bāzei, notiek mērķa izskaitļošana. Datalog
valodas interpretatora algoritms parādīts attēlā 4.5.
55
4.17. Att.: Datalog valodas interpretatora algoritms
Kad bija ievadīti visi dati, un zināmi visi likumi, ir laiks pielietot dedukcijas algoritmu,
jauno faktu iegūšanai.
Pirmkārt, pirms algoritma darbības, ir vērts pārbaudīt, vai mērķis atrodas starp zināmiem
faktiem? Ja mērķis atrodas starp zināmiem faktiem, tad ir jēga to iegūt, un pabeigt darbību.
Dedukcijas algoritms sastāv no dažām funkcijām. Pirmā, ir likumu sarakstu izveidošana,
pati intelektuālā darbība.
Ja mērķis ir fakts, vai faktu kopa, tad to var iegūt, vienkārši izvēlēties atbilstošus faktus no
faktu datu bāzes.
56
Ja mērķis ir likums, pie tam šis likums sastāv tikai no faktiem, vai citiem likumiem, kuri
sastāv tikai no faktiem, tos arī var izpildīt izvēloties faktus no faktu datu bāzes.
Ja mērķis ir rekursīvs likums, tad pirms to izpildīšanas vajag izvadīt visus nerekursīvus
predikātus. Kad predikāti ir izvadīti, var izvadīt rekursīvos datus atbilstoši likumam. Jauno
datu izvade beidzas tikai tad, kad vienas iterācijas laikā nebija iegūti jauni dati. Algoritms ir
parādīts attēlā 4.6.
4.18. Att.: Deduktīvais algoritms
57
4.5. Faktu tabula
Visi fakti glabājās datu bāzē noteiktās, iepriekš definētās struktūrās. Vaicājumi struktūru
veidošanai ir uzrādīti pielikumā četri. Katrs fakts saglabāts datu bāzē ar aprakstošiem
atribūtiem. Katram faktam ir savs unikāls numurs. Katrs fakts saņem savu vārdu, kas bija
definēts loģiskā programmā, un argumentu skaitu. Visi argumenti glabājas arī iepriekš
definētā struktūrā, kas ļauj operēt ar viņiem faktu iegūšanas laikā. Katrs arguments saņem
unikālo numuru, vienā faktā apgabalā. Argumentam piešķirts tipu apraksts, vai tas ir skaitlis,
vai simbolu virkne, un argumenta vērtība ir tāda, kā bija definēts loģiskā programmā. Faktu
glabāšanas tabula ir parādīta attēlā 4.7.
4.19. Att.: Faktu glabāšanas tabula
4.6. Likumu tabulas
Visi likumi glabājas datu bāzē noteiktās, iepriekš definētās struktūrās. Vaicājumi struktūru
veidošanai ir uzrādīti pielikumā četri. Katrs likums saglabāts datu bāzē ar aprakstošiem
atribūtiem. Katram likumam ir savs unikāls numurs. Katrs likums saņem savu vārdu, kas bija
definēts loģiskā programmā, predikātu skaitu un argumentu skaitu. Visi argumenti glabājas
arī iepriekš definētā struktūrā, kas ļauj operēt ar viņiem deduktīva mehānisma darbības laikā.
Katrs arguments saņem unikālo numuru, vienā likuma apgabalā. Argumentam piešķirts tipu
58
apraksts, vai tas ir skaitlis, vai simbolu virkne, vai mainīgais un argumenta vērtība ir tāda, kā
bija definēts loģiskā programmā. Likumu glabāšanas tabula ir parādīta attēlā 4.8.
4.20. Att.: Likumu glabāšanas tabula
Katrs likums definēts ar predikātu palīdzību. Predikātus izmanto izskaitļošanas mehānisma
darbībā. Katram predikātam ir savs unikāls numurs. Katrs predikāts piesaistīts likumam, un ir
definēta predikāta vieta likumā, predikāts saņem savu vārdu, kas bija definēts loģiskā
programmā un argumentu skaitu. Visi argumenti glabājas arī iepriekš definētā struktūrā, kas
ļauj operēt ar viņiem deduktīva mehānisma darbības laikā. Katrs arguments saņem unikālo
numuru, vienā predikāta apgabalā. Argumentam piešķirts tipu apraksts, vai tas ir skaitlis, vai
simbolu virkne, vai mainīgais un argumenta vērtība ir tāda, kā bija definēts loģiskā
programmā. Predikātu glabāšanas tabula ir paradītā attēlā 4.9.
4.21. Att.: Predikātu glabāšanas tabula
59
4.7. Izvadīto faktu tabula
Visi izvadītie fakti glabājas datu bāzē noteiktās, iepriekš definētās struktūrās. Vaicājumi
struktūru veidošanai ir uzrādīti pielikumā četri. Katrs izvadītais fakts saglabāts datu bāzē ar
aprakstošiem atribūtiem. Katram faktam ir savs unikāls numurs. Katrs fakts saņem savu
vārdu, kas bija definēts loģiskā programmā, un argumentu skaitu. Visi argumenti glabājas arī
iepriekš definētā struktūrā, kas ļauj operēt ar viņiem faktu iegūšanas laikā. Katrs arguments
saņem unikālo numuru, vienā fakta apgabalā. Argumentam piešķirts tipu apraksts, vai tas ir
skaitlis, vai simbolu virkne, un argumenta vērtība ir tāda, kā bija definēts loģiskajā
programmā. Izvadīto faktu glabāšanas tabula ir parādīta attēlā 4.10.
4.22. Att.: Izvadīto faktu glabāšanas tabula
60
5. IZSTRĀDĀTAS DEDUKTĪVAS DATU BĀZES PIELIETOJUMS
5.1. Faktu datu bāze
Par deduktīvas datu bāzes piemēru bija izvēlēta problēmsfēra, cilvēku ģenealoģiskais koks.
Ģenealoģiskais koka piemērs parādīts attēlā 5.1.
5.23. Att.: Ģenealoģiskais koks
Loģiskā programmā ir aprakstīti sakari starp cilvēkiem. Tie ir fakti vecāks.
vecāks(‘Jānis’, ‘Kārlis’).vecāks(‘Kārlis’, ‘Marta’).vecāks(‘Marta’, ‘Otis’).
Ir aprakstīti cilvēku dzimumi. Tie ir fakti vīrietis un sieviete.
vīrietis(‘Jānis’).vīrietis(‘Māris’).sieviete(‘Marta’).
61
Ir uzrādīti papildus fakti par dažiem cilvēkiem. Tie ir fakti karalis, spoks un devīgs.
karalis(‘Kārlis’).spoks(‘Kārlis’).devīgs(‘Otis’).
Pilns faktu saraksts ir dots pirmā pielikumā.
5.2. Likumu datu bāze
Loģiskā programmā ir definēti daži likumi, jauno faktu iegūšanai. Esošo faktu
pārveidošana. Likums bērns.
bērns(A, B) :- vecāks(B, A).
Dažu faktu apkopojums, un to apkopošanas rezultātā jauno faktu iegūšana. Likums māte,
likums tēvs.
māte(A, B) :- vecāks(A, B), sieviete(A).tēvs(A, B) :- vecāks(A, B), vīrietis(A).
Un rekursīva faktu iegūšana. Likums pēctecis.
pēctecis(A, B) :- vecāks(A, B).pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B).
Pilns likumu saraksts ir dots pirmā pielikumā.
5.3. Izpildes piemērs
Izstrādāta deduktīva datu bāze satur arī lietotāju interfeisu, ar visiem aprakstītiem rīkiem.
Lietotāja interfeiss bija realizēts, ievērojot augstas prasības priekš ērtības un vienkāršības,
pielietojot tādas sarežģītas tehnoloģijas.
Pēc palaišanas myDDB programmatūra izveido savienojumu ar Oracle datu bāzi, ar
iepriekš definētiem parametriem. Ja savienojums izveidots veiksmīgi, tad virsrakstā parādīsies
vārds (pieslēdzas). Programmatūras sākuma stāvoklis parādīts attēlā 5.2.
62
5.24. Att.: myDDB programmatūras sākuma logs
Visas komandas ir sagrupētas uz izvēlnēm, atkarībā no to funkcijām. Izvēlne Datu Bāze
parādīta attēlā 5.3. Komandas nodrošina uzstādes un savienojumu ar datu bāzi. Kā arī parāda
darbības izpildes protokolu, un viena komanda sagatavo jaunu datu bāzi darbībai.
5.25. Att.: Izvēlne Datu Bāze
Datu attēlošanai ir ievadītas trīs komandas, un tās sagrupētas izvēlnē Skats, attēls 5.4.
63
5.26. Att.: Izvēlne Skats
Deduktīvas datu bāzes faktu iegūšanai ir izveidota viena komanda, Izveduma Mehānisms,
kura atbild par deduktīva mehānisma palaišanu. Izvēlne ir parādīta attēlā 5.5.
5.27. Att.: Izvēlne Vaicājums
Programmas testēšanai ir izveidota vēl viena izvēlne. Izvēlne Piemēri parādīta attēlā 5.6.
Tā papildina jaunizveidoto datu bāzi ar faktiem un likumiem, kuri bija aprakstīti daļā 5.1 un
daļā 5.2.
64
5.28. Att.: Izvēlne Piemēri
Visas programmas darbības tiek protokolētas. Un protokolu par deduktīvo datu bāzi
iespējams apskatīties, izvēloties izvēlni Datu Bāze pogu Sistemas Protokols. Izpildes
protokols parādīts attēlā 5.7.
5.29. Att.: myDDB izpildes protokols
Oracle datu bāzes savienošanas īpašības var definēt logā Savienošanas Uzstādījumi. Logs
parādīts attēlā 5.8.
65
5.30. Att.: Logs Savienošanas Uzstādījumi
Ievadot datus deduktīvajā datu bāzē uzreiz mainīsies informatīvais uzraksts, kurš paziņo,
cik lieli glabājamo faktu skaits, glabājamo likumu skaits, cik faktu izvadīja izpildes
mehānisms, un cik liels SQL vaicājumu skaits bija izpildīts programmas darbības laikā.
Darbības gaitā var paskatīties, kādi fakti glabājas deduktīvajā datu bāzē. Attēls 5.9.
5.31. Att.: Faktu saraksts
Likumu saraksts arī glabājas deduktīvajā datu bāzē. Un to attēlojums ir parādīts attēlā 5.10.
66
5.32. Att.: Likumu saraksts
Pielietojot deduktīvo datu bāzi vaicājumu izpildei ir jāuzrāda mērķis, predikātu, kuru
lietotājs grib izskaitļot. Vaicājuma ? mate(B, A). izpildes piemērs dots attēlā 5.11.
5.33. Att.: Vaicājuma ? mate(B, A). izpildes piemērs
67
Vaicājumā ? nogrieznis(‘a’, B). izpildes piemērs dots attēlā 5.12.
5.34. Att.: Vaicājumā ? nogrieznis(‘a’, B). izpildes piemērs
Datalog loga var uzradīt gan vaicājumus, gan ievadīt faktus, gan ievadīt likumus.
Vaicājumiem, faktiem un likumiem jāatbilst Datalog vaicājumu valodas sintaksei. Datalog
valodas sintakse dota pielikumā trīs.
68
SECINĀJUMI
Deduktīvas datu bāzes pēc savas būtības ir datu bāžu un loģiskās programmēšanas
tehnoloģiju apvienojums. Deduktīvas datu bāzes ne tikai glabā datus, kā to dara relāciju datu
bāzes, bet glabā arī faktus, kuri sastāv no zināmiem datiem un glabā likumus, ar kuru
palīdzību var iegūt jaunus faktus no jau esošiem. Jauno faktu iegūšana tiek pamatota ar
loģisko programmēšanu. Loģisko vaicājumu izpildi nodrošina deduktīvas datu bāzes
izveduma mehānisms.
No pieredzes, kura bija iegūta darba izstrādes gaitā var secināt:
1) Izstrādāta sistēmas arhitektūra, kura ievēro prasības, priekš integrētām sistēmām, ļauj
izveidot deduktīvo datu bāzi ar plašām iespējām, gan pielietot dažus datu bažu vadības
sistēmas, gan pielietojot dažus loģiskas vaicājumu valodas, ar dažiem izpildes
mehānismiem.
2) Saistīto sistēmu gadījumā datu bāzes piekļuves moduļu izmantošana atrisina
savienošanas problēmas ar datu bāzes vadības sistēmu. Integrētas sistēmas, deduktīvas
datu bāzes arhitektūra ļoti piesaistītā pie datu bāzes vadības sistēmās, datu ievades un
izvades funkcijās.
3) Deduktīvas datu bāzes izveduma mehānismā ir vērts pielietot loģisko vaicājumu
pārveidošanu uz SQL vaicājumiem. Datalog vaicājumu pārveidošana uz SQL
vaicājumiem, prasa daudz līdzīgo SQL vaicājumu izpildi, jauno faktu iegūšanai.
4) Deduktīvas datu bāzēs ir vērts implementēt Datalog vaicājumu valodu, kura atbilst
datu bāžu vaicājumu valodām. Tā ļauj strādāt ar datu kopu, kā tradicionālas datu bāžu
vaicājumu valodas, un ļauj izvadīt jaunus datus, kā to dara tradicionālas loģiskās
programmēšanas valodas. Un Datalog vaicājumu valoda realizē plašumā meklēšanas
stratēģiju, faktu iegūšanai.
5) Lielo datu apjomu apstrādei var izmantot loģiskos vaicājumus. Deduktīvai datu bāzei
var izstrādāt Datalog valodas interpretatoru, kurš veic analīzi, pievieno faktus un
likumus deduktīvai datu bāzei, un pēc vajadzības palaiž deduktīvo mehānismu mērķu
izskaitļošanai.
Ir vērts runāt par izstrādātās sistēmas tālāko attīstību. Kā galvenās uzlabošanas darbības ir
vērts minēt četras.
69
1) Izstrādātais izvades mehānisms ļauj ļoti vienkārši paplašināt iebūvēto Datalog
vaicājumu valodu, lai to pārveidotu uz spēcīgāko vaicājumu valodu, pievienojot
funkcijas, aritmētiskās darbības, saglabājot loģisko vaicājumu izpildi.
2) Ir jēga uzlabot Deduktīvo mehānismu, optimizēt loģisko vaicājumu izpildi, samazinot
kopējo vaicājumu skaitu pie datu bāzes. Programmatūras arhitektūra ir tāda, ka katrs
vaicājums izpildās savā noteiktā atmiņas apgabalā, ar saviem mainīgiem. Tāda
arhitektūras īpašība bija izdarīta, lai šo programmatūru varētu izpildīt uz daudziem
procesoriem, daudzām kodolu sistēmām, kas ļoti krietni var paātrināt izveduma
mehānisma darbību. Deduktīvais mehānisms izpilda daudz viena tipa operāciju, kuru
var izpildīt paralēli.
3) Bija izveidots kļūdu apstrādes algoritms, kurš tikai paziņo, par notikušo kļūdu, un
apstāj izskaitļošanu. Sarežģītas sistēmas ir vērts apstrādāt kļūdas intelektuāli,
nepārtraucot sistēmas darbību, un nepārtraucot jauno faktu iegūšanu.
4) Ir vērts izveidot algoritmu operatīvās atmiņas optimālai izmantošanai. Kaut gan, katrs
likums izpildās savā atmiņas apgabala, un pēc likuma izskaitļošanas, iegūtie dati
saglabājas deduktīvā datu bāzē, un atmiņa atbrīvojas priekš nākamā likuma.
Kā iespējamās pielietošanas sfēras var minēt dažas:
1) Deduktīvas datu bāzes var pielietot koku analīzei. Kā piemērs, bija piedāvātas divas
loģiskās programmas: ģenealoģisko koku analīze, un loģistika, izdevīgāko ceļu
meklēšana.
2) Deduktīvas datu bāzes var pielietot datu analīzei un izvadei mākslīga intelekta
ekspertu sistēmās.
Bakalaura darba izstrādes gaitā bija izstrādāta sistēma, kura labāk atbilst tieši datu bāzei.
Izstrādāta deduktīva datu bāze var apkalpot lielu faktu apjomu un var izveidot lielu jauno
faktu kopas.
Ir dotas pilnas tehniskās specifikācijas, kuras attiecas uz sistēmas arhitektūru un darbību.
Bija izstrādāts interfeiss programmatūrai un aprakstīta Datalog valodas sintakse.
70
TERMINU VĀRDNĪCA
Termins angļu valodā Termins latviešu valodā Skaidrojums
Arity apjoms Argumentu skaits predikātā.
Bottom-up izpildes semantika no
apakšas uz augšu
Loģisko programmu izpildēs
semantika, kad sākumpunkts ir faktu
kopa. Katrā izpildes solī faktu kopa tiek
salīdzināta ar likumu galvām, kuru
ķermeņi ir patiesi. Izpilde beidzas, ja
sākotnēji dotais mērķis ir iekļauts
atvasināto faktu kopā.
Deductive Database deduktīva datu bāze Datubāze, kas glabā faktus un likumus,
un spēj izvadīt jaunus faktus no
esošiem, pielietojot likumus.
Extentional Database faktu datu bāze Deduktīvās datubāzes daļa, kurā
glabājas fakti.
Extentional predicate faktu datu bāzes
predikāts
Predikāts, kas izmantots faktu
definēšanā.
Fact fakts Jebkurš apgalvojums, par kuru vienmēr
var pateikt, ka tas ir patiess.
False aplams Predikāta vērtība loģiskā formulā
First Order Logic pirmās kārtas loģika Simboliskās loģikas teorija, kas formulē
kvantificētus apgalvojumus.
Horn clause Horna izteiksme Pirmās kārtas predikātu loģikā literāļu
disjunkcija kur kaut viens literālis ir
pozitīvs
Inference engine izvedumu mehānisms Problēmneatkarīga ekspertsistēmas
daļa, kas operē ar zināšanu bāzē
uzkrātajiem faktiem un formē jaunos
71
faktus.
Intensional Database zināšanu datu bāze Deduktīvās datubāzes daļa, kurā
glabājas likumi, un izvadītie fakti.
Intensional predicate zināšanu datu bāzes
predikāts
Predikāts, kas iekļauts secināšanas
likumu galvas daļās.
Literal literālis Atomārs teikums vai negatīvs atomārs
teikums.
Predicate predikāts Loģiska formula, kas sastāv no
predikāta vārda un iekavās seko termi,
kuri atdalīti ar komatu. Katra predikāta
vērtība ir vai nu patiess vai aplams.
Rule likums Loģiskā formula, kas sastāv no
predikātiem. Katra predikāta vērtība ir
vai nu patiess vai aplams.
Substitution substitūcija Saistītu mainīgo kopas piesaistīšana
termu kopai.
Term Terms Konstante vai mainīgais loģiskajā
programmēšanā.
Top-down izpildēs semantika no
augšas uz leju
Loģisko programmu izpildēs
semantika, kad sākumpunkts ir mērķis,
kas ir jāpierāda. Katrā izpildes solī
mērķis tiek aizvietots ar mērķa
apakšmērķi, kas var tikt unificēts ar
mērķi.
True Patiesība Predikāta vērtība loģiskā formulā
Unification algorithm Unifikācija Algoritms, kas ļauj noteikt to, kādas
piesaistes (substitūcijas) ir pieļaujamas
– rezultātā divi atšķirīgi teikumi, kuri
satur mainīgos, kļūst savietojami.
72
LITERATŪRAS SARAKSTS
1. Sergejevs A. Loģisko Programmēšanas Valodu Iespējas Deduktīvo Datubāzu Izstrādē
– Maģistra darbs. – RTU, 2005 – 74 lpp.
2. Voronovičs D. Deduktivās Dаtubāzes Reаlizešаnаs Vаriаntu Izpēte – Bakalaura darbs.
– RTU, 2006 – 101 lpp.
3. ANSI/ISO/IEC International Standard: Database Language – SQL / Internēts. -
ftp://ftp.iks-jena.de/pub/mitarb/lutz/standards/sql/
4. Ceri S., Gottlob G., Tanca L. Logic Programming and Databases – Springer Verlag,
1990
5. Codd E.F. A Relation Model of Data for Large Shared Data Banks - Communications
of the ACM, 1970. – Sējums 13. Numurs 6. – 377.–383. Lpp
6. Colomb R. Deductive Databases and Their Applications – CRC, 1998
7. Bocca J. EDUCE - A Marriage of Convenience: Prolog and a Relational DBS.
Proceedings Third Symposium on LogicProgramming. – Salt Lake City, 1986
8. Hinz Y. Datalog Bottom-up is the Trend in the Deductive Database Evaluation
Strategy - University of Maryland, 2002 – 18 lpp.
9. Lammel R. Artifically intelligent information systems. – Vrije Universiteit, 2004. – 7.
lpp.
10. Stanczyk S., Champion B., Leyton R. Theory and Practice of Relational Databases –
Routledge, 2001 – 264 lpp.
11. Sterling L., Shapiro E. The Art of Prolog - MIT Press, 1986
12. Ulman J.D., Garcia-Molina H., Widom J. Database Systems: The Complete Book -
Prentice Hall, 2001. – 1100 lpp.
13. Ulman J.D., Ramakrishnan R. A Survey of Research on Deductive Database Systems -
1993. – 30 lpp.
14. CitForum: Логические основы Пролога. / Internēts. -
http://citforum.oldbank.com/programming/digest/prolog/
15. ISU: Логика предикатов / Internēts. - http://www.isu.ru/~slava/do/disc/predlog.htm
16. Кайт Т. Oracle для профессионалов. – ДиаСофт, 2003 – 1265 стр.
17. Коннолли Т., Бегг К. Базы данных. Проектирование, реализация и
сопровождение. – Вильямс, 2003 - 1436 стр.
73
18. Электронная библиотека: Словарь Логики. Дизъюнкция. / Internēts. -
http://lib.walla.ru/?lib=dictionary&d=2&id=74
19. Электронная библиотека: Словарь Логики. Импликация. / Internēts. -
http://lib.walla.ru/?lib=dictionary&d=2&id=113
20. Электронная библиотека: Словарь Логики. Коньюнкция. / Internēts. -
http://lib.walla.ru/?lib=dictionary&d=2&id=151
21. Электронная библиотека: Словарь Логики. Логика отношений. / Internēts. -
http://lib.walla.ru/?lib=dictionary&d=2&id=170
22. Электронная библиотека: Словарь Логики. Отрицание. / Internēts. -
http://lib.walla.ru/?lib=dictionary&d=2&id=259
74
PIELIKUMI
75
PIELIKUMS 1
Loģiskā programma Ģimene
vīrietis(‘Jānis’).vīrietis(‘Kārlis’).vīrietis(‘Māris’).vīrietis(‘Ivars’).vīrietis(‘Pēteris’).vīrietis(‘Otis’).sieviete(‘Marta’).sieviete(‘Inga’).sieviete(‘Līga’).vecāks(‘Jānis’, ‘Kārlis’).vecāks(‘Jānis’, ‘Māris’).vecāks(‘Kārlis’, ‘Marta’).vecāks(‘Kārlis’, ‘Ivars’).vecāks(‘Māris’, ‘Inga’).vecāks(‘Māris’, ‘Līga’).vecāks(‘Marta’, ‘Otis’).vecāks(‘Inga’, ‘Pēteris’).karalis(‘Kārlis’).karalis(‘Pēteris’).spoks(‘Kārlis’).devīgs(‘Pēteris’).devīgs(‘Otis’).
pēctecis(A, B) :- vecāks(A, B).pēctecis(A, B) :- vecāks(A, Z), pēctecis(Z, B).bērns(A, B) :- vecāks(B, A).māte(A, B) :- vecāks(A, B), sieviete(A).tēvs(A, B) :- vecāks(A, B), vīrietis(A).labsirdīgs(A) :- karalis(A), devīgs(A).ļauns(A) :- karalis(A), spoks(A).
76
? pēctecis(‘Māris’, A).
77
PIELIKUMS 2
Loģiska programma Koks
nogrieznis(‘a’, ‘b’).nogrieznis(‘a’, ‘c’).nogrieznis(‘a’, ‘d’).nogrieznis(‘b’, ‘e’).nogrieznis(‘b’, ‘f’).nogrieznis(‘c’, ‘g’).nogrieznis(‘d’, ‘h’).nogrieznis(‘d’, ‘i’).
ceļš(A, B) :- nogrieznis(A, B).ceļš(A, B) :- nogrieznis(A, Z), ceļš(Z, B).
78
PIELIKUMS 3
myDDB Datalog Valodas Gramatika
Datalog likumam ir sekojoša sintakse:likums ::= galva :- ķermenis.galva ::= predikātsķermenis ::= predikāts [, ķermenis]predikāts ::= PREDIKĀTA_VĀRDS (argumentu_saraksts)argumentu_saraksts ::= arguments [, argumentu_saraksts]arguments ::= KONSTANTE | MAINĪGAIS | SKAITLISPREDIKĀTA_VāRDS ::= [‘a’..’z’]MAINĪGAIS ::= [‘A’..’Z’]KONSTANTE ::= ‘ [‘a’..’z’] | [‘A’..’Z’] ’SKAITLIS ::= [‘0’..’9’]
Datalog faktam ir sekojoša sintakse:fakts ::= PREDIKĀTA_VĀRDS (termu_saraksts).termu_saraksts ::= TERMS [,termu_saraksts]TERMS ::= KONSTANTE | SKAITLIS
Datalog mērķim ir sekojoša sintakse:goal ::= ? PREDIKĀTA_VĀRDS (argumentu_saraksts).
79
PIELIKUMS 4
myDDB iekšējo datu struktūru veidošana
myDDB sistēmu tipu izveidošanas vaicājumi:CREATE OR REPLACE TYPE TArg AS OBJECT(
Arg_ID number, Arg_Type varchar(10), Arg_Value varchar(50))
/CREATE OR REPLACE TYPE FactArgs AS TABLE OF TArg/CREATE OR REPLACE TYPE RuleArgs AS TABLE OF TArg/CREATE OR REPLACE TYPE PredicateArgs AS TABLE OF TArg/CREATE OR REPLACE TYPE DeductedArgs AS TABLE OF TArg/
myDDB datu glabāšanas struktūru izveidošanas vaicājumi:CREATE TABLE Facts(
Fact_ID number primary key, Fact_Name varchar(30), Fact_ArgCount int, Fact_Args FactArgs)
NESTED TABLE Fact_Args STORE AS FactArgs_Table/CREATE TABLE Rules(
Rule_ID number primary key, Rule_Name varchar(30), Rule_Predicates number, Rule_ArgCount int, Rule_Args RuleArgs)
NESTED TABLE Rule_Args STORE AS RuleArgs_Table /
80
CREATE TABLE Predicates( Predicate_ID number primary key, PredicateRule_ID number, Predicate_Order number, Predicate_Name varchar(30), Predicate_ArgCount int, Predicate_Args PredicateArgs)
NESTED TABLE Predicate_Args STORE AS PredicateArgs_Table /CREATE TABLE Deducted(
Deducted_ID number primary key, Deducted_Name varchar(30), Deducted_ArgCount int, Deducted_Args DeductedArgs)
NESTED TABLE Deducted_Args STORE AS DeductedArgs_Table/CREATE SEQUENCE DeductedID INCREMENT BY 1 START WITH 1 NOMAXVALUE
NOCYCLE CACHE 10/
myDDB darbības protokola glabāšanas struktūras izveidošanas vaicājumi:CREATE SEQUENCE LogID INCREMENT BY 1 START WITH 1 NOMAXVALUE
NOCYCLE CACHE 10/CREATE TABLE myDDBLog(
Log_ID number primary key, Log_Date varchar(23), Log_Text varchar(150))
/
81
PIELIKUMS 5
myDDB un Oracle Integrēšanas funkcijas
Datne myDDB_pkg.SQLcreate or replace package myddb_pkg
as
type rc is ref cursor;
procedure clear_ddb;
procedure get_fact_list( p_cursor out rc );
procedure get_fact_args( p_fact_id in number, p_cursor out rc);
procedure get_rule_list( p_cursor out rc );
procedure get_rule_args( p_rule_id in number, p_cursor out rc);
procedure get_predicate( p_rule_id in number, p_predicate_order in number, p_cursor out
rc );
procedure get_predicate_args( p_rule_id in number, p_predicate_id in number, p_cursor
out rc);
procedure get_deducted_list( p_cursor out rc );
procedure get_deducted_args( p_deducted_id in number, p_cursor out rc);
procedure get_fact_count (p_count out number);
procedure is_fact(p_name in varchar, p_count out number);
procedure get_rule_count (p_count out number);
procedure get_deducted_count (p_count out number);
procedure get_sys_log( p_cursor out rc );
procedure set_sys_log(p_time in varchar, p_info in varchar);
procedure check_get_fact_args(p_name in varchar, p_count in number, p_cursor out rc);
procedure check_get_deducted_args(p_name in varchar, p_count in number, p_cursor out
rc);
procedure get_fact_id(p_name in varchar, p_count in number, p_cursor out rc);
procedure get_rule_id(p_name in varchar, p_count in number, p_cursor out rc);
procedure get_rule(p_id in number, p_cursor out rc );
end;
82
Datne myDDB_pkg_body.SQLcreate or replace package body myddb_pkg
as
procedure clear_ddb
is
begin
DELETE FROM FACTS;
DELETE FROM RULES;
DELETE FROM PREDICATES;
DELETE FROM DEDUCTED;
end;
procedure get_fact_list( p_cursor out rc )
is
begin
open p_cursor for
SELECT F.Fact_Name, F.Fact_ID, F.Fact_ArgCount
FROM Facts F
ORDER BY F.Fact_Name, F.Fact_ID;
end;
procedure get_fact_args( p_fact_id in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT A.Arg_Type, A.Arg_Value
FROM Facts F, table(F.Fact_Args) (+) A
WHERE F.Fact_ID = p_fact_id;
end;
procedure get_rule_list( p_cursor out rc )
is
begin
open p_cursor for
SELECT R.Rule_Name, R.Rule_ID, R.Rule_Predicates, R.Rule_ArgCount
FROM Rules R
ORDER BY R.Rule_Name, R.Rule_ID;
end;
procedure get_rule_args( p_rule_id in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT A.Arg_Value, A.Arg_Type
FROM Rules R, table(R.Rule_Args) (+) A
WHERE R.Rule_ID = p_rule_id;
end;
83
procedure get_predicate( p_rule_id in number, p_predicate_order in number, p_cursor out
rc )
is
begin
open p_cursor for
SELECT P.Predicate_Name, P.Predicate_ID, P.Predicate_ArgCount
FROM Predicates P
WHERE P.PredicateRule_ID = p_rule_id AND P.Predicate_Order =
p_predicate_order;
end;
procedure get_predicate_args( p_rule_id in number, p_predicate_id in number, p_cursor
out rc)
is
begin
open p_cursor for
SELECT A.Arg_Value, A.Arg_Type
FROM Predicates P, table(P.Predicate_Args) (+) A
WHERE P.Predicate_ID = p_predicate_id AND P.PredicateRule_ID = p_rule_id;
end;
procedure get_deducted_list( p_cursor out rc )
is
begin
open p_cursor for
SELECT D.Deducted_Name, D.Deducted_ID, D.Deducted_ArgCount
FROM Deducted D
ORDER BY D.Deducted_Name, D.Deducted_ID;
end;
procedure get_deducted_args( p_deducted_id in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT A.Arg_Value, A.Arg_Type
FROM Deducted D, table(D.Deducted_Args) (+) A
WHERE D.Deducted_ID = p_deducted_id;
end;
procedure get_fact_count (p_count out number)
is
begin
SELECT COUNT(Fact_ID) INTO p_count
FROM Facts;
end;
procedure is_fact(p_name in varchar, p_count out number)
is
begin
SELECT COUNT(Fact_ID) INTO p_count
FROM Facts
84
WHERE Fact_Name= p_name;
end;
procedure get_rule_count (p_count out number)
is
begin
SELECT COUNT(Rule_ID) INTO p_count
FROM Rules;
end;
procedure get_deducted_count (p_count out number)
is
begin
SELECT COUNT(Deducted_ID) INTO p_count
FROM Deducted;
end;
procedure get_sys_log( p_cursor out rc )
is
begin
open p_cursor for
SELECT L.Log_Date, L.Log_text
FROM myDDBLog L;
end;
procedure set_sys_log(p_time in varchar, p_info in varchar)
is
begin
INSERT INTO myDDBLog VALUES(LogID.NEXTVAL, p_time, p_info);
end;
procedure check_get_fact_args(p_name in varchar, p_count in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT A.Arg_Type, A.Arg_Value
FROM Facts F, table(F.Fact_Args) (+) A
WHERE F.Fact_ID IN (
SELECT F2.Fact_ID
FROM Facts F2
WHERE F2.Fact_Name= p_name
AND F2.Fact_ArgCount= p_count);
end;
procedure check_get_deducted_args(p_name in varchar, p_count in number, p_cursor out
rc)
is
begin
open p_cursor for
SELECT A.Arg_Type, A.Arg_Value
FROM Deducted D, table(D.Deducted_Args) (+) A
WHERE D.Deducted_ID IN (
85
SELECT D2.Deducted_ID
FROM Deducted D2
WHERE D2.Deducted_Name= p_name
AND D2.Deducted_ArgCount= p_count);
end;
procedure get_fact_id(p_name in varchar, p_count in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT F.Fact_ID
FROM Facts F
WHERE F.Fact_Name= p_name
AND F.Fact_ArgCount= p_count;
end;
procedure get_rule_id(p_name in varchar, p_count in number, p_cursor out rc)
is
begin
open p_cursor for
SELECT R.Rule_ID
FROM Rules R
WHERE R.Rule_Name= p_name AND R.Rule_ArgCount= p_count
ORDER BY R.Rule_Predicates;
end;
procedure get_rule(p_id in number, p_cursor out rc )
is
begin
open p_cursor for
SELECT R.Rule_Name, R.Rule_Predicates, R.Rule_ArgCount
FROM Rules R
WHERE R.Rule_ID = p_id;
end;
end;
86
PIELIKUMS 6
myDDB Programmatūras Pirmteksts
Datne ddbIO.javapackage myDDBPackage;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.pool.OracleDataSource;
public class ddbIO {
private String DriverType;
private String NetworkProtocol;
private int PortNumber;
private String DatabaseName;
private String ServerName;
private String DBUser;
private String DBPassword;
private String SystemError;
private OracleDataSource ods;
protected Connection myDDBConnection;
protected Statement myStatement;
protected int QueryCount;
protected static int MaxPredicateNameLen = 30;
protected static int MaxArgumentNameLen = 30;
protected static int MaxPredicates = 5;
protected static int MaxArguments = 5;
protected static String VARIABLE = "variable";
protected static String STRING = "string";
protected static String NUMBER = "number";
public ddbIO() {
this.DriverType = "thin";
this.ServerName = "localhost";
this.NetworkProtocol = "tcp";
this.PortNumber = 1521;
this.DatabaseName = "XE";
this.DBUser = "sql_user";
this.DBPassword = "sql_pass";
this.QueryCount = 0;
this.SystemError = "";
}
public void SetServerName(String sName) {
this.ServerName = sName;
87
}
public void SetDBUser(String sUser) {
this.DBUser = sUser;
}
public void SetDBPassword(String sPass) {
this.DBPassword = sPass;
}
public String GetServerName() {
return this.ServerName;
}
public String GetDBUser() {
return this.DBUser;
}
public String GetDBPassword() {
return this.DBPassword;
}
public boolean OpenConnection() {
try {
SysErrorClear();
ods = new OracleDataSource();
ods.setDriverType(this.DriverType);
ods.setServerName(this.ServerName);
ods.setNetworkProtocol(this.NetworkProtocol);
ods.setDatabaseName(this.DatabaseName);
ods.setPortNumber(this.PortNumber);
ods.setUser(this.DBUser);
ods.setPassword(this.DBPassword);
this.myDDBConnection = ods.getConnection();
this.myStatement = this.myDDBConnection.createStatement();
return true;
} catch (SQLException e) {
SysError("OpenConnection()", e.getMessage());
return false;
}
}
public boolean CloseConnection() {
try {
SysErrorClear();
this.myDDBConnection.close();
this.ods.close();
return true;
} catch (SQLException e) {
SysError("CloseConnection()", e.getMessage());
return false;
}
}
88
protected void SysError(String fName, String sError) {
SystemError += "Kluda " + fName + ": " + sError + "\n";
}
public String GetSysError() {
return SystemError;
}
protected void SysErrorClear() {
SystemError = "";
}
protected boolean SysExecute(String sqlStatement) {
try {
myStatement.executeUpdate(sqlStatement);
this.QueryCount++;
return true;
} catch (SQLException e) {
SysError("SysExecute(String sqlStatement)", e.getMessage());
return false;
}
}
public void SysClearDDB() {
try {
SysErrorClear();
CallableStatement proc = myDDBConnection.prepareCall("{ call
myddb_pkg.clear_ddb() }");
proc.execute();
} catch (SQLException e) {
SysError("SysClearDDB()", e.getMessage());
}
}
public void SysInitDDB() {
SysErrorClear();
SysExecute("DROP SEQUENCE LogID");
SysExecute("DROP TABLE myDDBLog");
SysExecute("DROP TABLE Facts");
SysExecute("DROP TABLE Rules");
SysExecute("DROP TABLE Predicates");
SysExecute("DROP TABLE Deducted");
SysExecute("DROP TYPE DeductedArgs");
SysExecute("DROP TYPE PredicateArgs");
SysExecute("DROP TYPE RuleArgs");
SysExecute("DROP TYPE FactArgs");
SysExecute("DROP TYPE TArg");
SysExecute("CREATE SEQUENCE LogID INCREMENT BY 1 START WITH 1 NOMAXVALUE NOCYCLE
CACHE 10");
SysExecute("CREATE TABLE myDDBLog( " +
"Log_ID number primary key, " +
"Log_Date varchar(23), " +
"Log_Text varchar(150))");
SysExecute("CREATE OR REPLACE TYPE TArg AS OBJECT( " +
"Arg_ID number, " +
89
"Arg_Type varchar(10), " +
"Arg_Value varchar(" + MaxArgumentNameLen + "))");
SysExecute("CREATE OR REPLACE TYPE FactArgs AS TABLE OF TArg");
SysExecute("CREATE OR REPLACE TYPE RuleArgs AS TABLE OF TArg");
SysExecute("CREATE OR REPLACE TYPE PredicateArgs AS TABLE OF TArg");
SysExecute("CREATE OR REPLACE TYPE DeductedArgs AS TABLE OF TArg");
SysExecute("CREATE TABLE Facts(" +
"Fact_ID number primary key, " +
"Fact_Name varchar(" + MaxPredicateNameLen + "), " +
"Fact_ArgCount int, " +
"Fact_Args FactArgs) " +
"NESTED TABLE Fact_Args STORE AS FactArgs_Table");
SysExecute("CREATE TABLE Rules( " +
"Rule_ID number primary key, " +
"Rule_Name varchar(" + MaxPredicateNameLen + "), " +
"Rule_Predicates number, " +
"Rule_ArgCount int, " +
"Rule_Args RuleArgs) " +
"NESTED TABLE Rule_Args STORE AS RuleArgs_Table ");
SysExecute("CREATE TABLE Predicates( " +
"Predicate_ID number primary key, " +
"PredicateRule_ID number, " +
"Predicate_Order number, " +
"Predicate_Name varchar(" + MaxPredicateNameLen + "), " +
"Predicate_ArgCount int, " +
"Predicate_Args PredicateArgs) " +
"NESTED TABLE Predicate_Args STORE AS PredicateArgs_Table ");
SysExecute("CREATE TABLE Deducted( " +
"Deducted_ID number primary key, " +
"Deducted_Name varchar(" + MaxPredicateNameLen + "), " +
"Deducted_ArgCount int, " +
"Deducted_Args DeductedArgs) " +
"NESTED TABLE Deducted_Args STORE AS DeductedArgs_Table");
}
}
Datne ddbLog.javapackage myDDBPackage;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
public class ddbLog extends ddbIO {
protected void SysLog(String sLog) {
90
try {
Timestamp t =
new Timestamp(Calendar.getInstance().getTimeInMillis());
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.set_sys_log(?, ?) }" );
cstmt.setString(1,t.toString());
cstmt.setString(2,sLog);
cstmt.execute();
this.QueryCount++;
} catch (SQLException e) {
SysError("SysLog(String sLog)", e.getMessage());
}
}
public String[] GetSysLog() {
String [] SysLog = new String[150];
try {
SysErrorClear();
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_sys_log(?) }" );
cstmt.registerOutParameter(1,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(1);
this.QueryCount++;
int LogItem = 1;
while (rset.next()) {
SysLog[LogItem++] = rset.getString(1) + ": " + rset.getString(2) + "\n";
}
rset.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetSysLog()", e.getMessage());
}
return SysLog;
}
}
Datne ddbInterface.javapackage myDDBPackage;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
public class ddbInterface extends ddbLog {
protected int RuleCount;
protected int FactCount;
protected int DeductedCount;
91
public ddbInterface() {
this.RuleCount = 0;
this.FactCount = 0;
this.DeductedCount = 0;
}
public String[] GetFactList() {
String[] aFactList = new String[30];
try {
SysErrorClear();
int listRow = 0;
String sFact;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_list(?) }" );
cstmt.registerOutParameter(1,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(1);
this.QueryCount++;
while (rset.next()) {
String FactName = rset.getString(1);
int FactID = rset.getInt(2);
int FactArgCount = rset.getInt(3);
sFact = FactName;
sFact += GetFactArgs(FactID, FactArgCount);
aFactList[listRow++] = sFact;
}
rset.close();
cstmt.close();
SysLog("Izveidots Faktu Saraksts");
} catch (SQLException e) {
SysError("GetFactList()", e.getMessage());
}
return aFactList;
}
private String GetFactArgs(int ID, int ArgCount) {
String sFactArguments = "(";
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_args(?, ?) }" );
cstmt.setInt(1,ID);
cstmt.registerOutParameter(2,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetArgs = (ResultSet)cstmt.getObject(2);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rsetArgs.next();
92
String sFactType = rsetArgs.getString(1);
if (sFactType.equals(STRING)) {
sFactArguments += "'" + rsetArgs.getString(2) + "'";
} else {
sFactArguments += rsetArgs.getString(2);
}
if (i < ArgCount - 1)
sFactArguments += ", ";
}
rsetArgs.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetFactArgs(int ID, int ArgCount)", e.getMessage());
}
sFactArguments += ").";
return sFactArguments;
}
public String[] GetRuleList() {
String[] aRuleList = new String[30];
try {
SysErrorClear();
int listRow = 0;
String sRule;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule_list(?) }" );
cstmt.registerOutParameter(1,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(1);
this.QueryCount++;
while (rset.next()) {
sRule = rset.getString(1);
int RuleID = rset.getInt(2);
int PredicatesCount = rset.getInt(3);
int RuleArgCount = rset.getInt(4);
sRule += GetRuleArgs(RuleID, RuleArgCount);
aRuleList[listRow++] = sRule;
for (int i = 1; i <= PredicatesCount; i++) {
String sPredicate =
" " + GetPredicate(RuleID, i);
if (i < PredicatesCount)
sPredicate += ",";
else
sPredicate += ".";
aRuleList[listRow++] = sPredicate;
}
}
rset.close();
cstmt.close();
SysLog("Izveidots Likumu Saraksts");
93
} catch (SQLException e) {
SysError("GetRuleList()", e.getMessage());
}
return aRuleList;
}
private String GetRuleArgs(int ID, int ArgCount) {
String sRuleArgs = "(";
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule_args(?, ?) }" );
cstmt.setInt(1,ID);
cstmt.registerOutParameter(2,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetArgs = (ResultSet)cstmt.getObject(2);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rsetArgs.next();
sRuleArgs += rsetArgs.getString(1);
if (i < ArgCount - 1)
sRuleArgs += ", ";
}
rsetArgs.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetRuleArgs(int ID, int ArgCount)", e.getMessage());
}
sRuleArgs += ") :- ";
return sRuleArgs;
}
private String GetPredicate(int RuleID, int order) {
String sPredicate = "";
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate(?, ?, ?) }" );
cstmt.setInt(1,RuleID);
cstmt.setInt(2,order);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(3);
this.QueryCount++;
rset.next();
String PredicateName = rset.getString(1);
int PredicateID = rset.getInt(2);
int PredicateArgCount = rset.getInt(3);
sPredicate = PredicateName;
sPredicate += GetPredicateArgs(PredicateID, PredicateArgCount, RuleID);
94
rset.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetPredicate(int RuleID, int order)", e.getMessage());
}
return sPredicate;
}
private String GetPredicateArgs(int PredicateID, int ArgCount, int RuleID) {
String sPredicateArgs = "(";
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate_args(?, ?, ?) }" );
cstmt.setInt(1,RuleID);
cstmt.setInt(2,PredicateID);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(3);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rset.next();
sPredicateArgs += rset.getString(1);
if (i < ArgCount - 1)
sPredicateArgs += ", ";
}
rset.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetPredicateArgs(int PredicateID, int ArgCount, int RuleID)",
e.getMessage());
}
sPredicateArgs += ")";
return sPredicateArgs;
}
public String[] GetDeductedList() {
String[] aDeductedList = new String[30];
try {
SysErrorClear();
int listRow = 0;
String sDeducted;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_deducted_list(?) }" );
cstmt.registerOutParameter(1,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rset = (ResultSet)cstmt.getObject(1);
this.QueryCount++;
while (rset.next()) {
String DeductedName = rset.getString(1);
int DeductedID = rset.getInt(2);
95
int DeductedArgCount = rset.getInt(3);
sDeducted = DeductedName;
sDeducted += GetDeductedArgs(DeductedID, DeductedArgCount);
aDeductedList[listRow++] = sDeducted;
}
rset.close();
cstmt.close();
SysLog("Izveidots Izvadito Faktu Saraksts");
} catch (SQLException e) {
SysError("GetDeductedList()", e.getMessage());
}
return aDeductedList;
}
private String GetDeductedArgs(int ID, int ArgCount) {
String sDeductedArgs = "(";
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_deducted_args(?, ?) }" );
cstmt.setInt(1,ID);
cstmt.registerOutParameter(2,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetArgs = (ResultSet)cstmt.getObject(2);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rsetArgs.next();
String sDeductedType = rsetArgs.getString(2);
if (sDeductedType.equals(STRING)) {
sDeductedArgs += "'" + rsetArgs.getString(1) + "'";
} else {
sDeductedArgs += rsetArgs.getString(1);
}
if (i < ArgCount - 1) sDeductedArgs += ", ";
}
rsetArgs.close();
cstmt.close();
} catch (SQLException e) {
SysError("GetDeductedArgs(int ID, int ArgCount)", e.getMessage());
}
sDeductedArgs += ").";
return sDeductedArgs;
}
private void GetDeductedCount() {
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_deducted_count(?) }" );
cstmt.registerOutParameter(1,OracleTypes.NUMBER);
cstmt.execute();
this.QueryCount++;
96
DeductedCount = cstmt.getInt(1);
cstmt.close();
} catch (SQLException e) {
SysError("GetDeductedCount()", e.getMessage());
}
}
private void GetFactCount() {
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_count(?) }" );
cstmt.registerOutParameter(1,OracleTypes.NUMBER);
cstmt.execute();
this.QueryCount++;
FactCount = cstmt.getInt(1);
cstmt.close();
} catch (SQLException e) {
SysError("GetFactCount()", e.getMessage());
}
}
private void GetRuleCount() {
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule_count(?) }" );
cstmt.registerOutParameter(1,OracleTypes.NUMBER);
cstmt.execute();
this.QueryCount++;
RuleCount = cstmt.getInt(1);
cstmt.close();
} catch (SQLException e) {
SysError("GetRuleCount()", e.getMessage());
}
}
public String GetStats() {
String Stats;
GetFactCount();
GetRuleCount();
GetDeductedCount();
Stats = "Fakti: " + this.FactCount + " ";
Stats += "Likumi: " + this.RuleCount + " ";
Stats += "Izvaditie Fakti: " + this.DeductedCount + " ";
Stats += "Vaicajumi: " + this.QueryCount;
return Stats;
}
public String [] GetSampleFamilyDatalog() {
String [] data = new String[33];
int i = 1;
data[i++] = "virietis('Janis').";
data[i++] = "virietis('Karlis').";
97
data[i++] = "virietis('Maris').";
data[i++] = "virietis('Ivars').";
data[i++] = "virietis('Peteris').";
data[i++] = "virietis('Otis').";
data[i++] = "sieviete('Marta').";
data[i++] = "sieviete('Inga').";
data[i++] = "sieviete('Liga').";
data[i++] = "vecaks('Janis', 'Karlis').";
data[i++] = "vecaks('Janis', 'Maris').";
data[i++] = "vecaks('Karlis', 'Marta').";
data[i++] = "vecaks('Karlis', 'Ivars').";
data[i++] = "vecaks('Maris', 'Inga').";
data[i++] = "vecaks('Maris', 'Liga').";
data[i++] = "vecaks('Marta', 'Otis').";
data[i++] = "vecaks('Inga', 'Peteris').";
data[i++] = "karalis('Karlis').";
data[i++] = "karalis('Peteris').";
data[i++] = "spoks('Karlis').";
data[i++] = "devigs('Peteris').";
data[i++] = "devigs('Otis').";
data[i++] = "";
data[i++] = "pectecis(A, B) :- vecaks(A, B).";
data[i++] = "pectecis(A, B) :- vecaks(A, Z), pectecis(Z, B).";
data[i++] = "berns(A, B) :- vecaks(B, A).";
data[i++] = "mate(A, B) :- vecaks(A, B), sieviete(A).";
data[i++] = "tevs(A, B) :- vecaks(A, B), virietis(A).";
data[i++] = "labsirdigs(A) :- karalis(A), devigs(A).";
data[i++] = "launs(A) :- karalis(A), spoks(A).";
data[i++] = "";
data[i++] = "? mate(B, A).";
SysLog("Izveidota Logiska Programma Gimene");
return data;
}
public String[] GetSampleTreeDatalog() {
String[] data = new String[14];
int i = 1;
data[i++] = "nogrieznis('a', 'b').";
data[i++] = "nogrieznis('a', 'c').";
data[i++] = "nogrieznis('a', 'd').";
data[i++] = "nogrieznis('b', 'e').";
data[i++] = "nogrieznis('b', 'f').";
data[i++] = "nogrieznis('c', 'g').";
data[i++] = "nogrieznis('d', 'h').";
data[i++] = "nogrieznis('d', 'i').";
data[i++] = "";
data[i++] = "cels(A, B) :- nogrieznis(A, B).";
data[i++] = "cels(A, B) :- nogrieznis(A, Z), cels(Z, B).";
data[i++] = "";
data[i++] = "? cels(A, B).";
SysLog("Izveidota Logiska Programma Koks");
98
return data;
}
}
Datne ddbDeduction.javapackage myDDBPackage;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
public class ddbDeduction extends ddbInterface {
public boolean ExecuteGoal(String Goal, int ArgCount, Object [][] Args) {
if (isFact(Goal)) {
if (ExecuteFact(Goal, ArgCount, Args)) return true;
else return false;
} else {
ExecuteRule(Goal, ArgCount, Args);
}
return true;
}
protected boolean ExecuteRule(String Goal, int ArgCount, Object [][] Args) {
try {
int RuleID;
OracleCallableStatement cstmtIDs =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule_id(?, ?, ?) }" );
cstmtIDs.setString(1,Goal);
cstmtIDs.setInt(2,ArgCount);
cstmtIDs.registerOutParameter(3,OracleTypes.CURSOR);
cstmtIDs.execute();
ResultSet rsetIDs = (ResultSet)cstmtIDs.getObject(3);
this.QueryCount++;
while (rsetIDs.next()) {
RuleID = rsetIDs.getInt(1);
PreparePredicates(RuleID);
OracleCallableStatement cstmtRuleArgs =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule_args(?, ?) }" );
cstmtRuleArgs.setInt(1,RuleID);
cstmtRuleArgs.registerOutParameter(2,OracleTypes.CURSOR);
cstmtRuleArgs.execute();
ResultSet rsetRuleArgs = (ResultSet)cstmtRuleArgs.getObject(2);
this.QueryCount++;
Object[][] RuleArgs = new Object[ArgCount][2];
int RuleArgumentCount = 0;
99
while (rsetRuleArgs.next()) {
RuleArgs[RuleArgumentCount][0] = rsetRuleArgs.getString(2);
RuleArgs[RuleArgumentCount][1] = rsetRuleArgs.getString(1);
RuleArgumentCount++;
}
rsetRuleArgs.close();
cstmtRuleArgs.close();
OracleCallableStatement cstmtPredicate1 =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate(?, ?, ?) }" );
cstmtPredicate1.setInt(1,RuleID);
cstmtPredicate1.setInt(2,1);
cstmtPredicate1.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicate1.execute();
ResultSet rsetPredicate1 = (ResultSet)cstmtPredicate1.getObject(3);
this.QueryCount++;
rsetPredicate1.next();
int Predicate1ID = rsetPredicate1.getInt(2);
String Predicate1Name = rsetPredicate1.getString(1);
int Predicate1ArgCount = rsetPredicate1.getInt(3);
rsetPredicate1.close();
cstmtPredicate1.close();
OracleCallableStatement cstmtPredicate1Args =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate_args(?, ?, ?) }" );
cstmtPredicate1Args.setInt(1,RuleID);
cstmtPredicate1Args.setInt(2,Predicate1ID);
cstmtPredicate1Args.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicate1Args.execute();
ResultSet rsetPredicate1Args = (ResultSet)cstmtPredicate1Args.getObject(3);
this.QueryCount++;
int Predicate1ArgumentCount = 0;
Object[][] Predicate1Args = new Object[ArgCount][2];
while (rsetPredicate1Args.next()) {
Predicate1Args[Predicate1ArgumentCount][0] =
rsetPredicate1Args.getString(2);
Predicate1Args[Predicate1ArgumentCount][1] =
rsetPredicate1Args.getString(1);
Predicate1ArgumentCount++;
}
rsetPredicate1Args.close();
cstmtPredicate1Args.close();
OracleCallableStatement cstmtPredicate2 =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate(?, ?, ?) }" );
cstmtPredicate2.setInt(1,RuleID);
100
cstmtPredicate2.setInt(2,2);
cstmtPredicate2.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicate2.execute();
ResultSet rsetPredicate2 = (ResultSet)cstmtPredicate2.getObject(3);
this.QueryCount++;
rsetPredicate2.next();
int Predicate2ID = rsetPredicate2.getInt(2);
String Predicate2Name = rsetPredicate2.getString(1);
int Predicate2ArgCount = rsetPredicate2.getInt(3);
rsetPredicate2.close();
cstmtPredicate2.close();
OracleCallableStatement cstmtPredicate2Args =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate_args(?, ?, ?) }" );
cstmtPredicate2Args.setInt(1,RuleID);
cstmtPredicate2Args.setInt(2,Predicate2ID);
cstmtPredicate2Args.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicate2Args.execute();
ResultSet rsetPredicate2Args = (ResultSet)cstmtPredicate2Args.getObject(3);
this.QueryCount++;
int Predicate2ArgumentCount = 0;
Object[][] Predicate2Args = new Object[ArgCount][2];
while (rsetPredicate2Args.next()) {
Predicate2Args[Predicate2ArgumentCount][0] =
rsetPredicate2Args.getString(2);
Predicate2Args[Predicate2ArgumentCount][1] =
rsetPredicate2Args.getString(1);
Predicate2ArgumentCount++;
}
rsetPredicate2Args.close();
cstmtPredicate2Args.close();
int i, j;
int Terms1 [] = new int[5];
for (i = 0; i < ArgCount; i++) {
for (j = 0; j < ArgCount; j++) {
if (RuleArgs[i][1].equals(Predicate1Args[j][1])) Terms1[i] = j;
}
}
int Terms2 [] = new int[5];
for (i = 0; i < ArgCount; i++) {
for (j = 0; j < ArgCount; j++) {
if (RuleArgs[i][1].equals(Predicate1Args[j][1])) Terms2[i] = j;
}
}
Object[][] NewArgs = new Object[ArgCount][2];
for (i = 0; i < ArgCount; i++) {
101
NewArgs[i][0] = Args[Terms1[i]][0];
NewArgs[i][1] = Args[Terms1[i]][1];
}
ExecuteDeductedFact(Predicate1Name, Goal, Predicate1ArgCount, NewArgs);
}
rsetIDs.close();
cstmtIDs.close();
return true;
} catch (SQLException e) {
SysError("ExecuteGroundRule(String Goal, int ArgCount, Object [][] Args)",
e.getMessage());
return false;
}
}
protected void PreparePredicates(int RuleID) {
try {
OracleCallableStatement cstmtRule =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_rule(?, ?) }" );
cstmtRule.setInt(1, RuleID);
cstmtRule.registerOutParameter(2,OracleTypes.CURSOR);
cstmtRule.execute();
ResultSet rsetRule = (ResultSet)cstmtRule.getObject(2);
this.QueryCount++;
rsetRule.next();
String RuleName = rsetRule.getString(1);
int Count = rsetRule.getInt(2);
for (int i = 1; i <= Count; i++) {
OracleCallableStatement cstmtPredicate =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate(?, ?, ?) }" );
cstmtPredicate.setInt(1,RuleID);
cstmtPredicate.setInt(2,i);
cstmtPredicate.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicate.execute();
ResultSet rsetPredicate = (ResultSet)cstmtPredicate.getObject(3);
this.QueryCount++;
rsetPredicate.next();
int PredicateID = rsetPredicate.getInt(2);
String PredicateName = rsetPredicate.getString(1);
if (PredicateName.equals(RuleName)) continue;
int PredicateArgCount = rsetPredicate.getInt(3);
rsetPredicate.close();
cstmtPredicate.close();
OracleCallableStatement cstmtPredicateArgs =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_predicate_args(?, ?, ?) }" );
102
cstmtPredicateArgs.setInt(1,RuleID);
cstmtPredicateArgs.setInt(2,PredicateID);
cstmtPredicateArgs.registerOutParameter(3,OracleTypes.CURSOR);
cstmtPredicateArgs.execute();
ResultSet rsetPredicateArgs = (ResultSet)cstmtPredicateArgs.getObject(3);
this.QueryCount++;
int PredicateArgumentCount = 0;
Object[][] PredicateArgs = new Object[PredicateArgCount][2];
while (rsetPredicateArgs.next()) {
PredicateArgs[PredicateArgumentCount][0] =
rsetPredicateArgs.getString(2);
PredicateArgs[PredicateArgumentCount][1] =
rsetPredicateArgs.getString(1);
PredicateArgumentCount++;
}
rsetPredicateArgs.close();
cstmtPredicateArgs.close();
ExecuteFact(PredicateName, PredicateArgCount, PredicateArgs);
}
rsetRule.close();
cstmtRule.close();
} catch (SQLException e) {
SysError("PreparePredicates(int RuleID)", e.getMessage());
}
}
protected boolean ExecuteDeductedFact(String Goal, String Target, int ArgCount, Object
[][] Args) {
try {
boolean executedFact = false;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_id(?, ?, ?) }" );
cstmt.setString(1,Goal);
cstmt.setInt(2,ArgCount);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetIDs = (ResultSet)cstmt.getObject(3);
this.QueryCount++;
while (rsetIDs.next()) {
int FactID = rsetIDs.getInt(1);
Object [][] NewArgs = new Object [ArgCount][2];
boolean foundFact = true;
OracleCallableStatement cstmtArgs =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_args(?, ?) }" );
cstmtArgs.setInt(1,FactID);
cstmtArgs.registerOutParameter(2,OracleTypes.CURSOR);
103
cstmtArgs.execute();
ResultSet rsetArgs = (ResultSet)cstmtArgs.getObject(2);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rsetArgs.next();
String sFactArgType = rsetArgs.getString(1);
NewArgs[i][0] = sFactArgType;
String sFactArgValue = rsetArgs.getString(2);
NewArgs[i][1] = sFactArgValue;
if (!Args[i][0].equals("variable")) {
if (!sFactArgType.equals(Args[i][0])) foundFact = false;
if (!sFactArgValue.equals(Args[i][1])) foundFact = false;
}
}
if (foundFact) {
if (CheckForNewDeductedFact(Target, ArgCount, NewArgs)) {
InsertDeductedFact(Target, ArgCount, NewArgs);
}
}
rsetArgs.close();
cstmtArgs.close();
executedFact = true;
}
rsetIDs.close();
cstmt.close();
return executedFact;
} catch (SQLException e) {
SysError("ExecuteFact(String Goal, int ArgCount, Object [][] Args)",
e.getMessage());
return false;
}
}
protected boolean ExecuteFact(String Goal, int ArgCount, Object [][] Args) {
try {
boolean executedFact = false;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_id(?, ?, ?) }" );
cstmt.setString(1,Goal);
cstmt.setInt(2,ArgCount);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetIDs = (ResultSet)cstmt.getObject(3);
this.QueryCount++;
while (rsetIDs.next()) {
int FactID = rsetIDs.getInt(1);
Object [][] NewArgs = new Object [ArgCount][2];
boolean foundFact = true;
OracleCallableStatement cstmtArgs =
104
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.get_fact_args(?, ?) }" );
cstmtArgs.setInt(1,FactID);
cstmtArgs.registerOutParameter(2,OracleTypes.CURSOR);
cstmtArgs.execute();
ResultSet rsetArgs = (ResultSet)cstmtArgs.getObject(2);
this.QueryCount++;
for (int i = 0; i < ArgCount; i++) {
rsetArgs.next();
String sFactArgType = rsetArgs.getString(1);
NewArgs[i][0] = sFactArgType;
String sFactArgValue = rsetArgs.getString(2);
NewArgs[i][1] = sFactArgValue;
if (!Args[i][0].equals("variable")) {
if (!sFactArgType.equals(Args[i][0])) foundFact = false;
if (!sFactArgValue.equals(Args[i][1])) foundFact = false;
}
}
if (foundFact) {
if (CheckForNewDeductedFact(Goal, ArgCount, NewArgs)) {
InsertDeductedFact(Goal, ArgCount, NewArgs);
}
}
rsetArgs.close();
cstmtArgs.close();
executedFact = true;
}
rsetIDs.close();
cstmt.close();
return executedFact;
} catch (SQLException e) {
SysError("ExecuteFact(String Goal, int ArgCount, Object [][] Args)",
e.getMessage());
return false;
}
}
protected boolean CheckForNewDeductedFact(String Fact, int ArgCount, Object [][] Args) {
try {
boolean newArgs = true;
boolean firstFact = true;
Object [][] DeductedArgs = new Object [1000][2];
int DeductedArgsCount = 0;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.check_get_deducted_args(?, ?, ?) }" );
cstmt.setString(1,Fact);
cstmt.setInt(2,ArgCount);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetArgs = (ResultSet)cstmt.getObject(3);
105
this.QueryCount++;
while (rsetArgs.next()) {
DeductedArgs[DeductedArgsCount][0] = rsetArgs.getString(1);
DeductedArgs[DeductedArgsCount][1] = rsetArgs.getString(2);
DeductedArgsCount++;
if (firstFact) firstFact = false;
}
rsetArgs.close();
cstmt.close();
if (ArgCount == 1) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1]))
) newArgs = false;
}
} else if (ArgCount == 2) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1]))
) newArgs = false;
}
} else if (ArgCount == 3) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1])) &&
(DeductedArgs[i+2][0].equals(Args[2][0])) &&
(DeductedArgs[i+2][1].equals(Args[2][1]))
) newArgs = false;
}
} else if (ArgCount == 4) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1])) &&
(DeductedArgs[i+2][0].equals(Args[2][0])) &&
(DeductedArgs[i+2][1].equals(Args[2][1])) &&
(DeductedArgs[i+3][0].equals(Args[3][0])) &&
(DeductedArgs[i+3][1].equals(Args[3][1]))
) newArgs = false;
}
}
if (firstFact) return true;
return newArgs;
} catch (SQLException e) {
106
SysError("CheckForNewFact(String Fact, int ArgCount, Object [][] Args)",
e.getMessage());
return false;
}
}
protected void InsertDeductedFact(String Fact, int ArgCount, Object [][] Args) {
int i;
String sNewFactArgs = "";
DeductedCount++;
for (i = 0; i < ArgCount; i++) {
if ((ArgCount > 1) && (i > 0)) sNewFactArgs += "), TArg(";
sNewFactArgs += "'" + (i+1) + "', '" + Args[i][0] + "', '" + Args[i][1] + "' ";
}
String sqlInsertDeducted =
"INSERT INTO Deducted VALUES ('" + DeductedCount + "', '" +
Fact + "', '" + ArgCount + "', DeductedArgs(TArg(" + sNewFactArgs + ")))";
SysExecute(sqlInsertDeducted);
}
protected boolean isFact(String Predicate) {
try {
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.is_fact(?, ?) }" );
cstmt.setString(1,Predicate);
cstmt.registerOutParameter(2,OracleTypes.NUMBER);
cstmt.execute();
this.QueryCount++;
int Count = cstmt.getInt(2);
cstmt.close();
this.QueryCount++;
if (Count > 0) return true;
else return false;
} catch (SQLException e) {
SysError("isFact(String Predicate)", e.getMessage());
return false;
}
}
protected boolean isGroundRule(String Predicate) {
try {
String sqlFactCount = "SELECT COUNT(Fact_ID) " +
"FROM Facts " +
"WHERE Fact_Name='" + Predicate + "'";
ResultSet rset = myStatement.executeQuery(sqlFactCount);
this.QueryCount++;
rset.next();
FactCount = rset.getInt(1);
rset.close();
if (FactCount > 0) return true;
else return false;
} catch (SQLException e) {
107
SysError("isGroundRule(String Predicate)", e.getMessage());
return false;
}
}
}
Datne ddbMain.javapackage myDDBPackage;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;
public class ddbMain extends ddbDeduction {
public boolean Datalog(String Input) {
String[] DatalogCommands = new String[100];
char[] inputChars = Input.toCharArray();
char[] outputChars = new char[2000];
int inputLen = inputChars.length;
int outputLen = 0;
int DatalogCommandCount = 0;
int QueryID = 0;
boolean foundQuery = false;
for (int i = 0; i < inputLen; i++) {
char c = inputChars[i];
if (DatalogSyntaxChars(c)) {
outputChars[outputLen++] = c;
if (c == ' ')
continue;
if (c == '.') {
String DatalogCommand =
new String(outputChars, 0, outputLen - 1);
DatalogCommands[DatalogCommandCount++] = DatalogCommand;
outputLen = 0;
}
}
}
for (int i = 0; i < DatalogCommandCount; i++) {
char[] Command = DatalogCommands[i].toCharArray();
if (isQuery(Command)) {
foundQuery = true;
QueryID = i;
continue;
}
if (isRule(Command)) {
DatalogRule(Command);
continue;
}
108
DatalogFact(Command);
}
if (foundQuery) {
DatalogQuery(DatalogCommands[QueryID].toCharArray());
}
return true;
}
private void InsertDatalogFact(String Fact, int ArgCount, Object [][] Args) {
if (CheckForNewFact(Fact, ArgCount, Args)) {
int i;
String sNewFactArgs = "";
this.FactCount++;
for (i = 0; i < ArgCount; i++) {
if ((ArgCount > 1) && (i > 0)) sNewFactArgs += "), TArg(";
sNewFactArgs += "'" + (i+1) + "', '" + Args[i][0] + "', '" + Args[i][1] +
"' ";
}
String sqlInsertDeducted =
"INSERT INTO Facts VALUES ('" + this.FactCount + "', '" +
Fact + "', '" + ArgCount + "', FactArgs(TArg(" + sNewFactArgs + ")))";
SysExecute(sqlInsertDeducted);
}
}
private void InsertDatalogRuleHead(String Rule, int ArgCount, Object [][] Args) {
int i;
String sNewRuleArgs = "";
this.RuleCount++;
for (i = 0; i < ArgCount; i++) {
if ((ArgCount > 1) && (i > 0))
sNewRuleArgs += "), TArg(";
sNewRuleArgs += "'" + (i + 1) + "', '" + Args[i][0] +
"', '" + Args[i][1] + "' ";
}
String sqlInsertDeducted =
"INSERT INTO Rules VALUES ('" + this.RuleCount + "', '" + Rule +
"', '0', '" + ArgCount + "', RuleArgs(TArg(" + sNewRuleArgs + ")))";
SysExecute(sqlInsertDeducted);
}
private void InsertDatalogRulePredicate(String Rule, int ArgCount, Object [][] Args,
int Order) {
int i;
String sNewRuleArgs = "";
for (i = 0; i < ArgCount; i++) {
if ((ArgCount > 1) && (i > 0))
sNewRuleArgs += "), TArg(";
sNewRuleArgs += "'" + (i + 1) + "', '" + Args[i][0] +
"', '" + Args[i][1] + "' ";
}
String sqlUpdateRule =
109
"UPDATE Rules " +
"SET Rule_Predicates = Rule_Predicates + 1 " +
"WHERE Rule_ID = " + this.RuleCount;
SysExecute(sqlUpdateRule);
int PredicateID = this.RuleCount * 100 + Order;
String sqlInsertPredicate =
"INSERT INTO Predicates VALUES ('" + PredicateID + "', '" + this.RuleCount +
"', '" + Order + "', '" + Rule + "', '" + ArgCount +
"', PredicateArgs(TArg(" + sNewRuleArgs + ")))";
SysExecute(sqlInsertPredicate);
}
protected boolean CheckForNewFact(String Fact, int ArgCount, Object [][] Args) {
try {
boolean newArgs = true;
boolean firstFact = true;
Object [][] DeductedArgs = new Object [1000][2];
int DeductedArgsCount = 0;
OracleCallableStatement cstmt =
(OracleCallableStatement)myDDBConnection.prepareCall
( "{ call myddb_pkg.check_get_fact_args(?, ?, ?) }" );
cstmt.setString(1,Fact);
cstmt.setInt(2,ArgCount);
cstmt.registerOutParameter(3,OracleTypes.CURSOR);
cstmt.execute();
ResultSet rsetArgs = (ResultSet)cstmt.getObject(3);
this.QueryCount++;
while (rsetArgs.next()) {
DeductedArgs[DeductedArgsCount][0] = rsetArgs.getString(1);
DeductedArgs[DeductedArgsCount][1] = rsetArgs.getString(2);
DeductedArgsCount++;
if (firstFact) firstFact = false;
}
rsetArgs.close();
cstmt.close();
if (ArgCount == 1) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1]))
) newArgs = false;
}
} else if (ArgCount == 2) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1]))
) newArgs = false;
}
} else if (ArgCount == 3) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
110
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1])) &&
(DeductedArgs[i+2][0].equals(Args[2][0])) &&
(DeductedArgs[i+2][1].equals(Args[2][1]))
) newArgs = false;
}
} else if (ArgCount == 4) {
for (int i = 0; i < DeductedArgsCount; i += ArgCount) {
if ((DeductedArgs[i][0].equals(Args[0][0])) &&
(DeductedArgs[i][1].equals(Args[0][1])) &&
(DeductedArgs[i+1][0].equals(Args[1][0])) &&
(DeductedArgs[i+1][1].equals(Args[1][1])) &&
(DeductedArgs[i+2][0].equals(Args[2][0])) &&
(DeductedArgs[i+2][1].equals(Args[2][1])) &&
(DeductedArgs[i+3][0].equals(Args[3][0])) &&
(DeductedArgs[i+3][1].equals(Args[3][1]))
) newArgs = false;
}
}
if (firstFact) return true;
return newArgs;
} catch (SQLException e) {
SysError("CheckForNewFact(String Fact, int ArgCount, Object [][] Args)",
e.getMessage());
return false;
}
}
private void DatalogFact(char[] Fact) {
String FactName = "";
Object[][] FactArgs = new Object[4][2];
int ArgCount = 0;
boolean predicate = true;
boolean arguments = false;
boolean string = false;
boolean number = false;
char[] predicateValue = new char[30];
char[] stringValue = new char[30];
char[] numberValue = new char[30];
int predicatePos = 0;
int stringPos = 0;
int numberPos = 0;
for (int i = 0; i < Fact.length; i++) {
char c = Fact[i];
if (predicate) {
if (c >= 'a' && c <= 'z')
predicateValue[predicatePos++] = c;
if (predicatePos > 0) {
if (c == '(') {
111
FactName =
new String(predicateValue, 0, predicatePos);
predicate = false;
arguments = true;
continue;
}
}
}
if (arguments) {
if (string) {
if (c == "'".charAt(0)) {
FactArgs[ArgCount][0] = STRING;
FactArgs[ArgCount][1] =
new String(stringValue, 0, stringPos);
ArgCount++;
string = false;
stringPos = 0;
} else {
stringValue[stringPos++] = c;
}
} else if (number) {
if (c != ',' && c != ')')
numberValue[numberPos++] = c;
else {
FactArgs[ArgCount][0] = NUMBER;
FactArgs[ArgCount][1] =
new String(numberValue, 0, numberPos);
ArgCount++;
number = false;
numberPos = 0;
}
} else {
if (c == "'".charAt(0)) {
string = true;
}
if (c >= '0' && c <= '9') {
numberValue[numberPos++] = c;
number = true;
}
}
}
}
InsertDatalogFact(FactName, ArgCount, FactArgs);
}
private void DatalogRule(char[] Rule) {
String RuleName = "";
Object[][] RuleArgs = new Object[MaxArguments][2];
int ArgCount = 0;
boolean predicate = true;
boolean arguments = false;
112
boolean variable = false;
boolean string = false;
boolean number = false;
char[] predicateValue = new char[MaxPredicateNameLen];
char[] variableValue = new char[MaxArgumentNameLen];
char[] stringValue = new char[MaxArgumentNameLen];
char[] numberValue = new char[MaxArgumentNameLen];
int predicatePos = 0;
int variablePos = 0;
int stringPos = 0;
int numberPos = 0;
int predicateCount = 0;
boolean endHead = false;
boolean head = true;
boolean body = false;
for (int i = 0; i < Rule.length; i++) {
char c = Rule[i];
if (head) {
if (c == ':') {
endHead = true;
continue;
}
if (c == '-' && endHead) {
InsertDatalogRuleHead(RuleName, ArgCount, RuleArgs);
head = false;
body = true;
predicate = true;
arguments = false;
variable = false;
string = false;
number = false;
predicatePos = 0;
variablePos = 0;
stringPos = 0;
numberPos = 0;
ArgCount = 0;
continue;
}
}
if (body) {
if (c == ')') {
predicateCount++;
if (variable) {
RuleArgs[ArgCount][0] = VARIABLE;
RuleArgs[ArgCount][1] =
new String(variableValue, 0, variablePos);
} else if (string) {
RuleArgs[ArgCount][0] = STRING;
RuleArgs[ArgCount][1] =
new String(stringValue, 0, stringPos);
113
} else {
RuleArgs[ArgCount][0] = NUMBER;
RuleArgs[ArgCount][1] =
new String(numberValue, 0, numberPos);
}
ArgCount++;
InsertDatalogRulePredicate(RuleName, ArgCount, RuleArgs,
predicateCount);
predicate = true;
arguments = false;
predicate = true;
variable = false;
string = false;
number = false;
predicatePos = 0;
variablePos = 0;
stringPos = 0;
numberPos = 0;
ArgCount = 0;
continue;
}
}
if (predicate) {
if (c >= 'a' && c <= 'z')
predicateValue[predicatePos++] = c;
if (predicatePos > 0) {
if (c == '(') {
RuleName = new String(predicateValue, 0, predicatePos);
predicate = false;
arguments = true;
continue;
}
}
}
if (arguments) {
if (variable) {
if (c != ',' && c != ')')
variableValue[variablePos++] = c;
else {
RuleArgs[ArgCount][0] = VARIABLE;
RuleArgs[ArgCount][1] =
new String(variableValue, 0, variablePos);
ArgCount++;
variable = false;
variablePos = 0;
}
} else if (string) {
if (c == "'".charAt(0)) {
RuleArgs[ArgCount][0] = STRING;
RuleArgs[ArgCount][1] =
114
new String(stringValue, 0, stringPos);
ArgCount++;
string = false;
stringPos = 0;
} else {
stringValue[stringPos++] = c;
}
} else if (number) {
if (c != ',' && c != ')')
numberValue[numberPos++] = c;
else {
RuleArgs[ArgCount][0] = NUMBER;
RuleArgs[ArgCount][1] =
new String(numberValue, 0, numberPos);
ArgCount++;
number = false;
numberPos = 0;
}
} else {
if (c == "'".charAt(0)) {
string = true;
}
if (c >= 'A' && c <= 'Z') {
variableValue[variablePos++] = c;
variable = true;
}
if (c >= '0' && c <= '9') {
numberValue[numberPos++] = c;
number = true;
}
}
}
}
}
private void DatalogQuery(char[] Query) {
String QueryName = "";
Object[][] QueryArgs = new Object[MaxArguments][2];
int ArgCount = 0;
boolean predicate = true;
boolean arguments = false;
boolean variable = false;
boolean string = false;
boolean number = false;
char[] predicateValue = new char[MaxPredicateNameLen];
char[] variableValue = new char[MaxArgumentNameLen];
char[] stringValue = new char[MaxArgumentNameLen];
char[] numberValue = new char[MaxArgumentNameLen];
int predicatePos = 0;
int variablePos = 0;
int stringPos = 0;
115
int numberPos = 0;
for (int i = 1; i < Query.length; i++) {
char c = Query[i];
if (predicate) {
if (c >= 'a' && c <= 'z')
predicateValue[predicatePos++] = c;
if (predicatePos > 0) {
if (c == '(') {
QueryName =
new String(predicateValue, 0, predicatePos);
predicate = false;
arguments = true;
continue;
}
}
}
if (arguments) {
if (variable) {
if (c != ',' && c != ')')
variableValue[variablePos++] = c;
else {
QueryArgs[ArgCount][0] = VARIABLE;
QueryArgs[ArgCount][1] =
new String(variableValue, 0, variablePos);
ArgCount++;
variable = false;
variablePos = 0;
}
} else if (string) {
if (c == "'".charAt(0)) {
QueryArgs[ArgCount][0] = STRING;
QueryArgs[ArgCount][1] =
new String(stringValue, 0, stringPos);
ArgCount++;
string = false;
stringPos = 0;
} else {
stringValue[stringPos++] = c;
}
} else if (number) {
if (c != ',' && c != ')')
numberValue[numberPos++] = c;
else {
QueryArgs[ArgCount][0] = NUMBER;
QueryArgs[ArgCount][1] =
new String(numberValue, 0, numberPos);
ArgCount++;
number = false;
numberPos = 0;
}
116
} else {
if (c == "'".charAt(0)) {
string = true;
}
if (c >= 'A' && c <= 'Z') {
variableValue[variablePos++] = c;
variable = true;
}
if (c >= '0' && c <= '9') {
numberValue[numberPos++] = c;
number = true;
}
}
}
}
ExecuteGoal(QueryName, ArgCount, QueryArgs);
}
private boolean isQuery(char[] Command) {
if (Command[0] == '?')
return true;
else
return false;
}
private boolean isRule(char[] Command) {
for (int i = 0; i < Command.length; i++) {
if (Command[i] == ':' && Command[i + 1] == '-') return true;
}
return false;
}
private boolean DatalogSyntaxChars(char c) {
if (c >= 'a' && c <= 'z') return true;
if (c >= 'A' && c <= 'Z') return true;
if (c >= '0' && c <= '9') return true;
if (c == ':') return true;
if (c == '-') return true;
if (c == '?') return true;
if (c == '(') return true;
if (c == ')') return true;
if (c == '.') return true;
if (c == ',') return true;
if (c == ' ') return true;
if (c == "'".charAt(0)) return true;
return false;
}
}
117
Recommended