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