Prolog

***Prolog*** esas un ek la precipua programifo-lingui di logikala programigado. La nomo *Prolog* esas franca akronimo di PROgrammation LOGique. Ol kreesis da Alain Colmerauer, Philippe Roussel e Robert Kowalski cirkume 1972. La skopo di lua kreo esis developar programifo-linguo qua permisus uzar reguli logikala por solvar problemi, e transformar ca reguli en serio di instrukti por la komputero.

Prolog uzesas en multa programi di artifical inteligenteso, ed en la trakto dil linguistiko per komputero (precipue koncernanta naturala lingui). Lua sintaxo e semantiko judikesas kom tre simpla e klara (la skopo esas prokurar utensilo per la linguisti ne-savinta l'neformala). Multa ek la inquesti duktinta al aktuala instalo de Prolog venus di efektis di projeti per la komputeri dil kinesma generaciono ke uzis kom bazo vario.

La bazo di *Prolog* esas la kalkulo di predicati di unesma rango ; tamen ol esas restriktar ad aceptar sole la klauzi de Horn. L'exekuto di Prolog programo esas efektive apliko di teorio provinta per rezolvo di unesma rango. La fondamenta konceptaji esas l'uneso, la recurzivita, e la retro-veno sur traco.

## Tipi di donaji
Prolog ne uzas tipi di donaji en la ordinara maniero di lingui di programo. Ni devas parlar lore to kelkafoye di lexika elementi.

### Atomi
La konstanta texti esas en-duktita per la moyeno di atomi. Atomo esas sequo konsistinta ek letri, nombri e sub streki, qui komencas per minuskula letro. Komence, se atomo ne-alfanumerala esas necesa ol esas cirkondita per apostrofi (exemple '+' esas atomo, + esas operacanto).

### Nombri

La plumulteso di prolog instali ne facas diferanta inter di integra e reala nombri.

### Variani

La variani esas indikita en uzinta ensemblo di letri, nombri e sub-strekiza signi e komencinta kun majuskula letro. En l'ambiento Prolog, variano ne esas kontenanto, qua povas esar asignita (a l'inversa di lingui di programeso de proceduro). Sua konduto esas plu proxim di forma, qua esas plus specifita per l'unieso.

L' *anonima varianto* skribesas kun sub-strekiza (_).

### Termini

La termini esas la sola fasoni do Prolog povas reprezentar komplexa donaji. Termino konsistas en kapo, anke nomizita foncto (ke povas esar atomo), e di parametri (sen restrikto di tipo). La nombro di parametri, anke nomizita arito di termino, esas sencala. Termino esas identigita per sua kapo e sua arito, ofte skribas kom funcionero/arito.

### Listi

Listo ne esas tipo di izolata donaji, nam ol esas definita per recursiva konstrukto (uzinta termino '.'/2) :

# atomo [] esas vakua listo
# se *T* esas listo e *H* esas elemento, lore termino '.'(*H*, *T*) es listo.
L'unesma elemento, nomizita la kapo, esas *H*, qua esas sequas per la kontenita di ceteri dil listo, indikita kom *T* o kaudo.
La listo *[1, 2, 3]* reprezentesus en interna kom '.'(*1*, '.'(*2*, '.'(*3*, [])))
Plu korto di sintaxo es [*H* | *T*], qua e precipue per konstructar di normi.
La tota listo povas esas traktita en operacinta la prima elemento, e seque la sequanto en la listo, per tale nomizita rekursiono*, to esas, kande ula funciono iteras sua propra exekuto plurafoye.

Pro la facileso di programigo la listi povas konstruktesar e deskonstruktesar da diversa manieri.

* Elemento enumero: [abc, 1, f(x), *Y*, g(*A*, rst)]
* Des-kompozar en sole elemento: [abc | *L1*]
* Des-kompozar en di multa elementi: [abc, 1, f(x) | *L2*]
* expanso di termino: '.'(abc, '.'(1, '.'(f(x), '.'(*Y*, '.'(g(*A*, rst), [])))))

### Kateni di signi

La kateni di signi esas ordinare skritita kom sequo di signi cirkondita per di apostrofi. Ol reprezentesas ofte interne per listo di kodexo ASCII.

## Fakti

La programigado en *Prolog* esas multe diferanta de la programigado en imperala lingui. En *Prolog*, vi alimentas bazo di donaji di fakti e di normi; vi povas lore questionar la bazo di donaji. L'uneso di bazo de Prolog esas la predicato, qua esas definita kom esinta vera. Predicato konsistas en kapo e nombri di argumenti. exemple:

kato(tom).

Hike 'kato' esas la kapo, e 'tom' esas l'argumento. Yen kelka simpla questioni ke vi povas demandar ad interpreto segun ta fakto:

 ?- kato(tom).
      yes.

 ?- kato(X).
      X = tom;
      non.

La predicati esas en ordinare definita per expresar kelka fakto quon la programo konocas kelkafoye di mondo. En la plu-multeso queras ul-konvenciono. Do, ke versiono di du predicati sube volus signifikar ke Pat es la patro de Sally?

 patro(sally, pat).
 patro(pat, sally).

Ambe kazo 'patro' esas la kapo dum ke 'sally' e 'pat' esas la argumenti. Tamen en la prima kazo, Sally venas unesma en la listo di argumenti, ed en la duesma to es Pat (la rango en la listo di argumenti importacas). La prima kazo esas exemplo di defino en la rango verbo-subjeto-objekto, e la duesmo di verbo-objekto-subjeto. Kom Prolog ne komprenas la naturala linguo, la du versioni esas korekta en to ke li koncernas; tamen to esas bona stilo de programeso ke di mantenar kohero di konvenciono en programo.

Kelka predicati establisesas en la linguo e permisas prolog programo facar rutinala aktivesi (exemple: l'eniro/ekiro di dati, uzar la grafika interfacio e ordinare komunikar kun la sistemo dil komputero). exemple la predicato write povas uzesar por l'afishigo ala skreno. Do

 write('Bonveno')

prezentos la verto 'Bonveno' ala skreno.

## Normi

La duesma tipo di instrukti en Prolog esas la normo. Exemplo di normo esas

 lumo(on) :- interruptilo(on).

La « :- » signifikas « se »; ta normo indikas lumo(on) esas vera se interruptilo esas vera. Normi povas anke uzar di variani kom

 patro(X,Y) :- gepatro(X,Y), maskulo(Y).

To ke signifikas « se kelko esas la gepatro di altra kelko e to esas maskulo, oli esas do la patro ». L'antea e konsequanta esas en l'inversa normo di to ke trovas normale en logika. Ol esas posibla di pozar di multa predicati e konseque, grupita kun uniono « e », exemple:

 a, b, c :- d.

ke esas simple la equivalanto di tre separa normi, tamen la tri separa normi ne esas equivalanto di (a e b e c) se d, 
pro ke ol questionesas di uno « o » inkluzite:

 a :- d.
 b :- d.
 c :- d.

To ke ne esas permisita esas di normi kam:

 a;b :- c.

to qua esas « se c lore a o b ». To esas pro dil restrikto per la klauzo de Horn.

## Evaluo

Kande l'interpreto recevas demando ol probas di trovar di fakti ke korespondas ala questiono. Se irga simpla fakto es disponebla, ol probas di kontentigar omna la normi ke havas la fakto kom konkluzo. exemple havas to kodexo Prolog.

 fratulo_o_fratino(X,Y) :- gepatro(Z,X), gepatro(Z,Y).
 patro(X,Y) :- gepatro(X,Y), maskulo(X).
 matro(X,Y) :- maskulo(X,Y), femino(X).
 gepatro(X,Y) :- patro(X,Y).
 gepatro(X,Y) :- matro(X,Y).
 matro(trude, sally).
 patro(tom, sally).
 patro(tom, erica).
 patro(mike, tom).
 maskulo(tom).
 femino(trude).
 maskulo(mike).

Ol kam rezultas ke la sequa demando esas evaluita kom vera:

 ?- fratulo_o_fratino(sally, erica)
      yes.

L'interpreto par-venas a to rezulto kam facinta korespondar la normo  fratulo_o_fratino(X,Y) per kun-pozinta (preciza substitucinta) *sally* a *X* e *erica* a *Y*. 

To signifikas ke la demando povas esar extensita a gepatro(Z,sally), gepatro(Z,erica). Igar korespondar ta uniono esas obtenita kam vidinta omni la posibla gepatro di *sally*. 
Tamen, parent(trude,sally) ne duktas a vivatra solvo, per ke se *trude* esas substitucita per *Z*,  gepatro(trude,erica) devus esar vera, e irga fakto tala (o kelka normo qua povas kontentigar to) ne esas prezenta. Anke ala loko, *tom* substitucesas per *Z*, e *erica* e *sally* aparas esar *fratulo_o_fratino* tamen.

 matro(X,Y) :- gepatro(X,Y), femina(X).
 gepatro(X,Y) :- patro(X,Y).

povas semblar suspekt. Sume omna gepatro ne esar patro. Ma ol es vera ke omna patro es gepatro. Di altra parto, kelko esar la matro di un ke se el esas sam-tempe sua gepatro e femina.

Per indikar ke omna la patri es maskulo vi havas bezono di kodexo

 maskulo(X) :- patro(X,_).

to ke simple esas indiferanta a qua esas la filio (la sub-strekiza esas la *anonima varino*).

### Nego

Tipe, demando esas evaluita kom falsa per la merito di ne trovar di pozitiva normi o fakti qua suportas la stato. To nomizesas la premiso di klozita monda; on konsideras ke omna to qua devas esar konocita esas inkluzas en la bazo di donaji, lore ol ne esas di extera mondo ke povus kontenar la ne-konocata pruvi. En altra termini, se fakto ne esas konocata kom esinta vera (o falsa) ol esas konsiderita kom falsa.

Afirmo quale

 legala(X) :- NOT nelegala(X).

povas sole evaluesar quale inquestinta exhaustante per omna la nelegala kozi, la komparinta a *X*, e se irga fakto nelegala povas troversar kom la mem ke *X*, *X* esas legala. To nomizesas nego per falio.

## Exekuto

Prolog esas logikala linguo, anke quale teorio vi ne devus vi pre-okupar di quale ol exekutas su.

Tamen ol esas kelke foye prudenta di prenar en konto quale l'algoritmo di infero agas, por evitar ke la programo en Prolog divenas tro longa.

exemple, ni povas skribar di kodexo per kontar la nombro di elementi de listo.

 elemi([],0).
 elemi([H|T], X) :- elemi(T, Y), X esas Y + 1.

To signifikas simple; se la listo es vakua, la nombro di elementi esas zero. 
Se listo ne esas vakua, lore X esas augmentita di un per raporto a Y, qua esas la nombro di elementi en la cetero del listo sen la prima elemento.

En ta kazo, ol havas clara distingo inter la kazi en l'antea en la normi. Ma konsiderar la kazo ube vi havas bezono di decidar se vi continuas a ludar en cazino;

 mizar(X) :- havarpekunio(X).
 mizar(X) :- havarkredito(X), NOT havarpekunio(X).
 
Se vi havas dil pekunio, vi duras a mizar. Se vi havas omne perdita vi havas bezono di pruntar, o se ne ... plu kam pario.  havarpekunio(X) povas esar funciono tre kustozo, exemple, se ol povas acesar a vua banca konto per la reto. Ma to esas la mem kozo per *havarkredito*.

En teorio, la instaluro di Prolog povas evaluar ta normi en irga ordino, anke vi povus anke bona havas skritas;

 mizar(X) :- havarkredito(X), NOT havarpekunio(X).
 mizar(X) :- havarpekunio(X).

To ke esas bona, per ke amba questioni exkluzar su l'una l'altra. Tamen verifikinta se vi povas obtenar presto ne esas necesa se vi savas ke havas pekunio. Anke en praktiko, la instaluro di Prolog testos *la normo ke vi havas skritita prima*. 

Vi povas uzar l'operacero *cut* per dicar a l'interpreto di saltar la duesma selekto se la prima suficas. Exemple:

 mizar(X) :- havarpekunio(X), !.
 mizar(X) :- havarkredito(X), NOT havarpekunio(X).

To nomizesas operacero di haltigo *verda*. La *!* dicas simple a l'interpreto di ne plu serchar d’alternativo. Ma vi notez ke se vi havas bezono di pekunio ol havas bezono di evaluar la duesma normi, e oli feras. Testinta per *havarpekunio* en la duesma normo esas prefere ne-utila nam vi savas ke vi ne havas, segun la duesma normo ne esus evaluita prima. Anke vi povas chanjar la kodexo en:

 mizar(X) :- havarpekunio(X), !.
 mizar(X) :- havarkredito(X).

To nomizesas operacero di haltigo *reda*, per ke ol esas danjeroza facar ol. Vi esas nun dependinta di korekta poze di operacero di haltigo et la rango di normi per determinar la logikala senso. La acidenti di tranchar-e-glutinar guatas en la obskura anguli. Se la normi esas mixita, vi povas nun uzar vua kredito-karto ante di spensar vua disponebla pekunio.