3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-05 19:00:25 +00:00

separate pre-processing, add callback parameter to push/pop in python API

This commit is contained in:
Nikolaj Bjorner 2022-04-11 17:05:49 +02:00
parent f43d9d00d4
commit c996a66da0
16 changed files with 287 additions and 200 deletions

102
src/opt/opt_preprocess.cpp Normal file
View file

@ -0,0 +1,102 @@
/*++
Copyright (c) 2021 Microsoft Corporation
Module Name:
opt_preprocess.cpp
Abstract:
Pre-processing for MaxSMT
Find mutexes - at most 1 constraints and modify soft constraints and bounds.
Author:
Nikolaj Bjorner (nbjorner) 2022-04-11
--*/
#pragma once
#include "opt/opt_preprocess.h"
namespace opt {
bool preprocess::find_mutexes(vector<soft>& softs, rational& lower) {
expr_ref_vector fmls(m);
obj_map<expr, rational> new_soft;
for (soft& sf : softs) {
m_trail.push_back(sf.s);
if (new_soft.contains(sf.s))
new_soft[sf.s] += sf.weight;
else
new_soft.insert(sf.s, sf.weight);
fmls.push_back(sf.s);
}
vector<expr_ref_vector> mutexes;
lbool is_sat = s.find_mutexes(fmls, mutexes);
if (is_sat == l_false)
return true;
if (is_sat == l_undef)
return false;
for (auto& mux : mutexes)
process_mutex(mux, new_soft, lower);
softs.reset();
for (auto const& [k, v] : new_soft)
softs.push_back(soft(expr_ref(k, m), v, false));
m_trail.reset();
return true;
}
struct maxsmt_compare_soft {
obj_map<expr, rational> const& m_soft;
maxsmt_compare_soft(obj_map<expr, rational> const& soft): m_soft(soft) {}
bool operator()(expr* a, expr* b) const {
return m_soft.find(a) > m_soft.find(b);
}
};
void preprocess::process_mutex(expr_ref_vector& mutex, obj_map<expr, rational>& new_soft, rational& lower) {
TRACE("opt",
for (expr* e : mutex) {
tout << mk_pp(e, m) << " |-> " << new_soft.find(e) << "\n";
});
if (mutex.size() <= 1)
return;
maxsmt_compare_soft cmp(new_soft);
ptr_vector<expr> _mutex(mutex.size(), mutex.data());
std::sort(_mutex.begin(), _mutex.end(), cmp);
mutex.reset();
mutex.append(_mutex.size(), _mutex.data());
rational weight(0), sum1(0), sum2(0);
vector<rational> weights;
for (expr* e : mutex) {
rational w = new_soft.find(e);
weights.push_back(w);
sum1 += w;
new_soft.remove(e);
}
for (unsigned i = mutex.size(); i-- > 0; ) {
expr_ref soft(m.mk_or(i+1, mutex.data()), m);
m_trail.push_back(soft);
rational w = weights[i];
weight = w - weight;
lower += weight*rational(i);
IF_VERBOSE(1, verbose_stream() << "(opt.maxsat mutex size: " << i + 1 << " weight: " << weight << ")\n";);
sum2 += weight*rational(i+1);
new_soft.insert(soft, weight);
for (; i > 0 && weights[i-1] == w; --i) {}
weight = w;
}
SASSERT(sum1 == sum2);
}
preprocess::preprocess(solver& s): m(s.get_manager()), s(s), m_trail(m) {}
bool preprocess::operator()(vector<soft>& soft, rational& lower) {
return find_mutexes(soft, lower);
}
};