andres::graph
hdf5/digraph.hxx
1 #pragma once
2 #ifndef ANDRES_GRAPH_DIGRAPH_HDF5_HXX
3 #define ANDRES_GRAPH_DIGRAPH_HDF5_HXX
4 
5 #include <stdexcept>
6 #include <string>
7 #include <vector>
8 
9 #include "hdf5.hxx"
10 #include "../digraph.hxx"
11 
12 namespace andres {
13 namespace graph {
14 namespace hdf5 {
15 
16 template<>
17 template<class VISITOR>
18 struct GraphTraitsHDF5<Digraph<VISITOR> > {
19  static const int ID;
20 };
21 template<class VISITOR>
22  const int GraphTraitsHDF5<Digraph<VISITOR> >::ID = 10001;
23 
24 template <class VISITOR>
25 void save(const hid_t, const std::string&, const Digraph<VISITOR>&);
26 
27 template <class VISITOR>
28 void load(const hid_t, const std::string&, Digraph<VISITOR>&);
29 
30 template <class VISITOR>
31 void
33  const hid_t parentHandle,
34  const std::string& graphName,
35  const Digraph<VISITOR>& graph
36 ) {
37  HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
38  hid_t groupHandle = openGroup(parentHandle, graphName,true);
39 
40  try {
41  save(groupHandle, "graph-type-id", GraphTraitsHDF5<Digraph<VISITOR> >::ID);
42  save(groupHandle, "multiple-edges-enabled", static_cast<unsigned char>(graph.multipleEdgesEnabled()));
43  save(groupHandle, "number-of-vertices", graph.numberOfVertices());
44  save(groupHandle, "number-of-edges", graph.numberOfEdges());
45  if(graph.numberOfEdges() != 0) {
46  std::vector<std::size_t> vecIJ;
47  vecIJ.resize(2 * graph.numberOfEdges());
48  std::size_t *ptrI = &vecIJ[0];
49  std::size_t *ptrJ = &vecIJ[graph.numberOfEdges()];
50  for(std::size_t e=0; e<graph.numberOfEdges(); ++e) {
51  *(ptrI++) = graph.vertexOfEdge(e, 0);
52  *(ptrJ++) = graph.vertexOfEdge(e, 1);
53  }
54  save(groupHandle, "edges", {graph.numberOfEdges(), 2}, &vecIJ[0]);
55  }
56  } catch (std::exception& e) {
57  closeGroup(groupHandle);
58  throw std::runtime_error("error saving digraph: " + std::string(e.what()));
59  }
60 
61  closeGroup(groupHandle);
62 }
63 
64 template <class VISITOR>
65 void
67  const hid_t parentHandle,
68  const std::string& graphName,
69  Digraph<VISITOR>& graph
70 ) {
71  HandleCheck<ANDRES_GRAPH_HDF5_DEBUG> handleCheck;
72  hid_t groupHandle = openGroup(parentHandle, graphName);
73 
74  std::string sError;
75 
76  try {
77  int id = 0;
78  load(groupHandle, "graph-type-id", id);
79  if(id != GraphTraitsHDF5<Digraph<VISITOR> >::ID) {
80  sError = "graph type id mismatch.";
81  goto cleanup;
82  }
83 
84  std::size_t numberOfVertices = 0;
85  load(groupHandle, "number-of-vertices", numberOfVertices);
86 
87  std::size_t numberOfEdges = 0;
88  load(groupHandle, "number-of-edges", numberOfEdges);
89 
90  graph.assign(numberOfVertices);
91 
92  if(numberOfEdges != 0) {
93  graph.reserveEdges(numberOfEdges);
94 
95  std::vector<std::size_t> bufferIJ;
96  {
97  std::vector<std::size_t> shape;
98  load(groupHandle, "edges", shape, bufferIJ);
99  if(shape.size() != 2) {
100  sError = "edges dataset is not 2-dimensional.";
101  goto cleanup;
102  }
103  if(shape[0] != numberOfEdges || shape[1] != 2) {
104  sError = "edges dataset has incorrect shape.";
105  goto cleanup;
106  }
107  assert(shape[0] * 2 == bufferIJ.size());
108  }
109  std::size_t* ptrI = &bufferIJ[0];
110  std::size_t* ptrJ = &bufferIJ[numberOfEdges];
111  {
112  unsigned char multipleEdgesEnabled;
113  load(groupHandle, "multiple-edges-enabled", multipleEdgesEnabled);
114  graph.multipleEdgesEnabled() = static_cast<bool>(multipleEdgesEnabled);
115  }
116  for(std::size_t i=0;i<numberOfEdges;++i) {
117  const std::size_t s = *(ptrI++);
118  const std::size_t t = *(ptrJ++);
119  if(s >= numberOfVertices || t >= numberOfVertices) {
120  sError = "vertex index out of bounds.";
121  goto cleanup;
122  }
123  const std::size_t e = graph.insertEdge(s, t);
124  }
125  }
126  } catch(std::exception& e) {
127  sError = e.what();
128  }
129 
130 cleanup:
131  closeGroup(groupHandle);
132  if(!sError.empty()) {
133  throw std::runtime_error("error loading digraph: " + sError);
134  }
135 }
136 
137 } //namespace hdf
138 } //namespace graph
139 } //namespace andres
140 
141 #endif // #ifndef ANDRES_GRAPH_DIGRAPH_HDF5_HXX