15 #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
16 #define LLVM_CODEGEN_PBQP_GRAPH_H
36 return std::numeric_limits<NodeId>::max();
41 return std::numeric_limits<EdgeId>::max();
48 template <
typename SolverT>
51 typedef typename SolverT::CostAllocator CostAllocator;
55 typedef typename SolverT::Vector
Vector;
57 typedef typename CostAllocator::VectorPtr
VectorPtr;
58 typedef typename CostAllocator::MatrixPtr
MatrixPtr;
67 typedef std::vector<EdgeId> AdjEdgeList;
68 typedef AdjEdgeList::size_type AdjEdgeIdx;
69 typedef AdjEdgeList::const_iterator
AdjEdgeItr;
71 static AdjEdgeIdx getInvalidAdjEdgeIdx() {
72 return std::numeric_limits<AdjEdgeIdx>::max();
75 NodeEntry(
VectorPtr Costs) : Costs(Costs) {}
77 AdjEdgeIdx addAdjEdgeId(
EdgeId EId) {
78 AdjEdgeIdx Idx = AdjEdgeIds.size();
79 AdjEdgeIds.push_back(EId);
83 void removeAdjEdgeId(
Graph &
G,
NodeId ThisNId, AdjEdgeIdx Idx) {
90 G.getEdge(AdjEdgeIds.back()).setAdjEdgeIdx(ThisNId, Idx);
91 AdjEdgeIds[Idx] = AdjEdgeIds.back();
92 AdjEdgeIds.pop_back();
95 const AdjEdgeList& getAdjEdgeIds()
const {
return AdjEdgeIds; }
100 AdjEdgeList AdjEdgeIds;
109 ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx();
110 ThisEdgeAdjIdxs[1] = NodeEntry::getInvalidAdjEdgeIdx();
115 ThisEdgeAdjIdxs[0] = ThisEdgeAdjIdxs[1] =
116 NodeEntry::getInvalidAdjEdgeIdx();
120 void connectToN(
Graph &
G,
EdgeId ThisEdgeId,
unsigned NIdx) {
121 assert(ThisEdgeAdjIdxs[NIdx] == NodeEntry::getInvalidAdjEdgeIdx() &&
122 "Edge already connected to NIds[NIdx].");
123 NodeEntry &
N = G.getNode(NIds[NIdx]);
124 ThisEdgeAdjIdxs[NIdx] = N.addAdjEdgeId(ThisEdgeId);
129 connectToN(G, ThisEdgeId, 0);
131 assert(NId == NIds[1] &&
"Edge does not connect NId.");
132 connectToN(G, ThisEdgeId, 1);
137 connectToN(G, ThisEdgeId, 0);
138 connectToN(G, ThisEdgeId, 1);
141 void setAdjEdgeIdx(
NodeId NId,
typename NodeEntry::AdjEdgeIdx NewIdx) {
143 ThisEdgeAdjIdxs[0] = NewIdx;
145 assert(NId == NIds[1] &&
"Edge not connected to NId");
146 ThisEdgeAdjIdxs[1] = NewIdx;
150 void disconnectFromN(
Graph &G,
unsigned NIdx) {
151 assert(ThisEdgeAdjIdxs[NIdx] != NodeEntry::getInvalidAdjEdgeIdx() &&
152 "Edge not connected to NIds[NIdx].");
153 NodeEntry &N = G.getNode(NIds[NIdx]);
154 N.removeAdjEdgeId(G, NIds[NIdx], ThisEdgeAdjIdxs[NIdx]);
155 ThisEdgeAdjIdxs[NIdx] = NodeEntry::getInvalidAdjEdgeIdx();
160 disconnectFromN(G, 0);
162 assert(NId == NIds[1] &&
"Edge does not connect NId");
163 disconnectFromN(G, 1);
167 NodeId getN1Id()
const {
return NIds[0]; }
168 NodeId getN2Id()
const {
return NIds[1]; }
173 typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2];
179 CostAllocator CostAlloc;
182 typedef std::vector<NodeEntry> NodeVector;
183 typedef std::vector<NodeId> FreeNodeVector;
185 FreeNodeVector FreeNodeIds;
187 typedef std::vector<EdgeEntry> EdgeVector;
188 typedef std::vector<EdgeId> FreeEdgeVector;
190 FreeEdgeVector FreeEdgeIds;
194 NodeEntry &getNode(
NodeId NId) {
195 assert(NId < Nodes.size() &&
"Out of bound NodeId");
198 const NodeEntry &getNode(
NodeId NId)
const {
199 assert(NId < Nodes.size() &&
"Out of bound NodeId");
203 EdgeEntry& getEdge(
EdgeId EId) {
return Edges[EId]; }
204 const EdgeEntry& getEdge(
EdgeId EId)
const {
return Edges[EId]; }
206 NodeId addConstructedNode(NodeEntry N) {
208 if (!FreeNodeIds.empty()) {
209 NId = FreeNodeIds.back();
210 FreeNodeIds.pop_back();
211 Nodes[NId] = std::move(N);
214 Nodes.push_back(std::move(N));
219 EdgeId addConstructedEdge(EdgeEntry E) {
221 "Attempt to add duplicate edge.");
223 if (!FreeEdgeIds.empty()) {
224 EId = FreeEdgeIds.back();
225 FreeEdgeIds.pop_back();
226 Edges[EId] = std::move(E);
229 Edges.push_back(std::move(E));
232 EdgeEntry &
NE = getEdge(EId);
235 NE.connect(*
this, EId);
255 : CurNId(CurNId), EndNId(G.Nodes.
size()), FreeNodeIds(G.FreeNodeIds) {
256 this->CurNId = findNextInUse(CurNId);
266 while (NId < EndNId &&
267 std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) !=
275 const FreeNodeVector &FreeNodeIds;
281 : CurEId(CurEId), EndEId(G.Edges.
size()), FreeEdgeIds(G.FreeEdgeIds) {
282 this->CurEId = findNextInUse(CurEId);
292 while (EId < EndEId &&
293 std::find(FreeEdgeIds.begin(), FreeEdgeIds.end(), EId) !=
301 const FreeEdgeVector &FreeEdgeIds;
309 bool empty()
const {
return G.Nodes.empty(); }
310 typename NodeVector::size_type
size()
const {
311 return G.Nodes.size() - G.FreeNodeIds.size();
322 bool empty()
const {
return G.Edges.empty(); }
323 typename NodeVector::size_type
size()
const {
324 return G.Edges.size() - G.FreeEdgeIds.size();
333 typename NodeEntry::AdjEdgeItr
begin()
const {
334 return NE.getAdjEdgeIds().begin();
336 typename NodeEntry::AdjEdgeItr
end()
const {
337 return NE.getAdjEdgeIds().end();
339 bool empty()
const {
return NE.getAdjEdgeIds().empty(); }
340 typename NodeEntry::AdjEdgeList::size_type
size()
const {
341 return NE.getAdjEdgeIds().size();
364 assert(!Solver &&
"Solver already set. Call unsetSolver().");
367 Solver->handleAddNode(NId);
369 Solver->handleAddEdge(EId);
374 assert(Solver &&
"Solver not set.");
381 template <
typename OtherVectorT>
384 VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs));
385 NodeId NId = addConstructedNode(NodeEntry(AllocatedCosts));
387 Solver->handleAddNode(NId);
402 template <
typename OtherVectorPtrT>
404 NodeId NId = addConstructedNode(NodeEntry(Costs));
406 Solver->handleAddNode(NId);
415 template <
typename OtherVectorT>
417 assert(
getNodeCosts(N1Id).getLength() == Costs.getRows() &&
419 "Matrix dimensions mismatch.");
421 MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs));
422 EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, AllocatedCosts));
424 Solver->handleAddEdge(EId);
440 template <
typename OtherMatrixPtrT>
442 OtherMatrixPtrT Costs) {
443 assert(
getNodeCosts(N1Id).getLength() == Costs->getRows() &&
445 "Matrix dimensions mismatch.");
447 EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, Costs));
449 Solver->handleAddEdge(EId);
454 bool empty()
const {
return NodeIdSet(*this).empty(); }
456 NodeIdSet
nodeIds()
const {
return NodeIdSet(*
this); }
457 EdgeIdSet
edgeIds()
const {
return EdgeIdSet(*
this); }
472 template <
typename OtherVectorT>
474 VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs));
476 Solver->handleSetNodeCosts(NId, *AllocatedCosts);
477 getNode(NId).Costs = AllocatedCosts;
489 return getNode(NId).Costs;
500 return getNode(NId).Metadata;
504 return getNode(NId).Metadata;
508 return getNode(NId).getAdjEdgeIds().size();
514 template <
typename OtherMatrixT>
516 MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs));
518 Solver->handleUpdateCosts(EId, *AllocatedCosts);
519 getEdge(EId).Costs = AllocatedCosts;
531 return getEdge(EId).Costs;
538 return *getEdge(EId).Costs;
542 return getEdge(EId).Metadata;
546 return getEdge(EId).Metadata;
553 return getEdge(EId).getN1Id();
560 return getEdge(EId).getN2Id();
568 EdgeEntry &E = getEdge(EId);
569 if (E.getN1Id() == NId) {
594 Solver->handleRemoveNode(NId);
595 NodeEntry &N = getNode(NId);
598 AEEnd = N.adjEdgesEnd();
604 FreeNodeIds.push_back(NId);
634 Solver->handleDisconnectEdge(EId, NId);
636 EdgeEntry &E = getEdge(EId);
637 E.disconnectFrom(*
this, NId);
652 EdgeEntry &E = getEdge(EId);
653 E.connectTo(*
this, EId, NId);
655 Solver->handleReconnectEdge(EId, NId);
662 Solver->handleRemoveEdge(EId);
663 EdgeEntry &E = getEdge(EId);
665 FreeEdgeIds.push_back(EId);
666 Edges[EId].invalidate();
681 #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
const NodeMetadata & getNodeMetadata(NodeId NId) const
EdgeIdSet(const Graph &G)
NodeId getEdgeNode1Id(EdgeId EId) const
Get the first node connected to this edge.
const VectorPtr & getNodeCostsPtr(NodeId NId) const
Get a VectorPtr to a node's cost vector.
NodeVector::size_type size() const
EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs)
Add an edge between the given nodes with the given costs.
EdgeId findEdge(NodeId N1Id, NodeId N2Id)
Get the edge connecting two nodes.
static NodeId invalidNodeId()
Returns a value representing an invalid (non-existent) node.
unsigned getNumEdges() const
Get the number of edges in the graph.
NodeId getEdgeNode2Id(EdgeId EId) const
Get the second node connected to this edge.
NodeItr(NodeId CurNId, const Graph &G)
NodeEntry::AdjEdgeItr begin() const
void reconnectEdge(EdgeId EId, NodeId NId)
Re-attach an edge to its nodes.
void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs)
Update an edge's cost matrix.
const GraphMetadata & getMetadata() const
Get a const-reference to the graph metadata.
NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id, OtherMatrixPtrT Costs)
Add an edge bypassing the cost allocator.
NodeEntry::AdjEdgeItr AdjEdgeItr
SolverT::GraphMetadata GraphMetadata
SolverT::NodeMetadata NodeMetadata
const Vector & getNodeCosts(NodeId NId) const
Get a node's cost vector.
NodeVector::size_type size() const
bool operator!=(const NodeItr &O) const
SolverT::RawMatrix RawMatrix
NodeMetadata & getNodeMetadata(NodeId NId)
NodeEntry::AdjEdgeList::size_type size() const
void disconnectEdge(EdgeId EId, NodeId NId)
Disconnect an edge from the given node.
CostAllocator::VectorPtr VectorPtr
Graph()
Construct an empty PBQP graph.
NodeId getEdgeOtherNodeId(EdgeId EId, NodeId NId)
Get the "other" node connected to this edge.
NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const
unsigned getNumNodes() const
Get the number of nodes in the graph.
EdgeIdSet edgeIds() const
bool operator!=(const EdgeItr &O) const
NodeId addNodeBypassingCostAllocator(OtherVectorPtrT Costs)
Add a node bypassing the cost allocator.
NodeIdSet nodeIds() const
void removeNode(NodeId NId)
Remove a node from the graph.
AdjEdgeIdSet adjEdgeIds(NodeId NId)
void setSolver(SolverT &S)
Lock this graph to the given solver instance in preparation for running the solver.
void clear()
Remove all nodes and edges from the graph.
NodeEntry::AdjEdgeItr end() const
EdgeItr(EdgeId CurEId, const Graph &G)
GraphMetadata & getMetadata()
Get a reference to the graph metadata.
void removeEdge(EdgeId EId)
Remove an edge from the graph.
AdjEdgeIdSet(const NodeEntry &NE)
void unsetSolver()
Release from solver instance.
Graph(GraphMetadata Metadata)
Construct an empty PBQP graph with the given graph metadata.
const Matrix & getEdgeCosts(EdgeId EId) const
Get an edge's cost matrix.
bool empty() const
Returns true if the graph is empty.
static EdgeId invalidEdgeId()
Returns a value representing an invalid (non-existent) edge.
SolverT::EdgeMetadata EdgeMetadata
void disconnectAllNeighborsFromNode(NodeId NId)
Convenience method to disconnect all neighbours from the given node.
bool operator==(const NodeItr &O) const
std::forward_iterator_tag iterator_category
EdgeMetadata & getEdgeMetadata(EdgeId EId)
NodeIdSet(const Graph &G)
const EdgeMetadata & getEdgeMetadata(EdgeId EId) const
const MatrixPtr & getEdgeCostsPtr(EdgeId EId) const
Get a MatrixPtr to a node's cost matrix.
NodeId addNode(OtherVectorT Costs)
Add a node with the given costs.
bool operator==(const EdgeItr &O) const
SolverT::RawVector RawVector
CostAllocator::MatrixPtr MatrixPtr
void setNodeCosts(NodeId NId, OtherVectorT Costs)
Set a node's cost vector.