mirror of
https://github.com/Z3Prover/z3
synced 2025-08-07 19:51:22 +00:00
* fixing issue #4651 * regression fix * fix #4662 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reenabled lift_ites_throttled with an additional filter, without the filter finding the model in report #4651 goes from .02s to 20s, also updated pretty printing of regexes to be more accurate * removing temp testing variable * Allow to skip System.loadLibrary() calls from Java Native class (#4667) * using intended utility methods for sort detection * adding ack/model Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add smt params dependency Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * missing file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * deps Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * order Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * persist fields Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * dbg build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * reset caches Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * sr Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix cmake build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * shuffle dependencies Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * warnings /errors Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * update include Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * missing cmakelists Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * update cmake Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add depend Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * add depend Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * virtual method Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * path Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * move parameters from ast/rewriter to params Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * move fpa Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix warnings Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove pragma Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * dbg Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * updated sat_smt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix #4651 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * encoding options #4665 Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * expose name inclusion as optional Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix misc issues around #4661 introduced when adding lazy push/pop to selected theories Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * remove lazy push from theory_lra Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * fix dotnet build Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * release nodes Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * free memory in egraph Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * avoid duplicate class names frame in sat_scc and sat_smt Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * adding euf Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * elaborate on smt/drat format outline, expose euf mode as config Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * mk-var during copy Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * move theory_var_list into id_var_list and utilities from smt-enode into it, prepare for theory variables in egraph Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * with bounded Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * Remove duplicate binary condition. Fixes #4668. * butterfly effect on fp? Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * prepare for theory plugins Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * file Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * build fix * remove SMTFD Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * na Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com> * SMTFD is back (#4676) * fixing issue #4651 * regression fix * reenabled lift_ites_throttled with an additional filter, without the filter finding the model in report #4651 goes from .02s to 20s, also updated pretty printing of regexes to be more accurate * removing temp testing variable * using intended utility methods for sort detection * misc edits related to nonground regexes * bug fix of state id off by 1 calculation error and improved pretty printing with regex tooltip generated in dgml state graph * removed unused method declaration * improved id to regex value map info in generated dgml * reorgd callback function for state pretty printer * updated some comments Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com> Co-authored-by: Sergey Vladimirov <vlsergey@gmail.com> Co-authored-by: Christoph M. Wintersteiger <cwinter@microsoft.com> Co-authored-by: Arie Gurfinkel <arie.gurfinkel@gmail.com>
215 lines
7.1 KiB
C++
215 lines
7.1 KiB
C++
/*++
|
|
Copyright (c) 2020 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
state_graph.h
|
|
|
|
Abstract:
|
|
|
|
Data structure for incrementally tracking "live" and "dead" states in an
|
|
abstract transition system.
|
|
|
|
Author:
|
|
|
|
Caleb Stanford (calebstanford-msr / cdstanford) 2020-7
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
#include "util/map.h"
|
|
#include "util/uint_set.h"
|
|
#include "util/union_find.h"
|
|
#include "util/vector.h"
|
|
|
|
/*
|
|
state_graph
|
|
|
|
Data structure which is capable of incrementally tracking
|
|
live states and dead states.
|
|
|
|
"States" are integers. States and edges are added to the data
|
|
structure incrementally.
|
|
- States can be marked as "live" or "done".
|
|
"Done" signals that (1) no more outgoing edges will be
|
|
added and (2) the state will not be marked as live. The data
|
|
structure then tracks
|
|
which other states are live (can reach a live state), dead
|
|
(can't reach a live state), or neither.
|
|
- Some edges are labeled as not contained in a cycle. This is to
|
|
optimize search if it is known by the user of the structure
|
|
that no cycle will ever contain this edge.
|
|
|
|
Internally, we use union_find to identify states within an SCC,
|
|
and incrementally update SCCs, while propagating backwards
|
|
live and dead SCCs.
|
|
*/
|
|
class state_graph {
|
|
public:
|
|
/* Wrapper for custom callback function for pretty printing states */
|
|
struct state_pp {
|
|
/* Pointer to object that owns m_pp_state, it must be passed as the first argument to m_pp_state */
|
|
void* m_printer;
|
|
/* Pointer to function that pretty prints a state label into the stream (html-encoded if the last argument is true) */
|
|
void (*m_pp_state)(void*, std::ostream&, unsigned, bool);
|
|
state_pp(
|
|
/* Pointer to object that owns f */
|
|
void* p,
|
|
/* Pointer to function that pretty prints a state label into the stream (html-encoded if the last argument is true) */
|
|
void (*f)(void*, std::ostream&, unsigned, bool)) : m_printer(p), m_pp_state(f) {}
|
|
|
|
/* call back to m_printer using m_pp_state to pretty print state_id to the given stream (html-encoded by default) */
|
|
std::ostream& pp_state_label(std::ostream& out, unsigned state_id, bool html_encode = true) const {
|
|
if (m_printer && m_pp_state)
|
|
(*m_pp_state)(m_printer, out, state_id, html_encode);
|
|
return out;
|
|
}
|
|
};
|
|
|
|
typedef unsigned state;
|
|
typedef uint_set state_set;
|
|
typedef u_map<state_set> edge_rel;
|
|
typedef basic_union_find state_ufind;
|
|
|
|
private:
|
|
/*
|
|
All states are internally exactly one of:
|
|
- live: known to reach a live state
|
|
- dead: known to never reach a live state
|
|
- unknown: all outgoing edges have been added, but the
|
|
state is not known to be live or dead
|
|
- unexplored: not all outgoing edges have been added
|
|
|
|
As SCCs are merged, some states become aliases, and a
|
|
union find data structure collapses a now obsolete
|
|
state to its current representative. m_seen keeps track
|
|
of states we have seen, including obsolete states.
|
|
*/
|
|
state_set m_live;
|
|
state_set m_dead;
|
|
state_set m_unknown;
|
|
state_set m_unexplored;
|
|
|
|
state_set m_seen;
|
|
state_ufind m_state_ufind;
|
|
|
|
/*
|
|
Edges are saved in both from and to maps.
|
|
A subset of edges are also marked as possibly being
|
|
part of a cycle by being stored in m_sources_maybecycle.
|
|
*/
|
|
edge_rel m_sources;
|
|
edge_rel m_targets;
|
|
edge_rel m_sources_maybecycle;
|
|
|
|
/*
|
|
Pretty printer for states
|
|
*/
|
|
state_pp m_state_pp;
|
|
|
|
/*
|
|
CLASS INVARIANTS
|
|
|
|
*** To enable checking invariants, run z3 with -dbg:state_graph
|
|
(must also be in debug mode) ***
|
|
|
|
State invariants:
|
|
- live, dead, unknown, and unexplored form a partition of
|
|
the set of roots in m_state_ufind
|
|
- all of these are subsets of m_seen
|
|
- everything in m_seen is an integer less than the number of variables
|
|
in m_state_ufind
|
|
|
|
Edge invariants:
|
|
- all edges are between roots of m_state_ufind
|
|
- m_sources and m_targets are converses of each other
|
|
- no self-loops
|
|
- m_sources_maybecycle is a subrelation of m_sources
|
|
|
|
Relationship between states and edges:
|
|
- every state with a live target is live
|
|
- every state with a dead source is dead
|
|
- every state with only dead targets is dead
|
|
- there are no cycles of unknown states on maybecycle edges
|
|
*/
|
|
#ifdef Z3DEBUG
|
|
bool is_subset(state_set set1, state_set set2) const;
|
|
bool is_disjoint(state_set set1, state_set set2) const;
|
|
bool check_invariant() const;
|
|
/*
|
|
Output the whole state graph in dgml format into the file '.z3-state-graph.dgml'
|
|
*/
|
|
bool write_dgml();
|
|
/*
|
|
Output the whole state graph in dot format into the file '.z3-state-graph.dot'
|
|
*/
|
|
bool write_dot();
|
|
#endif
|
|
|
|
/*
|
|
'Core' functions that modify the plain graph, without
|
|
updating SCCs or propagating live/dead state information.
|
|
These are for internal use only.
|
|
*/
|
|
void add_state_core(state s); // unexplored + seen
|
|
void remove_state_core(state s); // unknown + seen -> seen
|
|
void mark_unknown_core(state s); // unexplored -> unknown
|
|
void mark_live_core(state s); // unknown -> live
|
|
void mark_dead_core(state s); // unknown -> dead
|
|
|
|
void add_edge_core(state s1, state s2, bool maybecycle);
|
|
void remove_edge_core(state s1, state s2);
|
|
void rename_edge_core(state old1, state old2, state new1, state new2);
|
|
|
|
state merge_states(state s1, state s2);
|
|
state merge_states(state_set& s_set);
|
|
|
|
/*
|
|
Algorithmic search routines
|
|
- live state propagation
|
|
- dead state propagation
|
|
- cycle / strongly-connected component detection
|
|
*/
|
|
void mark_live_recursive(state s);
|
|
bool all_targets_dead(state s);
|
|
void mark_dead_recursive(state s);
|
|
state merge_all_cycles(state s);
|
|
|
|
public:
|
|
state_graph(state_pp p):
|
|
m_live(), m_dead(), m_unknown(), m_unexplored(), m_seen(),
|
|
m_state_ufind(), m_sources(), m_targets(), m_sources_maybecycle(), m_state_pp(p)
|
|
{
|
|
CASSERT("state_graph", check_invariant());
|
|
}
|
|
|
|
/*
|
|
Exposed methods
|
|
|
|
These methods may be called in any order, as long as:
|
|
- states are added before edges are added between them
|
|
- outgoing edges are not added from a done state
|
|
- a done state is not marked as live
|
|
- edges are not added creating a cycle containing an edge with
|
|
maybecycle = false (this is not necessary for soundness, but
|
|
prevents completeness for successfully detecting dead states)
|
|
*/
|
|
void add_state(state s);
|
|
void add_edge(state s1, state s2, bool maybecycle);
|
|
void mark_live(state s);
|
|
void mark_done(state s);
|
|
|
|
bool is_seen(state s) const;
|
|
bool is_live(state s) const;
|
|
bool is_dead(state s) const;
|
|
bool is_done(state s) const;
|
|
|
|
unsigned get_size() const;
|
|
|
|
/*
|
|
Pretty printing
|
|
*/
|
|
std::ostream& display(std::ostream& o) const;
|
|
|
|
};
|