Listing 3
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/graphviz.hpp>
namespace ublas = boost::numeric::ublas;
typedef ublas::sparse_matrix<double> spmd;
typedef boost::GraphvizDigraph Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor VertexDescriptor;
typedef boost::graph_traits<Graph>::edge_descriptor EdgeDescriptor;
void GraphRowMajor(const spmd& M, std::string dotFile);
void GraphColMajor(const spmd& M, std::string dotFile);
int main()
{
// Construct a sample sparse matrix
spmd M(5, 5);
M(0,0) = 11; M(0,2) = 13;
M(1,0) = 21; M(1,1) = 22;
M(2,2) = 33; M(2,4) = 35;
M(3,3) = 44;
M(4,0) = 52; M(4,4) = 55;
// Construct its row-major and column-major representation
GraphRowMajor(M, "row.dot");
GraphColMajor(M, "col.dot");
}
void GraphRowMajor(const spmd& M, std::string dotFile)
{
// The graph that will represent the matrix
Graph matrixGraph;
// Assign some graph attributes
boost::graph_property<Graph, boost::graph_graph_attribute_t>::
type& graphAttr = boost::get_property(matrixGraph,
boost::graph_graph_attribute);
graphAttr["name"] = "MatrixRowMajor";
graphAttr["rankdir"] = "LR";
// Assign some properties to all nodes of the graph
boost::graph_property<Graph, boost::graph_vertex_attribute_t>::
type& graphVertAttr = boost::get_property(matrixGraph,
boost::graph_vertex_attribute);
graphVertAttr["shape"] = "record";
graphVertAttr["height"] = "0.1";
// Get the propery maps for node (vertex) and edge attributes
const boost::property_map<Graph, boost::vertex_attribute_t>::
type& vertAttr = boost::get(boost::vertex_attribute, matrixGraph);
const boost::property_map<Graph, boost::edge_attribute_t>::
type& edgeAttr = boost::get(boost::edge_attribute, matrixGraph);
// Process the matrix
VertexDescriptor prevHead, curHead;
EdgeDescriptor edge;
bool inserted;
// Cheat: add a vertex to represent the matrix. Format it differently
curHead = boost::add_vertex(matrixGraph);
vertAttr[curHead]["shape"] = "diamond";
vertAttr[curHead]["label"] = "M";
// Iterate through its rows
for (spmd::const_iterator1 it1 = M.begin1(); it1 != M.end1(); ++it1) {
prevHead = curHead;
// Add a vertex for the row head
curHead = boost::add_vertex(matrixGraph);
vertAttr[curHead]["shape"] = "box";
vertAttr[curHead]["label"] = boost::
lexical_cast<std::string>(it1.index1());
// Connect it with the previous row head
tie(edge, inserted) = boost::add_edge(prevHead, curHead, matrixGraph);
edgeAttr[edge]["constraint"] = "false";
edgeAttr[edge]["color"] = "grey";
// Add row elements
VertexDescriptor prevNode, curNode;
prevNode = curHead;
spmd::const_iterator2 it2 = it1.begin();
while (it2 != it1.end()) {
curNode = boost::add_vertex(matrixGraph);
vertAttr[curNode]["label"] =
"{" + boost::lexical_cast<std::string>(it2.index2()) +
" | " + boost::lexical_cast<std::string>(*it2) + "}";
tie(edge,inserted)= boost::add_edge(prevNode,curNode,matrixGraph);
prevNode = curNode;
++it2;
}
}
// Write the dot file
boost::write_graphviz(dotFile, matrixGraph);
}
void GraphColMajor(const spmd& M, std::string dotFile)
{
// The graph that will represent the matrix
Graph matrixGraph;
// Assign some graph attributes
boost::graph_property<Graph, boost::graph_graph_attribute_t>::
type& graphAttr = boost::get_property(matrixGraph,
boost::graph_graph_attribute);
graphAttr["name"] = "MatrixColMajor";
graphAttr["rankdir"] = "TB";
// Assign some properties to all nodes of the graph
boost::graph_property<Graph, boost::graph_vertex_attribute_t>::
type& graphVertAttr = boost::get_property(matrixGraph,
boost::graph_vertex_attribute);
graphVertAttr["shape"] = "record";
graphVertAttr["height"] = "0.1";
// Get the propery maps for node (vertex) and edge attributes
const boost::property_map<Graph, boost::vertex_attribute_t>::
type& vertAttr = boost::get(boost::vertex_attribute, matrixGraph);
const boost::property_map<Graph, boost::edge_attribute_t>::
type& edgeAttr = boost::get(boost::edge_attribute, matrixGraph);
// Process the matrix
VertexDescriptor prevHead, curHead;
EdgeDescriptor edge;
bool inserted;
// Cheat: add a vertex to represent the matrix. Format it differently
curHead = boost::add_vertex(matrixGraph);
vertAttr[curHead]["shape"] = "diamond";
vertAttr[curHead]["label"] = "M";
// Iterate through its columns
for (spmd::const_iterator2 it2 = M.begin2(); it2 != M.end2(); ++it2) {
prevHead = curHead;
// Add a vertex for the column head
curHead = boost::add_vertex(matrixGraph);
vertAttr[curHead]["shape"] = "box";
vertAttr[curHead]["label"] =
boost::lexical_cast<std::string>(it2.index2());
// Connect it with the previous column head
tie(edge, inserted) =
boost::add_edge(prevHead, curHead, matrixGraph);
edgeAttr[edge]["constraint"] = "false";
edgeAttr[edge]["color"] = "grey";
// Add column elements
VertexDescriptor prevNode, curNode;
prevNode = curHead;
spmd::const_iterator1 it1 = it2.begin();
while (it1 != it2.end()) {
curNode = boost::add_vertex(matrixGraph);
vertAttr[curNode]["label"] =
boost::lexical_cast<std::string>(it1.index1()) +
" | " + boost::lexical_cast<std::string>(*it1);
tie(edge, inserted) =
boost::add_edge(prevNode, curNode, matrixGraph);
prevNode = curNode;
++it1;
}
}
// Write the dot file
boost::write_graphviz(dotFile, matrixGraph);
}