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