summaryrefslogtreecommitdiff
path: root/MeaningSubst.hs
blob: a0821b5f7ae20d55daa60621412f4b95306ba00f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import System.Environment( getArgs )
import Text.Printf
import Library.Parse
import Library.ProofGraph
import Library.GraphPart
import Library.Theorem
import Library.Term
import Library.TypeVar
import Library.Generator
import Library.TermNet( TermNet )
import qualified Library.TermNet as TermNet
import Data.Graph.Inductive.Graph( Node, LNode )
import qualified Data.Graph.Inductive.Graph as Graph
import Data.Map( Map )
import qualified Data.Map as Map
import qualified Data.Set as Set
import Data.List
import Data.Maybe



data Step = Step { from :: Node
                 , to :: Node
                 , sub :: Substitution }



alreadyMatchedElem :: (Ord a, Eq b) => a -> b -> Map a b -> Bool
alreadyMatchedElem x y xymap =
    Map.member x xymap && Map.lookup x xymap /= Just y



createSubst :: Theorem -> Theorem -> Maybe Substitution
createSubst one two =
    let f = (\x y tymap varmap ->
                case (x,y) of
                    (TVar (Var n ty), term) ->
                        if (alreadyMatchedElem (Var n ty) term varmap)
                        then Nothing
                        else let varmap' = if (Map.lookup (Var n ty) varmap == Nothing)
                                           then Map.insert (Var n ty) term varmap
                                           else varmap
                             in Just (tymap, varmap')

                    (TConst a1 ty1, TConst a2 ty2) ->
                        if (alreadyMatchedElem (typeVar ty1) ty2 tymap || a1 /= a2 || (ty1 /= ty2 && not (isTypeVar ty1)))
                        then Nothing
                        else let tymap' = if (ty1 /= ty2)
                                          then Map.insert (typeVar ty1) ty2 tymap
                                          else tymap
                             in Just (tymap', varmap)

                    (TApp a1 b1, TApp a2 b2) ->
                        do (tymap', varmap') <- f a1 a2 tymap varmap
                           f b1 b2 tymap' varmap'

                    (TAbs a1 b1, TAbs a2 b2) ->
                        do (tymap', varmap') <- f a1 a2 tymap varmap
                           f b1 b2 tymap' varmap'

                    (other, combination) -> Nothing)

        g = (\x y tymap varmap ->
                let (hyp1,hyp2) = (Set.toList . thmHyp $ x, Set.toList . thmHyp $ y)
                in if (hyp1 == [] && hyp2 == [])
                   then f (thmCon x) (thmCon y) tymap varmap
                   else do (tymap', varmap') <- f (head hyp1) (head hyp2) tymap varmap
                           g (Theorem (Set.fromList . tail $ hyp1) (thmCon x))
                             (Theorem (Set.fromList . tail $ hyp2) (thmCon y))
                             tymap' varmap')

        maps = g one two Map.empty Map.empty

    in if ((Set.size . thmHyp $ one) /= (Set.size . thmHyp $ two) || isNothing maps)
       then Nothing
       else do (t,v) <- maps
               return (Map.toList t, Map.toList v)



checkNode :: PGraph -> TermNet -> Node -> (TermNet, Maybe (GraphPart, GraphPart), Maybe (Node,Node))
checkNode graph termnet node =
    let theorem = TermNet.genThm graph node
        possibles = TermNet.matchThm termnet theorem 

        canBeSubbed = (\inn out ->
            if (inn == [])
            then out
            else let sub = createSubst theorem (fst . head $ inn)
                     out' = if (isNothing sub)
                            then out
                            else (Step node (snd . head $ inn) (fromJust sub)) : out
                 in canBeSubbed (tail inn) out')

        maxPositiveBenefit = (\list ->
            let sortVal = (\x -> let added = fst . snd $ x
                                     removed = snd . snd $ x
                                     inn = from . fst $ x
                                     out = to . fst $ x
                                     outNodes = map (\(x,(y,z)) -> (x,y)) (Graph.lpre graph out)
                                 in (size removed) - (addedSize added (Just (inn,1)) outNodes graph) - (overlap added removed))
                sorted = sortBy (\x y -> compare (sortVal x) (sortVal y)) list
                check = head sorted
            in if (sortVal check > 0) then (Just (snd check), Just (from . fst $ check, to . fst $ check)) else (Nothing, Nothing))

        (step, between) = maxPositiveBenefit . (map (\x -> (x, stepGen graph x))) $ (canBeSubbed possibles [])
        termnet' = TermNet.addThm termnet theorem node

    in (termnet', step, between)



stepGen :: PGraph -> Step -> (GraphPart, GraphPart)
stepGen graph step =
    let unusedNodes = findUnused graph (Graph.suc graph (to step))
        unusedLabNodes = filter (\(x,y) -> x `elem` unusedNodes) (Graph.labNodes graph)
        unused = graphPart unusedLabNodes [] Nothing Nothing

        base = doGraphGen (substitutionGen . sub $ step)
        num = head (Graph.newNodes 1 base)
        node = (num, "subst")
        cons = head (filter (\x -> Graph.indeg base x == 0) (Graph.nodes base))
        edge = (num, cons, (2,1))

        substGraph = (Graph.insEdge edge) . (Graph.insNode node) $ base
        subst = makeGraphPart substGraph (Just (num,1)) (Just (num,1))

    in (subst, unused)



findUnused :: PGraph -> [Node] -> [Node]
findUnused graph nodeList =
    let nextLayer = concat . (map (Graph.suc graph)) $ nodeList
        unused = filter (\x -> all (\y -> y `elem` nodeList) (Graph.pre graph x)) nextLayer
    in nodeList ++ (findUnused graph unused)



doMeaningSubst :: PGraph -> PGraph
doMeaningSubst graph =
    let f = (\g termnet nodeList ->
                if (nodeList == [])
                then g
                else let working = head nodeList
                         (termnet', step, between) = checkNode g termnet working
                         (g', nodeList') = if (isNothing step || isNothing between)
                                           then (g, nodeList)
                                           else let (subst, unused) = fromJust step
                                                    (from, to) = fromJust between
                                                    toNodes = map (\(x,(y,z)) -> (x,y)) (Graph.lpre g to)
                                                in ((graphAdd subst (Just (from, 1)) toNodes) . (graphDel unused) $ g,
                                                    nodeList \\ (map (\(x,y) -> x) (nodes unused)))
                     in f g' termnet' nodeList')

    in f graph TermNet.empty (Graph.nodes graph)



main = do
    args <- getArgs
    list <- getLines (head args)
    let graph = doGraphGen (map stripReturn list)
        result = doMeaningSubst graph
    printf $ (show result) ++ "\n"