Orignał w języku Esperanto | Maszynowe tłumaczenie na język polski |
---|---|
Prolog estas programa lingvo, kiu bazas sur predikatkalkulo. Onidire tiu lingvo havas mirindajn eblojn kaj estas uzata por artefarita intelekto kaj ankaŭ en lingvistika programado. Tio estas por mi la kaŭzo pli detale rigardi la lingvon. Mian intereson pri tia programado vekis fine la ĉapitro pri logika programado en libro “Structure and Interpretation of Computer Programs” de Harold Abelson, Gerlald Jay Sussman kun Julie Sussman. La prezentita algoritmo nomiĝas angle “unification”. Mi iam ankaŭ en mia ŝtudperiodo provis prologon, sed tiam mi ne sukcesic kompreni pli ol la konata ekzemplo kun familio. Feliĉe en nuna tempo oni per interreto tre facile povas trovi liberan programaron kaj dokumentaron. Do mi instalis SWI-Prolog kaj komencis legi la instruan interetan libron pri prologo La ideo de prologo estas tre alloga. Oni ne difinas kiel fari ion, sed nur logikaj reguloj. La prologo mem trovas la rezulton de demando. Do programo estas la bazo de reguloj. Tio estas pro specifaj tipoj de problemoj tre potenca ilo. La prologo estas ankaŭ tre avantaĝa por prilaboro de arbaj strukturoj kaj listoj. Kvankam en prologo oni ŝajne ne devas pensi pri la afero, kiel la programo solvas problemojn, post pli detala rigardo la interna kalkulo de prologo estas esenca afero. Do estas tre grave kiel oni difinas regulojn kaj ankaŭ la ordo de reguloj. Ne estas ankaŭ tre facile kompreni la rekursion en tiuj reguloj. Sen mia okupo pri lingvo Scheme mi preskaŭ ne havus ŝancojn kompreni la principon de akumulatoro ĉe rekursio. Mi pensas, ke sen scio pri funkciaj lingvoj kiel “Lispo, Scheme” oni tre malfacile povus kompreni prologon. Insterese, ke mi retrovis ĉe tiu kazo la saman ekzercon kiel ĉe ŝemo, kiu pritraktas la reversadon de listo kun kaj sen akumulatoro ;; naiva programado naiverev([],[]). naiverev([H|T],R) :- naiverev(T,RevT),append(RevT,[H],R). ;; kun akumulatoro accRev([H|T],A,R) :- accRev(T,[H|A],R). accRev([],A,A). rev(L,R) :- accRev(L,[],R). ;; la sama tasko en ŝemo. ;; invert : (listof X) -> (listof X) ;; to construct the reverse of alox (define (invert alox0) (local (;; accumulator is the reversed list of all those items ;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) accumulator] [else (rev (rest alox) (cons (first alox) accumulator))]))) (rev alox0 empty))) La programo en prologo estas mirinde mallonga eĉ ĉe komparo kun ŝemo. Por mi nova estas en prologo la fakto, ke mi aŭ tuj sukcesas difini korektan regulon aŭ mi longe pensas pri 2 linioj de programo. Ekzemple mi tre longe pensis pri ekzerco 6.3. swapf([1,2,3,4],[4,2,3,1]) Yes swapf([1,2,3,4],[1,2,3,4]) No La ekzerco sugestis uzi la predikaton append/3. Kaj antaŭaj ekzercoj prilaboris la predikaton final(X,List), kiu testas, ĉu X estas la fino de listo L. Do mia unua provo estis. final([F],F) final(F,[H|T]) :- final(F,T). swapf([H1|T1],[H2|T2]) :- final(H2,T1), final(H1,T2), append(R,[H1],T2), append(R,[H2],T1). La programo funkciis perfekte por jes/ne demandoj, sed kiam mi volis demandi kun variablo, la programo donis la unuan rezulton kaj poste dronis en senfina laborado. 35 ?- swapfln([1,2,3,4],[4,2,3,1]). Yes 36 ?- swapfln([1,2,3,4],X). X = [4, 2, 3, 1] ; Action (h for help) ? abort % Execution Aborted Mi longe penis, kiel plibonigi tion. Fine mi difinis la regulojn kun rekursio kaj akumulatro. swapflInner([End],[Begin],Begin,End). swapflInner([E|T1],[E|T2],Begin,End) :- swapflInner(T1,T2,Begin,End). swapfl([H1|T1],[H2|T2]) :- swapflInner(T1,T2,H1,H2). Tiu difino sukcesis ankaŭ solvi la demandojn swapfln([1,2,3,4],X) kaj swapfln(X,[1,2,3,4]). Do prologo ne estas vere facila maniero de programado pro komencantoj kaj povas enhavi multajn aĉajn embuskojn. Mi povas imaĝi, ke de iu grando la flegado de tiuj programoj estas tre malfacila kaj bezonas longan sperton. Por mi ankoraŭ stranga estas la funkciado de predikato rek/2. ;; en tiu direkto funkcias ĉio 2 ?- rev([1,2,3],X). X = [3, 2, 1] ; No ;; en alia direkto okazas eraro 3 ?- rev(X,[1,2,3]). ERROR: Out of local stack Exception: (209,511) accRev(_G1257054, [_G1257053, _G1257047|...], [1, 2, 3]) ? Do ŝajne en prologo oni devas zorge pripensi, kien oni povas enmeti variablojn. En la instrua libro oni tamen neniam pri tio diris kaj ŝajne komentarojn kaj priskriboj de predikatoj ne estas kutimaj. Nun mi daŭre lernos tiun lingvon kaj mi volas apenaŭ vidi kelkajn ekzemplojn pri lingvistika programado per prologo. Interesa estas ankaŭ por mi vidi la programojn, kiuj estas taŭgaj por reala mondo. Do programoj, kiu havas uzulan interfacon aŭ prilaboras dosierojn. Feliĉe la labormanieron de prologo oni povas uzi de ankaŭ en aliaj lingvoj. Ofte medioj por prologo ebligas la komunikadon kun programoj skribitaj en C kaj Java. Ekzistas ankaŭ moduloj por javo, kiu ebligas la uzadon de logika programado. Ofte tiuj moduloj estas uzataj por difini kaj traserĉi bazojn de datumoj. leciono por EsperantiloCerte de programlingvo prolog oni povas lerni multon ankaŭ por aliaj programaj lingvoj. La ĉefa algoritmo de prologo, kiu estas “unification” oni povas ankaŭ programi en aliaj lingvoj. Ankaŭ ekzistas ekzempla programado por Tcl. Mi pensas, ke per metodoj de prologo, oni povus tre pure difini la regulojn por serĉado kaj transformigo de sintaksaj arboj. Penseblaj estas reguloj por gramatika korektilo, kiuj estas difinitaj laŭ logika maniero. Nun reguloj aspektas kiel sube: match { folioj { OR {b kilogramo b kvanto b litro b amaso b metro} v de } } Tiu lingvo estas tre simila al prefiksa predikata matematiko (+ 2 2) kiu estas uzata en ŝemo. Tio nun sufiĉas por facilaj reguloj.
Ne estas facila tasko tralabrori la abundan teorion kaj enprogrami tion en la taŭga programo, kiu donas al la uzantoj iun profiton. Ofte estas por uzantoj tre utilaj tute simplaj funkcioj. Aliaj funkcioj bezonas fundan teorion kaj longan rezonadon. |
Prolog jest język programowy, który bazuje na {predikatkalkulo}. Rzekomo ten język ma kapitalne możliwości i jest użytkowany dla sztucznego intelektu i także w lingwistycznym programowaniu. To jest dla mnie powód szczegółowiej patrzeć na język. Mój interes o takim programowaniu budził w końcu rozdział o logicznym programowaniu w książce “Structure and Interpretation of Computer Programs” od Haroldu {Abelson}, Gerlald Jay {Sussman} z Czerwcowo {Sussman}. Przedstawiony algorytm nazywa się z angielskiego “unification”. Kiedyś także w moim {ŝtudperiodo} próbowałem przedmowę, lecz wtedy ja nie {sukcesic} rozumieć więcej aniżeli znany przykład z rodziną. Szczęśliwie w obecnym czasie siecią globalną bardzo lekko można znaleźć wolne oprogramowanie i dokumentację. Więc instalowałem {SWI-Prolog} i zacząłem odtwarzać szkoleniową międzymałą książkę o przedmowie Pomysł przedmowy jest bardzo atrakcyjny. Nie definiuje się jak zrobić coś, lecz jedynie logiczne prawidła. Przedmowa sama znajduje wynik pytania. Więc program jest bazą prawideł. To jest z powodu swoistych typów problemów bardzo przemożny przyrząd. Przedmowa jest także bardzo przyjazna dla obróbki drzewnych struktur i spisów. Aczkolwiek w przedmowie na pozór nie trzeba myśleć o sprawie, jak program rozwiązuje problemy, po dokładniejszym spojrzeniu wewnętrzna kalkulacja przedmowy, jest merytoryczna sprawa. Więc jest bardzo ważnie jak definiuje prawidła i także ład prawideł. Nie jest także bardzo lekko rozumieć rekursję w tych prawidłach. Bez mojej posady o języku {Scheme} nieomal nie miałbym szans rozumieć zasadę akumulatora przy rekursji. Myślę, że bez wiedzy o funkcjonalnych językach jak “{Lispo}, {Scheme}” bardzo trudno można by było rozumieć przedmowę. {Insterese}, że odnalazłem przy tym przypadku takie same zadanie jak przy {ŝemo}, który zajmuje się {reversadon} spisa z i bez akumulatorem ;; naiva programado naiverev([],[]). naiverev([H|T],R) :- naiverev(T,RevT),append(RevT,[H],R). ;; kun akumulatoro accRev([H|T],A,R) :- accRev(T,[H|A],R). accRev([],A,A). rev(L,R) :- accRev(L,[],R). ;; la sama tasko en ŝemo. ;; invert : (listof X) -> (listof X) ;; to construct the reverse of alox (define (invert alox0) (local (;; accumulator is the reversed list of all those items ;; on alox0 that precede alox (define (rev alox accumulator) (cond [(empty? alox) accumulator] [else (rev (rest alox) (cons (first alox) accumulator))]))) (rev alox0 empty))) Program w przedmowie jest wspaniale krótki nawet przy porównaniu z {ŝemo}. Dla mnie nowego jest w przedmowie fakt, że ja albo natychmiast mam powodzenie definiować prawidło korektowe albo długo myślę o 2 liniach programu. Na przykład bardzo długo myślałem o zadaniu 6.3. swapf([1,2,3,4],[4,2,3,1]) Yes swapf([1,2,3,4],[1,2,3,4]) No Zadanie podsuwało użytkować orzeczenie {append} / 3. I uprzednie zadania przetwarzały orzeczenie {final} (X, List), który testuje, czy X jest końcem spisa L. Więc moja pierwsza próba była. final([F],F) final(F,[H|T]) :- final(F,T). swapf([H1|T1],[H2|T2]) :- final(H2,T1), final(H1,T2), append(R,[H1],T2), append(R,[H2],T1). Program funkcjonował wspaniale dla tak / nie pytania, lecz, kiedy chciałem zapytać ze zmienną, program dał pierwszy wynik i potem utonął w bezgranicznej pracy. 35 ?- swapfln([1,2,3,4],[4,2,3,1]). Yes 36 ?- swapfln([1,2,3,4],X). X = [4, 2, 3, 1] ; Action (h for help) ? abort % Execution Aborted Długo trudziłem się, jak ulepszyć to. W końcu definiowałem prawidła z rekursją i {akumulatro}. swapflInner([End],[Begin],Begin,End). swapflInner([E|T1],[E|T2],Begin,End) :- swapflInner(T1,T2,Begin,End). swapfl([H1|T1],[H2|T2]) :- swapflInner(T1,T2,H1,H2). Ta definicja miała powodzenie także rozwiązywać pytania {swapfln} ([ 1, 2, 3, 4 ], X) i {swapfln} (X, [ 1, 2, 3, 4 ]). Więc przedmowa nie jest naprawdę łatwym sposobem programowania z powodu początkujących i może mieścić liczne wstrętne zasadzki. Mogę {imaĝi}, że od jakiegoś zasięgu konserwacja tych programów jest bardzo trudna i potrzebuje długie doświadczenie. Dla mnie jeszcze osobliwego jest operacja orzeczenia {rek} / 2. ;; en tiu direkto funkcias ĉio 2 ?- rev([1,2,3],X). X = [3, 2, 1] ; No ;; en alia direkto okazas eraro 3 ?- rev(X,[1,2,3]). ERROR: Out of local stack Exception: (209,511) accRev(_G1257054, [_G1257053, _G1257047|...], [1, 2, 3]) ? Więc na pozór w przedmowie trzeba starannie przemyśleć, dokąd można wstawiać zmienne. We szkoleniowej książce jednak nigdy o tym nie powiedziano i na pozór komentarze i opisy orzeczeń nie są zwyczajne. Teraz nadal będę uczyć się tego języka i chcę zaledwie widzieć kilka przykładów o lingwistycznym programowaniu przedmową. Interesujące jest także dla mnie widzieć programy, które są zdatne dla rzeczywistego świata. Więc programy, który ma użytkowniczy interfejs albo przetwarza pliki. Szczęśliwie {labormanieron} przedmowy można użytkować od także w innych języków. Często środowiska dla przedmowy umożliwiają komunikację z programami napisane w C i {Java}. Istnieją także moduły dla {javo}, który umożliwia użycie logicznego programowania. Często te moduły są użytkowane aby definiować i przeszukać bazy danych. lekcja dla EsperantiloZ pewnością od języka programowania prolog można uczyć się mnóstwa także dla innych języków programowych. Główny algorytm przedmowy, która jest “unification” można także programować w innych językach. Także istnieje przykładowe programowanie dla Tcl. Myślę, że metodami przedmowy, można by było bardzo czysto definiować prawidła dla poszukiwania i transformacji syntaktycznych drzew. Możliwe do myśli są prawidła dla gramatycznego {korektilo}, które są konieczne według logiczny sposób. Teraz prawidła wyglądają jak pod spodem: match { folioj { OR {b kilogramo b kvanto b litro b amaso b metro} v de } } Ten język jest bardzo podobny do orzeczeniowej matematyki prefiksowej (+ 2 2) który jest użytkowany w {ŝemo}. To teraz starcza dla łatwych prawideł.
Nie jest łatwe zadanie {tralabrori} rzęsistą teorię i {enprogrami} to we zdatnym programie, który daje użytkownikom jakiś zysk. Często są dla użytkowników bardzo użytecznych całkiem proste funkcje. Inne funkcje potrzebują dogłębną teorię i długi rezonans. |