Prolog i logičko programiranje

Dok Amerika uči stroj da radi, Europa ga pita da zaključuje — uz vino, kredu i puno backtrackinga.

poglavlje 24/2718 min čitanja1970 – 1980

Zamisli da je 1971. Nisi u Kaliforniji, nema sunca koje se odbija od bazena, nema riziko-kapitalista koji ti gura novac u ruku jer si rekao riječ 'strojno'. Ti si u Marseilleu. Ili u Edinburghu, gdje je nebo sivo dvjesto dana godišnje i najbliža stvar riziko-kapitalu je stipendija koja kasni tri mjeseca. Nemaš DARPA-in ček — DARPA je agencija američkog ministarstva obrane koja je u to doba lopatom sipala novac u istraživanja umjetne inteligencije, valjda se nadajući pametnim raketama ili pametnijim generalima. Nemaš vojsku koja financira tvoje igranje. Imaš tablu, kredu, jako puno crnog čaja ili crnog vina ovisno o strani Kanala — i knjigu staru dvije i pol tisuće godina.

Ta knjiga se zove Organon, napisao ju je Aristotel, i u njoj stoji nešto što će Alain Colmerauer u Marseilleu i Robert Kowalski u Edinburghu pretvoriti u opsesiju: da se zaključivanje može zapisati kao pravilo. Ako je A istina i ako A povlači B, onda je B istina. Silogizam. Stara stvar. Toliko stara da ju je svaki logičar od Aristotela do Fregea vrtio u rukama — ali nitko je nije stavio u stroj.

I tu je razlika koja će odrediti cijelo poglavlje, pa je bolje da je postavimo odmah, dok je scena još prazna: jedna strana Atlantika pita „kako da mu kažem što da radi”, druga pita „kako da mu kažem što je istina, pa neka on sam zaključi ostalo”. Zvuči kao nijansa. Nije. To je razlika između recepta i suđenja.

Dobro, dosta atmosfere. Znam da čitatelj koji ovo čita nije logičar s rodovnicom do Aristotela, nego normalan čovjek koji se pita zašto bi ga to uopće zanimalo. Pa dobro — postavljaj pitanja, ja ću odgovarati. Krenimo s onim najbanalnijim, a zapravo najboljim: program bez naredbi? Kako, molim?

Dobro, stani malo. Kažeš da postoji jezik u kojem se ne piše što stroj treba RADITI?

Otprilike. Zamisli da si do sad učio kuhati po receptima — uzmi luk, nasjeckaj, poprži, dodaj meso, promiješaj. Korak po korak, redoslijed je bitan, ti si šef kuhinje i stroj sluša naredbe jednu za drugom. To je imperativno programiranje, ono što si dosad gledao u ovoj enciklopediji devedeset posto vremena — C, Pascal, Basic, svi ti jezici iz prethodnih poglavlja. Kažeš mu TOČNO što, i TOČNO kojim redom.

A Prolog?

Prolog ne kuha. Prolog je onaj gnjavator za stolom koji, kad mu kažeš što imaš u frižideru i što voliš jesti, sam smisli što ćeš večerati. Ti mu ne govoriš KAKO da dođe do zaključka — ti mu samo govoriš ČINJENICE i PRAVILA, a on sam kopa po njima dok ne nađe odgovor. To se zove deklarativno programiranje: deklariraš istinu o svijetu, a ne postupak kako do nje doći.

To mi je i dalje maglovito. Daj konkretno.

Konkretno. Zamisli da imaš obiteljsko stablo, kao ono što je teta crtala na božićnom ručku dok je objašnjavala tko je čiji stric po drugoj liniji. U Prologu bi stroju rekao samo goli materijal, bez ikakvih uputa: otac(Ivan, Ana). otac(Ana, Marko). To je to. Nisi rekao ništa o TOME kako se traži djed, samo si rekao — Ivan je otac Ane, Ana je... dobro, uzmimo da Prolog ne mari za rod, otac(X, Y) znači X je roditelj po muškoj liniji od Y, nemoj me sad hvatati za genealogiju, shvati koncept.

Dobro, dobro. I onda?

Onda dodaš JEDNO pravilo, samo jedno: djed(X, Z) :- otac(X, Y), otac(Y, Z). Pročitaj to kao rečenicu na hrvatskom, doslovno: „X je djed od Z AKO je X otac od Y I Y je otac od Z.” Ta strelica unatrag, taj znak :-, Prologov je način da kaže „ovo je istina pod uvjetom da...”. I to je sve. Nisi napisao petlju koja ide kroz listu ljudi, nisi napisao if-else koji provjerava svaki par, nisi napisao NIŠTA o postupku traženja. Samo si rekao stroju kako izgleda istina o djedovstvu, a onda ga pitaš: djed(Ivan, Marko)? — je li to istina? On sam, iza kulisa, počne kopati kroz sve što znaš o obitelji dok ne nađe put koji tu tvrdnju potvrđuje ili obara.

Čekaj, znači on sam smisli da mora provjeriti postoji li netko između njih dvoje?

Upravo to. I to je razlika koja laiku, kad prvi put sjedne pred to, doslovno okrene mozak naopako. U svakom jeziku koji si dosad vidio, TI si taj koji smišlja algoritam — TI kažeš „idi kroz svaku osobu, pa provjeri je li otac, pa provjeri je li tom ocu otac ta druga osoba”. U Prologu ti ne smišljaš algoritam za traženje djeda. Ti samo definiraš ŠTO ZNAČI biti djed, jednom, kao definiciju u rječniku, a stroj sam otkriva put do odgovora. Otprilike kao da bi odvjetniku dao samo tekst zakona, a on sam, bez tvoje pomoći, sastavio cijeli slučaj.

Zvuči kao filozofija, a ne kao programiranje, priznajem.

I jest, malo. Ti si u pravu što se čudiš — cijela ova europska struja, ono što ćemo ostatak poglavlja rastresati, izrasla je iz logičara koji su vjerovali da se ISTINA može zapisati kao skup pravila, a rješenje je onda samo mehaničko izvođenje te istine. Amerikanci su u istom desetljeću uglavnom pitali „kako da stroj nešto NAPRAVI”. Europljani, s druge strane stola i s puno više kave i puno manje novca od vojske, pitali su „kako da stroj nešto ZNA, i onda sam ZAKLJUČI”. Ta razlika u pitanju, vjeruj mi, ispada puno veća nego što zvuči na prvu.

OK, shvatio sam osnovu. Ali kako on onda stvarno KOPA kroz te činjenice? To mi je i dalje magija.

Nije magija, obećavam — samo je tvrdoglav detektiv koji ne odustaje, ali o tom detektivu, i kako on stvarno kopa kroz te činjenice, više u sljedećem pitanju.

"Kako stroj 'zaključuje'?"
§ 02

"Kako stroj 'zaključuje'?"

Dobro, kaže naš laik, shvatio sam da mu kažem tko je čiji djed i onda ga pitam. Ali kako on to ZNA? Nitko mu nije rekao formulu. Otac(X,Y) i otac(Y,Z) su samo dvije rečenice na ekranu. Odakle stroju odgovor?

E, tu ulazimo u srce cijele priče, u dva mehanizma koja se zovu unifikacija i backtracking. Zvuči kao dva teška predmeta s faksa, ali su, u suštini, jedna vrlo poznata ljudska aktivnost: uporno pogađanje, uz vraćanje unatrag kad pogodiš krivo. Zamisli detektiva — ne onog elegantnog iz filmova koji odmah zna sve, nego onog realnog, dosadnog, koji ima hrpu tragova na stolu i metodično ih križa jedan po jedan.

Unifikacija je taj trenutak kad detektiv uzme jedan trag i pita se: uklapa li se ovo u sliku koju tražim? Konkretno, kad postaviš upit djed(marko, X) — dakle pitaš tko je Markov djed — Prolog uzme svoje pravilo djed(A,C) :- otac(A,B), otac(B,C) i pokuša ga izjednačiti, unificirati, s tim pitanjem. A postaje marko. C postaje X, ono što tražiš. Sad treba samo pronaći B, osobu koja povezuje to dvoje — Markova oca. I to je cijeli trik: umjesto da ti kažeš stroju KAKO da traži, on sam uzme svaku poznatu činjenicu o očevima i pokušava ih spojiti kao Lego kockice, provjeravajući pristaje li spoj.

A kad ne pristaje? Tu dolazi backtracking, ono vraćanje unatrag. Zamisli da detektiv proba trag broj jedan, ode njime pola ulice, i onda shvati — ćorsokak. Ne baci cijeli slučaj, ne odustane. Samo se vrati na raskrižje odakle je krenuo i proba trag broj dva. Prolog radi identično. Kad pokuša neku kombinaciju činjenica i dođe do zida — pravilo se ne slaže, uvjet je pao — on se ne buni, tiho se vrati na zadnju točku gdje je imao izbor i proba sljedeću opciju. To radi automatski, a da mu ti to ne programiraš. Ti mu samo daš tragove — činjenice i pravila — a on sam odluči kojim redom ih isprobava i kada odustaje pa vraća.

Zato laik pita — pa dobro, zar stroj ne može biti pametniji, zar ne može odmah znati koji trag ne vrijedi provjeravati? Odgovor je — može, djelomično, i upravo tu je cijela znanost logičkog programiranja poslije Prologa uglavnom otišla: u pravljenje pametnijih detektiva koji unaprijed odbacuju očito glupe tragove (to se zove indeksiranje, ili cut operator, ako baš hoćeš stručni izraz), umjesto da ih svaki put fizički provjeravaju. Ali ni najpametniji detektiv ne izbjegne temeljni problem: kad problem naraste, broj mogućih kombinacija tragova raste brže od svega što možeš platiti procesorskim vremenom. To nije mana loše implementacije, to je matematička činjenica o kombinatorici, i vrijedi za svaki sustav koji pretražuje prostor mogućnosti — bio pisan u Prologu 1972. ili u najmodernijem AI sustavu danas.

"Zašto Europa? Zašto ne Amerika?"
§ 03

"Zašto Europa? Zašto ne Amerika?"

Dobro, kaže naš laik, sve mi je ovo jasno-ish. Ali zašto su baš neki Francuz u Marseilleu i neki Britanac u Edinburghu ovo skuhali? Amerika je u to doba imala DARPA-in novac koji je curio kao slavina bez brtve, MIT je vrvio genijalcima, a Silicijska dolina — pa, dolina još nije bila dolina, ali potencijal je već bio tu. Zašto logičko programiranje niče na drugom kontinentu, iz dva čovjeka koji su se, usput, i svađali oko toga tko je zapravo autor?

Odgovor je manje o novcu, a više o filozofiji — i to ozbiljno, ne u onom smislu „pa svi su filozofi na fakultetu”. Alain Colmerauer u Marseilleu bavio se obradom prirodnog jezika i htio je stroj koji razumije francuski, ne stroj koji igra šah. Robert Kowalski u Edinburghu dolazio je iz čiste matematičke logike — bavio se teorijom rezolucije, matematičkom metodom kojom se automatski dokazuje je li neka tvrdnja logički istinita na temelju skupa premisa, dakle formalnim dokazivanjem teorema. Dvojica ljudi, dva grada, dva različita ulaza u istu zgradu. Početkom sedamdesetih njihovi putevi se sudaraju — pola suradnja, pola prioritetski rat oko toga čija je ideja unifikacije s backtrackingom starija — i iz tog sudara ispada Prolog. Kowalski daje teoriju (logika kao izračunavanje), Colmerauerov tim daje implementaciju koja stvarno radi na stroju. Klasična europska podjela rada: jedan filozofira, drugi programira, a onda se obojica svađaju tko je pametniji.

I tu je stvar, koliko god zvučalo kao akademska sitnica: bio je to pravi kulturni rascjep u ranom svijetu umjetne inteligencije, ne samo estetska preferencija. Amerika je htjela strojeve koji rade stvari — pokreni robota, riješi zagonetku, isplaniraj put. Europa je htjela strojeve koji dokazuju stvari — pokaži mi da je ovo istina, i pokaži mi zašto. Jedno je pragmatično, drugo je matematičko do srži. I dugo se ta razlika prodavala kao brend: dok su Amerikanci govorili 'naš AI radi', Europljani su govorili 'naš AI je ispravan'. Zvuči kao marketinška fusnota, ali u financiranju znanosti sedamdesetih to je bila stvarna razlika u pristupu prijavama za projekte — jedni su tražili novac za demo koji leti, drugi za formalizam koji stoji na papiru.

Naravno, ne treba to romantizirati kao neki europski otpor američkoj hegemoniji — realnost je bila skromnija. Colmerauer je imao mali budžet, staru mašinu i studente koji su pisali interpreter u — ironično — Fortranu, prije nego se Prolog preselio na nešto pristojnije. Ali upravo ta oskudica možda objašnjava zašto je logika bila privlačna: kad nemaš novca za brutalnu silu, a brutalna sila u to doba zvala se LISP-mašine — specijalizirana, vrlo skupa računala građena baš za LISP, dominantan američki jezik umjetne inteligencije — elegantna teorija koja radi manje računanja za isti rezultat postaje ne luksuz, nego nužnost. Siromaštvo kao majka formalizma — nije loš naslov za poglavlje, ali nismo tu stigli, pa idemo dalje.

"Je li to ikad išta stvarno radilo?"
§ 04

"Je li to ikad išta stvarno radilo?"

— Dobro, dobro — kaže laik i vidljivo se namješta u stolici, kao netko koji se sprema uloviti sugovornika u laži. — Sve to lijepo zvuči: djedovi, unifikacija, backtracking, detektivi. Ali je li to ikad nešto STVARNO radilo? Je li Prolog nekome ikad riješio problem koji nije izmišljen na predavanju?

Jest, i to više nego što bi čovjek pomislio. Osamdesete su bile zlatno doba nečega što se zvalo ekspertni sustavi — programi koji su trebali zamijeniti čovjeka-stručnjaka u uskom, ali vrijednom polju. Ne „stroj koji misli kao ti”, nego „stroj koji zna sve što zna doktor Perić o dijagnosticiranju infekcija krvi, i to bez pauze za kavu”. I to je stvarno radilo. MYCIN, sustav napisan još ranih sedamdesetih na Stanfordu (tehnički ne u Prologu, ali ista filozofija — pravila, činjenice, zaključivanje), davao je preporuke za terapiju antibioticima koje su u testovima bile bolje od preporuka nekih liječnika. Ne svih. Ali nekih. Zamisli tu rečenicu izgovorenu 1979. — stroj je bolji dijagnostičar od čovjeka, u jednom uskom zadatku. To ti je bio šok ekvivalentan današnjem „AI je prošao odvjetnički ispit”.

— Znači radilo je. Pa što se onda dogodilo, gdje je taj MYCIN danas? — pita laik, sad već pravi malo optužujuće lice, kao da je uhvatio nekoga u laži koju tek treba dokazati.

E, tu dolazimo do razlike između „radi u demonstraciji” i „radi u bolnici, u petak popodne, kad je sestra umorna i liječnik žuri”. MYCIN nikad nije klinički korišten — ne zato što je griješio, nego zato što nitko nije htio odgovornost prebaciti na kutiju s pravilima ako nešto pođe po zlu. Pravni i etički problem, ne tehnički. To je nešto što se ponavlja kroz cijelu povijest umjetne inteligencije, uzgred — stroj nauči raditi posao, ljudi se onda pitaju tko ide u zatvor kad stroj pogriješi, i posao ostane čovjeku.

Ali gdje su ekspertni sustavi stvarno zaživjeli, u praksi, s parama? U industriji. XCON, sustav koji je konfigurirao narudžbe računala za Digital Equipment Corporation, štedio je firmi milijune dolara godišnje jer nije griješio u tome koji kabel ide s kojom karticom — dosadan posao, savršen za pravila oblika ako-ovo-onda-ono, savršen za logičko programiranje. To je bio pravi hit osamdesetih, ne robot koji piše sonete, nego softver koji je jeftinije i preciznije radio ono što je inače radio umoran inženjer s check-listom u ruci.

OK, dobro — kaže laik, malo umireniji. — Ekspertni sustavi, konfiguracije, državni projekti. Ima li nešto još konkretnije, gdje mogu reći „aha, to sam koristio a nisam ni znao”?

Ima, i baš je zanimljivo koliko je nisko-profilno. Parsiranje jezika — bilo prirodnog, bilo programskog, znači postupak kojim stroj rečenicu ili kod razlaže na dijelove i shvaća kako se ti dijelovi slažu, slično kao kad ti u osnovnoj školi raščlanjuješ rečenicu na subjekt i predikat — bilo je jedno od prvih prirodnih staništa logičkog programiranja, jer je gramatika u suštini skup pravila, a pravila su Prologov kruh. DCG, definite clause grammars, odnosno „gramatike definitnih klauzula”, bio je alat koji je izravno spajao lingvistiku i logičko programiranje, i preživio je duže od samog Prologa kao popularnog jezika. Planiranje — kako doći od stanja A do stanja B kroz niz koraka, robotika, logistika, rasporedi letova — druga je niša gdje deklarativni stil, gdje kažeš stroju cilj a ne korake, jednostavno prirodno odgovara problemu. I baze pravila, sustavi koji danas tiho sjede unutar poslovnog softvera i odlučuju hoće li ti banka odobriti kredit prema kombinaciji dvadesetak uvjeta — to je, iskreno, unuk Prologa, samo se ne zove tako, i nitko na sastanku ne spominje Marseille.

Znači nije bio promašaj.

Nije bio promašaj. Bio je jezik koji je pobijedio u nekoliko bitaka i onda tiho izgubio rat za dnevni red — a to je, vidjet ćeš u sljedećem odgovoru, sasvim druga priča od „nije radilo”.

"I gdje je to danas?"
§ 05

"I gdje je to danas?"

— OK, zvučalo je zanimljivo dok je trajalo. Ali gdje je Prolog danas? Otvorim li LinkedIn i potražim posao, hoću li ga naći?

Nećeš. Barem ne pod tim imenom, i barem ne s plaćom koja bi te oduševila. Prolog je danas ono što bi Wikipedija lijepo nazvala „niša akademski i industrijski relevantan jezik”, a mi ćemo to nazvati onako kako zapravo jest: izgubljena grana stabla umjetne inteligencije. Grana koja je nekad izgledala kao da će nositi cijelu krošnju, a onda je stablo odlučilo rasti u drugom smjeru.

— Zašto? Što je pobijedilo?

Mreže. Neuronske mreže, duboko učenje, sve ono o čemu ćeš čitati u poglavljima o zimama i proljećima umjetne inteligencije [vidi K6]. Simbolički AI — onaj koji pokušava zapisati znanje kao pravila i pustiti logiku da odradi posao — izgubio je od pristupa koji ne pokušava razumjeti ništa, samo gleda milijune primjera i pogađa uzorak. Ironično: stroj koji „zaključuje” kao Sherlock Holmes izgubio je od stroja koji je više kao onaj tip iz kviza koji pogodi odgovor jer ga je već čuo tisuću puta. Elegancija je izgubila od brute force-a — one sirove, „pokušavaj dok ne prođe” metode — uz dovoljno podataka i dovoljno struje.

— Dobro, ali rekao si da ništa nije umrlo do kraja. Jesi li to samo tako rekao, ili misliš ozbiljno?

Mislim ozbiljno, i evo dokaza. Sljedeći put kad napišeš SQL upit s WHERE klauzulom — SQL je, uzgred, standardni jezik kojim se baze podataka pita za informacije, ono što ukucaš kad želiš da baza „iskopa” nešto za tebe — »daj mi sve kupce koji su kupili X i ne žive u Y« — pišeš deklarativno pravilo. Ne kažeš bazi KAKO da traži, kažeš joj ŠTO tražiš, i ona to razriješi sama. To je Prologov unuk, samo se preziva Datalog i nosi odijelo poslovne baze podataka. Zapravo, Datalog je toliko blizu Prologa da bi ga Colmerauer prepoznao na prvi pogled — samo bez rekurzije koja ide u nedogled, jer bankarski sustav ne smije čekati da se stroj zamisli.

— A pravila? Rekao si nešto o poslovnoj logici.

Svaki sustav koji odlučuje »ako je klijent stariji od 65 i ima manje od tri kredita, odobri« radi upravo ono što je Prolog radio elegantnije prije pola stoljeća — samo je danas zakopano u nekoj Java klasi koja se zove RuleEngine ili u Excel makroima koje nitko ne smije dirati. Osiguravajuća društva, banke, porezni sustavi — puni su logike koja bi u Prologu bila tri retka, a u produkciji je tri tisuće redaka if-else naredbi koje nitko više ne razumije. Prolog nije umro, samo je promijenio odijelo i zaboravio svoje ime.

— A to što spominjete kod programskih jezika, »type inference« — ima li to veze s ovim?

Ima, i to direktnu. Kad ti Haskell ili TypeScript kažu »ovo je tip broj, ovo je tip string, i tu se ne slažu«, to nije magija — to je motor za unifikaciju koji radi gotovo identičan posao kao Prologov, samo na tipovima umjesto na činjenicama o obitelji. Isti algoritam koji je 1972. u Marseilleu spajao djeda i unuka, danas ti u pozadini uređivača koda govori da si zabrljao funkciju. Nitko od programera koji to koriste ne zna da koristi Alaina Colmerauera, i to je u redu — ideje ne moraju nositi imena da bi radile.

— Znači, poanta cijele ove priče?

Poanta je da u umjetnoj inteligenciji ništa ne ide zauvijek na smetlište. Ideja koja izgubi bitku samo čeka da joj zima prođe. Simbolička logika je danas u sjeni neuronskih mreža, ali onog trena kad netko poviče da mreže ne mogu objasniti SVOJE odluke — a to se već događa, i glasno — netko će otvoriti staru knjigu o Prologu, otpuhati prašinu s nje i reći: čekajte, možda smo bacili nešto što nam sad treba. Nije prvi put. Neće biti posljednji.