3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-03-02 03:36:53 +00:00
z3/src/ast/euf/euf_enode.cpp
LeeYoungJoon 0a93ff515d
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).
2025-05-28 14:31:25 +01:00

165 lines
4.6 KiB
C++

/*++
Copyright (c) 2020 Microsoft Corporation
Module Name:
euf_enode.cpp
Abstract:
enode layer
Author:
Nikolaj Bjorner (nbjorner) 2020-08-23
--*/
#include "ast/euf/euf_enode.h"
#include "ast/euf/euf_egraph.h"
namespace euf {
void enode::invariant(egraph& g) {
unsigned class_size = 0;
bool found_root = false;
bool found_this = false;
for (enode* c : enode_class(this)) {
VERIFY(c->m_root == m_root);
found_root |= c == m_root;
found_this |= c == this;
++class_size;
}
VERIFY(found_root);
VERIFY(found_this);
VERIFY(this != m_root || class_size == m_class_size);
if (is_root()) {
VERIFY(!m_target);
for (enode* p : enode_parents(this)) {
if (!p->cgc_enabled())
continue;
bool found = false;
for (enode* arg : enode_args(p)) {
found |= arg->get_root() == this;
}
CTRACE(euf, !found, tout << g.bpp(p) << " does not have a child with root: " << g.bpp(this) << "\n";);
VERIFY(found);
}
for (enode* c : enode_class(this)) {
if (c == this)
continue;
for (enode* p : enode_parents(c)) {
if (!p->cgc_enabled())
continue;
bool found = false;
for (enode* q : enode_parents(this)) {
found |= p->congruent(q);
}
CTRACE(euf, !found, tout << "parent " << g.bpp(p) << " of " << g.bpp(c) << " is not congruent to a parent of " << g.bpp(this) << "\n";);
VERIFY(found);
}
}
}
}
bool enode::congruent(enode* n) const {
if (get_decl() != n->get_decl())
return false;
if (num_args() != n->num_args())
return false;
SASSERT(!m_commutative || num_args() == 2);
if (m_commutative &&
get_arg(0)->get_root() == n->get_arg(1)->get_root() &&
get_arg(1)->get_root() == n->get_arg(0)->get_root())
return true;
for (unsigned i = num_args(); i-- > 0; )
if (get_arg(i)->get_root() != n->get_arg(i)->get_root())
return false;
return true;
}
/*
* Find the theory var that that is heuristically
* linked with the fewest equality justifications.
*/
theory_var enode::get_closest_th_var(theory_id id) const {
enode const* n = this;
while (n) {
theory_var v = n->get_th_var(id);
if (v != null_theory_var)
return v;
n = n->m_target;
}
return null_theory_var;
}
enode* enode::get_closest_th_node(theory_id id) {
enode* n = this;
while (n) {
theory_var v = n->get_th_var(id);
if (v != null_theory_var)
return n;
n = n->m_target;
}
return nullptr;
}
bool enode::acyclic() const {
enode const* n = this;
enode const* p = this;
while (n) {
n = n->m_target;
if (n) {
p = p->m_target;
n = n->m_target;
}
if (n == p)
return false;
}
return true;
}
bool enode::reaches(enode* n) const {
enode const* r = this;
SASSERT(acyclic());
while (r) {
if (r == n)
return true;
r = r->m_target;
}
return false;
}
void enode::reverse_justification() {
enode* curr = m_target;
enode* prev = this;
justification js = m_justification;
prev->m_target = nullptr;
prev->m_justification = justification::axiom(null_theory_id);
while (curr != nullptr) {
enode* new_curr = curr->m_target;
justification new_js = curr->m_justification;
curr->m_target = prev;
curr->m_justification = js;
prev = curr;
js = new_js;
curr = new_curr;
}
}
bool enode::children_are_roots() const {
for (auto* child : enode_args(this))
if (!child->is_root())
return false;
return true;
}
unsigned enode::class_generation() {
unsigned gen = m_generation;
for (enode* n : enode_class(this))
gen = std::min(n->generation(), gen);
return gen;
}
}