#ifndef YAP_PACKAGES_CLPBN_HORUS_ELIMGRAPH_H_ #define YAP_PACKAGES_CLPBN_HORUS_ELIMGRAPH_H_ #include #include #include #include "FactorGraph.h" #include "TinySet.h" #include "Horus.h" namespace Horus { class ElimGraph { public: enum class ElimHeuristic { sequentialEh, minNeighborsEh, minWeightEh, minFillEh, weightedMinFillEh }; ElimGraph (const Factors&); ~ElimGraph(); VarIds getEliminatingOrder (const VarIds&); void print() const; void exportToGraphViz (const char*, bool = true, const VarIds& = VarIds()) const; static VarIds getEliminationOrder (const Factors&, VarIds); static ElimHeuristic elimHeuristic() { return elimHeuristic_; } static void setElimHeuristic (ElimHeuristic eh) { elimHeuristic_ = eh; } private: class EGNode; typedef TinySet EGNeighs; class EGNode : public Var { public: EGNode (VarId vid, unsigned range) : Var (vid, range) { } void addNeighbor (EGNode* n) { neighs_.insert (n); } void removeNeighbor (EGNode* n) { neighs_.remove (n); } bool isNeighbor (EGNode* n) const { return neighs_.contains (n); } const EGNeighs& neighbors() const { return neighs_; } private: EGNeighs neighs_; }; void addEdge (EGNode* n1, EGNode* n2); unsigned getNeighborsCost (const EGNode* n) const; unsigned getWeightCost (const EGNode* n) const; unsigned getFillCost (const EGNode* n) const; unsigned getWeightedFillCost (const EGNode* n) const; bool neighbors (EGNode* n1, EGNode* n2) const; void addNode (EGNode*); EGNode* getEGNode (VarId) const; EGNode* getLowestCostNode() const; void connectAllNeighbors (const EGNode*); std::vector nodes_; EGNeighs unmarked_; std::unordered_map varMap_; static ElimHeuristic elimHeuristic_; DISALLOW_COPY_AND_ASSIGN (ElimGraph); }; /* Profiling shows that we should inline the following functions */ inline void ElimGraph::addEdge (EGNode* n1, EGNode* n2) { assert (n1 != n2); n1->addNeighbor (n2); n2->addNeighbor (n1); } inline unsigned ElimGraph::getNeighborsCost (const EGNode* n) const { return n->neighbors().size(); } inline unsigned ElimGraph::getWeightCost (const EGNode* n) const { unsigned cost = 1; const EGNeighs& neighs = n->neighbors(); for (size_t i = 0; i < neighs.size(); i++) { cost *= neighs[i]->range(); } return cost; } inline unsigned ElimGraph::getFillCost (const EGNode* n) const { unsigned cost = 0; const EGNeighs& neighs = n->neighbors(); if (neighs.size() > 0) { for (size_t i = 0; i < neighs.size() - 1; i++) { for (size_t j = i + 1; j < neighs.size(); j++) { if ( ! neighbors (neighs[i], neighs[j])) { cost ++; } } } } return cost; } inline unsigned ElimGraph::getWeightedFillCost (const EGNode* n) const { unsigned cost = 0; const EGNeighs& neighs = n->neighbors(); if (neighs.size() > 0) { for (size_t i = 0; i < neighs.size() - 1; i++) { for (size_t j = i + 1; j < neighs.size(); j++) { if ( ! neighbors (neighs[i], neighs[j])) { cost += neighs[i]->range() * neighs[j]->range(); } } } } return cost; } inline bool ElimGraph::neighbors (EGNode* n1, EGNode* n2) const { return n1->isNeighbor (n2); } } // namespace Horus #endif // YAP_PACKAGES_CLPBN_HORUS_ELIMGRAPH_H_