Satsuma
a delicious .NET graph library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
CompleteGraph.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 
28 namespace Satsuma
29 {
38  public sealed class CompleteGraph : IGraph
39  {
42  public bool Directed { get; private set; }
43 
44  private readonly int nodeCount;
45 
46  public CompleteGraph(int nodeCount, Directedness directedness)
47  {
48  this.nodeCount = nodeCount;
49  Directed = (directedness == Directedness.Directed);
50 
51  if (nodeCount < 0) throw new ArgumentException("Invalid node count: " + nodeCount);
52  long arcCount = (long)nodeCount*(nodeCount-1);
53  if (!Directed) arcCount /= 2;
54  if (arcCount > int.MaxValue)
55  throw new ArgumentException("Too many nodes: " + nodeCount);
56  }
57 
60  public Node GetNode(int index)
61  {
62  return new Node(1L + index);
63  }
64 
67  public int GetNodeIndex(Node node)
68  {
69  return (int)(node.Id - 1);
70  }
71 
76  public Arc GetArc(Node u, Node v)
77  {
78  int x = GetNodeIndex(u);
79  int y = GetNodeIndex(v);
80 
81  if (x == y) return Arc.Invalid;
82  if (!Directed && x > y)
83  {
84  var t = x; x = y; y = t;
85  }
86 
87  return GetArcInternal(x, y);
88  }
89 
90  // If !directed, then x < y must be true.
91  private Arc GetArcInternal(int x, int y)
92  {
93  return new Arc(1L + (long)y * nodeCount + x);
94  }
95 
96  public Node U(Arc arc)
97  {
98  return new Node(1L + (arc.Id - 1) % nodeCount);
99  }
100 
101  public Node V(Arc arc)
102  {
103  return new Node(1L + (arc.Id - 1) / nodeCount);
104  }
105 
106  public bool IsEdge(Arc arc)
107  {
108  return !Directed;
109  }
110 
111  public IEnumerable<Node> Nodes()
112  {
113  for (int i = 0; i < nodeCount; i++)
114  yield return GetNode(i);
115  }
116 
117  public IEnumerable<Arc> Arcs(ArcFilter filter = ArcFilter.All)
118  {
119  if (Directed)
120  {
121  for (int i = 0; i < nodeCount; i++)
122  for (int j = 0; j < nodeCount; j++)
123  if (i != j) yield return GetArcInternal(i, j);
124  }
125  else
126  {
127  for (int i = 0; i < nodeCount; i++)
128  for (int j = i+1; j < nodeCount; j++)
129  yield return GetArcInternal(i, j);
130  }
131  }
132 
133  public IEnumerable<Arc> Arcs(Node u, ArcFilter filter = ArcFilter.All)
134  {
135  if (Directed)
136  {
137  if (filter == ArcFilter.Edge) yield break;
138  if (filter != ArcFilter.Forward)
139  foreach (var w in Nodes())
140  if (w != u) yield return GetArc(w, u);
141  }
142  if (!Directed || filter != ArcFilter.Backward)
143  foreach (var w in Nodes())
144  if (w != u) yield return GetArc(u, w);
145  }
146 
147  public IEnumerable<Arc> Arcs(Node u, Node v, ArcFilter filter = ArcFilter.All)
148  {
149  if (Directed)
150  {
151  if (filter == ArcFilter.Edge) yield break;
152  if (filter != ArcFilter.Forward) yield return GetArc(v, u);
153  }
154  if (!Directed || filter != ArcFilter.Backward) yield return GetArc(u, v);
155  }
156 
157  public int NodeCount()
158  {
159  return nodeCount;
160  }
161 
162  public int ArcCount(ArcFilter filter = ArcFilter.All)
163  {
164  var result = nodeCount * (nodeCount - 1);
165  if (!Directed) result /= 2;
166  return result;
167  }
168 
169  public int ArcCount(Node u, ArcFilter filter = ArcFilter.All)
170  {
171  if (!Directed) return nodeCount - 1;
172  switch (filter)
173  {
174  case ArcFilter.All: return 2 * (nodeCount - 1);
175  case ArcFilter.Edge: return 0;
176  default: return nodeCount - 1;
177  }
178  }
179 
180  public int ArcCount(Node u, Node v, ArcFilter filter = ArcFilter.All)
181  {
182  if (!Directed) return 1;
183  switch (filter)
184  {
185  case ArcFilter.All: return 2;
186  case ArcFilter.Edge: return 0;
187  default: return 1;
188  }
189  }
190 
191  public bool HasNode(Node node)
192  {
193  return node.Id >= 1 && node.Id <= nodeCount;
194  }
195 
196  public bool HasArc(Arc arc)
197  {
198  Node v = V(arc);
199  if (!HasNode(v)) return false;
200  Node u = U(arc);
201  // HasNode(u) is always true
202  return Directed || u.Id < v.Id;
203  }
204  }
205 }