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/2
defineix 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/1
assegura que totes les reines estan en diferents columnes. - Restriccions de No Atac:
no_ataca/1
assegura 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/5
defineix 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