mirror of
https://github.com/Z3Prover/z3
synced 2026-02-14 21:01:49 +00:00
* Initial plan
* Refactor mk_and and mk_app to use std::span
- Made mk_and(unsigned num_args, expr * const * args) private
- Added new public mk_and(std::span<expr* const> args) method
- Added new public mk_app(family_id fid, decl_kind k, std::span<expr* const> args) method
- Updated all convenience overloads to use std::span version
- Updated all external call sites to use the new std::span API
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
* Fix remaining test files to use std::span API
- Updated src/test/sorting_network.cpp
- Updated src/test/ho_matcher.cpp with explicit cast to resolve ambiguity
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
* Revert overlapping changes superseded by PR #8286
Reverted 30 files to match the state from PR #8286 (commit ebc0688) which refactored mk_and/mk_or call sites to use vector overloads. This supersedes the std::span changes in those files.
Retained std::span changes in files unique to this PR:
- Core API changes (ast.h, ast.cpp)
- Files not affected by PR #8286 (api_context.cpp, ast_util.cpp, bool_rewriter.h, datatype_rewriter.cpp, dom_simplifier.cpp, factor_rewriter.cpp, pb2bv_rewriter.cpp, quant_hoist.cpp, spacer_cluster_util.cpp, sortmax.cpp, array_axioms.cpp, smtfd_solver.cpp, goal.cpp, ho_matcher.cpp, qe_arith.cpp, sorting_network.cpp)
- Special case in hnf.cpp where both PRs modified different lines
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
143 lines
4.6 KiB
C++
143 lines
4.6 KiB
C++
/*++
|
|
Copyright (c) 2014 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sortmax.cpp
|
|
|
|
Abstract:
|
|
|
|
Theory based MaxSAT.
|
|
|
|
Author:
|
|
|
|
Nikolaj Bjorner (nbjorner) 2016-11-18
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
#include "opt/maxsmt.h"
|
|
#include "util/uint_set.h"
|
|
#include "ast/ast_pp.h"
|
|
#include "model/model_smt2_pp.h"
|
|
#include "smt/smt_theory.h"
|
|
#include "smt/smt_context.h"
|
|
#include "opt/opt_context.h"
|
|
#include "util/sorting_network.h"
|
|
#include "ast/converters/generic_model_converter.h"
|
|
|
|
namespace opt {
|
|
|
|
class sortmax : public maxsmt_solver_base {
|
|
public:
|
|
typedef expr* pliteral;
|
|
typedef ptr_vector<expr> pliteral_vector;
|
|
psort_nw<sortmax> m_sort;
|
|
expr_ref_vector m_trail;
|
|
func_decl_ref_vector m_fresh;
|
|
ref<generic_model_converter> m_filter;
|
|
sortmax(maxsat_context& c, vector<soft>& s, unsigned index):
|
|
maxsmt_solver_base(c, s, index), m_sort(*this), m_trail(m), m_fresh(m) {}
|
|
|
|
lbool operator()() override {
|
|
if (!init())
|
|
return l_undef;
|
|
|
|
lbool is_sat = l_true;
|
|
m_filter = alloc(generic_model_converter, m, "sortmax");
|
|
expr_ref_vector in(m);
|
|
expr_ref tmp(m);
|
|
ptr_vector<expr> out;
|
|
for (auto const & [e, w, t] : m_soft) {
|
|
if (!w.is_unsigned()) {
|
|
throw default_exception("sortmax can only handle unsigned weights. Use a different heuristic.");
|
|
}
|
|
unsigned n = w.get_unsigned();
|
|
while (n > 0) {
|
|
in.push_back(e);
|
|
--n;
|
|
}
|
|
}
|
|
m_sort.sorting(in.size(), in.data(), out);
|
|
|
|
// initialize sorting network outputs using the initial assignment.
|
|
unsigned first = 0;
|
|
for (auto const & [e, w, t] : m_soft) {
|
|
if (t == l_true) {
|
|
unsigned n = w.get_unsigned();
|
|
while (n > 0) {
|
|
s().assert_expr(out[first]);
|
|
++first;
|
|
--n;
|
|
}
|
|
}
|
|
}
|
|
while (l_true == is_sat && first < out.size() && m_lower < m_upper) {
|
|
trace_bounds("sortmax");
|
|
s().assert_expr(out[first]);
|
|
is_sat = s().check_sat(0, nullptr);
|
|
TRACE(opt, tout << is_sat << "\n"; s().display(tout); tout << "\n";);
|
|
if (!m.inc()) {
|
|
is_sat = l_undef;
|
|
}
|
|
if (is_sat == l_true) {
|
|
++first;
|
|
s().get_model(m_model);
|
|
update_assignment();
|
|
for (; first < out.size() && is_true(out[first]); ++first) {
|
|
s().assert_expr(out[first]);
|
|
}
|
|
TRACE(opt, model_smt2_pp(tout, m, *m_model.get(), 0););
|
|
m_upper = m_lower + rational(out.size() - first);
|
|
(*m_filter)(m_model);
|
|
}
|
|
}
|
|
if (is_sat == l_false) {
|
|
is_sat = l_true;
|
|
m_lower = m_upper;
|
|
}
|
|
TRACE(opt, tout << "min cost: " << m_upper << "\n";);
|
|
return is_sat;
|
|
}
|
|
|
|
void update_assignment() {
|
|
for (soft& s : m_soft) s.set_value(is_true(s.s));
|
|
}
|
|
|
|
bool is_true(expr* e) {
|
|
return m_model->is_true(e);
|
|
}
|
|
|
|
// definitions used for sorting network
|
|
pliteral mk_false() { return m.mk_false(); }
|
|
pliteral mk_true() { return m.mk_true(); }
|
|
pliteral mk_max(unsigned n, pliteral const* as) { return trail(m.mk_or(n, as)); }
|
|
pliteral mk_min(unsigned n, pliteral const* as) { return trail(m.mk_and(std::span<expr* const>(as, n))); }
|
|
pliteral mk_not(pliteral a) { if (m.is_not(a,a)) return a; return trail(m.mk_not(a)); }
|
|
|
|
std::ostream& pp(std::ostream& out, pliteral lit) { return out << mk_pp(lit, m); }
|
|
|
|
pliteral trail(pliteral l) {
|
|
m_trail.push_back(l);
|
|
return l;
|
|
}
|
|
pliteral fresh(char const* n) {
|
|
expr_ref fr(m.mk_fresh_const(n, m.mk_bool_sort()), m);
|
|
func_decl* f = to_app(fr)->get_decl();
|
|
m_fresh.push_back(f);
|
|
m_filter->hide(f);
|
|
return trail(fr);
|
|
}
|
|
|
|
void mk_clause(unsigned n, pliteral const* lits) {
|
|
s().assert_expr(mk_or(m, n, lits));
|
|
}
|
|
|
|
};
|
|
|
|
|
|
maxsmt_solver_base* mk_sortmax(maxsat_context& c, vector<soft>& s, unsigned index) {
|
|
return alloc(sortmax, c, s, index);
|
|
}
|
|
|
|
}
|