69 auto nb_bags =
bags.size();
70 for(
bag_t i{0}; i<nb_bags; ++i) {
77 decltype(copy_children) new_children;
78 new_children.push_back(current);
80 new_children.push_back(copy_children[k]);
88 nb_bags =
bags.size();
89 for(
bag_t i{0}; i<nb_bags; ++i) {
95 for(
size_t k = 0; k <
getBag(i).
size() - j; ++k, ++it)
102 std::vector<std::set<gate_t>> gates_in_children(
bags.size());
103 auto getChildrenGates = [&gates_in_children](
bag_t i) ->
auto& {
104 return gates_in_children[
static_cast<std::underlying_type<bag_t>::type
>(i)];
110 getChildrenGates(
getParent(i)).insert(g);
117 nb_bags =
bags.size();
118 for(
bag_t i{0}; i<nb_bags; ++i) {
121 std::vector<gate_t> extra_gates;
123 if(getChildrenGates(i).find(g) == getChildrenGates(i).end())
124 extra_gates.push_back(g);
129 if(!extra_gates.empty()) {
132 if(
getChildren(i).size()==1 && intersection.
size()==getChildrenGates(i).size()) {
137 auto gate = extra_gates.back();
140 extra_gates.pop_back();
144 for(
auto g: extra_gates) {
160 const std::vector<bag_t> &ch)
208 std::string result=
"digraph circuit{\n graph [rankdir=UD] ;\n";
212 result +=
" " +
to_string(i) +
" [label=\"{";
214 for(
auto gate:
getBag(i)) {
237 unsigned long nb_bags;
240 td.
bags.resize(nb_bags);
241 td.
parent.resize(nb_bags);
244 for(
bag_t i{0}; i<nb_bags; ++i) {
255 for(
unsigned long j=0; j<nb_gates; ++j) {
270 unsigned long nb_children;
273 for(
unsigned long j=0; j<nb_children; ++j) {
296 unsigned max_width{0};
297 std::unordered_map<gate_t, bag_t> bag_ids;
305 unsigned long node = strategy.
get_next();
307 std::unordered_set<unsigned long> neigh = graph.
remove_node(node);
308 max_width = std::max<unsigned>(neigh.size(), max_width);
324 bag_ids[
gate_t{node}] = bag_id++;
337 bags.push_back(remaining_bag);
351 auto it = bag_ids.find(n);
352 if(it!=bag_ids.end() && it->second!=i)
353 min_bag = std::min(it->second, min_bag);
Boolean provenance circuit with support for knowledge compilation.
gate_t
Strongly-typed gate identifier.
Priority-queue-based node-elimination ordering for tree decomposition.
std::istream & operator>>(std::istream &in, TreeDecomposition &td)
Read a tree decomposition in PACE challenge format.
Tree decomposition of a Boolean circuit for knowledge compilation.
std::string to_string(bag_t b)
Convert a bag_t to its decimal string representation.
bag_t
Strongly-typed bag identifier for a tree decomposition.
Boolean circuit for provenance formula evaluation.
Mutable adjacency-list graph over unsigned-long node IDs.
void fill(const std::unordered_set< unsigned long > &nodes, bool undirected=true)
Add all missing edges within nodes (clique fill).
const std::unordered_set< unsigned long > & get_nodes() const
Return the set of all node IDs in the graph.
std::unordered_set< unsigned long > remove_node(unsigned long node)
Remove node and all its incident edges.
unsigned long number_nodes() const
Return the number of nodes in the graph.
Node-elimination ordering strategy using a priority queue.
unsigned long get_next()
Pop and return the node with the smallest statistic.
virtual void recompute(const std::unordered_set< unsigned long > &nodes, Graph &graph)
Recompute statistics for a subset of nodes and update the queue.
bool empty()
Return true if the queue is empty.
void init_permutation(Graph &graph)
Populate the priority queue with all nodes in graph.
Exception thrown when a tree decomposition cannot be constructed.
Tree decomposition of a Boolean circuit's primal graph.
bag_t findGateConnection(gate_t v) const
Find the bag whose gate set is closest to gate v (for rooting).
bag_t addEmptyBag(bag_t parent, const std::vector< bag_t > &children=std::vector< bag_t >())
Insert a new empty bag as a child of parent.
std::vector< Bag > bags
Bag contents, indexed by bag_t.
void addGateToBag(gate_t g, bag_t b)
Add gate g to the contents of bag b.
flat_set< gate_t, small_vector > Bag
The type of a bag: a small flat set of gate IDs.
void setParent(bag_t b, bag_t p)
Set the parent of bag b to p.
TreeDecomposition()=default
std::string toDot() const
Render the tree decomposition as a GraphViz DOT string.
void reroot(bag_t bag)
Re-root the tree so that bag becomes the root.
static constexpr int OPTIMAL_ARITY
Preferred maximum arity of bags in the friendly form.
std::vector< bag_t > parent
Parent of each bag (root points to itself)
unsigned treewidth
Treewidth of the decomposition.
bag_t getParent(bag_t b) const
Return the parent of bag b.
static constexpr int MAX_TREEWIDTH
Maximum supported treewidth.
std::vector< std::vector< bag_t > > children
Children of each bag.
bag_t root
Identifier of the root bag.
Bag & getBag(bag_t b)
Mutable access to bag b.
void makeFriendly(gate_t root)
Restructure the tree into the friendly normal form.
std::vector< bag_t > & getChildren(bag_t b)
Mutable access to the children of bag b.
Constructs a d-DNNF from a Boolean circuit and its tree decomposition.
decltype(std::begin(std::declval< const storage_t & >())) const_iterator
Const iterator.
iterator begin()
Return iterator to the first element.
size_t size() const
Return the number of elements in the set.
void insert(const K &value)
Insert value if not already present (const-ref overload).