<commit_before>{-# LANGUAGE TypeFamilies #-}

module Graph.GraphMorphism (
    -- * Types
      GraphMorphism
    -- * Construction
    , Graph.GraphMorphism.empty
    , buildGraphMorphism
    , fromGraphsAndRelations
    -- * Transformation
    , invertGraphMorphism
    , updateCodomain
    , updateDomain
    , updateNodes
    , updateNodeRelation
    , updateEdgeRelation
    , updateEdges
    , removeEdgeFromDomain
    , removeEdgeFromCodomain
    , removeNodeFromDomain
    , removeNodeFromDomainForced
    , removeNodeFromCodomain
    , createEdgeOnDomain
    , createEdgeOnCodomain
    , createNodeOnDomain
    , createNodeOnCodomain
    -- * Query
    , applyNode
    , applyNodeUnsafe
    , applyNodeId
    , applyNodeIdUnsafe
    , applyEdge
    , applyEdgeUnsafe
    , applyEdgeId
    , applyEdgeIdUnsafe
    , nodeRelation
    , edgeRelation
    , orphanNodeIds
    , orphanEdgeIds
    , orphanEdges

    , isPartialInjective
    ) where

import           Control.Arrow

import           Abstract.Morphism
import qualified Abstract.Relation as R
import           Abstract.Valid
import           Data.List
import           Data.Maybe        (fromMaybe, isNothing, mapMaybe)
import           Graph.Graph       as G

data GraphMorphism a b = GraphMorphism {
                          getDomain    :: Graph a b
                        , getCodomain  :: Graph a b
                        , nodeRelation :: R.Relation G.NodeId
                        , edgeRelation :: R.Relation G.EdgeId
                    }

instance Eq (GraphMorphism a b) where
    m1 == m2 = domain m1 == domain m2 &&
               codomain m1 == codomain m2 &&
               nodeRelation m1 == nodeRelation m2 &&
               edgeRelation m1 == edgeRelation m2

instance Show (GraphMorphism a b) where
    show m =
      "\nNode mappings: \n" ++ concatMap showNode (G.nodeIds $ getDomain m)
      ++ "\nEdge mappings: \n" ++ concatMap showEdge (G.edges $ getDomain m)
     where
       showNode n =
         show n ++ " --> " ++ show (applyNodeId m n) ++ "\n"

       showEdge (Edge e srcId tgtId _) =
         show e ++ " --> " ++ show (applyEdgeId m e)
         ++ " (from: " ++ show srcId ++ " to:" ++ show tgtId ++ ")\n"

-- | Return the orphan nodes ids in a graph morphism
orphanNodeIds :: GraphMorphism a b -> [G.NodeId]
orphanNodeIds gm = R.orphans (nodeRelation gm)

-- | Return the orphan edges in a graph morphism
orphanEdges :: GraphMorphism a b -> [G.Edge b]
orphanEdges gm = map idToEdge (R.orphans (edgeRelation gm))
  where
    idToEdge id =
      fromMaybe
        (error "orphanEdges: EdgeId is not in graph")
        (lookupEdge id (domain gm))

-- | Return the orphan edgesIds in a graph morphism
orphanEdgeIds :: GraphMorphism a b -> [G.EdgeId]
orphanEdgeIds gm = R.orphans (edgeRelation gm)

-- | Return the node to which @ln@ gets mapped.
applyNode :: GraphMorphism a b -> G.Node a -> Maybe (G.Node a)
applyNode m ln =
    case applyNodeId m (nodeId ln) of
        Just x  -> lookupNode x (codomain m)
        Nothing -> Nothing

-- | Return the nodeId to which @ln@ gets mapped.
applyNodeId :: GraphMorphism a b -> G.NodeId -> Maybe G.NodeId<commit_msg>Fixed bug in orphanEdges function<commit_after>{-# LANGUAGE TypeFamilies #-}

module Graph.GraphMorphism (
    -- * Types
      GraphMorphism
    -- * Construction
    , Graph.GraphMorphism.empty
    , buildGraphMorphism
    , fromGraphsAndRelations
    -- * Transformation
    , invertGraphMorphism
    , updateCodomain
    , updateDomain
    , updateNodes
    , updateNodeRelation
    , updateEdgeRelation
    , updateEdges
    , removeEdgeFromDomain
    , removeEdgeFromCodomain
    , removeNodeFromDomain
    , removeNodeFromDomainForced
    , removeNodeFromCodomain
    , createEdgeOnDomain
    , createEdgeOnCodomain
    , createNodeOnDomain
    , createNodeOnCodomain
    -- * Query
    , applyNode
    , applyNodeUnsafe
    , applyNodeId
    , applyNodeIdUnsafe
    , applyEdge
    , applyEdgeUnsafe
    , applyEdgeId
    , applyEdgeIdUnsafe
    , nodeRelation
    , edgeRelation
    , orphanNodeIds
    , orphanEdgeIds
    , orphanEdges

    , isPartialInjective
    ) where

import           Control.Arrow

import           Abstract.Morphism
import qualified Abstract.Relation as R
import           Abstract.Valid
import           Data.List
import           Data.Maybe        (fromMaybe, isNothing, mapMaybe)
import           Graph.Graph       as G

data GraphMorphism a b = GraphMorphism {
                          getDomain    :: Graph a b
                        , getCodomain  :: Graph a b
                        , nodeRelation :: R.Relation G.NodeId
                        , edgeRelation :: R.Relation G.EdgeId
                    }

instance Eq (GraphMorphism a b) where
    m1 == m2 = domain m1 == domain m2 &&
               codomain m1 == codomain m2 &&
               nodeRelation m1 == nodeRelation m2 &&
               edgeRelation m1 == edgeRelation m2

instance Show (GraphMorphism a b) where
    show m =
      "\nNode mappings: \n" ++ concatMap showNode (G.nodeIds $ getDomain m)
      ++ "\nEdge mappings: \n" ++ concatMap showEdge (G.edges $ getDomain m)
     where
       showNode n =
         show n ++ " --> " ++ show (applyNodeId m n) ++ "\n"

       showEdge (Edge e srcId tgtId _) =
         show e ++ " --> " ++ show (applyEdgeId m e)
         ++ " (from: " ++ show srcId ++ " to:" ++ show tgtId ++ ")\n"

-- | Return the orphan nodes ids in a graph morphism
orphanNodeIds :: GraphMorphism a b -> [G.NodeId]
orphanNodeIds gm = R.orphans (nodeRelation gm)

-- | Return the orphan edges in a graph morphism
orphanEdges :: GraphMorphism a b -> [G.Edge b]
orphanEdges gm = map idToEdge (R.orphans (edgeRelation gm))
  where
    idToEdge id =
      fromMaybe
        (error "orphanEdges: EdgeId is not in graph")
        (lookupEdge id (codomain gm))

-- | Return the orphan edgesIds in a graph morphism
orphanEdgeIds :: GraphMorphism a b -> [G.EdgeId]
orphanEdgeIds gm = R.orphans (edgeRelation gm)

-- | Return the node to which @ln@ gets mapped.
applyNode :: GraphMorphism a b -> G.Node a -> Maybe (G.Node a)
applyNode m ln =
    case applyNodeId m (nodeId ln) of
        Just x  -> lookupNode x (codomain m)
        Nothing -> Nothing

-- | Return the nodeId to which @ln@ gets mapped.
applyNodeId :: GraphMorphism a b -> G.NodeId -> Maybe G.NodeId
{'fraction_non_alphanumeric': 0.08790170132325142, 'fraction_numerical': 0.00315059861373661, 'mean_word_length': 2.1824561403508773, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '228797', 'n_tokens_mistral': 2006, 'n_tokens_neox': 1920, 'n_words': 569}