p(a). p(b). p(A/e) :- format("Încerc să leg pe A ~n"), q(A), t(b/A). p(A/B) :- q(A), !, t(A/B). p(d). q(a). q(b). q(c). q(d) :- format("Am legat la d ~n"). q(_) :- format("NU am putut lega ~n"), fail. t(a/a). t(a/b). t(b/c). t(b/d). % Pentru p, am ca alternative: % p(a) % p(b) % pentru regula p(A/e), % alternative pentru q(A): q(a), q(b), q(c), q(d) % pentru A=a și A=b nu avem t(b/A) % alternative pentru t nu avem, pentru că deja q leagă pe A % pentru regula p(A/B), % alternative pentru q(A): q(a), q(b), q(c), q(d) % pentru A=c și A=d nu avem t(A/_) % pentru t(A/B) avem alternative: t(a/a), t(a/b), t(b/c), t(b/d) % p(d) % cut se evaluează în timp ce explorăm p(A/B) și q(A) cu A=a (prima % variantă pentru q(A). % cele 2 alternative pentru A=a se explorează normal (sunt produse % de t(a/B), după cut) % guitracer. % noguitracer. % findall(+Template, :Query, -Bag) % strânge în Bag toate instanțele de Template pentru care Query este % legat % ar trebui ca în Query să existe variabile libere, care să se găsească % și în Template solutii_p(Solutii) :- findall(Solutie, p(Solutie), Solutii). solutii_p2(Solutii) :- findall(solutie(X, Y), p(X/Y), Solutii). % forall(Domeniu, Conditie) % Domeniu este o interogare care contine variabile libere, care ar % trebui să se găsească și în Conditie % Verifică că pentru fiecare dintre legările a.î. Domeniu să fie % adevărat, și Conditie este adevărată. % % echivalent cu % Oricare vars . (Domeniu peste vars => Conditie peste vars) inclus(LMica, LMare) :- forall((format("X este ~w.~n", [X]), member(X, LMica)), ( format("X este ~w.~n", [X]), member(X, LMare) ; format("~w nu este membru.~n", [X]), false )), format("X este ~w.~n", [X]). % pentru fiecare X membru în LMica, este adevărat că X este membru în % LMare care_lipsesc(LMica, LMare, Lipsesc) :- findall(X, ( member(X, LMica), \+ member(X, LMare) ), Lipsesc). % findall găsește toate soluțiile pentru o interogare % forall realizează o verificare. are(andrei, laptop, 1). are(andrei, telefon, 1). are(andrei, pix, 5). are(andrei, ghiozdan, 2). are(radu, papagal, 1). are(radu, ghiozdan, 1). are(radu, laptop, 2). are(ana, telefon, 3). are(ana, masina, 1). % bagof(+Template, :Goal, -Bag) % la fel ca findall, dar separă soluțiile pentru Bag după toate % posibilele legări ale variabilelor din Bag care: % - nu sunt legate % - nu apar în Template și % - care nu sunt agregate cu operatorul ^ % ?- bagof(Y, are(X, Y, Z), Bag). % ?- bagof(Y, are(X, Y, _), Bag). % ?- bagof(Y, Z^are(X, Y, Z), Bag). % ?- bagof(Y, Z^(are(X, Y, Z), Z > 1), Bag). % bagof cu toate variabilele libere care nu apar în Template agregate cu % operatorul ^ este echivalent cu findall % ?- bagof(Y, X^Z^are(X, Y, Z), Bag). % echivalent cu % ?- findall(Y, are(_, Y, _), Bag). % setof(+Template, :Goal, -Bag) % Identic cu bagof, dar sortează și elimină duplicatele din [fiecare % soluție pentru] Bag % ?- setof(Y, X^Z^are(X, Y, Z), Bag), writeln(Bag). % Cheryl's Birthday % ==================================================== % Albert and Bernard have just met Cheryl. 'When is your birthday?' % Albert asked Cheryl. Cheryl thought for a moment and said, 'I won't % tell you, but I'll give you some clues'. She wrote down a list of ten % dates: % May 15, May 16, May 19 % June 17, June 18 % July 14, July 16 % August 14, August 15, August 17 % 'One of these is my birthday,' she said. % Cheryl whispered in Albert's ear the month, and only the month, of her % birthday. To Bernard, she whispered the day, and only the day. 'Can % you figure it out now?' she asked Albert. % Albert: 'I don't know when your birthday is, but I know Bernard % doesn't know, either.' % Bernard: 'I didn't know originally, but now I do.' % Albert: 'Well, now I know, too!' % When is Cheryl's birthday? dates([may/15, may/16, may/19, june/17, june/18, july/14, july/16, aug/14, aug/15, aug/17]). % pentru ce date este adevărată afirmația % Albert: "I know Bernard doesn't know, either." % este adevărată pentru orice dată % pentru a cărei lună % nu conține nicio dată % a cărei zi % apare doar o dată în lista de date % dacă afirmația este adevărată pentru o dată, atunci: s1b(Day, Month) :- dates(Dates), % data este una dintre date member(Month/Day, Dates), % luna din dată (Month) % nu conține nicio dată Data1 = Month/D1 % pentru care ziua din dată (D1) apare o singură dată în Dates % (apare o singură dată printre datele din Dates) % sau % luna din dată (Month) conține numai date Month/D1 % ale căror zile (D1) % apar în Dates de mai multe ori (de cel puțin 2 ori) % pentru toate datele din Month este adevărat că forall(member(Month/D1, Dates), % pentru ziua D1 din dată % D1 apare de mai multe ori în Dates % există cel puțin două date Date în Dates, cu ziua D1 ( findall(Date, (member(M1/D1, Dates), Date = M1/D1), % există o singură dată în Dates cu ziua respetivă L), length(L, N), N >= 2) ). % Bernard: 'I didn't know originally, but now I do.' % Afirmația este adevărată pentru % o dată dintre datele pentru care este adevărată afirmația anterioară, % pentru care % ziua indică unic soluția % (ziua apare o singură dată în atele pentru care afirmația anterioară % este adevărată) s2(Day, Month) :- dates(Dates), % o dată dintre datele pentru care este adevărată afirmația anterioară, s1b(Day, Month), findall(Date, ( Date = M1/Day, member(Date, Dates), s1b(Day, M1) ), % (ziua apare o singură dată în datele pentru care afirmația anterioară % este adevărată) [_]). % Albert: 'Well, now I know, too!' % Afirmația este adevărată pentru % o dată dintre datele pentru care este adevărată afirmația anterioară % și pentru care luna % indică o singură soluție printre datele rămase % luna apare o singură dată în datele pentru care afirmația anterioară % este adevărată) s3(Day, Month) :- dates(Dates), % o dată dintre datele pentru care este adevărată afirmația anterioară s2(Day, Month), findall(Date, ( Date = Month/D1, member(Date, Dates), s2(D1, Month) ), % luna apare o singură dată în datele pentru care afirmația anterioară % este adevărată) [_]). % datele pentru care s1b este adevărată s1bVar2(DatesS1b) :- dates(Dates), findall(Date, ( member(Date, Dates), Date = Month/_, % caut toate datele din luna Month % pentru care ziua din data respectivă % este unică în dates % și nu vreau să am nicio astfel de dată findall(Day1, ( member(Month/Day1, Dates), findall(M1, member(M1/Day1, Dates), [_]) % are o singură soluție % findall îmi găsește toate datele din lună % unde ziua apare o singură dată printre toate datele ), []) % nu am nicio zi care să apară într-o singură dată din Dates % vreau să nu am nicio astfel de zi, care îmi indică unic soluția ), DatesS1b). s2Var2(DatesS2) :- s1bVar2(DatesS1), findall(Date, ( member(Date, DatesS1), findall(Date1, ( member(Date1, DatesS1), % datele din DatesS1 Date1 = _/D, % care au aceeași zi Date = _/D ), [_]) % printre datele care se califică pentru afirmația anterioară, % există o singură dată cu această zi ), DatesS2). s3Var2(DatesS3) :- s2Var2(DatesS2), findall(Date, ( % din aceste date member(Date, DatesS2), % caut numai datele % a căror lună % apare o singură dată printre datele din DatesS2 findall(Date1, ( member(Date1, DatesS2), % datele din DatesS2 Date1 = M/_, % care au aceeași lună cu datele din răspuns Date = M/_ ), [_]) ), DatesS3). sol(M/D) :- s3(D, M). sol2(M/D) :- s3Var2([M/D]).