File: graph-minor.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (139 lines) | stat: -rw-r--r-- 5,067 bytes parent folder | download | duplicates (5)
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
(*
 *  Graph minor.
 *  Allows contraction of nodes.  
 *  Remove self-edges during contraction. 
 *  
 *  -- Allen
 *) 
signature GRAPH_MINOR_VIEW =
sig

   val minor : ('n,'e,'g) Graph.graph
            -> ('n * 'n * 'e Graph.edge list -> 'n)
            -> { view  : ('n,'e,'g) Graph.graph,
                 union : Graph.node_id * Graph.node_id -> bool,
                 ==    : Graph.node_id * Graph.node_id -> bool,
                 partition : Graph.node_id -> Graph.node_id list 
               }

end

structure GraphMinorView : GRAPH_MINOR_VIEW =
struct

   structure G = Graph
   structure U = URef
   structure H = HashArray

   datatype ('n,'e) node = 
      NODE of { key   : int,
                data  : 'n,
                nodes : Graph.node_id list,
                succ  : 'e G.edge list,
                pred  : 'e G.edge list
              }

   fun minor(G.GRAPH G : ('n,'e,'g) Graph.graph) merge_nodes =
   let fun unimplemented _ = raise G.Readonly
       val N     = #capacity G ()
       val table = H.array'(N,fn _ => raise G.NotFound)
       fun get n = let val NODE x = U.!!(H.sub(table,n)) in x end
       val _ = #forall_nodes G 
                (fn (n,n') => 
                    H.update(table,n,
                       U.uRef(NODE{key=n,
                                   data=n',
                                   nodes=[n],
                                   succ= #out_edges G n,
                                   pred= #in_edges G n})))
       fun same(i,j) = U.equal (H.sub(table,i),H.sub(table,j))
       fun partition i = #nodes(get i) 
       val size  = ref (#size G ())
       val order = ref (#order G ())
       fun out_edges n = #succ(get n)
       fun in_edges n = #pred(get n)
       fun succ n  = map #2 (out_edges n)
       fun pred n  = map #1 (in_edges n) 
       fun nodes() = 
           let val found = H.array(10,false)
               fun collect((node as (n,_))::nodes,nodes') =
                   if H.sub(found,n) then collect(nodes,nodes')
                   else let val ns = partition n
                        in  app (fn n => H.update(found,n,true)) ns;
                            collect(nodes,node::nodes')
                        end
                 | collect([],nodes') = nodes'
           in collect(#nodes G (),[])
           end
       fun edges() = List.concat (map (fn (n,_) => out_edges n) (nodes()))
       fun has_edge(i,j) =
           List.exists (fn (_,j',_) => j = j') (out_edges i)
       fun has_node n = (H.sub(table,n);true) handle G.NotFound => false 
       fun node_info n = #data(get n)
       fun forall_nodes f = app f (nodes())
       fun forall_edges f = app f (edges())
       fun merge(NODE{key=k1,data=d1,succ=s1,pred=p1,nodes=n1},
                 NODE{key=k2,data=d2,succ=s2,pred=p2,nodes=n2}) =
       let fun key i = #key(get i)
           fun partition([],others,self) = (others,self)
             | partition((e as (i,j,_))::es,others,self) =
                let val k_i = key i
                    val k_j = key j
                in   if (k_i = k1 orelse k_i = k2) andalso   
                        (k_j = k1 orelse k_j = k2) then 
                          partition(es,others,e::self)  
                     else partition(es,e::others,self)
                end
           val (s,s') = partition(s1@s2,[],[])
           val (p,p') = partition(p1@p2,[],[])
           val n = NODE{key=k1,
                        data=merge_nodes(d1,d2,s'),
                        nodes=n1@n2, 
                        succ=s,
                        pred=p
                       } 
           val _ = order := !order - 1
           val _ = size  := !size - length s'
       in  n
       end
       fun union(i,j) = U.unify merge (H.sub(table,i),H.sub(table,j))
       val view =
       G.GRAPH
       { name            = #name G,
         graph_info      = #graph_info G,
         new_id          = unimplemented,
         add_node        = unimplemented,
         add_edge        = unimplemented,
         remove_node     = unimplemented,
         set_in_edges    = unimplemented,
         set_out_edges   = unimplemented,
         set_entries     = unimplemented,
         set_exits       = unimplemented,
         garbage_collect = unimplemented,
         nodes           = nodes,
         edges           = edges,
         order           = fn () => !order,
         size            = fn () => !size,
         capacity        = #capacity G,
         out_edges       = out_edges,
         in_edges        = in_edges,
         succ            = succ,
         pred            = pred,
         has_edge        = has_edge,
         has_node        = has_node,
         node_info       = node_info,
         entries         = #entries G,
         exits           = #exits G,
         entry_edges     = #entry_edges G,
         exit_edges      = #exit_edges G,
         forall_nodes    = forall_nodes, 
         forall_edges    = forall_edges
       }
   in  { view  = view,
         union = union,
         ==    = same,
         partition = partition
       }
   end
end