• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // PBQP Graph class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 
15 #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
16 #define LLVM_CODEGEN_PBQP_GRAPH_H
17 
18 #include "Math.h"
19 
20 #include <list>
21 #include <map>
22 
23 namespace PBQP {
24 
25   /// PBQP Graph class.
26   /// Instances of this class describe PBQP problems.
27   class Graph {
28   private:
29 
30     // ----- TYPEDEFS -----
31     class NodeEntry;
32     class EdgeEntry;
33 
34     typedef std::list<NodeEntry> NodeList;
35     typedef std::list<EdgeEntry> EdgeList;
36 
37   public:
38 
39     typedef NodeList::iterator NodeItr;
40     typedef NodeList::const_iterator ConstNodeItr;
41 
42     typedef EdgeList::iterator EdgeItr;
43     typedef EdgeList::const_iterator ConstEdgeItr;
44 
45   private:
46 
47     typedef std::list<EdgeItr> AdjEdgeList;
48 
49   public:
50 
51     typedef AdjEdgeList::iterator AdjEdgeItr;
52 
53   private:
54 
55     class NodeEntry {
56     private:
57       Vector costs;
58       AdjEdgeList adjEdges;
59       unsigned degree;
60       void *data;
61     public:
NodeEntry(const Vector & costs)62       NodeEntry(const Vector &costs) : costs(costs), degree(0) {}
getCosts()63       Vector& getCosts() { return costs; }
getCosts()64       const Vector& getCosts() const { return costs; }
getDegree()65       unsigned getDegree() const { return degree; }
edgesBegin()66       AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
edgesEnd()67       AdjEdgeItr edgesEnd() { return adjEdges.end(); }
addEdge(EdgeItr e)68       AdjEdgeItr addEdge(EdgeItr e) {
69         ++degree;
70         return adjEdges.insert(adjEdges.end(), e);
71       }
removeEdge(AdjEdgeItr ae)72       void removeEdge(AdjEdgeItr ae) {
73         --degree;
74         adjEdges.erase(ae);
75       }
setData(void * data)76       void setData(void *data) { this->data = data; }
getData()77       void* getData() { return data; }
78     };
79 
80     class EdgeEntry {
81     private:
82       NodeItr node1, node2;
83       Matrix costs;
84       AdjEdgeItr node1AEItr, node2AEItr;
85       void *data;
86     public:
EdgeEntry(NodeItr node1,NodeItr node2,const Matrix & costs)87       EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs)
88         : node1(node1), node2(node2), costs(costs) {}
getNode1()89       NodeItr getNode1() const { return node1; }
getNode2()90       NodeItr getNode2() const { return node2; }
getCosts()91       Matrix& getCosts() { return costs; }
getCosts()92       const Matrix& getCosts() const { return costs; }
setNode1AEItr(AdjEdgeItr ae)93       void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
getNode1AEItr()94       AdjEdgeItr getNode1AEItr() { return node1AEItr; }
setNode2AEItr(AdjEdgeItr ae)95       void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; }
getNode2AEItr()96       AdjEdgeItr getNode2AEItr() { return node2AEItr; }
setData(void * data)97       void setData(void *data) { this->data = data; }
getData()98       void *getData() { return data; }
99     };
100 
101     // ----- MEMBERS -----
102 
103     NodeList nodes;
104     unsigned numNodes;
105 
106     EdgeList edges;
107     unsigned numEdges;
108 
109     // ----- INTERNAL METHODS -----
110 
getNode(NodeItr nItr)111     NodeEntry& getNode(NodeItr nItr) { return *nItr; }
getNode(ConstNodeItr nItr)112     const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; }
113 
getEdge(EdgeItr eItr)114     EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; }
getEdge(ConstEdgeItr eItr)115     const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; }
116 
addConstructedNode(const NodeEntry & n)117     NodeItr addConstructedNode(const NodeEntry &n) {
118       ++numNodes;
119       return nodes.insert(nodes.end(), n);
120     }
121 
addConstructedEdge(const EdgeEntry & e)122     EdgeItr addConstructedEdge(const EdgeEntry &e) {
123       assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() &&
124              "Attempt to add duplicate edge.");
125       ++numEdges;
126       EdgeItr edgeItr = edges.insert(edges.end(), e);
127       EdgeEntry &ne = getEdge(edgeItr);
128       NodeEntry &n1 = getNode(ne.getNode1());
129       NodeEntry &n2 = getNode(ne.getNode2());
130       // Sanity check on matrix dimensions:
131       assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
132              (n2.getCosts().getLength() == ne.getCosts().getCols()) &&
133              "Edge cost dimensions do not match node costs dimensions.");
134       ne.setNode1AEItr(n1.addEdge(edgeItr));
135       ne.setNode2AEItr(n2.addEdge(edgeItr));
136       return edgeItr;
137     }
138 
139     inline void copyFrom(const Graph &other);
140   public:
141 
142     /// \brief Construct an empty PBQP graph.
Graph()143     Graph() : numNodes(0), numEdges(0) {}
144 
145     /// \brief Copy construct this graph from "other". Note: Does not copy node
146     ///        and edge data, only graph structure and costs.
147     /// @param other Source graph to copy from.
Graph(const Graph & other)148     Graph(const Graph &other) : numNodes(0), numEdges(0) {
149       copyFrom(other);
150     }
151 
152     /// \brief Make this graph a copy of "other". Note: Does not copy node and
153     ///        edge data, only graph structure and costs.
154     /// @param other The graph to copy from.
155     /// @return A reference to this graph.
156     ///
157     /// This will clear the current graph, erasing any nodes and edges added,
158     /// before copying from other.
159     Graph& operator=(const Graph &other) {
160       clear();
161       copyFrom(other);
162       return *this;
163     }
164 
165     /// \brief Add a node with the given costs.
166     /// @param costs Cost vector for the new node.
167     /// @return Node iterator for the added node.
addNode(const Vector & costs)168     NodeItr addNode(const Vector &costs) {
169       return addConstructedNode(NodeEntry(costs));
170     }
171 
172     /// \brief Add an edge between the given nodes with the given costs.
173     /// @param n1Itr First node.
174     /// @param n2Itr Second node.
175     /// @return Edge iterator for the added edge.
addEdge(Graph::NodeItr n1Itr,Graph::NodeItr n2Itr,const Matrix & costs)176     EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr,
177                     const Matrix &costs) {
178       assert(getNodeCosts(n1Itr).getLength() == costs.getRows() &&
179              getNodeCosts(n2Itr).getLength() == costs.getCols() &&
180              "Matrix dimensions mismatch.");
181       return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs));
182     }
183 
184     /// \brief Get the number of nodes in the graph.
185     /// @return Number of nodes in the graph.
getNumNodes()186     unsigned getNumNodes() const { return numNodes; }
187 
188     /// \brief Get the number of edges in the graph.
189     /// @return Number of edges in the graph.
getNumEdges()190     unsigned getNumEdges() const { return numEdges; }
191 
192     /// \brief Get a node's cost vector.
193     /// @param nItr Node iterator.
194     /// @return Node cost vector.
getNodeCosts(NodeItr nItr)195     Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); }
196 
197     /// \brief Get a node's cost vector (const version).
198     /// @param nItr Node iterator.
199     /// @return Node cost vector.
getNodeCosts(ConstNodeItr nItr)200     const Vector& getNodeCosts(ConstNodeItr nItr) const {
201       return getNode(nItr).getCosts();
202     }
203 
204     /// \brief Set a node's data pointer.
205     /// @param nItr Node iterator.
206     /// @param data Pointer to node data.
207     ///
208     /// Typically used by a PBQP solver to attach data to aid in solution.
setNodeData(NodeItr nItr,void * data)209     void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); }
210 
211     /// \brief Get the node's data pointer.
212     /// @param nItr Node iterator.
213     /// @return Pointer to node data.
getNodeData(NodeItr nItr)214     void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); }
215 
216     /// \brief Get an edge's cost matrix.
217     /// @param eItr Edge iterator.
218     /// @return Edge cost matrix.
getEdgeCosts(EdgeItr eItr)219     Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); }
220 
221     /// \brief Get an edge's cost matrix (const version).
222     /// @param eItr Edge iterator.
223     /// @return Edge cost matrix.
getEdgeCosts(ConstEdgeItr eItr)224     const Matrix& getEdgeCosts(ConstEdgeItr eItr) const {
225       return getEdge(eItr).getCosts();
226     }
227 
228     /// \brief Set an edge's data pointer.
229     /// @param eItr Edge iterator.
230     /// @param data Pointer to edge data.
231     ///
232     /// Typically used by a PBQP solver to attach data to aid in solution.
setEdgeData(EdgeItr eItr,void * data)233     void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); }
234 
235     /// \brief Get an edge's data pointer.
236     /// @param eItr Edge iterator.
237     /// @return Pointer to edge data.
getEdgeData(EdgeItr eItr)238     void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); }
239 
240     /// \brief Get a node's degree.
241     /// @param nItr Node iterator.
242     /// @return The degree of the node.
getNodeDegree(NodeItr nItr)243     unsigned getNodeDegree(NodeItr nItr) const {
244       return getNode(nItr).getDegree();
245     }
246 
247     /// \brief Begin iterator for node set.
nodesBegin()248     NodeItr nodesBegin() { return nodes.begin(); }
249 
250     /// \brief Begin const iterator for node set.
nodesBegin()251     ConstNodeItr nodesBegin() const { return nodes.begin(); }
252 
253     /// \brief End iterator for node set.
nodesEnd()254     NodeItr nodesEnd() { return nodes.end(); }
255 
256     /// \brief End const iterator for node set.
nodesEnd()257     ConstNodeItr nodesEnd() const { return nodes.end(); }
258 
259     /// \brief Begin iterator for edge set.
edgesBegin()260     EdgeItr edgesBegin() { return edges.begin(); }
261 
262     /// \brief End iterator for edge set.
edgesEnd()263     EdgeItr edgesEnd() { return edges.end(); }
264 
265     /// \brief Get begin iterator for adjacent edge set.
266     /// @param nItr Node iterator.
267     /// @return Begin iterator for the set of edges connected to the given node.
adjEdgesBegin(NodeItr nItr)268     AdjEdgeItr adjEdgesBegin(NodeItr nItr) {
269       return getNode(nItr).edgesBegin();
270     }
271 
272     /// \brief Get end iterator for adjacent edge set.
273     /// @param nItr Node iterator.
274     /// @return End iterator for the set of edges connected to the given node.
adjEdgesEnd(NodeItr nItr)275     AdjEdgeItr adjEdgesEnd(NodeItr nItr) {
276       return getNode(nItr).edgesEnd();
277     }
278 
279     /// \brief Get the first node connected to this edge.
280     /// @param eItr Edge iterator.
281     /// @return The first node connected to the given edge.
getEdgeNode1(EdgeItr eItr)282     NodeItr getEdgeNode1(EdgeItr eItr) {
283       return getEdge(eItr).getNode1();
284     }
285 
286     /// \brief Get the second node connected to this edge.
287     /// @param eItr Edge iterator.
288     /// @return The second node connected to the given edge.
getEdgeNode2(EdgeItr eItr)289     NodeItr getEdgeNode2(EdgeItr eItr) {
290       return getEdge(eItr).getNode2();
291     }
292 
293     /// \brief Get the "other" node connected to this edge.
294     /// @param eItr Edge iterator.
295     /// @param nItr Node iterator for the "given" node.
296     /// @return The iterator for the "other" node connected to this edge.
getEdgeOtherNode(EdgeItr eItr,NodeItr nItr)297     NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) {
298       EdgeEntry &e = getEdge(eItr);
299       if (e.getNode1() == nItr) {
300         return e.getNode2();
301       } // else
302       return e.getNode1();
303     }
304 
305     /// \brief Get the edge connecting two nodes.
306     /// @param n1Itr First node iterator.
307     /// @param n2Itr Second node iterator.
308     /// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists,
309     ///         otherwise returns edgesEnd().
findEdge(NodeItr n1Itr,NodeItr n2Itr)310     EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) {
311       for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr);
312          aeItr != aeEnd; ++aeItr) {
313         if ((getEdgeNode1(*aeItr) == n2Itr) ||
314             (getEdgeNode2(*aeItr) == n2Itr)) {
315           return *aeItr;
316         }
317       }
318       return edges.end();
319     }
320 
321     /// \brief Remove a node from the graph.
322     /// @param nItr Node iterator.
removeNode(NodeItr nItr)323     void removeNode(NodeItr nItr) {
324       NodeEntry &n = getNode(nItr);
325       for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) {
326         EdgeItr eItr = *itr;
327         ++itr;
328         removeEdge(eItr);
329       }
330       nodes.erase(nItr);
331       --numNodes;
332     }
333 
334     /// \brief Remove an edge from the graph.
335     /// @param eItr Edge iterator.
removeEdge(EdgeItr eItr)336     void removeEdge(EdgeItr eItr) {
337       EdgeEntry &e = getEdge(eItr);
338       NodeEntry &n1 = getNode(e.getNode1());
339       NodeEntry &n2 = getNode(e.getNode2());
340       n1.removeEdge(e.getNode1AEItr());
341       n2.removeEdge(e.getNode2AEItr());
342       edges.erase(eItr);
343       --numEdges;
344     }
345 
346     /// \brief Remove all nodes and edges from the graph.
clear()347     void clear() {
348       nodes.clear();
349       edges.clear();
350       numNodes = numEdges = 0;
351     }
352 
353     /// \brief Print a representation of this graph in DOT format.
354     /// @param os Output stream to print on.
355     template <typename OStream>
printDot(OStream & os)356     void printDot(OStream &os) {
357 
358       os << "graph {\n";
359 
360       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
361            nodeItr != nodeEnd; ++nodeItr) {
362 
363         os << "  node" << nodeItr << " [ label=\""
364            << nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n";
365       }
366 
367       os << "  edge [ len=" << getNumNodes() << " ]\n";
368 
369       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
370            edgeItr != edgeEnd; ++edgeItr) {
371 
372         os << "  node" << getEdgeNode1(edgeItr)
373            << " -- node" << getEdgeNode2(edgeItr)
374            << " [ label=\"";
375 
376         const Matrix &edgeCosts = getEdgeCosts(edgeItr);
377 
378         for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
379           os << edgeCosts.getRowAsVector(i) << "\\n";
380         }
381         os << "\" ]\n";
382       }
383       os << "}\n";
384     }
385 
386   };
387 
388   class NodeItrComparator {
389   public:
operator()390     bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const {
391       return &*n1 < &*n2;
392     }
393 
operator()394     bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const {
395       return &*n1 < &*n2;
396     }
397   };
398 
399   class EdgeItrCompartor {
400   public:
operator()401     bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const {
402       return &*e1 < &*e2;
403     }
404 
operator()405     bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const {
406       return &*e1 < &*e2;
407     }
408   };
409 
copyFrom(const Graph & other)410   void Graph::copyFrom(const Graph &other) {
411     std::map<Graph::ConstNodeItr, Graph::NodeItr,
412              NodeItrComparator> nodeMap;
413 
414      for (Graph::ConstNodeItr nItr = other.nodesBegin(),
415                              nEnd = other.nodesEnd();
416          nItr != nEnd; ++nItr) {
417       nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
418     }
419 
420   }
421 
422 }
423 
424 #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
425