forked from OSchip/llvm-project
Re-apply r194300 with fixes for warnings.
llvm-svn: 194311
This commit is contained in:
parent
279430585a
commit
fb82630a91
|
@ -20,79 +20,63 @@
|
||||||
#include "llvm/ADT/ilist_node.h"
|
#include "llvm/ADT/ilist_node.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace PBQP {
|
namespace PBQP {
|
||||||
|
|
||||||
/// PBQP Graph class.
|
/// PBQP Graph class.
|
||||||
/// Instances of this class describe PBQP problems.
|
/// Instances of this class describe PBQP problems.
|
||||||
class Graph {
|
class Graph {
|
||||||
private:
|
|
||||||
|
|
||||||
// ----- TYPEDEFS -----
|
|
||||||
class NodeEntry;
|
|
||||||
class EdgeEntry;
|
|
||||||
|
|
||||||
typedef llvm::ilist<NodeEntry> NodeList;
|
|
||||||
typedef llvm::ilist<EdgeEntry> EdgeList;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef NodeList::iterator NodeItr;
|
typedef unsigned NodeId;
|
||||||
typedef NodeList::const_iterator ConstNodeItr;
|
typedef unsigned EdgeId;
|
||||||
|
|
||||||
typedef EdgeList::iterator EdgeItr;
|
|
||||||
typedef EdgeList::const_iterator ConstEdgeItr;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef std::list<EdgeItr> AdjEdgeList;
|
typedef std::set<NodeId> AdjEdgeList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef AdjEdgeList::iterator AdjEdgeItr;
|
typedef AdjEdgeList::iterator AdjEdgeItr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class NodeEntry : public llvm::ilist_node<NodeEntry> {
|
class NodeEntry {
|
||||||
friend struct llvm::ilist_sentinel_traits<NodeEntry>;
|
|
||||||
private:
|
private:
|
||||||
Vector costs;
|
Vector costs;
|
||||||
AdjEdgeList adjEdges;
|
AdjEdgeList adjEdges;
|
||||||
unsigned degree;
|
|
||||||
void *data;
|
void *data;
|
||||||
NodeEntry() : costs(0, 0) {}
|
NodeEntry() : costs(0, 0) {}
|
||||||
public:
|
public:
|
||||||
NodeEntry(const Vector &costs) : costs(costs), degree(0) {}
|
NodeEntry(const Vector &costs) : costs(costs), data(0) {}
|
||||||
Vector& getCosts() { return costs; }
|
Vector& getCosts() { return costs; }
|
||||||
const Vector& getCosts() const { return costs; }
|
const Vector& getCosts() const { return costs; }
|
||||||
unsigned getDegree() const { return degree; }
|
unsigned getDegree() const { return adjEdges.size(); }
|
||||||
AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
|
AdjEdgeItr edgesBegin() { return adjEdges.begin(); }
|
||||||
AdjEdgeItr edgesEnd() { return adjEdges.end(); }
|
AdjEdgeItr edgesEnd() { return adjEdges.end(); }
|
||||||
AdjEdgeItr addEdge(EdgeItr e) {
|
AdjEdgeItr addEdge(EdgeId e) {
|
||||||
++degree;
|
|
||||||
return adjEdges.insert(adjEdges.end(), e);
|
return adjEdges.insert(adjEdges.end(), e);
|
||||||
}
|
}
|
||||||
void removeEdge(AdjEdgeItr ae) {
|
void removeEdge(AdjEdgeItr ae) {
|
||||||
--degree;
|
|
||||||
adjEdges.erase(ae);
|
adjEdges.erase(ae);
|
||||||
}
|
}
|
||||||
void setData(void *data) { this->data = data; }
|
void setData(void *data) { this->data = data; }
|
||||||
void* getData() { return data; }
|
void* getData() { return data; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class EdgeEntry : public llvm::ilist_node<EdgeEntry> {
|
class EdgeEntry {
|
||||||
friend struct llvm::ilist_sentinel_traits<EdgeEntry>;
|
|
||||||
private:
|
private:
|
||||||
NodeItr node1, node2;
|
NodeId node1, node2;
|
||||||
Matrix costs;
|
Matrix costs;
|
||||||
AdjEdgeItr node1AEItr, node2AEItr;
|
AdjEdgeItr node1AEItr, node2AEItr;
|
||||||
void *data;
|
void *data;
|
||||||
EdgeEntry() : costs(0, 0, 0) {}
|
EdgeEntry() : costs(0, 0, 0), data(0) {}
|
||||||
public:
|
public:
|
||||||
EdgeEntry(NodeItr node1, NodeItr node2, const Matrix &costs)
|
EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs)
|
||||||
: node1(node1), node2(node2), costs(costs) {}
|
: node1(node1), node2(node2), costs(costs) {}
|
||||||
NodeItr getNode1() const { return node1; }
|
NodeId getNode1() const { return node1; }
|
||||||
NodeItr getNode2() const { return node2; }
|
NodeId getNode2() const { return node2; }
|
||||||
Matrix& getCosts() { return costs; }
|
Matrix& getCosts() { return costs; }
|
||||||
const Matrix& getCosts() const { return costs; }
|
const Matrix& getCosts() const { return costs; }
|
||||||
void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
|
void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; }
|
||||||
|
@ -105,72 +89,128 @@ namespace PBQP {
|
||||||
|
|
||||||
// ----- MEMBERS -----
|
// ----- MEMBERS -----
|
||||||
|
|
||||||
NodeList nodes;
|
typedef std::vector<NodeEntry> NodeVector;
|
||||||
unsigned numNodes;
|
typedef std::vector<NodeId> FreeNodeVector;
|
||||||
|
NodeVector nodes;
|
||||||
|
FreeNodeVector freeNodes;
|
||||||
|
|
||||||
EdgeList edges;
|
typedef std::vector<EdgeEntry> EdgeVector;
|
||||||
unsigned numEdges;
|
typedef std::vector<EdgeId> FreeEdgeVector;
|
||||||
|
EdgeVector edges;
|
||||||
|
FreeEdgeVector freeEdges;
|
||||||
|
|
||||||
// ----- INTERNAL METHODS -----
|
// ----- INTERNAL METHODS -----
|
||||||
|
|
||||||
NodeEntry& getNode(NodeItr nItr) { return *nItr; }
|
NodeEntry& getNode(NodeId nId) { return nodes[nId]; }
|
||||||
const NodeEntry& getNode(ConstNodeItr nItr) const { return *nItr; }
|
const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; }
|
||||||
|
|
||||||
EdgeEntry& getEdge(EdgeItr eItr) { return *eItr; }
|
EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; }
|
||||||
const EdgeEntry& getEdge(ConstEdgeItr eItr) const { return *eItr; }
|
const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; }
|
||||||
|
|
||||||
NodeItr addConstructedNode(const NodeEntry &n) {
|
NodeId addConstructedNode(const NodeEntry &n) {
|
||||||
++numNodes;
|
NodeId nodeId = 0;
|
||||||
return nodes.insert(nodes.end(), n);
|
if (!freeNodes.empty()) {
|
||||||
|
nodeId = freeNodes.back();
|
||||||
|
freeNodes.pop_back();
|
||||||
|
nodes[nodeId] = n;
|
||||||
|
} else {
|
||||||
|
nodeId = nodes.size();
|
||||||
|
nodes.push_back(n);
|
||||||
|
}
|
||||||
|
return nodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeItr addConstructedEdge(const EdgeEntry &e) {
|
EdgeId addConstructedEdge(const EdgeEntry &e) {
|
||||||
assert(findEdge(e.getNode1(), e.getNode2()) == edges.end() &&
|
assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() &&
|
||||||
"Attempt to add duplicate edge.");
|
"Attempt to add duplicate edge.");
|
||||||
++numEdges;
|
EdgeId edgeId = 0;
|
||||||
EdgeItr edgeItr = edges.insert(edges.end(), e);
|
if (!freeEdges.empty()) {
|
||||||
EdgeEntry &ne = getEdge(edgeItr);
|
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 &n1 = getNode(ne.getNode1());
|
||||||
NodeEntry &n2 = getNode(ne.getNode2());
|
NodeEntry &n2 = getNode(ne.getNode2());
|
||||||
|
|
||||||
// Sanity check on matrix dimensions:
|
// Sanity check on matrix dimensions:
|
||||||
assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
|
assert((n1.getCosts().getLength() == ne.getCosts().getRows()) &&
|
||||||
(n2.getCosts().getLength() == ne.getCosts().getCols()) &&
|
(n2.getCosts().getLength() == ne.getCosts().getCols()) &&
|
||||||
"Edge cost dimensions do not match node costs dimensions.");
|
"Edge cost dimensions do not match node costs dimensions.");
|
||||||
ne.setNode1AEItr(n1.addEdge(edgeItr));
|
|
||||||
ne.setNode2AEItr(n2.addEdge(edgeItr));
|
ne.setNode1AEItr(n1.addEdge(edgeId));
|
||||||
return edgeItr;
|
ne.setNode2AEItr(n2.addEdge(edgeId));
|
||||||
|
return edgeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void copyFrom(const Graph &other);
|
Graph(const Graph &other) {}
|
||||||
|
void operator=(const Graph &other) {}
|
||||||
|
|
||||||
public:
|
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.
|
/// \brief Construct an empty PBQP graph.
|
||||||
Graph() : numNodes(0), numEdges(0) {}
|
Graph() {}
|
||||||
|
|
||||||
/// \brief Copy construct this graph from "other". Note: Does not copy node
|
|
||||||
/// and edge data, only graph structure and costs.
|
|
||||||
/// @param other Source graph to copy from.
|
|
||||||
Graph(const Graph &other) : numNodes(0), numEdges(0) {
|
|
||||||
copyFrom(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Make this graph a copy of "other". Note: Does not copy node and
|
|
||||||
/// edge data, only graph structure and costs.
|
|
||||||
/// @param other The graph to copy from.
|
|
||||||
/// @return A reference to this graph.
|
|
||||||
///
|
|
||||||
/// This will clear the current graph, erasing any nodes and edges added,
|
|
||||||
/// before copying from other.
|
|
||||||
Graph& operator=(const Graph &other) {
|
|
||||||
clear();
|
|
||||||
copyFrom(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Add a node with the given costs.
|
/// \brief Add a node with the given costs.
|
||||||
/// @param costs Cost vector for the new node.
|
/// @param costs Cost vector for the new node.
|
||||||
/// @return Node iterator for the added node.
|
/// @return Node iterator for the added node.
|
||||||
NodeItr addNode(const Vector &costs) {
|
NodeId addNode(const Vector &costs) {
|
||||||
return addConstructedNode(NodeEntry(costs));
|
return addConstructedNode(NodeEntry(costs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,32 +218,31 @@ namespace PBQP {
|
||||||
/// @param n1Itr First node.
|
/// @param n1Itr First node.
|
||||||
/// @param n2Itr Second node.
|
/// @param n2Itr Second node.
|
||||||
/// @return Edge iterator for the added edge.
|
/// @return Edge iterator for the added edge.
|
||||||
EdgeItr addEdge(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr,
|
EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) {
|
||||||
const Matrix &costs) {
|
assert(getNodeCosts(n1Id).getLength() == costs.getRows() &&
|
||||||
assert(getNodeCosts(n1Itr).getLength() == costs.getRows() &&
|
getNodeCosts(n2Id).getLength() == costs.getCols() &&
|
||||||
getNodeCosts(n2Itr).getLength() == costs.getCols() &&
|
|
||||||
"Matrix dimensions mismatch.");
|
"Matrix dimensions mismatch.");
|
||||||
return addConstructedEdge(EdgeEntry(n1Itr, n2Itr, costs));
|
return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get the number of nodes in the graph.
|
/// \brief Get the number of nodes in the graph.
|
||||||
/// @return Number of nodes in the graph.
|
/// @return Number of nodes in the graph.
|
||||||
unsigned getNumNodes() const { return numNodes; }
|
unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); }
|
||||||
|
|
||||||
/// \brief Get the number of edges in the graph.
|
/// \brief Get the number of edges in the graph.
|
||||||
/// @return Number of edges in the graph.
|
/// @return Number of edges in the graph.
|
||||||
unsigned getNumEdges() const { return numEdges; }
|
unsigned getNumEdges() const { return edges.size() - freeEdges.size(); }
|
||||||
|
|
||||||
/// \brief Get a node's cost vector.
|
/// \brief Get a node's cost vector.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return Node cost vector.
|
/// @return Node cost vector.
|
||||||
Vector& getNodeCosts(NodeItr nItr) { return getNode(nItr).getCosts(); }
|
Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); }
|
||||||
|
|
||||||
/// \brief Get a node's cost vector (const version).
|
/// \brief Get a node's cost vector (const version).
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return Node cost vector.
|
/// @return Node cost vector.
|
||||||
const Vector& getNodeCosts(ConstNodeItr nItr) const {
|
const Vector& getNodeCosts(NodeId nId) const {
|
||||||
return getNode(nItr).getCosts();
|
return getNode(nId).getCosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Set a node's data pointer.
|
/// \brief Set a node's data pointer.
|
||||||
|
@ -211,23 +250,23 @@ namespace PBQP {
|
||||||
/// @param data Pointer to node data.
|
/// @param data Pointer to node data.
|
||||||
///
|
///
|
||||||
/// Typically used by a PBQP solver to attach data to aid in solution.
|
/// Typically used by a PBQP solver to attach data to aid in solution.
|
||||||
void setNodeData(NodeItr nItr, void *data) { getNode(nItr).setData(data); }
|
void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); }
|
||||||
|
|
||||||
/// \brief Get the node's data pointer.
|
/// \brief Get the node's data pointer.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return Pointer to node data.
|
/// @return Pointer to node data.
|
||||||
void* getNodeData(NodeItr nItr) { return getNode(nItr).getData(); }
|
void* getNodeData(NodeId nId) { return getNode(nId).getData(); }
|
||||||
|
|
||||||
/// \brief Get an edge's cost matrix.
|
/// \brief Get an edge's cost matrix.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return Edge cost matrix.
|
/// @return Edge cost matrix.
|
||||||
Matrix& getEdgeCosts(EdgeItr eItr) { return getEdge(eItr).getCosts(); }
|
Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); }
|
||||||
|
|
||||||
/// \brief Get an edge's cost matrix (const version).
|
/// \brief Get an edge's cost matrix (const version).
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return Edge cost matrix.
|
/// @return Edge cost matrix.
|
||||||
const Matrix& getEdgeCosts(ConstEdgeItr eItr) const {
|
const Matrix& getEdgeCosts(EdgeId eId) const {
|
||||||
return getEdge(eItr).getCosts();
|
return getEdge(eId).getCosts();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Set an edge's data pointer.
|
/// \brief Set an edge's data pointer.
|
||||||
|
@ -235,124 +274,120 @@ namespace PBQP {
|
||||||
/// @param data Pointer to edge data.
|
/// @param data Pointer to edge data.
|
||||||
///
|
///
|
||||||
/// Typically used by a PBQP solver to attach data to aid in solution.
|
/// Typically used by a PBQP solver to attach data to aid in solution.
|
||||||
void setEdgeData(EdgeItr eItr, void *data) { getEdge(eItr).setData(data); }
|
void setEdgeData(EdgeId eId, void *data) { getEdge(eId).setData(data); }
|
||||||
|
|
||||||
/// \brief Get an edge's data pointer.
|
/// \brief Get an edge's data pointer.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return Pointer to edge data.
|
/// @return Pointer to edge data.
|
||||||
void* getEdgeData(EdgeItr eItr) { return getEdge(eItr).getData(); }
|
void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); }
|
||||||
|
|
||||||
/// \brief Get a node's degree.
|
/// \brief Get a node's degree.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return The degree of the node.
|
/// @return The degree of the node.
|
||||||
unsigned getNodeDegree(NodeItr nItr) const {
|
unsigned getNodeDegree(NodeId nId) const {
|
||||||
return getNode(nItr).getDegree();
|
return getNode(nId).getDegree();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Begin iterator for node set.
|
/// \brief Begin iterator for node set.
|
||||||
NodeItr nodesBegin() { return nodes.begin(); }
|
NodeItr nodesBegin() const { return NodeItr(0, *this); }
|
||||||
|
|
||||||
/// \brief Begin const iterator for node set.
|
|
||||||
ConstNodeItr nodesBegin() const { return nodes.begin(); }
|
|
||||||
|
|
||||||
/// \brief End iterator for node set.
|
/// \brief End iterator for node set.
|
||||||
NodeItr nodesEnd() { return nodes.end(); }
|
NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); }
|
||||||
|
|
||||||
/// \brief End const iterator for node set.
|
|
||||||
ConstNodeItr nodesEnd() const { return nodes.end(); }
|
|
||||||
|
|
||||||
/// \brief Begin iterator for edge set.
|
/// \brief Begin iterator for edge set.
|
||||||
EdgeItr edgesBegin() { return edges.begin(); }
|
EdgeItr edgesBegin() const { return EdgeItr(0, *this); }
|
||||||
|
|
||||||
/// \brief End iterator for edge set.
|
/// \brief End iterator for edge set.
|
||||||
EdgeItr edgesEnd() { return edges.end(); }
|
EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); }
|
||||||
|
|
||||||
/// \brief Get begin iterator for adjacent edge set.
|
/// \brief Get begin iterator for adjacent edge set.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return Begin iterator for the set of edges connected to the given node.
|
/// @return Begin iterator for the set of edges connected to the given node.
|
||||||
AdjEdgeItr adjEdgesBegin(NodeItr nItr) {
|
AdjEdgeItr adjEdgesBegin(NodeId nId) {
|
||||||
return getNode(nItr).edgesBegin();
|
return getNode(nId).edgesBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get end iterator for adjacent edge set.
|
/// \brief Get end iterator for adjacent edge set.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return End iterator for the set of edges connected to the given node.
|
/// @return End iterator for the set of edges connected to the given node.
|
||||||
AdjEdgeItr adjEdgesEnd(NodeItr nItr) {
|
AdjEdgeItr adjEdgesEnd(NodeId nId) {
|
||||||
return getNode(nItr).edgesEnd();
|
return getNode(nId).edgesEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get the first node connected to this edge.
|
/// \brief Get the first node connected to this edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return The first node connected to the given edge.
|
/// @return The first node connected to the given edge.
|
||||||
NodeItr getEdgeNode1(EdgeItr eItr) {
|
NodeId getEdgeNode1(EdgeId eId) {
|
||||||
return getEdge(eItr).getNode1();
|
return getEdge(eId).getNode1();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get the second node connected to this edge.
|
/// \brief Get the second node connected to this edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return The second node connected to the given edge.
|
/// @return The second node connected to the given edge.
|
||||||
NodeItr getEdgeNode2(EdgeItr eItr) {
|
NodeId getEdgeNode2(EdgeId eId) {
|
||||||
return getEdge(eItr).getNode2();
|
return getEdge(eId).getNode2();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get the "other" node connected to this edge.
|
/// \brief Get the "other" node connected to this edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @param nItr Node iterator for the "given" node.
|
/// @param nItr Node iterator for the "given" node.
|
||||||
/// @return The iterator for the "other" node connected to this edge.
|
/// @return The iterator for the "other" node connected to this edge.
|
||||||
NodeItr getEdgeOtherNode(EdgeItr eItr, NodeItr nItr) {
|
NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) {
|
||||||
EdgeEntry &e = getEdge(eItr);
|
EdgeEntry &e = getEdge(eId);
|
||||||
if (e.getNode1() == nItr) {
|
if (e.getNode1() == nId) {
|
||||||
return e.getNode2();
|
return e.getNode2();
|
||||||
} // else
|
} // else
|
||||||
return e.getNode1();
|
return e.getNode1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeId invalidEdgeId() const {
|
||||||
|
return std::numeric_limits<EdgeId>::max();
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Get the edge connecting two nodes.
|
/// \brief Get the edge connecting two nodes.
|
||||||
/// @param n1Itr First node iterator.
|
/// @param n1Id First node id.
|
||||||
/// @param n2Itr Second node iterator.
|
/// @param n2Id Second node id.
|
||||||
/// @return An iterator for edge (n1Itr, n2Itr) if such an edge exists,
|
/// @return An id for edge (n1Id, n2Id) if such an edge exists,
|
||||||
/// otherwise returns edgesEnd().
|
/// otherwise returns an invalid edge id.
|
||||||
EdgeItr findEdge(NodeItr n1Itr, NodeItr n2Itr) {
|
EdgeId findEdge(NodeId n1Id, NodeId n2Id) {
|
||||||
for (AdjEdgeItr aeItr = adjEdgesBegin(n1Itr), aeEnd = adjEdgesEnd(n1Itr);
|
for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id);
|
||||||
aeItr != aeEnd; ++aeItr) {
|
aeItr != aeEnd; ++aeItr) {
|
||||||
if ((getEdgeNode1(*aeItr) == n2Itr) ||
|
if ((getEdgeNode1(*aeItr) == n2Id) ||
|
||||||
(getEdgeNode2(*aeItr) == n2Itr)) {
|
(getEdgeNode2(*aeItr) == n2Id)) {
|
||||||
return *aeItr;
|
return *aeItr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return edges.end();
|
return invalidEdgeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Remove a node from the graph.
|
/// \brief Remove a node from the graph.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node id.
|
||||||
void removeNode(NodeItr nItr) {
|
void removeNode(NodeId nId) {
|
||||||
NodeEntry &n = getNode(nItr);
|
NodeEntry &n = getNode(nId);
|
||||||
for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end;) {
|
for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) {
|
||||||
EdgeItr eItr = *itr;
|
EdgeId eId = *itr;
|
||||||
++itr;
|
removeEdge(eId);
|
||||||
removeEdge(eItr);
|
|
||||||
}
|
}
|
||||||
nodes.erase(nItr);
|
freeNodes.push_back(nId);
|
||||||
--numNodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Remove an edge from the graph.
|
/// \brief Remove an edge from the graph.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
void removeEdge(EdgeItr eItr) {
|
void removeEdge(EdgeId eId) {
|
||||||
EdgeEntry &e = getEdge(eItr);
|
EdgeEntry &e = getEdge(eId);
|
||||||
NodeEntry &n1 = getNode(e.getNode1());
|
NodeEntry &n1 = getNode(e.getNode1());
|
||||||
NodeEntry &n2 = getNode(e.getNode2());
|
NodeEntry &n2 = getNode(e.getNode2());
|
||||||
n1.removeEdge(e.getNode1AEItr());
|
n1.removeEdge(e.getNode1AEItr());
|
||||||
n2.removeEdge(e.getNode2AEItr());
|
n2.removeEdge(e.getNode2AEItr());
|
||||||
edges.erase(eItr);
|
freeEdges.push_back(eId);
|
||||||
--numEdges;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Remove all nodes and edges from the graph.
|
/// \brief Remove all nodes and edges from the graph.
|
||||||
void clear() {
|
void clear() {
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
|
freeNodes.clear();
|
||||||
edges.clear();
|
edges.clear();
|
||||||
numNodes = numEdges = 0;
|
freeEdges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Dump a graph to an output stream.
|
/// \brief Dump a graph to an output stream.
|
||||||
|
@ -362,7 +397,7 @@ namespace PBQP {
|
||||||
|
|
||||||
for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
|
for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd();
|
||||||
nodeItr != nodeEnd; ++nodeItr) {
|
nodeItr != nodeEnd; ++nodeItr) {
|
||||||
const Vector& v = getNodeCosts(nodeItr);
|
const Vector& v = getNodeCosts(*nodeItr);
|
||||||
os << "\n" << v.getLength() << "\n";
|
os << "\n" << v.getLength() << "\n";
|
||||||
assert(v.getLength() != 0 && "Empty vector in graph.");
|
assert(v.getLength() != 0 && "Empty vector in graph.");
|
||||||
os << v[0];
|
os << v[0];
|
||||||
|
@ -374,10 +409,10 @@ namespace PBQP {
|
||||||
|
|
||||||
for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
|
for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
|
||||||
edgeItr != edgeEnd; ++edgeItr) {
|
edgeItr != edgeEnd; ++edgeItr) {
|
||||||
unsigned n1 = std::distance(nodesBegin(), getEdgeNode1(edgeItr));
|
NodeId n1 = getEdgeNode1(*edgeItr);
|
||||||
unsigned n2 = std::distance(nodesBegin(), getEdgeNode2(edgeItr));
|
NodeId n2 = getEdgeNode2(*edgeItr);
|
||||||
assert(n1 != n2 && "PBQP graphs shound not have self-edges.");
|
assert(n1 != n2 && "PBQP graphs shound not have self-edges.");
|
||||||
const Matrix& m = getEdgeCosts(edgeItr);
|
const Matrix& m = getEdgeCosts(*edgeItr);
|
||||||
os << "\n" << n1 << " " << n2 << "\n"
|
os << "\n" << n1 << " " << n2 << "\n"
|
||||||
<< m.getRows() << " " << m.getCols() << "\n";
|
<< m.getRows() << " " << m.getCols() << "\n";
|
||||||
assert(m.getRows() != 0 && "No rows in matrix.");
|
assert(m.getRows() != 0 && "No rows in matrix.");
|
||||||
|
@ -403,7 +438,7 @@ namespace PBQP {
|
||||||
nodeItr != nodeEnd; ++nodeItr) {
|
nodeItr != nodeEnd; ++nodeItr) {
|
||||||
|
|
||||||
os << " node" << nodeItr << " [ label=\""
|
os << " node" << nodeItr << " [ label=\""
|
||||||
<< nodeItr << ": " << getNodeCosts(nodeItr) << "\" ]\n";
|
<< nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
os << " edge [ len=" << getNumNodes() << " ]\n";
|
os << " edge [ len=" << getNumNodes() << " ]\n";
|
||||||
|
@ -411,11 +446,11 @@ namespace PBQP {
|
||||||
for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
|
for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd();
|
||||||
edgeItr != edgeEnd; ++edgeItr) {
|
edgeItr != edgeEnd; ++edgeItr) {
|
||||||
|
|
||||||
os << " node" << getEdgeNode1(edgeItr)
|
os << " node" << getEdgeNode1(*edgeItr)
|
||||||
<< " -- node" << getEdgeNode2(edgeItr)
|
<< " -- node" << getEdgeNode2(*edgeItr)
|
||||||
<< " [ label=\"";
|
<< " [ label=\"";
|
||||||
|
|
||||||
const Matrix &edgeCosts = getEdgeCosts(edgeItr);
|
const Matrix &edgeCosts = getEdgeCosts(*edgeItr);
|
||||||
|
|
||||||
for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
|
for (unsigned i = 0; i < edgeCosts.getRows(); ++i) {
|
||||||
os << edgeCosts.getRowAsVector(i) << "\\n";
|
os << edgeCosts.getRowAsVector(i) << "\\n";
|
||||||
|
@ -427,39 +462,16 @@ namespace PBQP {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NodeItrComparator {
|
// void Graph::copyFrom(const Graph &other) {
|
||||||
public:
|
// std::map<Graph::ConstNodeItr, Graph::NodeItr,
|
||||||
bool operator()(Graph::NodeItr n1, Graph::NodeItr n2) const {
|
// NodeItrComparator> nodeMap;
|
||||||
return &*n1 < &*n2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(Graph::ConstNodeItr n1, Graph::ConstNodeItr n2) const {
|
// for (Graph::ConstNodeItr nItr = other.nodesBegin(),
|
||||||
return &*n1 < &*n2;
|
// nEnd = other.nodesEnd();
|
||||||
}
|
// nItr != nEnd; ++nItr) {
|
||||||
};
|
// nodeMap[nItr] = addNode(other.getNodeCosts(nItr));
|
||||||
|
// }
|
||||||
class EdgeItrCompartor {
|
// }
|
||||||
public:
|
|
||||||
bool operator()(Graph::EdgeItr e1, Graph::EdgeItr e2) const {
|
|
||||||
return &*e1 < &*e2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(Graph::ConstEdgeItr e1, Graph::ConstEdgeItr e2) const {
|
|
||||||
return &*e1 < &*e2;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace PBQP {
|
||||||
class HeuristicBase {
|
class HeuristicBase {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef std::list<Graph::NodeItr> OptimalList;
|
typedef std::list<Graph::NodeId> OptimalList;
|
||||||
|
|
||||||
HeuristicSolverImpl<HImpl> &s;
|
HeuristicSolverImpl<HImpl> &s;
|
||||||
Graph &g;
|
Graph &g;
|
||||||
|
@ -63,8 +63,8 @@ namespace PBQP {
|
||||||
|
|
||||||
// Add the given node to the optimal reductions list. Keep an iterator to
|
// Add the given node to the optimal reductions list. Keep an iterator to
|
||||||
// its location for fast removal.
|
// its location for fast removal.
|
||||||
void addToOptimalReductionList(Graph::NodeItr nItr) {
|
void addToOptimalReductionList(Graph::NodeId nId) {
|
||||||
optimalList.insert(optimalList.end(), nItr);
|
optimalList.insert(optimalList.end(), nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -105,8 +105,8 @@ namespace PBQP {
|
||||||
/// criteria. Note however that your criteria for selecting optimal nodes
|
/// criteria. Note however that your criteria for selecting optimal nodes
|
||||||
/// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or
|
/// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or
|
||||||
/// higher should not be selected under any circumstances.
|
/// higher should not be selected under any circumstances.
|
||||||
bool shouldOptimallyReduce(Graph::NodeItr nItr) {
|
bool shouldOptimallyReduce(Graph::NodeId nId) {
|
||||||
if (g.getNodeDegree(nItr) < 3)
|
if (g.getNodeDegree(nId) < 3)
|
||||||
return true;
|
return true;
|
||||||
// else
|
// else
|
||||||
return false;
|
return false;
|
||||||
|
@ -118,8 +118,8 @@ namespace PBQP {
|
||||||
/// You probably don't want to over-ride this, except perhaps to record
|
/// You probably don't want to over-ride this, except perhaps to record
|
||||||
/// statistics before calling this implementation. HeuristicBase relies on
|
/// statistics before calling this implementation. HeuristicBase relies on
|
||||||
/// its behaviour.
|
/// its behaviour.
|
||||||
void addToOptimalReduceList(Graph::NodeItr nItr) {
|
void addToOptimalReduceList(Graph::NodeId nId) {
|
||||||
optimalList.push_back(nItr);
|
optimalList.push_back(nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Initialise the heuristic.
|
/// \brief Initialise the heuristic.
|
||||||
|
@ -132,10 +132,10 @@ namespace PBQP {
|
||||||
void setup() {
|
void setup() {
|
||||||
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
||||||
nItr != nEnd; ++nItr) {
|
nItr != nEnd; ++nItr) {
|
||||||
if (impl().shouldOptimallyReduce(nItr)) {
|
if (impl().shouldOptimallyReduce(*nItr)) {
|
||||||
addToOptimalReduceList(nItr);
|
addToOptimalReduceList(*nItr);
|
||||||
} else {
|
} else {
|
||||||
impl().addToHeuristicReduceList(nItr);
|
impl().addToHeuristicReduceList(*nItr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,13 +150,13 @@ namespace PBQP {
|
||||||
if (optimalList.empty())
|
if (optimalList.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Graph::NodeItr nItr = optimalList.front();
|
Graph::NodeId nId = optimalList.front();
|
||||||
optimalList.pop_front();
|
optimalList.pop_front();
|
||||||
|
|
||||||
switch (s.getSolverDegree(nItr)) {
|
switch (s.getSolverDegree(nId)) {
|
||||||
case 0: s.applyR0(nItr); break;
|
case 0: s.applyR0(nId); break;
|
||||||
case 1: s.applyR1(nItr); break;
|
case 1: s.applyR1(nId); break;
|
||||||
case 2: s.applyR2(nItr); break;
|
case 2: s.applyR2(nId); break;
|
||||||
default: llvm_unreachable(
|
default: llvm_unreachable(
|
||||||
"Optimal reductions of degree > 2 nodes is invalid.");
|
"Optimal reductions of degree > 2 nodes is invalid.");
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ namespace PBQP {
|
||||||
|
|
||||||
/// \brief Add a node to the heuristic reduce list.
|
/// \brief Add a node to the heuristic reduce list.
|
||||||
/// @param nItr Node iterator to add to the heuristic reduce list.
|
/// @param nItr Node iterator to add to the heuristic reduce list.
|
||||||
void addToHeuristicList(Graph::NodeItr nItr) {
|
void addToHeuristicList(Graph::NodeId nId) {
|
||||||
llvm_unreachable("Must be implemented in derived class.");
|
llvm_unreachable("Must be implemented in derived class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,19 +200,19 @@ namespace PBQP {
|
||||||
|
|
||||||
/// \brief Prepare a change in the costs on the given edge.
|
/// \brief Prepare a change in the costs on the given edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
void preUpdateEdgeCosts(Graph::EdgeItr eItr) {
|
void preUpdateEdgeCosts(Graph::EdgeId eId) {
|
||||||
llvm_unreachable("Must be implemented in derived class.");
|
llvm_unreachable("Must be implemented in derived class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Handle the change in the costs on the given edge.
|
/// \brief Handle the change in the costs on the given edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
void postUpdateEdgeCostts(Graph::EdgeItr eItr) {
|
void postUpdateEdgeCostts(Graph::EdgeId eId) {
|
||||||
llvm_unreachable("Must be implemented in derived class.");
|
llvm_unreachable("Must be implemented in derived class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Handle the addition of a new edge into the PBQP graph.
|
/// \brief Handle the addition of a new edge into the PBQP graph.
|
||||||
/// @param eItr Edge iterator for the added edge.
|
/// @param eItr Edge iterator for the added edge.
|
||||||
void handleAddEdge(Graph::EdgeItr eItr) {
|
void handleAddEdge(Graph::EdgeId eId) {
|
||||||
llvm_unreachable("Must be implemented in derived class.");
|
llvm_unreachable("Must be implemented in derived class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ namespace PBQP {
|
||||||
/// Edges are frequently removed due to the removal of a node. This
|
/// Edges are frequently removed due to the removal of a node. This
|
||||||
/// method allows for the effect to be computed only for the remaining
|
/// method allows for the effect to be computed only for the remaining
|
||||||
/// node in the graph.
|
/// node in the graph.
|
||||||
void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) {
|
void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) {
|
||||||
llvm_unreachable("Must be implemented in derived class.");
|
llvm_unreachable("Must be implemented in derived class.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace PBQP {
|
||||||
typedef typename HImpl::NodeData HeuristicNodeData;
|
typedef typename HImpl::NodeData HeuristicNodeData;
|
||||||
typedef typename HImpl::EdgeData HeuristicEdgeData;
|
typedef typename HImpl::EdgeData HeuristicEdgeData;
|
||||||
|
|
||||||
typedef std::list<Graph::EdgeItr> SolverEdges;
|
typedef std::list<Graph::EdgeId> SolverEdges;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ namespace PBQP {
|
||||||
|
|
||||||
HeuristicNodeData& getHeuristicData() { return hData; }
|
HeuristicNodeData& getHeuristicData() { return hData; }
|
||||||
|
|
||||||
SolverEdgeItr addSolverEdge(Graph::EdgeItr eItr) {
|
SolverEdgeItr addSolverEdge(Graph::EdgeId eId) {
|
||||||
++solverDegree;
|
++solverDegree;
|
||||||
return solverEdges.insert(solverEdges.end(), eItr);
|
return solverEdges.insert(solverEdges.end(), eId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeSolverEdge(SolverEdgeItr seItr) {
|
void removeSolverEdge(SolverEdgeItr seItr) {
|
||||||
|
@ -104,7 +104,7 @@ namespace PBQP {
|
||||||
Graph &g;
|
Graph &g;
|
||||||
HImpl h;
|
HImpl h;
|
||||||
Solution s;
|
Solution s;
|
||||||
std::vector<Graph::NodeItr> stack;
|
std::vector<Graph::NodeId> stack;
|
||||||
|
|
||||||
typedef std::list<NodeData> NodeDataList;
|
typedef std::list<NodeData> NodeDataList;
|
||||||
NodeDataList nodeDataList;
|
NodeDataList nodeDataList;
|
||||||
|
@ -127,15 +127,15 @@ namespace PBQP {
|
||||||
/// \brief Get the heuristic data attached to the given node.
|
/// \brief Get the heuristic data attached to the given node.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return The heuristic data attached to the given node.
|
/// @return The heuristic data attached to the given node.
|
||||||
HeuristicNodeData& getHeuristicNodeData(Graph::NodeItr nItr) {
|
HeuristicNodeData& getHeuristicNodeData(Graph::NodeId nId) {
|
||||||
return getSolverNodeData(nItr).getHeuristicData();
|
return getSolverNodeData(nId).getHeuristicData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get the heuristic data attached to the given edge.
|
/// \brief Get the heuristic data attached to the given edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
/// @return The heuristic data attached to the given node.
|
/// @return The heuristic data attached to the given node.
|
||||||
HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) {
|
HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeId eId) {
|
||||||
return getSolverEdgeData(eItr).getHeuristicData();
|
return getSolverEdgeData(eId).getHeuristicData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Begin iterator for the set of edges adjacent to the given node in
|
/// \brief Begin iterator for the set of edges adjacent to the given node in
|
||||||
|
@ -143,8 +143,8 @@ namespace PBQP {
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return Begin iterator for the set of edges adjacent to the given node
|
/// @return Begin iterator for the set of edges adjacent to the given node
|
||||||
/// in the solver graph.
|
/// in the solver graph.
|
||||||
SolverEdgeItr solverEdgesBegin(Graph::NodeItr nItr) {
|
SolverEdgeItr solverEdgesBegin(Graph::NodeId nId) {
|
||||||
return getSolverNodeData(nItr).solverEdgesBegin();
|
return getSolverNodeData(nId).solverEdgesBegin();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief End iterator for the set of edges adjacent to the given node in
|
/// \brief End iterator for the set of edges adjacent to the given node in
|
||||||
|
@ -152,8 +152,8 @@ namespace PBQP {
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return End iterator for the set of edges adjacent to the given node in
|
/// @return End iterator for the set of edges adjacent to the given node in
|
||||||
/// the solver graph.
|
/// the solver graph.
|
||||||
SolverEdgeItr solverEdgesEnd(Graph::NodeItr nItr) {
|
SolverEdgeItr solverEdgesEnd(Graph::NodeId nId) {
|
||||||
return getSolverNodeData(nItr).solverEdgesEnd();
|
return getSolverNodeData(nId).solverEdgesEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Remove a node from the solver graph.
|
/// \brief Remove a node from the solver graph.
|
||||||
|
@ -161,10 +161,10 @@ namespace PBQP {
|
||||||
///
|
///
|
||||||
/// Does <i>not</i> notify the heuristic of the removal. That should be
|
/// Does <i>not</i> notify the heuristic of the removal. That should be
|
||||||
/// done manually if necessary.
|
/// done manually if necessary.
|
||||||
void removeSolverEdge(Graph::EdgeItr eItr) {
|
void removeSolverEdge(Graph::EdgeId eId) {
|
||||||
EdgeData &eData = getSolverEdgeData(eItr);
|
EdgeData &eData = getSolverEdgeData(eId);
|
||||||
NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)),
|
NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)),
|
||||||
&n2Data = getSolverNodeData(g.getEdgeNode2(eItr));
|
&n2Data = getSolverNodeData(g.getEdgeNode2(eId));
|
||||||
|
|
||||||
n1Data.removeSolverEdge(eData.getN1SolverEdgeItr());
|
n1Data.removeSolverEdge(eData.getN1SolverEdgeItr());
|
||||||
n2Data.removeSolverEdge(eData.getN2SolverEdgeItr());
|
n2Data.removeSolverEdge(eData.getN2SolverEdgeItr());
|
||||||
|
@ -189,30 +189,30 @@ namespace PBQP {
|
||||||
|
|
||||||
/// \brief Add to the end of the stack.
|
/// \brief Add to the end of the stack.
|
||||||
/// @param nItr Node iterator to add to the reduction stack.
|
/// @param nItr Node iterator to add to the reduction stack.
|
||||||
void pushToStack(Graph::NodeItr nItr) {
|
void pushToStack(Graph::NodeId nId) {
|
||||||
getSolverNodeData(nItr).clearSolverEdges();
|
getSolverNodeData(nId).clearSolverEdges();
|
||||||
stack.push_back(nItr);
|
stack.push_back(nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns the solver degree of the given node.
|
/// \brief Returns the solver degree of the given node.
|
||||||
/// @param nItr Node iterator for which degree is requested.
|
/// @param nItr Node iterator for which degree is requested.
|
||||||
/// @return Node degree in the <i>solver</i> graph (not the original graph).
|
/// @return Node degree in the <i>solver</i> graph (not the original graph).
|
||||||
unsigned getSolverDegree(Graph::NodeItr nItr) {
|
unsigned getSolverDegree(Graph::NodeId nId) {
|
||||||
return getSolverNodeData(nItr).getSolverDegree();
|
return getSolverNodeData(nId).getSolverDegree();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Set the solution of the given node.
|
/// \brief Set the solution of the given node.
|
||||||
/// @param nItr Node iterator to set solution for.
|
/// @param nItr Node iterator to set solution for.
|
||||||
/// @param selection Selection for node.
|
/// @param selection Selection for node.
|
||||||
void setSolution(const Graph::NodeItr &nItr, unsigned selection) {
|
void setSolution(const Graph::NodeId &nId, unsigned selection) {
|
||||||
s.setSelection(nItr, selection);
|
s.setSelection(nId, selection);
|
||||||
|
|
||||||
for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr),
|
for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId),
|
||||||
aeEnd = g.adjEdgesEnd(nItr);
|
aeEnd = g.adjEdgesEnd(nId);
|
||||||
aeItr != aeEnd; ++aeItr) {
|
aeItr != aeEnd; ++aeItr) {
|
||||||
Graph::EdgeItr eItr(*aeItr);
|
Graph::EdgeId eId(*aeItr);
|
||||||
Graph::NodeItr anItr(g.getEdgeOtherNode(eItr, nItr));
|
Graph::NodeId anId(g.getEdgeOtherNode(eId, nId));
|
||||||
getSolverNodeData(anItr).addSolverEdge(eItr);
|
getSolverNodeData(anId).addSolverEdge(eId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,12 +220,12 @@ namespace PBQP {
|
||||||
/// @param nItr Node iterator for node to apply R0 to.
|
/// @param nItr Node iterator for node to apply R0 to.
|
||||||
///
|
///
|
||||||
/// Node will be automatically pushed to the solver stack.
|
/// Node will be automatically pushed to the solver stack.
|
||||||
void applyR0(Graph::NodeItr nItr) {
|
void applyR0(Graph::NodeId nId) {
|
||||||
assert(getSolverNodeData(nItr).getSolverDegree() == 0 &&
|
assert(getSolverNodeData(nId).getSolverDegree() == 0 &&
|
||||||
"R0 applied to node with degree != 0.");
|
"R0 applied to node with degree != 0.");
|
||||||
|
|
||||||
// Nothing to do. Just push the node onto the reduction stack.
|
// Nothing to do. Just push the node onto the reduction stack.
|
||||||
pushToStack(nItr);
|
pushToStack(nId);
|
||||||
|
|
||||||
s.recordR0();
|
s.recordR0();
|
||||||
}
|
}
|
||||||
|
@ -234,20 +234,20 @@ namespace PBQP {
|
||||||
/// @param xnItr Node iterator for node to apply R1 to.
|
/// @param xnItr Node iterator for node to apply R1 to.
|
||||||
///
|
///
|
||||||
/// Node will be automatically pushed to the solver stack.
|
/// Node will be automatically pushed to the solver stack.
|
||||||
void applyR1(Graph::NodeItr xnItr) {
|
void applyR1(Graph::NodeId xnId) {
|
||||||
NodeData &nd = getSolverNodeData(xnItr);
|
NodeData &nd = getSolverNodeData(xnId);
|
||||||
assert(nd.getSolverDegree() == 1 &&
|
assert(nd.getSolverDegree() == 1 &&
|
||||||
"R1 applied to node with degree != 1.");
|
"R1 applied to node with degree != 1.");
|
||||||
|
|
||||||
Graph::EdgeItr eItr = *nd.solverEdgesBegin();
|
Graph::EdgeId eId = *nd.solverEdgesBegin();
|
||||||
|
|
||||||
const Matrix &eCosts = g.getEdgeCosts(eItr);
|
const Matrix &eCosts = g.getEdgeCosts(eId);
|
||||||
const Vector &xCosts = g.getNodeCosts(xnItr);
|
const Vector &xCosts = g.getNodeCosts(xnId);
|
||||||
|
|
||||||
// Duplicate a little to avoid transposing matrices.
|
// Duplicate a little to avoid transposing matrices.
|
||||||
if (xnItr == g.getEdgeNode1(eItr)) {
|
if (xnId == g.getEdgeNode1(eId)) {
|
||||||
Graph::NodeItr ynItr = g.getEdgeNode2(eItr);
|
Graph::NodeId ynId = g.getEdgeNode2(eId);
|
||||||
Vector &yCosts = g.getNodeCosts(ynItr);
|
Vector &yCosts = g.getNodeCosts(ynId);
|
||||||
for (unsigned j = 0; j < yCosts.getLength(); ++j) {
|
for (unsigned j = 0; j < yCosts.getLength(); ++j) {
|
||||||
PBQPNum min = eCosts[0][j] + xCosts[0];
|
PBQPNum min = eCosts[0][j] + xCosts[0];
|
||||||
for (unsigned i = 1; i < xCosts.getLength(); ++i) {
|
for (unsigned i = 1; i < xCosts.getLength(); ++i) {
|
||||||
|
@ -257,10 +257,10 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
yCosts[j] += min;
|
yCosts[j] += min;
|
||||||
}
|
}
|
||||||
h.handleRemoveEdge(eItr, ynItr);
|
h.handleRemoveEdge(eId, ynId);
|
||||||
} else {
|
} else {
|
||||||
Graph::NodeItr ynItr = g.getEdgeNode1(eItr);
|
Graph::NodeId ynId = g.getEdgeNode1(eId);
|
||||||
Vector &yCosts = g.getNodeCosts(ynItr);
|
Vector &yCosts = g.getNodeCosts(ynId);
|
||||||
for (unsigned i = 0; i < yCosts.getLength(); ++i) {
|
for (unsigned i = 0; i < yCosts.getLength(); ++i) {
|
||||||
PBQPNum min = eCosts[i][0] + xCosts[0];
|
PBQPNum min = eCosts[i][0] + xCosts[0];
|
||||||
for (unsigned j = 1; j < xCosts.getLength(); ++j) {
|
for (unsigned j = 1; j < xCosts.getLength(); ++j) {
|
||||||
|
@ -270,12 +270,12 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
yCosts[i] += min;
|
yCosts[i] += min;
|
||||||
}
|
}
|
||||||
h.handleRemoveEdge(eItr, ynItr);
|
h.handleRemoveEdge(eId, ynId);
|
||||||
}
|
}
|
||||||
removeSolverEdge(eItr);
|
removeSolverEdge(eId);
|
||||||
assert(nd.getSolverDegree() == 0 &&
|
assert(nd.getSolverDegree() == 0 &&
|
||||||
"Degree 1 with edge removed should be 0.");
|
"Degree 1 with edge removed should be 0.");
|
||||||
pushToStack(xnItr);
|
pushToStack(xnId);
|
||||||
s.recordR1();
|
s.recordR1();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,30 +283,30 @@ namespace PBQP {
|
||||||
/// @param xnItr Node iterator for node to apply R2 to.
|
/// @param xnItr Node iterator for node to apply R2 to.
|
||||||
///
|
///
|
||||||
/// Node will be automatically pushed to the solver stack.
|
/// Node will be automatically pushed to the solver stack.
|
||||||
void applyR2(Graph::NodeItr xnItr) {
|
void applyR2(Graph::NodeId xnId) {
|
||||||
assert(getSolverNodeData(xnItr).getSolverDegree() == 2 &&
|
assert(getSolverNodeData(xnId).getSolverDegree() == 2 &&
|
||||||
"R2 applied to node with degree != 2.");
|
"R2 applied to node with degree != 2.");
|
||||||
|
|
||||||
NodeData &nd = getSolverNodeData(xnItr);
|
NodeData &nd = getSolverNodeData(xnId);
|
||||||
const Vector &xCosts = g.getNodeCosts(xnItr);
|
const Vector &xCosts = g.getNodeCosts(xnId);
|
||||||
|
|
||||||
SolverEdgeItr aeItr = nd.solverEdgesBegin();
|
SolverEdgeItr aeItr = nd.solverEdgesBegin();
|
||||||
Graph::EdgeItr yxeItr = *aeItr,
|
Graph::EdgeId yxeId = *aeItr,
|
||||||
zxeItr = *(++aeItr);
|
zxeId = *(++aeItr);
|
||||||
|
|
||||||
Graph::NodeItr ynItr = g.getEdgeOtherNode(yxeItr, xnItr),
|
Graph::NodeId ynId = g.getEdgeOtherNode(yxeId, xnId),
|
||||||
znItr = g.getEdgeOtherNode(zxeItr, xnItr);
|
znId = g.getEdgeOtherNode(zxeId, xnId);
|
||||||
|
|
||||||
bool flipEdge1 = (g.getEdgeNode1(yxeItr) == xnItr),
|
bool flipEdge1 = (g.getEdgeNode1(yxeId) == xnId),
|
||||||
flipEdge2 = (g.getEdgeNode1(zxeItr) == xnItr);
|
flipEdge2 = (g.getEdgeNode1(zxeId) == xnId);
|
||||||
|
|
||||||
const Matrix *yxeCosts = flipEdge1 ?
|
const Matrix *yxeCosts = flipEdge1 ?
|
||||||
new Matrix(g.getEdgeCosts(yxeItr).transpose()) :
|
new Matrix(g.getEdgeCosts(yxeId).transpose()) :
|
||||||
&g.getEdgeCosts(yxeItr);
|
&g.getEdgeCosts(yxeId);
|
||||||
|
|
||||||
const Matrix *zxeCosts = flipEdge2 ?
|
const Matrix *zxeCosts = flipEdge2 ?
|
||||||
new Matrix(g.getEdgeCosts(zxeItr).transpose()) :
|
new Matrix(g.getEdgeCosts(zxeId).transpose()) :
|
||||||
&g.getEdgeCosts(zxeItr);
|
&g.getEdgeCosts(zxeId);
|
||||||
|
|
||||||
unsigned xLen = xCosts.getLength(),
|
unsigned xLen = xCosts.getLength(),
|
||||||
yLen = yxeCosts->getRows(),
|
yLen = yxeCosts->getRows(),
|
||||||
|
@ -333,27 +333,27 @@ namespace PBQP {
|
||||||
if (flipEdge2)
|
if (flipEdge2)
|
||||||
delete zxeCosts;
|
delete zxeCosts;
|
||||||
|
|
||||||
Graph::EdgeItr yzeItr = g.findEdge(ynItr, znItr);
|
Graph::EdgeId yzeId = g.findEdge(ynId, znId);
|
||||||
bool addedEdge = false;
|
bool addedEdge = false;
|
||||||
|
|
||||||
if (yzeItr == g.edgesEnd()) {
|
if (yzeId == g.invalidEdgeId()) {
|
||||||
yzeItr = g.addEdge(ynItr, znItr, delta);
|
yzeId = g.addEdge(ynId, znId, delta);
|
||||||
addedEdge = true;
|
addedEdge = true;
|
||||||
} else {
|
} else {
|
||||||
Matrix &yzeCosts = g.getEdgeCosts(yzeItr);
|
Matrix &yzeCosts = g.getEdgeCosts(yzeId);
|
||||||
h.preUpdateEdgeCosts(yzeItr);
|
h.preUpdateEdgeCosts(yzeId);
|
||||||
if (ynItr == g.getEdgeNode1(yzeItr)) {
|
if (ynId == g.getEdgeNode1(yzeId)) {
|
||||||
yzeCosts += delta;
|
yzeCosts += delta;
|
||||||
} else {
|
} else {
|
||||||
yzeCosts += delta.transpose();
|
yzeCosts += delta.transpose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nullCostEdge = tryNormaliseEdgeMatrix(yzeItr);
|
bool nullCostEdge = tryNormaliseEdgeMatrix(yzeId);
|
||||||
|
|
||||||
if (!addedEdge) {
|
if (!addedEdge) {
|
||||||
// If we modified the edge costs let the heuristic know.
|
// If we modified the edge costs let the heuristic know.
|
||||||
h.postUpdateEdgeCosts(yzeItr);
|
h.postUpdateEdgeCosts(yzeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nullCostEdge) {
|
if (nullCostEdge) {
|
||||||
|
@ -361,26 +361,26 @@ namespace PBQP {
|
||||||
if (!addedEdge) {
|
if (!addedEdge) {
|
||||||
// We didn't just add it, so we need to notify the heuristic
|
// We didn't just add it, so we need to notify the heuristic
|
||||||
// and remove it from the solver.
|
// and remove it from the solver.
|
||||||
h.handleRemoveEdge(yzeItr, ynItr);
|
h.handleRemoveEdge(yzeId, ynId);
|
||||||
h.handleRemoveEdge(yzeItr, znItr);
|
h.handleRemoveEdge(yzeId, znId);
|
||||||
removeSolverEdge(yzeItr);
|
removeSolverEdge(yzeId);
|
||||||
}
|
}
|
||||||
g.removeEdge(yzeItr);
|
g.removeEdge(yzeId);
|
||||||
} else if (addedEdge) {
|
} else if (addedEdge) {
|
||||||
// If the edge was added, and non-null, finish setting it up, add it to
|
// If the edge was added, and non-null, finish setting it up, add it to
|
||||||
// the solver & notify heuristic.
|
// the solver & notify heuristic.
|
||||||
edgeDataList.push_back(EdgeData());
|
edgeDataList.push_back(EdgeData());
|
||||||
g.setEdgeData(yzeItr, &edgeDataList.back());
|
g.setEdgeData(yzeId, &edgeDataList.back());
|
||||||
addSolverEdge(yzeItr);
|
addSolverEdge(yzeId);
|
||||||
h.handleAddEdge(yzeItr);
|
h.handleAddEdge(yzeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
h.handleRemoveEdge(yxeItr, ynItr);
|
h.handleRemoveEdge(yxeId, ynId);
|
||||||
removeSolverEdge(yxeItr);
|
removeSolverEdge(yxeId);
|
||||||
h.handleRemoveEdge(zxeItr, znItr);
|
h.handleRemoveEdge(zxeId, znId);
|
||||||
removeSolverEdge(zxeItr);
|
removeSolverEdge(zxeId);
|
||||||
|
|
||||||
pushToStack(xnItr);
|
pushToStack(xnId);
|
||||||
s.recordR2();
|
s.recordR2();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,21 +391,21 @@ namespace PBQP {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NodeData& getSolverNodeData(Graph::NodeItr nItr) {
|
NodeData& getSolverNodeData(Graph::NodeId nId) {
|
||||||
return *static_cast<NodeData*>(g.getNodeData(nItr));
|
return *static_cast<NodeData*>(g.getNodeData(nId));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeData& getSolverEdgeData(Graph::EdgeItr eItr) {
|
EdgeData& getSolverEdgeData(Graph::EdgeId eId) {
|
||||||
return *static_cast<EdgeData*>(g.getEdgeData(eItr));
|
return *static_cast<EdgeData*>(g.getEdgeData(eId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addSolverEdge(Graph::EdgeItr eItr) {
|
void addSolverEdge(Graph::EdgeId eId) {
|
||||||
EdgeData &eData = getSolverEdgeData(eItr);
|
EdgeData &eData = getSolverEdgeData(eId);
|
||||||
NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eItr)),
|
NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)),
|
||||||
&n2Data = getSolverNodeData(g.getEdgeNode2(eItr));
|
&n2Data = getSolverNodeData(g.getEdgeNode2(eId));
|
||||||
|
|
||||||
eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eItr));
|
eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eId));
|
||||||
eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eItr));
|
eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
@ -417,15 +417,15 @@ namespace PBQP {
|
||||||
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
||||||
nItr != nEnd; ++nItr) {
|
nItr != nEnd; ++nItr) {
|
||||||
nodeDataList.push_back(NodeData());
|
nodeDataList.push_back(NodeData());
|
||||||
g.setNodeData(nItr, &nodeDataList.back());
|
g.setNodeData(*nItr, &nodeDataList.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create edge data objects.
|
// Create edge data objects.
|
||||||
for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
|
for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
|
||||||
eItr != eEnd; ++eItr) {
|
eItr != eEnd; ++eItr) {
|
||||||
edgeDataList.push_back(EdgeData());
|
edgeDataList.push_back(EdgeData());
|
||||||
g.setEdgeData(eItr, &edgeDataList.back());
|
g.setEdgeData(*eItr, &edgeDataList.back());
|
||||||
addSolverEdge(eItr);
|
addSolverEdge(*eItr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,28 +441,30 @@ namespace PBQP {
|
||||||
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd();
|
||||||
nItr != nEnd; ++nItr) {
|
nItr != nEnd; ++nItr) {
|
||||||
|
|
||||||
if (g.getNodeCosts(nItr).getLength() == 1) {
|
Graph::NodeId nId = *nItr;
|
||||||
|
|
||||||
std::vector<Graph::EdgeItr> edgesToRemove;
|
if (g.getNodeCosts(nId).getLength() == 1) {
|
||||||
|
|
||||||
for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nItr),
|
std::vector<Graph::EdgeId> edgesToRemove;
|
||||||
aeEnd = g.adjEdgesEnd(nItr);
|
|
||||||
|
for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId),
|
||||||
|
aeEnd = g.adjEdgesEnd(nId);
|
||||||
aeItr != aeEnd; ++aeItr) {
|
aeItr != aeEnd; ++aeItr) {
|
||||||
|
|
||||||
Graph::EdgeItr eItr = *aeItr;
|
Graph::EdgeId eId = *aeItr;
|
||||||
|
|
||||||
if (g.getEdgeNode1(eItr) == nItr) {
|
if (g.getEdgeNode1(eId) == nId) {
|
||||||
Graph::NodeItr otherNodeItr = g.getEdgeNode2(eItr);
|
Graph::NodeId otherNodeId = g.getEdgeNode2(eId);
|
||||||
g.getNodeCosts(otherNodeItr) +=
|
g.getNodeCosts(otherNodeId) +=
|
||||||
g.getEdgeCosts(eItr).getRowAsVector(0);
|
g.getEdgeCosts(eId).getRowAsVector(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Graph::NodeItr otherNodeItr = g.getEdgeNode1(eItr);
|
Graph::NodeId otherNodeId = g.getEdgeNode1(eId);
|
||||||
g.getNodeCosts(otherNodeItr) +=
|
g.getNodeCosts(otherNodeId) +=
|
||||||
g.getEdgeCosts(eItr).getColAsVector(0);
|
g.getEdgeCosts(eId).getColAsVector(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
edgesToRemove.push_back(eItr);
|
edgesToRemove.push_back(eId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!edgesToRemove.empty())
|
if (!edgesToRemove.empty())
|
||||||
|
@ -477,12 +479,12 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
|
|
||||||
void eliminateIndependentEdges() {
|
void eliminateIndependentEdges() {
|
||||||
std::vector<Graph::EdgeItr> edgesToProcess;
|
std::vector<Graph::EdgeId> edgesToProcess;
|
||||||
unsigned numEliminated = 0;
|
unsigned numEliminated = 0;
|
||||||
|
|
||||||
for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
|
for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd();
|
||||||
eItr != eEnd; ++eItr) {
|
eItr != eEnd; ++eItr) {
|
||||||
edgesToProcess.push_back(eItr);
|
edgesToProcess.push_back(*eItr);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!edgesToProcess.empty()) {
|
while (!edgesToProcess.empty()) {
|
||||||
|
@ -492,21 +494,21 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryToEliminateEdge(Graph::EdgeItr eItr) {
|
bool tryToEliminateEdge(Graph::EdgeId eId) {
|
||||||
if (tryNormaliseEdgeMatrix(eItr)) {
|
if (tryNormaliseEdgeMatrix(eId)) {
|
||||||
g.removeEdge(eItr);
|
g.removeEdge(eId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) {
|
bool tryNormaliseEdgeMatrix(Graph::EdgeId &eId) {
|
||||||
|
|
||||||
const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity();
|
const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity();
|
||||||
|
|
||||||
Matrix &edgeCosts = g.getEdgeCosts(eItr);
|
Matrix &edgeCosts = g.getEdgeCosts(eId);
|
||||||
Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)),
|
Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eId)),
|
||||||
&vCosts = g.getNodeCosts(g.getEdgeNode2(eItr));
|
&vCosts = g.getNodeCosts(g.getEdgeNode2(eId));
|
||||||
|
|
||||||
for (unsigned r = 0; r < edgeCosts.getRows(); ++r) {
|
for (unsigned r = 0; r < edgeCosts.getRows(); ++r) {
|
||||||
PBQPNum rowMin = infinity;
|
PBQPNum rowMin = infinity;
|
||||||
|
@ -554,34 +556,34 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void computeSolution(Graph::NodeItr nItr) {
|
void computeSolution(Graph::NodeId nId) {
|
||||||
|
|
||||||
NodeData &nodeData = getSolverNodeData(nItr);
|
NodeData &nodeData = getSolverNodeData(nId);
|
||||||
|
|
||||||
Vector v(g.getNodeCosts(nItr));
|
Vector v(g.getNodeCosts(nId));
|
||||||
|
|
||||||
// Solve based on existing solved edges.
|
// Solve based on existing solved edges.
|
||||||
for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(),
|
for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(),
|
||||||
solvedEdgeEnd = nodeData.solverEdgesEnd();
|
solvedEdgeEnd = nodeData.solverEdgesEnd();
|
||||||
solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) {
|
solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) {
|
||||||
|
|
||||||
Graph::EdgeItr eItr(*solvedEdgeItr);
|
Graph::EdgeId eId(*solvedEdgeItr);
|
||||||
Matrix &edgeCosts = g.getEdgeCosts(eItr);
|
Matrix &edgeCosts = g.getEdgeCosts(eId);
|
||||||
|
|
||||||
if (nItr == g.getEdgeNode1(eItr)) {
|
if (nId == g.getEdgeNode1(eId)) {
|
||||||
Graph::NodeItr adjNode(g.getEdgeNode2(eItr));
|
Graph::NodeId adjNode(g.getEdgeNode2(eId));
|
||||||
unsigned adjSolution = s.getSelection(adjNode);
|
unsigned adjSolution = s.getSelection(adjNode);
|
||||||
v += edgeCosts.getColAsVector(adjSolution);
|
v += edgeCosts.getColAsVector(adjSolution);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Graph::NodeItr adjNode(g.getEdgeNode1(eItr));
|
Graph::NodeId adjNode(g.getEdgeNode1(eId));
|
||||||
unsigned adjSolution = s.getSelection(adjNode);
|
unsigned adjSolution = s.getSelection(adjNode);
|
||||||
v += edgeCosts.getRowAsVector(adjSolution);
|
v += edgeCosts.getRowAsVector(adjSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setSolution(nItr, v.minIndex());
|
setSolution(nId, v.minIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
|
|
|
@ -47,8 +47,8 @@ namespace PBQP {
|
||||||
class LinkDegreeComparator {
|
class LinkDegreeComparator {
|
||||||
public:
|
public:
|
||||||
LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {}
|
LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {}
|
||||||
bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const {
|
bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const {
|
||||||
if (s->getSolverDegree(n1Itr) > s->getSolverDegree(n2Itr))
|
if (s->getSolverDegree(n1Id) > s->getSolverDegree(n2Id))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -60,12 +60,12 @@ namespace PBQP {
|
||||||
public:
|
public:
|
||||||
SpillCostComparator(HeuristicSolverImpl<Briggs> &s)
|
SpillCostComparator(HeuristicSolverImpl<Briggs> &s)
|
||||||
: s(&s), g(&s.getGraph()) {}
|
: s(&s), g(&s.getGraph()) {}
|
||||||
bool operator()(Graph::NodeItr n1Itr, Graph::NodeItr n2Itr) const {
|
bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const {
|
||||||
const PBQP::Vector &cv1 = g->getNodeCosts(n1Itr);
|
const PBQP::Vector &cv1 = g->getNodeCosts(n1Id);
|
||||||
const PBQP::Vector &cv2 = g->getNodeCosts(n2Itr);
|
const PBQP::Vector &cv2 = g->getNodeCosts(n2Id);
|
||||||
|
|
||||||
PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Itr);
|
PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Id);
|
||||||
PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Itr);
|
PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Id);
|
||||||
|
|
||||||
if (cost1 < cost2)
|
if (cost1 < cost2)
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,10 +77,10 @@ namespace PBQP {
|
||||||
Graph *g;
|
Graph *g;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<Graph::NodeItr> RNAllocableList;
|
typedef std::list<Graph::NodeId> RNAllocableList;
|
||||||
typedef RNAllocableList::iterator RNAllocableListItr;
|
typedef RNAllocableList::iterator RNAllocableListItr;
|
||||||
|
|
||||||
typedef std::list<Graph::NodeItr> RNUnallocableList;
|
typedef std::list<Graph::NodeId> RNUnallocableList;
|
||||||
typedef RNUnallocableList::iterator RNUnallocableListItr;
|
typedef RNUnallocableList::iterator RNUnallocableListItr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -123,8 +123,8 @@ namespace PBQP {
|
||||||
/// infinite are checked for allocability first. Allocable nodes may be
|
/// infinite are checked for allocability first. Allocable nodes may be
|
||||||
/// optimally reduced, but nodes whose allocability cannot be proven are
|
/// optimally reduced, but nodes whose allocability cannot be proven are
|
||||||
/// selected for heuristic reduction instead.
|
/// selected for heuristic reduction instead.
|
||||||
bool shouldOptimallyReduce(Graph::NodeItr nItr) {
|
bool shouldOptimallyReduce(Graph::NodeId nId) {
|
||||||
if (getSolver().getSolverDegree(nItr) < 3) {
|
if (getSolver().getSolverDegree(nId) < 3) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
|
@ -133,14 +133,14 @@ namespace PBQP {
|
||||||
|
|
||||||
/// \brief Add a node to the heuristic reduce list.
|
/// \brief Add a node to the heuristic reduce list.
|
||||||
/// @param nItr Node iterator to add to the heuristic reduce list.
|
/// @param nItr Node iterator to add to the heuristic reduce list.
|
||||||
void addToHeuristicReduceList(Graph::NodeItr nItr) {
|
void addToHeuristicReduceList(Graph::NodeId nId) {
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd = getHeuristicNodeData(nId);
|
||||||
initializeNode(nItr);
|
initializeNode(nId);
|
||||||
nd.isHeuristic = true;
|
nd.isHeuristic = true;
|
||||||
if (nd.isAllocable) {
|
if (nd.isAllocable) {
|
||||||
nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr);
|
nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId);
|
||||||
} else {
|
} else {
|
||||||
nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nItr);
|
nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,19 +159,19 @@ namespace PBQP {
|
||||||
RNAllocableListItr rnaItr =
|
RNAllocableListItr rnaItr =
|
||||||
min_element(rnAllocableList.begin(), rnAllocableList.end(),
|
min_element(rnAllocableList.begin(), rnAllocableList.end(),
|
||||||
LinkDegreeComparator(getSolver()));
|
LinkDegreeComparator(getSolver()));
|
||||||
Graph::NodeItr nItr = *rnaItr;
|
Graph::NodeId nId = *rnaItr;
|
||||||
rnAllocableList.erase(rnaItr);
|
rnAllocableList.erase(rnaItr);
|
||||||
handleRemoveNode(nItr);
|
handleRemoveNode(nId);
|
||||||
getSolver().pushToStack(nItr);
|
getSolver().pushToStack(nId);
|
||||||
return true;
|
return true;
|
||||||
} else if (!rnUnallocableList.empty()) {
|
} else if (!rnUnallocableList.empty()) {
|
||||||
RNUnallocableListItr rnuItr =
|
RNUnallocableListItr rnuItr =
|
||||||
min_element(rnUnallocableList.begin(), rnUnallocableList.end(),
|
min_element(rnUnallocableList.begin(), rnUnallocableList.end(),
|
||||||
SpillCostComparator(getSolver()));
|
SpillCostComparator(getSolver()));
|
||||||
Graph::NodeItr nItr = *rnuItr;
|
Graph::NodeId nId = *rnuItr;
|
||||||
rnUnallocableList.erase(rnuItr);
|
rnUnallocableList.erase(rnuItr);
|
||||||
handleRemoveNode(nItr);
|
handleRemoveNode(nId);
|
||||||
getSolver().pushToStack(nItr);
|
getSolver().pushToStack(nId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
|
@ -180,28 +180,28 @@ namespace PBQP {
|
||||||
|
|
||||||
/// \brief Prepare a change in the costs on the given edge.
|
/// \brief Prepare a change in the costs on the given edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
void preUpdateEdgeCosts(Graph::EdgeItr eItr) {
|
void preUpdateEdgeCosts(Graph::EdgeId eId) {
|
||||||
Graph &g = getGraph();
|
Graph &g = getGraph();
|
||||||
Graph::NodeItr n1Itr = g.getEdgeNode1(eItr),
|
Graph::NodeId n1Id = g.getEdgeNode1(eId),
|
||||||
n2Itr = g.getEdgeNode2(eItr);
|
n2Id = g.getEdgeNode2(eId);
|
||||||
NodeData &n1 = getHeuristicNodeData(n1Itr),
|
NodeData &n1 = getHeuristicNodeData(n1Id),
|
||||||
&n2 = getHeuristicNodeData(n2Itr);
|
&n2 = getHeuristicNodeData(n2Id);
|
||||||
|
|
||||||
if (n1.isHeuristic)
|
if (n1.isHeuristic)
|
||||||
subtractEdgeContributions(eItr, getGraph().getEdgeNode1(eItr));
|
subtractEdgeContributions(eId, getGraph().getEdgeNode1(eId));
|
||||||
if (n2.isHeuristic)
|
if (n2.isHeuristic)
|
||||||
subtractEdgeContributions(eItr, getGraph().getEdgeNode2(eItr));
|
subtractEdgeContributions(eId, getGraph().getEdgeNode2(eId));
|
||||||
|
|
||||||
EdgeData &ed = getHeuristicEdgeData(eItr);
|
EdgeData &ed = getHeuristicEdgeData(eId);
|
||||||
ed.isUpToDate = false;
|
ed.isUpToDate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Handle the change in the costs on the given edge.
|
/// \brief Handle the change in the costs on the given edge.
|
||||||
/// @param eItr Edge iterator.
|
/// @param eItr Edge iterator.
|
||||||
void postUpdateEdgeCosts(Graph::EdgeItr eItr) {
|
void postUpdateEdgeCosts(Graph::EdgeId eId) {
|
||||||
// This is effectively the same as adding a new edge now, since
|
// This is effectively the same as adding a new edge now, since
|
||||||
// we've factored out the costs of the old one.
|
// we've factored out the costs of the old one.
|
||||||
handleAddEdge(eItr);
|
handleAddEdge(eId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Handle the addition of a new edge into the PBQP graph.
|
/// \brief Handle the addition of a new edge into the PBQP graph.
|
||||||
|
@ -210,12 +210,12 @@ namespace PBQP {
|
||||||
/// Updates allocability of any nodes connected by this edge which are
|
/// Updates allocability of any nodes connected by this edge which are
|
||||||
/// being managed by the heuristic. If allocability changes they are
|
/// being managed by the heuristic. If allocability changes they are
|
||||||
/// moved to the appropriate list.
|
/// moved to the appropriate list.
|
||||||
void handleAddEdge(Graph::EdgeItr eItr) {
|
void handleAddEdge(Graph::EdgeId eId) {
|
||||||
Graph &g = getGraph();
|
Graph &g = getGraph();
|
||||||
Graph::NodeItr n1Itr = g.getEdgeNode1(eItr),
|
Graph::NodeId n1Id = g.getEdgeNode1(eId),
|
||||||
n2Itr = g.getEdgeNode2(eItr);
|
n2Id = g.getEdgeNode2(eId);
|
||||||
NodeData &n1 = getHeuristicNodeData(n1Itr),
|
NodeData &n1 = getHeuristicNodeData(n1Id),
|
||||||
&n2 = getHeuristicNodeData(n2Itr);
|
&n2 = getHeuristicNodeData(n2Id);
|
||||||
|
|
||||||
// If neither node is managed by the heuristic there's nothing to be
|
// If neither node is managed by the heuristic there's nothing to be
|
||||||
// done.
|
// done.
|
||||||
|
@ -223,29 +223,29 @@ namespace PBQP {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ok - we need to update at least one node.
|
// Ok - we need to update at least one node.
|
||||||
computeEdgeContributions(eItr);
|
computeEdgeContributions(eId);
|
||||||
|
|
||||||
// Update node 1 if it's managed by the heuristic.
|
// Update node 1 if it's managed by the heuristic.
|
||||||
if (n1.isHeuristic) {
|
if (n1.isHeuristic) {
|
||||||
bool n1WasAllocable = n1.isAllocable;
|
bool n1WasAllocable = n1.isAllocable;
|
||||||
addEdgeContributions(eItr, n1Itr);
|
addEdgeContributions(eId, n1Id);
|
||||||
updateAllocability(n1Itr);
|
updateAllocability(n1Id);
|
||||||
if (n1WasAllocable && !n1.isAllocable) {
|
if (n1WasAllocable && !n1.isAllocable) {
|
||||||
rnAllocableList.erase(n1.rnaItr);
|
rnAllocableList.erase(n1.rnaItr);
|
||||||
n1.rnuItr =
|
n1.rnuItr =
|
||||||
rnUnallocableList.insert(rnUnallocableList.end(), n1Itr);
|
rnUnallocableList.insert(rnUnallocableList.end(), n1Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Likewise for node 2.
|
// Likewise for node 2.
|
||||||
if (n2.isHeuristic) {
|
if (n2.isHeuristic) {
|
||||||
bool n2WasAllocable = n2.isAllocable;
|
bool n2WasAllocable = n2.isAllocable;
|
||||||
addEdgeContributions(eItr, n2Itr);
|
addEdgeContributions(eId, n2Id);
|
||||||
updateAllocability(n2Itr);
|
updateAllocability(n2Id);
|
||||||
if (n2WasAllocable && !n2.isAllocable) {
|
if (n2WasAllocable && !n2.isAllocable) {
|
||||||
rnAllocableList.erase(n2.rnaItr);
|
rnAllocableList.erase(n2.rnaItr);
|
||||||
n2.rnuItr =
|
n2.rnuItr =
|
||||||
rnUnallocableList.insert(rnUnallocableList.end(), n2Itr);
|
rnUnallocableList.insert(rnUnallocableList.end(), n2Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,27 +256,27 @@ namespace PBQP {
|
||||||
///
|
///
|
||||||
/// Updates allocability of the given node and, if appropriate, moves the
|
/// Updates allocability of the given node and, if appropriate, moves the
|
||||||
/// node to a new list.
|
/// node to a new list.
|
||||||
void handleRemoveEdge(Graph::EdgeItr eItr, Graph::NodeItr nItr) {
|
void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) {
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd =getHeuristicNodeData(nId);
|
||||||
|
|
||||||
// If the node is not managed by the heuristic there's nothing to be
|
// If the node is not managed by the heuristic there's nothing to be
|
||||||
// done.
|
// done.
|
||||||
if (!nd.isHeuristic)
|
if (!nd.isHeuristic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EdgeData &ed = getHeuristicEdgeData(eItr);
|
EdgeData &ed = getHeuristicEdgeData(eId);
|
||||||
(void)ed;
|
(void)ed;
|
||||||
assert(ed.isUpToDate && "Edge data is not up to date.");
|
assert(ed.isUpToDate && "Edge data is not up to date.");
|
||||||
|
|
||||||
// Update node.
|
// Update node.
|
||||||
bool ndWasAllocable = nd.isAllocable;
|
bool ndWasAllocable = nd.isAllocable;
|
||||||
subtractEdgeContributions(eItr, nItr);
|
subtractEdgeContributions(eId, nId);
|
||||||
updateAllocability(nItr);
|
updateAllocability(nId);
|
||||||
|
|
||||||
// If the node has gone optimal...
|
// If the node has gone optimal...
|
||||||
if (shouldOptimallyReduce(nItr)) {
|
if (shouldOptimallyReduce(nId)) {
|
||||||
nd.isHeuristic = false;
|
nd.isHeuristic = false;
|
||||||
addToOptimalReduceList(nItr);
|
addToOptimalReduceList(nId);
|
||||||
if (ndWasAllocable) {
|
if (ndWasAllocable) {
|
||||||
rnAllocableList.erase(nd.rnaItr);
|
rnAllocableList.erase(nd.rnaItr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,30 +287,30 @@ namespace PBQP {
|
||||||
// from "unallocable" to "allocable".
|
// from "unallocable" to "allocable".
|
||||||
if (!ndWasAllocable && nd.isAllocable) {
|
if (!ndWasAllocable && nd.isAllocable) {
|
||||||
rnUnallocableList.erase(nd.rnuItr);
|
rnUnallocableList.erase(nd.rnuItr);
|
||||||
nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nItr);
|
nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NodeData& getHeuristicNodeData(Graph::NodeItr nItr) {
|
NodeData& getHeuristicNodeData(Graph::NodeId nId) {
|
||||||
return getSolver().getHeuristicNodeData(nItr);
|
return getSolver().getHeuristicNodeData(nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeData& getHeuristicEdgeData(Graph::EdgeItr eItr) {
|
EdgeData& getHeuristicEdgeData(Graph::EdgeId eId) {
|
||||||
return getSolver().getHeuristicEdgeData(eItr);
|
return getSolver().getHeuristicEdgeData(eId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Work out what this edge will contribute to the allocability of the
|
// Work out what this edge will contribute to the allocability of the
|
||||||
// nodes connected to it.
|
// nodes connected to it.
|
||||||
void computeEdgeContributions(Graph::EdgeItr eItr) {
|
void computeEdgeContributions(Graph::EdgeId eId) {
|
||||||
EdgeData &ed = getHeuristicEdgeData(eItr);
|
EdgeData &ed = getHeuristicEdgeData(eId);
|
||||||
|
|
||||||
if (ed.isUpToDate)
|
if (ed.isUpToDate)
|
||||||
return; // Edge data is already up to date.
|
return; // Edge data is already up to date.
|
||||||
|
|
||||||
Matrix &eCosts = getGraph().getEdgeCosts(eItr);
|
Matrix &eCosts = getGraph().getEdgeCosts(eId);
|
||||||
|
|
||||||
unsigned numRegs = eCosts.getRows() - 1,
|
unsigned numRegs = eCosts.getRows() - 1,
|
||||||
numReverseRegs = eCosts.getCols() - 1;
|
numReverseRegs = eCosts.getCols() - 1;
|
||||||
|
@ -352,15 +352,15 @@ namespace PBQP {
|
||||||
// numDenied and safe members. No action is taken other than to update
|
// numDenied and safe members. No action is taken other than to update
|
||||||
// these member values. Once updated these numbers can be used by clients
|
// these member values. Once updated these numbers can be used by clients
|
||||||
// to update the node's allocability.
|
// to update the node's allocability.
|
||||||
void addEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) {
|
void addEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) {
|
||||||
EdgeData &ed = getHeuristicEdgeData(eItr);
|
EdgeData &ed = getHeuristicEdgeData(eId);
|
||||||
|
|
||||||
assert(ed.isUpToDate && "Using out-of-date edge numbers.");
|
assert(ed.isUpToDate && "Using out-of-date edge numbers.");
|
||||||
|
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd = getHeuristicNodeData(nId);
|
||||||
unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1;
|
unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1;
|
||||||
|
|
||||||
bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr);
|
bool nIsNode1 = nId == getGraph().getEdgeNode1(eId);
|
||||||
EdgeData::UnsafeArray &unsafe =
|
EdgeData::UnsafeArray &unsafe =
|
||||||
nIsNode1 ? ed.unsafe : ed.reverseUnsafe;
|
nIsNode1 ? ed.unsafe : ed.reverseUnsafe;
|
||||||
nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst;
|
nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst;
|
||||||
|
@ -379,15 +379,15 @@ namespace PBQP {
|
||||||
// numDenied and safe members. No action is taken other than to update
|
// numDenied and safe members. No action is taken other than to update
|
||||||
// these member values. Once updated these numbers can be used by clients
|
// these member values. Once updated these numbers can be used by clients
|
||||||
// to update the node's allocability.
|
// to update the node's allocability.
|
||||||
void subtractEdgeContributions(Graph::EdgeItr eItr, Graph::NodeItr nItr) {
|
void subtractEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) {
|
||||||
EdgeData &ed = getHeuristicEdgeData(eItr);
|
EdgeData &ed = getHeuristicEdgeData(eId);
|
||||||
|
|
||||||
assert(ed.isUpToDate && "Using out-of-date edge numbers.");
|
assert(ed.isUpToDate && "Using out-of-date edge numbers.");
|
||||||
|
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd = getHeuristicNodeData(nId);
|
||||||
unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1;
|
unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1;
|
||||||
|
|
||||||
bool nIsNode1 = nItr == getGraph().getEdgeNode1(eItr);
|
bool nIsNode1 = nId == getGraph().getEdgeNode1(eId);
|
||||||
EdgeData::UnsafeArray &unsafe =
|
EdgeData::UnsafeArray &unsafe =
|
||||||
nIsNode1 ? ed.unsafe : ed.reverseUnsafe;
|
nIsNode1 ? ed.unsafe : ed.reverseUnsafe;
|
||||||
nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst;
|
nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst;
|
||||||
|
@ -402,22 +402,22 @@ namespace PBQP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateAllocability(Graph::NodeItr nItr) {
|
void updateAllocability(Graph::NodeId nId) {
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd = getHeuristicNodeData(nId);
|
||||||
unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1;
|
unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1;
|
||||||
nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0;
|
nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeNode(Graph::NodeItr nItr) {
|
void initializeNode(Graph::NodeId nId) {
|
||||||
NodeData &nd = getHeuristicNodeData(nItr);
|
NodeData &nd = getHeuristicNodeData(nId);
|
||||||
|
|
||||||
if (nd.isInitialized)
|
if (nd.isInitialized)
|
||||||
return; // Node data is already up to date.
|
return; // Node data is already up to date.
|
||||||
|
|
||||||
unsigned numRegs = getGraph().getNodeCosts(nItr).getLength() - 1;
|
unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1;
|
||||||
|
|
||||||
nd.numDenied = 0;
|
nd.numDenied = 0;
|
||||||
const Vector& nCosts = getGraph().getNodeCosts(nItr);
|
const Vector& nCosts = getGraph().getNodeCosts(nId);
|
||||||
for (unsigned i = 1; i < nCosts.getLength(); ++i) {
|
for (unsigned i = 1; i < nCosts.getLength(); ++i) {
|
||||||
if (nCosts[i] == std::numeric_limits<PBQPNum>::infinity())
|
if (nCosts[i] == std::numeric_limits<PBQPNum>::infinity())
|
||||||
++nd.numDenied;
|
++nd.numDenied;
|
||||||
|
@ -428,27 +428,27 @@ namespace PBQP {
|
||||||
|
|
||||||
typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr;
|
typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr;
|
||||||
|
|
||||||
for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nItr),
|
for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nId),
|
||||||
aeEnd = getSolver().solverEdgesEnd(nItr);
|
aeEnd = getSolver().solverEdgesEnd(nId);
|
||||||
aeItr != aeEnd; ++aeItr) {
|
aeItr != aeEnd; ++aeItr) {
|
||||||
|
|
||||||
Graph::EdgeItr eItr = *aeItr;
|
Graph::EdgeId eId = *aeItr;
|
||||||
computeEdgeContributions(eItr);
|
computeEdgeContributions(eId);
|
||||||
addEdgeContributions(eItr, nItr);
|
addEdgeContributions(eId, nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAllocability(nItr);
|
updateAllocability(nId);
|
||||||
nd.isInitialized = true;
|
nd.isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleRemoveNode(Graph::NodeItr xnItr) {
|
void handleRemoveNode(Graph::NodeId xnId) {
|
||||||
typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr;
|
typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr;
|
||||||
std::vector<Graph::EdgeItr> edgesToRemove;
|
std::vector<Graph::EdgeId> edgesToRemove;
|
||||||
for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnItr),
|
for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnId),
|
||||||
aeEnd = getSolver().solverEdgesEnd(xnItr);
|
aeEnd = getSolver().solverEdgesEnd(xnId);
|
||||||
aeItr != aeEnd; ++aeItr) {
|
aeItr != aeEnd; ++aeItr) {
|
||||||
Graph::NodeItr ynItr = getGraph().getEdgeOtherNode(*aeItr, xnItr);
|
Graph::NodeId ynId = getGraph().getEdgeOtherNode(*aeItr, xnId);
|
||||||
handleRemoveEdge(*aeItr, ynItr);
|
handleRemoveEdge(*aeItr, ynId);
|
||||||
edgesToRemove.push_back(*aeItr);
|
edgesToRemove.push_back(*aeItr);
|
||||||
}
|
}
|
||||||
while (!edgesToRemove.empty()) {
|
while (!edgesToRemove.empty()) {
|
||||||
|
|
|
@ -26,8 +26,7 @@ namespace PBQP {
|
||||||
class Solution {
|
class Solution {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef std::map<Graph::ConstNodeItr, unsigned,
|
typedef std::map<Graph::NodeId, unsigned> SelectionsMap;
|
||||||
NodeItrComparator> SelectionsMap;
|
|
||||||
SelectionsMap selections;
|
SelectionsMap selections;
|
||||||
|
|
||||||
unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions;
|
unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions;
|
||||||
|
@ -73,15 +72,15 @@ namespace PBQP {
|
||||||
/// \brief Set the selection for a given node.
|
/// \brief Set the selection for a given node.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @param selection Selection for nItr.
|
/// @param selection Selection for nItr.
|
||||||
void setSelection(Graph::NodeItr nItr, unsigned selection) {
|
void setSelection(Graph::NodeId nodeId, unsigned selection) {
|
||||||
selections[nItr] = selection;
|
selections[nodeId] = selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Get a node's selection.
|
/// \brief Get a node's selection.
|
||||||
/// @param nItr Node iterator.
|
/// @param nItr Node iterator.
|
||||||
/// @return The selection for nItr;
|
/// @return The selection for nItr;
|
||||||
unsigned getSelection(Graph::ConstNodeItr nItr) const {
|
unsigned getSelection(Graph::NodeId nodeId) const {
|
||||||
SelectionsMap::const_iterator sItr = selections.find(nItr);
|
SelectionsMap::const_iterator sItr = selections.find(nodeId);
|
||||||
assert(sItr != selections.end() && "No selection for node.");
|
assert(sItr != selections.end() && "No selection for node.");
|
||||||
return sItr->second;
|
return sItr->second;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,22 +52,22 @@ namespace llvm {
|
||||||
/// PBQPBuilder you are unlikely to need this: Nodes and options for all
|
/// PBQPBuilder you are unlikely to need this: Nodes and options for all
|
||||||
/// vregs will already have been set up for you by the base class.
|
/// vregs will already have been set up for you by the base class.
|
||||||
template <typename AllowedRegsItr>
|
template <typename AllowedRegsItr>
|
||||||
void recordVReg(unsigned vreg, PBQP::Graph::NodeItr node,
|
void recordVReg(unsigned vreg, PBQP::Graph::NodeId nodeId,
|
||||||
AllowedRegsItr arBegin, AllowedRegsItr arEnd) {
|
AllowedRegsItr arBegin, AllowedRegsItr arEnd) {
|
||||||
assert(node2VReg.find(node) == node2VReg.end() && "Re-mapping node.");
|
assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node.");
|
||||||
assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg.");
|
assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg.");
|
||||||
assert(allowedSets[vreg].empty() && "vreg already has pregs.");
|
assert(allowedSets[vreg].empty() && "vreg already has pregs.");
|
||||||
|
|
||||||
node2VReg[node] = vreg;
|
node2VReg[nodeId] = vreg;
|
||||||
vreg2Node[vreg] = node;
|
vreg2Node[vreg] = nodeId;
|
||||||
std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg]));
|
std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the virtual register corresponding to the given PBQP node.
|
/// Get the virtual register corresponding to the given PBQP node.
|
||||||
unsigned getVRegForNode(PBQP::Graph::ConstNodeItr node) const;
|
unsigned getVRegForNode(PBQP::Graph::NodeId nodeId) const;
|
||||||
|
|
||||||
/// Get the PBQP node corresponding to the given virtual register.
|
/// Get the PBQP node corresponding to the given virtual register.
|
||||||
PBQP::Graph::NodeItr getNodeForVReg(unsigned vreg) const;
|
PBQP::Graph::NodeId getNodeForVReg(unsigned vreg) const;
|
||||||
|
|
||||||
/// Returns true if the given PBQP option represents a physical register,
|
/// Returns true if the given PBQP option represents a physical register,
|
||||||
/// false otherwise.
|
/// false otherwise.
|
||||||
|
@ -92,9 +92,8 @@ namespace llvm {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef std::map<PBQP::Graph::ConstNodeItr, unsigned,
|
typedef std::map<PBQP::Graph::NodeId, unsigned> Node2VReg;
|
||||||
PBQP::NodeItrComparator> Node2VReg;
|
typedef DenseMap<unsigned, PBQP::Graph::NodeId> VReg2Node;
|
||||||
typedef DenseMap<unsigned, PBQP::Graph::NodeItr> VReg2Node;
|
|
||||||
typedef DenseMap<unsigned, AllowedSet> AllowedSetMap;
|
typedef DenseMap<unsigned, AllowedSet> AllowedSetMap;
|
||||||
|
|
||||||
PBQP::Graph graph;
|
PBQP::Graph graph;
|
||||||
|
|
|
@ -158,13 +158,13 @@ char RegAllocPBQP::ID = 0;
|
||||||
|
|
||||||
} // End anonymous namespace.
|
} // End anonymous namespace.
|
||||||
|
|
||||||
unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::ConstNodeItr node) const {
|
unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::NodeId node) const {
|
||||||
Node2VReg::const_iterator vregItr = node2VReg.find(node);
|
Node2VReg::const_iterator vregItr = node2VReg.find(node);
|
||||||
assert(vregItr != node2VReg.end() && "No vreg for node.");
|
assert(vregItr != node2VReg.end() && "No vreg for node.");
|
||||||
return vregItr->second;
|
return vregItr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
PBQP::Graph::NodeItr PBQPRAProblem::getNodeForVReg(unsigned vreg) const {
|
PBQP::Graph::NodeId PBQPRAProblem::getNodeForVReg(unsigned vreg) const {
|
||||||
VReg2Node::const_iterator nodeItr = vreg2Node.find(vreg);
|
VReg2Node::const_iterator nodeItr = vreg2Node.find(vreg);
|
||||||
assert(nodeItr != vreg2Node.end() && "No node for vreg.");
|
assert(nodeItr != vreg2Node.end() && "No node for vreg.");
|
||||||
return nodeItr->second;
|
return nodeItr->second;
|
||||||
|
@ -247,7 +247,7 @@ PBQPRAProblem *PBQPBuilder::build(MachineFunction *mf, const LiveIntervals *lis,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct the node.
|
// Construct the node.
|
||||||
PBQP::Graph::NodeItr node =
|
PBQP::Graph::NodeId node =
|
||||||
g.addNode(PBQP::Vector(vrAllowed.size() + 1, 0));
|
g.addNode(PBQP::Vector(vrAllowed.size() + 1, 0));
|
||||||
|
|
||||||
// Record the mapping and allowed set in the problem.
|
// Record the mapping and allowed set in the problem.
|
||||||
|
@ -273,7 +273,7 @@ PBQPRAProblem *PBQPBuilder::build(MachineFunction *mf, const LiveIntervals *lis,
|
||||||
|
|
||||||
assert(!l2.empty() && "Empty interval in vreg set?");
|
assert(!l2.empty() && "Empty interval in vreg set?");
|
||||||
if (l1.overlaps(l2)) {
|
if (l1.overlaps(l2)) {
|
||||||
PBQP::Graph::EdgeItr edge =
|
PBQP::Graph::EdgeId edge =
|
||||||
g.addEdge(p->getNodeForVReg(vr1), p->getNodeForVReg(vr2),
|
g.addEdge(p->getNodeForVReg(vr1), p->getNodeForVReg(vr2),
|
||||||
PBQP::Matrix(vr1Allowed.size()+1, vr2Allowed.size()+1, 0));
|
PBQP::Matrix(vr1Allowed.size()+1, vr2Allowed.size()+1, 0));
|
||||||
|
|
||||||
|
@ -364,16 +364,16 @@ PBQPRAProblem *PBQPBuilderWithCoalescing::build(MachineFunction *mf,
|
||||||
}
|
}
|
||||||
if (pregOpt < allowed.size()) {
|
if (pregOpt < allowed.size()) {
|
||||||
++pregOpt; // +1 to account for spill option.
|
++pregOpt; // +1 to account for spill option.
|
||||||
PBQP::Graph::NodeItr node = p->getNodeForVReg(src);
|
PBQP::Graph::NodeId node = p->getNodeForVReg(src);
|
||||||
addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit);
|
addPhysRegCoalesce(g.getNodeCosts(node), pregOpt, cBenefit);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst);
|
const PBQPRAProblem::AllowedSet *allowed1 = &p->getAllowedSet(dst);
|
||||||
const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src);
|
const PBQPRAProblem::AllowedSet *allowed2 = &p->getAllowedSet(src);
|
||||||
PBQP::Graph::NodeItr node1 = p->getNodeForVReg(dst);
|
PBQP::Graph::NodeId node1 = p->getNodeForVReg(dst);
|
||||||
PBQP::Graph::NodeItr node2 = p->getNodeForVReg(src);
|
PBQP::Graph::NodeId node2 = p->getNodeForVReg(src);
|
||||||
PBQP::Graph::EdgeItr edge = g.findEdge(node1, node2);
|
PBQP::Graph::EdgeId edge = g.findEdge(node1, node2);
|
||||||
if (edge == g.edgesEnd()) {
|
if (edge == g.invalidEdgeId()) {
|
||||||
edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1,
|
edge = g.addEdge(node1, node2, PBQP::Matrix(allowed1->size() + 1,
|
||||||
allowed2->size() + 1,
|
allowed2->size() + 1,
|
||||||
0));
|
0));
|
||||||
|
@ -477,11 +477,11 @@ bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem,
|
||||||
const PBQP::Graph &g = problem.getGraph();
|
const PBQP::Graph &g = problem.getGraph();
|
||||||
// Iterate over the nodes mapping the PBQP solution to a register
|
// Iterate over the nodes mapping the PBQP solution to a register
|
||||||
// assignment.
|
// assignment.
|
||||||
for (PBQP::Graph::ConstNodeItr node = g.nodesBegin(),
|
for (PBQP::Graph::NodeItr nodeItr = g.nodesBegin(),
|
||||||
nodeEnd = g.nodesEnd();
|
nodeEnd = g.nodesEnd();
|
||||||
node != nodeEnd; ++node) {
|
nodeItr != nodeEnd; ++nodeItr) {
|
||||||
unsigned vreg = problem.getVRegForNode(node);
|
unsigned vreg = problem.getVRegForNode(*nodeItr);
|
||||||
unsigned alloc = solution.getSelection(node);
|
unsigned alloc = solution.getSelection(*nodeItr);
|
||||||
|
|
||||||
if (problem.isPRegOption(vreg, alloc)) {
|
if (problem.isPRegOption(vreg, alloc)) {
|
||||||
unsigned preg = problem.getPRegForOption(vreg, alloc);
|
unsigned preg = problem.getPRegForOption(vreg, alloc);
|
||||||
|
|
Loading…
Reference in New Issue