mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@194314 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			479 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			479 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-------------------- Graph.h - PBQP Graph ------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // PBQP Graph class.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| 
 | |
| #ifndef LLVM_CODEGEN_PBQP_GRAPH_H
 | |
| #define LLVM_CODEGEN_PBQP_GRAPH_H
 | |
| 
 | |
| #include "Math.h"
 | |
| #include "llvm/ADT/ilist.h"
 | |
| #include "llvm/ADT/ilist_node.h"
 | |
| #include <list>
 | |
| #include <map>
 | |
| #include <set>
 | |
| 
 | |
| namespace PBQP {
 | |
| 
 | |
|   /// PBQP Graph class.
 | |
|   /// Instances of this class describe PBQP problems.
 | |
|   class Graph {
 | |
|   public:
 | |
| 
 | |
|     typedef unsigned NodeId;
 | |
|     typedef unsigned EdgeId;
 | |
| 
 | |
|   private:
 | |
| 
 | |
|     typedef std::set<NodeId> AdjEdgeList;
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     typedef AdjEdgeList::iterator AdjEdgeItr;
 | |
| 
 | |
|   private:
 | |
| 
 | |
|     class NodeEntry {
 | |
|     private:
 | |
|       Vector costs;
 | |
|       AdjEdgeList adjEdges;
 | |
|       void *data;
 | |
|       NodeEntry() : costs(0, 0) {}
 | |
|     public:
 | |
|       NodeEntry(const Vector &costs) : costs(costs), data(0) {}
 | |
|       Vector& getCosts() { return costs; }
 | |
|       const Vector& getCosts() const { return costs; }
 | |
|       unsigned getDegree() const { return adjEdges.size(); }
 | |
|       AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
 | |
|       AdjEdgeItr edgesEnd() { return adjEdges.end(); }
 | |
|       AdjEdgeItr addEdge(EdgeId e) {
 | |
|         return adjEdges.insert(adjEdges.end(), e);
 | |
|       }
 | |
|       void removeEdge(AdjEdgeItr ae) {
 | |
|         adjEdges.erase(ae);
 | |
|       }
 | |
|       void setData(void *data) { this->data = data; }
 | |
|       void* getData() { return data; }
 | |
|     };
 | |
| 
 | |
|     class EdgeEntry {
 | |
|     private:
 | |
|       NodeId node1, node2;
 | |
|       Matrix costs;
 | |
|       AdjEdgeItr node1AEItr, node2AEItr;
 | |
|       void *data;
 | |
|       EdgeEntry() : costs(0, 0, 0), data(0) {}
 | |
|     public:
 | |
|       EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs)
 | |
|         : node1(node1), node2(node2), costs(costs) {}
 | |
|       NodeId getNode1() const { return node1; }
 | |
|       NodeId getNode2() const { return node2; }
 | |
|       Matrix& getCosts() { return costs; }
 | |
|       const Matrix& getCosts() const { return costs; }
 | |
|       void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
 | |
|       AdjEdgeItr getNode1AEItr() { return node1AEItr; }
 | |
|       void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; }
 | |
|       AdjEdgeItr getNode2AEItr() { return node2AEItr; }
 | |
|       void setData(void *data) { this->data = data; }
 | |
|       void *getData() { return data; }
 | |
|     };
 | |
| 
 | |
|     // ----- MEMBERS -----
 | |
| 
 | |
|     typedef std::vector<NodeEntry> NodeVector;
 | |
|     typedef std::vector<NodeId> FreeNodeVector;
 | |
|     NodeVector nodes;
 | |
|     FreeNodeVector freeNodes;
 | |
| 
 | |
|     typedef std::vector<EdgeEntry> EdgeVector;
 | |
|     typedef std::vector<EdgeId> FreeEdgeVector;
 | |
|     EdgeVector edges;
 | |
|     FreeEdgeVector freeEdges;
 | |
| 
 | |
|     // ----- INTERNAL METHODS -----
 | |
| 
 | |
|     NodeEntry& getNode(NodeId nId) { return nodes[nId]; }
 | |
|     const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; }
 | |
| 
 | |
|     EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; }
 | |
|     const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; }
 | |
| 
 | |
|     NodeId addConstructedNode(const NodeEntry &n) {
 | |
|       NodeId nodeId = 0;
 | |
|       if (!freeNodes.empty()) {
 | |
|         nodeId = freeNodes.back();
 | |
|         freeNodes.pop_back();
 | |
|         nodes[nodeId] = n;
 | |
|       } else {
 | |
|         nodeId = nodes.size();
 | |
|         nodes.push_back(n);
 | |
|       }
 | |
|       return nodeId;
 | |
|     }
 | |
| 
 | |
|     EdgeId addConstructedEdge(const EdgeEntry &e) {
 | |
|       assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() &&
 | |
|              "Attempt to add duplicate edge.");
 | |
|       EdgeId edgeId = 0;
 | |
|       if (!freeEdges.empty()) {
 | |
|         edgeId = freeEdges.back();
 | |
|         freeEdges.pop_back();
 | |
|         edges[edgeId] = e;
 | |
|       } else {
 | |
|         edgeId = edges.size();
 | |
|         edges.push_back(e);
 | |
|       }
 | |
| 
 | |
|       EdgeEntry &ne = getEdge(edgeId);
 | |
|       NodeEntry &n1 = getNode(ne.getNode1());
 | |
|       NodeEntry &n2 = getNode(ne.getNode2());
 | |
| 
 | |
|       // Sanity check on matrix dimensions:
 | |
|       assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
 | |
|              (n2.getCosts().getLength() == ne.getCosts().getCols()) &&
 | |
|              "Edge cost dimensions do not match node costs dimensions.");
 | |
| 
 | |
|       ne.setNode1AEItr(n1.addEdge(edgeId));
 | |
|       ne.setNode2AEItr(n2.addEdge(edgeId));
 | |
|       return edgeId;
 | |
|     }
 | |
| 
 | |
|     Graph(const Graph &other) {}
 | |
|     void operator=(const Graph &other) {}
 | |
| 
 | |
|   public:
 | |
| 
 | |
|     class NodeItr {
 | |
|     public:
 | |
|       NodeItr(NodeId nodeId, const Graph &g)
 | |
|         : nodeId(nodeId), endNodeId(g.nodes.size()), freeNodes(g.freeNodes) {
 | |
|         this->nodeId = findNextInUse(nodeId); // Move to the first in-use nodeId
 | |
|       }
 | |
| 
 | |
|       bool operator==(const NodeItr& n) const { return nodeId == n.nodeId; }
 | |
|       bool operator!=(const NodeItr& n) const { return !(*this == n); }
 | |
|       NodeItr& operator++() { nodeId = findNextInUse(++nodeId); return *this; }
 | |
|       NodeId operator*() const { return nodeId; }
 | |
| 
 | |
|     private:
 | |
|       NodeId findNextInUse(NodeId n) const {
 | |
|         while (n < endNodeId &&
 | |
|                std::find(freeNodes.begin(), freeNodes.end(), n) !=
 | |
|                  freeNodes.end()) {
 | |
|           ++n;
 | |
|         }
 | |
|         return n;
 | |
|       }
 | |
| 
 | |
|       NodeId nodeId, endNodeId;
 | |
|       const FreeNodeVector& freeNodes;
 | |
|     };
 | |
| 
 | |
|     class EdgeItr {
 | |
|     public:
 | |
|       EdgeItr(EdgeId edgeId, const Graph &g)
 | |
|         : edgeId(edgeId), endEdgeId(g.edges.size()), freeEdges(g.freeEdges) {
 | |
|         this->edgeId = findNextInUse(edgeId); // Move to the first in-use edgeId
 | |
|       }
 | |
| 
 | |
|       bool operator==(const EdgeItr& n) const { return edgeId == n.edgeId; }
 | |
|       bool operator!=(const EdgeItr& n) const { return !(*this == n); }
 | |
|       EdgeItr& operator++() { edgeId = findNextInUse(++edgeId); return *this; }
 | |
|       EdgeId operator*() const { return edgeId; }
 | |
| 
 | |
|     private:
 | |
|       EdgeId findNextInUse(EdgeId n) const {
 | |
|         while (n < endEdgeId &&
 | |
|                std::find(freeEdges.begin(), freeEdges.end(), n) !=
 | |
|                  freeEdges.end()) {
 | |
|           ++n;
 | |
|         }
 | |
|         return n;
 | |
|       }
 | |
| 
 | |
|       EdgeId edgeId, endEdgeId;
 | |
|       const FreeEdgeVector& freeEdges;
 | |
|     };
 | |
| 
 | |
|     /// \brief Construct an empty PBQP graph.
 | |
|     Graph() {}
 | |
| 
 | |
|     /// \brief Add a node with the given costs.
 | |
|     /// @param costs Cost vector for the new node.
 | |
|     /// @return Node iterator for the added node.
 | |
|     NodeId addNode(const Vector &costs) {
 | |
|       return addConstructedNode(NodeEntry(costs));
 | |
|     }
 | |
| 
 | |
|     /// \brief Add an edge between the given nodes with the given costs.
 | |
|     /// @param n1Id First node.
 | |
|     /// @param n2Id Second node.
 | |
|     /// @return Edge iterator for the added edge.
 | |
|     EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) {
 | |
|       assert(getNodeCosts(n1Id).getLength() == costs.getRows() &&
 | |
|              getNodeCosts(n2Id).getLength() == costs.getCols() &&
 | |
|              "Matrix dimensions mismatch.");
 | |
|       return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs));
 | |
|     }
 | |
| 
 | |
|     /// \brief Get the number of nodes in the graph.
 | |
|     /// @return Number of nodes in the graph.
 | |
|     unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); }
 | |
| 
 | |
|     /// \brief Get the number of edges in the graph.
 | |
|     /// @return Number of edges in the graph.
 | |
|     unsigned getNumEdges() const { return edges.size() - freeEdges.size(); }
 | |
| 
 | |
|     /// \brief Get a node's cost vector.
 | |
|     /// @param nId Node id.
 | |
|     /// @return Node cost vector.
 | |
|     Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); }
 | |
| 
 | |
|     /// \brief Get a node's cost vector (const version).
 | |
|     /// @param nId Node id.
 | |
|     /// @return Node cost vector.
 | |
|     const Vector& getNodeCosts(NodeId nId) const {
 | |
|       return getNode(nId).getCosts();
 | |
|     }
 | |
| 
 | |
|     /// \brief Set a node's data pointer.
 | |
|     /// @param nId Node id.
 | |
|     /// @param data Pointer to node data.
 | |
|     ///
 | |
|     /// Typically used by a PBQP solver to attach data to aid in solution.
 | |
|     void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); }
 | |
| 
 | |
|     /// \brief Get the node's data pointer.
 | |
|     /// @param nId Node id.
 | |
|     /// @return Pointer to node data.
 | |
|     void* getNodeData(NodeId nId) { return getNode(nId).getData(); }
 | |
| 
 | |
|     /// \brief Get an edge's cost matrix.
 | |
|     /// @param eId Edge id.
 | |
|     /// @return Edge cost matrix.
 | |
|     Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); }
 | |
| 
 | |
|     /// \brief Get an edge's cost matrix (const version).
 | |
|     /// @param eId Edge id.
 | |
|     /// @return Edge cost matrix.
 | |
|     const Matrix& getEdgeCosts(EdgeId eId) const {
 | |
|       return getEdge(eId).getCosts();
 | |
|     }
 | |
| 
 | |
|     /// \brief Set an edge's data pointer.
 | |
|     /// @param eId Edge id.
 | |
|     /// @param data Pointer to edge data.
 | |
|     ///
 | |
|     /// Typically used by a PBQP solver to attach data to aid in solution.
 | |
|     void setEdgeData(EdgeId eId, void *data) { getEdge(eId).setData(data); }
 | |
| 
 | |
|     /// \brief Get an edge's data pointer.
 | |
|     /// @param eId Edge id.
 | |
|     /// @return Pointer to edge data.
 | |
|     void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); }
 | |
| 
 | |
|     /// \brief Get a node's degree.
 | |
|     /// @param nId Node id.
 | |
|     /// @return The degree of the node.
 | |
|     unsigned getNodeDegree(NodeId nId) const {
 | |
|       return getNode(nId).getDegree();
 | |
|     }
 | |
| 
 | |
|     /// \brief Begin iterator for node set.
 | |
|     NodeItr nodesBegin() const { return NodeItr(0, *this);  }
 | |
| 
 | |
|     /// \brief End iterator for node set.
 | |
|     NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); }
 | |
| 
 | |
|     /// \brief Begin iterator for edge set.
 | |
|     EdgeItr edgesBegin() const { return EdgeItr(0, *this); }
 | |
| 
 | |
|     /// \brief End iterator for edge set.
 | |
|     EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); }
 | |
| 
 | |
|     /// \brief Get begin iterator for adjacent edge set.
 | |
|     /// @param nId Node id.
 | |
|     /// @return Begin iterator for the set of edges connected to the given node.
 | |
|     AdjEdgeItr adjEdgesBegin(NodeId nId) {
 | |
|       return getNode(nId).edgesBegin();
 | |
|     }
 | |
| 
 | |
|     /// \brief Get end iterator for adjacent edge set.
 | |
|     /// @param nId Node id.
 | |
|     /// @return End iterator for the set of edges connected to the given node.
 | |
|     AdjEdgeItr adjEdgesEnd(NodeId nId) {
 | |
|       return getNode(nId).edgesEnd();
 | |
|     }
 | |
| 
 | |
|     /// \brief Get the first node connected to this edge.
 | |
|     /// @param eId Edge id.
 | |
|     /// @return The first node connected to the given edge.
 | |
|     NodeId getEdgeNode1(EdgeId eId) {
 | |
|       return getEdge(eId).getNode1();
 | |
|     }
 | |
| 
 | |
|     /// \brief Get the second node connected to this edge.
 | |
|     /// @param eId Edge id.
 | |
|     /// @return The second node connected to the given edge.
 | |
|     NodeId getEdgeNode2(EdgeId eId) {
 | |
|       return getEdge(eId).getNode2();
 | |
|     }
 | |
| 
 | |
|     /// \brief Get the "other" node connected to this edge.
 | |
|     /// @param eId Edge id.
 | |
|     /// @param nId Node id for the "given" node.
 | |
|     /// @return The iterator for the "other" node connected to this edge.
 | |
|     NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) {
 | |
|       EdgeEntry &e = getEdge(eId);
 | |
|       if (e.getNode1() == nId) {
 | |
|         return e.getNode2();
 | |
|       } // else
 | |
|       return e.getNode1();
 | |
|     }
 | |
| 
 | |
|     EdgeId invalidEdgeId() const {
 | |
|       return std::numeric_limits<EdgeId>::max();
 | |
|     }
 | |
| 
 | |
|     /// \brief Get the edge connecting two nodes.
 | |
|     /// @param n1Id First node id.
 | |
|     /// @param n2Id Second node id.
 | |
|     /// @return An id for edge (n1Id, n2Id) if such an edge exists,
 | |
|     ///         otherwise returns an invalid edge id.
 | |
|     EdgeId findEdge(NodeId n1Id, NodeId n2Id) {
 | |
|       for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id);
 | |
|          aeItr != aeEnd; ++aeItr) {
 | |
|         if ((getEdgeNode1(*aeItr) == n2Id) ||
 | |
|             (getEdgeNode2(*aeItr) == n2Id)) {
 | |
|           return *aeItr;
 | |
|         }
 | |
|       }
 | |
|       return invalidEdgeId();
 | |
|     }
 | |
| 
 | |
|     /// \brief Remove a node from the graph.
 | |
|     /// @param nId Node id.
 | |
|     void removeNode(NodeId nId) {
 | |
|       NodeEntry &n = getNode(nId);
 | |
|       for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) {
 | |
|         EdgeId eId = *itr;
 | |
|         removeEdge(eId);
 | |
|       }
 | |
|       freeNodes.push_back(nId);
 | |
|     }
 | |
| 
 | |
|     /// \brief Remove an edge from the graph.
 | |
|     /// @param eId Edge id.
 | |
|     void removeEdge(EdgeId eId) {
 | |
|       EdgeEntry &e = getEdge(eId);
 | |
|       NodeEntry &n1 = getNode(e.getNode1());
 | |
|       NodeEntry &n2 = getNode(e.getNode2());
 | |
|       n1.removeEdge(e.getNode1AEItr());
 | |
|       n2.removeEdge(e.getNode2AEItr());
 | |
|       freeEdges.push_back(eId);
 | |
|     }
 | |
| 
 | |
|     /// \brief Remove all nodes and edges from the graph.
 | |
|     void clear() {
 | |
|       nodes.clear();
 | |
|       freeNodes.clear();
 | |
|       edges.clear();
 | |
|       freeEdges.clear();
 | |
|     }
 | |
| 
 | |
|     /// \brief Dump a graph to an output stream.
 | |
|     template <typename OStream>
 | |
|     void dump(OStream &os) {
 | |
|       os << getNumNodes() << " " << getNumEdges() << "\n";
 | |
| 
 | |
|       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
 | |
|            nodeItr != nodeEnd; ++nodeItr) {
 | |
|         const Vector& v = getNodeCosts(*nodeItr);
 | |
|         os << "\n" << v.getLength() << "\n";
 | |
|         assert(v.getLength() != 0 && "Empty vector in graph.");
 | |
|         os << v[0];
 | |
|         for (unsigned i = 1; i < v.getLength(); ++i) {
 | |
|           os << " " << v[i];
 | |
|         }
 | |
|         os << "\n";
 | |
|       }
 | |
| 
 | |
|       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
 | |
|            edgeItr != edgeEnd; ++edgeItr) {
 | |
|         NodeId n1 = getEdgeNode1(*edgeItr);
 | |
|         NodeId n2 = getEdgeNode2(*edgeItr);
 | |
|         assert(n1 != n2 && "PBQP graphs shound not have self-edges.");
 | |
|         const Matrix& m = getEdgeCosts(*edgeItr);
 | |
|         os << "\n" << n1 << " " << n2 << "\n"
 | |
|            << m.getRows() << " " << m.getCols() << "\n";
 | |
|         assert(m.getRows() != 0 && "No rows in matrix.");
 | |
|         assert(m.getCols() != 0 && "No cols in matrix.");
 | |
|         for (unsigned i = 0; i < m.getRows(); ++i) {
 | |
|           os << m[i][0];
 | |
|           for (unsigned j = 1; j < m.getCols(); ++j) {
 | |
|             os << " " << m[i][j];
 | |
|           }
 | |
|           os << "\n";
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     /// \brief Print a representation of this graph in DOT format.
 | |
|     /// @param os Output stream to print on.
 | |
|     template <typename OStream>
 | |
|     void printDot(OStream &os) {
 | |
| 
 | |
|       os << "graph {\n";
 | |
| 
 | |
|       for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
 | |
|            nodeItr != nodeEnd; ++nodeItr) {
 | |
| 
 | |
|         os << "  node" << nodeItr << " [ label=\""
 | |
|            << nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n";
 | |
|       }
 | |
| 
 | |
|       os << "  edge [ len=" << getNumNodes() << " ]\n";
 | |
| 
 | |
|       for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
 | |
|            edgeItr != edgeEnd; ++edgeItr) {
 | |
| 
 | |
|         os << "  node" << getEdgeNode1(*edgeItr)
 | |
|            << " -- node" << getEdgeNode2(*edgeItr)
 | |
|            << " [ label=\"";
 | |
| 
 | |
|         const Matrix &edgeCosts = getEdgeCosts(*edgeItr);
 | |
| 
 | |
|         for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
 | |
|           os << edgeCosts.getRowAsVector(i) << "\\n";
 | |
|         }
 | |
|         os << "\" ]\n";
 | |
|       }
 | |
|       os << "}\n";
 | |
|     }
 | |
| 
 | |
|   };
 | |
| 
 | |
| //  void Graph::copyFrom(const Graph &other) {
 | |
| //     std::map<Graph::ConstNodeItr, Graph::NodeItr,
 | |
| //              NodeItrComparator> nodeMap;
 | |
| 
 | |
| //      for (Graph::ConstNodeItr nItr = other.nodesBegin(),
 | |
| //                              nEnd = other.nodesEnd();
 | |
| //          nItr != nEnd; ++nItr) {
 | |
| //       nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
 | |
| //     }
 | |
| //  }
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP
 |