Egyszerű példák DLV-hez1. A családFeltételezve, hogy a családi viszonyokban az átlagember különösebb nehézség nélkül tud tájékozódni, vegyünk egy teljesnek nem mondható rokoni "adatbázist" és próbáljuk meg ennek DLV változatát megírni!A családról ennyit tudunk, a "ki kinek a kije" szöveges elbeszélését mellőzve: Nagy János Kis Zsuzsa | +--Nagy Róbert | +--Nagy Gábor | | Pásztor András | Kocsis Piroska | | | +--Pásztor János +-----Nagy Réka | +--Pásztor Edit Szabó Elek | +--Szabó Pál | Varga Zsófia | | | +--Szabó Zsolt | | | +--Szabó Mária | +--Szabó Péter Kovács Anna | | Juhász Tamás +--Szabó Erika | +--Juhász OrsolyaKövessük a természetesen adódó logikát és az ismert tényeket "apja" és "anyja" kapcsolatokkal rögzítsük DLV-ben: apja( nagy_janos, nagy_robert ). apja( nagy_janos, nagy_gabor ). apja( nagy_janos, nagy_reka ). anyja( kis_zsuzsa, nagy_robert ). anyja( kis_zsuzsa, nagy_gabor ). anyja( kis_zsuzsa, nagy_reka ). apja( szabo_peter, szabo_erika ). anyja( kovacs_anna, szabo_erika ). apja( juhasz_tamas, juhasz_orsolya ). anyja( szabo_erika, juhasz_orsolya ). apja( szabo_pal, szabo_zsolt ). apja( szabo_pal, szabo_maria ). anyja( varga_zsofia, szabo_zsolt ). anyja( varga_zsofia, szabo_maria ). apja( szabo_elek, szabo_pal ). apja( szabo_elek, szabo_peter ). anyja( pasztor_edit, szabo_pal ). anyja( pasztor_edit, szabo_peter ). apja( pasztor_janos, pasztor_edit ). anyja( nagy_reka, pasztor_edit ). apja( pasztor_andras, pasztor_janos ). anyja( kocsis_piroska, pasztor_janos ).(Sajnos a nagybetűkről és az ékezetekről most le kellett mondanunk.) A szokásos példa ezek után a nagyszülők megkeresése lenne, de ennél markoljunk kicsit nagyobbat és vegyük rá a DLV-t rögtön arra, hogy az összes őst feltérképezze!
1.1 Az ősökEhhez először is vezessük be a "szülő" predikátumot, ami később megkímél attól, hogy minden esetben apára és anyára külön hivatkozzunk:szuloje( A, B ) :- apja( A, B ). szuloje( A, B ) :- anyja( A, B ).Ezt nagyjából úgy lehet felolvasni, hogy "B-nek A akkor szülője, ha A B-nek apja, vagy anyja". Logikus, hogy ha valaki valakinek szülője, akkor őse is: ose( A, B ) :- szuloje( A, B ).Viszont ez még nem elég, mert ennél tovább kell lépnünk, ki kell egészítenünk, hogy a nagyszülőket, dédszülőket, stb. is megtalálja a DLV. Valamiféle iterációra lesz szükségünk, ami a szülőre újra alkalmazza az őse szabályt és mindaddig halad, míg talál valamit. A két személy, azaz a szülő (ős) és a gyermek (leszármazott) közé belép egy harmadik személy, akiről annyit tudunk, hogy az ősnek gyermeke, de a leszármazottnak őse: ose( A, B ) :- ose( A, X ), ose( X, B ).A többi a DLV dolga, fel is göngyölíti szépen pl. Juhász Orsolya felmenőit, ha feltesszük neki a megfelelő kérdést: ose( A, juhasz_orsolya )? DLV>dlv.mingw.exe -brave family_2.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] nagy_janos nagy_reka kis_zsuzsa szabo_peter szabo_erika kovacs_anna juhasz_tamas szabo_elek pasztor_edit pasztor_janos pasztor_andras kocsis_piroskaA teljes program az adatdefiníciós rész nélkül (az fentebb olvasható) a következő volt: szuloje( A, B ) :- apja( A, B ). szuloje( A, B ) :- anyja( A, B ). ose( A, B ) :- szuloje( A, B ). ose( A, B ) :- ose( A, X ), ose( X, B ).A program teljes forráskódja. Keressünk valami nehezebben áttekinthetőbbet (főleg a fentinél bővebb adathalmaznál)!
1.2 UnokatestvérekAz unokatestvérem a szülőm testvérének gyermeke. Magyarázzuk el ezt valahogy a DLV-nek is!Először is tudatnunk kell vele, mit értünk testvér alatt. Testvérek azok a gyermekek, akiknek a szülei ugyanazok. (Életszerűbb féltestvér szituációk az olvasóra bízva!) testvere( A, B ) :- szuloje( X, A ), szuloje( X, B ), A != B.A törzs harmadik tagja magyarázatra szorul: elhagyása esetén ugyanis minden gyermek a saját maga testvére is lenne, ami ugyan a gép szempontjából logikus, csak mi nem ilyen választ szeretnénk, ezért ezt az esetet külön ki kell zárnunk azzal, hogy a behelyettesítés során A nem egyezhet meg B-vel. A DLV a szülő-gyermek kapcsolatot már ismeri, most már tudja, mi a testvér, így megadhatjuk az unokatestvér szabályát: unokatestvere( A, B ) :- szuloje( X, A ), testvere( X, Y ), szuloje( Y, B ).Emberi nyelven kiolvasva körülbelül így szól: "A és B akkor unokatestvérek, ha létezik X és Y testvérek, akik közül X A-nak és Y B-nek szülője". Azt, hogy saját magunk unokatestvére legyünk, a testvér szabály szerencsére már kizárja. Lássuk, hány unokatestvért talál a DLV! unokatestvere( A, B )? DLV>dlv.mingw.exe -brave family_3.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] szabo_erika, szabo_zsolt szabo_erika, szabo_maria szabo_zsolt, szabo_erika szabo_maria, szabo_erikaA program teljes forráskódja. Persze így mindenki kétszer szerepel. Lássunk egy kissé még nehezebb feladatot!
1.3 A sógorokA sógorom a leánytestvérem férje. Itt már a nemekre is vigyázni kell, de szerencsére az alapadataink apa és anya megkülönböztetése ezt, amennyire most szükséges, biztosítja. Van már testvér szabályunk is, de férj, feleség nincs.Legyünk az egyszerűség kedvéért bigottak és tételezzük fel, hogy csak azok az igazi párok, melyeknek gyermekük is van, továbbá nincs a rendszerben válás és hasonló zavaró tényezők! :) Először tehát a "párja" szabály: parja( A, B ) :- apja( A, X ), anyja( B, X ). parja( A, B ) :- anyja( A, X ), apja( B, X ).A szimmetria biztosítja, hogy a behelyettesítés ne legyen később "féloldalas". "Testvér" szabályunk már van, jöhet a "sógor": sogora( A, B ) :- testvere( A, X ), parja( X, B ).Ellenőrizzük! sogora( A, B )? DLV>dlv.mingw.exe -brave family_4b.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] nagy_robert, pasztor_janos nagy_gabor, pasztor_janos szabo_peter, varga_zsofia szabo_pal, kovacs_annaA program teljes forráskódja. Elrontottunk valamit? Igen! :) Szabó Péternek és Pálnak nem lett volna szabad előbukkanni. Ők ugyanis fiútestvérek és a párjuk nő. :) Sógornőnek persze jó, de mi szigorúbbak akarunk lenni. A "testvére" szabállyal nem tudunk mit kezdeni, mert nem hordozza a nemet, mint információt, ám a "párja" átalakítható: ferje( A, B ) :- apja( A, X ), anyja( B, X ). felesege( A, B ) :- anyja( A, X ), apja( B, X ). parja( A, B ) :- ferje( A, B ). parja( A, B ) :- felesege( A, B ). sogora( A, B ) :- testvere( A, X ), ferje( B, X ). sogornoje( A, B ) :- testvere( A, X ), felesege( B, X ).Futtassuk: sogora( A, B )? DLV>dlv.mingw.exe -brave family_4c.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] nagy_robert, pasztor_janos nagy_gabor, pasztor_janosA program teljes forráskódja.
sogornoje( A, B )? DLV>dlv.mingw.exe -brave family_4d.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] szabo_peter, varga_zsofia szabo_pal, kovacs_annaA program teljes forráskódja. A további rokoni fokokat a kedves olvasó kedvére kidolgozhatja. |