{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
module Abstract.DPO.Core
where
import Abstract.AdhesiveHLR
import Abstract.Morphism
import Abstract.Valid
data Production m = Production
{ left :: m
, right :: m
, nacs :: [m]
}
deriving (Eq, Show, Read)
buildProduction :: m -> m -> [m] -> Production m
buildProduction = Production
getLHS :: Production m -> m
getLHS = left
getRHS :: Production m -> m
getRHS = right
getNACs :: Production m -> [m]
getNACs = nacs
instance (Morphism m, Valid m, Eq (Obj m)) => Valid (Production m) where
validate (Production l r nacs) =
mconcat $
[ withContext "left morphism" (validate l)
, withContext "right morphism" (validate r)
, ensure (isMonomorphism l) "The left side of the production is not monic"
, ensure (isMonomorphism r) "The right side of the production is not monic"
, ensure (domain l == domain r) "The domains of the left and right morphisms aren't the same"
] ++ zipWith validateNac nacs ([1..] :: [Int])
where
validateNac nac index =
mconcat
[ withContext ("NAC #" ++ show index) (validate nac)
, ensure (codomain l == domain nac) ("The domain of NAC #" ++ show index ++ " is not the left side of the rule")
]
class (AdhesiveHLR m, FindMorphism m) => DPO m where
invertProduction :: MorphismsConfig -> Production m -> Production m
shiftNacOverProduction :: MorphismsConfig -> Production m -> m -> [m]
isPartiallyMonomorphic :: m -> m -> Bool
findAllMatches :: (DPO m) => MorphismsConfig -> Production m -> Obj m -> [m]
findAllMatches conf production =
findMorphisms
(matchRestrictionToMorphismType $ matchRestriction conf)
(codomain $ left production)
findApplicableMatches :: (DPO m) => MorphismsConfig -> Production m -> Obj m -> [m]
findApplicableMatches conf production obj =
filter (satisfiesRewritingConditions conf production) (findAllMatches conf production obj)
calculateDPO :: AdhesiveHLR m => m -> Production m -> (m, m, m, m)
calculateDPO m (Production l r _) =
let (k, f) = calculatePushoutComplement m l
(n, g) = calculatePushout k r
in (k, n, f, g)
satisfiesRewritingConditions :: DPO m => MorphismsConfig -> Production m -> m -> Bool
satisfiesRewritingConditions conf production match =
satisfiesGluingConditions conf production match && satisfiesNACs conf production match
satisfiesGluingConditions :: DPO m => MorphismsConfig -> Production m -> m -> Bool
satisfiesGluingConditions conf production match =
hasPushoutComplement (matchIsMono, match) (GenericMorphism, left production)
where
matchIsMono =
matchRestrictionToMorphismType (matchRestriction conf)
satisfiesNACs :: DPO m => MorphismsConfig -> Production m -> m -> Bool
satisfiesNACs conf production match =
all (satisfiesSingleNac conf match) (nacs production)
satisfiesSingleNac :: DPO m => MorphismsConfig -> m -> m -> Bool
satisfiesSingleNac conf match nac =
let nacMatches =
case nacSatisfaction conf of
MonomorphicNAC ->
findMonomorphisms (codomain nac) (codomain match)
PartiallyMonomorphicNAC ->
partialInjectiveMatches nac match
commutes nacMatch =
compose nac nacMatch == match
in
not $ any commutes nacMatches
calculateComatch :: AdhesiveHLR m => m -> Production m -> m
calculateComatch m prod = let (_,m',_,_) = calculateDPO m prod in m'
rewrite :: AdhesiveHLR m => m -> Production m -> Obj m
rewrite m prod =
codomain (calculateComatch m prod)
invertProductionWithoutNacs :: Production m -> Production m
invertProductionWithoutNacs p = Production (right p) (left p) []