mirror of
https://github.com/Z3Prover/z3
synced 2025-04-12 12:08:18 +00:00
Merge branch 'opt' of https://git01.codeplex.com/z3 into opt
This commit is contained in:
commit
596796f7ef
|
@ -17,6 +17,7 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
#include<iostream>
|
||||||
#include<sstream>
|
#include<sstream>
|
||||||
|
#include<vector>
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -114,7 +114,7 @@ static void get_interpolant_and_maybe_check(cmd_context & ctx, expr * t, params_
|
||||||
|
|
||||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||||
ptr_vector<ast> cnsts(end - it);
|
ptr_vector<ast> cnsts((unsigned)(end - it));
|
||||||
for (int i = 0; it != end; ++it, ++i)
|
for (int i = 0; it != end; ++it, ++i)
|
||||||
cnsts[i] = *it;
|
cnsts[i] = *it;
|
||||||
|
|
||||||
|
@ -139,10 +139,11 @@ static void get_interpolant(cmd_context & ctx, expr * t, params_ref &m_params) {
|
||||||
get_interpolant_and_maybe_check(ctx,t,m_params,false);
|
get_interpolant_and_maybe_check(ctx,t,m_params,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void get_and_check_interpolant(cmd_context & ctx, params_ref &m_params, expr * t) {
|
static void get_and_check_interpolant(cmd_context & ctx, params_ref &m_params, expr * t) {
|
||||||
get_interpolant_and_maybe_check(ctx,t,m_params,true);
|
get_interpolant_and_maybe_check(ctx,t,m_params,true);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void compute_interpolant_and_maybe_check(cmd_context & ctx, expr * t, params_ref &m_params, bool check){
|
static void compute_interpolant_and_maybe_check(cmd_context & ctx, expr * t, params_ref &m_params, bool check){
|
||||||
|
|
||||||
|
|
|
@ -36,12 +36,11 @@ namespace Duality {
|
||||||
struct Z3User {
|
struct Z3User {
|
||||||
|
|
||||||
context &ctx;
|
context &ctx;
|
||||||
solver &slvr;
|
|
||||||
|
|
||||||
typedef func_decl FuncDecl;
|
typedef func_decl FuncDecl;
|
||||||
typedef expr Term;
|
typedef expr Term;
|
||||||
|
|
||||||
Z3User(context &_ctx, solver &_slvr) : ctx(_ctx), slvr(_slvr){}
|
Z3User(context &_ctx) : ctx(_ctx){}
|
||||||
|
|
||||||
const char *string_of_int(int n);
|
const char *string_of_int(int n);
|
||||||
|
|
||||||
|
@ -53,6 +52,8 @@ namespace Duality {
|
||||||
|
|
||||||
Term SubstRec(hash_map<ast, Term> &memo, const Term &t);
|
Term SubstRec(hash_map<ast, Term> &memo, const Term &t);
|
||||||
|
|
||||||
|
Term SubstRec(hash_map<ast, Term> &memo, hash_map<func_decl, func_decl> &map, const Term &t);
|
||||||
|
|
||||||
void Strengthen(Term &x, const Term &y);
|
void Strengthen(Term &x, const Term &y);
|
||||||
|
|
||||||
// return the func_del of an app if it is uninterpreted
|
// return the func_del of an app if it is uninterpreted
|
||||||
|
@ -77,14 +78,14 @@ namespace Duality {
|
||||||
|
|
||||||
void Summarize(const Term &t);
|
void Summarize(const Term &t);
|
||||||
|
|
||||||
int CumulativeDecisions();
|
|
||||||
|
|
||||||
int CountOperators(const Term &t);
|
int CountOperators(const Term &t);
|
||||||
|
|
||||||
Term SubstAtom(hash_map<ast, Term> &memo, const expr &t, const expr &atom, const expr &val);
|
Term SubstAtom(hash_map<ast, Term> &memo, const expr &t, const expr &atom, const expr &val);
|
||||||
|
|
||||||
Term RemoveRedundancy(const Term &t);
|
Term RemoveRedundancy(const Term &t);
|
||||||
|
|
||||||
|
Term IneqToEq(const Term &t);
|
||||||
|
|
||||||
bool IsLiteral(const expr &lit, expr &atom, expr &val);
|
bool IsLiteral(const expr &lit, expr &atom, expr &val);
|
||||||
|
|
||||||
expr Negate(const expr &f);
|
expr Negate(const expr &f);
|
||||||
|
@ -98,7 +99,10 @@ namespace Duality {
|
||||||
bool IsClosedFormula(const Term &t);
|
bool IsClosedFormula(const Term &t);
|
||||||
|
|
||||||
Term AdjustQuantifiers(const Term &t);
|
Term AdjustQuantifiers(const Term &t);
|
||||||
private:
|
|
||||||
|
FuncDecl RenumberPred(const FuncDecl &f, int n);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
void SummarizeRec(hash_set<ast> &memo, std::vector<expr> &lits, int &ops, const Term &t);
|
void SummarizeRec(hash_set<ast> &memo, std::vector<expr> &lits, int &ops, const Term &t);
|
||||||
int CountOperatorsRec(hash_set<ast> &memo, const Term &t);
|
int CountOperatorsRec(hash_set<ast> &memo, const Term &t);
|
||||||
|
@ -108,6 +112,7 @@ private:
|
||||||
expr ReduceAndOr(const std::vector<expr> &args, bool is_and, std::vector<expr> &res);
|
expr ReduceAndOr(const std::vector<expr> &args, bool is_and, std::vector<expr> &res);
|
||||||
expr FinishAndOr(const std::vector<expr> &args, bool is_and);
|
expr FinishAndOr(const std::vector<expr> &args, bool is_and);
|
||||||
expr PullCommonFactors(std::vector<expr> &args, bool is_and);
|
expr PullCommonFactors(std::vector<expr> &args, bool is_and);
|
||||||
|
Term IneqToEqRec(hash_map<ast, Term> &memo, const Term &t);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -256,9 +261,9 @@ private:
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iZ3LogicSolver(context &c) : LogicSolver(c) {
|
iZ3LogicSolver(context &c, bool models = true) : LogicSolver(c) {
|
||||||
ctx = ictx = &c;
|
ctx = ictx = &c;
|
||||||
slvr = islvr = new interpolating_solver(*ictx);
|
slvr = islvr = new interpolating_solver(*ictx, models);
|
||||||
need_goals = false;
|
need_goals = false;
|
||||||
islvr->SetWeakInterpolants(true);
|
islvr->SetWeakInterpolants(true);
|
||||||
}
|
}
|
||||||
|
@ -308,8 +313,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
LogicSolver *ls;
|
LogicSolver *ls;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
int nodeCount;
|
int nodeCount;
|
||||||
int edgeCount;
|
int edgeCount;
|
||||||
|
|
||||||
|
@ -324,7 +329,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
model dualModel;
|
model dualModel;
|
||||||
private:
|
protected:
|
||||||
literals dualLabels;
|
literals dualLabels;
|
||||||
std::list<stack_entry> stack;
|
std::list<stack_entry> stack;
|
||||||
std::vector<Term> axioms; // only saved here for printing purposes
|
std::vector<Term> axioms; // only saved here for printing purposes
|
||||||
|
@ -340,7 +345,7 @@ private:
|
||||||
inherit the axioms.
|
inherit the axioms.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx), *(_ls->slvr)), dualModel(*(_ls->ctx)), aux_solver(_ls->aux_solver)
|
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx)), dualModel(*(_ls->ctx)), aux_solver(_ls->aux_solver)
|
||||||
{
|
{
|
||||||
ls = _ls;
|
ls = _ls;
|
||||||
nodeCount = 0;
|
nodeCount = 0;
|
||||||
|
@ -350,7 +355,7 @@ private:
|
||||||
proof_core = 0;
|
proof_core = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~RPFP();
|
virtual ~RPFP();
|
||||||
|
|
||||||
/** Symbolic representation of a relational transformer */
|
/** Symbolic representation of a relational transformer */
|
||||||
class Transformer
|
class Transformer
|
||||||
|
@ -574,7 +579,7 @@ private:
|
||||||
* you must pop the context accordingly. The second argument is
|
* you must pop the context accordingly. The second argument is
|
||||||
* the number of pushes we are inside. */
|
* the number of pushes we are inside. */
|
||||||
|
|
||||||
void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false);
|
virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false);
|
||||||
|
|
||||||
/* Constrain an edge by the annotation of one of its children. */
|
/* Constrain an edge by the annotation of one of its children. */
|
||||||
|
|
||||||
|
@ -808,9 +813,31 @@ private:
|
||||||
/** Edges of the graph. */
|
/** Edges of the graph. */
|
||||||
std::vector<Edge *> edges;
|
std::vector<Edge *> edges;
|
||||||
|
|
||||||
|
/** Fuse a vector of transformers. If the total number of inputs of the transformers
|
||||||
|
is N, then the result is an N-ary transfomer whose output is the union of
|
||||||
|
the outputs of the given transformers. The is, suppose we have a vetor of transfoermers
|
||||||
|
{T_i(r_i1,...,r_iN(i) : i=1..M}. The the result is a transformer
|
||||||
|
|
||||||
|
F(r_11,...,r_iN(1),...,r_M1,...,r_MN(M)) =
|
||||||
|
T_1(r_11,...,r_iN(1)) U ... U T_M(r_M1,...,r_MN(M))
|
||||||
|
*/
|
||||||
|
|
||||||
|
Transformer Fuse(const std::vector<Transformer *> &trs);
|
||||||
|
|
||||||
|
/** Fuse edges so that each node is the output of at most one edge. This
|
||||||
|
transformation is solution-preserving, but changes the numbering of edges in
|
||||||
|
counterexamples.
|
||||||
|
*/
|
||||||
|
void FuseEdges();
|
||||||
|
|
||||||
|
void RemoveDeadNodes();
|
||||||
|
|
||||||
Term SubstParams(const std::vector<Term> &from,
|
Term SubstParams(const std::vector<Term> &from,
|
||||||
const std::vector<Term> &to, const Term &t);
|
const std::vector<Term> &to, const Term &t);
|
||||||
|
|
||||||
|
Term SubstParamsNoCapture(const std::vector<Term> &from,
|
||||||
|
const std::vector<Term> &to, const Term &t);
|
||||||
|
|
||||||
Term Localize(Edge *e, const Term &t);
|
Term Localize(Edge *e, const Term &t);
|
||||||
|
|
||||||
void EvalNodeAsConstraint(Node *p, Transformer &res);
|
void EvalNodeAsConstraint(Node *p, Transformer &res);
|
||||||
|
@ -829,7 +856,13 @@ private:
|
||||||
*/
|
*/
|
||||||
void ComputeProofCore();
|
void ComputeProofCore();
|
||||||
|
|
||||||
private:
|
int CumulativeDecisions();
|
||||||
|
|
||||||
|
solver &slvr(){
|
||||||
|
return *ls->slvr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
void ClearProofCore(){
|
void ClearProofCore(){
|
||||||
if(proof_core)
|
if(proof_core)
|
||||||
|
@ -947,6 +980,8 @@ private:
|
||||||
|
|
||||||
expr SimplifyOr(std::vector<expr> &lits);
|
expr SimplifyOr(std::vector<expr> &lits);
|
||||||
|
|
||||||
|
expr SimplifyAnd(std::vector<expr> &lits);
|
||||||
|
|
||||||
void SetAnnotation(Node *root, const expr &t);
|
void SetAnnotation(Node *root, const expr &t);
|
||||||
|
|
||||||
void AddEdgeToSolver(Edge *edge);
|
void AddEdgeToSolver(Edge *edge);
|
||||||
|
@ -959,9 +994,58 @@ private:
|
||||||
|
|
||||||
expr NegateLit(const expr &f);
|
expr NegateLit(const expr &f);
|
||||||
|
|
||||||
|
expr GetEdgeFormula(Edge *e, int persist, bool with_children, bool underapprox);
|
||||||
|
|
||||||
|
bool IsVar(const expr &t);
|
||||||
|
|
||||||
|
void GetVarsRec(hash_set<ast> &memo, const expr &cnst, std::vector<expr> &vars);
|
||||||
|
|
||||||
|
expr UnhoistPullRec(hash_map<ast,expr> & memo, const expr &w, hash_map<ast,expr> & init_defs, hash_map<ast,expr> & const_params, hash_map<ast,expr> &const_params_inv, std::vector<expr> &new_params);
|
||||||
|
|
||||||
|
void AddParamsToTransformer(Transformer &trans, const std::vector<expr> ¶ms);
|
||||||
|
|
||||||
|
expr AddParamsToApp(const expr &app, const func_decl &new_decl, const std::vector<expr> ¶ms);
|
||||||
|
|
||||||
|
expr GetRelRec(hash_set<ast> &memo, const expr &t, const func_decl &rel);
|
||||||
|
|
||||||
|
expr GetRel(Edge *edge, int child_idx);
|
||||||
|
|
||||||
|
void GetDefs(const expr &cnst, hash_map<ast,expr> &defs);
|
||||||
|
|
||||||
|
void GetDefsRec(const expr &cnst, hash_map<ast,expr> &defs);
|
||||||
|
|
||||||
|
void AddParamsToNode(Node *node, const std::vector<expr> ¶ms);
|
||||||
|
|
||||||
|
void UnhoistLoop(Edge *loop_edge, Edge *init_edge);
|
||||||
|
|
||||||
|
void Unhoist();
|
||||||
|
|
||||||
|
Term ElimIteRec(hash_map<ast,expr> &memo, const Term &t, std::vector<expr> &cnsts);
|
||||||
|
|
||||||
|
Term ElimIte(const Term &t);
|
||||||
|
|
||||||
|
void MarkLiveNodes(hash_map<Node *,std::vector<Edge *> > &outgoing, hash_set<Node *> &live_nodes, Node *node);
|
||||||
|
|
||||||
|
virtual void slvr_add(const expr &e);
|
||||||
|
|
||||||
|
virtual void slvr_pop(int i);
|
||||||
|
|
||||||
|
virtual void slvr_push();
|
||||||
|
|
||||||
|
virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0);
|
||||||
|
|
||||||
|
virtual lbool ls_interpolate_tree(TermTree *assumptions,
|
||||||
|
TermTree *&interpolants,
|
||||||
|
model &_model,
|
||||||
|
TermTree *goals = 0,
|
||||||
|
bool weak = false);
|
||||||
|
|
||||||
|
virtual bool proof_core_contains(const expr &e);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** RPFP solver base class. */
|
|
||||||
|
/** RPFP solver base class. */
|
||||||
|
|
||||||
class Solver {
|
class Solver {
|
||||||
|
|
||||||
|
@ -1005,6 +1089,8 @@ private:
|
||||||
/** Object thrown on cancellation */
|
/** Object thrown on cancellation */
|
||||||
struct Canceled {};
|
struct Canceled {};
|
||||||
|
|
||||||
|
/** Object thrown on incompleteness */
|
||||||
|
struct Incompleteness {};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,3 +1128,130 @@ namespace std {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #define LIMIT_STACK_WEIGHT 5
|
||||||
|
|
||||||
|
|
||||||
|
namespace Duality {
|
||||||
|
/** Caching version of RPFP. Instead of asserting constraints, returns assumption literals */
|
||||||
|
|
||||||
|
class RPFP_caching : public RPFP {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** appends assumption literals for edge to lits. if with_children is true,
|
||||||
|
includes that annotation of the edge's children.
|
||||||
|
*/
|
||||||
|
void AssertEdgeCache(Edge *e, std::vector<Term> &lits, bool with_children = false);
|
||||||
|
|
||||||
|
/** appends assumption literals for node to lits */
|
||||||
|
void AssertNodeCache(Node *, std::vector<Term> lits);
|
||||||
|
|
||||||
|
/** check assumption lits, and return core */
|
||||||
|
check_result CheckCore(const std::vector<Term> &assumps, std::vector<Term> &core);
|
||||||
|
|
||||||
|
/** Clone another RPFP into this one, keeping a map */
|
||||||
|
void Clone(RPFP *other);
|
||||||
|
|
||||||
|
/** Get the clone of a node */
|
||||||
|
Node *GetNodeClone(Node *other_node);
|
||||||
|
|
||||||
|
/** Get the clone of an edge */
|
||||||
|
Edge *GetEdgeClone(Edge *other_edge);
|
||||||
|
|
||||||
|
/** Try to strengthen the parent of an edge */
|
||||||
|
void GeneralizeCache(Edge *edge);
|
||||||
|
|
||||||
|
/** Try to propagate some facts from children to parents of edge.
|
||||||
|
Return true if success. */
|
||||||
|
bool PropagateCache(Edge *edge);
|
||||||
|
|
||||||
|
/** Construct a caching RPFP using a LogicSolver */
|
||||||
|
RPFP_caching(LogicSolver *_ls) : RPFP(_ls) {}
|
||||||
|
|
||||||
|
/** Constraint an edge by its child's annotation. Return
|
||||||
|
assumption lits. */
|
||||||
|
void ConstrainParentCache(Edge *parent, Node *child, std::vector<Term> &lits);
|
||||||
|
|
||||||
|
#ifdef LIMIT_STACK_WEIGHT
|
||||||
|
virtual void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual ~RPFP_caching(){}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
hash_map<ast,expr> AssumptionLits;
|
||||||
|
hash_map<Node *, Node *> NodeCloneMap;
|
||||||
|
hash_map<Edge *, Edge *> EdgeCloneMap;
|
||||||
|
std::vector<expr> alit_stack;
|
||||||
|
std::vector<unsigned> alit_stack_sizes;
|
||||||
|
hash_map<Edge *, uptr<LogicSolver> > edge_solvers;
|
||||||
|
|
||||||
|
#ifdef LIMIT_STACK_WEIGHT
|
||||||
|
struct weight_counter {
|
||||||
|
int val;
|
||||||
|
weight_counter(){val = 0;}
|
||||||
|
void swap(weight_counter &other){
|
||||||
|
std::swap(val,other.val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct big_stack_entry {
|
||||||
|
weight_counter weight_added;
|
||||||
|
std::vector<expr> new_alits;
|
||||||
|
std::vector<expr> alit_stack;
|
||||||
|
std::vector<unsigned> alit_stack_sizes;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<expr> new_alits;
|
||||||
|
weight_counter weight_added;
|
||||||
|
std::vector<big_stack_entry> big_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GetAssumptionLits(const expr &fmla, std::vector<expr> &lits, hash_map<ast,expr> *opt_map = 0);
|
||||||
|
|
||||||
|
void GreedyReduceCache(std::vector<expr> &assumps, std::vector<expr> &core);
|
||||||
|
|
||||||
|
void FilterCore(std::vector<expr> &core, std::vector<expr> &full_core);
|
||||||
|
void ConstrainEdgeLocalizedCache(Edge *e, const Term &tl, std::vector<expr> &lits);
|
||||||
|
|
||||||
|
virtual void slvr_add(const expr &e);
|
||||||
|
|
||||||
|
virtual void slvr_pop(int i);
|
||||||
|
|
||||||
|
virtual void slvr_push();
|
||||||
|
|
||||||
|
virtual check_result slvr_check(unsigned n = 0, expr * const assumptions = 0, unsigned *core_size = 0, expr *core = 0);
|
||||||
|
|
||||||
|
virtual lbool ls_interpolate_tree(TermTree *assumptions,
|
||||||
|
TermTree *&interpolants,
|
||||||
|
model &_model,
|
||||||
|
TermTree *goals = 0,
|
||||||
|
bool weak = false);
|
||||||
|
|
||||||
|
virtual bool proof_core_contains(const expr &e);
|
||||||
|
|
||||||
|
void GetTermTreeAssertionLiterals(TermTree *assumptions);
|
||||||
|
|
||||||
|
void GetTermTreeAssertionLiteralsRec(TermTree *assumptions);
|
||||||
|
|
||||||
|
LogicSolver *SolverForEdge(Edge *edge, bool models);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct scoped_solver_for_edge {
|
||||||
|
LogicSolver *orig_ls;
|
||||||
|
RPFP_caching *rpfp;
|
||||||
|
scoped_solver_for_edge(RPFP_caching *_rpfp, Edge *edge, bool models = false){
|
||||||
|
rpfp = _rpfp;
|
||||||
|
orig_ls = rpfp->ls;
|
||||||
|
rpfp->ls = rpfp->SolverForEdge(edge,models);
|
||||||
|
}
|
||||||
|
~scoped_solver_for_edge(){
|
||||||
|
rpfp->ls = orig_ls;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,14 @@ Revision History:
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "duality_wrapper.h"
|
#include "duality_wrapper.h"
|
||||||
|
#include "iz3profiling.h"
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
|
@ -103,6 +110,7 @@ namespace Duality {
|
||||||
output_time(*pfs, it->second.t);
|
output_time(*pfs, it->second.t);
|
||||||
(*pfs) << std::endl;
|
(*pfs) << std::endl;
|
||||||
}
|
}
|
||||||
|
profiling::print(os); // print the interpolation stats
|
||||||
}
|
}
|
||||||
|
|
||||||
void timer_start(const char *name){
|
void timer_start(const char *name){
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -19,6 +19,12 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "duality.h"
|
#include "duality.h"
|
||||||
#include "duality_profiling.h"
|
#include "duality_profiling.h"
|
||||||
|
|
||||||
|
@ -26,6 +32,7 @@ Revision History:
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
// TODO: make these official options or get rid of them
|
// TODO: make these official options or get rid of them
|
||||||
|
|
||||||
|
@ -37,14 +44,18 @@ Revision History:
|
||||||
#define MINIMIZE_CANDIDATES
|
#define MINIMIZE_CANDIDATES
|
||||||
// #define MINIMIZE_CANDIDATES_HARDER
|
// #define MINIMIZE_CANDIDATES_HARDER
|
||||||
#define BOUNDED
|
#define BOUNDED
|
||||||
#define CHECK_CANDS_FROM_IND_SET
|
// #define CHECK_CANDS_FROM_IND_SET
|
||||||
#define UNDERAPPROX_NODES
|
#define UNDERAPPROX_NODES
|
||||||
#define NEW_EXPAND
|
#define NEW_EXPAND
|
||||||
#define EARLY_EXPAND
|
#define EARLY_EXPAND
|
||||||
// #define TOP_DOWN
|
// #define TOP_DOWN
|
||||||
// #define EFFORT_BOUNDED_STRAT
|
// #define EFFORT_BOUNDED_STRAT
|
||||||
#define SKIP_UNDERAPPROX_NODES
|
#define SKIP_UNDERAPPROX_NODES
|
||||||
|
#define USE_RPFP_CLONE
|
||||||
|
// #define KEEP_EXPANSIONS
|
||||||
|
// #define USE_CACHING_RPFP
|
||||||
|
// #define PROPAGATE_BEFORE_CHECK
|
||||||
|
#define USE_NEW_GEN_CANDS
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
|
@ -101,7 +112,7 @@ namespace Duality {
|
||||||
public:
|
public:
|
||||||
Duality(RPFP *_rpfp)
|
Duality(RPFP *_rpfp)
|
||||||
: ctx(_rpfp->ctx),
|
: ctx(_rpfp->ctx),
|
||||||
slvr(_rpfp->slvr),
|
slvr(_rpfp->slvr()),
|
||||||
nodes(_rpfp->nodes),
|
nodes(_rpfp->nodes),
|
||||||
edges(_rpfp->edges)
|
edges(_rpfp->edges)
|
||||||
{
|
{
|
||||||
|
@ -115,8 +126,42 @@ namespace Duality {
|
||||||
Report = false;
|
Report = false;
|
||||||
StratifiedInlining = false;
|
StratifiedInlining = false;
|
||||||
RecursionBound = -1;
|
RecursionBound = -1;
|
||||||
|
{
|
||||||
|
scoped_no_proof no_proofs_please(ctx.m());
|
||||||
|
#ifdef USE_RPFP_CLONE
|
||||||
|
clone_ls = new RPFP::iZ3LogicSolver(ctx, false); // no models needed for this one
|
||||||
|
clone_rpfp = new RPFP_caching(clone_ls);
|
||||||
|
clone_rpfp->Clone(rpfp);
|
||||||
|
#endif
|
||||||
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
|
gen_cands_ls = new RPFP::iZ3LogicSolver(ctx);
|
||||||
|
gen_cands_rpfp = new RPFP_caching(gen_cands_ls);
|
||||||
|
gen_cands_rpfp->Clone(rpfp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Duality(){
|
||||||
|
#ifdef USE_RPFP_CLONE
|
||||||
|
delete clone_rpfp;
|
||||||
|
delete clone_ls;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
|
delete gen_cands_rpfp;
|
||||||
|
delete gen_cands_ls;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_RPFP_CLONE
|
||||||
|
RPFP::LogicSolver *clone_ls;
|
||||||
|
RPFP_caching *clone_rpfp;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_NEW_GEN_CANDS
|
||||||
|
RPFP::LogicSolver *gen_cands_ls;
|
||||||
|
RPFP_caching *gen_cands_rpfp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef RPFP::Node Node;
|
typedef RPFP::Node Node;
|
||||||
typedef RPFP::Edge Edge;
|
typedef RPFP::Edge Edge;
|
||||||
|
|
||||||
|
@ -804,8 +849,10 @@ namespace Duality {
|
||||||
Node *child = chs[i];
|
Node *child = chs[i];
|
||||||
if(TopoSort[child] < TopoSort[node->map]){
|
if(TopoSort[child] < TopoSort[node->map]){
|
||||||
Node *leaf = LeafMap[child];
|
Node *leaf = LeafMap[child];
|
||||||
if(!indset->Contains(leaf))
|
if(!indset->Contains(leaf)){
|
||||||
|
node->Outgoing->F.Formula = ctx.bool_val(false); // make this a proper leaf, else bogus cex
|
||||||
return node->Outgoing;
|
return node->Outgoing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1085,7 +1132,8 @@ namespace Duality {
|
||||||
void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){
|
void ExtractCandidateFromCex(Edge *edge, RPFP *checker, Node *root, Candidate &candidate){
|
||||||
candidate.edge = edge;
|
candidate.edge = edge;
|
||||||
for(unsigned j = 0; j < edge->Children.size(); j++){
|
for(unsigned j = 0; j < edge->Children.size(); j++){
|
||||||
Edge *lb = root->Outgoing->Children[j]->Outgoing;
|
Node *node = root->Outgoing->Children[j];
|
||||||
|
Edge *lb = node->Outgoing;
|
||||||
std::vector<Node *> &insts = insts_of_node[edge->Children[j]];
|
std::vector<Node *> &insts = insts_of_node[edge->Children[j]];
|
||||||
#ifndef MINIMIZE_CANDIDATES
|
#ifndef MINIMIZE_CANDIDATES
|
||||||
for(int k = insts.size()-1; k >= 0; k--)
|
for(int k = insts.size()-1; k >= 0; k--)
|
||||||
|
@ -1095,8 +1143,8 @@ namespace Duality {
|
||||||
{
|
{
|
||||||
Node *inst = insts[k];
|
Node *inst = insts[k];
|
||||||
if(indset->Contains(inst)){
|
if(indset->Contains(inst)){
|
||||||
if(checker->Empty(lb->Parent) ||
|
if(checker->Empty(node) ||
|
||||||
eq(checker->Eval(lb,NodeMarker(inst)),ctx.bool_val(true))){
|
eq(lb ? checker->Eval(lb,NodeMarker(inst)) : checker->dualModel.eval(NodeMarker(inst)),ctx.bool_val(true))){
|
||||||
candidate.Children.push_back(inst);
|
candidate.Children.push_back(inst);
|
||||||
goto next_child;
|
goto next_child;
|
||||||
}
|
}
|
||||||
|
@ -1166,6 +1214,25 @@ namespace Duality {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
Node *CheckerForEdgeClone(Edge *edge, RPFP_caching *checker){
|
||||||
|
Edge *gen_cands_edge = checker->GetEdgeClone(edge);
|
||||||
|
Node *root = gen_cands_edge->Parent;
|
||||||
|
root->Outgoing = gen_cands_edge;
|
||||||
|
GenNodeSolutionFromIndSet(edge->Parent, root->Bound);
|
||||||
|
#if 0
|
||||||
|
if(root->Bound.IsFull())
|
||||||
|
return = 0;
|
||||||
|
#endif
|
||||||
|
checker->AssertNode(root);
|
||||||
|
for(unsigned j = 0; j < edge->Children.size(); j++){
|
||||||
|
Node *oc = edge->Children[j];
|
||||||
|
Node *nc = gen_cands_edge->Children[j];
|
||||||
|
GenNodeSolutionWithMarkers(oc,nc->Annotation,true);
|
||||||
|
}
|
||||||
|
checker->AssertEdge(gen_cands_edge,1,true);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
/** If the current proposed solution is not inductive,
|
/** If the current proposed solution is not inductive,
|
||||||
use the induction failure to generate candidates for extension. */
|
use the induction failure to generate candidates for extension. */
|
||||||
void GenCandidatesFromInductionFailure(bool full_scan = false){
|
void GenCandidatesFromInductionFailure(bool full_scan = false){
|
||||||
|
@ -1175,6 +1242,7 @@ namespace Duality {
|
||||||
Edge *edge = edges[i];
|
Edge *edge = edges[i];
|
||||||
if(!full_scan && updated_nodes.find(edge->Parent) == updated_nodes.end())
|
if(!full_scan && updated_nodes.find(edge->Parent) == updated_nodes.end())
|
||||||
continue;
|
continue;
|
||||||
|
#ifndef USE_NEW_GEN_CANDS
|
||||||
slvr.push();
|
slvr.push();
|
||||||
RPFP *checker = new RPFP(rpfp->ls);
|
RPFP *checker = new RPFP(rpfp->ls);
|
||||||
Node *root = CheckerForEdge(edge,checker);
|
Node *root = CheckerForEdge(edge,checker);
|
||||||
|
@ -1186,6 +1254,18 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
slvr.pop(1);
|
slvr.pop(1);
|
||||||
delete checker;
|
delete checker;
|
||||||
|
#else
|
||||||
|
RPFP_caching::scoped_solver_for_edge(gen_cands_rpfp,edge,true /* models */);
|
||||||
|
gen_cands_rpfp->Push();
|
||||||
|
Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp);
|
||||||
|
if(gen_cands_rpfp->Check(root) != unsat){
|
||||||
|
Candidate candidate;
|
||||||
|
ExtractCandidateFromCex(edge,gen_cands_rpfp,root,candidate);
|
||||||
|
reporter->InductionFailure(edge,candidate.Children);
|
||||||
|
candidates.push_back(candidate);
|
||||||
|
}
|
||||||
|
gen_cands_rpfp->Pop(1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
updated_nodes.clear();
|
updated_nodes.clear();
|
||||||
timer_stop("GenCandIndFail");
|
timer_stop("GenCandIndFail");
|
||||||
|
@ -1309,6 +1389,9 @@ namespace Duality {
|
||||||
node. */
|
node. */
|
||||||
bool SatisfyUpperBound(Node *node){
|
bool SatisfyUpperBound(Node *node){
|
||||||
if(node->Bound.IsFull()) return true;
|
if(node->Bound.IsFull()) return true;
|
||||||
|
#ifdef PROPAGATE_BEFORE_CHECK
|
||||||
|
Propagate();
|
||||||
|
#endif
|
||||||
reporter->Bound(node);
|
reporter->Bound(node);
|
||||||
int start_decs = rpfp->CumulativeDecisions();
|
int start_decs = rpfp->CumulativeDecisions();
|
||||||
DerivationTree *dtp = new DerivationTreeSlow(this,unwinding,reporter,heuristic,FullExpand);
|
DerivationTree *dtp = new DerivationTreeSlow(this,unwinding,reporter,heuristic,FullExpand);
|
||||||
|
@ -1412,13 +1495,77 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Propagate conjuncts up the unwinding
|
||||||
|
void Propagate(){
|
||||||
|
reporter->Message("beginning propagation");
|
||||||
|
timer_start("Propagate");
|
||||||
|
std::vector<Node *> sorted_nodes = unwinding->nodes;
|
||||||
|
std::sort(sorted_nodes.begin(),sorted_nodes.end(),std::less<Node *>()); // sorts by sequence number
|
||||||
|
hash_map<Node *,std::set<expr> > facts;
|
||||||
|
for(unsigned i = 0; i < sorted_nodes.size(); i++){
|
||||||
|
Node *node = sorted_nodes[i];
|
||||||
|
std::set<expr> &node_facts = facts[node->map];
|
||||||
|
if(!(node->Outgoing && indset->Contains(node)))
|
||||||
|
continue;
|
||||||
|
std::vector<expr> conj_vec;
|
||||||
|
unwinding->CollectConjuncts(node->Annotation.Formula,conj_vec);
|
||||||
|
std::set<expr> conjs;
|
||||||
|
std::copy(conj_vec.begin(),conj_vec.end(),std::inserter(conjs,conjs.begin()));
|
||||||
|
if(!node_facts.empty()){
|
||||||
|
RPFP *checker = new RPFP(rpfp->ls);
|
||||||
|
slvr.push();
|
||||||
|
Node *root = checker->CloneNode(node);
|
||||||
|
Edge *edge = node->Outgoing;
|
||||||
|
// checker->AssertNode(root);
|
||||||
|
std::vector<Node *> cs;
|
||||||
|
for(unsigned j = 0; j < edge->Children.size(); j++){
|
||||||
|
Node *oc = edge->Children[j];
|
||||||
|
Node *nc = checker->CloneNode(oc);
|
||||||
|
nc->Annotation = oc->Annotation; // is this needed?
|
||||||
|
cs.push_back(nc);
|
||||||
|
}
|
||||||
|
Edge *checker_edge = checker->CreateEdge(root,edge->F,cs);
|
||||||
|
checker->AssertEdge(checker_edge, 0, true, false);
|
||||||
|
std::vector<expr> propagated;
|
||||||
|
for(std::set<expr> ::iterator it = node_facts.begin(), en = node_facts.end(); it != en;){
|
||||||
|
const expr &fact = *it;
|
||||||
|
if(conjs.find(fact) == conjs.end()){
|
||||||
|
root->Bound.Formula = fact;
|
||||||
|
slvr.push();
|
||||||
|
checker->AssertNode(root);
|
||||||
|
check_result res = checker->Check(root);
|
||||||
|
slvr.pop();
|
||||||
|
if(res != unsat){
|
||||||
|
std::set<expr> ::iterator victim = it;
|
||||||
|
++it;
|
||||||
|
node_facts.erase(victim); // if it ain't true, nix it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
propagated.push_back(fact);
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
slvr.pop();
|
||||||
|
for(unsigned i = 0; i < propagated.size(); i++){
|
||||||
|
root->Annotation.Formula = propagated[i];
|
||||||
|
UpdateNodeToNode(node,root);
|
||||||
|
}
|
||||||
|
delete checker;
|
||||||
|
}
|
||||||
|
for(std::set<expr> ::iterator it = conjs.begin(), en = conjs.end(); it != en; ++it){
|
||||||
|
expr foo = *it;
|
||||||
|
node_facts.insert(foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timer_stop("Propagate");
|
||||||
|
}
|
||||||
|
|
||||||
/** This class represents a derivation tree. */
|
/** This class represents a derivation tree. */
|
||||||
class DerivationTree {
|
class DerivationTree {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DerivationTree(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand)
|
DerivationTree(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand)
|
||||||
: slvr(rpfp->slvr),
|
: slvr(rpfp->slvr()),
|
||||||
ctx(rpfp->ctx)
|
ctx(rpfp->ctx)
|
||||||
{
|
{
|
||||||
duality = _duality;
|
duality = _duality;
|
||||||
|
@ -1462,7 +1609,13 @@ namespace Duality {
|
||||||
constrained = _constrained;
|
constrained = _constrained;
|
||||||
false_approx = true;
|
false_approx = true;
|
||||||
timer_start("Derive");
|
timer_start("Derive");
|
||||||
|
#ifndef USE_CACHING_RPFP
|
||||||
tree = _tree ? _tree : new RPFP(rpfp->ls);
|
tree = _tree ? _tree : new RPFP(rpfp->ls);
|
||||||
|
#else
|
||||||
|
RPFP::LogicSolver *cache_ls = new RPFP::iZ3LogicSolver(ctx);
|
||||||
|
cache_ls->slvr->push();
|
||||||
|
tree = _tree ? _tree : new RPFP_caching(cache_ls);
|
||||||
|
#endif
|
||||||
tree->HornClauses = rpfp->HornClauses;
|
tree->HornClauses = rpfp->HornClauses;
|
||||||
tree->Push(); // so we can clear out the solver later when finished
|
tree->Push(); // so we can clear out the solver later when finished
|
||||||
top = CreateApproximatedInstance(root);
|
top = CreateApproximatedInstance(root);
|
||||||
|
@ -1474,19 +1627,28 @@ namespace Duality {
|
||||||
timer_start("Pop");
|
timer_start("Pop");
|
||||||
tree->Pop(1);
|
tree->Pop(1);
|
||||||
timer_stop("Pop");
|
timer_stop("Pop");
|
||||||
|
#ifdef USE_CACHING_RPFP
|
||||||
|
cache_ls->slvr->pop(1);
|
||||||
|
delete cache_ls;
|
||||||
|
tree->ls = rpfp->ls;
|
||||||
|
#endif
|
||||||
timer_stop("Derive");
|
timer_stop("Derive");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WITH_CHILDREN
|
#define WITH_CHILDREN
|
||||||
|
|
||||||
Node *CreateApproximatedInstance(RPFP::Node *from){
|
void InitializeApproximatedInstance(RPFP::Node *to){
|
||||||
Node *to = tree->CloneNode(from);
|
to->Annotation = to->map->Annotation;
|
||||||
to->Annotation = from->Annotation;
|
|
||||||
#ifndef WITH_CHILDREN
|
#ifndef WITH_CHILDREN
|
||||||
tree->CreateLowerBoundEdge(to);
|
tree->CreateLowerBoundEdge(to);
|
||||||
#endif
|
#endif
|
||||||
leaves.push_back(to);
|
leaves.push_back(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node *CreateApproximatedInstance(RPFP::Node *from){
|
||||||
|
Node *to = tree->CloneNode(from);
|
||||||
|
InitializeApproximatedInstance(to);
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1555,13 +1717,23 @@ namespace Duality {
|
||||||
|
|
||||||
virtual void ExpandNode(RPFP::Node *p){
|
virtual void ExpandNode(RPFP::Node *p){
|
||||||
// tree->RemoveEdge(p->Outgoing);
|
// tree->RemoveEdge(p->Outgoing);
|
||||||
Edge *edge = duality->GetNodeOutgoing(p->map,last_decs);
|
Edge *ne = p->Outgoing;
|
||||||
std::vector<RPFP::Node *> &cs = edge->Children;
|
if(ne) {
|
||||||
std::vector<RPFP::Node *> children(cs.size());
|
// reporter->Message("Recycling edge...");
|
||||||
for(unsigned i = 0; i < cs.size(); i++)
|
std::vector<RPFP::Node *> &cs = ne->Children;
|
||||||
children[i] = CreateApproximatedInstance(cs[i]);
|
for(unsigned i = 0; i < cs.size(); i++)
|
||||||
Edge *ne = tree->CreateEdge(p, p->map->Outgoing->F, children);
|
InitializeApproximatedInstance(cs[i]);
|
||||||
ne->map = p->map->Outgoing->map;
|
// ne->dual = expr();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Edge *edge = duality->GetNodeOutgoing(p->map,last_decs);
|
||||||
|
std::vector<RPFP::Node *> &cs = edge->Children;
|
||||||
|
std::vector<RPFP::Node *> children(cs.size());
|
||||||
|
for(unsigned i = 0; i < cs.size(); i++)
|
||||||
|
children[i] = CreateApproximatedInstance(cs[i]);
|
||||||
|
ne = tree->CreateEdge(p, p->map->Outgoing->F, children);
|
||||||
|
ne->map = p->map->Outgoing->map;
|
||||||
|
}
|
||||||
#ifndef WITH_CHILDREN
|
#ifndef WITH_CHILDREN
|
||||||
tree->AssertEdge(ne); // assert the edge in the solver
|
tree->AssertEdge(ne); // assert the edge in the solver
|
||||||
#else
|
#else
|
||||||
|
@ -1703,12 +1875,25 @@ namespace Duality {
|
||||||
void RemoveExpansion(RPFP::Node *p){
|
void RemoveExpansion(RPFP::Node *p){
|
||||||
Edge *edge = p->Outgoing;
|
Edge *edge = p->Outgoing;
|
||||||
Node *parent = edge->Parent;
|
Node *parent = edge->Parent;
|
||||||
|
#ifndef KEEP_EXPANSIONS
|
||||||
std::vector<RPFP::Node *> cs = edge->Children;
|
std::vector<RPFP::Node *> cs = edge->Children;
|
||||||
tree->DeleteEdge(edge);
|
tree->DeleteEdge(edge);
|
||||||
for(unsigned i = 0; i < cs.size(); i++)
|
for(unsigned i = 0; i < cs.size(); i++)
|
||||||
tree->DeleteNode(cs[i]);
|
tree->DeleteNode(cs[i]);
|
||||||
|
#endif
|
||||||
leaves.push_back(parent);
|
leaves.push_back(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove all the descendants of tree root (but not root itself)
|
||||||
|
void RemoveTree(RPFP *tree, RPFP::Node *root){
|
||||||
|
Edge *edge = root->Outgoing;
|
||||||
|
std::vector<RPFP::Node *> cs = edge->Children;
|
||||||
|
tree->DeleteEdge(edge);
|
||||||
|
for(unsigned i = 0; i < cs.size(); i++){
|
||||||
|
RemoveTree(tree,cs[i]);
|
||||||
|
tree->DeleteNode(cs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class DerivationTreeSlow : public DerivationTree {
|
class DerivationTreeSlow : public DerivationTree {
|
||||||
|
@ -1730,13 +1915,14 @@ namespace Duality {
|
||||||
|
|
||||||
virtual bool Build(){
|
virtual bool Build(){
|
||||||
|
|
||||||
stack.back().level = tree->slvr.get_scope_level();
|
stack.back().level = tree->slvr().get_scope_level();
|
||||||
|
bool was_sat = true;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
lbool res;
|
lbool res;
|
||||||
|
|
||||||
unsigned slvr_level = tree->slvr.get_scope_level();
|
unsigned slvr_level = tree->slvr().get_scope_level();
|
||||||
if(slvr_level != stack.back().level)
|
if(slvr_level != stack.back().level)
|
||||||
throw "stacks out of sync!";
|
throw "stacks out of sync!";
|
||||||
|
|
||||||
|
@ -1756,14 +1942,22 @@ namespace Duality {
|
||||||
tree->SolveSingleNode(top,node);
|
tree->SolveSingleNode(top,node);
|
||||||
if(expansions.size() == 1 && NodeTooComplicated(node))
|
if(expansions.size() == 1 && NodeTooComplicated(node))
|
||||||
SimplifyNode(node);
|
SimplifyNode(node);
|
||||||
tree->Generalize(top,node);
|
else
|
||||||
|
node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify();
|
||||||
|
Generalize(node);
|
||||||
if(RecordUpdate(node))
|
if(RecordUpdate(node))
|
||||||
update_count++;
|
update_count++;
|
||||||
|
else
|
||||||
|
heuristic->Update(node->map); // make it less likely to expand this node in future
|
||||||
}
|
}
|
||||||
if(update_count == 0)
|
if(update_count == 0){
|
||||||
|
if(was_sat)
|
||||||
|
throw Incompleteness();
|
||||||
reporter->Message("backtracked without learning");
|
reporter->Message("backtracked without learning");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tree->ComputeProofCore(); // need to compute the proof core before popping solver
|
tree->ComputeProofCore(); // need to compute the proof core before popping solver
|
||||||
|
bool propagated = false;
|
||||||
while(1) {
|
while(1) {
|
||||||
std::vector<Node *> &expansions = stack.back().expansions;
|
std::vector<Node *> &expansions = stack.back().expansions;
|
||||||
bool prev_level_used = LevelUsedInProof(stack.size()-2); // need to compute this before pop
|
bool prev_level_used = LevelUsedInProof(stack.size()-2); // need to compute this before pop
|
||||||
|
@ -1787,28 +1981,42 @@ namespace Duality {
|
||||||
RemoveExpansion(node);
|
RemoveExpansion(node);
|
||||||
}
|
}
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
if(prev_level_used || stack.size() == 1) break;
|
if(stack.size() == 1)break;
|
||||||
|
if(prev_level_used){
|
||||||
|
Node *node = stack.back().expansions[0];
|
||||||
|
if(!Propagate(node)) break;
|
||||||
|
if(!RecordUpdate(node)) break; // shouldn't happen!
|
||||||
|
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
||||||
|
propagated = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(propagated) break; // propagation invalidates the proof core, so disable non-chron backtrack
|
||||||
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
||||||
std::vector<Node *> &unused_ex = stack.back().expansions;
|
std::vector<Node *> &unused_ex = stack.back().expansions;
|
||||||
for(unsigned i = 0; i < unused_ex.size(); i++)
|
for(unsigned i = 0; i < unused_ex.size(); i++)
|
||||||
heuristic->Update(unused_ex[i]->map); // make it less likely to expand this node in future
|
heuristic->Update(unused_ex[i]->map); // make it less likely to expand this node in future
|
||||||
}
|
}
|
||||||
HandleUpdatedNodes();
|
HandleUpdatedNodes();
|
||||||
if(stack.size() == 1)
|
if(stack.size() == 1){
|
||||||
|
if(top->Outgoing)
|
||||||
|
tree->DeleteEdge(top->Outgoing); // in case we kept the tree
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
was_sat = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
was_sat = true;
|
||||||
tree->Push();
|
tree->Push();
|
||||||
std::vector<Node *> &expansions = stack.back().expansions;
|
std::vector<Node *> &expansions = stack.back().expansions;
|
||||||
for(unsigned i = 0; i < expansions.size(); i++){
|
for(unsigned i = 0; i < expansions.size(); i++){
|
||||||
tree->FixCurrentState(expansions[i]->Outgoing);
|
tree->FixCurrentState(expansions[i]->Outgoing);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if(tree->slvr.check() == unsat)
|
if(tree->slvr().check() == unsat)
|
||||||
throw "help!";
|
throw "help!";
|
||||||
#endif
|
#endif
|
||||||
stack.push_back(stack_entry());
|
stack.push_back(stack_entry());
|
||||||
stack.back().level = tree->slvr.get_scope_level();
|
stack.back().level = tree->slvr().get_scope_level();
|
||||||
if(ExpandSomeNodes(false,1)){
|
if(ExpandSomeNodes(false,1)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1822,13 +2030,18 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NodeTooComplicated(Node *node){
|
bool NodeTooComplicated(Node *node){
|
||||||
|
int ops = tree->CountOperators(node->Annotation.Formula);
|
||||||
|
if(ops > 10) return true;
|
||||||
|
node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify();
|
||||||
return tree->CountOperators(node->Annotation.Formula) > 3;
|
return tree->CountOperators(node->Annotation.Formula) > 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimplifyNode(Node *node){
|
void SimplifyNode(Node *node){
|
||||||
// have to destroy the old proof to get a new interpolant
|
// have to destroy the old proof to get a new interpolant
|
||||||
|
timer_start("SimplifyNode");
|
||||||
tree->PopPush();
|
tree->PopPush();
|
||||||
tree->InterpolateByCases(top,node);
|
tree->InterpolateByCases(top,node);
|
||||||
|
timer_stop("SimplifyNode");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LevelUsedInProof(unsigned level){
|
bool LevelUsedInProof(unsigned level){
|
||||||
|
@ -1927,6 +2140,39 @@ namespace Duality {
|
||||||
throw "can't unmap node";
|
throw "can't unmap node";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Generalize(Node *node){
|
||||||
|
#ifndef USE_RPFP_CLONE
|
||||||
|
tree->Generalize(top,node);
|
||||||
|
#else
|
||||||
|
RPFP_caching *clone_rpfp = duality->clone_rpfp;
|
||||||
|
if(!node->Outgoing->map) return;
|
||||||
|
Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map);
|
||||||
|
Node *clone_node = clone_edge->Parent;
|
||||||
|
clone_node->Annotation = node->Annotation;
|
||||||
|
for(unsigned i = 0; i < clone_edge->Children.size(); i++)
|
||||||
|
clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation;
|
||||||
|
clone_rpfp->GeneralizeCache(clone_edge);
|
||||||
|
node->Annotation = clone_node->Annotation;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Propagate(Node *node){
|
||||||
|
#ifdef USE_RPFP_CLONE
|
||||||
|
RPFP_caching *clone_rpfp = duality->clone_rpfp;
|
||||||
|
Edge *clone_edge = clone_rpfp->GetEdgeClone(node->Outgoing->map);
|
||||||
|
Node *clone_node = clone_edge->Parent;
|
||||||
|
clone_node->Annotation = node->map->Annotation;
|
||||||
|
for(unsigned i = 0; i < clone_edge->Children.size(); i++)
|
||||||
|
clone_edge->Children[i]->Annotation = node->map->Outgoing->Children[i]->Annotation;
|
||||||
|
bool res = clone_rpfp->PropagateCache(clone_edge);
|
||||||
|
if(res)
|
||||||
|
node->Annotation = clone_node->Annotation;
|
||||||
|
return res;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1948,6 +2194,11 @@ namespace Duality {
|
||||||
Duality *parent;
|
Duality *parent;
|
||||||
bool some_updates;
|
bool some_updates;
|
||||||
|
|
||||||
|
#define NO_CONJ_ON_SIMPLE_LOOPS
|
||||||
|
#ifdef NO_CONJ_ON_SIMPLE_LOOPS
|
||||||
|
hash_set<Node *> simple_loops;
|
||||||
|
#endif
|
||||||
|
|
||||||
Node *&covered_by(Node *node){
|
Node *&covered_by(Node *node){
|
||||||
return cm[node].covered_by;
|
return cm[node].covered_by;
|
||||||
}
|
}
|
||||||
|
@ -1982,6 +2233,24 @@ namespace Duality {
|
||||||
Covering(Duality *_parent){
|
Covering(Duality *_parent){
|
||||||
parent = _parent;
|
parent = _parent;
|
||||||
some_updates = false;
|
some_updates = false;
|
||||||
|
|
||||||
|
#ifdef NO_CONJ_ON_SIMPLE_LOOPS
|
||||||
|
hash_map<Node *,std::vector<Edge *> > outgoing;
|
||||||
|
for(unsigned i = 0; i < parent->rpfp->edges.size(); i++)
|
||||||
|
outgoing[parent->rpfp->edges[i]->Parent].push_back(parent->rpfp->edges[i]);
|
||||||
|
for(unsigned i = 0; i < parent->rpfp->nodes.size(); i++){
|
||||||
|
Node * node = parent->rpfp->nodes[i];
|
||||||
|
std::vector<Edge *> &outs = outgoing[node];
|
||||||
|
if(outs.size() == 2){
|
||||||
|
for(int j = 0; j < 2; j++){
|
||||||
|
Edge *loop_edge = outs[j];
|
||||||
|
if(loop_edge->Children.size() == 1 && loop_edge->Children[0] == loop_edge->Parent)
|
||||||
|
simple_loops.insert(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCoveredRec(hash_set<Node *> &memo, Node *node){
|
bool IsCoveredRec(hash_set<Node *> &memo, Node *node){
|
||||||
|
@ -2144,6 +2413,11 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CouldCover(Node *covered, Node *covering){
|
bool CouldCover(Node *covered, Node *covering){
|
||||||
|
#ifdef NO_CONJ_ON_SIMPLE_LOOPS
|
||||||
|
// Forsimple loops, we rely on propagation, not covering
|
||||||
|
if(simple_loops.find(covered->map) != simple_loops.end())
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
#ifdef UNDERAPPROX_NODES
|
#ifdef UNDERAPPROX_NODES
|
||||||
// if(parent->underapprox_map.find(covering) != parent->underapprox_map.end())
|
// if(parent->underapprox_map.find(covering) != parent->underapprox_map.end())
|
||||||
// return parent->underapprox_map[covering] == covered;
|
// return parent->underapprox_map[covering] == covered;
|
||||||
|
|
|
@ -18,6 +18,13 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "duality_wrapper.h"
|
#include "duality_wrapper.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "smt_solver.h"
|
#include "smt_solver.h"
|
||||||
|
@ -30,10 +37,11 @@ Revision History:
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
solver::solver(Duality::context& c, bool extensional) : object(c), the_model(c) {
|
solver::solver(Duality::context& c, bool extensional, bool models) : object(c), the_model(c) {
|
||||||
params_ref p;
|
params_ref p;
|
||||||
p.set_bool("proof", true); // this is currently useless
|
p.set_bool("proof", true); // this is currently useless
|
||||||
p.set_bool("model", true);
|
if(models)
|
||||||
|
p.set_bool("model", true);
|
||||||
p.set_bool("unsat_core", true);
|
p.set_bool("unsat_core", true);
|
||||||
p.set_bool("mbqi",true);
|
p.set_bool("mbqi",true);
|
||||||
p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants
|
p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants
|
||||||
|
@ -44,6 +52,7 @@ namespace Duality {
|
||||||
m_solver = (*sf)(m(), p, true, true, true, ::symbol::null);
|
m_solver = (*sf)(m(), p, true, true, true, ::symbol::null);
|
||||||
m_solver->updt_params(p); // why do we have to do this?
|
m_solver->updt_params(p); // why do we have to do this?
|
||||||
canceled = false;
|
canceled = false;
|
||||||
|
m_mode = m().proof_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
expr context::constant(const std::string &name, const sort &ty){
|
expr context::constant(const std::string &name, const sort &ty){
|
||||||
|
@ -338,6 +347,17 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
return ctx().cook(result);
|
return ctx().cook(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr expr::qe_lite(const std::set<int> &idxs, bool index_of_bound) const {
|
||||||
|
::qe_lite qe(m());
|
||||||
|
expr_ref result(to_expr(raw()),m());
|
||||||
|
proof_ref pf(m());
|
||||||
|
uint_set uis;
|
||||||
|
for(std::set<int>::const_iterator it=idxs.begin(), en = idxs.end(); it != en; ++it)
|
||||||
|
uis.insert(*it);
|
||||||
|
qe(uis,index_of_bound,result);
|
||||||
|
return ctx().cook(result);
|
||||||
|
}
|
||||||
|
|
||||||
expr clone_quantifier(const expr &q, const expr &b){
|
expr clone_quantifier(const expr &q, const expr &b){
|
||||||
return q.ctx().cook(q.m().update_quantifier(to_quantifier(q.raw()), to_expr(b.raw())));
|
return q.ctx().cook(q.m().update_quantifier(to_quantifier(q.raw()), to_expr(b.raw())));
|
||||||
}
|
}
|
||||||
|
@ -362,6 +382,18 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned func_decl::arity() const {
|
||||||
|
return (to_func_decl(raw())->get_arity());
|
||||||
|
}
|
||||||
|
|
||||||
|
sort func_decl::domain(unsigned i) const {
|
||||||
|
return sort(ctx(),(to_func_decl(raw())->get_domain(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
sort func_decl::range() const {
|
||||||
|
return sort(ctx(),(to_func_decl(raw())->get_range()));
|
||||||
|
}
|
||||||
|
|
||||||
func_decl context::fresh_func_decl(char const * prefix, const std::vector<sort> &domain, sort const & range){
|
func_decl context::fresh_func_decl(char const * prefix, const std::vector<sort> &domain, sort const & range){
|
||||||
std::vector < ::sort * > _domain(domain.size());
|
std::vector < ::sort * > _domain(domain.size());
|
||||||
for(unsigned i = 0; i < domain.size(); i++)
|
for(unsigned i = 0; i < domain.size(); i++)
|
||||||
|
@ -504,7 +536,10 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
add(linear_assumptions[i][j]);
|
add(linear_assumptions[i][j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_result res = check();
|
check_result res = unsat;
|
||||||
|
|
||||||
|
if(!m_solver->get_proof())
|
||||||
|
res = check();
|
||||||
|
|
||||||
if(res == unsat){
|
if(res == unsat){
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ Revision History:
|
||||||
#include<sstream>
|
#include<sstream>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
#include<list>
|
#include<list>
|
||||||
|
#include <set>
|
||||||
#include"version.h"
|
#include"version.h"
|
||||||
#include<limits.h>
|
#include<limits.h>
|
||||||
|
|
||||||
|
@ -50,6 +51,7 @@ Revision History:
|
||||||
#include"scoped_ctrl_c.h"
|
#include"scoped_ctrl_c.h"
|
||||||
#include"cancel_eh.h"
|
#include"cancel_eh.h"
|
||||||
#include"scoped_timer.h"
|
#include"scoped_timer.h"
|
||||||
|
#include"scoped_proof.h"
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
|
@ -449,6 +451,7 @@ namespace Duality {
|
||||||
bool is_datatype() const { return get_sort().is_datatype(); }
|
bool is_datatype() const { return get_sort().is_datatype(); }
|
||||||
bool is_relation() const { return get_sort().is_relation(); }
|
bool is_relation() const { return get_sort().is_relation(); }
|
||||||
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
bool is_finite_domain() const { return get_sort().is_finite_domain(); }
|
||||||
|
bool is_true() const {return is_app() && decl().get_decl_kind() == True; }
|
||||||
|
|
||||||
bool is_numeral() const {
|
bool is_numeral() const {
|
||||||
return is_app() && decl().get_decl_kind() == OtherArith && m().is_unique_value(to_expr(raw()));
|
return is_app() && decl().get_decl_kind() == OtherArith && m().is_unique_value(to_expr(raw()));
|
||||||
|
@ -560,6 +563,8 @@ namespace Duality {
|
||||||
|
|
||||||
expr qe_lite() const;
|
expr qe_lite() const;
|
||||||
|
|
||||||
|
expr qe_lite(const std::set<int> &idxs, bool index_of_bound) const;
|
||||||
|
|
||||||
friend expr clone_quantifier(const expr &, const expr &);
|
friend expr clone_quantifier(const expr &, const expr &);
|
||||||
|
|
||||||
friend expr clone_quantifier(const expr &q, const expr &b, const std::vector<expr> &patterns);
|
friend expr clone_quantifier(const expr &q, const expr &b, const std::vector<expr> &patterns);
|
||||||
|
@ -718,6 +723,7 @@ namespace Duality {
|
||||||
m_model = s;
|
m_model = s;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
bool null() const {return !m_model;}
|
||||||
|
|
||||||
expr eval(expr const & n, bool model_completion=true) const {
|
expr eval(expr const & n, bool model_completion=true) const {
|
||||||
::model * _m = m_model.get();
|
::model * _m = m_model.get();
|
||||||
|
@ -811,8 +817,9 @@ namespace Duality {
|
||||||
::solver *m_solver;
|
::solver *m_solver;
|
||||||
model the_model;
|
model the_model;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
|
proof_gen_mode m_mode;
|
||||||
public:
|
public:
|
||||||
solver(context & c, bool extensional = false);
|
solver(context & c, bool extensional = false, bool models = true);
|
||||||
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
||||||
solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;}
|
solver(solver const & s):object(s), the_model(s.the_model) { m_solver = s.m_solver; canceled = false;}
|
||||||
~solver() {
|
~solver() {
|
||||||
|
@ -824,6 +831,7 @@ namespace Duality {
|
||||||
m_ctx = s.m_ctx;
|
m_ctx = s.m_ctx;
|
||||||
m_solver = s.m_solver;
|
m_solver = s.m_solver;
|
||||||
the_model = s.the_model;
|
the_model = s.the_model;
|
||||||
|
m_mode = s.m_mode;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
struct cancel_exception {};
|
struct cancel_exception {};
|
||||||
|
@ -832,11 +840,12 @@ namespace Duality {
|
||||||
throw(cancel_exception());
|
throw(cancel_exception());
|
||||||
}
|
}
|
||||||
// void set(params const & p) { Z3_solver_set_params(ctx(), m_solver, p); check_error(); }
|
// void set(params const & p) { Z3_solver_set_params(ctx(), m_solver, p); check_error(); }
|
||||||
void push() { m_solver->push(); }
|
void push() { scoped_proof_mode spm(m(),m_mode); m_solver->push(); }
|
||||||
void pop(unsigned n = 1) { m_solver->pop(n); }
|
void pop(unsigned n = 1) { scoped_proof_mode spm(m(),m_mode); m_solver->pop(n); }
|
||||||
// void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); }
|
// void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); }
|
||||||
void add(expr const & e) { m_solver->assert_expr(e); }
|
void add(expr const & e) { scoped_proof_mode spm(m(),m_mode); m_solver->assert_expr(e); }
|
||||||
check_result check() {
|
check_result check() {
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
checkpoint();
|
checkpoint();
|
||||||
lbool r = m_solver->check_sat(0,0);
|
lbool r = m_solver->check_sat(0,0);
|
||||||
model_ref m;
|
model_ref m;
|
||||||
|
@ -845,6 +854,7 @@ namespace Duality {
|
||||||
return to_check_result(r);
|
return to_check_result(r);
|
||||||
}
|
}
|
||||||
check_result check_keep_model(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
check_result check_keep_model(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
model old_model(the_model);
|
model old_model(the_model);
|
||||||
check_result res = check(n,assumptions,core_size,core);
|
check_result res = check(n,assumptions,core_size,core);
|
||||||
if(the_model == 0)
|
if(the_model == 0)
|
||||||
|
@ -852,6 +862,7 @@ namespace Duality {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
check_result check(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
check_result check(unsigned n, expr * const assumptions, unsigned *core_size = 0, expr *core = 0) {
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
checkpoint();
|
checkpoint();
|
||||||
std::vector< ::expr *> _assumptions(n);
|
std::vector< ::expr *> _assumptions(n);
|
||||||
for (unsigned i = 0; i < n; i++) {
|
for (unsigned i = 0; i < n; i++) {
|
||||||
|
@ -876,6 +887,7 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
check_result check(expr_vector assumptions) {
|
check_result check(expr_vector assumptions) {
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
unsigned n = assumptions.size();
|
unsigned n = assumptions.size();
|
||||||
z3array<Z3_ast> _assumptions(n);
|
z3array<Z3_ast> _assumptions(n);
|
||||||
for (unsigned i = 0; i < n; i++) {
|
for (unsigned i = 0; i < n; i++) {
|
||||||
|
@ -900,17 +912,19 @@ namespace Duality {
|
||||||
int get_num_decisions();
|
int get_num_decisions();
|
||||||
|
|
||||||
void cancel(){
|
void cancel(){
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
canceled = true;
|
canceled = true;
|
||||||
if(m_solver)
|
if(m_solver)
|
||||||
m_solver->cancel();
|
m_solver->cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned get_scope_level(){return m_solver->get_scope_level();}
|
unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();}
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
void show_assertion_ids();
|
void show_assertion_ids();
|
||||||
|
|
||||||
proof get_proof(){
|
proof get_proof(){
|
||||||
|
scoped_proof_mode spm(m(),m_mode);
|
||||||
return proof(ctx(),m_solver->get_proof());
|
return proof(ctx(),m_solver->get_proof());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1294,8 +1308,8 @@ namespace Duality {
|
||||||
|
|
||||||
class interpolating_solver : public solver {
|
class interpolating_solver : public solver {
|
||||||
public:
|
public:
|
||||||
interpolating_solver(context &ctx)
|
interpolating_solver(context &ctx, bool models = true)
|
||||||
: solver(ctx)
|
: solver(ctx, true, models)
|
||||||
{
|
{
|
||||||
weak_mode = false;
|
weak_mode = false;
|
||||||
}
|
}
|
||||||
|
@ -1359,6 +1373,21 @@ namespace Duality {
|
||||||
typedef double clock_t;
|
typedef double clock_t;
|
||||||
clock_t current_time();
|
clock_t current_time();
|
||||||
inline void output_time(std::ostream &os, clock_t time){os << time;}
|
inline void output_time(std::ostream &os, clock_t time){os << time;}
|
||||||
|
|
||||||
|
template <class X> class uptr {
|
||||||
|
public:
|
||||||
|
X *ptr;
|
||||||
|
uptr(){ptr = 0;}
|
||||||
|
void set(X *_ptr){
|
||||||
|
if(ptr) delete ptr;
|
||||||
|
ptr = _ptr;
|
||||||
|
}
|
||||||
|
X *get(){ return ptr;}
|
||||||
|
~uptr(){
|
||||||
|
if(ptr) delete ptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// to make Duality::ast hashable
|
// to make Duality::ast hashable
|
||||||
|
@ -1393,6 +1422,18 @@ namespace std {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to make Duality::ast usable in ordered collections
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
class less<Duality::expr> {
|
||||||
|
public:
|
||||||
|
bool operator()(const Duality::expr &s, const Duality::expr &t) const {
|
||||||
|
// return s.raw() < t.raw();
|
||||||
|
return s.raw()->get_id() < t.raw()->get_id();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// to make Duality::func_decl hashable
|
// to make Duality::func_decl hashable
|
||||||
namespace hash_space {
|
namespace hash_space {
|
||||||
template <>
|
template <>
|
||||||
|
@ -1425,6 +1466,5 @@ namespace std {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,12 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3base.h"
|
#include "iz3base.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -17,6 +17,13 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3base.h"
|
#include "iz3base.h"
|
||||||
#include "iz3checker.h"
|
#include "iz3checker.h"
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ Revision History:
|
||||||
namespace stl_ext {
|
namespace stl_ext {
|
||||||
template <>
|
template <>
|
||||||
class hash<std::string> {
|
class hash<std::string> {
|
||||||
stl_ext::hash<char *> H;
|
stl_ext::hash<const char *> H;
|
||||||
public:
|
public:
|
||||||
size_t operator()(const std::string &s) const {
|
size_t operator()(const std::string &s) const {
|
||||||
return H(s.c_str());
|
return H(s.c_str());
|
||||||
|
|
|
@ -18,6 +18,14 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
/* Copyright 2011 Microsoft Research. */
|
/* Copyright 2011 Microsoft Research. */
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
@ -18,6 +18,15 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#pragma warning(disable:4805)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3mgr.h"
|
#include "iz3mgr.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -172,7 +181,7 @@ iz3mgr::ast iz3mgr::make_quant(opr op, const std::vector<ast> &bvs, ast &body){
|
||||||
|
|
||||||
|
|
||||||
std::vector<symbol> names;
|
std::vector<symbol> names;
|
||||||
std::vector<sort *> types;
|
std::vector<class sort *> types;
|
||||||
std::vector<expr *> bound_asts;
|
std::vector<expr *> bound_asts;
|
||||||
unsigned num_bound = bvs.size();
|
unsigned num_bound = bvs.size();
|
||||||
|
|
||||||
|
@ -485,7 +494,7 @@ void iz3mgr::get_farkas_coeffs(const ast &proof, std::vector<ast>& coeffs){
|
||||||
get_farkas_coeffs(proof,rats);
|
get_farkas_coeffs(proof,rats);
|
||||||
coeffs.resize(rats.size());
|
coeffs.resize(rats.size());
|
||||||
for(unsigned i = 0; i < rats.size(); i++){
|
for(unsigned i = 0; i < rats.size(); i++){
|
||||||
sort *is = m().mk_sort(m_arith_fid, INT_SORT);
|
class sort *is = m().mk_sort(m_arith_fid, INT_SORT);
|
||||||
ast coeff = cook(m_arith_util.mk_numeral(rats[i],is));
|
ast coeff = cook(m_arith_util.mk_numeral(rats[i],is));
|
||||||
coeffs[i] = coeff;
|
coeffs[i] = coeff;
|
||||||
}
|
}
|
||||||
|
@ -640,9 +649,9 @@ void iz3mgr::get_assign_bounds_rule_coeffs(const ast &proof, std::vector<rationa
|
||||||
|
|
||||||
/** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */
|
/** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */
|
||||||
|
|
||||||
void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q){
|
void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q, bool round_off){
|
||||||
ast Qrhs;
|
ast Qrhs;
|
||||||
bool strict = op(P) == Lt;
|
bool qstrict = false;
|
||||||
if(is_not(Q)){
|
if(is_not(Q)){
|
||||||
ast nQ = arg(Q,0);
|
ast nQ = arg(Q,0);
|
||||||
switch(op(nQ)){
|
switch(op(nQ)){
|
||||||
|
@ -654,11 +663,11 @@ void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q){
|
||||||
break;
|
break;
|
||||||
case Geq:
|
case Geq:
|
||||||
Qrhs = make(Sub,arg(nQ,1),arg(nQ,0));
|
Qrhs = make(Sub,arg(nQ,1),arg(nQ,0));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
case Leq:
|
case Leq:
|
||||||
Qrhs = make(Sub,arg(nQ,0),arg(nQ,1));
|
Qrhs = make(Sub,arg(nQ,0),arg(nQ,1));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw "not an inequality";
|
throw "not an inequality";
|
||||||
|
@ -674,28 +683,31 @@ void iz3mgr::linear_comb(ast &P, const ast &c, const ast &Q){
|
||||||
break;
|
break;
|
||||||
case Lt:
|
case Lt:
|
||||||
Qrhs = make(Sub,arg(Q,1),arg(Q,0));
|
Qrhs = make(Sub,arg(Q,1),arg(Q,0));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
case Gt:
|
case Gt:
|
||||||
Qrhs = make(Sub,arg(Q,0),arg(Q,1));
|
Qrhs = make(Sub,arg(Q,0),arg(Q,1));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw "not an inequality";
|
throw "not an inequality";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Qrhs = make(Times,c,Qrhs);
|
Qrhs = make(Times,c,Qrhs);
|
||||||
|
bool pstrict = op(P) == Lt, strict = pstrict || qstrict;
|
||||||
|
if(pstrict && qstrict && round_off)
|
||||||
|
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
||||||
if(strict)
|
if(strict)
|
||||||
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
||||||
else
|
else
|
||||||
P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
P = make(Leq,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
iz3mgr::ast iz3mgr::sum_inequalities(const std::vector<ast> &coeffs, const std::vector<ast> &ineqs){
|
iz3mgr::ast iz3mgr::sum_inequalities(const std::vector<ast> &coeffs, const std::vector<ast> &ineqs, bool round_off){
|
||||||
ast zero = make_int("0");
|
ast zero = make_int("0");
|
||||||
ast thing = make(Leq,zero,zero);
|
ast thing = make(Leq,zero,zero);
|
||||||
for(unsigned i = 0; i < ineqs.size(); i++){
|
for(unsigned i = 0; i < ineqs.size(); i++){
|
||||||
linear_comb(thing,coeffs[i],ineqs[i]);
|
linear_comb(thing,coeffs[i],ineqs[i], round_off);
|
||||||
}
|
}
|
||||||
thing = simplify_ineq(thing);
|
thing = simplify_ineq(thing);
|
||||||
return thing;
|
return thing;
|
||||||
|
|
|
@ -22,6 +22,7 @@ Revision History:
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <vector>
|
||||||
#include "iz3hash.h"
|
#include "iz3hash.h"
|
||||||
|
|
||||||
#include"well_sorted.h"
|
#include"well_sorted.h"
|
||||||
|
@ -262,6 +263,7 @@ class iz3mgr {
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ast arg(const ast &t, int i){
|
ast arg(const ast &t, int i){
|
||||||
|
@ -606,9 +608,9 @@ class iz3mgr {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void linear_comb(ast &P, const ast &c, const ast &Q);
|
void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false);
|
||||||
|
|
||||||
ast sum_inequalities(const std::vector<ast> &coeffs, const std::vector<ast> &ineqs);
|
ast sum_inequalities(const std::vector<ast> &coeffs, const std::vector<ast> &ineqs, bool round_off = false);
|
||||||
|
|
||||||
ast simplify_ineq(const ast &ineq){
|
ast simplify_ineq(const ast &ineq){
|
||||||
ast res = make(op(ineq),arg(ineq,0),z3_simplify(arg(ineq,1)));
|
ast res = make(op(ineq),arg(ineq,0),z3_simplify(arg(ineq,1)));
|
||||||
|
|
|
@ -58,20 +58,20 @@ namespace stl_ext {
|
||||||
class free_func_visitor {
|
class free_func_visitor {
|
||||||
ast_manager& m;
|
ast_manager& m;
|
||||||
func_decl_set m_funcs;
|
func_decl_set m_funcs;
|
||||||
obj_hashtable<sort> m_sorts;
|
obj_hashtable<class sort> m_sorts;
|
||||||
public:
|
public:
|
||||||
free_func_visitor(ast_manager& m): m(m) {}
|
free_func_visitor(ast_manager& m): m(m) {}
|
||||||
void operator()(var * n) { }
|
void operator()(var * n) { }
|
||||||
void operator()(app * n) {
|
void operator()(app * n) {
|
||||||
m_funcs.insert(n->get_decl());
|
m_funcs.insert(n->get_decl());
|
||||||
sort* s = m.get_sort(n);
|
class sort* s = m.get_sort(n);
|
||||||
if (s->get_family_id() == null_family_id) {
|
if (s->get_family_id() == null_family_id) {
|
||||||
m_sorts.insert(s);
|
m_sorts.insert(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void operator()(quantifier * n) { }
|
void operator()(quantifier * n) { }
|
||||||
func_decl_set& funcs() { return m_funcs; }
|
func_decl_set& funcs() { return m_funcs; }
|
||||||
obj_hashtable<sort>& sorts() { return m_sorts; }
|
obj_hashtable<class sort>& sorts() { return m_sorts; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class iz3pp_helper : public iz3mgr {
|
class iz3pp_helper : public iz3mgr {
|
||||||
|
@ -146,8 +146,8 @@ void iz3pp(ast_manager &m,
|
||||||
func_decl_set &funcs = visitor.funcs();
|
func_decl_set &funcs = visitor.funcs();
|
||||||
func_decl_set::iterator it = funcs.begin(), end = funcs.end();
|
func_decl_set::iterator it = funcs.begin(), end = funcs.end();
|
||||||
|
|
||||||
obj_hashtable<sort>& sorts = visitor.sorts();
|
obj_hashtable<class sort>& sorts = visitor.sorts();
|
||||||
obj_hashtable<sort>::iterator sit = sorts.begin(), send = sorts.end();
|
obj_hashtable<class sort>::iterator sit = sorts.begin(), send = sorts.end();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,13 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
|
@ -18,6 +18,12 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3proof.h"
|
#include "iz3proof.h"
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
|
|
@ -17,6 +17,13 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3proof_itp.h"
|
#include "iz3proof_itp.h"
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
@ -2170,7 +2177,8 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
for(unsigned i = 0; i < prem_cons.size(); i++){
|
for(unsigned i = 0; i < prem_cons.size(); i++){
|
||||||
const ast &lit = prem_cons[i];
|
const ast &lit = prem_cons[i];
|
||||||
if(get_term_type(lit) == LitA)
|
if(get_term_type(lit) == LitA)
|
||||||
linear_comb(thing,coeffs[i],lit);
|
// Farkas rule seems to assume strict integer inequalities are rounded
|
||||||
|
linear_comb(thing,coeffs[i],lit,true /*round_off*/);
|
||||||
}
|
}
|
||||||
thing = simplify_ineq(thing);
|
thing = simplify_ineq(thing);
|
||||||
for(unsigned i = 0; i < prem_cons.size(); i++){
|
for(unsigned i = 0; i < prem_cons.size(); i++){
|
||||||
|
@ -2195,9 +2203,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
|
|
||||||
/** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */
|
/** Set P to P + cQ, where P and Q are linear inequalities. Assumes P is 0 <= y or 0 < y. */
|
||||||
|
|
||||||
void linear_comb(ast &P, const ast &c, const ast &Q){
|
void linear_comb(ast &P, const ast &c, const ast &Q, bool round_off = false){
|
||||||
ast Qrhs;
|
ast Qrhs;
|
||||||
bool strict = op(P) == Lt;
|
bool qstrict = false;
|
||||||
if(is_not(Q)){
|
if(is_not(Q)){
|
||||||
ast nQ = arg(Q,0);
|
ast nQ = arg(Q,0);
|
||||||
switch(op(nQ)){
|
switch(op(nQ)){
|
||||||
|
@ -2209,11 +2217,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
break;
|
break;
|
||||||
case Geq:
|
case Geq:
|
||||||
Qrhs = make(Sub,arg(nQ,1),arg(nQ,0));
|
Qrhs = make(Sub,arg(nQ,1),arg(nQ,0));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
case Leq:
|
case Leq:
|
||||||
Qrhs = make(Sub,arg(nQ,0),arg(nQ,1));
|
Qrhs = make(Sub,arg(nQ,0),arg(nQ,1));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw proof_error();
|
throw proof_error();
|
||||||
|
@ -2229,17 +2237,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
||||||
break;
|
break;
|
||||||
case Lt:
|
case Lt:
|
||||||
Qrhs = make(Sub,arg(Q,1),arg(Q,0));
|
Qrhs = make(Sub,arg(Q,1),arg(Q,0));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
case Gt:
|
case Gt:
|
||||||
Qrhs = make(Sub,arg(Q,0),arg(Q,1));
|
Qrhs = make(Sub,arg(Q,0),arg(Q,1));
|
||||||
strict = true;
|
qstrict = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw proof_error();
|
throw proof_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Qrhs = make(Times,c,Qrhs);
|
Qrhs = make(Times,c,Qrhs);
|
||||||
|
bool pstrict = op(P) == Lt, strict = pstrict || qstrict;
|
||||||
|
if(pstrict && qstrict && round_off)
|
||||||
|
Qrhs = make(Sub,Qrhs,make_int(rational(1)));
|
||||||
if(strict)
|
if(strict)
|
||||||
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
P = make(Lt,arg(P,0),make(Plus,arg(P,1),Qrhs));
|
||||||
else
|
else
|
||||||
|
|
|
@ -17,6 +17,13 @@ Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3translate.h"
|
#include "iz3translate.h"
|
||||||
#include "iz3proof.h"
|
#include "iz3proof.h"
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
@ -1079,7 +1086,7 @@ public:
|
||||||
my_cons.push_back(mk_not(arg(con,i)));
|
my_cons.push_back(mk_not(arg(con,i)));
|
||||||
my_coeffs.push_back(farkas_coeffs[i]);
|
my_coeffs.push_back(farkas_coeffs[i]);
|
||||||
}
|
}
|
||||||
ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons));
|
ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */));
|
||||||
my_cons.push_back(mk_not(farkas_con));
|
my_cons.push_back(mk_not(farkas_con));
|
||||||
my_coeffs.push_back(make_int("1"));
|
my_coeffs.push_back(make_int("1"));
|
||||||
std::vector<Iproof::node> my_hyps;
|
std::vector<Iproof::node> my_hyps;
|
||||||
|
@ -1103,7 +1110,7 @@ public:
|
||||||
my_cons.push_back(conc(prem(proof,i-1)));
|
my_cons.push_back(conc(prem(proof,i-1)));
|
||||||
my_coeffs.push_back(farkas_coeffs[i]);
|
my_coeffs.push_back(farkas_coeffs[i]);
|
||||||
}
|
}
|
||||||
ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons));
|
ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons,true /* round_off */));
|
||||||
std::vector<Iproof::node> my_hyps;
|
std::vector<Iproof::node> my_hyps;
|
||||||
for(int i = 1; i < nargs; i++)
|
for(int i = 1; i < nargs; i++)
|
||||||
my_hyps.push_back(prems[i-1]);
|
my_hyps.push_back(prems[i-1]);
|
||||||
|
@ -1642,6 +1649,10 @@ public:
|
||||||
res = iproof->make_axiom(lits);
|
res = iproof->make_axiom(lits);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PR_IFF_TRUE: { // turns p into p <-> true, noop for us
|
||||||
|
res = args[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert(0 && "translate_main: unsupported proof rule");
|
assert(0 && "translate_main: unsupported proof rule");
|
||||||
throw unsupported();
|
throw unsupported();
|
||||||
|
|
|
@ -20,6 +20,14 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#pragma warning(disable:4390)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "iz3translate.h"
|
#include "iz3translate.h"
|
||||||
#include "iz3proof.h"
|
#include "iz3proof.h"
|
||||||
#include "iz3profiling.h"
|
#include "iz3profiling.h"
|
||||||
|
@ -58,7 +66,9 @@ namespace stl_ext {
|
||||||
|
|
||||||
|
|
||||||
static int lemma_count = 0;
|
static int lemma_count = 0;
|
||||||
|
#if 0
|
||||||
static int nll_lemma_count = 0;
|
static int nll_lemma_count = 0;
|
||||||
|
#endif
|
||||||
#define SHOW_LEMMA_COUNT -1
|
#define SHOW_LEMMA_COUNT -1
|
||||||
|
|
||||||
// One half of a resolution. We need this to distinguish
|
// One half of a resolution. We need this to distinguish
|
||||||
|
|
|
@ -97,6 +97,7 @@ namespace simplex {
|
||||||
unsigned m_blands_rule_threshold;
|
unsigned m_blands_rule_threshold;
|
||||||
random_gen m_random;
|
random_gen m_random;
|
||||||
uint_set m_left_basis;
|
uint_set m_left_basis;
|
||||||
|
unsigned m_infeasible_var;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
simplex():
|
simplex():
|
||||||
|
@ -111,7 +112,8 @@ namespace simplex {
|
||||||
typedef typename matrix::col_iterator col_iterator;
|
typedef typename matrix::col_iterator col_iterator;
|
||||||
|
|
||||||
void ensure_var(var_t v);
|
void ensure_var(var_t v);
|
||||||
row add_row(unsigned num_vars, var_t base, var_t const* vars, numeral const* coeffs);
|
row add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs);
|
||||||
|
row get_infeasible_row();
|
||||||
void del_row(row const& r);
|
void del_row(row const& r);
|
||||||
void set_lower(var_t var, eps_numeral const& b);
|
void set_lower(var_t var, eps_numeral const& b);
|
||||||
void set_upper(var_t var, eps_numeral const& b);
|
void set_upper(var_t var, eps_numeral const& b);
|
||||||
|
@ -125,6 +127,9 @@ namespace simplex {
|
||||||
eps_numeral const& get_value(var_t v);
|
eps_numeral const& get_value(var_t v);
|
||||||
void display(std::ostream& out) const;
|
void display(std::ostream& out) const;
|
||||||
|
|
||||||
|
unsigned get_num_vars() const { return m_vars.size(); }
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
var_t select_var_to_fix();
|
var_t select_var_to_fix();
|
||||||
|
@ -159,10 +164,11 @@ namespace simplex {
|
||||||
bool outside_bounds(var_t v) const { return below_lower(v) || above_upper(v); }
|
bool outside_bounds(var_t v) const { return below_lower(v) || above_upper(v); }
|
||||||
bool is_free(var_t v) const { return !m_vars[v].m_lower_valid && !m_vars[v].m_upper_valid; }
|
bool is_free(var_t v) const { return !m_vars[v].m_lower_valid && !m_vars[v].m_upper_valid; }
|
||||||
bool is_non_free(var_t v) const { return !is_free(v); }
|
bool is_non_free(var_t v) const { return !is_free(v); }
|
||||||
unsigned get_num_vars() const { return m_vars.size(); }
|
|
||||||
bool is_base(var_t x) const { return m_vars[x].m_is_base; }
|
bool is_base(var_t x) const { return m_vars[x].m_is_base; }
|
||||||
|
void add_patch(var_t v);
|
||||||
|
|
||||||
bool well_formed() const;
|
bool well_formed() const;
|
||||||
|
bool well_formed_row(row const& r) const;
|
||||||
bool is_feasible() const;
|
bool is_feasible() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,27 @@ namespace simplex {
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
typename simplex<Ext>::row
|
typename simplex<Ext>::row
|
||||||
simplex<Ext>::add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs) {
|
simplex<Ext>::add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs) {
|
||||||
DEBUG_CODE(
|
|
||||||
bool found = false;
|
|
||||||
for (unsigned i = 0; !found && i < num_vars; ++i) found = vars[i] == base;
|
|
||||||
SASSERT(found);
|
|
||||||
);
|
|
||||||
scoped_numeral base_coeff(m);
|
scoped_numeral base_coeff(m);
|
||||||
|
scoped_eps_numeral value(em), tmp(em);
|
||||||
row r = M.mk_row();
|
row r = M.mk_row();
|
||||||
for (unsigned i = 0; i < num_vars; ++i) {
|
for (unsigned i = 0; i < num_vars; ++i) {
|
||||||
M.add(r, coeffs[i], vars[i]);
|
if (!m.is_zero(coeffs[i])) {
|
||||||
if (vars[i] == base) {
|
var_t v = vars[i];
|
||||||
m.set(base_coeff, coeffs[i]);
|
M.add_var(r, coeffs[i], v);
|
||||||
|
if (v == base) {
|
||||||
|
m.set(base_coeff, coeffs[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SASSERT(!is_base(v));
|
||||||
|
em.mul(m_vars[v].m_value, coeffs[i], tmp);
|
||||||
|
em.add(value, tmp, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
em.neg(value);
|
||||||
|
em.div(value, base_coeff, value);
|
||||||
|
SASSERT(!m.is_zero(base_coeff));
|
||||||
|
SASSERT(!is_base(base));
|
||||||
while (m_row2base.size() <= r.id()) {
|
while (m_row2base.size() <= r.id()) {
|
||||||
m_row2base.push_back(null_var);
|
m_row2base.push_back(null_var);
|
||||||
}
|
}
|
||||||
|
@ -44,9 +52,28 @@ namespace simplex {
|
||||||
m_vars[base].m_base2row = r.id();
|
m_vars[base].m_base2row = r.id();
|
||||||
m_vars[base].m_is_base = true;
|
m_vars[base].m_is_base = true;
|
||||||
m.set(m_vars[base].m_base_coeff, base_coeff);
|
m.set(m_vars[base].m_base_coeff, base_coeff);
|
||||||
|
em.set(m_vars[base].m_value, value);
|
||||||
|
add_patch(base);
|
||||||
|
SASSERT(well_formed_row(r));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
typename simplex<Ext>::row
|
||||||
|
simplex<Ext>::get_infeasible_row() {
|
||||||
|
SASSERT(is_base(m_infeasible_var));
|
||||||
|
unsigned row_id = m_vars[m_infeasible_var].m_base2row;
|
||||||
|
return row(row_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void simplex<Ext>::add_patch(var_t v) {
|
||||||
|
SASSERT(is_base(v));
|
||||||
|
if (outside_bounds(v)) {
|
||||||
|
m_to_patch.insert(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void simplex<Ext>::del_row(row const& r) {
|
void simplex<Ext>::del_row(row const& r) {
|
||||||
m_vars[m_row2base[r.id()]].m_is_base = false;
|
m_vars[m_row2base[r.id()]].m_is_base = false;
|
||||||
|
@ -114,8 +141,12 @@ namespace simplex {
|
||||||
if (vi.m_lower_valid) out << em.to_string(vi.m_lower); else out << "-oo";
|
if (vi.m_lower_valid) out << em.to_string(vi.m_lower); else out << "-oo";
|
||||||
out << ":";
|
out << ":";
|
||||||
if (vi.m_upper_valid) out << em.to_string(vi.m_upper); else out << "oo";
|
if (vi.m_upper_valid) out << em.to_string(vi.m_upper); else out << "oo";
|
||||||
out << "]";
|
out << "] ";
|
||||||
if (vi.m_is_base) out << " b:" << vi.m_base2row;
|
if (vi.m_is_base) out << "b:" << vi.m_base2row << " ";
|
||||||
|
//col_iterator it = M.col_begin(i), end = M.col_end(i);
|
||||||
|
//for (; it != end; ++it) {
|
||||||
|
// out << "r" << it.get_row().id() << " ";
|
||||||
|
//}
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,20 +162,23 @@ namespace simplex {
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool simplex<Ext>::make_feasible() {
|
lbool simplex<Ext>::make_feasible() {
|
||||||
m_left_basis.reset();
|
m_left_basis.reset();
|
||||||
|
m_infeasible_var = null_var;
|
||||||
unsigned num_iterations = 0;
|
unsigned num_iterations = 0;
|
||||||
unsigned num_repeated = 0;
|
unsigned num_repeated = 0;
|
||||||
var_t v = null_var;
|
var_t v = null_var;
|
||||||
|
SASSERT(well_formed());
|
||||||
while ((v = select_var_to_fix()) != null_var) {
|
while ((v = select_var_to_fix()) != null_var) {
|
||||||
if (m_cancel || num_iterations > m_max_iterations) {
|
if (m_cancel || num_iterations > m_max_iterations) {
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
check_blands_rule(v, num_repeated);
|
check_blands_rule(v, num_repeated);
|
||||||
if (!make_var_feasible(v)) {
|
if (!make_var_feasible(v)) {
|
||||||
|
m_infeasible_var = v;
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
++num_iterations;
|
++num_iterations;
|
||||||
SASSERT(well_formed());
|
|
||||||
}
|
}
|
||||||
|
SASSERT(well_formed());
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,18 +222,18 @@ namespace simplex {
|
||||||
m.set(x_jI.m_base_coeff, a_ij);
|
m.set(x_jI.m_base_coeff, a_ij);
|
||||||
x_jI.m_is_base = true;
|
x_jI.m_is_base = true;
|
||||||
x_iI.m_is_base = false;
|
x_iI.m_is_base = false;
|
||||||
if (outside_bounds(x_j)) {
|
add_patch(x_j);
|
||||||
m_to_patch.insert(x_j);
|
SASSERT(well_formed_row(row(r_i)));
|
||||||
}
|
|
||||||
col_iterator it = M.col_begin(x_j), end = M.col_end(x_j);
|
col_iterator it = M.col_begin(x_j), end = M.col_end(x_j);
|
||||||
scoped_numeral a_kj(m), g(m);
|
scoped_numeral a_kj(m), g(m);
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
row r_k = it.get_row();
|
row r_k = it.get_row();
|
||||||
if (r_k != r_i) {
|
if (r_k.id() != r_i) {
|
||||||
a_kj = it.get_row_entry().m_coeff;
|
a_kj = it.get_row_entry().m_coeff;
|
||||||
a_kj.neg();
|
a_kj.neg();
|
||||||
M.mul(r_k, a_ij);
|
M.mul(r_k, a_ij);
|
||||||
M.add(r_k, a_kj, r_i);
|
M.add(r_k, a_kj, row(r_i));
|
||||||
var_t s = m_row2base[r_k.id()];
|
var_t s = m_row2base[r_k.id()];
|
||||||
numeral& coeff = m_vars[s].m_base_coeff;
|
numeral& coeff = m_vars[s].m_base_coeff;
|
||||||
m.mul(coeff, a_ij, coeff);
|
m.mul(coeff, a_ij, coeff);
|
||||||
|
@ -207,6 +241,7 @@ namespace simplex {
|
||||||
if (!m.is_one(g)) {
|
if (!m.is_one(g)) {
|
||||||
m.div(coeff, g, coeff);
|
m.div(coeff, g, coeff);
|
||||||
}
|
}
|
||||||
|
SASSERT(well_formed_row(row(r_k)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +275,8 @@ namespace simplex {
|
||||||
void simplex<Ext>::update_value_core(var_t v, eps_numeral const& delta) {
|
void simplex<Ext>::update_value_core(var_t v, eps_numeral const& delta) {
|
||||||
eps_numeral& val = m_vars[v].m_value;
|
eps_numeral& val = m_vars[v].m_value;
|
||||||
em.add(val, delta, val);
|
em.add(val, delta, val);
|
||||||
if (is_base(v) && outside_bounds(v)) {
|
if (is_base(v)) {
|
||||||
m_to_patch.insert(v);
|
add_patch(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,6 +534,7 @@ namespace simplex {
|
||||||
|
|
||||||
pivot(x_i, x_j, a_ij);
|
pivot(x_i, x_j, a_ij);
|
||||||
move_to_bound(x_i, inc == m.is_pos(a_ij));
|
move_to_bound(x_i, inc == m.is_pos(a_ij));
|
||||||
|
SASSERT(well_formed_row(row(m_vars[x_j].m_base2row)));
|
||||||
}
|
}
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
@ -705,18 +741,7 @@ namespace simplex {
|
||||||
var_t s = m_row2base[i];
|
var_t s = m_row2base[i];
|
||||||
if (s == null_var) continue;
|
if (s == null_var) continue;
|
||||||
SASSERT(i == m_vars[s].m_base2row);
|
SASSERT(i == m_vars[s].m_base2row);
|
||||||
//
|
SASSERT(well_formed_row(row(i)));
|
||||||
// TBD: extract coefficient of base variable and compare
|
|
||||||
// with m_vars[s].m_base_coeff;
|
|
||||||
//
|
|
||||||
// check that sum of assignments add up to 0 for every row.
|
|
||||||
row_iterator it = M.row_begin(row(i)), end = M.row_end(row(i));
|
|
||||||
scoped_eps_numeral sum(em), tmp(em);
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
em.mul(m_vars[it->m_var].m_value, it->m_coeff, tmp);
|
|
||||||
sum += tmp;
|
|
||||||
}
|
|
||||||
SASSERT(em.is_zero(sum));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -729,6 +754,25 @@ namespace simplex {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
bool simplex<Ext>::well_formed_row(row const& r) const {
|
||||||
|
|
||||||
|
//
|
||||||
|
// TBD: extract coefficient of base variable and compare
|
||||||
|
// with m_vars[s].m_base_coeff;
|
||||||
|
//
|
||||||
|
// check that sum of assignments add up to 0 for every row.
|
||||||
|
row_iterator it = M.row_begin(r), end = M.row_end(r);
|
||||||
|
scoped_eps_numeral sum(em), tmp(em);
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
em.mul(m_vars[it->m_var].m_value, it->m_coeff, tmp);
|
||||||
|
sum += tmp;
|
||||||
|
}
|
||||||
|
SASSERT(em.is_zero(sum));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -92,8 +92,7 @@ namespace simplex {
|
||||||
void del_row_entry(unsigned idx);
|
void del_row_entry(unsigned idx);
|
||||||
void compress(manager& m, vector<column> & cols);
|
void compress(manager& m, vector<column> & cols);
|
||||||
void compress_if_needed(manager& m, vector<column> & cols);
|
void compress_if_needed(manager& m, vector<column> & cols);
|
||||||
void save_var_pos(svector<int> & result_map) const;
|
void save_var_pos(svector<int> & result_map, unsigned_vector& idxs) const;
|
||||||
void reset_var_pos(svector<int> & result_map) const;
|
|
||||||
bool is_coeff_of(var_t v, numeral const & expected) const;
|
bool is_coeff_of(var_t v, numeral const & expected) const;
|
||||||
int get_idx_of(var_t v) const;
|
int get_idx_of(var_t v) const;
|
||||||
};
|
};
|
||||||
|
@ -125,6 +124,7 @@ namespace simplex {
|
||||||
svector<unsigned> m_dead_rows; // rows to recycle
|
svector<unsigned> m_dead_rows; // rows to recycle
|
||||||
vector<column> m_columns; // per var
|
vector<column> m_columns; // per var
|
||||||
svector<int> m_var_pos; // temporary map from variables to positions in row
|
svector<int> m_var_pos; // temporary map from variables to positions in row
|
||||||
|
unsigned_vector m_var_pos_idx; // indices in m_var_pos
|
||||||
|
|
||||||
bool well_formed_row(unsigned row_id) const;
|
bool well_formed_row(unsigned row_id) const;
|
||||||
bool well_formed_column(unsigned column_id) const;
|
bool well_formed_column(unsigned column_id) const;
|
||||||
|
@ -138,7 +138,7 @@ namespace simplex {
|
||||||
class row {
|
class row {
|
||||||
unsigned m_id;
|
unsigned m_id;
|
||||||
public:
|
public:
|
||||||
row(unsigned r):m_id(r) {}
|
explicit row(unsigned r):m_id(r) {}
|
||||||
row():m_id(UINT_MAX) {}
|
row():m_id(UINT_MAX) {}
|
||||||
bool operator!=(row const& other) const {
|
bool operator!=(row const& other) const {
|
||||||
return m_id != other.m_id;
|
return m_id != other.m_id;
|
||||||
|
@ -149,7 +149,7 @@ namespace simplex {
|
||||||
void ensure_var(var_t v);
|
void ensure_var(var_t v);
|
||||||
|
|
||||||
row mk_row();
|
row mk_row();
|
||||||
void add(row r, numeral const& n, var_t var);
|
void add_var(row r, numeral const& n, var_t var);
|
||||||
void add(row r, numeral const& n, row src);
|
void add(row r, numeral const& n, row src);
|
||||||
void mul(row r, numeral const& n);
|
void mul(row r, numeral const& n);
|
||||||
void neg(row r);
|
void neg(row r);
|
||||||
|
|
|
@ -134,31 +134,18 @@ namespace simplex {
|
||||||
\brief Fill the map var -> pos/idx
|
\brief Fill the map var -> pos/idx
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inline void sparse_matrix<Ext>::_row::save_var_pos(svector<int> & result_map) const {
|
inline void sparse_matrix<Ext>::_row::save_var_pos(svector<int> & result_map, unsigned_vector& idxs) const {
|
||||||
typename vector<_row_entry>::const_iterator it = m_entries.begin();
|
typename vector<_row_entry>::const_iterator it = m_entries.begin();
|
||||||
typename vector<_row_entry>::const_iterator end = m_entries.end();
|
typename vector<_row_entry>::const_iterator end = m_entries.end();
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
for (; it != end; ++it, ++idx) {
|
for (; it != end; ++it, ++idx) {
|
||||||
if (!it->is_dead()) {
|
if (!it->is_dead()) {
|
||||||
result_map[it->m_var] = idx;
|
result_map[it->m_var] = idx;
|
||||||
|
idxs.push_back(it->m_var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
\brief Reset the map var -> pos/idx. That is for all variables v in the row, set result[v] = -1
|
|
||||||
This method can be viewed as the "inverse" of save_var_pos.
|
|
||||||
*/
|
|
||||||
template<typename Ext>
|
|
||||||
inline void sparse_matrix<Ext>::_row::reset_var_pos(svector<int> & result_map) const {
|
|
||||||
typename vector<_row_entry>::const_iterator it = m_entries.begin();
|
|
||||||
typename vector<_row_entry>::const_iterator end = m_entries.end();
|
|
||||||
for (; it != end; ++it) {
|
|
||||||
if (!it->is_dead()) {
|
|
||||||
result_map[it->m_var] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
int sparse_matrix<Ext>::_row::get_idx_of(var_t v) const {
|
int sparse_matrix<Ext>::_row::get_idx_of(var_t v) const {
|
||||||
|
@ -316,7 +303,7 @@ namespace simplex {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void sparse_matrix<Ext>::add(row dst, numeral const& n, var_t v) {
|
void sparse_matrix<Ext>::add_var(row dst, numeral const& n, var_t v) {
|
||||||
_row& r = m_rows[dst.id()];
|
_row& r = m_rows[dst.id()];
|
||||||
column& c = m_columns[v];
|
column& c = m_columns[v];
|
||||||
unsigned r_idx;
|
unsigned r_idx;
|
||||||
|
@ -339,7 +326,7 @@ namespace simplex {
|
||||||
_row & r1 = m_rows[row1.id()];
|
_row & r1 = m_rows[row1.id()];
|
||||||
_row & r2 = m_rows[row2.id()];
|
_row & r2 = m_rows[row2.id()];
|
||||||
|
|
||||||
r1.save_var_pos(m_var_pos);
|
r1.save_var_pos(m_var_pos, m_var_pos_idx);
|
||||||
|
|
||||||
//
|
//
|
||||||
// loop over variables in row2,
|
// loop over variables in row2,
|
||||||
|
@ -376,7 +363,6 @@ namespace simplex {
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
((void) 0)
|
((void) 0)
|
||||||
|
|
||||||
if (m.is_one(n)) {
|
if (m.is_one(n)) {
|
||||||
|
@ -394,7 +380,11 @@ namespace simplex {
|
||||||
m.add(r_entry.m_coeff, tmp, r_entry.m_coeff));
|
m.add(r_entry.m_coeff, tmp, r_entry.m_coeff));
|
||||||
}
|
}
|
||||||
|
|
||||||
r1.reset_var_pos(m_var_pos);
|
// reset m_var_pos:
|
||||||
|
for (unsigned i = 0; i < m_var_pos_idx.size(); ++i) {
|
||||||
|
m_var_pos[m_var_pos_idx[i]] = -1;
|
||||||
|
}
|
||||||
|
m_var_pos_idx.reset();
|
||||||
r1.compress_if_needed(m, m_columns);
|
r1.compress_if_needed(m, m_columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,15 @@ Revision History:
|
||||||
#include "model_smt2_pp.h"
|
#include "model_smt2_pp.h"
|
||||||
#include "model_v2_pp.h"
|
#include "model_v2_pp.h"
|
||||||
#include "fixedpoint_params.hpp"
|
#include "fixedpoint_params.hpp"
|
||||||
#include "scoped_proof.h"
|
|
||||||
|
|
||||||
// template class symbol_table<family_id>;
|
// template class symbol_table<family_id>;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#pragma warning(disable:4800)
|
||||||
|
#pragma warning(disable:4267)
|
||||||
|
#pragma warning(disable:4101)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "duality.h"
|
#include "duality.h"
|
||||||
#include "duality_profiling.h"
|
#include "duality_profiling.h"
|
||||||
|
@ -213,6 +218,9 @@ lbool dl_interface::query(::expr * query) {
|
||||||
catch (Duality::solver::cancel_exception &exn){
|
catch (Duality::solver::cancel_exception &exn){
|
||||||
throw default_exception("duality canceled");
|
throw default_exception("duality canceled");
|
||||||
}
|
}
|
||||||
|
catch (Duality::Solver::Incompleteness &exn){
|
||||||
|
throw default_exception("incompleteness");
|
||||||
|
}
|
||||||
|
|
||||||
// profile!
|
// profile!
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,130 @@
|
||||||
#include "simplex.h"
|
#include "simplex.h"
|
||||||
#include "simplex_def.h"
|
#include "simplex_def.h"
|
||||||
#include "mpq_inf.h"
|
#include "mpq_inf.h"
|
||||||
|
#include "vector.h"
|
||||||
|
#include "rational.h"
|
||||||
|
|
||||||
|
#define R rational
|
||||||
typedef simplex::simplex<simplex::mpz_ext> Simplex;
|
typedef simplex::simplex<simplex::mpz_ext> Simplex;
|
||||||
|
typedef simplex::sparse_matrix<simplex::mpz_ext> sparse_matrix;
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j) {
|
||||||
|
vector<R> nv;
|
||||||
|
nv.resize(2);
|
||||||
|
nv[0] = R(i);
|
||||||
|
nv[1] = R(j);
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j, int k) {
|
||||||
|
vector<R> nv = vec(i, j);
|
||||||
|
nv.push_back(R(k));
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j, int k, int l) {
|
||||||
|
vector<R> nv = vec(i, j, k);
|
||||||
|
nv.push_back(R(l));
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j, int k, int l, int x) {
|
||||||
|
vector<R> nv = vec(i, j, k, l);
|
||||||
|
nv.push_back(R(x));
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j, int k, int l, int x, int y) {
|
||||||
|
vector<R> nv = vec(i, j, k, l, x);
|
||||||
|
nv.push_back(R(y));
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<R> vec(int i, int j, int k, int l, int x, int y, int z) {
|
||||||
|
vector<R> nv = vec(i, j, k, l, x, y);
|
||||||
|
nv.push_back(R(z));
|
||||||
|
return nv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void add_row(Simplex& S, vector<R> const& _v, R const& _b, bool is_eq = false) {
|
||||||
|
unsynch_mpz_manager m;
|
||||||
|
unsigned_vector vars;
|
||||||
|
vector<R> v(_v);
|
||||||
|
R b(_b);
|
||||||
|
R l(denominator(b));
|
||||||
|
scoped_mpz_vector coeffs(m);
|
||||||
|
for (unsigned i = 0; i < v.size(); ++i) {
|
||||||
|
l = lcm(l, denominator(v[i]));
|
||||||
|
vars.push_back(i);
|
||||||
|
S.ensure_var(i);
|
||||||
|
}
|
||||||
|
b *= l;
|
||||||
|
b.neg();
|
||||||
|
for (unsigned i = 0; i < v.size(); ++i) {
|
||||||
|
v[i] *= l;
|
||||||
|
coeffs.push_back(v[i].to_mpq().numerator());
|
||||||
|
}
|
||||||
|
unsigned nv = S.get_num_vars();
|
||||||
|
vars.push_back(nv);
|
||||||
|
vars.push_back(nv+1);
|
||||||
|
S.ensure_var(nv);
|
||||||
|
S.ensure_var(nv+1);
|
||||||
|
coeffs.push_back(mpz(-1));
|
||||||
|
coeffs.push_back(b.to_mpq().numerator());
|
||||||
|
mpq_inf one(mpq(1),mpq(0));
|
||||||
|
mpq_inf zero(mpq(0),mpq(0));
|
||||||
|
SASSERT(vars.size() == coeffs.size());
|
||||||
|
S.set_lower(nv, zero);
|
||||||
|
if (is_eq) S.set_upper(nv, zero);
|
||||||
|
S.set_lower(nv+1, one);
|
||||||
|
S.set_upper(nv+1, one);
|
||||||
|
S.add_row(nv, coeffs.size(), vars.c_ptr(), coeffs.c_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void feas(Simplex& S) {
|
||||||
|
S.display(std::cout);
|
||||||
|
lbool is_sat = S.make_feasible();
|
||||||
|
std::cout << "feasible: " << is_sat << "\n";
|
||||||
|
S.display(std::cout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test1() {
|
||||||
|
Simplex S;
|
||||||
|
add_row(S, vec(1,0), R(1));
|
||||||
|
add_row(S, vec(0,1), R(1));
|
||||||
|
add_row(S, vec(1,1), R(1));
|
||||||
|
feas(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test2() {
|
||||||
|
Simplex S;
|
||||||
|
add_row(S, vec(1, 0), R(1));
|
||||||
|
add_row(S, vec(0, 1), R(1));
|
||||||
|
add_row(S, vec(1, 1), R(1), true);
|
||||||
|
feas(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test3() {
|
||||||
|
Simplex S;
|
||||||
|
add_row(S, vec(-1, 0), R(-1));
|
||||||
|
add_row(S, vec(0, -1), R(-1));
|
||||||
|
add_row(S, vec(1, 1), R(1), true);
|
||||||
|
feas(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test4() {
|
||||||
|
Simplex S;
|
||||||
|
add_row(S, vec(1, 0), R(1));
|
||||||
|
add_row(S, vec(0, -1), R(-1));
|
||||||
|
add_row(S, vec(1, 1), R(1), true);
|
||||||
|
feas(S);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tst_simplex() {
|
void tst_simplex() {
|
||||||
simplex::sparse_matrix<simplex::mpz_ext> M;
|
|
||||||
Simplex S;
|
Simplex S;
|
||||||
|
|
||||||
std::cout << "simplex\n";
|
std::cout << "simplex\n";
|
||||||
|
@ -37,4 +156,9 @@ void tst_simplex() {
|
||||||
is_sat = S.make_feasible();
|
is_sat = S.make_feasible();
|
||||||
std::cout << "feasible: " << is_sat << "\n";
|
std::cout << "feasible: " << is_sat << "\n";
|
||||||
S.display(std::cout);
|
S.display(std::cout);
|
||||||
|
|
||||||
|
test1();
|
||||||
|
test2();
|
||||||
|
test3();
|
||||||
|
test4();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue