mirror of
https://github.com/Z3Prover/z3
synced 2026-05-24 10:59:38 +00:00
Centralize and document TRACE tags using X-macros (#7657)
* Introduce X-macro-based trace tag definition - Created trace_tags.def to centralize TRACE tag definitions - Each tag includes a symbolic name and description - Set up enum class TraceTag for type-safe usage in TRACE macros * Add script to generate Markdown documentation from trace_tags.def - Python script parses trace_tags.def and outputs trace_tags.md * Refactor TRACE_NEW to prepend TraceTag and pass enum to is_trace_enabled * trace: improve trace tag handling system with hierarchical tagging - Introduce hierarchical tag-class structure: enabling a tag class activates all child tags - Unify TRACE, STRACE, SCTRACE, and CTRACE under enum TraceTag - Implement initial version of trace_tag.def using X(tag, tag_class, description) (class names and descriptions to be refined in a future update) * trace: replace all string-based TRACE tags with enum TraceTag - Migrated all TRACE, STRACE, SCTRACE, and CTRACE macros to use enum TraceTag values instead of raw string literals * trace : add cstring header * trace : Add Markdown documentation generation from trace_tags.def via mk_api_doc.py * trace : rename macro parameter 'class' to 'tag_class' and remove Unicode comment in trace_tags.h. * trace : Add TODO comment for future implementation of tag_class activation * trace : Disable code related to tag_class until implementation is ready (#7663).
This commit is contained in:
parent
d766292dab
commit
0a93ff515d
583 changed files with 8698 additions and 7299 deletions
|
|
@ -64,7 +64,7 @@ namespace mbp {
|
|||
expr* e1, * e2;
|
||||
DEBUG_CODE(expr_ref val(m);
|
||||
eval(lit, val);
|
||||
CTRACE("qe", !m.is_true(val), tout << mk_pp(lit, m) << " := " << val << "\n";);
|
||||
CTRACE(qe, !m.is_true(val), tout << mk_pp(lit, m) << " := " << val << "\n";);
|
||||
if (m.is_false(val))
|
||||
return false;
|
||||
SASSERT(m.limit().is_canceled() || !m.is_false(val)););
|
||||
|
|
@ -72,7 +72,7 @@ namespace mbp {
|
|||
if (!m.inc())
|
||||
return false;
|
||||
|
||||
TRACE("opt", tout << mk_pp(lit, m) << " " << a.is_lt(lit) << " " << a.is_gt(lit) << "\n";);
|
||||
TRACE(opt, tout << mk_pp(lit, m) << " " << a.is_lt(lit) << " " << a.is_gt(lit) << "\n";);
|
||||
bool is_not = m.is_not(lit, lit);
|
||||
if (is_not) {
|
||||
mul.neg();
|
||||
|
|
@ -115,7 +115,7 @@ namespace mbp {
|
|||
vector<std::pair<expr*, rational> > nums;
|
||||
for (expr* arg : *alit) {
|
||||
val = eval(arg);
|
||||
TRACE("qe", tout << mk_pp(arg, m) << " " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(arg, m) << " " << val << "\n";);
|
||||
if (!a.is_numeral(val, r)) return false;
|
||||
nums.push_back(std::make_pair(arg, r));
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ namespace mbp {
|
|||
expr* arg1 = to_app(lit)->get_arg(i), * arg2 = nullptr;
|
||||
rational r;
|
||||
expr_ref val = eval(arg1);
|
||||
TRACE("qe", tout << mk_pp(arg1, m) << " " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(arg1, m) << " " << val << "\n";);
|
||||
if (!a.is_numeral(val, r)) return false;
|
||||
if (values.find(r, arg2)) {
|
||||
ty = opt::t_eq;
|
||||
|
|
@ -168,7 +168,7 @@ namespace mbp {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
TRACE("qe", tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
else if (m.is_and(lit) && is_not) {
|
||||
|
|
@ -178,11 +178,11 @@ namespace mbp {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
TRACE("qe", tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
TRACE("qe", tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "Skipping " << mk_pp(lit, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
vars coeffs;
|
||||
|
|
@ -230,7 +230,7 @@ namespace mbp {
|
|||
|
||||
else if (m.is_ite(t, t1, t2, t3)) {
|
||||
val = eval(t1);
|
||||
TRACE("qe", tout << mk_pp(t1, m) << " := " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(t1, m) << " := " << val << "\n";);
|
||||
if (m.is_true(val)) {
|
||||
linearize(mbo, eval, mul, t2, c, fmls, ts, tids);
|
||||
fmls.push_back(t1);
|
||||
|
|
@ -275,7 +275,7 @@ namespace mbp {
|
|||
mbo.add_divides(coeffs, c0, mul1);
|
||||
}
|
||||
else {
|
||||
TRACE("qe", tout << "insert mul " << mk_pp(t, m) << "\n");
|
||||
TRACE(qe, tout << "insert mul " << mk_pp(t, m) << "\n");
|
||||
insert_mul(t, mul, ts);
|
||||
}
|
||||
}
|
||||
|
|
@ -324,7 +324,7 @@ namespace mbp {
|
|||
if (!has_arith)
|
||||
return true;
|
||||
model_evaluator eval(model);
|
||||
TRACE("qe", tout << model;);
|
||||
TRACE(qe, tout << model;);
|
||||
eval.set_model_completion(true);
|
||||
model.set_inline();
|
||||
compute_def |= m_apply_projection;
|
||||
|
|
@ -333,12 +333,12 @@ namespace mbp {
|
|||
obj_map<expr, unsigned> tids;
|
||||
expr_ref_vector pinned(m);
|
||||
unsigned j = 0;
|
||||
TRACE("qe", tout << "vars: " << vars << "\n";
|
||||
TRACE(qe, tout << "vars: " << vars << "\n";
|
||||
for (expr* f : fmls) tout << mk_pp(f, m) << " := " << model(f) << "\n";);
|
||||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
expr* fml = fmls.get(i);
|
||||
if (!linearize(mbo, eval, fml, fmls, tids)) {
|
||||
TRACE("qe", tout << "could not linearize: " << mk_pp(fml, m) << "\n";);
|
||||
TRACE(qe, tout << "could not linearize: " << mk_pp(fml, m) << "\n";);
|
||||
fmls[j++] = fml;
|
||||
}
|
||||
else {
|
||||
|
|
@ -346,7 +346,7 @@ namespace mbp {
|
|||
}
|
||||
}
|
||||
fmls.shrink(j);
|
||||
TRACE("qe", tout << "formulas\n" << fmls << "\n";
|
||||
TRACE(qe, tout << "formulas\n" << fmls << "\n";
|
||||
for (auto const& [e, id] : tids)
|
||||
tout << mk_pp(e, m) << " -> " << id << "\n";);
|
||||
|
||||
|
|
@ -370,7 +370,7 @@ namespace mbp {
|
|||
IF_VERBOSE(1, verbose_stream() << "mbp failed on " << mk_pp(v, m) << " := " << val << "\n");
|
||||
throw default_exception("evaluation did not produce a numeral");
|
||||
}
|
||||
TRACE("qe", tout << mk_pp(v, m) << " " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(v, m) << " " << val << "\n";);
|
||||
tids.insert(v, mbo.add_var(r, a.is_int(v)));
|
||||
}
|
||||
}
|
||||
|
|
@ -414,7 +414,7 @@ namespace mbp {
|
|||
}
|
||||
vars.shrink(j);
|
||||
|
||||
TRACE("qe", tout << "remaining vars: " << vars << "\n";
|
||||
TRACE(qe, tout << "remaining vars: " << vars << "\n";
|
||||
for (unsigned v : real_vars) tout << "v" << v << " " << mk_pp(index2expr[v], m) << "\n";
|
||||
mbo.display(tout););
|
||||
vector<opt::model_based_opt::def_ref> defs = mbo.project(real_vars.size(), real_vars.data(), compute_def);
|
||||
|
|
@ -430,7 +430,7 @@ namespace mbp {
|
|||
def_vars.insert(r.m_id, r);
|
||||
}
|
||||
rows2fmls(def_vars, rows, index2expr, fmls);
|
||||
TRACE("qe", mbo.display(tout << "mbo result\n");
|
||||
TRACE(qe, mbo.display(tout << "mbo result\n");
|
||||
for (auto const& d : defs) if (d) tout << "def: " << *d << "\n";
|
||||
tout << fmls << "\n";);
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ namespace mbp {
|
|||
if (m_apply_projection && !apply_projection(eval, result, fmls))
|
||||
return false;
|
||||
|
||||
TRACE("qe",
|
||||
TRACE(qe,
|
||||
for (auto const& [v, t] : result)
|
||||
tout << v << " := " << t << "\n";
|
||||
for (auto* f : fmls)
|
||||
|
|
@ -629,7 +629,7 @@ namespace mbp {
|
|||
mdl.register_decl(f, val);
|
||||
}
|
||||
else {
|
||||
TRACE("qe", tout << "omitting model update for non-uninterpreted constant " << mk_pp(e, m) << "\n";);
|
||||
TRACE(qe, tout << "omitting model update for non-uninterpreted constant " << mk_pp(e, m) << "\n";);
|
||||
}
|
||||
}
|
||||
expr_ref val(a.mk_numeral(value.get_rational(), false), m);
|
||||
|
|
@ -660,7 +660,7 @@ namespace mbp {
|
|||
expr_ref val = eval(fml);
|
||||
if (!m.is_true(val)) {
|
||||
valid = false;
|
||||
TRACE("qe", tout << mk_pp(fml, m) << " := " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(fml, m) << " := " << val << "\n";);
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
|
|
@ -676,14 +676,14 @@ namespace mbp {
|
|||
rational r;
|
||||
expr_ref val = eval(v);
|
||||
if (!a.is_numeral(val, r)) {
|
||||
TRACE("qe", tout << eval.get_model() << "\n";);
|
||||
TRACE(qe, tout << eval.get_model() << "\n";);
|
||||
IF_VERBOSE(1, verbose_stream() << "mbp failed on " << mk_pp(v, m) << " := " << val << "\n");
|
||||
throw default_exception("mbp evaluation was only partial");
|
||||
}
|
||||
id = mbo.add_var(r, a.is_int(v));
|
||||
tids.insert(v, id);
|
||||
}
|
||||
CTRACE("qe", kv.m_value.is_zero(), tout << mk_pp(v, m) << " has coefficient 0\n";);
|
||||
CTRACE(qe, kv.m_value.is_zero(), tout << mk_pp(v, m) << " has coefficient 0\n";);
|
||||
if (!kv.m_value.is_zero()) {
|
||||
coeffs.push_back(var(id, kv.m_value));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ namespace mbp {
|
|||
(m_arr_u.is_store (a) && (a->get_arg (0) == m_v))) {
|
||||
m_has_stores_v.mark (a, true);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "has stores:\n";
|
||||
tout << mk_pp (a, m) << "\n";
|
||||
);
|
||||
|
|
@ -248,7 +248,7 @@ namespace mbp {
|
|||
app_ref p_exp = mk_peq (eq->get_arg (0), eq->get_arg (1), empty, m);
|
||||
bool subst_eq_found = false;
|
||||
while (true) {
|
||||
TRACE ("qe", tout << "processing peq:\n" << p_exp << "\n";);
|
||||
TRACE(qe, tout << "processing peq:\n" << p_exp << "\n";);
|
||||
|
||||
peq p (p_exp, m);
|
||||
expr_ref lhs = p.lhs(), rhs = p.rhs();
|
||||
|
|
@ -294,7 +294,7 @@ namespace mbp {
|
|||
}
|
||||
}
|
||||
if (idx_in_I) {
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "store index in diff indices:\n";
|
||||
tout << mk_pp (m_idx_lits_v.back (), m) << "\n";
|
||||
);
|
||||
|
|
@ -302,7 +302,7 @@ namespace mbp {
|
|||
// arr0 ==I arr1
|
||||
p_exp = mk_peq (arr0, arr1, I, m);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "new peq:\n";
|
||||
tout << mk_pp (p_exp, m) << "\n";
|
||||
);
|
||||
|
|
@ -313,7 +313,7 @@ namespace mbp {
|
|||
I.push_back (idxs);
|
||||
p_exp = mk_peq (arr0, arr1, I, m);
|
||||
|
||||
TRACE ("qe", tout << "new peq:\n" << p_exp << "\n"; );
|
||||
TRACE(qe, tout << "new peq:\n" << p_exp << "\n"; );
|
||||
|
||||
// arr1[idx] == x
|
||||
ptr_vector<expr> sel_args;
|
||||
|
|
@ -323,7 +323,7 @@ namespace mbp {
|
|||
expr_ref eq (m.mk_eq (arr1_idx, x), m);
|
||||
m_aux_lits_v.push_back (eq);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "new eq:\n";
|
||||
tout << mk_pp (eq, m) << "\n";
|
||||
);
|
||||
|
|
@ -334,7 +334,7 @@ namespace mbp {
|
|||
}
|
||||
else if (lhs == m_v || rhs == m_v) {
|
||||
subst_eq_found = true;
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "subst eq found!\n";
|
||||
);
|
||||
break;
|
||||
|
|
@ -348,7 +348,7 @@ namespace mbp {
|
|||
if (subst_eq_found) {
|
||||
factor_selects (p_exp);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "after factoring selects:\n";
|
||||
tout << mk_pp (p_exp, m) << "\n";
|
||||
for (unsigned i = m_aux_lits_v.size () - m_aux_vars.size (); i < m_aux_lits_v.size (); i++) {
|
||||
|
|
@ -366,7 +366,7 @@ namespace mbp {
|
|||
convert_peq_to_eq (p_exp, eq, stores_on_rhs);
|
||||
m_subst_term_v = eq->get_arg (1);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "subst term found:\n";
|
||||
tout << mk_pp (m_subst_term_v, m) << "\n";
|
||||
);
|
||||
|
|
@ -406,7 +406,7 @@ namespace mbp {
|
|||
/* empty */ ;
|
||||
}
|
||||
if (store != m_v) {
|
||||
TRACE("qe", tout << "not a store " << mk_pp(eq, m) << " " << lhs_has_v << " " << rhs_has_v << " " << mk_pp(m_v, m) << "\n";);
|
||||
TRACE(qe, tout << "not a store " << mk_pp(eq, m) << " " << lhs_has_v << " " << rhs_has_v << " " << mk_pp(m_v, m) << "\n";);
|
||||
return UINT_MAX;
|
||||
}
|
||||
return nd;
|
||||
|
|
@ -428,11 +428,11 @@ namespace mbp {
|
|||
svector<std::pair<unsigned, app*> > true_eqs;
|
||||
|
||||
find_arr_eqs (fml, eqs);
|
||||
TRACE ("qe", tout << "array equalities:\n" << eqs << "\n";);
|
||||
TRACE(qe, tout << "array equalities:\n" << eqs << "\n";);
|
||||
|
||||
// evaluate eqs in M
|
||||
for (app * eq : eqs) {
|
||||
TRACE ("qe", tout << "array equality:\n" << mk_pp (eq, m) << "\n"; );
|
||||
TRACE(qe, tout << "array equality:\n" << mk_pp (eq, m) << "\n"; );
|
||||
|
||||
if (m_mev->is_false(eq)) {
|
||||
m_false_sub_v.insert (eq, m.mk_false());
|
||||
|
|
@ -506,13 +506,13 @@ namespace mbp {
|
|||
reset_v ();
|
||||
m_v = arr_vars.get (i);
|
||||
if (!m_arr_u.is_array (m_v)) {
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "not an array variable: " << m_v << "\n";
|
||||
);
|
||||
aux_vars.push_back (m_v);
|
||||
continue;
|
||||
}
|
||||
TRACE ("qe", tout << "projecting equalities on variable: " << m_v << "\n"; );
|
||||
TRACE(qe, tout << "projecting equalities on variable: " << m_v << "\n"; );
|
||||
|
||||
if (project (fml)) {
|
||||
mk_result (fml);
|
||||
|
|
@ -521,11 +521,11 @@ namespace mbp {
|
|||
if (!m_subst_term_v || contains_v (m_subst_term_v)) {
|
||||
arr_vars[j++] = m_v;
|
||||
}
|
||||
TRACE ("qe", tout << "after projection: \n" << fml << "\n";);
|
||||
TRACE(qe, tout << "after projection: \n" << fml << "\n";);
|
||||
}
|
||||
else {
|
||||
IF_VERBOSE(2, verbose_stream() << "can't project:" << m_v << "\n";);
|
||||
TRACE ("qe", tout << "Failed to project: " << m_v << "\n";);
|
||||
TRACE(qe, tout << "Failed to project: " << m_v << "\n";);
|
||||
arr_vars[j++] = m_v;
|
||||
}
|
||||
}
|
||||
|
|
@ -705,7 +705,7 @@ namespace mbp {
|
|||
fml = mk_and(lits);
|
||||
// simplify all trivial expressions introduced
|
||||
m_rw (fml);
|
||||
TRACE ("qe", tout << "after reducing selects:\n" << fml << "\n";);
|
||||
TRACE(qe, tout << "after reducing selects:\n" << fml << "\n";);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -741,7 +741,7 @@ namespace mbp {
|
|||
}
|
||||
else {
|
||||
IF_VERBOSE(2, verbose_stream() << "can't project arrays:" << "\n";);
|
||||
TRACE ("qe", tout << "Failed to project arrays\n";);
|
||||
TRACE(qe, tout << "Failed to project arrays\n";);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -888,7 +888,7 @@ namespace mbp {
|
|||
for (unsigned i = 0; i < arity && is_numeric; ++i) {
|
||||
sort* srt = get_array_domain(v_sort, i);
|
||||
if (!m_ari_u.is_real(srt) && !m_ari_u.is_int(srt) && !m_bv_u.is_bv_sort(srt)) {
|
||||
TRACE("qe", tout << "non-numeric index sort for Ackerman" << mk_pp(srt, m) << "\n";);
|
||||
TRACE(qe, tout << "non-numeric index sort for Ackerman" << mk_pp(srt, m) << "\n";);
|
||||
is_numeric = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -973,7 +973,7 @@ namespace mbp {
|
|||
// substitute for sel terms
|
||||
m_sub (fml);
|
||||
|
||||
TRACE ("qe", tout << "after projection of selects:\n" << fml << "\n";);
|
||||
TRACE(qe, tout << "after projection of selects:\n" << fml << "\n";);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -985,10 +985,10 @@ namespace mbp {
|
|||
collect_selects (fml);
|
||||
// model based ackermannization
|
||||
for (auto & kv : m_sel_terms) {
|
||||
TRACE ("qe",tout << "ackermann for var: " << mk_pp (kv.m_key, m) << "\n";);
|
||||
TRACE(qe,tout << "ackermann for var: " << mk_pp (kv.m_key, m) << "\n";);
|
||||
ackermann (*(kv.m_value));
|
||||
}
|
||||
TRACE ("qe", tout << "idx lits:\n" << m_idx_lits; );
|
||||
TRACE(qe, tout << "idx lits:\n" << m_idx_lits; );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1028,7 +1028,7 @@ namespace mbp {
|
|||
}
|
||||
else {
|
||||
IF_VERBOSE(2, verbose_stream() << "can't project arrays:" << "\n";);
|
||||
TRACE ("qe", tout << "Failed to project arrays\n";);
|
||||
TRACE(qe, tout << "Failed to project arrays\n";);
|
||||
}
|
||||
|
||||
// dealloc
|
||||
|
|
@ -1239,7 +1239,7 @@ namespace mbp {
|
|||
collect_store_expressions(tg, lits);
|
||||
collect_index_expressions(tg, lits);
|
||||
|
||||
TRACE("qe",
|
||||
TRACE(qe,
|
||||
tout << "indices\n";
|
||||
for (auto& kv : m_indices) {
|
||||
tout << sort_ref(kv.m_key, m) << " |-> " << *kv.m_value << "\n";
|
||||
|
|
@ -1253,7 +1253,7 @@ namespace mbp {
|
|||
assert_extensionality(model, tg, lits);
|
||||
assert_store_select(model, tg, lits);
|
||||
|
||||
TRACE("qe", tout << lits << "\n";);
|
||||
TRACE(qe, tout << lits << "\n";);
|
||||
|
||||
for (auto& kv : m_indices) {
|
||||
dealloc(kv.m_value);
|
||||
|
|
@ -1265,7 +1265,7 @@ namespace mbp {
|
|||
m_indices.reset();
|
||||
m_arrays.reset();
|
||||
|
||||
TRACE("qe", tout << "done: " << lits << "\n";);
|
||||
TRACE(qe, tout << "done: " << lits << "\n";);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1467,7 +1467,7 @@ namespace mbp {
|
|||
ast_manager& m = fml.get_manager();
|
||||
array_project_eqs_util pe (m);
|
||||
pe (mdl, arr_vars, fml, aux_vars);
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "Projected array eqs: " << fml << "\n";
|
||||
tout << "Remaining array vars: " << arr_vars << "\n";
|
||||
tout << "Aux vars: " << aux_vars << "\n";
|
||||
|
|
@ -1477,13 +1477,13 @@ namespace mbp {
|
|||
array_select_reducer rs (m);
|
||||
rs (mdl, arr_vars, fml, reduce_all_selects);
|
||||
|
||||
TRACE ("qe", tout << "Reduced selects:\n" << fml << "\n"; );
|
||||
TRACE(qe, tout << "Reduced selects:\n" << fml << "\n"; );
|
||||
|
||||
// 3. project selects using model based ackermannization
|
||||
array_project_selects_util ps (m);
|
||||
ps (mdl, arr_vars, fml, aux_vars);
|
||||
|
||||
TRACE ("qe",
|
||||
TRACE(qe,
|
||||
tout << "Projected array selects: " << fml << "\n";
|
||||
tout << "All aux vars: " << aux_vars << "\n";
|
||||
);
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ struct mbp_array_tg::impl {
|
|||
auto js = array_store_indices(to_app(p.lhs()));
|
||||
auto elem = array_store_elem(to_app(p.lhs()));
|
||||
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "applying elimwreq on " << expr_ref(p.mk_peq(), m) << " is neg: " << is_neg << "\n");
|
||||
vector<expr_ref_vector> indices;
|
||||
bool in = false;
|
||||
|
|
@ -251,7 +251,7 @@ struct mbp_array_tg::impl {
|
|||
void add_rdVar(expr *rd) {
|
||||
// do not assign new variable if rd is already equal to a value
|
||||
if (m_tg.has_val_in_class(rd)) return;
|
||||
TRACE("mbp_tg", tout << "applying add_rdVar on " << expr_ref(rd, m););
|
||||
TRACE(mbp_tg, tout << "applying add_rdVar on " << expr_ref(rd, m););
|
||||
app_ref u = new_var(to_app(rd)->get_sort(), m);
|
||||
m_new_vars.push_back(u);
|
||||
m_tg.add_var(u);
|
||||
|
|
@ -262,7 +262,7 @@ struct mbp_array_tg::impl {
|
|||
// given a \peq_{indices} t, where a is a variable, merge equivalence class
|
||||
// of a with store(t, indices, elems) where elems are fresh constants
|
||||
void elimeq(peq p) {
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "applying elimeq on " << expr_ref(p.mk_peq(), m););
|
||||
app_ref_vector aux_consts(m);
|
||||
expr_ref eq(m);
|
||||
|
|
@ -283,12 +283,12 @@ struct mbp_array_tg::impl {
|
|||
}
|
||||
m_tg.add_lit(eq);
|
||||
m_tg.add_eq(p.mk_peq(), m.mk_true());
|
||||
TRACE("mbp_tg", tout << "added lit " << eq;);
|
||||
TRACE(mbp_tg, tout << "added lit " << eq;);
|
||||
}
|
||||
|
||||
// rewrite select(store(a, i, k), j) into either select(a, j) or k
|
||||
void elimrdwr(app *term) {
|
||||
TRACE("mbp_tg", tout << "applying elimrdwr on " << expr_ref(term, m););
|
||||
TRACE(mbp_tg, tout << "applying elimrdwr on " << expr_ref(term, m););
|
||||
auto rd_indices = array_select_indices(term);
|
||||
auto store_term = to_app(term->get_arg(0));
|
||||
auto wr_indices = array_store_indices(store_term);
|
||||
|
|
@ -321,7 +321,7 @@ struct mbp_array_tg::impl {
|
|||
// iterate through all terms in m_tg and apply all array MBP rules once
|
||||
// returns true if any rules were applied
|
||||
bool apply() {
|
||||
TRACE("mbp_tg", tout << "Iterating over terms of tg\n");
|
||||
TRACE(mbp_tg, tout << "Iterating over terms of tg\n");
|
||||
indices.reset();
|
||||
rdTerms.reset();
|
||||
m_new_vars.reset();
|
||||
|
|
@ -336,7 +336,7 @@ struct mbp_array_tg::impl {
|
|||
continue;
|
||||
if (m_tg.is_cgr(term))
|
||||
continue;
|
||||
TRACE("mbp_tg", tout << "processing " << expr_ref(term, m) << "\n");
|
||||
TRACE(mbp_tg, tout << "processing " << expr_ref(term, m) << "\n");
|
||||
expr* a, *b;
|
||||
if (is_implicit_peq(term, a, b) || is_neg_peq(term, a, b)) {
|
||||
// rewrite array eq as peq
|
||||
|
|
|
|||
|
|
@ -64,12 +64,12 @@ struct mbp_basic_tg::impl {
|
|||
expr *c, *th, *el;
|
||||
expr_ref nterm(m);
|
||||
bool progress = false;
|
||||
TRACE("mbp_tg", tout << "Iterating over terms of tg";);
|
||||
TRACE(mbp_tg, tout << "Iterating over terms of tg";);
|
||||
// Not resetting terms because get_terms calls resize on terms
|
||||
m_tg.get_terms(terms, false);
|
||||
for (expr *term : terms) {
|
||||
if (is_seen(term)) continue;
|
||||
TRACE("mbp_tg", tout << "Processing " << expr_ref(term, m) << "\n";);
|
||||
TRACE(mbp_tg, tout << "Processing " << expr_ref(term, m) << "\n";);
|
||||
if (m.is_ite(term, c, th, el) && should_split(c)) {
|
||||
mark_seen(term);
|
||||
progress = true;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace mbp {
|
|||
bool project1(model& model, app* var, app_ref_vector& vars, expr_ref_vector& lits) {
|
||||
expr_ref val = model(var);
|
||||
SASSERT(is_app(val));
|
||||
TRACE("qe", tout << mk_pp(var, m) << " := " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(var, m) << " := " << val << "\n";);
|
||||
m_val = to_app(val);
|
||||
if (!dt.is_constructor(m_val)) {
|
||||
// assert: var does not occur in lits.
|
||||
|
|
@ -61,7 +61,7 @@ namespace mbp {
|
|||
}
|
||||
}
|
||||
catch (const cant_project &) {
|
||||
TRACE("qe", tout << "can't project:" << mk_pp(var, m) << "\n";);
|
||||
TRACE(qe, tout << "can't project:" << mk_pp(var, m) << "\n";);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -82,7 +82,7 @@ namespace mbp {
|
|||
args.push_back(arg);
|
||||
}
|
||||
val = m.mk_app(f, args.size(), args.data());
|
||||
TRACE("qe", tout << mk_pp(m_var->x(), m) << " |-> " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(m_var->x(), m) << " |-> " << val << "\n";);
|
||||
reduce(val, lits);
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ namespace mbp {
|
|||
th_rewriter rw(m);
|
||||
expr_ref tmp(m);
|
||||
sub.insert(m_var->x(), val);
|
||||
TRACE("qe", tout << mk_pp(m_var->x(), m) << " = " << mk_pp(val, m) << "\n";
|
||||
TRACE(qe, tout << mk_pp(m_var->x(), m) << " = " << mk_pp(val, m) << "\n";
|
||||
tout << lits << "\n";);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
sub(lits[i].get(), tmp);
|
||||
|
|
@ -211,7 +211,7 @@ namespace mbp {
|
|||
reduced = true;
|
||||
}
|
||||
}
|
||||
CTRACE("qe", reduced, tout << vars << "\n" << lits << "\n";);
|
||||
CTRACE(qe, reduced, tout << vars << "\n" << lits << "\n";);
|
||||
}
|
||||
return reduced;
|
||||
}
|
||||
|
|
@ -274,10 +274,10 @@ namespace mbp {
|
|||
if (has_v) {
|
||||
has_var.mark(f);
|
||||
}
|
||||
TRACE("qe", tout << "contains: " << mk_pp(f, m) << " " << has_var.is_marked(f) << "\n";);
|
||||
TRACE(qe, tout << "contains: " << mk_pp(f, m) << " " << has_var.is_marked(f) << "\n";);
|
||||
visited.mark(f);
|
||||
}
|
||||
TRACE("qe", tout << "contains: " << mk_pp(e, m) << " " << has_var.is_marked(e) << "\n";);
|
||||
TRACE(qe, tout << "contains: " << mk_pp(e, m) << " " << has_var.is_marked(e) << "\n";);
|
||||
return has_var.is_marked(e);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ struct mbp_dt_tg::impl {
|
|||
SASSERT(is_app(term) &&
|
||||
m_dt_util.is_accessor(to_app(term)->get_decl()) &&
|
||||
has_var(to_app(term)->get_arg(0)));
|
||||
TRACE("mbp_tg", tout << "applying rm_accessor on " << expr_ref(term, m););
|
||||
TRACE(mbp_tg, tout << "applying rm_accessor on " << expr_ref(term, m););
|
||||
expr *v = to_app(term)->get_arg(0);
|
||||
expr_ref sel(m);
|
||||
app_ref u(m);
|
||||
|
|
@ -107,7 +107,7 @@ struct mbp_dt_tg::impl {
|
|||
// rewrite cons(v, u) = x with v = head(x) and u = tail(x)
|
||||
// where u or v contain variables
|
||||
void deconstruct_eq(expr *cons, expr *rhs) {
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "applying deconstruct_eq on " << expr_ref(cons, m););
|
||||
ptr_vector<func_decl> const *accessors =
|
||||
m_dt_util.get_constructor_accessors(to_app(cons)->get_decl());
|
||||
|
|
@ -125,7 +125,7 @@ struct mbp_dt_tg::impl {
|
|||
// rewrite cons(v, u) != x into one of !cons(x) or v != head(x) or u !=
|
||||
// tail(x) where u or v contain variables
|
||||
void deconstruct_neq(expr *cons, expr *rhs) {
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "applying deconstruct_neq on " << expr_ref(cons, m););
|
||||
ptr_vector<func_decl> const *accessors =
|
||||
m_dt_util.get_constructor_accessors(to_app(cons)->get_decl());
|
||||
|
|
@ -153,7 +153,7 @@ struct mbp_dt_tg::impl {
|
|||
expr *cons, *rhs, *f, *term;
|
||||
bool progress = false;
|
||||
m_new_vars.reset();
|
||||
TRACE("mbp_tg", tout << "Iterating over terms of tg";);
|
||||
TRACE(mbp_tg, tout << "Iterating over terms of tg";);
|
||||
// Not resetting terms because get_terms calls resize on terms
|
||||
m_tg.get_terms(terms, false);
|
||||
for (unsigned i = 0; i < terms.size(); i++) {
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ namespace mbp {
|
|||
todo.push_back({ ax->get_arg(i), ay->get_arg(i) });
|
||||
}
|
||||
|
||||
TRACE("qe", tout << "unification attempt\n";
|
||||
TRACE(qe, tout << "unification attempt\n";
|
||||
for (auto [a, b] : todo)
|
||||
tout << mk_pp(a, m) << " == " << mk_pp(b, m) << "\n";
|
||||
for (auto [key, value] : soln)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ namespace mbp {
|
|||
for (expr* e1 : *alit) {
|
||||
expr* e2;
|
||||
val = model(e1);
|
||||
TRACE("qe", tout << mk_pp(e1, m) << " |-> " << val << "\n";);
|
||||
TRACE(qe, tout << mk_pp(e1, m) << " |-> " << val << "\n";);
|
||||
if (val2expr.find(val, e2)) {
|
||||
return expr_ref(m.mk_eq(e1, e2), m);
|
||||
}
|
||||
|
|
@ -193,8 +193,8 @@ namespace mbp {
|
|||
expr_ref val(m);
|
||||
model_evaluator eval(model);
|
||||
eval.set_expand_array_equalities(true);
|
||||
TRACE("qe", tout << fmls << "\n";);
|
||||
DEBUG_CODE(for (expr* fml : fmls) { CTRACE("qe", m.is_false(eval(fml)), tout << mk_pp(fml, m) << " is false\n" << model;); SASSERT(!m.is_false(eval(fml))); });
|
||||
TRACE(qe, tout << fmls << "\n";);
|
||||
DEBUG_CODE(for (expr* fml : fmls) { CTRACE(qe, m.is_false(eval(fml)), tout << mk_pp(fml, m) << " is false\n" << model;); SASSERT(!m.is_false(eval(fml))); });
|
||||
|
||||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
expr* nfml, * fml = fmls.get(i);
|
||||
|
|
@ -205,11 +205,11 @@ namespace mbp {
|
|||
else
|
||||
extract_bools(eval, fmls, i, fml, true);
|
||||
}
|
||||
TRACE("qe", tout << "fmls: " << fmls << "\n";);
|
||||
TRACE(qe, tout << "fmls: " << fmls << "\n";);
|
||||
}
|
||||
|
||||
void project_plugin::extract_bools(model_evaluator& eval, expr_ref_vector& fmls, unsigned idx, expr* fml, bool is_true) {
|
||||
TRACE("qe", tout << "extract bools: " << mk_pp(fml, m) << "\n";);
|
||||
TRACE(qe, tout << "extract bools: " << mk_pp(fml, m) << "\n";);
|
||||
if (!is_app(fml))
|
||||
return;
|
||||
m_to_visit.reset();
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public:
|
|||
init(vars, fml, mdl);
|
||||
// Apply MBP rules till saturation
|
||||
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "mbp tg " << m_tg.get_lits() << "\nand vars " << vars << "\n";);
|
||||
|
||||
// First, apply rules without splitting on model
|
||||
|
|
@ -137,9 +137,9 @@ public:
|
|||
// Do complete mbp
|
||||
saturate(vars);
|
||||
|
||||
TRACE("mbp_tg",
|
||||
TRACE(mbp_tg,
|
||||
tout << "mbp tg " << m_tg.get_lits() << " and vars " << vars << "\n";);
|
||||
TRACE("mbp_tg_verbose", obj_hashtable<app> vars_tmp;
|
||||
TRACE(mbp_tg_verbose, obj_hashtable<app> vars_tmp;
|
||||
collect_uninterp_consts(mk_and(m_tg.get_lits()), vars_tmp);
|
||||
for (auto a : vars_tmp)
|
||||
tout << mk_pp(a->get_decl(), m) << "\n";
|
||||
|
|
@ -173,7 +173,7 @@ public:
|
|||
for (auto v : vars)
|
||||
if (is_red(v))
|
||||
red_vars.mark(v);
|
||||
CTRACE("mbp_tg", !core_vars.empty(), tout << "vars not redundant ";
|
||||
CTRACE(mbp_tg, !core_vars.empty(), tout << "vars not redundant ";
|
||||
for (auto v : core_vars) tout << " " << app_ref(v, m);
|
||||
tout << "\n";);
|
||||
|
||||
|
|
@ -188,14 +188,14 @@ public:
|
|||
// Step 3.
|
||||
m_tg.qel(vars, fml, &non_core);
|
||||
|
||||
CTRACE("mbp_tg", !vars.empty(),
|
||||
CTRACE(mbp_tg, !vars.empty(),
|
||||
tout << "before substitution " << fml << "\n";);
|
||||
// for all remaining non-cgr bool, dt, array variables, add v = mdl(v)
|
||||
expr_sparse_mark s_vars;
|
||||
for (auto v : vars) {
|
||||
if (m_dt_util.is_datatype(v->get_sort()) ||
|
||||
m_array_util.is_array(v) || m.is_bool(v)) {
|
||||
CTRACE("mbp_tg",
|
||||
CTRACE(mbp_tg,
|
||||
m_array_util.is_array(v) ||
|
||||
m_dt_util.is_datatype(v->get_sort()),
|
||||
tout << "Could not eliminate " << v->get_name()
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ namespace mbp {
|
|||
v = e;
|
||||
a_val = rational(1)/a_val;
|
||||
t = mk_term(is_int, a_val, sign, done);
|
||||
TRACE("qe", tout << mk_pp(e, m) << " := " << t << "\n";);
|
||||
TRACE(qe, tout << mk_pp(e, m) << " := " << t << "\n";);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -390,7 +390,7 @@ void term_graph::add_deq_proc::inc_count() {
|
|||
bool term_graph::is_variable_proc::operator()(const expr *e) const {
|
||||
if (!is_app(e)) return false;
|
||||
const app *a = ::to_app(e);
|
||||
TRACE("qe_verbose", tout << a->get_family_id() << " "
|
||||
TRACE(qe_verbose, tout << a->get_family_id() << " "
|
||||
<< m_solved.contains(a->get_decl()) << " "
|
||||
<< m_decls.contains(a->get_decl()) << "\n";);
|
||||
return a->get_family_id() == null_family_id &&
|
||||
|
|
@ -773,7 +773,7 @@ void term_graph::mk_qe_lite_equalities(term &t, expr_ref_vector &out,
|
|||
rep = mk_app(t);
|
||||
if (contains_nc(rep)) {
|
||||
TRACE(
|
||||
"qe_debug", tout << "repr not in core " << t;
|
||||
qe_debug, tout << "repr not in core " << t;
|
||||
for (term *it = &t.get_next(); it != &t;
|
||||
it = &it->get_next()) { tout << *it << "\n"; };);
|
||||
DEBUG_CODE(
|
||||
|
|
@ -1091,7 +1091,7 @@ class term_graph::projector {
|
|||
expr_ref_vector m_pinned; // tracks expr in the maps
|
||||
|
||||
expr *mk_pure(term const &t) {
|
||||
TRACE("qe", t.display(tout));
|
||||
TRACE(qe, t.display(tout));
|
||||
expr *e = nullptr;
|
||||
if (find_term2app(t, e))
|
||||
return e;
|
||||
|
|
@ -1109,7 +1109,7 @@ class term_graph::projector {
|
|||
kids.push_back(e);
|
||||
else
|
||||
return nullptr;
|
||||
TRACE("qe_verbose", tout << *ch << " -> " << mk_pp(e, m) << "\n";);
|
||||
TRACE(qe_verbose, tout << *ch << " -> " << mk_pp(e, m) << "\n";);
|
||||
}
|
||||
expr_ref pure = m_rewriter.mk_app(a->get_decl(), kids.size(), kids.data());
|
||||
m_pinned.push_back(pure);
|
||||
|
|
@ -1183,7 +1183,7 @@ class term_graph::projector {
|
|||
for (auto *lit : m_tg.m_lits)
|
||||
if (!m.is_eq(lit) && find_app(lit, e))
|
||||
res.push_back(e);
|
||||
TRACE("qe", tout << "literals: " << res << "\n";);
|
||||
TRACE(qe, tout << "literals: " << res << "\n";);
|
||||
}
|
||||
|
||||
void lits2pure(expr_ref_vector &res) {
|
||||
|
|
@ -1194,14 +1194,14 @@ class term_graph::projector {
|
|||
if (p1 != p2) res.push_back(m.mk_eq(p1, p2));
|
||||
}
|
||||
else
|
||||
TRACE("qe", tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
}
|
||||
else if (m.is_not(lit, e) && m.is_eq(e, e1, e2)) {
|
||||
if (find_app(e1, p1) && find_app(e2, p2)) {
|
||||
res.push_back(mk_neq(m, p1, p2));
|
||||
}
|
||||
else
|
||||
TRACE("qe", tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
}
|
||||
else if (m.is_distinct(lit)) {
|
||||
ptr_buffer<expr> diff;
|
||||
|
|
@ -1210,15 +1210,15 @@ class term_graph::projector {
|
|||
if (diff.size() > 1)
|
||||
res.push_back(m.mk_distinct(diff.size(), diff.data()));
|
||||
else
|
||||
TRACE("qe", tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
}
|
||||
else if (find_app(lit, p1))
|
||||
res.push_back(p1);
|
||||
else
|
||||
TRACE("qe", tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
TRACE(qe, tout << "skipping " << mk_pp(lit, m) << "\n";);
|
||||
}
|
||||
remove_duplicates(res);
|
||||
TRACE("qe", tout << "literals: " << res << "\n";);
|
||||
TRACE(qe, tout << "literals: " << res << "\n";);
|
||||
}
|
||||
|
||||
void remove_duplicates(expr_ref_vector &v) {
|
||||
|
|
@ -1291,7 +1291,7 @@ class term_graph::projector {
|
|||
if (roots.size() > 1) {
|
||||
ptr_buffer<expr> args;
|
||||
for (expr *r : roots) { args.push_back(r); }
|
||||
TRACE("qe", tout << "function: " << d->get_name() << "\n";);
|
||||
TRACE(qe, tout << "function: " << d->get_name() << "\n";);
|
||||
res.push_back(m.mk_distinct(args.size(), args.data()));
|
||||
}
|
||||
}
|
||||
|
|
@ -1301,7 +1301,7 @@ class term_graph::projector {
|
|||
void mk_distinct(expr_ref_vector &res) {
|
||||
collect_decl2terms();
|
||||
args_are_distinct(res);
|
||||
TRACE("qe", tout << res << "\n";);
|
||||
TRACE(qe, tout << res << "\n";);
|
||||
}
|
||||
|
||||
void mk_pure_equalities(const term &t, expr_ref_vector &res) {
|
||||
|
|
@ -1353,7 +1353,7 @@ class term_graph::projector {
|
|||
else
|
||||
mk_unpure_equalities(*t, res);
|
||||
}
|
||||
TRACE("qe", tout << "literals: " << res << "\n";);
|
||||
TRACE(qe, tout << "literals: " << res << "\n";);
|
||||
}
|
||||
|
||||
void mk_pure_equalities(expr_ref_vector &res) { mk_equalities<true>(res); }
|
||||
|
|
@ -1412,7 +1412,7 @@ class term_graph::projector {
|
|||
res.push_back(m.mk_distinct(j - i, reps.data() + i));
|
||||
i = j;
|
||||
}
|
||||
TRACE("qe", tout << "after distinct: " << res << "\n";);
|
||||
TRACE(qe, tout << "after distinct: " << res << "\n";);
|
||||
}
|
||||
|
||||
std::ostream &display(std::ostream &out) const {
|
||||
|
|
@ -1567,7 +1567,7 @@ public:
|
|||
if (!pure) continue;
|
||||
|
||||
add_term2app(*t, pure);
|
||||
TRACE("qe_verbose",
|
||||
TRACE(qe_verbose,
|
||||
tout << "purified " << *t << " " << mk_pp(pure, m) << "\n";);
|
||||
expr *rep = nullptr; // ensure that the root has a representative
|
||||
m_root2rep.find(t->get_root().get_id(), rep);
|
||||
|
|
@ -1592,7 +1592,7 @@ public:
|
|||
// and can be mined using other means, such as theory
|
||||
// aware core minimization
|
||||
m_tg.reset_marks();
|
||||
TRACE("qe", display(tout << "after purify\n"););
|
||||
TRACE(qe, display(tout << "after purify\n"););
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1689,7 +1689,7 @@ void term_graph::add_model_based_terms(model &mdl,
|
|||
}
|
||||
}
|
||||
TRACE(
|
||||
"qe", for (auto &es
|
||||
qe, for (auto &es
|
||||
: equivs) {
|
||||
tout << "equiv: ";
|
||||
for (expr *t : es) tout << expr_ref(t, m) << " ";
|
||||
|
|
@ -1708,7 +1708,7 @@ expr* term_graph::rep_of(expr *e) {
|
|||
}
|
||||
|
||||
expr_ref_vector term_graph::dcert(model &mdl, expr_ref_vector const &lits) {
|
||||
TRACE("qe", tout << "dcert " << lits << "\n";);
|
||||
TRACE(qe, tout << "dcert " << lits << "\n";);
|
||||
struct pair_t {
|
||||
expr *a, *b;
|
||||
pair_t() : a(nullptr), b(nullptr) {}
|
||||
|
|
@ -1806,7 +1806,7 @@ expr_ref_vector term_graph::dcert(model &mdl, expr_ref_vector const &lits) {
|
|||
}
|
||||
}
|
||||
}
|
||||
TRACE("qe", tout << result << "\n";);
|
||||
TRACE(qe, tout << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue