Satsuma
a delicious .NET graph library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
ContractedGraph.cs
Go to the documentation of this file.
1 #region License
2 /*This file is part of Satsuma Graph Library
3 Copyright © 2013 Balázs Szalkai
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17 
18  2. Altered source versions must be plainly marked as such, and must not be
19  misrepresented as being the original software.
20 
21  3. This notice may not be removed or altered from any source
22  distribution.*/
23 #endregion
24 
25 using System;
26 using System.Collections.Generic;
27 using System.Linq;
28 
29 namespace Satsuma
30 {
37  public sealed class ContractedGraph : IGraph
38  {
39  private IGraph graph;
40  private DisjointSet<Node> nodeGroups;
41  private int unionCount;
42 
43  public ContractedGraph(IGraph graph)
44  {
45  this.graph = graph;
46  nodeGroups = new DisjointSet<Node>();
47  Reset();
48  }
49 
51  public void Reset()
52  {
53  nodeGroups.Clear();
54  unionCount = 0;
55  }
56 
61  {
62  return nodeGroups.WhereIs(n).Representative;
63  }
64 
68  public IEnumerable<Node> GetChildren(Node n)
69  {
70  return nodeGroups.Elements(nodeGroups.WhereIs(n));
71  }
72 
77  public Node Merge(Node u, Node v)
78  {
79  var x = nodeGroups.WhereIs(u);
80  var y = nodeGroups.WhereIs(v);
81  if (x.Equals(y)) return x.Representative;
82  unionCount++;
83  return nodeGroups.Union(x, y).Representative;
84  }
85 
89  public Node Contract(Arc arc)
90  {
91  return Merge(graph.U(arc), graph.V(arc));
92  }
93 
94  public Node U(Arc arc)
95  {
96  return GetRepresentative(graph.U(arc));
97  }
98 
99  public Node V(Arc arc)
100  {
101  return GetRepresentative(graph.V(arc));
102  }
103 
104  public bool IsEdge(Arc arc)
105  {
106  return graph.IsEdge(arc);
107  }
108 
109  public IEnumerable<Node> Nodes()
110  {
111  foreach (var node in graph.Nodes())
112  if (GetRepresentative(node) == node) yield return node;
113  }
114 
115  public IEnumerable<Arc> Arcs(ArcFilter filter = ArcFilter.All)
116  {
117  return graph.Arcs(filter);
118  }
119 
120  public IEnumerable<Arc> Arcs(Node u, ArcFilter filter = ArcFilter.All)
121  {
122  foreach (var node in GetChildren(u))
123  {
124  foreach (var arc in graph.Arcs(node, filter))
125  {
126  bool loop = (U(arc) == V(arc));
127  // we should avoid outputting an arc twice
128  if (!loop || !(filter == ArcFilter.All || IsEdge(arc)) || graph.U(arc) == node)
129  yield return arc;
130  }
131  }
132  }
133 
134  public IEnumerable<Arc> Arcs(Node u, Node v, ArcFilter filter = ArcFilter.All)
135  {
136  foreach (var arc in Arcs(u, filter))
137  if (this.Other(arc, u) == v) yield return arc;
138  }
139 
140  public int NodeCount()
141  {
142  return graph.NodeCount() - unionCount;
143  }
144 
145  public int ArcCount(ArcFilter filter = ArcFilter.All)
146  {
147  return graph.ArcCount(filter);
148  }
149 
150  public int ArcCount(Node u, ArcFilter filter = ArcFilter.All)
151  {
152  return Arcs(u, filter).Count();
153  }
154 
155  public int ArcCount(Node u, Node v, ArcFilter filter = ArcFilter.All)
156  {
157  return Arcs(u, v, filter).Count();
158  }
159 
160  public bool HasNode(Node node)
161  {
162  return node == GetRepresentative(node);
163  }
164 
165  public bool HasArc(Arc arc)
166  {
167  return graph.HasArc(arc);
168  }
169  }
170 }