Egyszerű példák DLV-hez2. HáromszögekAmibe most vágunk bele, az korai iskolai éveinkben helyettesíthetett volna bennünket. :) A DLV ezúttal a háromszögek tudományában lesz kénytelen eligazodni. Az egyszerűség kedvéért az euklideszi síkon.2.1 Háromszög, vagy sem?A háromszög oldalaira igaz az az szabály, hogy a leghosszabb oldal mindig rövidebb, mint a másik két oldal összege. Hogy megkerüljük a "leghosszabb" definiálását, fogalmazzuk át úgy, hogy "minden oldalra igaz, hogy az egyik rövidebb, mint a másik két oldal összege"!Egyúttal megismerkedünk a DLV korlátozott aritmetikai képességeivel is. Először is meg kell adnunk, mekkora az a legnagyobb szám, amivel a DLV számolhat: #maxint = 1000.Ezek után megadunk három oldalhosszt egyben és ennek értékeit változtatgatva tesztelhetjük programunkat: oldalak( 11, 1, 1 ).Ez például pont nem lehet háromszög. Jöhet a kulcsszabály: haromszog :- oldalak( A, B, C ), +(A, B, AB), AB > C, +(A, C, AC), AC > B, +(B, C, BC), BC > A.Ez a következőt jelenti: vesszük az oldalakat, és ha ebből kettő összege az összes lehetséges sorrendben(!) nagyobb, mint a harmadiké, akkor kapunk vissza igaz értéket. Próbáljuk ki: haromszog? DLV>dlv.mingw.exe -brave tri_1a.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] haromszog is bravely false.A program teljes forráskódja. Eddig igaza van. Írjuk át az értéket! oldalak( 3, 4, 5 ). haromszog? DLV>dlv.mingw.exe -brave tri_1b.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] haromszog is bravely true, evidenced by {oldalak(3,4,5), haromszog}A program teljes forráskódja. Ez is igaz. Hasonló módon dolgozhatunk szögekkel is. A háromszög szögeinek összege 180 fok: haromszog :- szogek( A, B, C ), +( A, B, AB ), +( AB, C, ABC ), ABC = 180.A program teljes forráskódja. Az aritmetikai kifejezések leírása persze nem épp kényelmes. Lépjünk tovább!
2.2 Milyen háromszög?Teve van egypúpú, kétpúpú... Háromszögből is van pár, ennek osztályozását a DLV el tudja végezni, ha megtanítjuk rá.egyenlo_oldalu_haromszog :- oldalak( A, B, C ), A = B, B = C. egyenlo_szaru_haromszog :- oldalak( A, B, C ), A = B. egyenlo_szaru_haromszog :- oldalak( A, B, C ), A = C. egyenlo_szaru_haromszog :- oldalak( A, B, C ), B = C.A program teljes forráskódja. Eddig egyszerű, de ahhoz, hogy a derékszögű háromszögeket is fel tudjuk ismertetni, már kell a Pitagorasz-tétel is: pitagorasz( A, B, C ) :- *( A, A, A2 ), *( B, B, B2 ), *( C, C, C2 ), +( A2, B2, A2B2 ), A2B2 = C2. derekszogu_haromszog :- oldalak( A, B, C ), pitagorasz( A, B, C ). derekszogu_haromszog :- oldalak( A, B, C ), pitagorasz( A, C, B ). derekszogu_haromszog :- oldalak( A, B, C ), pitagorasz( B, C, A ).Ennek futtatásával a DLV viszont már komolyan megterheli a gépet. Miért is? Lássuk a futás eredményét! derekszogu_haromszog? D:\phd\02-felev\DLV>dlv.mingw.exe -brave tri_3c.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] derekszogu_haromszog is bravely true, evidenced by {oldalak(5,3,4), pitagorasz(0 ,0,0), pitagorasz(0,1,1), pitagorasz(0,2,2), pitagorasz(0,3,3), pitagorasz(0,4,4 ), pitagorasz(0,5,5), pitagorasz(0,6,6), pitagorasz(0,7,7), pitagorasz(0,8,8), p itagorasz(0,9,9), pitagorasz(0,10,10), pitagorasz(0,11,11), pitagorasz(0,12,12), pitagorasz(0,13,13), pitagorasz(0,14,14), pitagorasz(0,15,15), pitagorasz(0,16, 16), pitagorasz(0,17,17), pitagorasz(0,18,18), pitagorasz(0,19,19), pitagorasz(0 ,20,20), pitagorasz(0,21,21), pitagorasz(0,22,22), pitagorasz(0,23,23), pitagora sz(0,24,24), pitagorasz(0,25,25), pitagorasz(0,26,26), pitagorasz(0,27,27), pita gorasz(0,28,28), pitagorasz(0,29,29), pitagorasz(0,30,30), pitagorasz(0,31,31), pitagorasz(1,0,1), pitagorasz(2,0,2), pitagorasz(3,0,3), pitagorasz(3,4,5), pita gorasz(4,0,4), pitagorasz(4,3,5), pitagorasz(5,0,5), pitagorasz(5,12,13), pitago rasz(6,0,6), pitagorasz(6,8,10), pitagorasz(7,0,7), pitagorasz(7,24,25), pitagor asz(8,0,8), pitagorasz(8,6,10), pitagorasz(8,15,17), pitagorasz(9,0,9), pitagora sz(9,12,15), pitagorasz(10,0,10), pitagorasz(10,24,26), pitagorasz(11,0,11), pit agorasz(12,0,12), pitagorasz(12,5,13), pitagorasz(12,9,15), pitagorasz(12,16,20) , pitagorasz(13,0,13), pitagorasz(14,0,14), pitagorasz(15,0,15), pitagorasz(15,8 ,17), pitagorasz(15,20,25), pitagorasz(16,0,16), pitagorasz(16,12,20), pitagoras z(17,0,17), pitagorasz(18,0,18), pitagorasz(18,24,30), pitagorasz(19,0,19), pita gorasz(20,0,20), pitagorasz(20,15,25), pitagorasz(20,21,29), pitagorasz(21,0,21) , pitagorasz(21,20,29), pitagorasz(22,0,22), pitagorasz(23,0,23), pitagorasz(24, 0,24), pitagorasz(24,7,25), pitagorasz(24,10,26), pitagorasz(24,18,30), pitagora sz(25,0,25), pitagorasz(26,0,26), pitagorasz(27,0,27), pitagorasz(28,0,28), pita gorasz(29,0,29), pitagorasz(30,0,30), pitagorasz(31,0,31), derekszogu_haromszog}A program teljes forráskódja. Látható, hogy a DLV "össze-vissza" próbálkozik sok-sok számmal, és aztán talál megoldást. A tétel ilyen módon való beépítése nem célszerű. derekszogu_haromszog :- oldalak( A, B, C ), *( A, A, A2 ), *( B, B, B2 ), *( C, C, C2 ), +( A2, B2, A2B2 ), A2B2 = C2. derekszogu_haromszog :- oldalak( A, C, B ), *( A, A, A2 ), *( B, B, B2 ), *( C, C, C2 ), +( A2, B2, A2B2 ), A2B2 = C2. derekszogu_haromszog :- oldalak( C, A, B ), *( A, A, A2 ), *( B, B, B2 ), *( C, C, C2 ), +( A2, B2, A2B2 ), A2B2 = C2.Így a válasz gyors lesz, a kód viszont "csúnya". A probléma az, hogy első esetben a DLV túlzottan "szabadjára" lett engedve, s ha ezt korlátozni tudjuk, azaz csak a szóba jöhető értékek vizsgálatát engedjük meg, gyors választ kapunk. kivalasztott_oldal( X ) :- oldalak( X, _, _ ). kivalasztott_oldal( X ) :- oldalak( _, X, _ ). kivalasztott_oldal( X ) :- oldalak( _, _, X ). pitagorasz( A, B, C ) :- kivalasztott_oldal( A ), kivalasztott_oldal( B ), kivalasztott_oldal( C ), *( A, A, A2 ), *( B, B, B2 ), *( C, C, C2 ), +( A2, B2, A2B2 ), A2B2 = C2. derekszogu_haromszog :- pitagorasz( A, B, C ).A futtatás mutatja, hogy a kivalasztott_oldal szabály veszi le a terhet a programról, illetve rólunk, hogy minden permutációt lekódoljunk. derekszogu_haromszog? D:\phd\02-felev\DLV>dlv.mingw.exe -brave tri_3e.dlv DLV [build BEN/Oct 11 2007 gcc 3.4.5 (mingw special)] derekszogu_haromszog is bravely true, evidenced by {oldalak(4,3,5), kivalasztott _oldal(3), kivalasztott_oldal(4), kivalasztott_oldal(5), pitagorasz(3,4,5), pita gorasz(4,3,5), derekszogu_haromszog}A program teljes forráskódja.
2.3 Kerület, terület?A kerület kiszámolása triviális:kerulet( K ) :- oldalak( A, B, C ), +( A, B, AB ), +( AB, C, K ).A területhez viszont szögfüggvény kellene, de még osztás, sőt kivonás sincs! Azért nézzük meg, mit lehet tenni!
Segítségünkre siet Héron, az ő képletével:
terulet( X ) :- oldalak( A, B, C ), kerulet( K ), *( 2, S, K ), +( A, SA, S ), +( B, SB, S ), +( C, SC, S ), *( SA, SB, SAB ), *( SC, SAB, SABC ), *( S, SABC, X2 ), *( X, X, X2 ).A program teljes forráskódja. Itt érdemes sorról sorra magyarázatot adni:
A programunk sajnos csak egész számokkal tud futni. A gyökvonást ilyen környezetben közelítő módszerrel tudjuk (úgy-ahogy) pótolni, ami a gyökhöz legközelebb eső egész számot adja vissza: sq( X, X2 ) :- *( X, X, X2 ). sq( X, X2 ) :- *( X, X, X2T ), +( D, X2T, X2 ), D <= X. sq( X, X2 ) :- *( X, X, X2T ), +( D, X2, X2T ), D <= X.Az első sor akkor ad eredményt, ha a szám gyöke is egész, a másik kettő olyan közelítő eredményt ad, mely négyzetének eltérése a négyzetszámtól kisebb, vagy egyenlő, mint a gyök értéke. Tehát |X2-X2| <= X. Háromszögekről talán ennyi elég is. :) |