La programació lògica amb restriccions (CLP, per les seves sigles en anglès) és una extensió de la programació lògica que permet treballar amb restriccions en lloc de simples fets i regles. Aquesta tècnica és especialment útil per a problemes d'optimització, planificació i altres problemes que impliquen restriccions complexes.
Conceptes Clau
- Què és una Restricció?
Una restricció és una condició que ha de ser satisfeta per a que una solució sigui vàlida. En el context de CLP, les restriccions es poden expressar com a relacions entre variables.
- Domini de les Variables
El domini d'una variable és el conjunt de valors que aquesta variable pot prendre. En CLP, els dominis poden ser finits o infinits.
- Solucionadors de Restriccions
Un solucionador de restriccions és un algorisme que troba valors per a les variables que satisfan totes les restriccions imposades.
Exemples Pràctics
Exemple 1: Problema de les N-Reines
El problema de les N-reines consisteix a col·locar N reines en un tauler de N x N de manera que cap reina pugui atacar una altra. Això significa que no hi pot haver dues reines en la mateixa fila, columna o diagonal.
:- use_module(library(clpfd)).
n_reines(N, Reines) :-
length(Reines, N),
Reines ins 1..N,
totes_diferents(Reines),
no_ataca(Reines),
labeling([], Reines).
totes_diferents([]).
totes_diferents([X|Xs]) :-
all_different(Xs),
totes_diferents(Xs).
no_ataca([]).
no_ataca([X|Xs]) :-
no_ataca(Xs, X, 1),
no_ataca(Xs).
no_ataca([], _, _).
no_ataca([Y|Ys], X, Dist) :-
X #\= Y,
X #\= Y + Dist,
X #\= Y - Dist,
Dist1 #= Dist + 1,
no_ataca(Ys, X, Dist1).Explicació del Codi
- Importació del Mòdul CLP(FD):
:- use_module(library(clpfd)).importa el mòdul de restriccions sobre dominis finits. - Definició del Problema:
n_reines/2defineix el problema de les N-reines.length(Reines, N): Crea una llista de longitud N.Reines ins 1..N: Defineix el domini de les variables.totes_diferents(Reines): Assegura que totes les reines estan en diferents columnes.no_ataca(Reines): Assegura que les reines no es poden atacar entre elles.labeling([], Reines): Troba una solució que satisfaci totes les restriccions.
- Restriccions de Diferència:
totes_diferents/1assegura que totes les reines estan en diferents columnes. - Restriccions de No Atac:
no_ataca/1assegura que les reines no es poden atacar en les diagonals.
Exemple 2: Problema de la Mochila
El problema de la mochila consisteix a seleccionar un subconjunt d'objectes amb pesos i valors donats per maximitzar el valor total sense excedir un pes màxim.
:- use_module(library(clpfd)).
mochila(Pesos, Valors, Capacitat, Seleccio, ValorTotal) :-
length(Pesos, N),
length(Seleccio, N),
Seleccio ins 0..1,
scalar_product(Pesos, Seleccio, #=<, Capacitat),
scalar_product(Valors, Seleccio, #=, ValorTotal),
labeling([maximize(ValorTotal)], Seleccio).Explicació del Codi
- Importació del Mòdul CLP(FD):
:- use_module(library(clpfd)).importa el mòdul de restriccions sobre dominis finits. - Definició del Problema:
mochila/5defineix el problema de la mochila.length(Pesos, N): Obté el nombre d'objectes.length(Seleccio, N): Crea una llista de selecció de longitud N.Seleccio ins 0..1: Defineix el domini de les variables de selecció (0 o 1).scalar_product(Pesos, Seleccio, #=<, Capacitat): Assegura que el pes total no excedeixi la capacitat.scalar_product(Valors, Seleccio, #=, ValorTotal): Calcula el valor total dels objectes seleccionats.labeling([maximize(ValorTotal)], Seleccio): Troba una solució que maximitzi el valor total.
Exercicis Pràctics
Exercici 1: Sudoku
Implementa un solucionador de Sudoku utilitzant CLP.
Solució
:- use_module(library(clpfd)).
sudoku(Rows) :-
length(Rows, 9),
maplist(same_length(Rows), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns),
maplist(all_distinct, Columns),
Rows = [A,B,C,D,E,F,G,H,I],
blocks(A, B, C), blocks(D, E, F), blocks(G, H, I),
maplist(label, Rows).
blocks([], [], []).
blocks([A,B,C|Bs1], [D,E,F|Bs2], [G,H,I|Bs3]) :-
all_distinct([A,B,C,D,E,F,G,H,I]),
blocks(Bs1, Bs2, Bs3).Exercici 2: Problema de la Coloració de Grafs
Implementa un solucionador per al problema de la coloració de grafs utilitzant CLP.
Solució
:- use_module(library(clpfd)).
coloracio_graf(Nodes, Edges, Colors) :-
length(Nodes, N),
Nodes ins 1..Colors,
maplist(no_same_color(Nodes), Edges),
labeling([], Nodes).
no_same_color(Nodes, (A, B)) :-
nth1(A, Nodes, ColorA),
nth1(B, Nodes, ColorB),
ColorA #\= ColorB.Resum
En aquesta secció, hem après sobre la programació lògica amb restriccions (CLP) i com utilitzar-la per resoldre problemes complexos. Hem vist exemples pràctics com el problema de les N-reines i el problema de la mochila, i hem proporcionat exercicis per practicar. La CLP és una eina poderosa que amplia les capacitats de la programació lògica tradicional, permetent treballar amb restriccions i dominis de variables de manera eficient.
Curs de Programació en Prolog
Mòdul 1: Introducció a Prolog
- Què és Prolog?
- Instal·lant Prolog
- Primers Passos en Prolog
- Sintaxi i Estructura Bàsiques
- Fets, Regles i Consultes
Mòdul 2: Programació Bàsica en Prolog
Mòdul 3: Estructures de Dades en Prolog
Mòdul 4: Programació Avançada en Prolog
- Unificació Avançada
- Tall i Negació
- Meta-Programació
- Gramàtiques de Claus Definides (DCGs)
- Programació Lògica amb Restriccions
Mòdul 5: Prolog en la Pràctica
- Entrada/Sortida de Fitxers
- Depuració de Programes Prolog
- Biblioteques Prolog
- Interfície amb Altres Llenguatges
- Construint una Aplicació Prolog
