Hypergraph ParBMAlgorithm::transversal (const Hypergraph& H) const { BOOST_LOG_TRIVIAL(debug) << "Starting BM with " << num_threads << " threads. Hypergraph has " << H.num_verts() << " vertices and " << H.num_edges() << " edges."; // Set up inputs Hypergraph Hmin = H.minimization(); Hypergraph G (H.num_verts()); Hypergraph::Edge V = Hmin.verts_covered(); // Initialize using any HS we can find Hypergraph::Edge first_hs = FKAlgorithm::minimize_new_hs(Hmin, G, V); G.add_edge(first_hs); // Grow G until it covers all vertices bool G_has_full_coverage = false; while (not G_has_full_coverage) { Hypergraph::Edge new_hs = V - coverage_condition_check(H, G); if (new_hs.is_proper_subset_of(V)) { Hypergraph::Edge new_mhs = FKAlgorithm::minimize_new_hs(Hmin, G, new_hs); G.add_edge(new_mhs); } else { G_has_full_coverage = true; } } // Apply the BM algorithm repeatedly, generating new transversals // until duality is confirmed bool still_searching_for_transversals = true; Hypergraph::EdgeQueue new_hses, new_mhses; #pragma omp parallel shared(Hmin, G, new_hses, new_mhses) num_threads(num_threads) #pragma omp master while (still_searching_for_transversals) { find_new_hses(Hmin, G, Hmin.verts_covered(), new_hses); if (new_hses.size_approx() == 0) { still_searching_for_transversals = false; } else { minimize_new_hses(Hmin, G, new_hses, new_mhses); Hypergraph::Edge new_mhs; while (new_mhses.try_dequeue(new_mhs)) { // The results will all be inclusion-minimal, but // there may be some overlap. Thus, we try to add // them... try { G.add_edge(new_mhs, true); } // But ignore any minimality_violated_exception // that is thrown. catch (minimality_violated_exception& e) {} } BOOST_LOG_TRIVIAL(debug) << "New |G|: " << G.num_edges(); } } return G; }
Hypergraph FKAlgorithmA::transversal (const Hypergraph& H) const { BOOST_LOG_TRIVIAL(debug) << "Starting FKA. Hypergraph has " << H.num_verts() << " vertices and " << H.num_edges() << " edges."; Hypergraph G (H.num_verts()); Hypergraph Hmin = H.minimization(); Hypergraph::Edge V = Hmin.verts_covered(); bool still_searching_for_transversals = true; while (still_searching_for_transversals) { Hypergraph::Edge omit_set = find_omit_set(Hmin, G); if (omit_set.none() and G.num_edges() > 0) { BOOST_LOG_TRIVIAL(debug) << "Received empty omit_set, so we're done."; still_searching_for_transversals = false; } else { Hypergraph::Edge new_hs = V - omit_set; Hypergraph::Edge new_mhs = minimize_new_hs(H, G, new_hs); BOOST_LOG_TRIVIAL(trace) << "Received witness." << "\nomit_set:\t" << omit_set << "\nMHS:\t\t" << new_mhs; G.add_edge(new_mhs, true); BOOST_LOG_TRIVIAL(debug) << "New G size: " << G.num_edges(); } } return G; }
Hypergraph ParBMAlgorithm::l5_full_cover (const Hypergraph& H, const Hypergraph::Edge& base_transversal) { /** Find a full cover of the dual of H from the given base_transversal in accordance with lemma 5 of BM. **/ Hypergraph C (H.num_verts()); Hypergraph::Edge V = H.verts_covered(); C.add_edge(base_transversal, false); Hypergraph::EdgeIndex i = base_transversal.find_first(); while (i != Hypergraph::Edge::npos) { V.reset(i); C.add_edge(V, false); V.set(i); i = base_transversal.find_next(i); } return C; }
Hypergraph ParBMAlgorithm::l4_full_cover (const Hypergraph& H, const Hypergraph::Edge& base_edge) { /** Find a full cover of the dual of H from the given base_edge in accordance with lemma 4 of BM. **/ Hypergraph C (H.num_verts()); Hypergraph::Edge V = H.verts_covered(); for (auto& edge: H) { Hypergraph::Edge intersection = edge & base_edge; Hypergraph::EdgeIndex i = intersection.find_first(); while (i != Hypergraph::Edge::npos) { Hypergraph::Edge new_edge = V - edge; new_edge.set(i); C.add_edge(new_edge, false); i = intersection.find_next(i); } } return C; }