mirror of
https://github.com/Z3Prover/z3
synced 2025-04-26 10:35:33 +00:00
fix and coallesce clique functionality
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
1600823435
commit
ea601dd403
17 changed files with 361 additions and 119 deletions
140
src/util/max_cliques.h
Normal file
140
src/util/max_cliques.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*++
|
||||
Copyright (c) 2016 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
max_cliques.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Utility for enumerating locally maximal sub cliques.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2016-11-18
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "vector.h"
|
||||
#include "uint_set.h"
|
||||
|
||||
class max_cliques_plugin {
|
||||
public:
|
||||
virtual unsigned operator()(unsigned i) = 0;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class max_cliques : public T {
|
||||
vector<unsigned_vector> m_next, m_tc;
|
||||
uint_set m_reachable[2];
|
||||
uint_set m_seen1, m_seen2;
|
||||
unsigned_vector m_todo;
|
||||
|
||||
void get_reachable(unsigned p, uint_set const& goal, uint_set& reachable) {
|
||||
m_seen1.reset();
|
||||
m_todo.reset();
|
||||
m_todo.push_back(p);
|
||||
for (unsigned i = 0; i < m_todo.size(); ++i) {
|
||||
p = m_todo[i];
|
||||
if (m_seen1.contains(p)) {
|
||||
continue;
|
||||
}
|
||||
m_seen1.insert(p);
|
||||
if (m_seen2.contains(p)) {
|
||||
unsigned_vector const& tc = m_tc[p];
|
||||
for (unsigned j = 0; j < tc.size(); ++j) {
|
||||
unsigned np = tc[j];
|
||||
if (goal.contains(np)) {
|
||||
reachable.insert(np);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned np = negate(p);
|
||||
if (goal.contains(np)) {
|
||||
reachable.insert(np);
|
||||
}
|
||||
m_todo.append(next(np));
|
||||
}
|
||||
}
|
||||
for (unsigned i = m_todo.size(); i > 0; ) {
|
||||
--i;
|
||||
p = m_todo[i];
|
||||
if (m_seen2.contains(p)) {
|
||||
continue;
|
||||
}
|
||||
m_seen2.insert(p);
|
||||
unsigned np = negate(p);
|
||||
unsigned_vector& tc = m_tc[p];
|
||||
if (goal.contains(np)) {
|
||||
tc.push_back(np);
|
||||
}
|
||||
else {
|
||||
unsigned_vector const& succ = next(np);
|
||||
for (unsigned j = 0; j < succ.size(); ++j) {
|
||||
tc.append(m_tc[succ[j]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
unsigned_vector const& next(unsigned vertex) const { return m_next[vertex]; }
|
||||
|
||||
public:
|
||||
max_cliques() {}
|
||||
|
||||
void add_edge(unsigned src, unsigned dst) {
|
||||
m_next.reserve(std::max(src, dst) + 1);
|
||||
m_next.reserve(std::max(negate(src), negate(dst)) + 1);
|
||||
m_next[src].push_back(dst);
|
||||
m_next[dst].push_back(src);
|
||||
}
|
||||
|
||||
void cliques(unsigned_vector const& ps, vector<unsigned_vector>& cliques) {
|
||||
unsigned max = 0;
|
||||
unsigned num_ps = ps.size();
|
||||
for (unsigned i = 0; i < num_ps; ++i) {
|
||||
unsigned p = ps[i];
|
||||
unsigned np = negate(p);
|
||||
max = std::max(max, std::max(np, p) + 1);
|
||||
}
|
||||
m_next.reserve(max);
|
||||
m_tc.reserve(max);
|
||||
unsigned_vector clique;
|
||||
uint_set vars;
|
||||
for (unsigned i = 0; i < num_ps; ++i) {
|
||||
vars.insert(ps[i]);
|
||||
}
|
||||
|
||||
while (!vars.empty()) {
|
||||
clique.reset();
|
||||
bool turn = false;
|
||||
m_reachable[turn] = vars;
|
||||
while (!m_reachable[turn].empty()) {
|
||||
unsigned p = *m_reachable[turn].begin();
|
||||
m_reachable[turn].remove(p);
|
||||
vars.remove(p);
|
||||
clique.push_back(p);
|
||||
if (m_reachable[turn].empty()) {
|
||||
break;
|
||||
}
|
||||
m_reachable[!turn].reset();
|
||||
get_reachable(p, m_reachable[turn], m_reachable[!turn]);
|
||||
turn = !turn;
|
||||
}
|
||||
if (clique.size() > 1) {
|
||||
std::cout << clique.size() << "\n";
|
||||
cliques.push_back(clique);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
|
@ -744,6 +744,7 @@ Notes:
|
|||
return vc_cmp()*std::min(a-1,b);
|
||||
}
|
||||
|
||||
public:
|
||||
void sorting(unsigned n, literal const* xs, literal_vector& out) {
|
||||
TRACE("pb", tout << "sorting: " << n << "\n";);
|
||||
switch(n) {
|
||||
|
@ -773,8 +774,9 @@ Notes:
|
|||
TRACE("pb", tout << "sorting: " << n << "\n";
|
||||
pp(tout << "in:", n, xs) << "\n";
|
||||
pp(tout << "out:", out) << "\n";);
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
vc vc_sorting(unsigned n) {
|
||||
switch(n) {
|
||||
case 0: return vc(0,0);
|
||||
|
|
|
@ -163,10 +163,11 @@ public:
|
|||
class iterator {
|
||||
uint_set const* m_set;
|
||||
unsigned m_index;
|
||||
unsigned m_last;
|
||||
|
||||
bool invariant() const { return m_index <= m_set->get_max_elem(); }
|
||||
bool invariant() const { return m_index <= m_last; }
|
||||
|
||||
bool at_end() const { return m_index == m_set->get_max_elem(); }
|
||||
bool at_end() const { return m_index == m_last; }
|
||||
|
||||
void scan_idx() {
|
||||
SASSERT(invariant());
|
||||
|
@ -200,7 +201,7 @@ public:
|
|||
}
|
||||
public:
|
||||
iterator(uint_set const& s, bool at_end):
|
||||
m_set(&s), m_index(at_end?s.get_max_elem():0) {
|
||||
m_set(&s), m_index(at_end?s.get_max_elem():0), m_last(s.get_max_elem()) {
|
||||
scan();
|
||||
SASSERT(invariant());
|
||||
}
|
||||
|
@ -212,6 +213,7 @@ public:
|
|||
iterator & operator=(iterator const& other) {
|
||||
m_set = other.m_set;
|
||||
m_index = other.m_index;
|
||||
m_last = other.m_last;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue