0 | module Chem.Aromaticity
7 | import Data.Graph.Indexed
8 | import Data.Graph.Indexed.Util.Bipartite
9 | import Data.Graph.Indexed.Ring.Relevant
10 | import Data.SortedMap
11 | import Data.SortedSet
12 | import Derive.Prelude
15 | %language ElabReflection
22 | record AromBond (a : Type) where
27 | %runElab derive "AromBond" [Show,Eq,Ord]
31 | isAromatic : IGraph k (AromBond e) n -> Fin k -> Bool
32 | isAromatic g = any arom . neighboursAsAL g
35 | Cast a BondOrder => Cast (AromBond a) BondOrder where
45 | record AromBonds where
54 | numBonds : AromBonds -> Nat
55 | numBonds (ABS s a d t) = s + a + d + t
62 | totalBondOrder : AromBonds -> Nat
63 | totalBondOrder (ABS s a d t) =
64 | let rem = s + 2 * d + 3 * t
74 | 0 Edges : Nat -> Type
75 | Edges k = SortedSet (Fin k, Fin k)
77 | toPair : Fin k -> Fin k -> (Fin k, Fin k)
78 | toPair x y = if x > y then (y,x) else (x,y)
80 | %inline hasEdge : Fin k -> Fin k -> Edges k -> Bool
81 | hasEdge x y = contains (toPair x y)
85 | hueckel : Nat -> Bool
86 | hueckel n = prim__and_Integer (cast n) 7 == 4
92 | parameters {0 e,n : Type}
93 | (contrib : n -> Maybe Nat)
98 | aromatizeI : {k : _} -> IGraph k e n -> IGraph k (AromBond e) n
100 | let bs := foldl (pairs [] 0) empty (map ecycle . cr $
computeCrAndMCB g)
101 | in IG $
mapWithIndex (toArom bs) g.graph
104 | toArom : Edges k -> Fin k -> Adj k e n -> Adj k (AromBond e) n
105 | toArom ps m = {neighbours $= mapKV (\n,v => AB v $
hasEdge m n ps)}
107 | pairs : List (Fin k, Fin k) -> Nat -> Edges k -> ECycle k -> Edges k
108 | pairs xs k es all@(E x y _ :: ys) =
109 | case [| contrib (lab g x) + contrib (lab g y) |] of
111 | Just v => pairs (toPair x y :: xs) (k+v) es ys
112 | pairs xs k es [] = if hueckel k then foldl (flip insert) es xs else es
117 | aromatize : Graph e n -> Graph (AromBond e) n
118 | aromatize (G o g) = G o $
aromatizeI g
124 | atMap : SortedMap (Elem,Charge,Hybridization) Nat
129 | , ((C,1,Planar), 0)
131 | , ((C,(-
1),SP2), 1)
132 | , ((C,(-
1),SP3), 2)
138 | , ((N,(-
1),SP3), 2)
139 | , ((N,(-
1),SP2), 1)
143 | , ((P,(-
1),SP3), 2)
144 | , ((P,(-
1),SP2), 1)
151 | atomType : Cast e Elem => Atom e Charge p r h AtomType c l -> Maybe Nat
152 | atomType a = lookup (cast a.elem, a.charge, a.type.hybridization) atMap
159 | 0 KAtom : (e,c,p,r,h,ch,l : Type) -> Type
160 | KAtom e c p r h ch l = Atom e c p r h AtomType ch l
162 | parameters {0 b,e,c,p,r,h,ch,l : Type}
163 | {auto cb : Cast b BondOrder}
166 | available : IGraph k b (KAtom e c p r h ch l) -> Fin k -> Bool
168 | let A l es := adj g x
169 | in S (count ((Dbl ==) . cast) es) == l.type.double
172 | kekulize : Graph b (KAtom e c p r h ch l) -> Graph b (KAtom e c p r h ch l)
174 | let es := map setdbl <$> matchEdgesWhere g (available g)
175 | in G k $
insEdges es g