I am trying to implement Floyd-Warshall Algorithm. To do this it requires me to set up an adjacency matrix
of a weighted graph. How would I go about doing this? I
So, you seem not to be familiarized with Graphs, take a look at Wikipedia. Also browse for some images, it gets easier to understand.
Your picture can be represented as a Graph
. Generally graphs are implemented using 2 basic kinds of elements, Nodes
and Links
(sometimes called Arcs
).
A Node
represent the letters in your picture, they would be A, B, C, etc.
An Arc
or Link
, is the line that connect two nodes, if you look the connection between H to L, the have a link between the two, in a weighted graph, different links have different weights.
What we have to do is represent your picture as a graph in the code, so let's start creating the basic elements Node
and Arc
:
Node
A node has a Name
, so we can identify the node. And a node can be connected to other nodes, we could use a collection of Nodes, but yours is a weighted graph, so, each of the connections has to be represented by the linked node and it's weight. Therefore, we use a collection of Arcs.
public class Node
{
public string Name;
public List Arcs = new List();
public Node(string name)
{
Name = name;
}
///
/// Create a new arc, connecting this Node to the Nod passed in the parameter
/// Also, it creates the inversed node in the passed node
///
public Node AddArc(Node child, int w)
{
Arcs.Add(new Arc
{
Parent = this,
Child = child,
Weigth = w
});
if (!child.Arcs.Exists(a => a.Parent == child && a.Child == this))
{
child.AddArc(this, w);
}
return this;
}
}
Arc
Really simple class, it contains the linked nodes, and the weight of the connection:
public class Arc
{
public int Weigth;
public Node Parent;
public Node Child;
}
Graph
Graph is a kind of wrapper class, for organization purposes. I also have declared a Root for the graph, we're not using it, but is useful in several cases:
public class Graph
{
public Node Root;
public List AllNodes = new List();
public Node CreateRoot(string name)
{
Root = CreateNode(name);
return Root;
}
public Node CreateNode(string name)
{
var n = new Node(name);
AllNodes.Add(n);
return n;
}
public int?[,] CreateAdjMatrix()
{
// Matrix will be created here...
}
}
Now we have all the data structure for holding the graph, let's fill it with some data. Here's some code that initializes a graph similar to your cube picture. It's boring and dull, but in real life cases, the graph will be created dynamically:
static void Main(string[] args)
{
var graph = new Graph();
var a = graph.CreateRoot("A");
var b = graph.CreateNode("B");
var c = graph.CreateNode("C");
var d = graph.CreateNode("D");
var e = graph.CreateNode("E");
var f = graph.CreateNode("F");
var g = graph.CreateNode("G");
var h = graph.CreateNode("H");
var i = graph.CreateNode("I");
var j = graph.CreateNode("J");
var k = graph.CreateNode("K");
var l = graph.CreateNode("L");
var m = graph.CreateNode("M");
var n = graph.CreateNode("N");
var o = graph.CreateNode("O");
var p = graph.CreateNode("P");
a.AddArc(b, 1)
.AddArc(c, 1);
b.AddArc(e, 1)
.AddArc(d, 3);
c.AddArc(f, 1)
.AddArc(d, 3);
c.AddArc(f, 1)
.AddArc(d, 3);
d.AddArc(h, 8);
e.AddArc(g, 1)
.AddArc(h, 3);
f.AddArc(h, 3)
.AddArc(i, 1);
g.AddArc(j, 3)
.AddArc(l, 1);
h.AddArc(j, 8)
.AddArc(k, 8)
.AddArc(m, 3);
i.AddArc(k, 3)
.AddArc(n, 1);
j.AddArc(o, 3);
k.AddArc(p, 3);
l.AddArc(o, 1);
m.AddArc(o, 1)
.AddArc(p, 1);
n.AddArc(p, 1);
// o - Already added
// p - Already added
int?[,] adj = graph.CreateAdjMatrix(); // We're going to implement that down below
PrintMatrix(ref adj, graph.AllNodes.Count); // We're going to implement that down below
}
So, we have a completelly initialized graph, let's create the matrix. The next method creates a matrix of two dimensions, n by n, where n is the number of node we get from the graph class. Foreach of the nodes, we search if they have a link, if they have a link, a filled the matrix in the appropriate position. Look that in your adjacency matrix example, you only have 1
s, here I put the weight of the link, I've put this way, so there's no sense in having a weighted graph!
public int?[,] CreateAdjMatrix()
{
int?[,] adj = new int?[AllNodes.Count, AllNodes.Count];
for (int i = 0; i < AllNodes.Count; i++)
{
Node n1 = AllNodes[i];
for (int j = 0; j < AllNodes.Count; j++)
{
Node n2 = AllNodes[j];
var arc = n1.Arcs.FirstOrDefault(a => a.Child == n2);
if (arc != null)
{
adj[i, j] = arc.Weigth;
}
}
}
return adj;
}
That's done, you have your weighted adjacency matrix, some way to print it:
private static void PrintMatrix(ref int?[,] matrix, int Count)
{
Console.Write(" ");
for (int i = 0; i < Count; i++)
{
Console.Write("{0} ", (char)('A' + i));
}
Console.WriteLine();
for (int i = 0; i < Count; i++)
{
Console.Write("{0} | [ ", (char)('A' + i));
for (int j = 0; j < Count; j++)
{
if (i == j)
{
Console.Write(" &,");
}
else if (matrix[i, j] == null)
{
Console.Write(" .,");
}
else
{
Console.Write(" {0},", matrix[i, j]);
}
}
Console.Write(" ]\r\n");
}
Console.Write("\r\n");
}
What give us the following output:
A B C D E F G H I J K L M N O P
A | [ &, 1, 1, ., ., ., ., ., ., ., ., ., ., ., ., ., ]
B | [ 1, &, ., 3, 1, ., ., ., ., ., ., ., ., ., ., ., ]
C | [ 1, ., &, 3, ., 1, ., ., ., ., ., ., ., ., ., ., ]
D | [ ., 3, 3, &, ., ., ., 8, ., ., ., ., ., ., ., ., ]
E | [ ., 1, ., ., &, ., 1, 3, ., ., ., ., ., ., ., ., ]
F | [ ., ., 1, ., ., &, ., 3, 1, ., ., ., ., ., ., ., ]
G | [ ., ., ., ., 1, ., &, ., ., 3, ., 1, ., ., ., ., ]
H | [ ., ., ., 8, 3, 3, ., &, ., 8, 8, ., 3, ., ., ., ]
I | [ ., ., ., ., ., 1, ., ., &, ., 3, ., ., 1, ., ., ]
J | [ ., ., ., ., ., ., 3, 8, ., &, ., ., ., ., 3, ., ]
K | [ ., ., ., ., ., ., ., 8, 3, ., &, ., ., ., ., 3, ]
L | [ ., ., ., ., ., ., 1, ., ., ., ., &, ., ., 1, ., ]
M | [ ., ., ., ., ., ., ., 3, ., ., ., ., &, ., 1, 1, ]
N | [ ., ., ., ., ., ., ., ., 1, ., ., ., ., &, ., 1, ]
O | [ ., ., ., ., ., ., ., ., ., 3, ., 1, 1, ., &, ., ]
P | [ ., ., ., ., ., ., ., ., ., ., 3, ., 1, 1, ., &, ]