module TypedGraph.Morphism.AdhesiveHLR where
import Abstract.AdhesiveHLR
import Abstract.Morphism
import Graph.Graph as G
import qualified Graph.GraphMorphism as GM
import TypedGraph.Morphism.Cocomplete ()
import TypedGraph.Morphism.Core
import Data.Maybe (fromJust, fromMaybe, mapMaybe)
instance AdhesiveHLR (TypedGraphMorphism a b) where
calculateInitialPushout f = (b,d,c)
where
b = addCollapsedEdges $ addCollapsedNodes $ addDanglingNodes init
where
init = emptyMorphismToA
addDanglingNodes m = addNodes m danglingNodes
addCollapsedNodes m = addNodes m collapsedNodes
addCollapsedEdges m = addEdges m collapsedEdges
(d,c) = calculatePushoutComplement f b
typeGraph = codomain typedGraphA
typedGraphA = domain f
nodeTypesInA = GM.applyNodeUnsafe typedGraphA
edgeTypesInA = GM.applyEdgeUnsafe typedGraphA
graphA = domain typedGraphA
graphA' = domain (codomain f)
edgesOfA = edgesFromDomain f
nodesOfA = nodeIdsFromDomain f
emptyMorphismToA = buildTypedGraphMorphism emptyTypedGraph typedGraphA emptyMapToA
where
emptyTypedGraph = GM.empty empty typeGraph
emptyMapToA = GM.empty empty graphA
danglingNodes = filter checkExistsOrphanIncidentEdge nodesOfA
where
checkExistsOrphanIncidentEdge n = any (isOrphanEdge f) incEdges
where
incEdges = getIncidentEdges graphA' (applyNodeUnsafe f n)
collapsedNodes =
filter
(\n ->
any
(\n' ->
n/=n' &&
(applyNodeUnsafe f n == applyNodeUnsafe f n')
) nodesOfA
) nodesOfA
collapsedEdges =
concatMap
(\e ->
[(edgeId e, sourceId e, targetId e) |
any (\e' -> (edgeId e) /= (edgeId e') && (applyEdgeUnsafe f (edgeId e) == applyEdgeUnsafe f (edgeId e'))) edgesOfA]
) edgesOfA
addNodes = foldr (\n -> createNodeOnDomain n (nodeTypesInA n) n)
addEdges =
foldr
(\(e,src,tgt) b ->
(createEdgeOnDomain e src tgt (edgeTypesInA e) e
(createNodeOnDomain tgt (nodeTypesInA tgt) tgt
(createNodeOnDomain src (nodeTypesInA src) src b)
)
)
)
calculatePushoutComplement m l =
let ml = compose l m
delEdges = mapMaybe (GM.applyEdge $ mapping m) (orphanTypedEdgeIds l)
delNodes = mapMaybe (GM.applyNode $ mapping m) (orphanTypedNodeIds l)
k = foldr removeNodeFromCodomain
(foldr removeEdgeFromCodomain ml delEdges)
delNodes
in (k, idMap (codomain k) (codomain m))
calculatePullback f g = (f'',g'')
where
nodeTypeInB = GM.applyNodeUnsafe typedGraphB
nodeTypeInA = GM.applyNodeUnsafe typedGraphA
edgeTypeInB = GM.applyEdgeUnsafe typedGraphB
edgeTypeInA = GM.applyEdgeUnsafe typedGraphA
typeGraph = codomain typedGraphC
typedGraphA = domain f
typedGraphB = domain g
typedGraphC = codomain f
graphB = domain typedGraphB
graphA = domain typedGraphA
nodesInA = nodeIdsFromDomain f
nodesInB = nodeIdsFromDomain g
edgesInA = edgeIdsFromDomain f
edgesInB = edgeIdsFromDomain g
nodesWithoutId = getPairs applyNodeUnsafe nodesInA nodesInB nodeIds
nodesWithId = zip nodesWithoutId ([0..]::[Int])
egdesWithoutId = getPairs applyEdgeUnsafe edgesInA edgesInB edgeIds
edgesWithId = zip egdesWithoutId ([0..]::[Int])
getPairs apply elemA elemB list = concatMap (uncurry product) comb
where
comb =
map
(\n ->
(filter (\n' -> apply f n' == n) elemA,
filter (\n' -> apply g n' == n) elemB))
(list (domain typedGraphC))
product x y = [(a,b) | a <- x, b <- y]
initX = GM.empty empty typeGraph
initF' = buildTypedGraphMorphism initX typedGraphB (GM.empty empty (domain typedGraphB))
initG' = buildTypedGraphMorphism initX typedGraphA (GM.empty empty (domain typedGraphA))
(g',f') = foldr updateNodes (initG',initF') nodesWithId
(g'',f'') = foldr updateEdges (g',f') edgesWithId
updateNodes ((a,b),newId) (g',f') = (updateG',updateF')
where
newNode = NodeId newId
updateG' = createNodeOnDomain newNode (nodeTypeInA a) a g'
updateF' = createNodeOnDomain newNode (nodeTypeInB b) b f'
updateEdges ((a,b),newId) (g',f') = (updateG',updateF')
where
newEdge = EdgeId newId
src1 =
filter
(\n ->
applyNodeUnsafe f' n == sourceOfUnsafe graphB b &&
applyNodeUnsafe g' n == sourceOfUnsafe graphA a)
(nodeIdsFromDomain f')
src = if Prelude.null src1 then error "src not found" else head src1
tgt1 =
filter
(\n ->
applyNodeUnsafe f' n == targetOfUnsafe graphB b &&
applyNodeUnsafe g' n == targetOfUnsafe graphA a)
(nodeIdsFromDomain f')
tgt = if Prelude.null tgt1 then error "tgt not found" else head tgt1
updateG' = createEdgeOnDomain newEdge src tgt (edgeTypeInA a) a g'
updateF' = createEdgeOnDomain newEdge src tgt (edgeTypeInB b) b f'
hasPushoutComplement (Monomorphism, g) (_, f) =
satisfiesDanglingCondition f g
hasPushoutComplement (_, g) (_, f) =
satisfiesDanglingCondition f g && satisfiesIdentificationCondition f g
generateNewNodeInstances :: TypedGraphMorphism a b -> [(NodeId, NodeId)] -> TypedGraphMorphism a b
generateNewNodeInstances gf =
foldr (\(a,b) tgm -> let tp = fromJust $ GM.applyNode (domain gf) a
in updateNodeRelation a b tp tgm) gf
generateNewEdgeInstances :: TypedGraphMorphism a b -> [(EdgeId, NodeId, NodeId, EdgeId, NodeId, NodeId, EdgeId)]
-> TypedGraphMorphism a b
generateNewEdgeInstances =
foldr (\(a,_,_,b,sb,tb,tp) tgm -> updateEdgeRelation a b (createEdgeOnCodomain b sb tb tp tgm) )
satisfiesIdentificationCondition :: TypedGraphMorphism a b -> TypedGraphMorphism a b -> Bool
satisfiesIdentificationCondition l m =
all (==True) (notIdentificatedNodes ++ notIdentificatedEdges)
where
notIdentificatedNodes =
map (notIdentificatedElement l m nodeIdsFromDomain applyNode) (nodeIdsFromCodomain m)
notIdentificatedEdges =
map (notIdentificatedElement l m edgeIdsFromDomain applyEdge) (edgeIdsFromCodomain m)
notIdentificatedElement :: Eq t => TypedGraphMorphism a b -> TypedGraphMorphism a b -> (TypedGraphMorphism a b -> [t])
-> (TypedGraphMorphism a b -> t -> Maybe t) -> t -> Bool
notIdentificatedElement l m domain apply e = (length incidentElements <= 1) || not eIsDeleted
where
incidentElements = [a | a <- domain m, apply m a == Just e]
l' = apply (invert l)
eIsDeleted = Nothing `elem` map l' incidentElements
satisfiesDanglingCondition :: TypedGraphMorphism a b -> TypedGraphMorphism a b -> Bool
satisfiesDanglingCondition l m = all (==True) (concat incidentDeletedEdges)
where
lhs = graphDomain m
instanceGraph = graphCodomain m
checkEdgeDeletion = map (checkDeletion l m applyEdge edgeIdsFromDomain)
matchedNodes = mapMaybe (applyNode m) (nodeIds lhs)
deletedNodes = filter (checkDeletion l m applyNode nodeIdsFromDomain) matchedNodes
incidentEdgesOnDeletedNodes = map (getIncidentEdges instanceGraph) deletedNodes
incidentDeletedEdges = map checkEdgeDeletion incidentEdgesOnDeletedNodes
checkDeletion :: Eq t => TypedGraphMorphism a b -> TypedGraphMorphism a b -> (TypedGraphMorphism a b -> t -> Maybe t)
-> (TypedGraphMorphism a b -> [t]) -> t -> Bool
checkDeletion l m apply list e = elementInL && not elementInK
where
elementInL = any (\x -> apply m x == Just e) (list m)
kToG = compose l m
elementInK = any (\x -> apply kToG x == Just e) (list kToG)
isOrphanEdge :: TypedGraphMorphism a b -> EdgeId -> Bool
isOrphanEdge m n = n `elem` orphanTypedEdgeIds m