Está en la página 1de 13

Grafos

Lic. Wilber Ramos Lovón


Grafos en Haskell

• Tenemos al igual que en los arrays la posibilidad


de representar grafos en Haskell de dos formas:

• Representación de grafos conociendo los


sucesores.

• Representación de un grafo como una instancia


de una clase.
Representación de grafos conociendo
los sucesores:
• data Grafo a = G [a] (a->[a])

• vértices funciones que representa aristas


• g :: Grafo Int
• g = G[1,2,3,4,5,6] suc
• Where
• suc 1 = [2,3]
• suc 2 = [4]
• suc 3 = [4]
• suc _ = []
El ejemplo que a continuación se propone calcula el
sucesor de un nodo en el grafo propuesto
anteriormente:

• sucesor :: Int-> (Grafo Int) -> [Int]

• sucesor x (G(h:hs) suc)


• | x == h = suc x
• | otherwise = sucesor x (G hs suc)
Podemos también crear grafos en los cuales
introducir un valor (peso ) a cada arista.

• data GrafoP a p = GP [a] (a->[(a,p)])


• Tipo de los vértices Peso de aristas entre cada nodo

• De esta forma quedan totalmente definidos tanto los


vértices, los sucesores y los pesos de las aristas .
Representación en Haskell:

• gp :: GrafoP Int Int


• gp = GP [1,2,3,4,5] suc
• where
• suc 1 = [(2,5),(3,8)]
• suc 2 = [(4,2)]
• suc 3 = [(4,1)]
• suc _ = []
Haskell da la posibilidad de representación
de grafos utilizando las clases.

• Definiremos una clase con dos funciones


esenciales: vértices y sucesor.

class (Eq a) => Grafo a


where
vertices :: [a]; devuelve los vértices de un grafo.
sucesor :: a -> [a]; devuelve los vértices
sucesores
• La representación anteriormente expuesta:
class (Eq a) => Grafo a
• La interpretación que se le da es que el tipo
de Grafo definido como a tiene que ser el
mismo que el definido en Eq para que se
puedan comparar los elementos.
• También podríamos interpretar la definición
de Grafo como una subclase de Eq.
• A continuación definiremos una serie de
métodos para resolver problemas de
búsquedas de caminos.
(</-) :: (Eq a)=> a->[a]->Bool
camino :: a->[a] ->[a]
camino_desde:: a->(a->Bool)->[a]->[[a]]

• (</-) indica la pertenencia de un


elemento, camino nos devuelve una lista
con los vértices que forman un camino
entre dos vértices dados
• camino_desde:: a->(a->Bool)->[a]->[[a]]

vértice origen
condición que debe cumplir el final
salida

• La condición que debe cumplir es lo


que se llama test de localización (o
poda).
• camino_desde o te vis
| te o = [o : vis]--¿satisface el test el vértice origen?
| otherwise = concat [ camino_desde o' te (o : vis)
| o' <- suc o, o'</- vis ]

• Siendo:
o: vértice origen.
te: test de localización.
vis: lista de vértices ya visitados (inicialmente [ ]).
• La función camino_desde devuelve la lista
de todos los caminos partiendo desde un
vértice hasta satisfacer el test de
localización.
• La función camino podemos definirla en
función de camino_desde como sigue:
camino u v = head (camino_desde u (== v) [ ])
• Como podemos observar, selecciona el
primer camino de todos los que cumplen el
test de localización para el vértice indicado.
• Como se crearía un grafo con esta forma de
representación:
data G1 = Uno | Dos | Tres | Cuatro | Cinco deriving
(Eq, Enum)
instance Grafo G1 where
vertices = [Uno .. Cinco] -- Permitido al derivar G1 de
Enum

suc Uno = [Dos ,Tres]


suc Dos = [Cuatro]
suc Tres = [Cuatro]
suc _ = [ ]

También podría gustarte