{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
module Pattern.Graph.GraphQuery
(
TraversalDirection(..)
, TraversalWeight
, undirected
, directed
, directedReverse
, GraphQuery(..)
, frameQuery
, memoizeIncidentRels
) where
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import Pattern.Core (Pattern(..))
import Pattern.Graph.GraphClassifier (GraphValue(..))
data TraversalDirection = Forward | Backward
deriving (TraversalDirection -> TraversalDirection -> Bool
(TraversalDirection -> TraversalDirection -> Bool)
-> (TraversalDirection -> TraversalDirection -> Bool)
-> Eq TraversalDirection
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TraversalDirection -> TraversalDirection -> Bool
== :: TraversalDirection -> TraversalDirection -> Bool
$c/= :: TraversalDirection -> TraversalDirection -> Bool
/= :: TraversalDirection -> TraversalDirection -> Bool
Eq, Int -> TraversalDirection -> ShowS
[TraversalDirection] -> ShowS
TraversalDirection -> String
(Int -> TraversalDirection -> ShowS)
-> (TraversalDirection -> String)
-> ([TraversalDirection] -> ShowS)
-> Show TraversalDirection
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TraversalDirection -> ShowS
showsPrec :: Int -> TraversalDirection -> ShowS
$cshow :: TraversalDirection -> String
show :: TraversalDirection -> String
$cshowList :: [TraversalDirection] -> ShowS
showList :: [TraversalDirection] -> ShowS
Show)
type TraversalWeight v = Pattern v -> TraversalDirection -> Double
undirected :: TraversalWeight v
undirected :: forall v. TraversalWeight v
undirected Pattern v
_ TraversalDirection
_ = Double
1.0
directed :: TraversalWeight v
directed :: forall v. TraversalWeight v
directed Pattern v
_ TraversalDirection
Forward = Double
1.0
directed Pattern v
_ TraversalDirection
Backward = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0
directedReverse :: TraversalWeight v
directedReverse :: forall v. TraversalWeight v
directedReverse Pattern v
_ TraversalDirection
Forward = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
0
directedReverse Pattern v
_ TraversalDirection
Backward = Double
1.0
data GraphQuery v = GraphQuery
{ forall v. GraphQuery v -> [Pattern v]
queryNodes :: [Pattern v]
, forall v. GraphQuery v -> [Pattern v]
queryRelationships :: [Pattern v]
, forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryIncidentRels :: Pattern v -> [Pattern v]
, forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
querySource :: Pattern v -> Maybe (Pattern v)
, forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
queryTarget :: Pattern v -> Maybe (Pattern v)
, forall v. GraphQuery v -> Pattern v -> Int
queryDegree :: Pattern v -> Int
, forall v. GraphQuery v -> Id v -> Maybe (Pattern v)
queryNodeById :: Id v -> Maybe (Pattern v)
, forall v. GraphQuery v -> Id v -> Maybe (Pattern v)
queryRelationshipById :: Id v -> Maybe (Pattern v)
, forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryContainers :: Pattern v -> [Pattern v]
}
frameQuery :: (Pattern v -> Bool) -> GraphQuery v -> GraphQuery v
frameQuery :: forall v. (Pattern v -> Bool) -> GraphQuery v -> GraphQuery v
frameQuery Pattern v -> Bool
include GraphQuery v
base = GraphQuery
{ queryNodes :: [Pattern v]
queryNodes = (Pattern v -> Bool) -> [Pattern v] -> [Pattern v]
forall a. (a -> Bool) -> [a] -> [a]
filter Pattern v -> Bool
include (GraphQuery v -> [Pattern v]
forall v. GraphQuery v -> [Pattern v]
queryNodes GraphQuery v
base)
, queryRelationships :: [Pattern v]
queryRelationships = (Pattern v -> Bool) -> [Pattern v] -> [Pattern v]
forall a. (a -> Bool) -> [a] -> [a]
filter Pattern v -> Bool
include (GraphQuery v -> [Pattern v]
forall v. GraphQuery v -> [Pattern v]
queryRelationships GraphQuery v
base)
, queryIncidentRels :: Pattern v -> [Pattern v]
queryIncidentRels = \Pattern v
n ->
(Pattern v -> Bool) -> [Pattern v] -> [Pattern v]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Pattern v
r -> Bool -> (Pattern v -> Bool) -> Maybe (Pattern v) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False Pattern v -> Bool
include (GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
querySource GraphQuery v
base Pattern v
r)
Bool -> Bool -> Bool
&& Bool -> (Pattern v -> Bool) -> Maybe (Pattern v) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False Pattern v -> Bool
include (GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
queryTarget GraphQuery v
base Pattern v
r))
(GraphQuery v -> Pattern v -> [Pattern v]
forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryIncidentRels GraphQuery v
base Pattern v
n)
, querySource :: Pattern v -> Maybe (Pattern v)
querySource = GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
querySource GraphQuery v
base
, queryTarget :: Pattern v -> Maybe (Pattern v)
queryTarget = GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
queryTarget GraphQuery v
base
, queryDegree :: Pattern v -> Int
queryDegree = \Pattern v
n ->
[Pattern v] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Pattern v] -> Int) -> [Pattern v] -> Int
forall a b. (a -> b) -> a -> b
$ (Pattern v -> Bool) -> [Pattern v] -> [Pattern v]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Pattern v
r -> Bool -> (Pattern v -> Bool) -> Maybe (Pattern v) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False Pattern v -> Bool
include (GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
querySource GraphQuery v
base Pattern v
r)
Bool -> Bool -> Bool
&& Bool -> (Pattern v -> Bool) -> Maybe (Pattern v) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False Pattern v -> Bool
include (GraphQuery v -> Pattern v -> Maybe (Pattern v)
forall v. GraphQuery v -> Pattern v -> Maybe (Pattern v)
queryTarget GraphQuery v
base Pattern v
r))
(GraphQuery v -> Pattern v -> [Pattern v]
forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryIncidentRels GraphQuery v
base Pattern v
n)
, queryNodeById :: Id v -> Maybe (Pattern v)
queryNodeById = \Id v
i -> case GraphQuery v -> Id v -> Maybe (Pattern v)
forall v. GraphQuery v -> Id v -> Maybe (Pattern v)
queryNodeById GraphQuery v
base Id v
i of
Just Pattern v
n | Pattern v -> Bool
include Pattern v
n -> Pattern v -> Maybe (Pattern v)
forall a. a -> Maybe a
Just Pattern v
n
Maybe (Pattern v)
_ -> Maybe (Pattern v)
forall a. Maybe a
Nothing
, queryRelationshipById :: Id v -> Maybe (Pattern v)
queryRelationshipById = \Id v
i -> case GraphQuery v -> Id v -> Maybe (Pattern v)
forall v. GraphQuery v -> Id v -> Maybe (Pattern v)
queryRelationshipById GraphQuery v
base Id v
i of
Just Pattern v
r | Pattern v -> Bool
include Pattern v
r -> Pattern v -> Maybe (Pattern v)
forall a. a -> Maybe a
Just Pattern v
r
Maybe (Pattern v)
_ -> Maybe (Pattern v)
forall a. Maybe a
Nothing
, queryContainers :: Pattern v -> [Pattern v]
queryContainers = \Pattern v
p ->
(Pattern v -> Bool) -> [Pattern v] -> [Pattern v]
forall a. (a -> Bool) -> [a] -> [a]
filter Pattern v -> Bool
include (GraphQuery v -> Pattern v -> [Pattern v]
forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryContainers GraphQuery v
base Pattern v
p)
}
memoizeIncidentRels :: (GraphValue v, Ord (Id v)) => GraphQuery v -> GraphQuery v
memoizeIncidentRels :: forall v.
(GraphValue v, Ord (Id v)) =>
GraphQuery v -> GraphQuery v
memoizeIncidentRels GraphQuery v
base =
let cache :: Map (Id v) [Pattern v]
cache = [(Id v, [Pattern v])] -> Map (Id v) [Pattern v]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
[ (v -> Id v
forall v. GraphValue v => v -> Id v
identify (Pattern v -> v
forall v. Pattern v -> v
value Pattern v
n), GraphQuery v -> Pattern v -> [Pattern v]
forall v. GraphQuery v -> Pattern v -> [Pattern v]
queryIncidentRels GraphQuery v
base Pattern v
n)
| Pattern v
n <- GraphQuery v -> [Pattern v]
forall v. GraphQuery v -> [Pattern v]
queryNodes GraphQuery v
base
]
cachedIncident :: Pattern v -> [Pattern v]
cachedIncident Pattern v
n = [Pattern v] -> Id v -> Map (Id v) [Pattern v] -> [Pattern v]
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault [] (v -> Id v
forall v. GraphValue v => v -> Id v
identify (Pattern v -> v
forall v. Pattern v -> v
value Pattern v
n)) Map (Id v) [Pattern v]
cache
in GraphQuery v
base { queryIncidentRels = cachedIncident
, queryDegree = \Pattern v
n -> [Pattern v] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Pattern v -> [Pattern v]
cachedIncident Pattern v
n)
}