Esperantilo Blogo en Esperanto pri projekto Esperantilo kaj komputila lingvistiko

22.6.2007

Ludoj kun programlingvo „prolog“

Filed under: programado — artur @ 18:21

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
(Lern Prolog Now!).

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.
La tasko estis: Difinu la regulon swapfl/2 kiu pruvas ĉe du listoj estas samaj, krome ke la unua kaj ka lasta elemento estis interŝanĝitaj.

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 Esperantilo

Certe 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.
Esprimo (v de) signifas = (folio de sintaksa arbo, kies vorto estas „de“). Se oni povus uzi variablojn kaj logikaj reguloj, tiuj difinoj povus estas pli kompleksaj. Ekzistas nun projektoj, kiuj uzas prologon por difini regulojn de XML-transformado. Onidire tiuj reguloj estas pli klaraj ol tiuj de XSLT. La alia eblo estas la difino de sintaksa analizilo per Prologo. La fama DLT projekto uzis prologon por tiu tasko. Mi havas dubojn pri tio, ĉu vere prologo estas tre taŭga por tiu celo. Unue oni plej ofte interesas ne pri ĉiuj eblaj analizoj sed nur pri unu analizo, kiu estas la plej verŝajna. Due oni volas havi la rezultojn de analizo, eĉ se la plena korekta analizo ne estas ebla. Tial la labormaniero de prologo, kiu estas „top-down“ ne estas avantaĝa. Mi pensas ankaŭ, ke difino de esceptoj de natura lingvo (ankaŭ de Esperanto) povas esti tre malfacila en prologo. Mi ĝis nun ne trovis la pritakson de tiu problemo kaj estas tre neverŝajne, ke tio ekzistus por Esperanto. Ŝajne ĉiuj nunaj sintaksaj analiziloj ne plu uzas prologon aŭ logikan programadon. Eble la ĉefa kazo estas la rapideco de tiuj programoj. La alia kampo estas la difino de semantikaj retoj. Tio ŝajne estas la forta trajto de prologo. En prologo estas eble difini demandoj sur rekursiaj strukturoj kaj evidente semantikaj retoj estas rekursiaj. Tio ne estas eble en normala SQL de kutimaj datumbazoj. Semantikaj retoj estas kondiĉo por pli bona maŝina tradukado.

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.
Avantaĝe estas, ke pro interreto nun eĉ la neprofesiulo kiel mi havas la senpagan aliron al modernaj programoj kaj dokumentaro.
Ankaŭ hodiaŭaj hejmaj komputiloj estas sufiĉe rapidaj por tiaj taskoj.

Keine Kommentare »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Du musst angemeldet sein, um einen Kommentar abzugeben.

Powered by WordPress