LLVM API Documentation

Graph.h
Go to the documentation of this file.
00001 //===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // PBQP Graph class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 
00015 #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
00016 #define LLVM_CODEGEN_PBQP_GRAPH_H
00017 
00018 #include "llvm/ADT/ilist.h"
00019 #include "llvm/ADT/ilist_node.h"
00020 #include "llvm/Support/Compiler.h"
00021 #include <list>
00022 #include <map>
00023 #include <set>
00024 
00025 namespace PBQP {
00026 
00027   class GraphBase {
00028   public:
00029     typedef unsigned NodeId;
00030     typedef unsigned EdgeId;
00031 
00032     /// \brief Returns a value representing an invalid (non-existent) node.
00033     static NodeId invalidNodeId() {
00034       return std::numeric_limits<NodeId>::max();
00035     }
00036 
00037     /// \brief Returns a value representing an invalid (non-existent) edge.
00038     static EdgeId invalidEdgeId() {
00039       return std::numeric_limits<EdgeId>::max();
00040     }
00041   };
00042 
00043   /// PBQP Graph class.
00044   /// Instances of this class describe PBQP problems.
00045   ///
00046   template <typename SolverT>
00047   class Graph : public GraphBase {
00048   private:
00049     typedef typename SolverT::CostAllocator CostAllocator;
00050   public:
00051     typedef typename SolverT::RawVector RawVector;
00052     typedef typename SolverT::RawMatrix RawMatrix;
00053     typedef typename SolverT::Vector Vector;
00054     typedef typename SolverT::Matrix Matrix;
00055     typedef typename CostAllocator::VectorPtr VectorPtr;
00056     typedef typename CostAllocator::MatrixPtr MatrixPtr;
00057     typedef typename SolverT::NodeMetadata NodeMetadata;
00058     typedef typename SolverT::EdgeMetadata EdgeMetadata;
00059 
00060   private:
00061 
00062     class NodeEntry {
00063     public:
00064       typedef std::vector<EdgeId> AdjEdgeList;
00065       typedef AdjEdgeList::size_type AdjEdgeIdx;
00066       typedef AdjEdgeList::const_iterator AdjEdgeItr;
00067 
00068       static AdjEdgeIdx getInvalidAdjEdgeIdx() {
00069         return std::numeric_limits<AdjEdgeIdx>::max();
00070       }
00071 
00072       NodeEntry(VectorPtr Costs) : Costs(Costs) {}
00073 
00074       AdjEdgeIdx addAdjEdgeId(EdgeId EId) {
00075         AdjEdgeIdx Idx = AdjEdgeIds.size();
00076         AdjEdgeIds.push_back(EId);
00077         return Idx;
00078       }
00079 
00080       void removeAdjEdgeId(Graph &G, NodeId ThisNId, AdjEdgeIdx Idx) {
00081         // Swap-and-pop for fast removal.
00082         //   1) Update the adj index of the edge currently at back().
00083         //   2) Move last Edge down to Idx.
00084         //   3) pop_back()
00085         // If Idx == size() - 1 then the setAdjEdgeIdx and swap are
00086         // redundant, but both operations are cheap.
00087         G.getEdge(AdjEdgeIds.back()).setAdjEdgeIdx(ThisNId, Idx);
00088         AdjEdgeIds[Idx] = AdjEdgeIds.back();
00089         AdjEdgeIds.pop_back();
00090       }
00091 
00092       const AdjEdgeList& getAdjEdgeIds() const { return AdjEdgeIds; }
00093 
00094       VectorPtr Costs;
00095       NodeMetadata Metadata;
00096     private:
00097       AdjEdgeList AdjEdgeIds;
00098     };
00099 
00100     class EdgeEntry {
00101     public:
00102       EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs)
00103         : Costs(Costs) {
00104         NIds[0] = N1Id;
00105         NIds[1] = N2Id;
00106         ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx();
00107         ThisEdgeAdjIdxs[1] = NodeEntry::getInvalidAdjEdgeIdx();
00108       }
00109 
00110       void invalidate() {
00111         NIds[0] = NIds[1] = Graph::invalidNodeId();
00112         ThisEdgeAdjIdxs[0] = ThisEdgeAdjIdxs[1] =
00113           NodeEntry::getInvalidAdjEdgeIdx();
00114         Costs = nullptr;
00115       }
00116 
00117       void connectToN(Graph &G, EdgeId ThisEdgeId, unsigned NIdx) {
00118         assert(ThisEdgeAdjIdxs[NIdx] == NodeEntry::getInvalidAdjEdgeIdx() &&
00119                "Edge already connected to NIds[NIdx].");
00120         NodeEntry &N = G.getNode(NIds[NIdx]);
00121         ThisEdgeAdjIdxs[NIdx] = N.addAdjEdgeId(ThisEdgeId);
00122       }
00123 
00124       void connectTo(Graph &G, EdgeId ThisEdgeId, NodeId NId) {
00125         if (NId == NIds[0])
00126           connectToN(G, ThisEdgeId, 0);
00127         else {
00128           assert(NId == NIds[1] && "Edge does not connect NId.");
00129           connectToN(G, ThisEdgeId, 1);
00130         }
00131       }
00132 
00133       void connect(Graph &G, EdgeId ThisEdgeId) {
00134         connectToN(G, ThisEdgeId, 0);
00135         connectToN(G, ThisEdgeId, 1);
00136       }
00137 
00138       void setAdjEdgeIdx(NodeId NId, typename NodeEntry::AdjEdgeIdx NewIdx) {
00139         if (NId == NIds[0])
00140           ThisEdgeAdjIdxs[0] = NewIdx;
00141         else {
00142           assert(NId == NIds[1] && "Edge not connected to NId");
00143           ThisEdgeAdjIdxs[1] = NewIdx;
00144         }
00145       }
00146 
00147       void disconnectFromN(Graph &G, unsigned NIdx) {
00148         assert(ThisEdgeAdjIdxs[NIdx] != NodeEntry::getInvalidAdjEdgeIdx() &&
00149                "Edge not connected to NIds[NIdx].");
00150         NodeEntry &N = G.getNode(NIds[NIdx]);
00151         N.removeAdjEdgeId(G, NIds[NIdx], ThisEdgeAdjIdxs[NIdx]);
00152         ThisEdgeAdjIdxs[NIdx] = NodeEntry::getInvalidAdjEdgeIdx();
00153       }
00154 
00155       void disconnectFrom(Graph &G, NodeId NId) {
00156         if (NId == NIds[0])
00157           disconnectFromN(G, 0);
00158         else {
00159           assert(NId == NIds[1] && "Edge does not connect NId");
00160           disconnectFromN(G, 1);
00161         }
00162       }
00163 
00164       NodeId getN1Id() const { return NIds[0]; }
00165       NodeId getN2Id() const { return NIds[1]; }
00166       MatrixPtr Costs;
00167       EdgeMetadata Metadata;
00168     private:
00169       NodeId NIds[2];
00170       typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2];
00171     };
00172 
00173     // ----- MEMBERS -----
00174 
00175     CostAllocator CostAlloc;
00176     SolverT *Solver;
00177 
00178     typedef std::vector<NodeEntry> NodeVector;
00179     typedef std::vector<NodeId> FreeNodeVector;
00180     NodeVector Nodes;
00181     FreeNodeVector FreeNodeIds;
00182 
00183     typedef std::vector<EdgeEntry> EdgeVector;
00184     typedef std::vector<EdgeId> FreeEdgeVector;
00185     EdgeVector Edges;
00186     FreeEdgeVector FreeEdgeIds;
00187 
00188     // ----- INTERNAL METHODS -----
00189 
00190     NodeEntry& getNode(NodeId NId) { return Nodes[NId]; }
00191     const NodeEntry& getNode(NodeId NId) const { return Nodes[NId]; }
00192 
00193     EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; }
00194     const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; }
00195 
00196     NodeId addConstructedNode(const NodeEntry &N) {
00197       NodeId NId = 0;
00198       if (!FreeNodeIds.empty()) {
00199         NId = FreeNodeIds.back();
00200         FreeNodeIds.pop_back();
00201         Nodes[NId] = std::move(N);
00202       } else {
00203         NId = Nodes.size();
00204         Nodes.push_back(std::move(N));
00205       }
00206       return NId;
00207     }
00208 
00209     EdgeId addConstructedEdge(const EdgeEntry &E) {
00210       assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() &&
00211              "Attempt to add duplicate edge.");
00212       EdgeId EId = 0;
00213       if (!FreeEdgeIds.empty()) {
00214         EId = FreeEdgeIds.back();
00215         FreeEdgeIds.pop_back();
00216         Edges[EId] = std::move(E);
00217       } else {
00218         EId = Edges.size();
00219         Edges.push_back(std::move(E));
00220       }
00221 
00222       EdgeEntry &NE = getEdge(EId);
00223 
00224       // Add the edge to the adjacency sets of its nodes.
00225       NE.connect(*this, EId);
00226       return EId;
00227     }
00228 
00229     Graph(const Graph &Other) {}
00230     void operator=(const Graph &Other) {}
00231 
00232   public:
00233 
00234     typedef typename NodeEntry::AdjEdgeItr AdjEdgeItr;
00235 
00236     class NodeItr {
00237     public:
00238       NodeItr(NodeId CurNId, const Graph &G)
00239         : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) {
00240         this->CurNId = findNextInUse(CurNId); // Move to first in-use node id
00241       }
00242 
00243       bool operator==(const NodeItr &O) const { return CurNId == O.CurNId; }
00244       bool operator!=(const NodeItr &O) const { return !(*this == O); }
00245       NodeItr& operator++() { CurNId = findNextInUse(++CurNId); return *this; }
00246       NodeId operator*() const { return CurNId; }
00247 
00248     private:
00249       NodeId findNextInUse(NodeId NId) const {
00250         while (NId < EndNId &&
00251                std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) !=
00252                  FreeNodeIds.end()) {
00253           ++NId;
00254         }
00255         return NId;
00256       }
00257 
00258       NodeId CurNId, EndNId;
00259       const FreeNodeVector &FreeNodeIds;
00260     };
00261 
00262     class EdgeItr {
00263     public:
00264       EdgeItr(EdgeId CurEId, const Graph &G)
00265         : CurEId(CurEId), EndEId(G.Edges.size()), FreeEdgeIds(G.FreeEdgeIds) {
00266         this->CurEId = findNextInUse(CurEId); // Move to first in-use edge id
00267       }
00268 
00269       bool operator==(const EdgeItr &O) const { return CurEId == O.CurEId; }
00270       bool operator!=(const EdgeItr &O) const { return !(*this == O); }
00271       EdgeItr& operator++() { CurEId = findNextInUse(++CurEId); return *this; }
00272       EdgeId operator*() const { return CurEId; }
00273 
00274     private:
00275       EdgeId findNextInUse(EdgeId EId) const {
00276         while (EId < EndEId &&
00277                std::find(FreeEdgeIds.begin(), FreeEdgeIds.end(), EId) !=
00278                FreeEdgeIds.end()) {
00279           ++EId;
00280         }
00281         return EId;
00282       }
00283 
00284       EdgeId CurEId, EndEId;
00285       const FreeEdgeVector &FreeEdgeIds;
00286     };
00287 
00288     class NodeIdSet {
00289     public:
00290       NodeIdSet(const Graph &G) : G(G) { }
00291       NodeItr begin() const { return NodeItr(0, G); }
00292       NodeItr end() const { return NodeItr(G.Nodes.size(), G); }
00293       bool empty() const { return G.Nodes.empty(); }
00294       typename NodeVector::size_type size() const {
00295         return G.Nodes.size() - G.FreeNodeIds.size();
00296       }
00297     private:
00298       const Graph& G;
00299     };
00300 
00301     class EdgeIdSet {
00302     public:
00303       EdgeIdSet(const Graph &G) : G(G) { }
00304       EdgeItr begin() const { return EdgeItr(0, G); }
00305       EdgeItr end() const { return EdgeItr(G.Edges.size(), G); }
00306       bool empty() const { return G.Edges.empty(); }
00307       typename NodeVector::size_type size() const {
00308         return G.Edges.size() - G.FreeEdgeIds.size();
00309       }
00310     private:
00311       const Graph& G;
00312     };
00313 
00314     class AdjEdgeIdSet {
00315     public:
00316       AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) { }
00317       typename NodeEntry::AdjEdgeItr begin() const {
00318         return NE.getAdjEdgeIds().begin();
00319       }
00320       typename NodeEntry::AdjEdgeItr end() const {
00321         return NE.getAdjEdgeIds().end();
00322       }
00323       bool empty() const { return NE.getAdjEdgeIds().empty(); }
00324       typename NodeEntry::AdjEdgeList::size_type size() const {
00325         return NE.getAdjEdgeIds().size();
00326       }
00327     private:
00328       const NodeEntry &NE;
00329     };
00330 
00331     /// \brief Construct an empty PBQP graph.
00332     Graph() : Solver(nullptr) { }
00333 
00334     /// \brief Lock this graph to the given solver instance in preparation
00335     /// for running the solver. This method will call solver.handleAddNode for
00336     /// each node in the graph, and handleAddEdge for each edge, to give the
00337     /// solver an opportunity to set up any requried metadata.
00338     void setSolver(SolverT &S) {
00339       assert(!Solver && "Solver already set. Call unsetSolver().");
00340       Solver = &S;
00341       for (auto NId : nodeIds())
00342         Solver->handleAddNode(NId);
00343       for (auto EId : edgeIds())
00344         Solver->handleAddEdge(EId);
00345     }
00346 
00347     /// \brief Release from solver instance.
00348     void unsetSolver() {
00349       assert(Solver && "Solver not set.");
00350       Solver = nullptr;
00351     }
00352 
00353     /// \brief Add a node with the given costs.
00354     /// @param Costs Cost vector for the new node.
00355     /// @return Node iterator for the added node.
00356     template <typename OtherVectorT>
00357     NodeId addNode(OtherVectorT Costs) {
00358       // Get cost vector from the problem domain
00359       VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs));
00360       NodeId NId = addConstructedNode(NodeEntry(AllocatedCosts));
00361       if (Solver)
00362         Solver->handleAddNode(NId);
00363       return NId;
00364     }
00365 
00366     /// \brief Add an edge between the given nodes with the given costs.
00367     /// @param N1Id First node.
00368     /// @param N2Id Second node.
00369     /// @return Edge iterator for the added edge.
00370     template <typename OtherVectorT>
00371     EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) {
00372       assert(getNodeCosts(N1Id).getLength() == Costs.getRows() &&
00373              getNodeCosts(N2Id).getLength() == Costs.getCols() &&
00374              "Matrix dimensions mismatch.");
00375       // Get cost matrix from the problem domain.
00376       MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs));
00377       EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, AllocatedCosts));
00378       if (Solver)
00379         Solver->handleAddEdge(EId);
00380       return EId;
00381     }
00382 
00383     /// \brief Returns true if the graph is empty.
00384     bool empty() const { return NodeIdSet(*this).empty(); }
00385 
00386     NodeIdSet nodeIds() const { return NodeIdSet(*this); }
00387     EdgeIdSet edgeIds() const { return EdgeIdSet(*this); }
00388 
00389     AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); }
00390 
00391     /// \brief Get the number of nodes in the graph.
00392     /// @return Number of nodes in the graph.
00393     unsigned getNumNodes() const { return NodeIdSet(*this).size(); }
00394 
00395     /// \brief Get the number of edges in the graph.
00396     /// @return Number of edges in the graph.
00397     unsigned getNumEdges() const { return EdgeIdSet(*this).size(); }
00398 
00399     /// \brief Set a node's cost vector.
00400     /// @param NId Node to update.
00401     /// @param Costs New costs to set.
00402     template <typename OtherVectorT>
00403     void setNodeCosts(NodeId NId, OtherVectorT Costs) {
00404       VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs));
00405       if (Solver)
00406         Solver->handleSetNodeCosts(NId, *AllocatedCosts);
00407       getNode(NId).Costs = AllocatedCosts;
00408     }
00409 
00410     /// \brief Get a node's cost vector (const version).
00411     /// @param NId Node id.
00412     /// @return Node cost vector.
00413     const Vector& getNodeCosts(NodeId NId) const {
00414       return *getNode(NId).Costs;
00415     }
00416 
00417     NodeMetadata& getNodeMetadata(NodeId NId) {
00418       return getNode(NId).Metadata;
00419     }
00420 
00421     const NodeMetadata& getNodeMetadata(NodeId NId) const {
00422       return getNode(NId).Metadata;
00423     }
00424 
00425     typename NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const {
00426       return getNode(NId).getAdjEdgeIds().size();
00427     }
00428 
00429     /// \brief Set an edge's cost matrix.
00430     /// @param EId Edge id.
00431     /// @param Costs New cost matrix.
00432     template <typename OtherMatrixT>
00433     void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) {
00434       MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs));
00435       if (Solver)
00436         Solver->handleSetEdgeCosts(EId, *AllocatedCosts);
00437       getEdge(EId).Costs = AllocatedCosts;
00438     }
00439 
00440     /// \brief Get an edge's cost matrix (const version).
00441     /// @param EId Edge id.
00442     /// @return Edge cost matrix.
00443     const Matrix& getEdgeCosts(EdgeId EId) const { return *getEdge(EId).Costs; }
00444 
00445     EdgeMetadata& getEdgeMetadata(EdgeId NId) {
00446       return getEdge(NId).Metadata;
00447     }
00448 
00449     const EdgeMetadata& getEdgeMetadata(EdgeId NId) const {
00450       return getEdge(NId).Metadata;
00451     }
00452 
00453     /// \brief Get the first node connected to this edge.
00454     /// @param EId Edge id.
00455     /// @return The first node connected to the given edge.
00456     NodeId getEdgeNode1Id(EdgeId EId) {
00457       return getEdge(EId).getN1Id();
00458     }
00459 
00460     /// \brief Get the second node connected to this edge.
00461     /// @param EId Edge id.
00462     /// @return The second node connected to the given edge.
00463     NodeId getEdgeNode2Id(EdgeId EId) {
00464       return getEdge(EId).getN2Id();
00465     }
00466 
00467     /// \brief Get the "other" node connected to this edge.
00468     /// @param EId Edge id.
00469     /// @param NId Node id for the "given" node.
00470     /// @return The iterator for the "other" node connected to this edge.
00471     NodeId getEdgeOtherNodeId(EdgeId EId, NodeId NId) {
00472       EdgeEntry &E = getEdge(EId);
00473       if (E.getN1Id() == NId) {
00474         return E.getN2Id();
00475       } // else
00476       return E.getN1Id();
00477     }
00478 
00479     /// \brief Get the edge connecting two nodes.
00480     /// @param N1Id First node id.
00481     /// @param N2Id Second node id.
00482     /// @return An id for edge (N1Id, N2Id) if such an edge exists,
00483     ///         otherwise returns an invalid edge id.
00484     EdgeId findEdge(NodeId N1Id, NodeId N2Id) {
00485       for (auto AEId : adjEdgeIds(N1Id)) {
00486         if ((getEdgeNode1Id(AEId) == N2Id) ||
00487             (getEdgeNode2Id(AEId) == N2Id)) {
00488           return AEId;
00489         }
00490       }
00491       return invalidEdgeId();
00492     }
00493 
00494     /// \brief Remove a node from the graph.
00495     /// @param NId Node id.
00496     void removeNode(NodeId NId) {
00497       if (Solver)
00498         Solver->handleRemoveNode(NId);
00499       NodeEntry &N = getNode(NId);
00500       // TODO: Can this be for-each'd?
00501       for (AdjEdgeItr AEItr = N.adjEdgesBegin(),
00502                       AEEnd = N.adjEdgesEnd();
00503            AEItr != AEEnd;) {
00504         EdgeId EId = *AEItr;
00505         ++AEItr;
00506         removeEdge(EId);
00507       }
00508       FreeNodeIds.push_back(NId);
00509     }
00510 
00511     /// \brief Disconnect an edge from the given node.
00512     ///
00513     /// Removes the given edge from the adjacency list of the given node.
00514     /// This operation leaves the edge in an 'asymmetric' state: It will no
00515     /// longer appear in an iteration over the given node's (NId's) edges, but
00516     /// will appear in an iteration over the 'other', unnamed node's edges.
00517     ///
00518     /// This does not correspond to any normal graph operation, but exists to
00519     /// support efficient PBQP graph-reduction based solvers. It is used to
00520     /// 'effectively' remove the unnamed node from the graph while the solver
00521     /// is performing the reduction. The solver will later call reconnectNode
00522     /// to restore the edge in the named node's adjacency list.
00523     ///
00524     /// Since the degree of a node is the number of connected edges,
00525     /// disconnecting an edge from a node 'u' will cause the degree of 'u' to
00526     /// drop by 1.
00527     ///
00528     /// A disconnected edge WILL still appear in an iteration over the graph
00529     /// edges.
00530     ///
00531     /// A disconnected edge should not be removed from the graph, it should be
00532     /// reconnected first.
00533     ///
00534     /// A disconnected edge can be reconnected by calling the reconnectEdge
00535     /// method.
00536     void disconnectEdge(EdgeId EId, NodeId NId) {
00537       if (Solver)
00538         Solver->handleDisconnectEdge(EId, NId);
00539 
00540       EdgeEntry &E = getEdge(EId);
00541       E.disconnectFrom(*this, NId);
00542     }
00543 
00544     /// \brief Convenience method to disconnect all neighbours from the given
00545     ///        node.
00546     void disconnectAllNeighborsFromNode(NodeId NId) {
00547       for (auto AEId : adjEdgeIds(NId))
00548         disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId));
00549     }
00550 
00551     /// \brief Re-attach an edge to its nodes.
00552     ///
00553     /// Adds an edge that had been previously disconnected back into the
00554     /// adjacency set of the nodes that the edge connects.
00555     void reconnectEdge(EdgeId EId, NodeId NId) {
00556       EdgeEntry &E = getEdge(EId);
00557       E.connectTo(*this, EId, NId);
00558       if (Solver)
00559         Solver->handleReconnectEdge(EId, NId);
00560     }
00561 
00562     /// \brief Remove an edge from the graph.
00563     /// @param EId Edge id.
00564     void removeEdge(EdgeId EId) {
00565       if (Solver)
00566         Solver->handleRemoveEdge(EId);
00567       EdgeEntry &E = getEdge(EId);
00568       E.disconnect();
00569       FreeEdgeIds.push_back(EId);
00570       Edges[EId].invalidate();
00571     }
00572 
00573     /// \brief Remove all nodes and edges from the graph.
00574     void clear() {
00575       Nodes.clear();
00576       FreeNodeIds.clear();
00577       Edges.clear();
00578       FreeEdgeIds.clear();
00579     }
00580 
00581     /// \brief Dump a graph to an output stream.
00582     template <typename OStream>
00583     void dump(OStream &OS) {
00584       OS << nodeIds().size() << " " << edgeIds().size() << "\n";
00585 
00586       for (auto NId : nodeIds()) {
00587         const Vector& V = getNodeCosts(NId);
00588         OS << "\n" << V.getLength() << "\n";
00589         assert(V.getLength() != 0 && "Empty vector in graph.");
00590         OS << V[0];
00591         for (unsigned i = 1; i < V.getLength(); ++i) {
00592           OS << " " << V[i];
00593         }
00594         OS << "\n";
00595       }
00596 
00597       for (auto EId : edgeIds()) {
00598         NodeId N1Id = getEdgeNode1Id(EId);
00599         NodeId N2Id = getEdgeNode2Id(EId);
00600         assert(N1Id != N2Id && "PBQP graphs shound not have self-edges.");
00601         const Matrix& M = getEdgeCosts(EId);
00602         OS << "\n" << N1Id << " " << N2Id << "\n"
00603            << M.getRows() << " " << M.getCols() << "\n";
00604         assert(M.getRows() != 0 && "No rows in matrix.");
00605         assert(M.getCols() != 0 && "No cols in matrix.");
00606         for (unsigned i = 0; i < M.getRows(); ++i) {
00607           OS << M[i][0];
00608           for (unsigned j = 1; j < M.getCols(); ++j) {
00609             OS << " " << M[i][j];
00610           }
00611           OS << "\n";
00612         }
00613       }
00614     }
00615 
00616     /// \brief Print a representation of this graph in DOT format.
00617     /// @param OS Output stream to print on.
00618     template <typename OStream>
00619     void printDot(OStream &OS) {
00620       OS << "graph {\n";
00621       for (auto NId : nodeIds()) {
00622         OS << "  node" << NId << " [ label=\""
00623            << NId << ": " << getNodeCosts(NId) << "\" ]\n";
00624       }
00625       OS << "  edge [ len=" << nodeIds().size() << " ]\n";
00626       for (auto EId : edgeIds()) {
00627         OS << "  node" << getEdgeNode1Id(EId)
00628            << " -- node" << getEdgeNode2Id(EId)
00629            << " [ label=\"";
00630         const Matrix &EdgeCosts = getEdgeCosts(EId);
00631         for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) {
00632           OS << EdgeCosts.getRowAsVector(i) << "\\n";
00633         }
00634         OS << "\" ]\n";
00635       }
00636       OS << "}\n";
00637     }
00638   };
00639 
00640 }
00641 
00642 #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP