FGL es una coleccion de tipos y definiciones de funciones para resolver
problemas de grafos. La base de la libreria es la definicion inductiva
de grafos, tipo de datos algebraicos inductivos, definiciones
recursivas de algoritmos.
Define un tipo para nodos dirigidos y
arcos(aristas) etiquetados, que es en si la representación más general,
los otros tipos de grafos pueden ser obtenidos como casos especiales ,
por ejemplo, los grafos no dirigidos pueden ser simulados por un grafo
dirigido que tiene una estructura de aristas simetrica, y nodos o
aristas sin etiqueta se representan simplemente con el tipo ()
(unit/tipo trivial)
Cada grafo puede ser representado por un Contexto, una cuadrupla representada por :
lista de predecesores , Identificador del nodo, Etiqueta del Nodo, lista de sucesores.
type Context a b = (Adj b, Node, a, Adj b)
type Adj b = [(b, Node)]
Provee ademas funciones sobre nodos: obtener sucesores(suc), predecesores(pre), vecinos, grado de un nodo, nmap
Ejemplo :
import Data.Graph.Inductive
import Data.Graph.Inductive.Query.MST
--import Data.Graph.Inductive.Graphviz
...
g :: Gr Char Int -- Un grafo que en sus nodos contiene Caracteres
-- y las aristas tienen valor(peso, distancia)del tipo Entero
-- predecesores , Ident Nodo, Etiqueta del Nodo, sucesores
g = ([(10,2),(11,3)],1,'a',[(12,2)]) & -- & añade un contexto( osea un grafo) a otro grafo.
(([] ,2,'b',[(13,3)]) &
(([] ,3,'c',[]) & empty ))-- empty denota un grafo vacio
-- agrega nodos. Devuelve un grafo con el nuevo nodo
grafo = insNode (4,'d') g3
-- inserta un par de aristas simetricas.
a1 = insEdge (4, 3, 15) grafo -- del nodo 4 al 3 existe una arista con valor 15
ngrafo = insEdge (3,4 , 16) a1 -- del nodo 3 al 4 existe una arista con valor 16
--El grafo ngrafo se representa asi:
1:'a'->[(12,2)] -- Indica que el nodo 1 tiene( o contiene) la etiqueta 'a' Char
-- y con una arista de valor 12 llega al nodo 2
2:'b'->[(13,3),(10,1)] -- El nodo 2 contiene 'b' y con 13 llega al nodo 3
-- con 10 llega al nodo 1
3:'c'->[(16,4),(11,1)] -- El nodo 3 contiene 'c' y con 16 llega al nodo 4
-- con 11 llega al nodo 1
4:'d'->[(15,3)] -- El nodo 4 contiene 'd' y con 15 llega al nodo 3
--podemos estraer el arbol de expansion minimo (Minimum-Spanning-Tree)
aem = msTree ngrafo
--Resulta
[[(2,0)],[(1,10),(2,0)],[(3,13),(2,0)]]
-- Map sobre nodos o aristas
-- nmap :: DynGraph gr => (a -> c) -> gr a b -> gr c b
aplicaSobreNodos = nmap toUpper ngrafo --Modifica los nodos aplicando una funcion
--Resulta
1:'A'->[(12,2)]
2:'B'->[(13,3),(10,1)]
3:'C'->[(16,4),(11,1)]
4:'D'->[(15,3)]
-- emap :: DynGraph gr => (b -> c) -> gr a b -> gr a c
aplicaSobreAristas = emap (+2) ngrafo -- Modifica las aristas aplicando la funcion
--Resulta
1:'a'->[(14,2)]
2:'b'->[(15,3),(12,1)]
3:'c'->[(18,4),(13,1)]
4:'d'->[(17,3)]
Existen varios ejemplos en: Data.Graph.Inductive.Example
tambien
en Data.Graph.Inductive.Query encontramos varias implementaciones de
algoritmos sobre grafos como:Breadth-First Search, Depth-First Search,
Maximum Flow,Dijkstra's shortest path.(Tomar en cuenta que FGL difiere
significativamente del modo imperativo tradicional de pensar para
resolver algoritmos sobre grafos, por tanto no se debe esperar la más
eficiente implementación de algoritmos sobre grafos, pero en principo
son tan eficientes como los correspondientes algoritmos imperativos :S )
En Data.Graph.Inductive.Graphviz existen funciones para visualizar grafos con esa herramienta(Graphviz).
-- main = writeFile "Grafo.dot" (graphviz' ngrafo) -- *
Palabras clave: (FGL ), Functional Graph Library, haskell