summaryrefslogtreecommitdiff
path: root/Source/Core/GraphAlgorithms.ssc
blob: e1303316d0939886b42827b61ff003b20fa6d49f (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
167
168
169
170
171
172
173
174
175
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System.Collections.Generic;
using Microsoft.Contracts;

namespace Microsoft.Boogie
{
  public delegate System.Collections.IEnumerable/*<Node!>*/! Adjacency<T>(T! node);


  // An SCC is a set of nodes
  public sealed class SCC<Node> : ICollection<Node>
  {
    private IDictionary<Node,object>! nodesMap = new Dictionary<Node,object>();
    private ICollection<Node>! nodes { get { return (!) nodesMap.Keys; } }
    
    [Pure] [GlobalAccess(false)] [Escapes(true,false)]
    System.Collections.IEnumerator! System.Collections.IEnumerable.GetEnumerator()
    {
      return ((System.Collections.IEnumerable)nodes).GetEnumerator();
    }

    [Pure] [GlobalAccess(false)] [Escapes(true,false)]
    IEnumerator<Node>! IEnumerable<Node>.GetEnumerator()
    {
      return ((IEnumerable<Node>)nodes).GetEnumerator();
    }
    
    public int Count { get { return nodes.Count; } }
    public bool IsReadOnly { get { return nodesMap.IsReadOnly; } }
    public void Add(Node item) { nodesMap.Add(item,null); }
    public void Clear() { nodesMap.Clear(); }
    [Pure]
    public bool Contains(Node item) { return nodesMap.ContainsKey(item); }
    public void CopyTo(Node[]! array, int arrayIndex) { nodes.CopyTo(array, arrayIndex); }
    public bool Remove(Node item) { return nodesMap.Remove(item); }
  }

  public sealed class StronglyConnectedComponents<Node> : IEnumerable<SCC<Node>!>
  {
    private readonly IDictionary<Node!,object>! graph;
    private readonly Adjacency<Node>! preds;
    private readonly Adjacency<Node>! succs;

    private bool computed = false;
    public bool Computed { get { return computed; } }
    
    [NotDelayed]
    public StronglyConnectedComponents(System.Collections.IEnumerable/*<Node!>*/! graph, Adjacency<Node>! preds, Adjacency<Node>! succs)
      ensures !Computed;
    {
      IDictionary<Node!,object>! dict = new Dictionary<Node!,object>();
      foreach (Node! n in graph) { dict.Add(n,null); } 
      
      this.graph = dict;
      this.preds = preds;
      this.succs = succs;
      base();
    }
          
    [Pure] [GlobalAccess(false)] [Escapes(true,false)]
    System.Collections.IEnumerator! System.Collections.IEnumerable.GetEnumerator()
    {
      return ((System.Collections.IEnumerable)sccs).GetEnumerator();
    }

    [Pure] [GlobalAccess(false)] [Escapes(true,false)]
    IEnumerator<SCC<Node>!>! IEnumerable<SCC<Node>!>.GetEnumerator()
    {
      assume Computed;
      return ((IEnumerable<SCC<Node>!>)sccs).GetEnumerator();
    }

    private readonly IList<SCC<Node>!>! sccs = new List<SCC<Node>!>();

    public void Compute()
      requires !Computed;
      ensures  Computed;
    {
      // Compute post times on graph with edges reversed
      this.dfsNext = this.preds;
      foreach (Node! n in (!)graph.Keys)
      {
        if (!seen.ContainsKey(n))
        {
          OrderNodes(n);
        }
      }

      // Clear seen
      seen.Clear();

      // Compute SCCs
      this.dfsNext = this.succs;
      while (postOrder.Count > 0)
      {
        Node! n = postOrder.Pop();

        if (!seen.ContainsKey(n))
        {
          SCC<Node>! curr = new SCC<Node>();
          FindSCCs(n, curr);
          sccs.Add(curr);
        }
      }

      // Clear seen
      seen.Clear();
      
      this.computed = true;
    }

    private Adjacency<Node>/*?*/ dfsNext = null;

    private readonly IDictionary<Node!,object>! seen = new Dictionary<Node!,object>();
    private readonly Stack<Node!>! postOrder = new Stack<Node!>();
    
    // DFS to order nodes by post times
    private void OrderNodes(Node! node)
    {
      seen.Add(node,null);

      assert dfsNext != null;
      System.Collections.IEnumerable! nexts = dfsNext(node);
      foreach (Node! n in nexts)
      {
        if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { OrderNodes(n); }
      }

      postOrder.Push(node);
    }

    // DFS to compute SCCs
    private void FindSCCs(Node! node, SCC<Node>! currSCC)
      //modifies currSCC.*;
    {
      seen.Add(node,null);
      currSCC.Add(node);

      assert dfsNext != null;
      System.Collections.IEnumerable! nexts = dfsNext(node);
      foreach (Node! n in nexts)
      {
        if (graph.ContainsKey(n) && !seen.ContainsKey(n)) { FindSCCs(n,currSCC); }
      }
    }

    [Pure]
    public override string! ToString()
    {
      string outStr = "";
      int i = 0;

      foreach(ICollection<Node> component in this) 
      {      
        string! tmp = System.String.Format("\nComponent #{0} = ", i++);
        outStr += tmp;

        bool firstInRow = true;

        foreach(Node b in component)
        {
          string! tmpComponent = System.String.Format("{0}{1}", firstInRow? "" : ", ", b);
          outStr += tmpComponent;
          firstInRow = false;
        }
      }
      return outStr;
    }

  }
}