Satsuma
a delicious .NET graph library
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
CompleteBipartiteGraph.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 CompleteBipartiteGraph : IGraph
39  {
41  public enum Color
42  {
43  Red,
44  Blue
45  }
46 
48  public int RedNodeCount { get; private set; }
50  public int BlueNodeCount { get; private set; }
53  public bool Directed { get; private set; }
54 
58  public CompleteBipartiteGraph(int redNodeCount, int blueNodeCount, Directedness directedness)
59  {
60  if (redNodeCount < 0 || blueNodeCount < 0)
61  throw new ArgumentException("Invalid node count: " + redNodeCount + ";" + blueNodeCount);
62  if ((long)redNodeCount + blueNodeCount > int.MaxValue ||
63  (long)redNodeCount * blueNodeCount > int.MaxValue)
64  throw new ArgumentException("Too many nodes: " + redNodeCount + ";" + blueNodeCount);
65 
66  RedNodeCount = redNodeCount;
67  BlueNodeCount = blueNodeCount;
68  Directed = (directedness == Directedness.Directed);
69  }
70 
73  public Node GetRedNode(int index)
74  {
75  return new Node(1L + index);
76  }
77 
80  public Node GetBlueNode(int index)
81  {
82  return new Node(1L + RedNodeCount + index);
83  }
84 
85  public bool IsRed(Node node)
86  {
87  return node.Id <= RedNodeCount;
88  }
89 
94  public Arc GetArc(Node u, Node v)
95  {
96  bool ured = IsRed(u);
97  bool vred = IsRed(v);
98 
99  if (ured == vred) return Arc.Invalid;
100  if (vred)
101  {
102  var t = u; u = v; v = t;
103  }
104 
105  int uindex = (int)(u.Id - 1);
106  int vindex = (int)(v.Id - RedNodeCount - 1);
107 
108  return new Arc(1 + (long)vindex * RedNodeCount + uindex);
109  }
110 
112  public Node U(Arc arc)
113  {
114  return new Node(1L + (arc.Id - 1) % RedNodeCount);
115  }
116 
118  public Node V(Arc arc)
119  {
120  return new Node(1L + RedNodeCount + (arc.Id - 1) / RedNodeCount);
121  }
122 
123  public bool IsEdge(Arc arc)
124  {
125  return !Directed;
126  }
127 
129  public IEnumerable<Node> Nodes(Color color)
130  {
131  switch (color)
132  {
133  case Color.Red:
134  for (int i = 0; i < RedNodeCount; i++)
135  yield return GetRedNode(i);
136  break;
137 
138  case Color.Blue:
139  for (int i = 0; i < BlueNodeCount; i++)
140  yield return GetBlueNode(i);
141  break;
142  }
143  }
144 
145  public IEnumerable<Node> Nodes()
146  {
147  for (int i = 0; i < RedNodeCount; i++)
148  yield return GetRedNode(i);
149  for (int i = 0; i < BlueNodeCount; i++)
150  yield return GetBlueNode(i);
151  }
152 
153  public IEnumerable<Arc> Arcs(ArcFilter filter = ArcFilter.All)
154  {
155  if (Directed && filter == ArcFilter.Edge) yield break;
156 
157  for (int i = 0; i < RedNodeCount; i++)
158  for (int j = 0; j < BlueNodeCount; j++)
159  yield return GetArc(GetRedNode(i), GetBlueNode(j));
160  }
161 
162  public IEnumerable<Arc> Arcs(Node u, ArcFilter filter = ArcFilter.All)
163  {
164  bool isRed = IsRed(u);
165  if (Directed && (filter == ArcFilter.Edge ||
166  (filter == ArcFilter.Forward && !isRed) ||
167  (filter == ArcFilter.Backward && isRed))) yield break;
168 
169  if (isRed)
170  {
171  for (int i = 0; i < BlueNodeCount; i++)
172  yield return GetArc(u, GetBlueNode(i));
173  }
174  else
175  {
176  for (int i = 0; i < RedNodeCount; i++)
177  yield return GetArc(GetRedNode(i), u);
178  }
179  }
180 
181  public IEnumerable<Arc> Arcs(Node u, Node v, ArcFilter filter = ArcFilter.All)
182  {
183  Arc arc = GetArc(u, v);
184  if (arc != Arc.Invalid && ArcCount(u, filter) > 0) yield return arc;
185  }
186 
187  public int NodeCount()
188  {
189  return RedNodeCount + BlueNodeCount;
190  }
191 
192  public int ArcCount(ArcFilter filter = ArcFilter.All)
193  {
194  if (Directed && filter == ArcFilter.Edge) return 0;
195  return RedNodeCount * BlueNodeCount;
196  }
197 
198  public int ArcCount(Node u, ArcFilter filter = ArcFilter.All)
199  {
200  bool isRed = IsRed(u);
201  if (Directed && (filter == ArcFilter.Edge ||
202  (filter == ArcFilter.Forward && !isRed) ||
203  (filter == ArcFilter.Backward && isRed))) return 0;
204 
205  return isRed ? BlueNodeCount : RedNodeCount;
206  }
207 
208  public int ArcCount(Node u, Node v, ArcFilter filter = ArcFilter.All)
209  {
210  if (IsRed(u) == IsRed(v)) return 0;
211  return ArcCount(u, filter) > 0 ? 1 : 0;
212  }
213 
214  public bool HasNode(Node node)
215  {
216  return node.Id >= 1 && node.Id <= RedNodeCount + BlueNodeCount;
217  }
218 
219  public bool HasArc(Arc arc)
220  {
221  return arc.Id >= 1 && arc.Id <= RedNodeCount * BlueNodeCount;
222  }
223  }
224 }