3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-20 07:36:38 +00:00

Merge branch 'master' into polysat

This commit is contained in:
Jakob Rath 2023-02-01 16:28:57 +01:00
commit 20b5455d08
669 changed files with 26145 additions and 20652 deletions

View file

@ -56,9 +56,10 @@ jobs:
./test-z3 -a
cd -
# Disabled: ${{github.workspace}}/build/examples/c_example_build_dir/c_example
- name: Run examples
run: |
${{github.workspace}}/build/examples/c_example_build_dir/c_example
${{github.workspace}}/build/examples/cpp_example_build_dir/cpp_example
${{github.workspace}}/build/examples/tptp_build_dir/z3_tptp5 --help
${{github.workspace}}/build/examples/c_maxsat_example_build_dir/c_maxsat_example ${{github.workspace}}/examples/maxsat/ex.smt

View file

@ -41,7 +41,7 @@ jobs:
type=edge
type=sha,prefix=ubuntu-20.04-bare-z3-sha-
- name: Build and push Bare Z3 Docker Image
uses: docker/build-push-action@v3.1.1
uses: docker/build-push-action@v4.0.0
with:
context: .
push: true

View file

@ -1,9 +1,12 @@
name: MSVC Static Build
on:
push:
pull_request:
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build:
runs-on: windows-2019

View file

@ -36,7 +36,7 @@ jobs:
cp ../../../LICENSE.txt .
- name: Setup emscripten
uses: mymindstorm/setup-emsdk@v11
uses: mymindstorm/setup-emsdk@v12
with:
no-install: true
version: ${{env.EM_VERSION}}

View file

@ -29,7 +29,7 @@ jobs:
node-version: "lts/*"
- name: Setup emscripten
uses: mymindstorm/setup-emsdk@v11
uses: mymindstorm/setup-emsdk@v12
with:
no-install: true
version: ${{env.EM_VERSION}}

3
.gitignore vendored
View file

@ -81,6 +81,8 @@ src/api/js/node_modules/
src/api/js/build/
src/api/js/**/*.__GENERATED__.*
debug/*
examples/python/z3
examples/python/libz3.dll
out/**
*.bak
@ -93,3 +95,4 @@ CMakeSettings.json
*.swp
.DS_Store
dbg/**
*.wsp

View file

@ -2,7 +2,7 @@
cmake_minimum_required(VERSION 3.4)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake")
project(Z3 VERSION 4.11.3.0 LANGUAGES CXX C)
project(Z3 VERSION 4.12.2.0 LANGUAGES CXX C)
################################################################################
# Project version

View file

@ -1,605 +0,0 @@
## Module pi
Description: pattern inference (heuristics) for universal formulas (without annotation)
Parameter | Type | Description | Default
----------|------|-------------|--------
arith | unsigned int | 0 - do not infer patterns with arithmetic terms, 1 - use patterns with arithmetic terms if there is no other pattern, 2 - always use patterns with arithmetic terms | 1
arith_weight | unsigned int | default weight for quantifiers where the only available pattern has nested arithmetic terms | 5
block_loop_patterns | bool | block looping patterns during pattern inference | true
max_multi_patterns | unsigned int | when patterns are not provided, the prover uses a heuristic to infer them, this option sets the threshold on the number of extra multi-patterns that can be created; by default, the prover creates at most one multi-pattern when there is no unary pattern | 0
non_nested_arith_weight | unsigned int | default weight for quantifiers where the only available pattern has non nested arithmetic terms | 10
pull_quantifiers | bool | pull nested quantifiers, if no pattern was found | true
use_database | bool | use pattern database | false
warnings | bool | enable/disable warning messages in the pattern inference module | false
## Module tactic
Description: tactic parameters
Parameter | Type | Description | Default
----------|------|-------------|--------
blast_term_ite.max_inflation | unsigned int | multiplicative factor of initial term size. | 4294967295
blast_term_ite.max_steps | unsigned int | maximal number of steps allowed for tactic. | 4294967295
default_tactic | symbol | overwrite default tactic in strategic solver |
propagate_values.max_rounds | unsigned int | maximal number of rounds to propagate values. | 4
solve_eqs.context_solve | bool | solve equalities within disjunctions. | true
solve_eqs.ite_solver | bool | use if-then-else solvers. | true
solve_eqs.max_occs | unsigned int | maximum number of occurrences for considering a variable for gaussian eliminations. | 4294967295
solve_eqs.theory_solver | bool | use theory solvers. | true
## Module pp
Description: pretty printer
Parameter | Type | Description | Default
----------|------|-------------|--------
bounded | bool | ignore characters exceeding max width | false
bv_literals | bool | use Bit-Vector literals (e.g, #x0F and #b0101) during pretty printing | true
bv_neg | bool | use bvneg when displaying Bit-Vector literals where the most significant bit is 1 | false
decimal | bool | pretty print real numbers using decimal notation (the output may be truncated). Z3 adds a ? if the value is not precise | false
decimal_precision | unsigned int | maximum number of decimal places to be used when pp.decimal=true | 10
fixed_indent | bool | use a fixed indentation for applications | false
flat_assoc | bool | flat associative operators (when pretty printing SMT2 terms/formulas) | true
fp_real_literals | bool | use real-numbered floating point literals (e.g, +1.0p-1) during pretty printing | false
max_depth | unsigned int | max. term depth (when pretty printing SMT2 terms/formulas) | 5
max_indent | unsigned int | max. indentation in pretty printer | 4294967295
max_num_lines | unsigned int | max. number of lines to be displayed in pretty printer | 4294967295
max_ribbon | unsigned int | max. ribbon (width - indentation) in pretty printer | 80
max_width | unsigned int | max. width in pretty printer | 80
min_alias_size | unsigned int | min. size for creating an alias for a shared term (when pretty printing SMT2 terms/formulas) | 10
pretty_proof | bool | use slower, but prettier, printer for proofs | false
simplify_implies | bool | simplify nested implications for pretty printing | true
single_line | bool | ignore line breaks when true | false
## Module sat
Description: propositional SAT solver
Parameter | Type | Description | Default
----------|------|-------------|--------
abce | bool | eliminate blocked clauses using asymmetric literals | false
acce | bool | eliminate covered clauses using asymmetric added literals | false
anf | bool | enable ANF based simplification in-processing | false
anf.delay | unsigned int | delay ANF simplification by in-processing round | 2
anf.exlin | bool | enable extended linear simplification | false
asymm_branch | bool | asymmetric branching | true
asymm_branch.all | bool | asymmetric branching on all literals per clause | false
asymm_branch.delay | unsigned int | number of simplification rounds to wait until invoking asymmetric branch simplification | 1
asymm_branch.limit | unsigned int | approx. maximum number of literals visited during asymmetric branching | 100000000
asymm_branch.rounds | unsigned int | maximal number of rounds to run asymmetric branch simplifications if progress is made | 2
asymm_branch.sampled | bool | use sampling based asymmetric branching based on binary implication graph | true
ate | bool | asymmetric tautology elimination | true
backtrack.conflicts | unsigned int | number of conflicts before enabling chronological backtracking | 4000
backtrack.scopes | unsigned int | number of scopes to enable chronological backtracking | 100
bca | bool | blocked clause addition - add blocked binary clauses | false
bce | bool | eliminate blocked clauses | false
bce_at | unsigned int | eliminate blocked clauses only once at the given simplification round | 2
bce_delay | unsigned int | delay eliminate blocked clauses until simplification round | 2
binspr | bool | enable SPR inferences of binary propagation redundant clauses. This inprocessing step eliminates models | false
blocked_clause_limit | unsigned int | maximum number of literals visited during blocked clause elimination | 100000000
branching.anti_exploration | bool | apply anti-exploration heuristic for branch selection | false
branching.heuristic | symbol | branching heuristic vsids, chb | vsids
burst_search | unsigned int | number of conflicts before first global simplification | 100
cardinality.encoding | symbol | encoding used for at-most-k constraints: grouped, bimander, ordered, unate, circuit | grouped
cardinality.solver | bool | use cardinality solver | true
cce | bool | eliminate covered clauses | false
core.minimize | bool | minimize computed core | false
core.minimize_partial | bool | apply partial (cheap) core minimization | false
cut | bool | enable AIG based simplification in-processing | false
cut.aig | bool | extract aigs (and ites) from cluases for cut simplification | false
cut.delay | unsigned int | delay cut simplification by in-processing round | 2
cut.dont_cares | bool | integrate dont cares with cuts | true
cut.force | bool | force redoing cut-enumeration until a fixed-point | false
cut.lut | bool | extract luts from clauses for cut simplification | false
cut.npn3 | bool | extract 3 input functions from clauses for cut simplification | false
cut.redundancies | bool | integrate redundancy checking of cuts | true
cut.xor | bool | extract xors from clauses for cut simplification | false
ddfw.init_clause_weight | unsigned int | initial clause weight for DDFW local search | 8
ddfw.reinit_base | unsigned int | increment basis for geometric backoff scheme of re-initialization of weights | 10000
ddfw.restart_base | unsigned int | number of flips used a starting point for hessitant restart backoff | 100000
ddfw.threads | unsigned int | number of ddfw threads to run in parallel with sat solver | 0
ddfw.use_reward_pct | unsigned int | percentage to pick highest reward variable when it has reward 0 | 15
ddfw_search | bool | use ddfw local search instead of CDCL | false
dimacs.core | bool | extract core from DIMACS benchmarks | false
drat.activity | bool | dump variable activities | false
drat.binary | bool | use Binary DRAT output format | false
drat.check_sat | bool | build up internal trace, check satisfying model | false
drat.check_unsat | bool | build up internal proof and check | false
drat.file | symbol | file to dump DRAT proofs |
drup.trim | bool | build and trim drup proof | false
dyn_sub_res | bool | dynamic subsumption resolution for minimizing learned clauses | true
elim_vars | bool | enable variable elimination using resolution during simplification | true
elim_vars_bdd | bool | enable variable elimination using BDD recompilation during simplification | true
elim_vars_bdd_delay | unsigned int | delay elimination of variables using BDDs until after simplification round | 3
enable_pre_simplify | bool | enable pre simplifications before the bounded search | false
euf | bool | enable euf solver (this feature is preliminary and not ready for general consumption) | false
force_cleanup | bool | force cleanup to remove tautologies and simplify clauses | false
gc | symbol | garbage collection strategy: psm, glue, glue_psm, dyn_psm | glue_psm
gc.burst | bool | perform eager garbage collection during initialization | false
gc.defrag | bool | defragment clauses when garbage collecting | true
gc.increment | unsigned int | increment to the garbage collection threshold | 500
gc.initial | unsigned int | learned clauses garbage collection frequency | 20000
gc.k | unsigned int | learned clauses that are inactive for k gc rounds are permanently deleted (only used in dyn_psm) | 7
gc.small_lbd | unsigned int | learned clauses with small LBD are never deleted (only used in dyn_psm) | 3
inprocess.max | unsigned int | maximal number of inprocessing passes | 4294967295
inprocess.out | symbol | file to dump result of the first inprocessing step and exit |
local_search | bool | use local search instead of CDCL | false
local_search_dbg_flips | bool | write debug information for number of flips | false
local_search_mode | symbol | local search algorithm, either default wsat or qsat | wsat
local_search_threads | unsigned int | number of local search threads to find satisfiable solution | 0
lookahead.cube.cutoff | symbol | cutoff type used to create lookahead cubes: depth, freevars, psat, adaptive_freevars, adaptive_psat | depth
lookahead.cube.depth | unsigned int | cut-off depth to create cubes. Used when lookahead.cube.cutoff is depth. | 1
lookahead.cube.fraction | double | adaptive fraction to create lookahead cubes. Used when lookahead.cube.cutoff is adaptive_freevars or adaptive_psat | 0.4
lookahead.cube.freevars | double | cube free variable fraction. Used when lookahead.cube.cutoff is freevars | 0.8
lookahead.cube.psat.clause_base | double | clause base for PSAT cutoff | 2
lookahead.cube.psat.trigger | double | trigger value to create lookahead cubes for PSAT cutoff. Used when lookahead.cube.cutoff is psat | 5
lookahead.cube.psat.var_exp | double | free variable exponent for PSAT cutoff | 1
lookahead.delta_fraction | double | number between 0 and 1, the smaller the more literals are selected for double lookahead | 1.0
lookahead.double | bool | enable doubld lookahead | true
lookahead.global_autarky | bool | prefer to branch on variables that occur in clauses that are reduced | false
lookahead.preselect | bool | use pre-selection of subset of variables for branching | false
lookahead.reward | symbol | select lookahead heuristic: ternary, heule_schur (Heule Schur), heuleu (Heule Unit), unit, or march_cu | march_cu
lookahead.use_learned | bool | use learned clauses when selecting lookahead literal | false
lookahead_scores | bool | extract lookahead scores. A utility that can only be used from the DIMACS front-end | false
lookahead_simplify | bool | use lookahead solver during simplification | false
lookahead_simplify.bca | bool | add learned binary clauses as part of lookahead simplification | true
max_conflicts | unsigned int | maximum number of conflicts | 4294967295
max_memory | unsigned int | maximum amount of memory in megabytes | 4294967295
minimize_lemmas | bool | minimize learned clauses | true
override_incremental | bool | override incremental safety gaps. Enable elimination of blocked clauses and variables even if solver is reused | false
pb.lemma_format | symbol | generate either cardinality or pb lemmas | cardinality
pb.min_arity | unsigned int | minimal arity to compile pb/cardinality constraints to CNF | 9
pb.resolve | symbol | resolution strategy for boolean algebra solver: cardinality, rounding | cardinality
pb.solver | symbol | method for handling Pseudo-Boolean constraints: circuit (arithmetical circuit), sorting (sorting circuit), totalizer (use totalizer encoding), binary_merge, segmented, solver (use native solver) | solver
phase | symbol | phase selection strategy: always_false, always_true, basic_caching, random, caching | caching
phase.sticky | bool | use sticky phase caching | true
prob_search | bool | use probsat local search instead of CDCL | false
probing | bool | apply failed literal detection during simplification | true
probing_binary | bool | probe binary clauses | true
probing_cache | bool | add binary literals as lemmas | true
probing_cache_limit | unsigned int | cache binaries unless overall memory usage exceeds cache limit | 1024
probing_limit | unsigned int | limit to the number of probe calls | 5000000
propagate.prefetch | bool | prefetch watch lists for assigned literals | true
random_freq | double | frequency of random case splits | 0.01
random_seed | unsigned int | random seed | 0
reorder.activity_scale | unsigned int | scaling factor for activity update | 100
reorder.base | unsigned int | number of conflicts per random reorder | 4294967295
reorder.itau | double | inverse temperature for softmax | 4.0
rephase.base | unsigned int | number of conflicts per rephase | 1000
resolution.cls_cutoff1 | unsigned int | limit1 - total number of problems clauses for the second cutoff of Boolean variable elimination | 100000000
resolution.cls_cutoff2 | unsigned int | limit2 - total number of problems clauses for the second cutoff of Boolean variable elimination | 700000000
resolution.limit | unsigned int | approx. maximum number of literals visited during variable elimination | 500000000
resolution.lit_cutoff_range1 | unsigned int | second cutoff (total number of literals) for Boolean variable elimination, for problems containing less than res_cls_cutoff1 clauses | 700
resolution.lit_cutoff_range2 | unsigned int | second cutoff (total number of literals) for Boolean variable elimination, for problems containing more than res_cls_cutoff1 and less than res_cls_cutoff2 | 400
resolution.lit_cutoff_range3 | unsigned int | second cutoff (total number of literals) for Boolean variable elimination, for problems containing more than res_cls_cutoff2 | 300
resolution.occ_cutoff | unsigned int | first cutoff (on number of positive/negative occurrences) for Boolean variable elimination | 10
resolution.occ_cutoff_range1 | unsigned int | second cutoff (number of positive/negative occurrences) for Boolean variable elimination, for problems containing less than res_cls_cutoff1 clauses | 8
resolution.occ_cutoff_range2 | unsigned int | second cutoff (number of positive/negative occurrences) for Boolean variable elimination, for problems containing more than res_cls_cutoff1 and less than res_cls_cutoff2 | 5
resolution.occ_cutoff_range3 | unsigned int | second cutoff (number of positive/negative occurrences) for Boolean variable elimination, for problems containing more than res_cls_cutoff2 | 3
restart | symbol | restart strategy: static, luby, ema or geometric | ema
restart.emafastglue | double | ema alpha factor for fast moving average | 0.03
restart.emaslowglue | double | ema alpha factor for slow moving average | 1e-05
restart.factor | double | restart increment factor for geometric strategy | 1.5
restart.fast | bool | use fast restart approach only removing less active literals. | true
restart.initial | unsigned int | initial restart (number of conflicts) | 2
restart.margin | double | margin between fast and slow restart factors. For ema | 1.1
restart.max | unsigned int | maximal number of restarts. | 4294967295
retain_blocked_clauses | bool | retain blocked clauses as lemmas | true
scc | bool | eliminate Boolean variables by computing strongly connected components | true
scc.tr | bool | apply transitive reduction, eliminate redundant binary clauses | true
search.sat.conflicts | unsigned int | period for solving for sat (in number of conflicts) | 400
search.unsat.conflicts | unsigned int | period for solving for unsat (in number of conflicts) | 400
simplify.delay | unsigned int | set initial delay of simplification by a conflict count | 0
subsumption | bool | eliminate subsumed clauses | true
subsumption.limit | unsigned int | approx. maximum number of literals visited during subsumption (and subsumption resolution) | 100000000
threads | unsigned int | number of parallel threads to use | 1
variable_decay | unsigned int | multiplier (divided by 100) for the VSIDS activity increment | 110
## Module solver
Description: solver parameters
Parameter | Type | Description | Default
----------|------|-------------|--------
axioms2files | bool | print negated theory axioms to separate files during search | false
cancel_backup_file | symbol | file to save partial search state if search is canceled |
lemmas2console | bool | print lemmas during search | false
smtlib2_log | symbol | file to save solver interaction |
timeout | unsigned int | timeout on the solver object; overwrites a global timeout | 4294967295
## Module opt
Description: optimization parameters
Parameter | Type | Description | Default
----------|------|-------------|--------
dump_benchmarks | bool | dump benchmarks for profiling | false
dump_models | bool | display intermediary models to stdout | false
elim_01 | bool | eliminate 01 variables | true
enable_core_rotate | bool | enable core rotation to both sample cores and correction sets | false
enable_lns | bool | enable LNS during weighted maxsat | false
enable_sat | bool | enable the new SAT core for propositional constraints | true
enable_sls | bool | enable SLS tuning during weighted maxsat | false
incremental | bool | set incremental mode. It disables pre-processing and enables adding constraints in model event handler | false
lns_conflicts | unsigned int | initial conflict count for LNS search | 1000
maxlex.enable | bool | enable maxlex heuristic for lexicographic MaxSAT problems | true
maxres.add_upper_bound_block | bool | restict upper bound with constraint | false
maxres.hill_climb | bool | give preference for large weight cores | true
maxres.max_core_size | unsigned int | break batch of generated cores if size reaches this number | 3
maxres.max_correction_set_size | unsigned int | allow generating correction set constraints up to maximal size | 3
maxres.max_num_cores | unsigned int | maximal number of cores per round | 200
maxres.maximize_assignment | bool | find an MSS/MCS to improve current assignment | false
maxres.pivot_on_correction_set | bool | reduce soft constraints if the current correction set is smaller than current core | true
maxres.wmax | bool | use weighted theory solver to constrain upper bounds | false
maxsat_engine | symbol | select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres', 'maxres-bin', 'rc2' | maxres
optsmt_engine | symbol | select optimization engine: 'basic', 'symba' | basic
pb.compile_equality | bool | compile arithmetical equalities into pseudo-Boolean equality (instead of two inequalites) | false
pp.neat | bool | use neat (as opposed to less readable, but faster) pretty printer when displaying context | true
pp.wcnf | bool | print maxsat benchmark into wcnf format | false
priority | symbol | select how to priortize objectives: 'lex' (lexicographic), 'pareto', 'box' | lex
rc2.totalizer | bool | use totalizer for rc2 encoding | true
rlimit | unsigned int | resource limit (0 means no limit) | 0
solution_prefix | symbol | path prefix to dump intermediary, but non-optimal, solutions |
timeout | unsigned int | timeout (in milliseconds) (UINT_MAX and 0 mean no timeout) | 4294967295
## Module parallel
Description: parameters for parallel solver
Parameter | Type | Description | Default
----------|------|-------------|--------
conquer.backtrack_frequency | unsigned int | frequency to apply core minimization during conquer | 10
conquer.batch_size | unsigned int | number of cubes to batch together for fast conquer | 100
conquer.delay | unsigned int | delay of cubes until applying conquer | 10
conquer.restart.max | unsigned int | maximal number of restarts during conquer phase | 5
enable | bool | enable parallel solver by default on selected tactics (for QF_BV) | false
simplify.exp | double | restart and inprocess max is multiplied by simplify.exp ^ depth | 1
simplify.inprocess.max | unsigned int | maximal number of inprocessing steps during simplification | 2
simplify.max_conflicts | unsigned int | maximal number of conflicts during simplifcation phase | 4294967295
simplify.restart.max | unsigned int | maximal number of restarts during simplification phase | 5000
threads.max | unsigned int | caps maximal number of threads below the number of processors | 10000
## Module nnf
Description: negation normal form
Parameter | Type | Description | Default
----------|------|-------------|--------
ignore_labels | bool | remove/ignore labels in the input formula, this option is ignored if proofs are enabled | false
max_memory | unsigned int | maximum amount of memory in megabytes | 4294967295
mode | symbol | NNF translation mode: skolem (skolem normal form), quantifiers (skolem normal form + quantifiers in NNF), full | skolem
sk_hack | bool | hack for VCC | false
## Module algebraic
Description: real algebraic number package. Non-default parameter settings are not supported
Parameter | Type | Description | Default
----------|------|-------------|--------
factor | bool | use polynomial factorization to simplify polynomials representing algebraic numbers | true
factor_max_prime | unsigned int | parameter for the polynomial factorization procedure in the algebraic number module. Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. This parameter limits the maximum prime number p to be used in the first step | 31
factor_num_primes | unsigned int | parameter for the polynomial factorization procedure in the algebraic number module. Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. The search space may be reduced by factoring the polynomial in different GF(p)'s. This parameter specify the maximum number of finite factorizations to be considered, before lifiting and searching | 1
factor_search_size | unsigned int | parameter for the polynomial factorization procedure in the algebraic number module. Z3 polynomial factorization is composed of three steps: factorization in GF(p), lifting and search. This parameter can be used to limit the search space | 5000
min_mag | unsigned int | Z3 represents algebraic numbers using a (square-free) polynomial p and an isolating interval (which contains one and only one root of p). This interval may be refined during the computations. This parameter specifies whether to cache the value of a refined interval or not. It says the minimal size of an interval for caching purposes is 1/2^16 | 16
zero_accuracy | unsigned int | one of the most time-consuming operations in the real algebraic number module is determining the sign of a polynomial evaluated at a sample point with non-rational algebraic number values. Let k be the value of this option. If k is 0, Z3 uses precise computation. Otherwise, the result of a polynomial evaluation is considered to be 0 if Z3 can show it is inside the interval (-1/2^k, 1/2^k) | 0
## Module combined_solver
Description: combines two solvers: non-incremental (solver1) and incremental (solver2)
Parameter | Type | Description | Default
----------|------|-------------|--------
ignore_solver1 | bool | if true, solver 2 is always used | false
solver2_timeout | unsigned int | fallback to solver 1 after timeout even when in incremental model | 4294967295
solver2_unknown | unsigned int | what should be done when solver 2 returns unknown: 0 - just return unknown, 1 - execute solver 1 if quantifier free problem, 2 - execute solver 1 | 1
## Module rcf
Description: real closed fields
Parameter | Type | Description | Default
----------|------|-------------|--------
clean_denominators | bool | clean denominators before root isolation | true
inf_precision | unsigned int | a value k that is the initial interval size (i.e., (0, 1/2^l)) used as an approximation for infinitesimal values | 24
initial_precision | unsigned int | a value k that is the initial interval size (as 1/2^k) when creating transcendentals and approximated division | 24
lazy_algebraic_normalization | bool | during sturm-seq and square-free polynomial computations, only normalize algebraic polynomial expressions when the defining polynomial is monic | true
max_precision | unsigned int | during sign determination we switch from interval arithmetic to complete methods when the interval size is less than 1/2^k, where k is the max_precision | 128
use_prem | bool | use pseudo-remainder instead of remainder when computing GCDs and Sturm-Tarski sequences | true
ERROR: unknown module 'rewriter, description: new formula simplification module used in the tactic framework'
## Module ackermannization
Description: solving UF via ackermannization
Parameter | Type | Description | Default
----------|------|-------------|--------
eager | bool | eagerly instantiate all congruence rules | true
inc_sat_backend | bool | use incremental SAT | false
sat_backend | bool | use SAT rather than SMT in qfufbv_ackr_tactic | false
## Module nlsat
Description: nonlinear solver
Parameter | Type | Description | Default
----------|------|-------------|--------
check_lemmas | bool | check lemmas on the fly using an independent nlsat solver | false
factor | bool | factor polynomials produced during conflict resolution. | true
inline_vars | bool | inline variables that can be isolated from equations (not supported in incremental mode) | false
lazy | unsigned int | how lazy the solver is. | 0
log_lemmas | bool | display lemmas as self-contained SMT formulas | false
max_conflicts | unsigned int | maximum number of conflicts. | 4294967295
max_memory | unsigned int | maximum amount of memory in megabytes | 4294967295
minimize_conflicts | bool | minimize conflicts | false
randomize | bool | randomize selection of a witness in nlsat. | true
reorder | bool | reorder variables. | true
seed | unsigned int | random seed. | 0
shuffle_vars | bool | use a random variable order. | false
simplify_conflicts | bool | simplify conflicts using equalities before resolving them in nlsat solver. | true
## Module fp
Description: fixedpoint parameters
Parameter | Type | Description | Default
----------|------|-------------|--------
bmc.linear_unrolling_depth | unsigned int | Maximal level to explore | 4294967295
datalog.all_or_nothing_deltas | bool | compile rules so that it is enough for the delta relation in union and widening operations to determine only whether the updated relation was modified or not | false
datalog.check_relation | symbol | name of default relation to check. operations on the default relation will be verified using SMT solving | null
datalog.compile_with_widening | bool | widening will be used to compile recursive rules | false
datalog.dbg_fpr_nonempty_relation_signature | bool | if true, finite_product_relation will attempt to avoid creating inner relation with empty signature by putting in half of the table columns, if it would have been empty otherwise | false
datalog.default_relation | symbol | default relation implementation: external_relation, pentagon | pentagon
datalog.default_table | symbol | default table implementation: sparse, hashtable, bitvector, interval | sparse
datalog.default_table_checked | bool | if true, the default table will be default_table inside a wrapper that checks that its results are the same as of default_table_checker table | false
datalog.default_table_checker | symbol | see default_table_checked | null
datalog.explanations_on_relation_level | bool | if true, explanations are generated as history of each relation, rather than per fact (generate_explanations must be set to true for this option to have any effect) | false
datalog.generate_explanations | bool | produce explanations for produced facts when using the datalog engine | false
datalog.initial_restart_timeout | unsigned int | length of saturation run before the first restart (in ms), zero means no restarts | 0
datalog.magic_sets_for_queries | bool | magic set transformation will be used for queries | false
datalog.output_profile | bool | determines whether profile information should be output when outputting Datalog rules or instructions | false
datalog.print.tuples | bool | determines whether tuples for output predicates should be output | true
datalog.profile_timeout_milliseconds | unsigned int | instructions and rules that took less than the threshold will not be printed when printed the instruction/rule list | 0
datalog.similarity_compressor | bool | rules that differ only in values of constants will be merged into a single rule | true
datalog.similarity_compressor_threshold | unsigned int | if similarity_compressor is on, this value determines how many similar rules there must be in order for them to be merged | 11
datalog.subsumption | bool | if true, removes/filters predicates with total transitions | true
datalog.timeout | unsigned int | Time limit used for saturation | 0
datalog.unbound_compressor | bool | auxiliary relations will be introduced to avoid unbound variables in rule heads | true
datalog.use_map_names | bool | use names from map files when displaying tuples | true
engine | symbol | Select: auto-config, datalog, bmc, spacer | auto-config
generate_proof_trace | bool | trace for 'sat' answer as proof object | false
print_aig | symbol | Dump clauses in AIG text format (AAG) to the given file name |
print_answer | bool | print answer instance(s) to query | false
print_boogie_certificate | bool | print certificate for reachability or non-reachability using a format understood by Boogie | false
print_certificate | bool | print certificate for reachability or non-reachability | false
print_fixedpoint_extensions | bool | use SMT-LIB2 fixedpoint extensions, instead of pure SMT2, when printing rules | true
print_low_level_smt2 | bool | use (faster) low-level SMT2 printer (the printer is scalable but the result may not be as readable) | false
print_statistics | bool | print statistics | false
print_with_variable_declarations | bool | use variable declarations when displaying rules (instead of attempting to use original names) | true
spacer.arith.solver | unsigned int | arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination 4 - utvpi, 5 - infinitary lra, 6 - lra solver | 2
spacer.blast_term_ite_inflation | unsigned int | Maximum inflation for non-Boolean ite-terms expansion: 0 (none), k (multiplicative) | 3
spacer.ctp | bool | Enable counterexample-to-pushing | true
spacer.dump_benchmarks | bool | Dump SMT queries as benchmarks | false
spacer.dump_threshold | double | Threshold in seconds on dumping benchmarks | 5.0
spacer.elim_aux | bool | Eliminate auxiliary variables in reachability facts | true
spacer.eq_prop | bool | Enable equality and bound propagation in arithmetic | true
spacer.gpdr | bool | Use GPDR solving strategy for non-linear CHC | false
spacer.gpdr.bfs | bool | Use BFS exploration strategy for expanding model search | true
spacer.ground_pobs | bool | Ground pobs by using values from a model | true
spacer.iuc | unsigned int | 0 = use old implementation of unsat-core-generation, 1 = use new implementation of IUC generation, 2 = use new implementation of IUC + min-cut optimization | 1
spacer.iuc.arith | unsigned int | 0 = use simple Farkas plugin, 1 = use simple Farkas plugin with constant from other partition (like old unsat-core-generation),2 = use Gaussian elimination optimization (broken), 3 = use additive IUC plugin | 1
spacer.iuc.debug_proof | bool | prints proof used by unsat-core-learner for debugging purposes (debugging) | false
spacer.iuc.old_hyp_reducer | bool | use old hyp reducer instead of new implementation, for debugging only | false
spacer.iuc.print_farkas_stats | bool | prints for each proof how many Farkas lemmas it contains and how many of these participate in the cut (for debugging) | false
spacer.iuc.split_farkas_literals | bool | Split Farkas literals | false
spacer.keep_proxy | bool | keep proxy variables (internal parameter) | true
spacer.logic | symbol | SMT-LIB logic to configure internal SMT solvers |
spacer.max_level | unsigned int | Maximum level to explore | 4294967295
spacer.max_num_contexts | unsigned int | maximal number of contexts to create | 500
spacer.mbqi | bool | Enable mbqi | true
spacer.min_level | unsigned int | Minimal level to explore | 0
spacer.native_mbp | bool | Use native mbp of Z3 | true
spacer.order_children | unsigned int | SPACER: order of enqueuing children in non-linear rules : 0 (original), 1 (reverse), 2 (random) | 0
spacer.p3.share_invariants | bool | Share invariants lemmas | false
spacer.p3.share_lemmas | bool | Share frame lemmas | false
spacer.print_json | symbol | Print pobs tree in JSON format to a given file |
spacer.propagate | bool | Enable propagate/pushing phase | true
spacer.push_pob | bool | push blocked pobs to higher level | false
spacer.push_pob_max_depth | unsigned int | Maximum depth at which push_pob is enabled | 4294967295
spacer.q3 | bool | Allow quantified lemmas in frames | true
spacer.q3.instantiate | bool | Instantiate quantified lemmas | true
spacer.q3.qgen.normalize | bool | normalize cube before quantified generalization | true
spacer.q3.use_qgen | bool | use quantified lemma generalizer | false
spacer.random_seed | unsigned int | Random seed to be used by SMT solver | 0
spacer.reach_dnf | bool | Restrict reachability facts to DNF | true
spacer.reset_pob_queue | bool | SPACER: reset pob obligation queue when entering a new level | true
spacer.restart_initial_threshold | unsigned int | Initial threshold for restarts | 10
spacer.restarts | bool | Enable resetting obligation queue | false
spacer.simplify_lemmas_post | bool | simplify derived lemmas after inductive propagation | false
spacer.simplify_lemmas_pre | bool | simplify derived lemmas before inductive propagation | false
spacer.simplify_pob | bool | simplify pobs by removing redundant constraints | false
spacer.trace_file | symbol | Log file for progress events |
spacer.use_array_eq_generalizer | bool | SPACER: attempt to generalize lemmas with array equalities | true
spacer.use_bg_invs | bool | Enable external background invariants | false
spacer.use_derivations | bool | SPACER: using derivation mechanism to cache intermediate results for non-linear rules | true
spacer.use_euf_gen | bool | Generalize lemmas and pobs using implied equalities | false
spacer.use_inc_clause | bool | Use incremental clause to represent trans | true
spacer.use_inductive_generalizer | bool | generalize lemmas using induction strengthening | true
spacer.use_lemma_as_cti | bool | SPACER: use a lemma instead of a CTI in flexible_trace | false
spacer.use_lim_num_gen | bool | Enable limit numbers generalizer to get smaller numbers | false
spacer.validate_lemmas | bool | Validate each lemma after generalization | false
spacer.weak_abs | bool | Weak abstraction | true
tab.selection | symbol | selection method for tabular strategy: weight (default), first, var-use | weight
validate | bool | validate result (by proof checking or model checking) | false
xform.array_blast | bool | try to eliminate local array terms using Ackermannization -- some array terms may remain | false
xform.array_blast_full | bool | eliminate all local array variables by QE | false
xform.bit_blast | bool | bit-blast bit-vectors | false
xform.coalesce_rules | bool | coalesce rules | false
xform.coi | bool | use cone of influence simplification | true
xform.compress_unbound | bool | compress tails with unbound variables | true
xform.elim_term_ite | bool | Eliminate term-ite expressions | false
xform.elim_term_ite.inflation | unsigned int | Maximum inflation for non-Boolean ite-terms blasting: 0 (none), k (multiplicative) | 3
xform.fix_unbound_vars | bool | fix unbound variables in tail | false
xform.inline_eager | bool | try eager inlining of rules | true
xform.inline_linear | bool | try linear inlining method | true
xform.inline_linear_branch | bool | try linear inlining method with potential expansion | false
xform.instantiate_arrays | bool | Transforms P(a) into P(i, a[i] a) | false
xform.instantiate_arrays.enforce | bool | Transforms P(a) into P(i, a[i]), discards a from predicate | false
xform.instantiate_arrays.nb_quantifier | unsigned int | Gives the number of quantifiers per array | 1
xform.instantiate_arrays.slice_technique | symbol | <no-slicing>=> GetId(i) = i, <smash> => GetId(i) = true | no-slicing
xform.instantiate_quantifiers | bool | instantiate quantified Horn clauses using E-matching heuristic | false
xform.magic | bool | perform symbolic magic set transformation | false
xform.quantify_arrays | bool | create quantified Horn clauses from clauses with arrays | false
xform.scale | bool | add scaling variable to linear real arithmetic clauses | false
xform.slice | bool | simplify clause set using slicing | true
xform.subsumption_checker | bool | Enable subsumption checker (no support for model conversion) | true
xform.tail_simplifier_pve | bool | propagate_variable_equivalences | true
xform.transform_arrays | bool | Rewrites arrays equalities and applies select over store | false
xform.unfold_rules | unsigned int | unfold rules statically using iterative squaring | 0
## Module smt
Description: smt solver based on lazy smt
Parameter | Type | Description | Default
----------|------|-------------|--------
arith.auto_config_simplex | bool | force simplex solver in auto_config | false
arith.bprop_on_pivoted_rows | bool | propagate bounds on rows changed by the pivot operation | true
arith.branch_cut_ratio | unsigned int | branch/cut ratio for linear integer arithmetic | 2
arith.dump_lemmas | bool | dump arithmetic theory lemmas to files | false
arith.eager_eq_axioms | bool | eager equality axioms | true
arith.enable_hnf | bool | enable hnf (Hermite Normal Form) cuts | true
arith.greatest_error_pivot | bool | Pivoting strategy | false
arith.ignore_int | bool | treat integer variables as real | false
arith.int_eq_branch | bool | branching using derived integer equations | false
arith.min | bool | minimize cost | false
arith.nl | bool | (incomplete) nonlinear arithmetic support based on Groebner basis and interval propagation, relevant only if smt.arith.solver=2 | true
arith.nl.branching | bool | branching on integer variables in non linear clusters, relevant only if smt.arith.solver=2 | true
arith.nl.delay | unsigned int | number of calls to final check before invoking bounded nlsat check | 500
arith.nl.expp | bool | expensive patching | false
arith.nl.gr_q | unsigned int | grobner's quota | 10
arith.nl.grobner | bool | run grobner's basis heuristic | true
arith.nl.grobner_cnfl_to_report | unsigned int | grobner's maximum number of conflicts to report | 1
arith.nl.grobner_eqs_growth | unsigned int | grobner's number of equalities growth | 10
arith.nl.grobner_expr_degree_growth | unsigned int | grobner's maximum expr degree growth | 2
arith.nl.grobner_expr_size_growth | unsigned int | grobner's maximum expr size growth | 2
arith.nl.grobner_frequency | unsigned int | grobner's call frequency | 4
arith.nl.grobner_max_simplified | unsigned int | grobner's maximum number of simplifications | 10000
arith.nl.grobner_subs_fixed | unsigned int | 0 - no subs, 1 - substitute, 2 - substitute fixed zeros only | 1
arith.nl.horner | bool | run horner's heuristic | true
arith.nl.horner_frequency | unsigned int | horner's call frequency | 4
arith.nl.horner_row_length_limit | unsigned int | row is disregarded by the heuristic if its length is longer than the value | 10
arith.nl.horner_subs_fixed | unsigned int | 0 - no subs, 1 - substitute, 2 - substitute fixed zeros only | 2
arith.nl.nra | bool | call nra_solver when incremental linearization does not produce a lemma, this option is ignored when arith.nl=false, relevant only if smt.arith.solver=6 | true
arith.nl.order | bool | run order lemmas | true
arith.nl.rounds | unsigned int | threshold for number of (nested) final checks for non linear arithmetic, relevant only if smt.arith.solver=2 | 1024
arith.nl.tangents | bool | run tangent lemmas | true
arith.print_ext_var_names | bool | print external variable names | false
arith.print_stats | bool | print statistic | false
arith.propagate_eqs | bool | propagate (cheap) equalities | true
arith.propagation_mode | unsigned int | 0 - no propagation, 1 - propagate existing literals, 2 - refine finite bounds | 1
arith.random_initial_value | bool | use random initial values in the simplex-based procedure for linear arithmetic | false
arith.rep_freq | unsigned int | the report frequency, in how many iterations print the cost and other info | 0
arith.simplex_strategy | unsigned int | simplex strategy for the solver | 0
arith.solver | unsigned int | arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination 4 - utvpi, 5 - infinitary lra, 6 - lra solver | 6
array.extensional | bool | extensional array theory | true
array.weak | bool | weak array theory | false
auto_config | bool | automatically configure solver | true
bv.delay | bool | delay internalize expensive bit-vector operations | true
bv.enable_int2bv | bool | enable support for int2bv and bv2int operators | true
bv.eq_axioms | bool | enable redundant equality axioms for bit-vectors | true
bv.reflect | bool | create enode for every bit-vector term | true
bv.watch_diseq | bool | use watch lists instead of eager axioms for bit-vectors | false
candidate_models | bool | create candidate models even when quantifier or theory reasoning is incomplete | false
case_split | unsigned int | 0 - case split based on variable activity, 1 - similar to 0, but delay case splits created during the search, 2 - similar to 0, but cache the relevancy, 3 - case split based on relevancy (structural splitting), 4 - case split on relevancy and activity, 5 - case split on relevancy and current goal, 6 - activity-based case split with theory-aware branching activity | 1
clause_proof | bool | record a clausal proof | false
core.extend_nonlocal_patterns | bool | extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier's body | false
core.extend_patterns | bool | extend unsat core with literals that trigger (potential) quantifier instances | false
core.extend_patterns.max_distance | unsigned int | limits the distance of a pattern-extended unsat core | 4294967295
core.minimize | bool | minimize unsat core produced by SMT context | false
core.validate | bool | [internal] validate unsat core produced by SMT context. This option is intended for debugging | false
cube_depth | unsigned int | cube depth. | 1
dack | unsigned int | 0 - disable dynamic ackermannization, 1 - expand Leibniz's axiom if a congruence is the root of a conflict, 2 - expand Leibniz's axiom if a congruence is used during conflict resolution | 1
dack.eq | bool | enable dynamic ackermannization for transtivity of equalities | false
dack.factor | double | number of instance per conflict | 0.1
dack.gc | unsigned int | Dynamic ackermannization garbage collection frequency (per conflict) | 2000
dack.gc_inv_decay | double | Dynamic ackermannization garbage collection decay | 0.8
dack.threshold | unsigned int | number of times the congruence rule must be used before Leibniz's axiom is expanded | 10
delay_units | bool | if true then z3 will not restart when a unit clause is learned | false
delay_units_threshold | unsigned int | maximum number of learned unit clauses before restarting, ignored if delay_units is false | 32
dt_lazy_splits | unsigned int | How lazy datatype splits are performed: 0- eager, 1- lazy for infinite types, 2- lazy | 1
ematching | bool | E-Matching based quantifier instantiation | true
induction | bool | enable generation of induction lemmas | false
lemma_gc_strategy | unsigned int | lemma garbage collection strategy: 0 - fixed, 1 - geometric, 2 - at restart, 3 - none | 0
logic | symbol | logic used to setup the SMT solver |
macro_finder | bool | try to find universally quantified formulas that can be viewed as macros | false
max_conflicts | unsigned int | maximum number of conflicts before giving up. | 4294967295
mbqi | bool | model based quantifier instantiation (MBQI) | true
mbqi.force_template | unsigned int | some quantifiers can be used as templates for building interpretations for functions. Z3 uses heuristics to decide whether a quantifier will be used as a template or not. Quantifiers with weight >= mbqi.force_template are forced to be used as a template | 10
mbqi.id | string | Only use model-based instantiation for quantifiers with id's beginning with string |
mbqi.max_cexs | unsigned int | initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation | 1
mbqi.max_cexs_incr | unsigned int | increment for MBQI_MAX_CEXS, the increment is performed after each round of MBQI | 0
mbqi.max_iterations | unsigned int | maximum number of rounds of MBQI | 1000
mbqi.trace | bool | generate tracing messages for Model Based Quantifier Instantiation (MBQI). It will display a message before every round of MBQI, and the quantifiers that were not satisfied | false
pb.conflict_frequency | unsigned int | conflict frequency for Pseudo-Boolean theory | 1000
pb.learn_complements | bool | learn complement literals for Pseudo-Boolean theory | true
phase_caching_off | unsigned int | number of conflicts while phase caching is off | 100
phase_caching_on | unsigned int | number of conflicts while phase caching is on | 400
phase_selection | unsigned int | phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences, 7 - theory | 3
pull_nested_quantifiers | bool | pull nested quantifiers | false
q.lift_ite | unsigned int | 0 - don not lift non-ground if-then-else, 1 - use conservative ite lifting, 2 - use full lifting of if-then-else under quantifiers | 0
q.lite | bool | Use cheap quantifier elimination during pre-processing | false
qi.cost | string | expression specifying what is the cost of a given quantifier instantiation | (+ weight generation)
qi.eager_threshold | double | threshold for eager quantifier instantiation | 10.0
qi.lazy_threshold | double | threshold for lazy quantifier instantiation | 20.0
qi.max_instances | unsigned int | maximum number of quantifier instantiations | 4294967295
qi.max_multi_patterns | unsigned int | specify the number of extra multi patterns | 0
qi.profile | bool | profile quantifier instantiation | false
qi.profile_freq | unsigned int | how frequent results are reported by qi.profile | 4294967295
qi.quick_checker | unsigned int | specify quick checker mode, 0 - no quick checker, 1 - using unsat instances, 2 - using both unsat and no-sat instances | 0
quasi_macros | bool | try to find universally quantified formulas that are quasi-macros | false
random_seed | unsigned int | random seed for the smt solver | 0
refine_inj_axioms | bool | refine injectivity axioms | true
relevancy | unsigned int | relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant | 2
restart.max | unsigned int | maximal number of restarts. | 4294967295
restart_factor | double | when using geometric (or inner-outer-geometric) progression of restarts, it specifies the constant used to multiply the current restart threshold | 1.1
restart_strategy | unsigned int | 0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic | 1
restricted_quasi_macros | bool | try to find universally quantified formulas that are restricted quasi-macros | false
seq.max_unfolding | unsigned int | maximal unfolding depth for checking string equations and regular expressions | 1000000000
seq.split_w_len | bool | enable splitting guided by length constraints | true
seq.validate | bool | enable self-validation of theory axioms created by seq theory | false
str.aggressive_length_testing | bool | prioritize testing concrete length values over generating more options | false
str.aggressive_unroll_testing | bool | prioritize testing concrete regex unroll counts over generating more options | true
str.aggressive_value_testing | bool | prioritize testing concrete string constant values over generating more options | false
str.fast_length_tester_cache | bool | cache length tester constants instead of regenerating them | false
str.fast_value_tester_cache | bool | cache value tester constants instead of regenerating them | true
str.fixed_length_naive_cex | bool | construct naive counterexamples when fixed-length model construction fails for a given length assignment (Z3str3 only) | true
str.fixed_length_refinement | bool | use abstraction refinement in fixed-length equation solver (Z3str3 only) | false
str.overlap_priority | double | theory-aware priority for overlapping variable cases; use smt.theory_aware_branching=true | -0.1
str.regex_automata_difficulty_threshold | unsigned int | difficulty threshold for regex automata heuristics | 1000
str.regex_automata_failed_automaton_threshold | unsigned int | number of failed automaton construction attempts after which a full automaton is automatically built | 10
str.regex_automata_failed_intersection_threshold | unsigned int | number of failed automaton intersection attempts after which intersection is always computed | 10
str.regex_automata_intersection_difficulty_threshold | unsigned int | difficulty threshold for regex intersection heuristics | 1000
str.regex_automata_length_attempt_threshold | unsigned int | number of length/path constraint attempts before checking unsatisfiability of regex terms | 10
str.string_constant_cache | bool | cache all generated string constants generated from anywhere in theory_str | true
str.strong_arrangements | bool | assert equivalences instead of implications when generating string arrangement axioms | true
string_solver | symbol | solver for string/sequence theories. options are: 'z3str3' (specialized string solver), 'seq' (sequence solver), 'auto' (use static features to choose best solver), 'empty' (a no-op solver that forces an answer unknown if strings were used), 'none' (no solver) | seq
theory_aware_branching | bool | Allow the context to use extra information from theory solvers regarding literal branching prioritization. | false
theory_case_split | bool | Allow the context to use heuristics involving theory case splits, which are a set of literals of which exactly one can be assigned True. If this option is false, the context will generate extra axioms to enforce this instead. | false
threads | unsigned int | maximal number of parallel threads. | 1
threads.cube_frequency | unsigned int | frequency for using cubing | 2
threads.max_conflicts | unsigned int | maximal number of conflicts between rounds of cubing for parallel SMT | 400
## Module sls
Description: Experimental Stochastic Local Search Solver (for QFBV only).
Parameter | Type | Description | Default
----------|------|-------------|--------
early_prune | bool | use early pruning for score prediction | true
max_memory | unsigned int | maximum amount of memory in megabytes | 4294967295
max_restarts | unsigned int | maximum number of restarts | 4294967295
paws_init | unsigned int | initial/minimum assertion weights | 40
paws_sp | unsigned int | smooth assertion weights with probability paws_sp / 1024 | 52
random_offset | bool | use random offset for candidate evaluation | true
random_seed | unsigned int | random seed | 0
rescore | bool | rescore/normalize top-level score every base restart interval | true
restart_base | unsigned int | base restart interval given by moves per run | 100
restart_init | bool | initialize to 0 or random value (= 1) after restart | false
scale_unsat | double | scale score of unsat expressions by this factor | 0.5
track_unsat | bool | keep a list of unsat assertions as done in SAT - currently disabled internally | false
vns_mc | unsigned int | in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit | 0
vns_repick | bool | in local minima, try picking a different assertion (only for walksat) | false
walksat | bool | use walksat assertion selection (instead of gsat) | true
walksat_repick | bool | repick assertion if randomizing in local minima | true
walksat_ucb | bool | use bandit heuristic for walksat assertion selection (instead of random) | true
walksat_ucb_constant | double | the ucb constant c in the term score + c * f(touched) | 20.0
walksat_ucb_forget | double | scale touched by this factor every base restart interval | 1.0
walksat_ucb_init | bool | initialize total ucb touched to formula size | false
walksat_ucb_noise | double | add noise 0 <= 256 * ucb_noise to ucb score for assertion selection | 0.0002
wp | unsigned int | random walk with probability wp / 1024 | 100

View file

@ -10,6 +10,134 @@ Version 4.next
- native word level bit-vector solving.
- introduction of simple induction lemmas to handle a limited repertoire of induction proofs.
Version 4.12.2
==============
- remove MSF (Microsoft Solver Foundation) plugin
- updated propagate-ineqs tactic and implementing it as a simplifier, bound_simplifier.
It now eliminates occurrences of "mod" operators when bounds information
implies that the modulus is redundant. This tactic is useful for
benchmarks created by converting bit-vector semantics to integer
reasoning.
- add API function Z3_mk_real_int64 to take two int64 as arguments. The Z3_mk_real function takes integers.
- Add _simplifiers_ as optional incremental pre-processing to solvers.
They are exposed over the SMTLIB API using the command [`set-simplifier`](https://microsoft.github.io/z3guide/docs/strategies/simplifiers).
Simplifiers are similar to tactics, but they operate on solver state that can be incrementally updated.
The exposed simplifiers cover all the pre-processing techniques used internally with some additional simplifiers, such as `solve-eqs`
and `elim-predicates` that go beyond incremental pre-processing used internally. The advantage of using `solve-eqs` during pre-processing
can be significant. Incremental pre-processing simplification using `solve-eqs` and other simplifiers that change interpretations
was not possible before.
Version 4.12.1
==============
- change macos build to use explicit reference to Macos version 11. Hosted builds are migrating to macos-12 and it broke a user Issue #6539.
Version 4.12.0
==============
- add clause logging API.
- The purpose of logging API and self-checking is to enable an array of use cases.
- proof mining (what instantiations did Z3 use)?
- A refresh of the AxiomProfiler could use the logging API.
The (brittle) trace feature should be deprecated.
- debugging
- a built-in self certifier implements a custom proof checker for
the format used by the new solver (sat.euf=true).
- other potential options:
- integration into certified tool chains
- interpolation
- Z3_register_on_clause (also exposed over C++, Python and .Net)
- it applies to z3's main CDCL(T) core and a new CDCL(T) core (sat.euf=true).
- The added API function allows to register a callback for when clauses
are inferred. More precisely, when clauses are assumed (as part of input),
deleted, or deduced.
Clauses that are deduced by the CDCL SAT engine using standard
inferences are marked as 'rup'.
Clauses that are deduced by theories are marked by default
by 'smt', and when more detailed information
is available with proof hints or proof objects.
Instantations are considered useful to track so they
are logged using terms of the form
(inst (not (forall (x) body)) body[t/x] (bind t)), where
'inst' is a name of a function that produces a proof term representing
the instantiation.
- add options for proof logging, trimming, and checking for the new core.
- sat.smt.proof (symbol) add SMT proof to file (default: )
- sat.smt.proof.check (bool) check SMT proof while it is created (default: false)
- it applies a custom self-validator. The self-validator comprises of
several small checkers and represent a best-effort validation mechanism.
If there are no custom validators associated with inferences, or the custom
validators fail to certify inferences, the self-validator falls back to
invoking z3 (SMT) solving on the lemma.
- euf - propagations and conflicts from congruence closure
(theory of equality and uninterpreted functions) are checked
based on a proof format that tracks uses of congruence closure and
equalities. It only performs union find operations.
- tseitin - clausification steps are checked for Boolean operators.
- farkas, bound, implies_eq - arithmetic inferences that can be justified using
a combination of Farkas lemma and cuts are checked.
Note: the arithmetic solver may produce proof hints that the proof
checker cannot check. It is mainly a limitation
of the arithmetic solver not pulling relevant information.
Ensuring a tight coupling with proof hints and the validator
capabilites is open ended future work and good material for theses.
- bit-vector inferences - are treated as trusted
(there is no validation, it always blindly succeeds)
- arrays, datatypes - there is no custom validation for
other theories at present. Lemmas are validated using SMT.
- sat.smt.proof.check_rup (bool) apply forward RUP proof checking (default: true)
- this option can incur significant runtime overhead.
Effective proof checking relies on first trimming proofs into a
format where dependencies are tracked and then checking relevant inferences.
Turn this option off if you just want to check theory inferences.
- add options to validate proofs offline. It applies to proofs
saved when sat.smt.proof is set to a valid file name.
- solver.proof.check (bool) check proof logs (default: true)
- the option sat.smt.proof_check_rup can be used to control what is checked
- solver.proof.save (bool) save proof log into a proof object
that can be extracted using (get-proof) (default: false)
- experimental: saves a proof log into a term
- solver.proof.trim (bool) trim the offline proof and print the trimmed proof to the console
- experimental: performs DRUP trimming to reduce the set of hypotheses
and inferences relevant to derive the empty clause.
- JS support for Arrays, thanks to Walden Yan
- More portable memory allocation, thanks to Nuno Lopes
(avoid custom handling to calculate memory usage)
- clause logging and proofs: many open-ended directions.
Many directions and functionality features remain in an open-ended state,
subject to fixes, improvements, and contributions.
We list a few of them here:
- comprehensive efficient self-validators for arithmetic, and other theories
- an efficient proof checker when several theory solvers cooperate in a propagation or
conflict. The theory combination case is currently delegated to the smt solver.
The proper setup for integrating theory lemmas is in principle not complicated,
but the implementation requires some changes.
- external efficient proof validators (based on certified tool chains)
can be integrated over the API.
- dampening repeated clauses: A side-effect of conflict resolution is to
log theory lemmas. It often happens that the theory lemma becomes
the conflict clause, that is then logged as rup. Thus, two clauses are
logged.
- support for online trim so that proofs generated using clause logging can be used for SPACER
- SPACER also would benefit from more robust proof hints for arithmetic
lemmas (bounds and implied equalities are sometimes not logged correctly)
- integration into axiom profiling through online and/or offline interfaces.
- an online interface attaches a callback with a running solver. This is available.
- an offline interface saves a clause proof to a file (currently just
supported for sat.euf) and then reads the file in a separate process
The separate process attaches a callback on inferred clauses.
This is currently not available but a relatively small feature.
- more detailed proof hints for the legacy solver clause logger.
Other than quantifier instantiations, no detailed information is retained for
theory clauses.
- integration of pre-processing proofs with logging proofs. There is
currently no supported bridge to create a end-to-end proof objects.
- experimental API for accessing E-graphs. Exposed over Python. This API should be considered temporary
and subject to be changed depending on use cases or removed. The functions are `Z3_solver_congruence_root`, `Z3_solver_congruence_next`.
Version 4.11.2
==============
- add error handling to fromString method in JavaScript

View file

@ -202,7 +202,7 @@ jobs:
setupCmd2: 'julia -e "using libcxxwrap_julia_jll; print(dirname(libcxxwrap_julia_jll.libcxxwrap_julia_path))" > tmp.env'
setupCmd3: 'set /P JlCxxDir=<tmp.env'
bindings: '-DJlCxx_DIR=%JlCxxDir%\..\lib\cmake\JlCxx $(cmakeJava) $(cmakeNet) $(cmakePy) -DCMAKE_BUILD_TYPE=RelWithDebInfo'
runTests: 'True'
runTests: 'False'
arm64:
arch: 'amd64_arm64'
setupCmd1: ''

View file

@ -65,7 +65,7 @@ int parse(string const & filename, map<string, map_entry> & data) {
inx != string::npos;
inx = line.find(" : ", from)) {
tokens[ti] = trim(line.substr(from, inx-from));
from = inx+1;
from = inx+3; //3 is the length of " : "
ti++;
}
if (from != line.length() && ti < 4)

129
doc/mk_tactic_doc.py Normal file
View file

@ -0,0 +1,129 @@
# Copyright (c) Microsoft Corporation 2015
"""
Tactic documentation generator script
"""
import os
import re
import sys
import subprocess
BUILD_DIR='../build'
SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
OUTPUT_DIRECTORY = os.path.join(os.getcwd(), 'api')
def doc_path(path):
return os.path.join(SCRIPT_DIR, path)
is_doc = re.compile("Tactic Documentation")
is_doc_end = re.compile("\-\-\*\/")
is_tac_name = re.compile("## Tactic (.*)")
is_simplifier = re.compile("ADD_SIMPLIFIER\(.*\"([^\"]*)\".*,.*\"([^\"]*)\".*,.*\"([^\"]*)\"\.*\)")
def is_ws(s):
return all([0 for ch in s if ch != ' ' and ch != '\n'])
def extract_params(ous, tac):
z3_exe = BUILD_DIR + "/z3"
out = subprocess.Popen([z3_exe, f"-tacticsmd:{tac}"], stdout=subprocess.PIPE).communicate()[0]
if not out:
return
out = out.decode(sys.stdout.encoding)
if is_ws(out):
return
ous.write("### Parameters\n\n")
for line in out:
ous.write(line.replace("\r",""))
ous.write("\n")
def generate_tactic_doc(ous, f, ins):
tac_name = None
for line in ins:
m = is_tac_name.search(line)
if m:
tac_name = m.group(1)
if is_doc_end.search(line):
if tac_name:
extract_params(ous, tac_name)
break
ous.write(line)
def extract_tactic_doc(ous, f):
with open(f) as ins:
for line in ins:
if is_doc.search(line):
generate_tactic_doc(ous, f, ins)
def generate_simplifier_doc(ous, name, desc):
ous.write("## Simplifier [" + name + "](https://microsoft.github.io/z3guide/docs/strategies/summary/#tactic-" + name + ")\n")
ous.write("### Description\n" + desc + "\n")
def extract_simplifier_doc(ous, f):
with open(f) as ins:
for line in ins:
m = is_simplifier.search(line)
if m:
generate_simplifier_doc(ous, m.group(1), m.group(2))
def find_tactic_name(path):
with open(path) as ins:
for line in ins:
m = is_tac_name.search(line)
if m:
return m.group(1)
print(f"no tactic in {path}")
return ""
def find_simplifier_name(path):
with open(path) as ins:
for line in ins:
m = is_simplifier.search(line)
if m:
return m.group(1)
print(f"no simplifier in {path}")
return ""
def presort_files(find_fn):
tac_files = []
for root, dirs, files in os.walk(doc_path("../src")):
for f in files:
if f.endswith("~"):
continue
if f.endswith("tactic.h") or "simplifiers" in root:
tac_files += [(f, os.path.join(root, f))]
tac_files = sorted(tac_files, key = lambda x: find_fn(x[1]))
return tac_files
def help(ous):
ous.write("---\n")
ous.write("title: Tactics Summary\n")
ous.write("sidebar_position: 6\n")
ous.write("---\n")
tac_files = presort_files(find_tactic_name)
for file, path in tac_files:
extract_tactic_doc(ous, path)
def help_simplifier(ous):
ous.write("---\n")
ous.write("title: Simplifiers Summary\n")
ous.write("sidebar_position: 7\n")
ous.write("---\n")
tac_files = presort_files(find_simplifier_name)
for file, path in tac_files:
extract_simplifier_doc(ous, path)
def mk_dir(d):
if not os.path.exists(d):
os.makedirs(d)
mk_dir(os.path.join(OUTPUT_DIRECTORY, 'md'))
with open(OUTPUT_DIRECTORY + "/md/tactics-summary.md",'w') as ous:
help(ous)
with open(OUTPUT_DIRECTORY + "/md/simplifier-summary.md",'w') as ous:
help_simplifier(ous)

View file

@ -561,6 +561,7 @@ void display_ast(Z3_context c, FILE * out, Z3_ast v)
}
case Z3_QUANTIFIER_AST: {
fprintf(out, "quantifier");
break;
}
default:
fprintf(out, "#unknown");

View file

@ -1,20 +0,0 @@
In order to use Z3 MSF plugin, follow the following steps:
1. Compile latest Z3 .NET API (from any branch consisting of opt features) and copy 'libz3.dll' and 'Microsoft.Z3.dll' to the folder of 'Z3MSFPlugin.sln'.
2. Retrieve 'Microsoft.Solver.Foundation.dll' from http://archive.msdn.microsoft.com/solverfoundation/Release/ProjectReleases.aspx?ReleaseId=1799,
preferably using DLL only version. Copy 'Microsoft.Solver.Foundation.dll' to the folder of 'Z3MSFPlugin.sln'
3. Build 'Z3MSFPlugin.sln'. Note that you have to compile using x86 target for Microsoft.Z3.dll 32-bit and x64 target for Microsoft.Z3.dll 64-bit.
The solution consists of a plugin project, a test project with a few simple test cases and a command line projects for external OML, MPS and SMPS models.
To retrieve SMT2 models which are native to Z3, set the logging file in corresponding directives or solver params e.g.
var p = new Z3MILPParams();
p.SMT2LogFile = "model.smt2";
For more details, check out the commands in 'Validator\Program.cs'.
Enjoy!

View file

@ -1,60 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="MsfConfig"
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
allowLocation="true"
allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true"
requirePermission="true"/>
</configSections>
<MsfConfig>
<MsfPluginSolvers>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MINLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="NLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
</MsfPluginSolvers>
</MsfConfig>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View file

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SolverFoundation.Plugin.Z3.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SolverFoundation.Plugin.Z3.Tests")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("27657eee-ca7b-4996-a905-86a3f4584988")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -1,92 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Solvers;
using Microsoft.SolverFoundation.Services;
using Microsoft.SolverFoundation.Plugin.Z3;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.SolverFoundation.Plugin.Z3.Tests
{
[TestClass]
public class ServiceTests
{
[TestInitialize]
public void SetUp()
{
SolverContext context = SolverContext.GetContext();
context.ClearModel();
}
private void TestService1(Directive directive)
{
SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();
Decision x1 = new Decision(Domain.RealRange(0, 2), "x1");
Decision x2 = new Decision(Domain.RealRange(0, 2), "x2");
Decision z = new Decision(Domain.IntegerRange(0, 1), "z");
model.AddDecisions(x1, x2, z);
model.AddConstraint("Row0", x1 - z <= 1);
model.AddConstraint("Row1", x2 + z <= 2);
Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, x1 + x2);
Solution solution = context.Solve(directive);
Assert.IsTrue(goal.ToInt32() == 3);
context.ClearModel();
}
private void TestService2(Directive directive)
{
SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();
Decision x1 = new Decision(Domain.RealNonnegative, "x1");
Decision x2 = new Decision(Domain.RealNonnegative, "x2");
Decision z = new Decision(Domain.IntegerRange(0, 1), "z");
Rational M = 100;
model.AddDecisions(x1, x2, z);
model.AddConstraint("Row0", x1 + x2 >= 1);
model.AddConstraint("Row1", x1 - z * 100 <= 0);
model.AddConstraint("Row2", x2 + z * 100 <= 100);
Goal goal = model.AddGoal("Goal0", GoalKind.Maximize, x1 + x2);
Solution solution = context.Solve(directive);
Assert.IsTrue(goal.ToInt32() == 100);
context.ClearModel();
}
[TestMethod]
public void TestService1()
{
TestService1(new Z3MILPDirective());
TestService1(new Z3TermDirective());
}
[TestMethod]
public void TestService2()
{
TestService2(new Z3MILPDirective());
TestService2(new Z3TermDirective());
}
}
}

View file

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{280AEE2F-1FDB-4A27-BE37-14DC154C873B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.SolverFoundation.Plugin.Z3.Tests</RootNamespace>
<AssemblyName>SolverFoundation.Plugin.Z3.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Solver.Foundation">
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceTests.cs" />
<Compile Include="SolverTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj">
<Project>{7340e664-f648-4ff7-89b2-f4da424996d3}</Project>
<Name>SolverFoundation.Plugin.Z3</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -1,138 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Solvers;
using Microsoft.SolverFoundation.Services;
using Microsoft.SolverFoundation.Plugin.Z3;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.SolverFoundation.Plugin.Z3.Tests
{
[TestClass]
public class SolverTests
{
[TestMethod]
public void TestMILPSolver1()
{
var solver = new Z3MILPSolver();
int goal;
solver.AddRow("goal", out goal);
int x1, x2, z;
// 0 <= x1 <= 2
solver.AddVariable("x1", out x1);
solver.SetBounds(x1, 0, 2);
// 0 <= x2 <= 2
solver.AddVariable("x2", out x2);
solver.SetBounds(x2, 0, 2);
// z is an integer in [0,1]
solver.AddVariable("z", out z);
solver.SetIntegrality(z, true);
solver.SetBounds(z, 0, 1);
//max x1 + x2
solver.SetCoefficient(goal, x1, 1);
solver.SetCoefficient(goal, x2, 1);
solver.AddGoal(goal, 1, false);
// 0 <= x1 -z <= 1
int row1;
solver.AddRow("rowI1", out row1);
solver.SetBounds(row1, 0, 1);
solver.SetCoefficient(row1, x1, 1);
solver.SetCoefficient(row1, z, -1);
// 0 <= x2 + z <= 2
int row2;
solver.AddRow("rowI2", out row2);
solver.SetBounds(row2, 0, 2);
solver.SetCoefficient(row2, x2, 1);
solver.SetCoefficient(row2, z, 1);
var p = new Z3MILPParams();
solver.Solve(p);
Assert.IsTrue(solver.Result == LinearResult.Optimal);
Assert.AreEqual(solver.GetValue(x1), 2 * Rational.One);
Assert.AreEqual(solver.GetValue(x2), Rational.One);
Assert.AreEqual(solver.GetValue(z), Rational.One);
Assert.AreEqual(solver.GetValue(goal), 3 * Rational.One);
}
[TestMethod]
public void TestMILPSolver2()
{
var solver = new Z3MILPSolver();
int goal, extraGoal;
Rational M = 100;
solver.AddRow("goal", out goal);
int x1, x2, z;
// 0 <= x1 <= 100
solver.AddVariable("x1", out x1);
solver.SetBounds(x1, 0, M);
// 0 <= x2 <= 100
solver.AddVariable("x2", out x2);
solver.SetBounds(x2, 0, M);
// z is an integer in [0,1]
solver.AddVariable("z", out z);
solver.SetIntegrality(z, true);
solver.SetBounds(z, 0, 1);
solver.SetCoefficient(goal, x1, 1);
solver.SetCoefficient(goal, x2, 2);
solver.AddGoal(goal, 1, false);
solver.AddRow("extraGoal", out extraGoal);
solver.SetCoefficient(extraGoal, x1, 2);
solver.SetCoefficient(extraGoal, x2, 1);
solver.AddGoal(extraGoal, 2, false);
// x1 + x2 >= 1
int row;
solver.AddRow("row", out row);
solver.SetBounds(row, 1, Rational.PositiveInfinity);
solver.SetCoefficient(row, x1, 1);
solver.SetCoefficient(row, x2, 1);
// x1 - M*z <= 0
int row1;
solver.AddRow("rowI1", out row1);
solver.SetBounds(row1, Rational.NegativeInfinity, 0);
solver.SetCoefficient(row1, x1, 1);
solver.SetCoefficient(row1, z, -M);
// x2 - M* (1-z) <= 0
int row2;
solver.AddRow("rowI2", out row2);
solver.SetBounds(row2, Rational.NegativeInfinity, M);
solver.SetCoefficient(row2, x2, 1);
solver.SetCoefficient(row2, z, M);
var p = new Z3MILPParams();
p.OptKind = OptimizationKind.BoundingBox;
solver.Solve(p);
Assert.IsTrue(solver.Result == LinearResult.Optimal);
Assert.AreEqual(solver.GetValue(goal), 200 * Rational.One);
Assert.AreEqual(solver.GetValue(extraGoal), 200 * Rational.One);
}
}
}

View file

@ -1,98 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Z3;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
/// <summary>
/// Thread that will wait until the query abort function returns true or
/// the stop method is called. If the abort function returns true at some
/// point it will issue a softCancel() call to Z3.
/// </summary>
internal class AbortWorker
{
#region Private Members
/// <summary>The Z3 solver</summary>
private Microsoft.Z3.Context _context;
/// <summary>The abort function to use to check if we are aborted</summary>
private Func<bool> _QueryAbortFunction;
/// <summary>Flag indicating that worker should stop</summary>
private bool _stop = false;
/// <summary>Flag indicating that we have been sent an abort signal</summary>
private bool _aborted = false;
#endregion Private Members
#region Construction
/// <summary>
/// Worker constructor taking a Z3 instance and a function to periodically
/// check for aborts.
/// </summary>
/// <param name="z3">Z3 instance</param>
/// <param name="queryAbortFunction">method to call to check for aborts</param>
public AbortWorker(Context context, Func<bool> queryAbortFunction)
{
_context = context;
_QueryAbortFunction = queryAbortFunction;
}
#endregion Construction
#region Public Methods
/// <summary>
/// Stop the abort worker.
/// </summary>
public void Stop()
{
_stop = true;
}
/// <summary>
/// Is true if we have been aborted.
/// </summary>
public bool Aborted
{
get
{
return _aborted;
}
}
/// <summary>
/// Starts the abort worker. The worker checks the abort method
/// periodically until either it is stopped by a call to the Stop()
/// method or it gets an abort signal. In the latter case it will
/// issue a soft abort signal to Z3.
/// </summary>
public void Start()
{
// We go until someone stops us
_stop = false;
while (!_stop && !_QueryAbortFunction())
{
// Wait for a while
Thread.Sleep(10);
}
// If we were stopped on abort, cancel z3
if (!_stop)
{
_context.Interrupt();
_aborted = true;
}
}
#endregion Public Methods
}
}

View file

@ -1,60 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="MsfConfig"
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
allowLocation="true"
allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true"
requirePermission="true"/>
</configSections>
<MsfConfig>
<MsfPluginSolvers>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MINLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="NLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
</MsfPluginSolvers>
</MsfConfig>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View file

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SolverFoundation.Plugin.Z3")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("SolverFoundation.Plugin.Z3")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("ed1476c0-96de-4d2c-983d-3888b140c3ad")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -1,149 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7340E664-F648-4FF7-89B2-F4DA424996D3}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.SolverFoundation.Plugin.Z3</RootNamespace>
<AssemblyName>SolverFoundation.Plugin.Z3</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>false</SignAssembly>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial|AnyCPU'">
<OutputPath>bin\commercial\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial_64|AnyCPU'">
<OutputPath>bin\commercial_64\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial|x86'">
<OutputPath>bin\x86\commercial\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'commercial_64|x86'">
<OutputPath>bin\x86\commercial_64\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Solver.Foundation">
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Z3, Version=4.3.2.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Microsoft.Z3.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq">
</Reference>
<Reference Include="System.Data.DataSetExtensions">
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AbortWorker.cs" />
<Compile Include="Utils.cs" />
<Compile Include="Z3BaseDirective.cs" />
<Compile Include="Z3BaseParams.cs" />
<Compile Include="Z3BaseSolver.cs" />
<Compile Include="Z3MILPDirective.cs" />
<Compile Include="Z3MILPParams.cs" />
<Compile Include="Z3MILPSolver.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Z3TermDirective.cs" />
<Compile Include="Z3TermParams.cs" />
<Compile Include="Z3TermSolver.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -1,130 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Z3;
using Microsoft.SolverFoundation.Common;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
public class Utils
{
/// <summary>
/// Returns the Z3 term corresponding to the MSF rational number.
/// </summary>
/// <param name="rational">The MSF rational</param>
/// <returns>The Z3 term</returns>
public static ArithExpr GetNumeral(Context context, Rational rational, Sort sort = null)
{
try
{
sort = rational.IsInteger() ? ((Sort)context.IntSort) : (sort == null ? (Sort)context.RealSort : sort);
return (ArithExpr)context.MkNumeral(rational.ToString(), sort);
}
catch (Z3Exception e)
{
Console.Error.WriteLine("Conversion of {0} failed:\n {1}", rational, e);
throw new NotSupportedException();
}
}
private static long BASE = 10 ^ 18;
private static Rational ToRational(System.Numerics.BigInteger bi)
{
if (System.Numerics.BigInteger.Abs(bi) <= BASE)
{
return (Rational)((long)bi);
}
return BASE * ToRational(bi / BASE) + ToRational(bi % BASE);
}
public static Rational ToRational(IntNum i)
{
return ToRational(i.BigInteger);
}
public static Rational ToRational(RatNum r)
{
return ToRational(r.BigIntNumerator) / ToRational(r.BigIntDenominator);
}
public static Rational ToRational(Expr expr)
{
Debug.Assert(expr is ArithExpr, "Only accept ArithExpr for now.");
var e = expr as ArithExpr;
if (e is IntNum)
{
Debug.Assert(expr.IsIntNum, "Number should be an integer.");
return ToRational(expr as IntNum);
}
if (e is RatNum)
{
Debug.Assert(expr.IsRatNum, "Number should be a rational.");
return ToRational(expr as RatNum);
}
if (e.IsAdd)
{
Rational r = Rational.Zero;
foreach (var arg in e.Args)
{
r += ToRational(arg);
}
return r;
}
if (e.IsMul)
{
Rational r = Rational.One;
foreach (var arg in e.Args)
{
r *= ToRational(arg);
}
return r;
}
if (e.IsUMinus)
{
return -ToRational(e.Args[0]);
}
if (e.IsDiv)
{
return ToRational(e.Args[0]) / ToRational(e.Args[1]);
}
if (e.IsSub)
{
Rational r = ToRational(e.Args[0]);
for (int i = 1; i < e.Args.Length; ++i)
{
r -= ToRational(e.Args[i]);
}
return r;
}
if (e.IsConst && e.FuncDecl.Name.ToString() == "oo")
{
return Rational.PositiveInfinity;
}
if (e.IsConst && e.FuncDecl.Name.ToString() == "epsilon")
{
return Rational.One/Rational.PositiveInfinity;
}
Debug.Assert(false, "Should not happen");
return Rational.One;
}
}
}

View file

@ -1,107 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Text;
using Microsoft.SolverFoundation.Services;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
/// <summary>
/// Combining objective functions
/// </summary>
public enum OptimizationKind
{
Lexicographic,
BoundingBox,
ParetoOptimal
};
/// <summary>
/// Algorithm for solving cardinality constraints
/// </summary>
public enum CardinalityAlgorithm
{
FuMalik,
CoreMaxSAT
}
/// <summary>
/// Algorithm for solving pseudo-boolean constraints
/// </summary>
public enum PseudoBooleanAlgorithm
{
WeightedMaxSAT,
IterativeWeightedMaxSAT,
BisectionWeightedMaxSAT,
WeightedPartialMaxSAT2
}
/// <summary>
/// Strategy for solving arithmetic optimization
/// </summary>
public enum ArithmeticStrategy
{
Basic,
Farkas
}
public abstract class Z3BaseDirective : Directive
{
protected OptimizationKind _optKind;
protected CardinalityAlgorithm _cardAlgorithm;
protected PseudoBooleanAlgorithm _pboAlgorithm;
protected ArithmeticStrategy _arithStrategy;
protected string _smt2LogFile;
public Z3BaseDirective()
{
Arithmetic = Arithmetic.Exact;
}
public OptimizationKind OptKind
{
get { return _optKind; }
set { _optKind = value; }
}
public CardinalityAlgorithm CardinalityAlgorithm
{
get { return _cardAlgorithm; }
set { _cardAlgorithm = value; }
}
public PseudoBooleanAlgorithm PseudoBooleanAlgorithm
{
get { return _pboAlgorithm; }
set { _pboAlgorithm = value; }
}
public ArithmeticStrategy ArithmeticStrategy
{
get { return _arithStrategy; }
set { _arithStrategy = value; }
}
public string SMT2LogFile
{
get { return _smt2LogFile; }
set { _smt2LogFile = value; }
}
public override string ToString()
{
var sb = new StringBuilder();
sb.Append(this.GetType().Name);
sb.Append("(");
sb.AppendFormat("OptKind: {0}, ", _optKind);
sb.AppendFormat("SMT2LogFile: {0}", _smt2LogFile);
sb.Append(")");
return sb.ToString();
}
}
}

View file

@ -1,109 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using Microsoft.SolverFoundation.Services;
using System;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
/// <summary>
/// Implementation of the solver parameters for Z3
/// </summary>
public class Z3BaseParams : ISolverParameters
{
#region Private Members
/// <summary>The abort method we can call (defaults to always false)
protected Func<bool> _queryAbortFunction = delegate() { return false; };
/// <summary>The directive to use</summary>
protected Directive _directive = null;
protected OptimizationKind _optKind;
protected CardinalityAlgorithm _cardAlgorithm;
protected PseudoBooleanAlgorithm _pboAlgorithm;
protected ArithmeticStrategy _arithStrategy;
protected string _smt2LogFile;
#endregion Private Members
#region Construction
public Z3BaseParams() { }
public Z3BaseParams(Directive directive)
{
_directive = directive;
var z3Directive = directive as Z3BaseDirective;
if (z3Directive != null)
{
_optKind = z3Directive.OptKind;
_cardAlgorithm = z3Directive.CardinalityAlgorithm;
_pboAlgorithm = z3Directive.PseudoBooleanAlgorithm;
_arithStrategy = z3Directive.ArithmeticStrategy;
_smt2LogFile = z3Directive.SMT2LogFile;
}
}
public Z3BaseParams(Func<bool> queryAbortFunction)
{
_queryAbortFunction = queryAbortFunction;
}
public Z3BaseParams(Z3BaseParams z3Parameters)
{
_queryAbortFunction = z3Parameters._queryAbortFunction;
}
#endregion Construction
#region ISolverParameters Members
/// <summary>
/// Getter for the abort method
/// </summary>
public Func<bool> QueryAbort
{
get { return _queryAbortFunction; }
set { _queryAbortFunction = value; }
}
public OptimizationKind OptKind
{
get { return _optKind; }
set { _optKind = value; }
}
public CardinalityAlgorithm CardinalityAlgorithm
{
get { return _cardAlgorithm; }
set { _cardAlgorithm = value; }
}
public PseudoBooleanAlgorithm PseudoBooleanAlgorithm
{
get { return _pboAlgorithm; }
set { _pboAlgorithm = value; }
}
public ArithmeticStrategy ArithmeticStrategy
{
get { return _arithStrategy; }
set { _arithStrategy = value; }
}
public string SMT2LogFile
{
get { return _smt2LogFile; }
set { _smt2LogFile = value; }
}
#endregion
}
}

View file

@ -1,387 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.Z3;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Services;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
internal enum Z3Result
{
Optimal,
LocalOptimal,
Feasible,
Interrupted,
Infeasible
}
/// <summary>
/// The basic solver class to take care of transformation from an MSF instance to an Z3 instance
/// </summary>
internal class Z3BaseSolver
{
/// <summary>Representing MSF model</summary>
private IRowVariableModel _model;
/// <summary>The Z3 solver we are currently using</summary>
private Context _context = null;
/// <summary>Default optimization solver</summary>
private Optimize _optSolver = null;
/// <summary>Marks when we are inside the Solve() method</summary>
private bool _isSolving = false;
/// <summary>A map from MSF variable ids to Z3 variables</summary>
private Dictionary<int, Expr> _variables = new Dictionary<int, Expr>();
/// <summary>A map from MSF variable ids to Z3 goal ids</summary>
private Dictionary<IGoal, Optimize.Handle> _goals = new Dictionary<IGoal, Optimize.Handle>();
internal Z3BaseSolver(IRowVariableModel model)
{
_model = model;
}
internal Context Context
{
get { return _context; }
}
internal Dictionary<int, Expr> Variables
{
get { return _variables; }
}
internal Dictionary<IGoal, Optimize.Handle> Goals
{
get { return _goals; }
}
/// <summary>
/// Destructs a currently active Z3 solver and the associated data.
/// </summary>
internal void DestructSolver(bool checkInSolve)
{
if (_context != null)
{
if (checkInSolve && !_isSolving)
{
_variables.Clear();
if (!_isSolving)
{
_optSolver.Dispose();
_context.Dispose();
}
}
else
{
Console.Error.WriteLine("Z3 destruction is invoked while in Solving phase.");
}
}
}
/// <summary>
/// Constructs a Z3 solver to be used.
/// </summary>
internal void ConstructSolver(Z3BaseParams parameters)
{
// If Z3 is there already, kill it
if (_context != null)
{
DestructSolver(false);
}
_context = new Context();
_optSolver = _context.MkOptimize();
var p = _context.MkParams();
switch (parameters.OptKind)
{
case OptimizationKind.BoundingBox:
p.Add("priority", _context.MkSymbol("box"));
break;
case OptimizationKind.Lexicographic:
p.Add("priority", _context.MkSymbol("lex"));
break;
case OptimizationKind.ParetoOptimal:
p.Add("priority", _context.MkSymbol("pareto"));
break;
default:
Debug.Assert(false, String.Format("Unknown optimization option {0}", parameters.OptKind));
break;
}
switch (parameters.CardinalityAlgorithm)
{
case CardinalityAlgorithm.FuMalik:
p.Add("maxsat_engine", _context.MkSymbol("fu_malik"));
break;
case CardinalityAlgorithm.CoreMaxSAT:
p.Add("maxsat_engine", _context.MkSymbol("core_maxsat"));
break;
default:
Debug.Assert(false, String.Format("Unknown cardinality algorithm option {0}", parameters.CardinalityAlgorithm));
break;
}
switch (parameters.PseudoBooleanAlgorithm)
{
case PseudoBooleanAlgorithm.WeightedMaxSAT:
p.Add("wmaxsat_engine", _context.MkSymbol("wmax"));
break;
case PseudoBooleanAlgorithm.IterativeWeightedMaxSAT:
p.Add("wmaxsat_engine", _context.MkSymbol("iwmax"));
break;
case PseudoBooleanAlgorithm.BisectionWeightedMaxSAT:
p.Add("wmaxsat_engine", _context.MkSymbol("bwmax"));
break;
case PseudoBooleanAlgorithm.WeightedPartialMaxSAT2:
p.Add("wmaxsat_engine", _context.MkSymbol("wpm2"));
break;
default:
Debug.Assert(false, String.Format("Unknown pseudo-boolean algorithm option {0}", parameters.PseudoBooleanAlgorithm));
break;
}
switch (parameters.ArithmeticStrategy)
{
case ArithmeticStrategy.Basic:
p.Add("engine", _context.MkSymbol("basic"));
break;
case ArithmeticStrategy.Farkas:
p.Add("engine", _context.MkSymbol("farkas"));
break;
default:
Debug.Assert(false, String.Format("Unknown arithmetic strategy option {0}", parameters.ArithmeticStrategy));
break;
}
_optSolver.Parameters = p;
}
internal ArithExpr GetVariable(int vid)
{
Expr variable;
if (!_variables.TryGetValue(vid, out variable))
{
AddVariable(vid);
variable = _variables[vid];
}
return (ArithExpr)variable;
}
internal void AssertBool(BoolExpr row)
{
_optSolver.Assert(row);
}
internal void AssertArith(int vid, ArithExpr variable)
{
// Get the bounds on the row
Rational lower, upper;
_model.GetBounds(vid, out lower, out upper);
// Case of equality
if (lower == upper)
{
// Create the equality term
Expr eqConst = GetNumeral(lower, variable.Sort);
BoolExpr constraint = _context.MkEq(eqConst, variable);
// Assert the constraint
_optSolver.Assert(constraint);
}
else
{
// If upper bound is finite assert the upper bound constraint
if (lower.IsFinite)
{
// Create the lower Bound constraint
ArithExpr lowerTerm = GetNumeral(lower, variable.Sort);
BoolExpr constraint = _context.MkLe(lowerTerm, variable);
// Assert the constraint
_optSolver.Assert(constraint);
}
// If lower bound is finite assert the lower bound constraint
if (upper.IsFinite)
{
// Create the upper bound constraint
ArithExpr upperTerm = GetNumeral(upper, variable.Sort);
BoolExpr constraint = _context.MkGe(upperTerm, variable);
// Assert the constraint
_optSolver.Assert(constraint);
}
}
}
/// <summary>
/// Adds a MSF variable with the corresponding assertion to the Z3 variables.
/// </summary>
/// <param name="vid">The MSF id of the variable</param>
internal void AddVariable(int vid)
{
// Is the variable an integer
bool isInteger = _model.GetIntegrality(vid);
// Construct the sort we will be using
Sort sort = isInteger ? (Sort)_context.IntSort : (Sort)_context.RealSort;
// Get the variable key
object key = _model.GetKeyFromIndex(vid);
// Try to construct the name
string name;
if (key != null) name = String.Format("x_{0}_{1}", key, vid);
else name = String.Format("x_{0}", vid);
ArithExpr variable = (ArithExpr)_context.MkConst(name, sort);
// Create the variable and add it to the map
Debug.Assert(!_variables.ContainsKey(vid), "Variable names should be unique.");
_variables.Add(vid, variable);
AssertArith(vid, variable);
}
internal ArithExpr GetNumeral(Rational rational, Sort sort = null)
{
return Utils.GetNumeral(_context, rational, sort);
}
internal void Solve(Z3BaseParams parameters, IEnumerable<IGoal> modelGoals,
Action<int> addRow, Func<int, ArithExpr> mkGoalRow, Action<Z3Result> setResult)
{
_variables.Clear();
_goals.Clear();
try
{
// Mark that we are in solving phase
_isSolving = true;
// Construct Z3
ConstructSolver(parameters);
// Add all the variables
foreach (int vid in _model.VariableIndices)
{
AddVariable(vid);
}
// Add all the rows
foreach (int rid in _model.RowIndices)
{
addRow(rid);
}
// Add enabled goals to optimization problem
foreach (IGoal g in modelGoals)
{
if (!g.Enabled) continue;
ArithExpr gr = mkGoalRow(g.Index);
if (g.Minimize)
_goals.Add(g, _optSolver.MkMinimize(gr));
else
_goals.Add(g, _optSolver.MkMaximize(gr));
}
if (_goals.Any() && parameters.SMT2LogFile != null)
{
Debug.WriteLine("Dumping SMT2 benchmark to log file...");
File.WriteAllText(parameters.SMT2LogFile, _optSolver.ToString());
}
bool aborted = parameters.QueryAbort();
if (!aborted)
{
// Start the abort thread
AbortWorker abortWorker = new AbortWorker(_context, parameters.QueryAbort);
Thread abortThread = new Thread(abortWorker.Start);
abortThread.Start();
// Now solve the problem
Status status = _optSolver.Check();
// Stop the abort thread
abortWorker.Stop();
abortThread.Join();
switch (status)
{
case Status.SATISFIABLE:
Microsoft.Z3.Model model = _optSolver.Model;
Debug.Assert(model != null, "Should be able to get Z3 model.");
// Remember the solution values
foreach (KeyValuePair<int, Expr> pair in _variables)
{
var value = Utils.ToRational(model.Eval(pair.Value, true));
_model.SetValue(pair.Key, value);
}
// Remember all objective values
foreach (var pair in _goals)
{
var optimalValue = Utils.ToRational(pair.Value.Upper);
_model.SetValue(pair.Key.Index, optimalValue);
}
model.Dispose();
setResult(_goals.Any() ? Z3Result.Optimal : Z3Result.Feasible);
break;
case Status.UNSATISFIABLE:
setResult(Z3Result.Infeasible);
break;
case Status.UNKNOWN:
if (abortWorker.Aborted)
{
Microsoft.Z3.Model subOptimalModel = _optSolver.Model;
if (subOptimalModel != null && subOptimalModel.NumConsts != 0)
{
// Remember the solution values
foreach (KeyValuePair<int, Expr> pair in _variables)
{
var value = Utils.ToRational(subOptimalModel.Eval(pair.Value, true));
_model.SetValue(pair.Key, value);
}
// Remember all objective values
foreach (var pair in _goals)
{
var optimalValue = Utils.ToRational(pair.Value.Upper);
_model.SetValue(pair.Key.Index, optimalValue);
}
subOptimalModel.Dispose();
setResult(Z3Result.LocalOptimal);
}
else
setResult(Z3Result.Infeasible);
}
else
setResult(Z3Result.Interrupted);
break;
default:
Debug.Assert(false, "Unrecognized Z3 Status");
break;
}
}
}
finally
{
_isSolving = false;
}
// Now kill Z3
DestructSolver(true);
}
}
}

View file

@ -1,15 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using Microsoft.SolverFoundation.Services;
using System;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
public class Z3MILPDirective : Z3BaseDirective
{
}
}

View file

@ -1,25 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using Microsoft.SolverFoundation.Services;
using System;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
public class Z3MILPParams : Z3BaseParams
{
// Need these constructors for reflection done by plugin model
public Z3MILPParams() : base() { }
public Z3MILPParams(Directive directive) : base(directive) { }
public Z3MILPParams(Func<bool> queryAbortFunction) : base(queryAbortFunction) { }
public Z3MILPParams(Z3BaseParams z3Parameters) : base (z3Parameters) { }
}
}

View file

@ -1,236 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;
using Microsoft.Z3;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Services;
using Microsoft.SolverFoundation.Plugin;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
/// <summary>
/// The class is implementation of the MSF mixed linear programming solver
/// using the Microsoft Z3 solver as the backend.
/// </summary>
public class Z3MILPSolver : LinearModel, ILinearSolver, ILinearSolution, IReportProvider
{
#region Private members
private LinearResult _result;
private LinearSolutionQuality _solutionQuality;
private Z3BaseSolver _solver;
#endregion Private members
#region Solver construction and destruction
/// <summary>Constructor that initializes the base classes</summary>
public Z3MILPSolver() : base(null)
{
_result = LinearResult.Feasible;
_solver = new Z3BaseSolver(this);
}
/// <summary>Constructor that initializes the base classes</summary>
public Z3MILPSolver(ISolverEnvironment context) : this() { }
/// <summary>
/// Shutdown can be called when when the solver is not active, i.e.
/// when it is done with Solve() or it has gracefully returns from Solve()
/// after an abort.
/// </summary>
public void Shutdown() { _solver.DestructSolver(true); }
#endregion Solver construction and destruction
#region Obtaining information about the solution
public ILinearSolverReport GetReport(LinearSolverReportType reportType)
{
// We don't support sensitivity report
return null;
}
#endregion Obtaining information about the solution
#region Construction of the problem
/// <summary>
/// Get corresponding Z3 formula of a MSF row.
/// </summary>
/// <param name="rid">The MSF row id</param>
private ArithExpr MkGoalRow(int rid)
{
// Start with the 0 term
List<ArithExpr> row = new List<ArithExpr>();
// Now, add all the entries of this row
foreach (LinearEntry entry in GetRowEntries(rid))
{
// Get the variable and constant in the row
ArithExpr e = _solver.GetVariable(entry.Index);
if (!entry.Value.IsOne)
{
e = _solver.Context.MkMul(_solver.GetNumeral(entry.Value, e.Sort), e);
}
row.Add(e);
}
switch (row.Count)
{
case 0: return _solver.GetNumeral(new Rational());
case 1: return row[0];
default: return _solver.Context.MkAdd(row.ToArray());
}
}
/// <summary>
/// Adds a MSF row to the Z3 assertions.
/// </summary>
/// <param name="rid">The MSF row id</param>
private void AddRow(int rid)
{
// Start with the 0 term
ArithExpr row = MkGoalRow(rid);
_solver.AssertArith(rid, row);
}
/// <summary>
/// Set results based on internal solver status
/// </summary>
private void SetResult(Z3Result status)
{
switch (status)
{
case Z3Result.Optimal:
_result = LinearResult.Optimal;
_solutionQuality = LinearSolutionQuality.Exact;
break;
case Z3Result.LocalOptimal:
_result = LinearResult.Feasible;
_solutionQuality = LinearSolutionQuality.Approximate;
break;
case Z3Result.Feasible:
_result = LinearResult.Feasible;
_solutionQuality = LinearSolutionQuality.Exact;
break;
case Z3Result.Infeasible:
_result = LinearResult.InfeasiblePrimal;
_solutionQuality = LinearSolutionQuality.None;
break;
case Z3Result.Interrupted:
_result = LinearResult.Interrupted;
_solutionQuality = LinearSolutionQuality.None;
break;
default:
Debug.Assert(false, "Unrecognized Z3 Result");
break;
}
}
#endregion Construction of the problem
#region Solving the problem
/// <summary>
/// Starts solving the problem using the Z3 solver.
/// </summary>
/// <param name="parameters">Parameters to the solver</param>
/// <returns>The solution to the problem</returns>
public ILinearSolution Solve(ISolverParameters parameters)
{
// Get the Z3 parameters
var z3Params = parameters as Z3BaseParams;
Debug.Assert(z3Params != null, "Parameters should be an instance of Z3BaseParams.");
_solver.Solve(z3Params, Goals, AddRow, MkGoalRow, SetResult);
return this;
}
#endregion Solving the problem
#region ILinearSolution Members
public Rational GetSolutionValue(int goalIndex)
{
var goal = Goals.ElementAt(goalIndex);
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
return GetValue(goal.Index);
}
public void GetSolvedGoal(int goalIndex, out object key, out int vid, out bool minimize, out bool optimal)
{
var goal = Goals.ElementAt(goalIndex);
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
key = goal.Key;
vid = goal.Index;
minimize = goal.Minimize;
optimal = _result == LinearResult.Optimal;
}
// LpResult is LP relaxation assignment.
public LinearResult LpResult
{
get { return _result; }
}
public Rational MipBestBound
{
get
{
Debug.Assert(GoalCount > 0, "MipBestBound is only applicable for optimization instances.");
return GetSolutionValue(0);
}
}
public LinearResult MipResult
{
get { return _result; }
}
public LinearResult Result
{
get { return _result; }
}
public LinearSolutionQuality SolutionQuality
{
get { return _solutionQuality; }
}
public int SolvedGoalCount
{
get { return GoalCount; }
}
#endregion
public Report GetReport(SolverContext context, Solution solution, SolutionMapping solutionMapping)
{
LinearSolutionMapping lpSolutionMapping = solutionMapping as LinearSolutionMapping;
if (lpSolutionMapping == null && solutionMapping != null)
throw new ArgumentException("solutionMapping is not a LinearSolutionMapping", "solutionMapping");
return new Z3LinearSolverReport(context, this, solution, lpSolutionMapping);
}
}
/// <summary>
/// Class implementing the LinearReport.
/// </summary>
public class Z3LinearSolverReport : LinearReport
{
public Z3LinearSolverReport(SolverContext context, ISolver solver, Solution solution, LinearSolutionMapping solutionMapping)
: base(context, solver, solution, solutionMapping) {
}
}
}

View file

@ -1,15 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using Microsoft.SolverFoundation.Services;
using System;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
public class Z3TermDirective : Z3BaseDirective
{
}
}

View file

@ -1,23 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using Microsoft.SolverFoundation.Services;
using System;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
public class Z3TermParams : Z3BaseParams
{
public Z3TermParams() : base() { }
public Z3TermParams(Directive directive) : base(directive) { }
public Z3TermParams(Func<bool> queryAbortFunction) : base(queryAbortFunction) { }
public Z3TermParams(Z3BaseParams z3Parameters) : base(z3Parameters) { }
}
}

View file

@ -1,388 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.Threading;
using System.Globalization;
using System.Collections.Generic;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Properties;
using Microsoft.SolverFoundation.Solvers;
using Microsoft.SolverFoundation.Services;
using Microsoft.Z3;
using System.Linq;
using System.Diagnostics;
using System.IO;
namespace Microsoft.SolverFoundation.Plugin.Z3
{
/// <summary>
/// The class is implementation of the MSF constraint solver
/// using the Microsoft Z3 solver as the backend.
/// This solver supports Int, Real constraints and their arbitrary boolean combinations.
/// </summary>
public class Z3TermSolver : TermModel, ITermSolver, INonlinearSolution, IReportProvider
{
private NonlinearResult _result;
private Z3BaseSolver _solver;
/// <summary>Constructor that initializes the base classes</summary>
public Z3TermSolver() : base(null)
{
_solver = new Z3BaseSolver(this);
}
/// <summary>Constructor that initializes the base classes</summary>
public Z3TermSolver(ISolverEnvironment context) : this() { }
/// <summary>
/// Shutdown can be called when when the solver is not active, i.e.
/// when it is done with Solve() or it has gracefully returns from Solve()
/// after an abort.
/// </summary>
public void Shutdown() { _solver.DestructSolver(true); }
private BoolExpr MkBool(int rid)
{
var context = _solver.Context;
if (IsConstant(rid))
{
Rational lower, upper;
GetBounds(rid, out lower, out upper);
Debug.Assert(lower == upper);
if (lower.IsZero) return context.MkFalse();
return context.MkTrue();
}
if (IsOperation(rid))
{
BoolExpr[] children;
ArithExpr[] operands;
TermModelOperation op = GetOperation(rid);
switch(op) {
case TermModelOperation.And:
Debug.Assert(GetOperandCount(rid) >= 2, "Conjunction requires at least two operands.");
children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray();
return context.MkAnd(children);
case TermModelOperation.Or:
Debug.Assert(GetOperandCount(rid) >= 2, "Disjunction requires at least two operands.");
children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray();
return context.MkOr(children);
case TermModelOperation.Not:
Debug.Assert(GetOperandCount(rid) == 1, "Negation is unary.");
return context.MkNot(MkBool(GetOperand(rid, 0)));
case TermModelOperation.If:
Debug.Assert(GetOperandCount(rid) == 3, "If is ternary.");
BoolExpr b = MkBool(GetOperand(rid, 0));
Expr x1 = MkBool(GetOperand(rid, 1));
Expr x2 = MkBool(GetOperand(rid, 2));
return (BoolExpr)context.MkITE(b, x1, x2);
case TermModelOperation.Unequal:
Debug.Assert(GetOperandCount(rid) >= 2, "Distinct should have at least two operands.");
return context.MkDistinct((GetOperands(rid)).Select(x => MkTerm(x)).ToArray());
case TermModelOperation.Greater:
case TermModelOperation.Less:
case TermModelOperation.GreaterEqual:
case TermModelOperation.LessEqual:
case TermModelOperation.Equal:
Debug.Assert(GetOperandCount(rid) >= 2, "Comparison should have at least two operands.");
operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray();
return ReduceComparison(GetOperation(rid), operands);
case TermModelOperation.Identity:
Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand.");
return MkBool(GetOperand(rid, 0));
default:
return context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One));
}
}
return context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One));
}
private ArithExpr MkBoolToArith(BoolExpr e)
{
var context = _solver.Context;
return (ArithExpr)context.MkITE(e, _solver.GetNumeral(Rational.One), _solver.GetNumeral(Rational.Zero));
}
private ArithExpr MkTerm(int rid)
{
var context = _solver.Context;
if (IsConstant(rid))
{
Rational lower, upper;
GetBounds(rid, out lower, out upper);
Debug.Assert(lower == upper);
return _solver.GetNumeral(lower);
}
else if (IsOperation(rid))
{
ArithExpr[] operands;
TermModelOperation op = GetOperation(rid);
switch(op)
{
case TermModelOperation.And:
case TermModelOperation.Or:
case TermModelOperation.Not:
case TermModelOperation.Unequal:
case TermModelOperation.Greater:
case TermModelOperation.Less:
case TermModelOperation.GreaterEqual:
case TermModelOperation.LessEqual:
case TermModelOperation.Equal:
return MkBoolToArith(MkBool(rid));
case TermModelOperation.If:
Debug.Assert(GetOperandCount(rid) == 3, "If is ternary.");
BoolExpr b = MkBool(GetOperand(rid, 0));
Expr x1 = MkTerm(GetOperand(rid, 1));
Expr x2 = MkTerm(GetOperand(rid, 2));
return (ArithExpr)context.MkITE(b, x1, x2);
case TermModelOperation.Plus:
Debug.Assert(GetOperandCount(rid) >= 2, "Plus takes at least two operands.");
operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray();
return context.MkAdd(operands);
case TermModelOperation.Minus:
Debug.Assert(GetOperandCount(rid) == 1, "Minus takes exactly one operand.");
return context.MkUnaryMinus(MkTerm(GetOperand(rid, 0)));
case TermModelOperation.Times:
Debug.Assert(GetOperandCount(rid) >= 2, "Times requires at least two operands.");
operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray();
return context.MkMul(operands);
case TermModelOperation.Identity:
Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand.");
return MkTerm(GetOperand(rid, 0));
case TermModelOperation.Abs:
Debug.Assert(GetOperandCount(rid) == 1, "Abs takes exactly one operand.");
ArithExpr e = MkTerm(GetOperand(rid, 0));
ArithExpr minusE = context.MkUnaryMinus(e);
ArithExpr zero = _solver.GetNumeral(Rational.Zero);
return (ArithExpr)context.MkITE(context.MkGe(e, zero), e, minusE);
default:
Console.Error.WriteLine("{0} operation isn't supported.", op);
throw new NotSupportedException();
}
}
else
{
return _solver.GetVariable(rid);
}
}
private BoolExpr ReduceComparison(TermModelOperation type, ArithExpr[] operands)
{
var context = _solver.Context;
Debug.Assert(operands.Length >= 2);
Func<ArithExpr, ArithExpr, BoolExpr> mkComparison;
switch (type)
{
case TermModelOperation.Greater:
mkComparison = (x, y) => context.MkGt(x, y);
break;
case TermModelOperation.Less:
mkComparison = (x, y) => context.MkLt(x, y);
break;
case TermModelOperation.GreaterEqual:
mkComparison = (x, y) => context.MkGe(x, y);
break;
case TermModelOperation.LessEqual:
mkComparison = (x, y) => context.MkLe(x, y);
break;
case TermModelOperation.Equal:
mkComparison = (x, y) => context.MkEq(x, y);
break;
default:
throw new NotSupportedException();
}
BoolExpr current = mkComparison(operands[0], operands[1]);
for (int i = 1; i < operands.Length - 1; ++i)
current = context.MkAnd(current, mkComparison(operands[i], operands[i + 1]));
return current;
}
private bool IsBoolRow(int rid)
{
Rational lower, upper;
GetBounds(rid, out lower, out upper);
return lower == upper && lower.IsOne && IsBoolTerm(rid);
}
private bool IsBoolTerm(int rid)
{
if (IsConstant(rid))
{
Rational lower, upper;
GetBounds(rid, out lower, out upper);
Debug.Assert(lower == upper);
return lower.IsOne || lower.IsZero;
}
if (IsOperation(rid))
{
TermModelOperation op = GetOperation(rid);
switch (op)
{
case TermModelOperation.And:
case TermModelOperation.Or:
case TermModelOperation.Not:
case TermModelOperation.LessEqual:
case TermModelOperation.Less:
case TermModelOperation.Greater:
case TermModelOperation.GreaterEqual:
case TermModelOperation.Unequal:
case TermModelOperation.Equal:
return true;
case TermModelOperation.If:
return IsBoolTerm(GetOperand(rid, 1)) &&
IsBoolTerm(GetOperand(rid, 2));
case TermModelOperation.Identity:
return IsBoolTerm(GetOperand(rid, 0));
default:
return false;
}
}
return false;
}
/// <summary>
/// Adds a MSF row to the Z3 assertions.
/// </summary>
/// <param name="rid">The MSF row id</param>
private void AddRow(int rid)
{
if (IsConstant(rid))
return;
if (IsBoolRow(rid))
{
_solver.AssertBool(MkBool(rid));
return;
}
// Start with the 0 term
ArithExpr row = MkTerm(rid);
_solver.AssertArith(rid, row);
}
private TermModelOperation[] _supportedOperations =
{ TermModelOperation.And,
TermModelOperation.Or,
TermModelOperation.Not,
TermModelOperation.Unequal,
TermModelOperation.Greater,
TermModelOperation.Less,
TermModelOperation.GreaterEqual,
TermModelOperation.LessEqual,
TermModelOperation.Equal,
TermModelOperation.If,
TermModelOperation.Plus,
TermModelOperation.Minus,
TermModelOperation.Times,
TermModelOperation.Identity,
TermModelOperation.Abs };
/// <summary>
/// Gets the operations supported by the solver.
/// </summary>
/// <returns>All the TermModelOperations supported by the solver.</returns>
public IEnumerable<TermModelOperation> SupportedOperations
{
get { return _supportedOperations; }
}
/// <summary>
/// Set results based on internal solver status
/// </summary>
private void SetResult(Z3Result status)
{
switch (status)
{
case Z3Result.Optimal:
_result = NonlinearResult.Optimal;
break;
case Z3Result.LocalOptimal:
_result = NonlinearResult.LocalOptimal;
break;
case Z3Result.Feasible:
_result = NonlinearResult.Feasible;
break;
case Z3Result.Infeasible:
_result = NonlinearResult.Infeasible;
break;
case Z3Result.Interrupted:
_result = NonlinearResult.Interrupted;
break;
default:
Debug.Assert(false, "Unrecognized Z3 Result");
break;
}
}
/// <summary>
/// Starts solving the problem using the Z3 solver.
/// </summary>
/// <param name="parameters">Parameters to the solver</param>
/// <returns>The solution to the problem</returns>
public INonlinearSolution Solve(ISolverParameters parameters)
{
// Get the Z3 parameters
var z3Params = parameters as Z3BaseParams;
Debug.Assert(z3Params != null, "Parameters should be an instance of Z3BaseParams.");
_solver.Solve(z3Params, Goals, AddRow, MkTerm, SetResult);
return this;
}
double INonlinearSolution.GetValue(int vid)
{
Debug.Assert(_solver.Variables.ContainsKey(vid), "This index should correspond to a variable.");
return GetValue(vid).ToDouble();
}
public int SolvedGoalCount
{
get { return GoalCount; }
}
public double GetSolutionValue(int goalIndex)
{
var goal = Goals.ElementAt(goalIndex);
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
return GetValue(goal.Index).ToDouble();
}
public void GetSolvedGoal(int goalIndex, out object key, out int vid, out bool minimize, out bool optimal)
{
var goal = Goals.ElementAt(goalIndex);
Debug.Assert(goal != null, "Goal should be an element of the goal list.");
key = goal.Key;
vid = goal.Index;
minimize = goal.Minimize;
optimal = _result == NonlinearResult.Optimal;
}
public NonlinearResult Result
{
get { return _result; }
}
public Report GetReport(SolverContext context, Solution solution, SolutionMapping solutionMapping)
{
PluginSolutionMapping pluginSolutionMapping = solutionMapping as PluginSolutionMapping;
if (pluginSolutionMapping == null && solutionMapping != null)
throw new ArgumentException("solutionMapping is not a LinearSolutionMapping", "solutionMapping");
return new Z3TermSolverReport(context, this, solution, pluginSolutionMapping);
}
}
public class Z3TermSolverReport : Report
{
public Z3TermSolverReport(SolverContext context, ISolver solver, Solution solution, PluginSolutionMapping pluginSolutionMapping)
: base(context, solver, solution, pluginSolutionMapping)
{
}
}
}

View file

@ -1,60 +0,0 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="MsfConfig"
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
allowLocation="true"
allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true"
requirePermission="true"/>
</configSections>
<MsfConfig>
<MsfPluginSolvers>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MINLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="NLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
</MsfPluginSolvers>
</MsfConfig>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="MsfConfig"
type="Microsoft.SolverFoundation.Services.MsfConfigSection, Microsoft.Solver.Foundation"
allowLocation="true"
allowDefinition="Everywhere"
allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true"
requirePermission="true" />
</configSections>
<MsfConfig>
<MsfPluginSolvers>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 MILP Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3MILPParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MILP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="LP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="MINLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
<MsfPluginSolver name="Microsoft Z3 Term Solver"
capability="NLP"
assembly="SolverFoundation.Plugin.Z3.dll"
interface="Microsoft.SolverFoundation.Services.ITermSolver"
solverclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermSolver"
directiveclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermDirective"
parameterclass="Microsoft.SolverFoundation.Plugin.Z3.Z3TermParams"/>
</MsfPluginSolvers>
</MsfConfig>
</configuration>

View file

@ -1,200 +0,0 @@
/*++
Copyright (c) 2015 Microsoft Corporation
--*/
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using Microsoft.SolverFoundation.Common;
using Microsoft.SolverFoundation.Solvers;
using Microsoft.SolverFoundation.Plugin.Z3;
using Microsoft.SolverFoundation.Services;
using System.Text;
namespace Validator
{
class Program
{
static void LoadModel(SolverContext context, string fileName)
{
string ext = Path.GetExtension(fileName).ToLower();
if (ext == ".mps")
{
context.LoadModel(FileFormat.MPS, Path.GetFullPath(fileName));
}
else if (ext == ".smps")
{
context.LoadModel(FileFormat.SMPS, Path.GetFullPath(fileName));
}
else if (ext == ".oml")
{
context.LoadModel(FileFormat.OML, Path.GetFullPath(fileName));
}
else
{
throw new NotSupportedException("This file format hasn't been supported.");
}
}
static void ExecuteZ3(string fileName, Z3BaseDirective directive)
{
SolverContext context = SolverContext.GetContext();
try
{
LoadModel(context, fileName);
Solution solution = context.Solve(directive);
Report report = solution.GetReport();
Console.Write("{0}", report);
}
catch (Exception e)
{
Console.WriteLine("Skipping unsolvable instance in {0} with error message '{1}'.", fileName, e.Message);
}
finally
{
context.ClearModel();
}
}
static void ConvertToSMT2(string fileName, Z3BaseDirective directive)
{
SolverContext context = SolverContext.GetContext();
try
{
LoadModel(context, fileName);
if (context.CurrentModel.Goals.Any())
{
directive.SMT2LogFile = Path.ChangeExtension(fileName, ".smt2");
context.Solve(() => true, directive);
}
}
catch (Exception e)
{
Console.WriteLine("Skipping unconvertable instance in {0} with error message '{1}'.", fileName, e.Message);
}
finally
{
context.ClearModel();
}
}
static void ValidateZ3(string fileName, Z3BaseDirective directive)
{
SolverContext context = SolverContext.GetContext();
try
{
LoadModel(context, fileName);
if (context.CurrentModel.Goals.Any())
{
var msfDirective = (directive is Z3MILPDirective) ? (Directive)new MixedIntegerProgrammingDirective() { TimeLimit = 10000 }
: (Directive)new Directive() { TimeLimit = 10000 };
var sol1 = context.Solve(msfDirective);
Console.WriteLine("Solved the model using MSF.");
Console.Write("{0}", sol1.GetReport());
var expectedGoals = sol1.Goals.Select(x => x.ToDouble());
context.ClearModel();
context.LoadModel(FileFormat.OML, Path.GetFullPath(fileName));
directive.SMT2LogFile = Path.ChangeExtension(fileName, ".smt2");
var sol2 = context.Solve(directive);
//Console.Write("{0}", sol2.GetReport());
var actualGoals = sol2.Goals.Select(x => x.ToDouble());
Console.WriteLine("Solved the model using Z3.");
var goalPairs = expectedGoals.Zip(actualGoals, (expected, actual) => new { expected, actual }).ToArray();
bool validated = goalPairs.All(p => Math.Abs(p.expected - p.actual) <= 0.0001);
if (validated)
{
Console.WriteLine("INFO: Two solvers give approximately the same results.");
}
else
{
Console.Error.WriteLine("ERROR: Discrepancy found between results.");
if (!validated && File.Exists(directive.SMT2LogFile))
{
var sb = new StringBuilder();
for(int i = 0; i < goalPairs.Length; i++)
{
sb.AppendFormat("\n(echo \"Goal {0}: actual |-> {1:0.0000}, expected |-> {2:0.0000}\")",
i + 1, goalPairs[i].actual, goalPairs[i].expected);
}
Console.Error.WriteLine(sb.ToString());
File.AppendAllText(directive.SMT2LogFile, sb.ToString());
}
}
}
else
{
Console.WriteLine("Ignoring this instance without having any goal.");
}
}
catch (Exception e)
{
Console.WriteLine("Skipping unsolvable instance in {0} with error message '{1}'.",
fileName, e.Message);
}
finally
{
context.ClearModel();
}
}
static void Main(string[] args)
{
Z3BaseDirective directive = new Z3MILPDirective();
for (int i = 0; i < args.Length; ++i) {
if (args[i] == "-s" || args[i] == "-solve")
{
ExecuteZ3(args[i + 1], directive);
return;
}
if (args[i] == "-c" || args[i] == "-convert")
{
ConvertToSMT2(args[i + 1], directive);
return;
}
if (args[i] == "-v" || args[i] == "-validate")
{
ValidateZ3(args[i + 1], directive);
return;
}
if (args[i] == "-t" || args[i] == "-term")
{
directive = new Z3TermDirective();
}
}
if (args.Length > 0)
{
ExecuteZ3(args[0], directive);
return;
}
Console.WriteLine(@"
Validator is a simple command line to migrate benchmarks from OML, MPS and SMPS to SMT2 formats.
Commands:
-solve <file_name> : solving the model using Z3
-convert <file_name> : converting the model into SMT2 format
-validate <file_name> : validating by comparing results between Z3 and MSF solvers
-term : change the default Z3 MILP solver to Z3 Term solver
where <file_name> is any file with OML, MPS or SMPS extension.
Examples:
Validator.exe -convert model.mps
Validator.exe -term -solve model.oml
");
}
}
}

View file

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("testSolver")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("testSolver")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2009")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c03c1084-d119-483f-80fe-c639eae75959")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{54835857-129F-44C9-B529-A42158647B36}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Validator</RootNamespace>
<AssemblyName>Validator</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Solver.Foundation">
<HintPath>..\Microsoft.Solver.Foundation.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core">
</Reference>
<Reference Include="System.Xml.Linq">
</Reference>
<Reference Include="System.Data.DataSetExtensions">
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="MicrosoftSolverFoundationForExcel.dll.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj">
<Project>{7340e664-f648-4ff7-89b2-f4da424996d3}</Project>
<Name>SolverFoundation.Plugin.Z3</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -1,125 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolverFoundation.Plugin.Z3", "SolverFoundation.Plugin.Z3\SolverFoundation.Plugin.Z3.csproj", "{7340E664-F648-4FF7-89B2-F4DA424996D3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolverFoundation.Plugin.Z3.Tests", "SolverFoundation.Plugin.Z3.Tests\SolverFoundation.Plugin.Z3.Tests.csproj", "{280AEE2F-1FDB-4A27-BE37-14DC154C873B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Validator", "Validator\Validator.csproj", "{54835857-129F-44C9-B529-A42158647B36}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F1E99540-BA5E-46DF-9E29-6146A309CD18}"
ProjectSection(SolutionItems) = preProject
README = README
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
commercial_64|Any CPU = commercial_64|Any CPU
commercial_64|Mixed Platforms = commercial_64|Mixed Platforms
commercial_64|x64 = commercial_64|x64
commercial_64|x86 = commercial_64|x86
commercial|Any CPU = commercial|Any CPU
commercial|Mixed Platforms = commercial|Mixed Platforms
commercial|x64 = commercial|x64
commercial|x86 = commercial|x86
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Any CPU.ActiveCfg = commercial_64|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Any CPU.Build.0 = commercial_64|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Mixed Platforms.ActiveCfg = commercial_64|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|Mixed Platforms.Build.0 = commercial_64|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x64.ActiveCfg = commercial_64|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x86.ActiveCfg = commercial_64|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial_64|x86.Build.0 = commercial_64|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Any CPU.ActiveCfg = commercial|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Any CPU.Build.0 = commercial|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Mixed Platforms.ActiveCfg = commercial|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|Mixed Platforms.Build.0 = commercial|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x64.ActiveCfg = commercial|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x86.ActiveCfg = commercial|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.commercial|x86.Build.0 = commercial|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|Mixed Platforms.Build.0 = Debug|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x64.ActiveCfg = Debug|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x86.ActiveCfg = Debug|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Debug|x86.Build.0 = Debug|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Any CPU.Build.0 = Release|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Mixed Platforms.ActiveCfg = Release|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|Mixed Platforms.Build.0 = Release|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x64.ActiveCfg = Release|Any CPU
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x86.ActiveCfg = Release|x86
{7340E664-F648-4FF7-89B2-F4DA424996D3}.Release|x86.Build.0 = Release|x86
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Any CPU.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Any CPU.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Mixed Platforms.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|Mixed Platforms.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|x64.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial_64|x86.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Any CPU.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Any CPU.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Mixed Platforms.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|Mixed Platforms.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|x64.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.commercial|x86.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x64.ActiveCfg = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x86.ActiveCfg = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Debug|x86.Build.0 = Debug|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Any CPU.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x64.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x86.ActiveCfg = Release|Any CPU
{280AEE2F-1FDB-4A27-BE37-14DC154C873B}.Release|x86.Build.0 = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|Any CPU.ActiveCfg = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|Any CPU.Build.0 = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|Mixed Platforms.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|Mixed Platforms.Build.0 = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|x64.ActiveCfg = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|x64.Build.0 = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|x86.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial_64|x86.Build.0 = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial|Any CPU.ActiveCfg = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.commercial|Any CPU.Build.0 = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.commercial|Mixed Platforms.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial|Mixed Platforms.Build.0 = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial|x64.ActiveCfg = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.commercial|x64.Build.0 = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.commercial|x86.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.commercial|x86.Build.0 = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
{54835857-129F-44C9-B529-A42158647B36}.Debug|Mixed Platforms.Build.0 = Debug|x86
{54835857-129F-44C9-B529-A42158647B36}.Debug|x64.ActiveCfg = Debug|x64
{54835857-129F-44C9-B529-A42158647B36}.Debug|x64.Build.0 = Debug|x64
{54835857-129F-44C9-B529-A42158647B36}.Debug|x86.ActiveCfg = Debug|x86
{54835857-129F-44C9-B529-A42158647B36}.Debug|x86.Build.0 = Debug|x86
{54835857-129F-44C9-B529-A42158647B36}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.Release|Any CPU.Build.0 = Release|Any CPU
{54835857-129F-44C9-B529-A42158647B36}.Release|Mixed Platforms.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.Release|Mixed Platforms.Build.0 = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.Release|x64.ActiveCfg = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.Release|x64.Build.0 = Release|x64
{54835857-129F-44C9-B529-A42158647B36}.Release|x86.ActiveCfg = Release|x86
{54835857-129F-44C9-B529-A42158647B36}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,93 @@
# This script illustrates uses of proof logs over the Python interface.
from z3 import *
example1 = """
(declare-sort T)
(declare-fun subtype (T T) Bool)
;; subtype is reflexive
(assert (forall ((x T)) (subtype x x)))
;; subtype is antisymmetric
(assert (forall ((x T) (y T)) (=> (and (subtype x y)
(subtype y x))
(= x y))))
;; subtype is transitive
(assert (forall ((x T) (y T) (z T)) (=> (and (subtype x y)
(subtype y z))
(subtype x z))))
;; subtype has the tree-property
(assert (forall ((x T) (y T) (z T)) (=> (and (subtype x z)
(subtype y z))
(or (subtype x y)
(subtype y x)))))
;; now we define a simple example using the axiomatization above.
(declare-const obj-type T)
(declare-const int-type T)
(declare-const real-type T)
(declare-const complex-type T)
(declare-const string-type T)
;; we have an additional axiom: every type is a subtype of obj-type
(assert (forall ((x T)) (subtype x obj-type)))
(assert (subtype int-type real-type))
(assert (subtype real-type complex-type))
(assert (not (subtype string-type real-type)))
(declare-const root-type T)
(assert (subtype obj-type root-type))
"""
def monitor_plain():
print("Monitor all inferred clauses")
s = Solver()
s.from_string(example1)
onc = OnClause(s, lambda pr, clause : print(pr, clause))
print(s.check())
def log_instance(pr, clause):
if pr.decl().name() == "inst":
q = pr.arg(0).arg(0) # first argument is Not(q)
for ch in pr.children():
if ch.decl().name() == "bind":
print("Binding")
print(q)
print(ch.children())
break
def monitor_instances():
print("Monitor just quantifier bindings")
s = Solver()
s.from_string(example1)
onc = OnClause(s, log_instance)
print(s.check())
def monitor_with_proofs():
print("Monitor clauses annotated with detailed justifications")
set_param(proof=True)
s = Solver()
s.from_string(example1)
onc = OnClause(s, lambda pr, clause : print(pr, clause))
print(s.check())
def monitor_new_core():
print("Monitor proof objects from the new core")
set_param("sat.euf", True)
set_param("tactic.default_tactic", "sat")
s = Solver()
s.from_string(example1)
onc = OnClause(s, lambda pr, clause : print(pr, clause))
print(s.check())
if __name__ == "__main__":
monitor_plain()
monitor_instances()
monitor_new_core()
# Monitoring with proofs cannot be done in the same session
# monitor_with_proofs()

View file

@ -0,0 +1,113 @@
# This script illustrates uses of proof replay and proof logs over the Python interface.
from z3 import *
example1 = """
(declare-sort T)
(declare-fun subtype (T T) Bool)
;; subtype is reflexive
(assert (forall ((x T)) (subtype x x)))
;; subtype is antisymmetric
(assert (forall ((x T) (y T)) (=> (and (subtype x y)
(subtype y x))
(= x y))))
;; subtype is transitive
(assert (forall ((x T) (y T) (z T)) (=> (and (subtype x y)
(subtype y z))
(subtype x z))))
;; subtype has the tree-property
(assert (forall ((x T) (y T) (z T)) (=> (and (subtype x z)
(subtype y z))
(or (subtype x y)
(subtype y x)))))
;; now we define a simple example using the axiomatization above.
(declare-const obj-type T)
(declare-const int-type T)
(declare-const real-type T)
(declare-const complex-type T)
(declare-const string-type T)
;; we have an additional axiom: every type is a subtype of obj-type
(assert (forall ((x T)) (subtype x obj-type)))
(assert (subtype int-type real-type))
(assert (subtype real-type complex-type))
(assert (not (subtype string-type real-type)))
(declare-const root-type T)
(assert (subtype obj-type root-type))
"""
if __name__ == "__main__":
print("Solve and log inferences")
print("--------------------------------------------------------")
# inference logging, replay, and checking is supported for
# the core enabled by setting sat.euf = true.
# setting the default tactic to 'sat' bypasses other tactics that could
# end up using different solvers.
set_param("sat.euf", True)
set_param("tactic.default_tactic", "sat")
# Set a log file to trace inferences
set_param("sat.smt.proof", "proof_log.smt2")
s = Solver()
s.from_string(example1)
print(s.check())
print(s.statistics())
print("Parse the logged inferences and replay them")
print("--------------------------------------------------------")
# Reset the log file to an invalid (empty) file name.
set_param("sat.smt.proof", "")
# Turn off proof checking. It is on by default when parsing proof logs.
set_param("solver.proof.check", False)
s = Solver()
onc = OnClause(s, lambda pr, clause : print(pr, clause))
s.from_file("proof_log.smt2")
print("Parse the logged inferences and check them")
print("--------------------------------------------------------")
s = Solver()
# Now turn on proof checking. It invokes the self-validator.
# The self-validator produces log lines of the form:
# (proofs +tseitin 60 +alldiff 8 +euf 3 +rup 5 +inst 6 -quant 3 -inst 2)
# (verified-smt
# (inst (forall (vars (x T) (y T) (z T)) (or (subtype (:var 2) (:var 1)) ...
# The 'proofs' line summarizes inferences that were self-validated.
# The pair +tseitin 60 indicates that 60 inferences were validated as Tseitin
# encodings.
# The pair -inst 2 indicates that two quantifier instantiations were not self-validated
# They were instead validated using a call to SMT solving. A log for an smt invocation
# is exemplified in the next line.
# Note that the pair +inst 6 indicates that 6 quantifier instantations were validated
# using a syntactic (cheap) check. Some quantifier instantiations based on quantifier elimination
# are not simple substitutions and therefore a simple syntactic check does not suffice.
set_param("solver.proof.check", True)
s.from_file("proof_log.smt2")
print("Verify and self-validate on the fly")
print("--------------------------------------------------------")
set_param("sat.smt.proof.check", True)
s = Solver()
s.from_string(example1)
print(s.check())
print(s.statistics())
print("Verify and self-validate on the fly, but don't check rup")
print("--------------------------------------------------------")
set_param("sat.smt.proof.check", True)
set_param("sat.smt.proof.check_rup", False)
s = Solver()
s.from_string(example1)
print(s.check())
print(s.statistics())

View file

@ -2305,12 +2305,26 @@ static void display_smt2(std::ostream& out) {
return;
}
z3::expr_vector asms(ctx);
size_t num_assumptions = fmls.m_formulas.size();
for (size_t i = 0; i < num_assumptions; ++i)
asms.push_back(fmls.m_formulas[i]);
Z3_ast* assumptions = new Z3_ast[num_assumptions];
for (size_t i = 0; i < num_assumptions; ++i) {
assumptions[i] = fmls.m_formulas[i];
for (size_t i = 0; i < asms.size(); ++i) {
z3::expr fml = asms[i];
if (fml.is_and()) {
z3::expr arg0 = fml.arg(0);
asms.set(i, arg0);
for (unsigned j = 1; j < fml.num_args(); ++j)
asms.push_back(fml.arg(j));
--i;
}
}
Z3_ast* assumptions = new Z3_ast[asms.size()];
for (size_t i = 0; i < asms.size(); ++i)
assumptions[i] = asms[i];
Z3_set_ast_print_mode(ctx, Z3_PRINT_SMTLIB_FULL);
Z3_string s =
Z3_benchmark_to_smtlib_string(
ctx,
@ -2318,7 +2332,7 @@ static void display_smt2(std::ostream& out) {
0, // no logic is set
"unknown", // no status annotation
"", // attributes
static_cast<unsigned>(num_assumptions),
static_cast<unsigned>(asms.size()),
assumptions,
ctx.bool_val(true));

View file

@ -38,7 +38,7 @@ jobs:
publishSymbols: true
symbolServerType: TeamServices
detailedLog: true
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
displayName: Sign
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'

View file

@ -672,6 +672,7 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path):
components.
"""
ADD_TACTIC_DATA = []
ADD_SIMPLIFIER_DATA = []
ADD_PROBE_DATA = []
def ADD_TACTIC(name, descr, cmd):
ADD_TACTIC_DATA.append((name, descr, cmd))
@ -679,9 +680,13 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path):
def ADD_PROBE(name, descr, cmd):
ADD_PROBE_DATA.append((name, descr, cmd))
def ADD_SIMPLIFIER(name, descr, cmd):
ADD_SIMPLIFIER_DATA.append((name, descr, cmd))
eval_globals = {
'ADD_TACTIC': ADD_TACTIC,
'ADD_PROBE': ADD_PROBE,
'ADD_SIMPLIFIER': ADD_SIMPLIFIER
}
assert isinstance(h_files_full_path, list)
@ -691,9 +696,11 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path):
fout.write('// Automatically generated file.\n')
fout.write('#include "tactic/tactic.h"\n')
fout.write('#include "cmd_context/tactic_cmds.h"\n')
fout.write('#include "cmd_context/simplifier_cmds.h"\n')
fout.write('#include "cmd_context/cmd_context.h"\n')
tactic_pat = re.compile('[ \t]*ADD_TACTIC\(.*\)')
probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)')
probe_pat = re.compile('[ \t]*ADD_PROBE\(.*\)')
simplifier_pat = re.compile('[ \t]*ADD_SIMPLIFIER\(.*\)')
for h_file in sorted_headers_by_component(h_files_full_path):
added_include = False
try:
@ -719,17 +726,31 @@ def mk_install_tactic_cpp_internal(h_files_full_path, path):
_logger.error("Failed processing ADD_PROBE command at '{}'\n{}".format(
fullname, line))
raise e
if simplifier_pat.match(line):
if not added_include:
added_include = True
fout.write('#include "%s"\n' % path_after_src(h_file))
try:
eval(line.strip('\n '), eval_globals, None)
except Exception as e:
_logger.error("Failed processing ADD_SIMPLIFIER command at '{}'\n{}".format(
fullname, line))
raise e
except Exception as e:
_logger.error("Failed to read file {}\n".format(h_file))
raise e
# First pass will just generate the tactic factories
fout.write('#define ADD_TACTIC_CMD(NAME, DESCR, CODE) ctx.insert(alloc(tactic_cmd, symbol(NAME), DESCR, [](ast_manager &m, const params_ref &p) { return CODE; }))\n')
fout.write('#define ADD_PROBE(NAME, DESCR, PROBE) ctx.insert(alloc(probe_info, symbol(NAME), DESCR, PROBE))\n')
fout.write('#define ADD_SIMPLIFIER_CMD(NAME, DESCR, CODE) ctx.insert(alloc(simplifier_cmd, symbol(NAME), DESCR, [](auto& m, auto& p, auto &s) -> dependent_expr_simplifier* { return CODE; }))\n')
fout.write('void install_tactics(tactic_manager & ctx) {\n')
for data in ADD_TACTIC_DATA:
fout.write(' ADD_TACTIC_CMD("%s", "%s", %s);\n' % data)
for data in ADD_PROBE_DATA:
fout.write(' ADD_PROBE("%s", "%s", %s);\n' % data)
for data in ADD_SIMPLIFIER_DATA:
fout.write(' ADD_SIMPLIFIER_CMD("%s", "%s", %s);\n' % data)
fout.write('}\n')
fout.close()
return fullname

View file

@ -8,7 +8,7 @@
from mk_util import *
def init_version():
set_version(4, 11, 3, 0) # express a default build version or pick up ci build version
set_version(4, 12, 2, 0) # express a default build version or pick up ci build version
# Z3 Project definition
def init_project_def():
@ -20,48 +20,50 @@ def init_project_def():
add_lib('simplex', ['util'], 'math/simplex')
add_lib('hilbert', ['util'], 'math/hilbert')
add_lib('automata', ['util'], 'math/automata')
add_lib('params', ['util'])
add_lib('realclosure', ['interval'], 'math/realclosure')
add_lib('subpaving', ['interval'], 'math/subpaving')
add_lib('ast', ['util', 'polynomial'])
add_lib('euf', ['ast', 'util'], 'ast/euf')
add_lib('params', ['util'])
add_lib('smt_params', ['params'], 'smt/params')
add_lib('smt_params', ['ast', 'params'], 'smt/params')
add_lib('parser_util', ['ast'], 'parsers/util')
add_lib('euf', ['ast'], 'ast/euf')
add_lib('grobner', ['ast', 'dd', 'simplex'], 'math/grobner')
add_lib('sat', ['params', 'util', 'dd', 'grobner'])
add_lib('nlsat', ['polynomial', 'sat'])
add_lib('lp', ['util', 'nlsat', 'grobner', 'interval', 'smt_params'], 'math/lp')
add_lib('rewriter', ['ast', 'polynomial', 'automata', 'params'], 'ast/rewriter')
add_lib('macros', ['rewriter'], 'ast/macros')
add_lib('rewriter', ['ast', 'polynomial', 'interval', 'automata', 'params'], 'ast/rewriter')
add_lib('bit_blaster', ['rewriter'], 'ast/rewriter/bit_blaster')
add_lib('normal_forms', ['rewriter'], 'ast/normal_forms')
add_lib('model', ['rewriter', 'macros'])
add_lib('tactic', ['ast', 'model'])
add_lib('substitution', ['ast', 'rewriter'], 'ast/substitution')
add_lib('parser_util', ['ast'], 'parsers/util')
add_lib('proofs', ['rewriter', 'util'], 'ast/proofs')
add_lib('solver', ['params', 'model', 'tactic', 'proofs'])
add_lib('substitution', ['rewriter'], 'ast/substitution')
add_lib('proofs', ['rewriter'], 'ast/proofs')
add_lib('macros', ['rewriter'], 'ast/macros')
add_lib('model', ['macros'])
add_lib('converters', ['model'], 'ast/converters')
add_lib('simplifiers', ['euf', 'normal_forms', 'bit_blaster', 'converters', 'substitution'], 'ast/simplifiers')
add_lib('tactic', ['simplifiers'])
add_lib('mbp', ['model', 'simplex'], 'qe/mbp')
add_lib('qe_lite', ['tactic', 'mbp'], 'qe/lite')
add_lib('solver', ['params', 'smt_params', 'model', 'tactic', 'qe_lite', 'proofs'])
add_lib('cmd_context', ['solver', 'rewriter', 'params'])
add_lib('smt2parser', ['cmd_context', 'parser_util'], 'parsers/smt2')
add_lib('pattern', ['normal_forms', 'smt2parser', 'rewriter'], 'ast/pattern')
add_lib('aig_tactic', ['tactic'], 'tactic/aig')
add_lib('ackermannization', ['model', 'rewriter', 'ast', 'solver', 'tactic'], 'ackermannization')
add_lib('fpa', ['ast', 'util', 'rewriter', 'model'], 'ast/fpa')
add_lib('bit_blaster', ['rewriter', 'params'], 'ast/rewriter/bit_blaster')
add_lib('core_tactics', ['tactic', 'macros', 'normal_forms', 'rewriter', 'pattern'], 'tactic/core')
add_lib('arith_tactics', ['core_tactics', 'sat'], 'tactic/arith')
add_lib('mbp', ['model', 'simplex'], 'qe/mbp')
add_lib('qe_lite', ['tactic', 'mbp'], 'qe/lite')
add_lib('solver_assertions', ['pattern','smt_params','cmd_context','qe_lite'], 'solver/assertions')
add_lib('bigfix',['util'], 'math/bigfix')
add_lib('polysat_univariate_solver', ['util', 'solver'], 'math/polysat/univariate')
add_lib('polysat', ['bigfix','util','dd','simplex','interval','polysat_univariate_solver'], 'math/polysat')
add_lib('solver_assertions', ['pattern','smt_params','cmd_context','qe_lite'], 'solver/assertions')
add_lib('sat_smt', ['sat', 'euf', 'tactic', 'solver', 'smt_params', 'bit_blaster', 'fpa', 'mbp', 'normal_forms', 'lp', 'pattern', 'qe_lite', 'polysat'], 'sat/smt')
add_lib('sat_tactic', ['tactic', 'sat', 'solver', 'sat_smt'], 'sat/tactic')
add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'nlsat/tactic')
add_lib('subpaving_tactic', ['core_tactics', 'subpaving'], 'math/subpaving/tactic')
add_lib('proto_model', ['model', 'rewriter', 'smt_params'], 'smt/proto_model')
add_lib('smt', ['bit_blaster', 'macros', 'normal_forms', 'cmd_context', 'proto_model', 'solver_assertions',
'substitution', 'grobner', 'simplex', 'proofs', 'pattern', 'parser_util', 'fpa', 'lp'])
add_lib('sat_smt', ['sat', 'euf', 'smt', 'tactic', 'solver', 'smt_params', 'bit_blaster', 'fpa', 'mbp', 'normal_forms', 'lp', 'pattern', 'qe_lite', 'polysat'], 'sat/smt')
add_lib('sat_tactic', ['tactic', 'sat', 'solver', 'sat_smt'], 'sat/tactic')
add_lib('nlsat_tactic', ['nlsat', 'sat_tactic', 'arith_tactics'], 'nlsat/tactic')
add_lib('bv_tactics', ['tactic', 'bit_blaster', 'core_tactics'], 'tactic/bv')
add_lib('fuzzing', ['ast'], 'test/fuzzing')
add_lib('smt_tactic', ['smt'], 'smt/tactic')
@ -85,9 +87,9 @@ def init_project_def():
add_lib('portfolio', ['smtlogic_tactics', 'sat_solver', 'ufbv_tactic', 'fpa_tactics', 'aig_tactic', 'fp', 'fd_solver', 'qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
add_lib('opt', ['smt', 'smtlogic_tactics', 'sls_tactic', 'sat_solver'], 'opt')
API_files = ['z3_api.h', 'z3_ast_containers.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_fixedpoint.h', 'z3_optimization.h', 'z3_fpa.h', 'z3_spacer.h']
add_lib('api', ['portfolio', 'realclosure', 'opt'],
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
add_lib('extra_cmds', ['cmd_context', 'subpaving_tactic', 'qe', 'euf', 'arith_tactics'], 'cmd_context/extra_cmds')
add_lib('api', ['portfolio', 'realclosure', 'opt', 'extra_cmds'],
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
add_exe('shell', ['api', 'sat', 'extra_cmds', 'opt'], exe_name='z3')
add_exe('test', ['polysat','api', 'fuzzing', 'simplex', 'sat_smt'], exe_name='test-z3', install=False)
_libz3Component = add_dll('api_dll', ['api', 'sat', 'extra_cmds'], 'api/dll',

View file

@ -1,7 +1,7 @@
variables:
Major: '4'
Minor: '11'
Patch: '3'
Minor: '12'
Patch: '2'
AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId)
NightlyVersion: $(AssemblyVersion)-$(Build.DefinitionName)
@ -11,7 +11,7 @@ stages:
- job: Mac
displayName: "Mac Build"
pool:
vmImage: "macOS-latest"
vmImage: "macOS-11"
steps:
- script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
- script: git clone https://github.com/z3prover/z3test z3test
@ -25,7 +25,7 @@ stages:
- job: MacArm64
displayName: "Mac ARM64 Build"
pool:
vmImage: "macOS-latest"
vmImage: "macOS-11"
steps:
- script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64 --os=osx-11.0
- script: git clone https://github.com/z3prover/z3test z3test
@ -91,7 +91,7 @@ stages:
displayName: "ManyLinux build"
pool:
vmImage: "ubuntu-latest"
container: "quay.io/pypa/manylinux2010_x86_64:latest"
container: "quay.io/pypa/manylinux2014_x86_64:latest"
steps:
- script: $(python) scripts/mk_unix_dist.py --nodotnet --nojava
- script: git clone https://github.com/z3prover/z3test z3test
@ -261,7 +261,7 @@ stages:
minorVersion: $(Minor)
patchVersion: $(Patch)
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.sym.nuspec -Version $(NightlyVersion) -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
continueOnError: true
displayName: 'Sign Package'
inputs:
@ -289,7 +289,7 @@ stages:
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
continueOnError: true
displayName: 'Sign Symbol Package'
inputs:
@ -366,7 +366,7 @@ stages:
minorVersion: $(Minor)
patchVersion: $(Patch)
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -Version $(NightlyVersion) -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
continueOnError: true
displayName: 'Sign Package'
inputs:
@ -394,7 +394,7 @@ stages:
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
continueOnError: true
displayName: 'Sign Symbol Package'
inputs:

View file

@ -6,7 +6,7 @@
trigger: none
variables:
ReleaseVersion: '4.11.3'
ReleaseVersion: '4.12.2'
stages:
@ -17,7 +17,7 @@ stages:
- job: MacBuild
displayName: "macOS Build"
pool:
vmImage: "macOS-latest"
vmImage: "macOS-11"
steps:
- task: PythonScript@0
displayName: Build
@ -46,7 +46,7 @@ stages:
- job: MacBuildArm64
displayName: "macOS ARM64 Build"
pool:
vmImage: "macOS-latest"
vmImage: "macOS-11"
steps:
- script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64 --os=osx-11.0
- script: git clone https://github.com/z3prover/z3test z3test
@ -124,11 +124,10 @@ stages:
displayName: "ManyLinux build"
variables:
name: ManyLinux
image: "quay.io/pypa/manylinux2010_x86_64:latest"
python: "/opt/python/cp37-cp37m/bin/python"
pool:
vmImage: "ubuntu-latest"
container: "quay.io/pypa/manylinux2010_x86_64:latest"
container: "quay.io/pypa/manylinux2014_x86_64:latest"
steps:
- task: PythonScript@0
displayName: Build
@ -220,7 +219,7 @@ stages:
inputs:
command: custom
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.sym.nuspec -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
displayName: 'Sign Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
@ -234,20 +233,20 @@ stages:
"OperationCode" : "NuGetSign",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
"ToolVersion" : "2.0"
},
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
"ToolVersion" : "2.0"
}
]
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
displayName: 'Sign Symbol Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
@ -261,14 +260,14 @@ stages:
"OperationCode" : "NuGetSign",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
"ToolVersion" : "2.0"
},
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
"ToolVersion" : "2.0"
}
]
SessionTimeout: '60'
@ -319,7 +318,7 @@ stages:
inputs:
command: custom
arguments: 'pack $(Agent.TempDirectory)\package\out\Microsoft.Z3.x86.sym.nuspec -OutputDirectory $(Build.ArtifactStagingDirectory) -Verbosity detailed -Symbols -SymbolPackageFormat snupkg -BasePath $(Agent.TempDirectory)\package\out'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
displayName: 'Sign Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'
@ -346,7 +345,7 @@ stages:
SessionTimeout: '60'
MaxConcurrency: '50'
MaxRetryAttempts: '5'
- task: EsrpCodeSigning@1
- task: EsrpCodeSigning@2
displayName: 'Sign Symbol Package'
inputs:
ConnectedServiceName: 'z3-esrp-signing-2'

View file

@ -312,7 +312,7 @@ NULLWrapped = [ 'Z3_mk_context', 'Z3_mk_context_rc' ]
Unwrapped = [ 'Z3_del_context', 'Z3_get_error_code' ]
Unchecked = frozenset([ 'Z3_dec_ref', 'Z3_params_dec_ref', 'Z3_model_dec_ref',
'Z3_func_interp_dec_ref', 'Z3_func_entry_dec_ref',
'Z3_goal_dec_ref', 'Z3_tactic_dec_ref', 'Z3_probe_dec_ref',
'Z3_goal_dec_ref', 'Z3_tactic_dec_ref', 'Z3_simplifier_dec_ref', 'Z3_probe_dec_ref',
'Z3_fixedpoint_dec_ref', 'Z3_param_descrs_dec_ref',
'Z3_ast_vector_dec_ref', 'Z3_ast_map_dec_ref',
'Z3_apply_result_dec_ref', 'Z3_solver_dec_ref',
@ -339,6 +339,10 @@ def Z3_set_error_handler(ctx, hndlr, _elems=Elementaries(_lib.Z3_set_error_handl
_elems.Check(ctx)
return ceh
def Z3_solver_register_on_clause(ctx, s, user_ctx, on_clause_eh, _elems = Elementaries(_lib.Z3_solver_register_on_clause)):
_elems.f(ctx, s, user_ctx, on_clause_eh)
_elems.Check(ctx)
def Z3_solver_propagate_init(ctx, s, user_ctx, push_eh, pop_eh, fresh_eh, _elems = Elementaries(_lib.Z3_solver_propagate_init)):
_elems.f(ctx, s, user_ctx, push_eh, pop_eh, fresh_eh)
_elems.Check(ctx)
@ -1172,6 +1176,8 @@ def ml_plus_type(ts):
return 'Z3_goal_plus'
elif ts == 'Z3_tactic':
return 'Z3_tactic_plus'
elif ts == 'Z3_simplifier':
return 'Z3_simplifier_plus'
elif ts == 'Z3_probe':
return 'Z3_probe_plus'
elif ts == 'Z3_apply_result':
@ -1216,6 +1222,8 @@ def ml_minus_type(ts):
return 'Z3_goal'
elif ts == 'Z3_tactic_plus':
return 'Z3_tactic'
elif ts == 'Z3_simplifier_plus':
return 'Z3_simplifier'
elif ts == 'Z3_probe_plus':
return 'Z3_probe'
elif ts == 'Z3_apply_result_plus':
@ -1315,7 +1323,8 @@ z3_ml_callbacks = frozenset([
'Z3_solver_propagate_eq',
'Z3_solver_propagate_diseq',
'Z3_solver_propagate_created',
'Z3_solver_propagate_decide'
'Z3_solver_propagate_decide',
'Z3_solver_register_on_clause'
])
def mk_ml(ml_src_dir, ml_output_dir):
@ -1844,6 +1853,7 @@ _error_handler_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint)
_lib.Z3_set_error_handler.restype = None
_lib.Z3_set_error_handler.argtypes = [ContextObj, _error_handler_type]
Z3_on_clause_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
Z3_push_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p)
Z3_pop_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint)
Z3_fresh_eh = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
@ -1855,6 +1865,7 @@ Z3_eq_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_
Z3_created_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
Z3_decide_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p)
_lib.Z3_solver_register_on_clause.restype = None
_lib.Z3_solver_propagate_init.restype = None
_lib.Z3_solver_propagate_final.restype = None
_lib.Z3_solver_propagate_fixed.restype = None

View file

@ -47,12 +47,17 @@ add_subdirectory(math/subpaving)
add_subdirectory(ast)
add_subdirectory(params)
add_subdirectory(ast/rewriter)
add_subdirectory(ast/rewriter/bit_blaster)
add_subdirectory(ast/normal_forms)
add_subdirectory(ast/macros)
add_subdirectory(model)
add_subdirectory(tactic)
add_subdirectory(ast/substitution)
add_subdirectory(ast/euf)
add_subdirectory(ast/converters)
add_subdirectory(ast/substitution)
add_subdirectory(ast/simplifiers)
add_subdirectory(tactic)
add_subdirectory(qe/mbp)
add_subdirectory(qe/lite)
add_subdirectory(smt/params)
add_subdirectory(parsers/util)
add_subdirectory(math/grobner)
@ -68,11 +73,8 @@ add_subdirectory(math/polysat)
add_subdirectory(cmd_context)
add_subdirectory(cmd_context/extra_cmds)
add_subdirectory(parsers/smt2)
add_subdirectory(qe/mbp)
add_subdirectory(qe/lite)
add_subdirectory(solver/assertions)
add_subdirectory(ast/pattern)
add_subdirectory(ast/rewriter/bit_blaster)
add_subdirectory(math/lp)
add_subdirectory(sat/smt)
add_subdirectory(sat/tactic)
@ -138,7 +140,7 @@ if (MSVC AND Z3_BUILD_LIBZ3_MSVC_STATIC)
set(${CompilerFlag} "${${CompilerFlag}}" CACHE STRING "msvc compiler flags" FORCE)
message("MSVC flags: ${CompilerFlag}:${${CompilerFlag}}")
endforeach()
endif(MSVC)
endif()
add_library(libz3 ${lib_type} ${object_files})
target_include_directories(libz3 INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/api>

View file

@ -16,7 +16,7 @@
--*/
#pragma once
#include "tactic/model_converter.h"
#include "ast/converters/model_converter.h"
#include "ackermannization/ackr_info.h"
model_converter * mk_ackermannize_bv_model_converter(ast_manager & m, const ackr_info_ref& info);

View file

@ -11,7 +11,37 @@ Author:
Mikolas Janota
Revision History:
Tactic Documentation:
## Tactic ackernannize_bv
### Short Description
A tactic for performing Ackermann reduction for bit-vector formulas
### Long Description
The Ackermann reduction replaces uninterpreted functions $f(t_1), f(t_2)$
by fresh variables $f_1, f_2$ and addes axioms $t_1 \simeq t_2 \implies f_1 \simeq f_2$.
The reduction has the effect of eliminating uninterpreted functions. When the reduction
produces a pure bit-vector benchmark, it allows Z3 to use a specialized SAT solver.
### Example
```z3
(declare-const x (_ BitVec 32))
(declare-const y (_ BitVec 32))
(declare-fun f ((_ BitVec 32)) (_ BitVec 8))
(assert (not (= (f x) (f y))))
(apply ackermannize_bv)
```
### Notes
* does not support proofs, does not support unsatisfiable cores
--*/
#pragma once

View file

@ -15,7 +15,7 @@ Revision History:
--*/
#pragma once
#include "tactic/model_converter.h"
#include "ast/converters/model_converter.h"
#include "ackermannization/ackr_info.h"
model_converter * mk_ackr_model_converter(ast_manager & m, const ackr_info_ref & info, model_ref & abstr_model);

View file

@ -16,7 +16,7 @@
--*/
#pragma once
#include "tactic/model_converter.h"
#include "ast/converters/model_converter.h"
#include "ackermannization/ackr_info.h"
model_converter * mk_lackr_model_converter_lazy(ast_manager & m, const ackr_info_ref& info, model_ref& abstr_model);

View file

@ -68,4 +68,5 @@ z3_add_component(api
opt
portfolio
realclosure
extra_cmds
)

View file

@ -48,6 +48,20 @@ extern "C" {
Z3_CATCH_RETURN(nullptr);
}
Z3_ast Z3_API Z3_mk_real_int64(Z3_context c, int64_t num, int64_t den) {
Z3_TRY;
LOG_Z3_mk_real_int64(c, num, den);
RESET_ERROR_CODE();
if (den == 0) {
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
RETURN_Z3(nullptr);
}
sort* s = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT);
ast* a = mk_c(c)->mk_numeral_core(rational(num, rational::i64())/rational(den, rational::i64()), s);
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(nullptr);
}
Z3_ast Z3_API Z3_mk_real(Z3_context c, int num, int den) {
Z3_TRY;
LOG_Z3_mk_real(c, num, den);

View file

@ -137,7 +137,7 @@ extern "C" {
ast_manager& m = mk_c(c)->m();
recfun::decl::plugin& p = mk_c(c)->recfun().get_plugin();
if (!p.has_def(d)) {
std::string msg = "function " + mk_pp(d, m) + " needs to be defined using rec_func_decl";
std::string msg = "function " + mk_pp(d, m) + " needs to be declared using rec_func_decl";
SET_ERROR_CODE(Z3_INVALID_ARG, msg.c_str());
return;
}
@ -158,6 +158,12 @@ extern "C" {
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
return;
}
if (!pd.get_def()->get_cases().empty()) {
std::string msg = "function " + mk_pp(d, m) + " has already been given a definition";
SET_ERROR_CODE(Z3_INVALID_ARG, msg.c_str());
return;
}
if (abs_body->get_sort() != d->get_range()) {
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
return;
@ -654,11 +660,14 @@ extern "C" {
LOG_Z3_get_domain(c, d, i);
RESET_ERROR_CODE();
CHECK_VALID_AST(d, nullptr);
if (i >= to_func_decl(d)->get_arity()) {
func_decl* _d = to_func_decl(d);
if (_d->is_associative())
i = 0;
if (i >= _d->get_arity()) {
SET_ERROR_CODE(Z3_IOB, nullptr);
RETURN_Z3(nullptr);
}
Z3_sort r = of_sort(to_func_decl(d)->get_domain(i));
Z3_sort r = of_sort(_d->get_domain(i));
RETURN_Z3(r);
Z3_CATCH_RETURN(nullptr);
}

View file

@ -51,6 +51,8 @@ namespace api {
}
void context::del_object(api::object* o) {
if (!o)
return;
#ifndef SINGLE_THREAD
if (m_concurrent_dec_ref) {
lock_guard lock(m_mux);
@ -149,6 +151,8 @@ namespace api {
context::~context() {
if (m_parser)
smt2::free_parser(m_parser);
m_last_obj = nullptr;
flush_objects();
for (auto& kv : m_allocated_objects) {

View file

@ -50,6 +50,11 @@ namespace realclosure {
class manager;
};
namespace smt2 {
class parser;
void free_parser(parser*);
};
namespace api {
class seq_expr_solver : public expr_solver {
@ -233,6 +238,19 @@ namespace api {
void check_sorts(ast * n);
// ------------------------------------------------
//
// State reused by calls to Z3_eval_smtlib2_string
//
// ------------------------------------------------
//
// The m_parser field is reused by all calls of Z3_eval_smtlib2_string using this context.
// It is an optimization to save the cost of recreating these objects on each invocation.
//
// See https://github.com/Z3Prover/z3/pull/6422 for the motivation
smt2::parser* m_parser = nullptr;
// ------------------------
//
// Polynomial manager & caches

View file

@ -395,8 +395,7 @@ extern "C" {
Z3_string s) {
Z3_TRY;
LOG_Z3_fixedpoint_from_string(c, d, s);
std::string str(s);
std::istringstream is(str);
std::istringstream is(s);
RETURN_Z3(Z3_fixedpoint_from_stream(c, d, is));
Z3_CATCH_RETURN(nullptr);
}

View file

@ -102,6 +102,13 @@ extern "C" {
sort* e;
ptr_vector<constructor_decl> constrs;
symbol sname = to_symbol(name);
if (mk_c(c)->get_dt_plugin()->is_declared(sname)) {
SET_ERROR_CODE(Z3_INVALID_ARG, "enumeration sort name is already declared");
RETURN_Z3(nullptr);
}
for (unsigned i = 0; i < n; ++i) {
symbol e_name(to_symbol(enum_names[i]));
std::string recognizer_s("is_");
@ -112,8 +119,9 @@ extern "C" {
}
{
datatype_decl * dt = mk_datatype_decl(dt_util, to_symbol(name), 0, nullptr, n, constrs.data());
datatype_decl * dt = mk_datatype_decl(dt_util, sname, 0, nullptr, n, constrs.data());
bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, 0, nullptr, sorts);
del_datatype_decl(dt);

View file

@ -383,8 +383,7 @@ extern "C" {
Z3_string s) {
Z3_TRY;
//LOG_Z3_optimize_from_string(c, d, s);
std::string str(s);
std::istringstream is(str);
std::istringstream is(s);
Z3_optimize_from_stream(c, d, is, nullptr);
Z3_CATCH;
}

View file

@ -116,7 +116,7 @@ extern "C" {
RESET_ERROR_CODE();
std::ostringstream buffer;
to_params(p)->m_params.display(buffer);
return mk_c(c)->mk_external_string(buffer.str());
return mk_c(c)->mk_external_string(std::move(buffer).str());
Z3_CATCH_RETURN("");
}
@ -208,7 +208,7 @@ extern "C" {
buffer << to_param_descrs_ptr(p)->get_param_name(i);
}
buffer << ")";
return mk_c(c)->mk_external_string(buffer.str());
return mk_c(c)->mk_external_string(std::move(buffer).str());
Z3_CATCH_RETURN("");
}

View file

@ -27,6 +27,7 @@ Revision History:
#include "solver/solver_na2as.h"
#include "muz/fp/dl_cmds.h"
#include "opt/opt_cmds.h"
#include "cmd_context/extra_cmds/proof_cmds.h"
@ -42,6 +43,7 @@ extern "C" {
ast_manager& m = c.m();
ctx = alloc(cmd_context, false, &(m));
install_dl_cmds(*ctx.get());
install_proof_cmds(*ctx.get());
install_opt_cmds(*ctx.get());
install_smt2_extra_cmds(*ctx.get());
ctx->register_plist();
@ -155,8 +157,7 @@ extern "C" {
Z3_ast_vector Z3_API Z3_parser_context_from_string(Z3_context c, Z3_parser_context pc, Z3_string str) {
Z3_TRY;
LOG_Z3_parser_context_from_string(c, pc, str);
std::string s(str);
std::istringstream is(s);
std::istringstream is(str);
auto& ctx = to_parser_context(pc)->ctx;
Z3_ast_vector r = Z3_parser_context_parse_stream(c, ctx, false, is);
RETURN_Z3(r);
@ -175,6 +176,7 @@ extern "C" {
ast_manager& m = mk_c(c)->m();
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(m));
install_dl_cmds(*ctx.get());
install_proof_cmds(*ctx.get());
install_opt_cmds(*ctx.get());
install_smt2_extra_cmds(*ctx.get());
ctx->register_plist();
@ -199,8 +201,7 @@ extern "C" {
Z3_func_decl const decls[]) {
Z3_TRY;
LOG_Z3_parse_smtlib2_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
std::string s(str);
std::istringstream is(s);
std::istringstream is(str);
Z3_ast_vector r = parse_smtlib2_stream(false, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
RETURN_Z3(r);
Z3_CATCH_RETURN(nullptr);
@ -233,19 +234,20 @@ extern "C" {
auto* ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
mk_c(c)->cmd() = ctx;
install_dl_cmds(*ctx);
install_proof_cmds(*ctx);
install_opt_cmds(*ctx);
install_smt2_extra_cmds(*ctx);
ctx->register_plist();
ctx->set_solver_factory(mk_smt_strategic_solver_factory());
}
scoped_ptr<cmd_context>& ctx = mk_c(c)->cmd();
std::string s(str);
std::istringstream is(s);
std::istringstream is(str);
ctx->set_regular_stream(ous);
ctx->set_diagnostic_stream(ous);
cmd_context::scoped_redirect _redirect(*ctx);
try {
if (!parse_smt2_commands(*ctx.get(), is)) {
// See api::context::m_parser for a motivation about the reuse of the parser
if (!parse_smt2_commands_with_parser(mk_c(c)->m_parser, *ctx.get(), is)) {
SET_ERROR_CODE(Z3_PARSER_ERROR, ous.str());
RETURN_Z3(mk_c(c)->mk_external_string(ous.str()));
}

View file

@ -25,7 +25,7 @@ Notes:
#include "api/api_model.h"
#include "api/api_ast_map.h"
#include "api/api_ast_vector.h"
#include "qe/lite/qe_lite.h"
#include "qe/lite/qe_lite_tactic.h"
#include "muz/spacer/spacer_util.h"
extern "C"

View file

@ -212,6 +212,8 @@ extern "C" {
buffer.push_back('\\');
buffer.push_back('u');
buffer.push_back('{');
if (ch == 0)
buff.push_back('0');
while (ch > 0) {
unsigned d = ch & 0xF;
if (d < 10)

View file

@ -43,6 +43,8 @@ Revision History:
#include "sat/sat_solver.h"
#include "sat/tactic/goal2sat.h"
#include "sat/tactic/sat2goal.h"
#include "cmd_context/extra_cmds/proof_cmds.h"
#include "solver/simplifier_solver.h"
extern "C" {
@ -231,12 +233,26 @@ extern "C" {
Z3_CATCH_RETURN(nullptr);
}
Z3_solver Z3_API Z3_solver_add_simplifier(Z3_context c, Z3_solver solver, Z3_simplifier simplifier) {
Z3_TRY;
LOG_Z3_solver_add_simplifier(c, solver, simplifier);
init_solver(c, solver);
auto simp = to_simplifier_ref(simplifier);
auto* slv = mk_simplifier_solver(to_solver_ref(solver), simp);
Z3_solver_ref* sr = alloc(Z3_solver_ref, *mk_c(c), slv);
mk_c(c)->save_object(sr);
// ?? init_solver_log(c, sr)
RETURN_Z3(of_solver(sr));
Z3_CATCH_RETURN(nullptr);
}
Z3_solver Z3_API Z3_solver_translate(Z3_context c, Z3_solver s, Z3_context target) {
Z3_TRY;
LOG_Z3_solver_translate(c, s, target);
RESET_ERROR_CODE();
params_ref const& p = to_solver(s)->m_params;
Z3_solver_ref * sr = alloc(Z3_solver_ref, *mk_c(target), nullptr);
Z3_solver_ref * sr = alloc(Z3_solver_ref, *mk_c(target), (solver_factory *)nullptr);
init_solver(c, s);
sr->m_solver = to_solver(s)->m_solver->translate(mk_c(target)->m(), p);
mk_c(target)->save_object(sr);
@ -257,8 +273,10 @@ extern "C" {
void solver_from_stream(Z3_context c, Z3_solver s, std::istream& is) {
auto& solver = *to_solver(s);
if (!solver.m_cmd_context)
if (!solver.m_cmd_context) {
solver.m_cmd_context = alloc(cmd_context, false, &(mk_c(c)->m()));
install_proof_cmds(*solver.m_cmd_context);
}
auto& ctx = solver.m_cmd_context;
ctx->set_ignore_check(true);
std::stringstream errstrm;
@ -270,6 +288,7 @@ extern "C" {
return;
}
bool initialized = to_solver(s)->m_solver.get() != nullptr;
if (!initialized)
init_solver(c, s);
@ -277,6 +296,10 @@ extern "C" {
to_solver(s)->assert_expr(e);
ctx->reset_tracked_assertions();
to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
auto* ctx_s = ctx->get_solver();
if (ctx_s && ctx_s->get_proof())
to_solver_ref(s)->set_proof(ctx_s->get_proof());
}
static void solver_from_dimacs_stream(Z3_context c, Z3_solver s, std::istream& is) {
@ -310,8 +333,7 @@ extern "C" {
void Z3_API Z3_solver_from_string(Z3_context c, Z3_solver s, Z3_string c_str) {
Z3_TRY;
LOG_Z3_solver_from_string(c, s, c_str);
std::string str(c_str);
std::istringstream is(str);
std::istringstream is(c_str);
if (is_dimacs_string(c_str)) {
solver_from_dimacs_stream(c, s, is);
}
@ -399,7 +421,11 @@ extern "C" {
params.validate(r);
to_solver_ref(s)->updt_params(params);
}
to_solver(s)->m_params.append(params);
auto& solver = *to_solver(s);
solver.m_params.append(params);
if (solver.m_cmd_context && solver.m_cmd_context->get_proof_cmds())
solver.m_cmd_context->get_proof_cmds()->updt_params(solver.m_params);
init_solver_log(c, s);
@ -684,7 +710,29 @@ extern "C" {
RESET_ERROR_CODE();
init_solver(c, s);
expr_ref_vector core(mk_c(c)->m());
to_solver_ref(s)->get_unsat_core(core);
solver_params sp(to_solver(s)->m_params);
unsigned timeout = mk_c(c)->get_timeout();
timeout = to_solver(s)->m_params.get_uint("timeout", timeout);
timeout = sp.timeout() != UINT_MAX ? sp.timeout() : timeout;
unsigned rlimit = to_solver(s)->m_params.get_uint("rlimit", mk_c(c)->get_rlimit());
bool use_ctrl_c = to_solver(s)->m_params.get_bool("ctrl_c", true);
cancel_eh<reslimit> eh(mk_c(c)->m().limit());
to_solver(s)->set_eh(&eh);
{
scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
scoped_timer timer(timeout, &eh);
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
try {
to_solver_ref(s)->get_unsat_core(core);
}
catch (...) {
to_solver_ref(s)->set_reason_unknown(eh);
to_solver(s)->set_eh(nullptr);
if (core.empty())
throw;
}
}
to_solver(s)->set_eh(nullptr);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(v);
for (expr* e : core) {
@ -870,6 +918,26 @@ extern "C" {
Z3_CATCH_RETURN(nullptr);
}
Z3_ast Z3_API Z3_solver_congruence_root(Z3_context c, Z3_solver s, Z3_ast a) {
Z3_TRY;
LOG_Z3_solver_congruence_root(c, s, a);
RESET_ERROR_CODE();
init_solver(c, s);
expr* r = to_solver_ref(s)->congruence_root(to_expr(a));
RETURN_Z3(of_expr(r));
Z3_CATCH_RETURN(nullptr);
}
Z3_ast Z3_API Z3_solver_congruence_next(Z3_context c, Z3_solver s, Z3_ast a) {
Z3_TRY;
LOG_Z3_solver_congruence_next(c, s, a);
RESET_ERROR_CODE();
init_solver(c, s);
expr* sib = to_solver_ref(s)->congruence_next(to_expr(a));
RETURN_Z3(of_expr(sib));
Z3_CATCH_RETURN(nullptr);
}
class api_context_obj : public user_propagator::context_obj {
api::context* c;
public:
@ -877,6 +945,45 @@ extern "C" {
~api_context_obj() override { dealloc(c); }
};
struct scoped_ast_vector {
Z3_ast_vector_ref* v;
scoped_ast_vector(Z3_ast_vector_ref* v): v(v) { v->inc_ref(); }
~scoped_ast_vector() { v->dec_ref(); }
};
void Z3_API Z3_solver_register_on_clause(
Z3_context c,
Z3_solver s,
void* user_context,
Z3_on_clause_eh on_clause_eh) {
Z3_TRY;
RESET_ERROR_CODE();
init_solver(c, s);
user_propagator::on_clause_eh_t _on_clause = [=](void* user_ctx, expr* proof, unsigned n, expr* const* _literals) {
Z3_ast_vector_ref * literals = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(literals);
expr_ref pr(proof, mk_c(c)->m());
scoped_ast_vector _sc(literals);
for (unsigned i = 0; i < n; ++i)
literals->m_ast_vector.push_back(_literals[i]);
on_clause_eh(user_ctx, of_expr(pr.get()), of_ast_vector(literals));
};
to_solver_ref(s)->register_on_clause(user_context, _on_clause);
auto& solver = *to_solver(s);
if (!solver.m_cmd_context) {
solver.m_cmd_context = alloc(cmd_context, false, &(mk_c(c)->m()));
install_proof_cmds(*solver.m_cmd_context);
}
if (!solver.m_cmd_context->get_proof_cmds()) {
init_proof_cmds(*solver.m_cmd_context);
solver.m_cmd_context->get_proof_cmds()->updt_params(solver.m_params);
}
solver.m_cmd_context->get_proof_cmds()->register_on_clause(user_context, _on_clause);
Z3_CATCH;
}
void Z3_API Z3_solver_propagate_init(
Z3_context c,
Z3_solver s,

View file

@ -52,6 +52,9 @@ struct Z3_solver_ref : public api::object {
Z3_solver_ref(api::context& c, solver_factory * f):
api::object(c), m_solver_factory(f), m_solver(nullptr), m_logic(symbol::null), m_eh(nullptr) {}
Z3_solver_ref(api::context& c, solver * s):
api::object(c), m_solver_factory(nullptr), m_solver(s), m_logic(symbol::null), m_eh(nullptr) {}
void assert_expr(expr* e);
void assert_expr(expr* e, expr* t);
void set_eh(event_handler* eh);

View file

@ -20,9 +20,11 @@ Revision History:
#include "api/api_context.h"
#include "api/api_tactic.h"
#include "api/api_model.h"
#include "api/api_solver.h"
#include "util/scoped_ctrl_c.h"
#include "util/cancel_eh.h"
#include "util/scoped_timer.h"
#include "ast/simplifiers/seq_simplifier.h"
Z3_apply_result_ref::Z3_apply_result_ref(api::context& c, ast_manager & m): api::object(c) {
}
@ -45,6 +47,14 @@ extern "C" {
RETURN_Z3(_result_); \
}
#define RETURN_SIMPLIFIER(_t_) { \
Z3_simplifier_ref * _ref_ = alloc(Z3_simplifier_ref, *mk_c(c)); \
_ref_->m_simplifier = _t_; \
mk_c(c)->save_object(_ref_); \
Z3_simplifier _result_ = of_simplifier(_ref_); \
RETURN_Z3(_result_); \
}
Z3_tactic Z3_API Z3_mk_tactic(Z3_context c, Z3_string name) {
Z3_TRY;
LOG_Z3_mk_tactic(c, name);
@ -517,6 +527,146 @@ extern "C" {
RETURN_Z3(result);
Z3_CATCH_RETURN(nullptr);
}
Z3_simplifier Z3_API Z3_mk_simplifier(Z3_context c, Z3_string name) {
Z3_TRY;
LOG_Z3_mk_simplifier(c, name);
RESET_ERROR_CODE();
simplifier_cmd * t = mk_c(c)->find_simplifier_cmd(symbol(name));
if (t == nullptr) {
std::stringstream err;
err << "unknown simplifier " << name;
SET_ERROR_CODE(Z3_INVALID_ARG, err.str());
RETURN_Z3(nullptr);
}
simplifier_factory new_t = t->factory();
RETURN_SIMPLIFIER(new_t);
Z3_CATCH_RETURN(nullptr);
}
void Z3_API Z3_simplifier_inc_ref(Z3_context c, Z3_simplifier t) {
Z3_TRY;
LOG_Z3_simplifier_inc_ref(c, t);
RESET_ERROR_CODE();
to_simplifier(t)->inc_ref();
Z3_CATCH;
}
void Z3_API Z3_simplifier_dec_ref(Z3_context c, Z3_simplifier t) {
Z3_TRY;
LOG_Z3_simplifier_dec_ref(c, t);
if (t)
to_simplifier(t)->dec_ref();
Z3_CATCH;
}
unsigned Z3_API Z3_get_num_simplifiers(Z3_context c) {
Z3_TRY;
LOG_Z3_get_num_simplifiers(c);
RESET_ERROR_CODE();
return mk_c(c)->num_simplifiers();
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_get_simplifier_name(Z3_context c, unsigned idx) {
Z3_TRY;
LOG_Z3_get_simplifier_name(c, idx);
RESET_ERROR_CODE();
if (idx >= mk_c(c)->num_simplifiers()) {
SET_ERROR_CODE(Z3_IOB, nullptr);
return "";
}
return mk_c(c)->mk_external_string(mk_c(c)->get_simplifier(idx)->get_name().str().c_str());
Z3_CATCH_RETURN("");
}
Z3_simplifier Z3_API Z3_simplifier_and_then(Z3_context c, Z3_simplifier t1, Z3_simplifier t2) {
Z3_TRY;
LOG_Z3_simplifier_and_then(c, t1, t2);
RESET_ERROR_CODE();
auto fac1 = *to_simplifier_ref(t1);
auto fac2 = *to_simplifier_ref(t2);
auto new_s = [fac1, fac2](auto& m, auto& p, auto& st) {
auto* r = alloc(seq_simplifier, m, p, st);
r->add_simplifier(fac1(m, p, st));
r->add_simplifier(fac2(m, p, st));
return r;
};
RETURN_SIMPLIFIER(new_s);
Z3_CATCH_RETURN(nullptr);
}
Z3_simplifier Z3_API Z3_simplifier_using_params(Z3_context c, Z3_simplifier t, Z3_params p) {
Z3_TRY;
LOG_Z3_simplifier_using_params(c, t, p);
RESET_ERROR_CODE();
param_descrs r;
ast_manager& m = mk_c(c)->m();
default_dependent_expr_state st(m);
params_ref p1;
auto fac = (*to_simplifier_ref(t));
scoped_ptr<dependent_expr_simplifier> simp = fac(m, p1, st);
simp->collect_param_descrs(r);
auto params = to_param_ref(p);
params.validate(r);
auto new_s = [params, fac](auto& m, auto& p, auto& st) {
params_ref pp;
pp.append(params);
pp.append(p);
return fac(m, pp, st);
};
RETURN_SIMPLIFIER(new_s);
Z3_CATCH_RETURN(nullptr);
}
Z3_string Z3_API Z3_simplifier_get_help(Z3_context c, Z3_simplifier t) {
Z3_TRY;
LOG_Z3_simplifier_get_help(c, t);
RESET_ERROR_CODE();
std::ostringstream buffer;
param_descrs descrs;
ast_manager& m = mk_c(c)->m();
default_dependent_expr_state st(m);
params_ref p;
scoped_ptr<dependent_expr_simplifier> simp = (*to_simplifier_ref(t))(m, p, st);
simp->collect_param_descrs(descrs);
descrs.display(buffer);
return mk_c(c)->mk_external_string(buffer.str());
Z3_CATCH_RETURN("");
}
Z3_param_descrs Z3_API Z3_simplifier_get_param_descrs(Z3_context c, Z3_simplifier t) {
Z3_TRY;
LOG_Z3_simplifier_get_param_descrs(c, t);
RESET_ERROR_CODE();
Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref, *mk_c(c));
mk_c(c)->save_object(d);
ast_manager& m = mk_c(c)->m();
default_dependent_expr_state st(m);
params_ref p;
scoped_ptr<dependent_expr_simplifier> simp = (*to_simplifier_ref(t))(m, p, st);
simp->collect_param_descrs(d->m_descrs);
Z3_param_descrs r = of_param_descrs(d);
RETURN_Z3(r);
Z3_CATCH_RETURN(nullptr);
}
Z3_string Z3_API Z3_simplifier_get_descr(Z3_context c, Z3_string name) {
Z3_TRY;
LOG_Z3_simplifier_get_descr(c, name);
RESET_ERROR_CODE();
simplifier_cmd * t = mk_c(c)->find_simplifier_cmd(symbol(name));
if (t == nullptr) {
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
return "";
}
return t->get_descr();
Z3_CATCH_RETURN("");
}
};

View file

@ -19,6 +19,7 @@ Revision History:
#include "api/api_goal.h"
#include "tactic/tactical.h"
#include "ast/simplifiers/dependent_expr_state.h"
namespace api {
class context;
@ -35,10 +36,19 @@ struct Z3_probe_ref : public api::object {
Z3_probe_ref(api::context& c):api::object(c) {}
};
struct Z3_simplifier_ref : public api::object {
simplifier_factory m_simplifier;
Z3_simplifier_ref(api::context& c):api::object(c) {}
};
inline Z3_tactic_ref * to_tactic(Z3_tactic g) { return reinterpret_cast<Z3_tactic_ref *>(g); }
inline Z3_tactic of_tactic(Z3_tactic_ref * g) { return reinterpret_cast<Z3_tactic>(g); }
inline tactic * to_tactic_ref(Z3_tactic g) { return g == nullptr ? nullptr : to_tactic(g)->m_tactic.get(); }
inline Z3_simplifier_ref * to_simplifier(Z3_simplifier g) { return reinterpret_cast<Z3_simplifier_ref *>(g); }
inline Z3_simplifier of_simplifier(Z3_simplifier_ref * g) { return reinterpret_cast<Z3_simplifier>(g); }
inline simplifier_factory * to_simplifier_ref(Z3_simplifier g) { return g == nullptr ? nullptr : &to_simplifier(g)->m_simplifier; }
inline Z3_probe_ref * to_probe(Z3_probe g) { return reinterpret_cast<Z3_probe_ref *>(g); }
inline Z3_probe of_probe(Z3_probe_ref * g) { return reinterpret_cast<Z3_probe>(g); }
inline probe * to_probe_ref(Z3_probe g) { return g == nullptr ? nullptr : to_probe(g)->m_probe.get(); }

View file

@ -63,6 +63,7 @@ namespace z3 {
class solver;
class goal;
class tactic;
class simplifier;
class probe;
class model;
class func_interp;
@ -158,7 +159,7 @@ namespace z3 {
class context {
private:
friend class user_propagator_base;
bool m_enable_exceptions;
bool m_enable_exceptions = true;
rounding_mode m_rounding_mode;
Z3_context m_ctx = nullptr;
void init(config & c) {
@ -366,8 +367,14 @@ namespace z3 {
void recdef(func_decl, expr_vector const& args, expr const& body);
func_decl user_propagate_function(symbol const& name, sort_vector const& domain, sort const& range);
/**
\brief create an uninterpreted constant.
*/
expr constant(symbol const & name, sort const & s);
expr constant(char const * name, sort const & s);
/**
\brief create uninterpreted constants of a given sort.
*/
expr bool_const(char const * name);
expr int_const(char const * name);
expr real_const(char const * name);
@ -378,6 +385,12 @@ namespace z3 {
template<size_t precision>
expr fpa_const(char const * name);
/**
\brief create a de-Bruijn variable.
*/
expr variable(unsigned index, sort const& s);
expr fpa_rounding_mode();
expr bool_val(bool b);
@ -388,11 +401,11 @@ namespace z3 {
expr int_val(uint64_t n);
expr int_val(char const * n);
expr real_val(int n, int d);
expr real_val(int n);
expr real_val(unsigned n);
expr real_val(int64_t n);
expr real_val(uint64_t n);
expr real_val(int64_t n, int64_t d);
expr real_val(char const * n);
expr bv_val(int n, unsigned sz);
@ -1566,6 +1579,11 @@ namespace z3 {
*/
expr substitute(expr_vector const& dst);
/**
\brief Apply function substitution by macro definitions.
*/
expr substitute(func_decl_vector const& funs, expr_vector const& bodies);
class iterator {
expr& e;
@ -1902,21 +1920,21 @@ namespace z3 {
inline expr operator>(expr const & a, int b) { return a > a.ctx().num_val(b, a.get_sort()); }
inline expr operator>(int a, expr const & b) { return b.ctx().num_val(a, b.get_sort()) > b; }
inline expr operator&(expr const & a, expr const & b) { if (a.is_bool()) return a && b; check_context(a, b); Z3_ast r = Z3_mk_bvand(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr operator&(expr const & a, expr const & b) { if (a.is_bool()) return a && b; check_context(a, b); Z3_ast r = Z3_mk_bvand(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr operator&(expr const & a, int b) { return a & a.ctx().num_val(b, a.get_sort()); }
inline expr operator&(int a, expr const & b) { return b.ctx().num_val(a, b.get_sort()) & b; }
inline expr operator^(expr const & a, expr const & b) { check_context(a, b); Z3_ast r = a.is_bool() ? Z3_mk_xor(a.ctx(), a, b) : Z3_mk_bvxor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr operator^(expr const & a, expr const & b) { check_context(a, b); Z3_ast r = a.is_bool() ? Z3_mk_xor(a.ctx(), a, b) : Z3_mk_bvxor(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr operator^(expr const & a, int b) { return a ^ a.ctx().num_val(b, a.get_sort()); }
inline expr operator^(int a, expr const & b) { return b.ctx().num_val(a, b.get_sort()) ^ b; }
inline expr operator|(expr const & a, expr const & b) { if (a.is_bool()) return a || b; check_context(a, b); Z3_ast r = Z3_mk_bvor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr operator|(expr const & a, expr const & b) { if (a.is_bool()) return a || b; check_context(a, b); Z3_ast r = Z3_mk_bvor(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr operator|(expr const & a, int b) { return a | a.ctx().num_val(b, a.get_sort()); }
inline expr operator|(int a, expr const & b) { return b.ctx().num_val(a, b.get_sort()) | b; }
inline expr nand(expr const& a, expr const& b) { if (a.is_bool()) return !(a && b); check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr nor(expr const& a, expr const& b) { if (a.is_bool()) return !(a || b); check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr xnor(expr const& a, expr const& b) { if (a.is_bool()) return !(a ^ b); check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); return expr(a.ctx(), r); }
inline expr nand(expr const& a, expr const& b) { if (a.is_bool()) return !(a && b); check_context(a, b); Z3_ast r = Z3_mk_bvnand(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr nor(expr const& a, expr const& b) { if (a.is_bool()) return !(a || b); check_context(a, b); Z3_ast r = Z3_mk_bvnor(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr xnor(expr const& a, expr const& b) { if (a.is_bool()) return !(a ^ b); check_context(a, b); Z3_ast r = Z3_mk_bvxnor(a.ctx(), a, b); a.check_error(); return expr(a.ctx(), r); }
inline expr min(expr const& a, expr const& b) {
check_context(a, b);
Z3_ast r;
@ -1930,6 +1948,7 @@ namespace z3 {
assert(a.is_fpa());
r = Z3_mk_fpa_min(a.ctx(), a, b);
}
a.check_error();
return expr(a.ctx(), r);
}
inline expr max(expr const& a, expr const& b) {
@ -1945,6 +1964,7 @@ namespace z3 {
assert(a.is_fpa());
r = Z3_mk_fpa_max(a.ctx(), a, b);
}
a.check_error();
return expr(a.ctx(), r);
}
inline expr bvredor(expr const & a) {
@ -2670,12 +2690,13 @@ namespace z3 {
public:
struct simple {};
struct translate {};
solver(context & c):object(c) { init(Z3_mk_solver(c)); }
solver(context & c, simple):object(c) { init(Z3_mk_simple_solver(c)); }
solver(context & c):object(c) { init(Z3_mk_solver(c)); check_error(); }
solver(context & c, simple):object(c) { init(Z3_mk_simple_solver(c)); check_error(); }
solver(context & c, Z3_solver s):object(c) { init(s); }
solver(context & c, char const * logic):object(c) { init(Z3_mk_solver_for_logic(c, c.str_symbol(logic))); }
solver(context & c, char const * logic):object(c) { init(Z3_mk_solver_for_logic(c, c.str_symbol(logic))); check_error(); }
solver(context & c, solver const& src, translate): object(c) { Z3_solver s = Z3_solver_translate(src.ctx(), src, c); check_error(); init(s); }
solver(solver const & s):object(s) { init(s.m_solver); }
solver(solver const& s, simplifier const& simp);
~solver() { Z3_solver_dec_ref(ctx(), m_solver); }
operator Z3_solver() const { return m_solver; }
solver & operator=(solver const & s) {
@ -3046,6 +3067,47 @@ namespace z3 {
return tactic(t1.ctx(), r);
}
class simplifier : public object {
Z3_simplifier m_simplifier;
void init(Z3_simplifier s) {
m_simplifier = s;
Z3_simplifier_inc_ref(ctx(), s);
}
public:
simplifier(context & c, char const * name):object(c) { Z3_simplifier r = Z3_mk_simplifier(c, name); check_error(); init(r); }
simplifier(context & c, Z3_simplifier s):object(c) { init(s); }
simplifier(simplifier const & s):object(s) { init(s.m_simplifier); }
~simplifier() { Z3_simplifier_dec_ref(ctx(), m_simplifier); }
operator Z3_simplifier() const { return m_simplifier; }
simplifier & operator=(simplifier const & s) {
Z3_simplifier_inc_ref(s.ctx(), s.m_simplifier);
Z3_simplifier_dec_ref(ctx(), m_simplifier);
object::operator=(s);
m_simplifier = s.m_simplifier;
return *this;
}
std::string help() const { char const * r = Z3_simplifier_get_help(ctx(), m_simplifier); check_error(); return r; }
friend simplifier operator&(simplifier const & t1, simplifier const & t2);
friend simplifier with(simplifier const & t, params const & p);
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_simplifier_get_param_descrs(ctx(), m_simplifier)); }
};
inline solver::solver(solver const& s, simplifier const& simp):object(s) { init(Z3_solver_add_simplifier(s.ctx(), s, simp)); }
inline simplifier operator&(simplifier const & t1, simplifier const & t2) {
check_context(t1, t2);
Z3_simplifier r = Z3_simplifier_and_then(t1.ctx(), t1, t2);
t1.check_error();
return simplifier(t1.ctx(), r);
}
inline simplifier with(simplifier const & t, params const & p) {
Z3_simplifier r = Z3_simplifier_using_params(t.ctx(), t, p);
t.check_error();
return simplifier(t.ctx(), r);
}
class probe : public object {
Z3_probe m_probe;
void init(Z3_probe s) {
@ -3575,6 +3637,11 @@ namespace z3 {
return expr(*this, r);
}
inline expr context::constant(char const * name, sort const & s) { return constant(str_symbol(name), s); }
inline expr context::variable(unsigned idx, sort const& s) {
Z3_ast r = Z3_mk_bound(m_ctx, idx, s);
check_error();
return expr(*this, r);
}
inline expr context::bool_const(char const * name) { return constant(name, bool_sort()); }
inline expr context::int_const(char const * name) { return constant(name, int_sort()); }
inline expr context::real_const(char const * name) { return constant(name, real_sort()); }
@ -3606,7 +3673,7 @@ namespace z3 {
inline expr context::int_val(uint64_t n) { Z3_ast r = Z3_mk_unsigned_int64(m_ctx, n, int_sort()); check_error(); return expr(*this, r); }
inline expr context::int_val(char const * n) { Z3_ast r = Z3_mk_numeral(m_ctx, n, int_sort()); check_error(); return expr(*this, r); }
inline expr context::real_val(int n, int d) { Z3_ast r = Z3_mk_real(m_ctx, n, d); check_error(); return expr(*this, r); }
inline expr context::real_val(int64_t n, int64_t d) { Z3_ast r = Z3_mk_real_int64(m_ctx, n, d); check_error(); return expr(*this, r); }
inline expr context::real_val(int n) { Z3_ast r = Z3_mk_int(m_ctx, n, real_sort()); check_error(); return expr(*this, r); }
inline expr context::real_val(unsigned n) { Z3_ast r = Z3_mk_unsigned_int(m_ctx, n, real_sort()); check_error(); return expr(*this, r); }
inline expr context::real_val(int64_t n) { Z3_ast r = Z3_mk_int64(m_ctx, n, real_sort()); check_error(); return expr(*this, r); }
@ -4059,6 +4126,41 @@ namespace z3 {
return expr(ctx(), r);
}
inline expr expr::substitute(func_decl_vector const& funs, expr_vector const& dst) {
array<Z3_ast> _dst(dst.size());
array<Z3_func_decl> _funs(funs.size());
if (dst.size() != funs.size()) {
Z3_THROW(exception("length of argument lists don't align"));
return expr(ctx(), nullptr);
}
for (unsigned i = 0; i < dst.size(); ++i) {
_dst[i] = dst[i];
_funs[i] = funs[i];
}
Z3_ast r = Z3_substitute_funs(ctx(), m_ast, dst.size(), _funs.ptr(), _dst.ptr());
check_error();
return expr(ctx(), r);
}
typedef std::function<void(expr const& proof, expr_vector const& clause)> on_clause_eh_t;
class on_clause {
context& c;
on_clause_eh_t m_on_clause;
static void _on_clause_eh(void* _ctx, Z3_ast _proof, Z3_ast_vector _literals) {
on_clause* ctx = static_cast<on_clause*>(_ctx);
expr_vector lits(ctx->c, _literals);
expr proof(ctx->c, _proof);
ctx->m_on_clause(proof, lits);
}
public:
on_clause(solver& s, on_clause_eh_t& on_clause_eh): c(s.ctx()) {
m_on_clause = on_clause_eh;
Z3_solver_register_on_clause(c, s, this, _on_clause_eh);
c.check_error();
}
};
class user_propagator_base {

View file

@ -87,6 +87,7 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
NativeFuncInterp.cs
NativeModel.cs
NativeSolver.cs
OnClause.cs
Optimize.cs
ParamDescrs.cs
Params.cs

102
src/api/dotnet/OnClause.cs Normal file
View file

@ -0,0 +1,102 @@
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
OnClause.cs
Abstract:
Callback on clause inferences
Author:
Nikolaj Bjorner (nbjorner) 2022-10-19
Notes:
--*/
using System;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Microsoft.Z3
{
using Z3_context = System.IntPtr;
using Z3_solver = System.IntPtr;
using voidp = System.IntPtr;
using Z3_ast = System.IntPtr;
using Z3_ast_vector = System.IntPtr;
/// <summary>
/// OnClause - clause inference callback
/// </summary>
public class OnClause : IDisposable
{
/// <summary>
/// Delegate type for when clauses are inferred.
/// An inference is a pair comprising of
/// - a proof (hint). A partial (or comprehensive) derivation justifying the inference.
/// - a clause (vector of literals)
/// The life-time of the proof hint and clause vector is limited to the scope of the callback.
/// should the callback want to store hints or clauses it will need to call Dup on the hints
/// and/or extract literals from the clause, respectively.
/// </summary>
public delegate void OnClauseEh(Expr proof_hint, ASTVector clause);
// access managed objects through a static array.
// thread safety is ignored for now.
GCHandle gch;
Solver solver;
Context ctx;
OnClauseEh on_clause;
Native.Z3_on_clause_eh on_clause_eh;
static void _on_clause(voidp ctx, Z3_ast _proof_hint, Z3_ast_vector _clause)
{
var onc = (OnClause)GCHandle.FromIntPtr(ctx).Target;
using var proof_hint = Expr.Create(onc.ctx, _proof_hint);
using var clause = new ASTVector(onc.ctx, _clause);
onc.on_clause(proof_hint, clause);
}
/// <summary>
/// OnClause constructor
/// </summary>
public OnClause(Solver s, OnClauseEh onc)
{
gch = GCHandle.Alloc(this);
solver = s;
ctx = solver.Context;
on_clause = onc;
on_clause_eh = _on_clause;
Native.Z3_solver_register_on_clause(ctx.nCtx, solver.NativeObject, GCHandle.ToIntPtr(gch), on_clause_eh);
}
/// <summary>
/// Release private memory.
/// </summary>
~OnClause()
{
Dispose();
}
/// <summary>
/// Must be called. The object will not be garbage collected automatically even if the context is disposed
/// </summary>
public virtual void Dispose()
{
if (!gch.IsAllocated)
return;
gch.Free();
}
}
}

View file

@ -2110,7 +2110,7 @@ public class Context implements AutoCloseable {
* Check if the string s1 is lexicographically strictly less than s2.
*/
public BoolExpr MkStringLt(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
public BoolExpr MkStringLt(Expr<SeqSort<CharSort>> s1, Expr<SeqSort<CharSort>> s2)
{
checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkStrLt(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
@ -2119,7 +2119,7 @@ public class Context implements AutoCloseable {
/**
* Check if the string s1 is lexicographically less or equal to s2.
*/
public BoolExpr MkStringLe(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
public BoolExpr MkStringLe(Expr<SeqSort<CharSort>> s1, Expr<SeqSort<CharSort>> s2)
{
checkContextMatch(s1, s2);
return new BoolExpr(this, Native.mkStrLe(nCtx(), s1.getNativeObject(), s2.getNativeObject()));

View file

@ -11,6 +11,9 @@ You'll need to have emscripten set up, along with all of its dependencies. The e
Then run `npm i` to install dependencies, `npm run build:ts` to build the TypeScript wrapper, and `npm run build:wasm` to build the wasm artifact.
### Build on your own
Consult the file [build-wasm.ts](https://github.com/Z3Prover/z3/blob/master/src/api/js/scripts/build-wasm.ts) for configurations used for building wasm.
## Tests

File diff suppressed because it is too large Load diff

View file

@ -35,7 +35,8 @@
"contributors": [
"Kevin Gibbons <bakkot@gmail.com>",
"Nikolaj Bjorner",
"Olaf Tomalka <olaf@tomalka.me>"
"Olaf Tomalka <olaf@tomalka.me>",
"Walden Yan <waldenyan20@gmail.com>"
],
"devDependencies": {
"@types/jest": "^27.5.1",
@ -49,6 +50,7 @@
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"sprintf-js": "^1.1.2",
"ts-expect": "^1.3.0",
"ts-jest": "^28.0.3",
"ts-node": "^10.8.0",
"typedoc": "^0.22.17",

View file

@ -45,6 +45,8 @@ const types = {
__proto__: null,
// these are function types I can't be bothered to parse
// NSB: They can be extracted automatically from z3_api.h thanks to the use
// of a macro.
Z3_error_handler: 'Z3_error_handler',
Z3_push_eh: 'Z3_push_eh',
Z3_pop_eh: 'Z3_pop_eh',
@ -54,6 +56,7 @@ const types = {
Z3_final_eh: 'Z3_final_eh',
Z3_created_eh: 'Z3_created_eh',
Z3_decide_eh: 'Z3_decide_eh',
Z3_on_clause_eh: 'Z3_on_clause_eh',
} as unknown as Record<string, string>;
export type ApiParam = { kind: string; sizeIndex?: number; type: string };

View file

@ -2,6 +2,7 @@ import assert from 'assert';
import asyncToArray from 'iter-tools/methods/async-to-array';
import { init, killThreads } from '../jest';
import { Arith, Bool, Model, Z3AssertionError, Z3HighLevel } from './types';
import { expectType } from "ts-expect";
/**
* Generate all possible solutions from given assumptions.
@ -113,7 +114,7 @@ describe('high-level', () => {
const { Solver, Not, Int } = api.Context('main');
const solver = new Solver();
solver.fromString("(declare-const x Int) (assert (and (< x 2) (> x 0)))")
expect(await solver.check()).toStrictEqual('sat')
expect(await solver.check()).toStrictEqual('sat')
const x = Int.const('x')
solver.add(Not(x.eq(1)))
expect(await solver.check()).toStrictEqual('unsat')
@ -211,6 +212,7 @@ describe('high-level', () => {
}
return cells;
}
const INSTANCE = toSudoku(`
....94.3.
...51...7
@ -390,6 +392,106 @@ describe('high-level', () => {
});
});
describe('arrays', () => {
it('Example 1', async () => {
const Z3 = api.Context('main');
const arr = Z3.Array.const('arr', Z3.Int.sort(), Z3.Int.sort());
const [idx, val] = Z3.Int.consts('idx val');
const conjecture = (arr.store(idx, val).select(idx).eq(val));
await prove(conjecture);
});
it('domain and range type inference', async () => {
const { BitVec, Array, isArray, isArraySort } = api.Context('main');
const arr = Array.const('arr', BitVec.sort(160), BitVec.sort(256));
const domain = arr.domain();
expect(domain.size()).toStrictEqual(160);
expect(arr.domain_n(0).size()).toStrictEqual(160);
const range = arr.range();
expect(range.size()).toStrictEqual(256);
assert(isArray(arr) && isArraySort(arr.sort));
const arr2 = Array.const('arr2', BitVec.sort(1), BitVec.sort(2), BitVec.sort(3));
const dom2 = arr2.domain_n(1);
// We can call size() on dom2 and see that it is two bits
// purely from type inference
expectType<2>(dom2.size());
// Won't let us create an array constant with only one of domain/range
// and is detected at compile time
// @ts-expect-error
const arr3 = Array.const('arr3', BitVec.sort(1));
})
it('can do simple proofs', async () => {
const { BitVec, Array, isArray, isArraySort, isConstArray, Eq, Not } = api.Context('main');
const idx = BitVec.const('idx', 160);
const val = BitVec.const('val', 256);
const FIVE_VAL = BitVec.val(5, 256);
const arr = Array.const('arr', BitVec.sort(160), BitVec.sort(256));
const constArr = Array.K(BitVec.sort(160), FIVE_VAL);
assert(isArray(arr) && isArraySort(arr.sort) && isConstArray(constArr));
const arr2 = arr.store(0, 5);
await prove(Eq(arr2.select(0), FIVE_VAL));
await prove(Not(Eq(arr2.select(0), BitVec.val(6, 256))));
await prove(Eq(arr2.store(idx, val).select(idx), constArr.store(idx, val).select(idx)));
// TODO: add in Quantifiers and better typing of arrays
// await prove(
// ForAll([idx], idx.add(1).ugt(idx).and(arr.select(idx.add(1)).ugt(arr.select(idx)))).implies(
// arr.select(0).ult(arr.select(1000))
// )
// );
});
it('Finds arrays that differ but that sum to the same', async () => {
const Z3 = api.Context('main');
const { Array, BitVec } = Z3;
const mod = 1n << 32n;
const arr1 = Array.const('arr', BitVec.sort(2), BitVec.sort(32));
const arr2 = Array.const('arr2', BitVec.sort(2), BitVec.sort(32));
const same_sum = arr1.select(0)
.add(arr1.select(1))
.add(arr1.select(2))
.add(arr1.select(3))
.eq(
arr2.select(0)
.add(arr2.select(1))
.add(arr2.select(2))
.add(arr2.select(3))
);
const different = arr1.select(0).neq(arr2.select(0))
.or(arr1.select(1).neq(arr2.select(1)))
.or(arr1.select(2).neq(arr2.select(2)))
.or(arr1.select(3).neq(arr2.select(3)));
const model = await solve(same_sum.and(different));
const arr1Vals = [0, 1, 2, 3].map(i => model.eval(arr1.select(i)).value());
const arr2Vals = [0, 1, 2, 3].map(i => model.eval(arr2.select(i)).value());
expect((arr1Vals.reduce((a, b) => a + b, 0n) % mod) === arr2Vals.reduce((a, b) => a + b, 0n) % mod);
for (let i = 0; i < 4; i++) {
expect(arr1Vals[i] !== arr2Vals[i]);
}
});
});
describe('Solver', () => {
it('can use push and pop', async () => {
const { Solver, Int } = api.Context('main');

View file

@ -37,7 +37,7 @@ import {
AnyExpr,
AnySort,
Arith,
ArithSort,
ArithSort, ArrayIndexType,
Ast,
AstMap,
AstMapCtor,
@ -48,7 +48,7 @@ import {
BitVecSort,
Bool,
BoolSort,
CheckSatResult,
CheckSatResult, CoercibleFromMap,
CoercibleRational,
CoercibleToBitVec,
CoercibleToExpr,
@ -63,6 +63,8 @@ import {
Model,
Probe,
RatNum,
SMTArray,
SMTArraySort,
Solver,
Sort,
SortToExprMap,
@ -86,12 +88,11 @@ function isCoercibleRational(obj: any): obj is CoercibleRational {
(obj.denominator !== null &&
(typeof obj.denominator === 'number' || typeof obj.denominator === 'bigint'))
);
r &&
assert(
(typeof obj.numerator !== 'number' || Number.isSafeInteger(obj.numerator)) &&
(typeof obj.denominator !== 'number' || Number.isSafeInteger(obj.denominator)),
'Fraction numerator and denominator must be integers',
);
r && assert(
(typeof obj!.numerator !== 'number' || Number.isSafeInteger(obj!.numerator)) &&
(typeof obj!.denominator !== 'number' || Number.isSafeInteger(obj!.denominator)),
'Fraction numerator and denominator must be integers',
);
return r;
}
@ -151,7 +152,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
function createContext<Name extends string>(name: Name, options?: Record<string, any>): Context<Name> {
const cfg = Z3.mk_config();
if (options != null) {
Object.entries(options).forEach(([key, value]) => check(Z3.set_param_value(cfg, key, value.toString())));
Object.entries(options).forEach(
([key, value]) => check(Z3.set_param_value(cfg, key, value.toString()))
);
}
const contextPtr = Z3.mk_context_rc(cfg);
Z3.set_ast_print_mode(contextPtr, Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT);
@ -216,20 +219,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return new ArithSortImpl(ast);
case Z3_sort_kind.Z3_BV_SORT:
return new BitVecSortImpl(ast);
case Z3_sort_kind.Z3_ARRAY_SORT:
return new ArraySortImpl(ast);
default:
return new SortImpl(ast);
}
}
function _toExpr(ast: Z3_ast): Bool<Name> | IntNum<Name> | RatNum<Name> | Arith<Name> | Expr<Name> {
function _toExpr(ast: Z3_ast): AnyExpr<Name> {
const kind = check(Z3.get_ast_kind(contextPtr, ast));
if (kind === Z3_ast_kind.Z3_QUANTIFIER_AST) {
if (Z3.is_quantifier_forall(contextPtr, ast))
return new BoolImpl(ast);
return new BoolImpl(ast);
if (Z3.is_quantifier_exists(contextPtr, ast))
return new BoolImpl(ast);
return new BoolImpl(ast);
if (Z3.is_lambda(contextPtr, ast))
return new ExprImpl(ast);
return new ExprImpl(ast);
assert(false);
}
const sortKind = check(Z3.get_sort_kind(contextPtr, Z3.get_sort(contextPtr, ast)));
@ -251,6 +256,8 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return new BitVecNumImpl(ast);
}
return new BitVecImpl(ast);
case Z3_sort_kind.Z3_ARRAY_SORT:
return new ArrayImpl(ast);
default:
return new ExprImpl(ast);
}
@ -440,6 +447,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return r;
}
function isArraySort(obj: unknown): obj is SMTArraySort<Name> {
const r = obj instanceof ArraySortImpl;
r && _assertContext(obj);
return r;
}
function isArray(obj: unknown): obj is SMTArray<Name> {
const r = obj instanceof ArrayImpl;
r && _assertContext(obj);
return r;
}
function isConstArray(obj: unknown): boolean {
return isAppOf(obj, Z3_decl_kind.Z3_OP_CONST_ARRAY);
}
function isProbe(obj: unknown): obj is Probe<Name> {
const r = obj instanceof ProbeImpl;
r && _assertContext(obj);
@ -508,9 +531,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
// expression simplification //
///////////////////////////////
async function simplify(e : Expr<Name>) {
const result = await Z3.simplify(contextPtr, e.ast)
return _toExpr(check(result));
async function simplify(e: Expr<Name>) {
const result = await Z3.simplify(contextPtr, e.ast)
return _toExpr(check(result));
}
/////////////
@ -677,6 +700,44 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
);
},
};
const Array = {
sort<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
...sig: [...DomainSort, RangeSort]
): SMTArraySort<Name, DomainSort, RangeSort> {
const arity = sig.length - 1;
const r = sig[arity];
const d = sig[0];
if (arity === 1) {
return new ArraySortImpl(Z3.mk_array_sort(contextPtr, d.ptr, r.ptr));
}
const dom = sig.slice(0, arity);
return new ArraySortImpl(Z3.mk_array_sort_n(contextPtr, dom.map(s => s.ptr), r.ptr));
},
const<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
name: string, ...sig: [...DomainSort, RangeSort]
): SMTArray<Name, DomainSort, RangeSort> {
return new ArrayImpl<DomainSort, RangeSort>(
check(Z3.mk_const(contextPtr, _toSymbol(name), Array.sort(...sig).ptr))
);
},
consts<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
names: string | string[],
...sig: [...DomainSort, RangeSort]
): SMTArray<Name, DomainSort, RangeSort>[] {
if (typeof names === 'string') {
names = names.split(' ');
}
return names.map(name => Array.const(name, ...sig));
},
K<DomainSort extends AnySort<Name>, RangeSort extends AnySort<Name>>(
domain: DomainSort,
value: SortToExprMap<RangeSort, Name>
): SMTArray<Name, [DomainSort], RangeSort> {
return new ArrayImpl<[DomainSort], RangeSort>(
check(Z3.mk_const_array(contextPtr, domain.ptr, value.ptr))
);
}
}
////////////////
// Operations //
@ -948,6 +1009,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
readonly ptr: Z3_solver;
readonly ctx: Context<Name>;
constructor(ptr: Z3_solver | string = Z3.mk_solver(contextPtr)) {
this.ctx = ctx;
let myPtr: Z3_solver;
@ -964,21 +1026,26 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
push() {
Z3.solver_push(contextPtr, this.ptr);
}
pop(num: number = 1) {
Z3.solver_pop(contextPtr, this.ptr, num);
}
numScopes() {
return Z3.solver_get_num_scopes(contextPtr, this.ptr);
}
reset() {
Z3.solver_reset(contextPtr, this.ptr);
}
add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]) {
_flattenArgs(exprs).forEach(expr => {
_assertContext(expr);
check(Z3.solver_assert(contextPtr, this.ptr, expr.ast));
});
}
addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string) {
if (typeof constant === 'string') {
constant = Bool.const(constant);
@ -1019,7 +1086,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return check(Z3.solver_to_string(contextPtr, this.ptr));
}
fromString(s : string) {
fromString(s: string) {
Z3.solver_from_string(contextPtr, this.ptr, s);
throwIfError();
}
@ -1043,20 +1110,20 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return this.values();
}
*entries(): IterableIterator<[number, FuncDecl<Name>]> {
* entries(): IterableIterator<[number, FuncDecl<Name>]> {
const length = this.length();
for (let i = 0; i < length; i++) {
yield [i, this.get(i)];
}
}
*keys(): IterableIterator<number> {
* keys(): IterableIterator<number> {
for (const [key] of this.entries()) {
yield key;
}
}
*values(): IterableIterator<FuncDecl<Name>> {
* values(): IterableIterator<FuncDecl<Name>> {
for (const [, value] of this.entries()) {
yield value;
}
@ -1076,11 +1143,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
eval(expr: Bool<Name>, modelCompletion?: boolean): Bool<Name>;
eval(expr: Arith<Name>, modelCompletion?: boolean): Arith<Name>;
eval<Bits extends number = number>(expr: BitVec<Bits, Name>, modelCompletion?: boolean): BitVecNum<Bits, Name>;
eval(expr: Expr<Name>, modelCompletion: boolean = false) {
_assertContext(expr);
const r = check(Z3.model_eval(contextPtr, this.ptr, expr.ast, modelCompletion));
if (r === null) {
throw new Z3Error('Failed to evaluatio expression in the model');
throw new Z3Error('Failed to evaluate expression in the model');
}
return _toExpr(r);
}
@ -1092,7 +1160,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>;
get(
i: number | FuncDecl<Name> | Expr<Name> | Sort<Name>,
to?: number,
to?: number
): FuncDecl<Name> | FuncInterp<Name> | Expr<Name> | AstVector<Name, AnyAst<Name>> | FuncDecl<Name>[] {
assert(to === undefined || typeof i === 'number');
if (typeof i === 'number') {
@ -1362,15 +1430,22 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
not(): Bool<Name> {
return Not(this);
}
and(other: Bool<Name> | boolean): Bool<Name> {
return And(this, other);
}
or(other: Bool<Name> | boolean): Bool<Name> {
return Or(this, other);
}
xor(other: Bool<Name> | boolean): Bool<Name> {
return Xor(this, other);
}
implies(other: Bool<Name> | boolean): Bool<Name> {
return Implies(this, other);
}
}
class ProbeImpl implements Probe<Name> {
@ -1571,27 +1646,35 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
add(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvadd(contextPtr, this.ast, this.sort.cast(other).ast)));
}
mul(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvmul(contextPtr, this.ast, this.sort.cast(other).ast)));
}
sub(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvsub(contextPtr, this.ast, this.sort.cast(other).ast)));
}
sdiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvsdiv(contextPtr, this.ast, this.sort.cast(other).ast)));
}
udiv(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvudiv(contextPtr, this.ast, this.sort.cast(other).ast)));
}
smod(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvsmod(contextPtr, this.ast, this.sort.cast(other).ast)));
}
urem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvurem(contextPtr, this.ast, this.sort.cast(other).ast)));
}
srem(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvsrem(contextPtr, this.ast, this.sort.cast(other).ast)));
}
neg(): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvneg(contextPtr, this.ast)));
}
@ -1599,33 +1682,43 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
or(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvor(contextPtr, this.ast, this.sort.cast(other).ast)));
}
and(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvand(contextPtr, this.ast, this.sort.cast(other).ast)));
}
nand(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvnand(contextPtr, this.ast, this.sort.cast(other).ast)));
}
xor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvxor(contextPtr, this.ast, this.sort.cast(other).ast)));
}
xnor(other: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvxnor(contextPtr, this.ast, this.sort.cast(other).ast)));
}
shr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvashr(contextPtr, this.ast, this.sort.cast(count).ast)));
}
lshr(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvlshr(contextPtr, this.ast, this.sort.cast(count).ast)));
}
shl(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvshl(contextPtr, this.ast, this.sort.cast(count).ast)));
}
rotateRight(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_right(contextPtr, this.ast, this.sort.cast(count).ast)));
}
rotateLeft(count: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_ext_rotate_left(contextPtr, this.ast, this.sort.cast(count).ast)));
}
not(): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvnot(contextPtr, this.ast)));
}
@ -1633,12 +1726,15 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
extract(high: number, low: number): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_extract(contextPtr, high, low, this.ast)));
}
signExt(count: number): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_sign_ext(contextPtr, count, this.ast)));
}
zeroExt(count: number): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_zero_ext(contextPtr, count, this.ast)));
}
repeat(count: number): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_repeat(contextPtr, count, this.ast)));
}
@ -1646,24 +1742,31 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
sle(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsle(contextPtr, this.ast, this.sort.cast(other).ast)));
}
ule(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvule(contextPtr, this.ast, this.sort.cast(other).ast)));
}
slt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvslt(contextPtr, this.ast, this.sort.cast(other).ast)));
}
ult(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvult(contextPtr, this.ast, this.sort.cast(other).ast)));
}
sge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsge(contextPtr, this.ast, this.sort.cast(other).ast)));
}
uge(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvuge(contextPtr, this.ast, this.sort.cast(other).ast)));
}
sgt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsgt(contextPtr, this.ast, this.sort.cast(other).ast)));
}
ugt(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvugt(contextPtr, this.ast, this.sort.cast(other).ast)));
}
@ -1671,6 +1774,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
redAnd(): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvredand(contextPtr, this.ast)));
}
redOr(): BitVec<Bits, Name> {
return new BitVecImpl<Bits>(check(Z3.mk_bvredor(contextPtr, this.ast)));
}
@ -1678,24 +1782,31 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
addNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvadd_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
}
addNoUnderflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvadd_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
}
subNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsub_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
}
subNoUndeflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsub_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
}
sdivNoOverflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvsdiv_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast)));
}
mulNoOverflow(other: CoercibleToBitVec<Bits, Name>, isSigned: boolean): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvmul_no_overflow(contextPtr, this.ast, this.sort.cast(other).ast, isSigned)));
}
mulNoUndeflow(other: CoercibleToBitVec<Bits, Name>): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvmul_no_underflow(contextPtr, this.ast, this.sort.cast(other).ast)));
}
negNoOverflow(): Bool<Name> {
return new BoolImpl(check(Z3.mk_bvneg_no_overflow(contextPtr, this.ast)));
}
@ -1703,6 +1814,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
class BitVecNumImpl<Bits extends number> extends BitVecImpl<Bits> implements BitVecNum<Bits, Name> {
declare readonly __typename: BitVecNum['__typename'];
value() {
return BigInt(this.asString());
}
@ -1718,14 +1830,87 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
}
return val;
}
asString() {
return Z3.get_numeral_string(contextPtr, this.ast);
}
asBinaryString() {
return Z3.get_numeral_binary_string(contextPtr, this.ast);
}
}
class ArraySortImpl<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
RangeSort extends AnySort<Name> = Sort<Name>>
extends SortImpl
implements SMTArraySort<Name, DomainSort, RangeSort> {
declare readonly __typename: SMTArraySort['__typename'];
domain(): DomainSort[0] {
return _toSort(check(Z3.get_array_sort_domain(contextPtr, this.ptr)));
}
domain_n<T extends number>(i: T): DomainSort[T] {
return _toSort(check(Z3.get_array_sort_domain_n(contextPtr, this.ptr, i)));
}
range(): RangeSort {
return _toSort(check(Z3.get_array_sort_range(contextPtr, this.ptr))) as RangeSort;
}
}
class ArrayImpl<
DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
RangeSort extends AnySort<Name> = Sort<Name>
> extends ExprImpl<Z3_ast, ArraySortImpl<DomainSort, RangeSort>>
implements SMTArray<Name, DomainSort, RangeSort> {
declare readonly __typename: SMTArray['__typename'];
domain(): DomainSort[0] {
return this.sort.domain();
}
domain_n<T extends number>(i: T): DomainSort[T] {
return this.sort.domain_n(i);
}
range(): RangeSort {
return this.sort.range();
}
select(...indices: ArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name> {
const args = indices.map((arg, i) => this.domain_n(i).cast(arg as any));
if (args.length === 1) {
return _toExpr(check(Z3.mk_select(contextPtr, this.ast, args[0].ast))) as SortToExprMap<RangeSort, Name>;
}
const _args = args.map(arg => arg.ast);
return _toExpr(check(Z3.mk_select_n(contextPtr, this.ast, _args))) as SortToExprMap<RangeSort, Name>;
}
store(
...indicesAndValue: [
...ArrayIndexType<Name, DomainSort>,
CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>
]
): SMTArray<Name, DomainSort, RangeSort> {
const args = indicesAndValue.map((arg, i) => {
if (i === indicesAndValue.length - 1) {
return this.range().cast(arg as CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>);
}
return this.domain_n(i).cast(arg as any);
});
if (args.length <= 1) {
throw new Z3Error("Array store requires both index and value arguments");
}
if (args.length === 2) {
return _toExpr(check(Z3.mk_store(contextPtr, this.ast, args[0].ast, args[1].ast))) as SMTArray<Name, DomainSort, RangeSort>;
}
const _idxs = args.slice(0, args.length - 1).map(arg => arg.ast);
return _toExpr(check(Z3.mk_store_n(contextPtr, this.ast, _idxs, args[args.length - 1].ast))) as SMTArray<Name, DomainSort, RangeSort>;
}
}
class AstVectorImpl<Item extends AnyAst<Name>> {
declare readonly __typename: AstVector['__typename'];
readonly ctx: Context<Name>;
@ -1744,20 +1929,20 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return this.values();
}
*entries(): IterableIterator<[number, Item]> {
* entries(): IterableIterator<[number, Item]> {
const length = this.length();
for (let i = 0; i < length; i++) {
yield [i, this.get(i)];
}
}
*keys(): IterableIterator<number> {
* keys(): IterableIterator<number> {
for (let [key] of this.entries()) {
yield key;
}
}
*values(): IterableIterator<Item> {
* values(): IterableIterator<Item> {
for (let [, value] of this.entries()) {
yield value;
}
@ -1842,7 +2027,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return Z3.ast_map_size(contextPtr, this.ptr);
}
*entries(): IterableIterator<[Key, Value]> {
* entries(): IterableIterator<[Key, Value]> {
for (const key of this.keys()) {
yield [key, this.get(key)];
}
@ -1852,11 +2037,12 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
return new AstVectorImpl(Z3.ast_map_keys(contextPtr, this.ptr));
}
*values(): IterableIterator<Value> {
* values(): IterableIterator<Value> {
for (const [_, value] of this.entries()) {
yield value;
}
}
get(key: Key): Value {
return _toAst(check(Z3.ast_map_find(contextPtr, this.ptr, key.ast))) as Value;
}
@ -1928,6 +2114,9 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
isBitVecSort,
isBitVec,
isBitVecVal, // TODO fix ordering
isArraySort,
isArray,
isConstArray,
isProbe,
isTactic,
isAstVector,
@ -1946,6 +2135,7 @@ export function createApi(Z3: Z3Core): Z3HighLevel {
Int,
Real,
BitVec,
Array,
////////////////
// Operations //

File diff suppressed because it is too large Load diff

View file

@ -528,7 +528,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module &m)
m.BINARY_OP(tactic, &, &);
m.BINARY_OP(tactic, |, |);
m.method("repeat", &repeat);
m.method("with", &with);
m.method("with", static_cast<tactic (*)(const tactic & , const params &)>(&with));
m.method("try_for", &try_for);
m.method("par_or", &par_or);
m.method("par_and_then", &par_and_then);
@ -692,7 +692,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module &m)
.method("real_val", [](context &a, const jlcxx::StrictlyTypedNumber<unsigned> b) { return a.real_val(b.value); })
.method("real_val", [](context &a, const jlcxx::StrictlyTypedNumber<int64_t> b) { return a.real_val(b.value); })
.method("real_val", [](context &a, const jlcxx::StrictlyTypedNumber<uint64_t> b) { return a.real_val(b.value); })
.method("real_val", static_cast<expr (context::*)(int, int)>(&context::real_val))
.method("real_val", static_cast<expr (context::*)(int64_t, int64_t)>(&context::real_val))
.method("real_val", static_cast<expr (context::*)(char const *)>(&context::real_val))
//
.method("bv_val", [](context &a, const jlcxx::StrictlyTypedNumber<int> b, unsigned c) { return a.bv_val(b.value, c); })

View file

@ -1734,6 +1734,39 @@ struct
let interrupt = Z3native.interrupt
end
module Simplifier =
struct
type simplifier = Z3native.simplifier
let gc = Z3native.context_of_simplifier
let get_help (x:simplifier) = Z3native.simplifier_get_help (gc x) x
let get_param_descrs (x:simplifier) = Z3native.simplifier_get_param_descrs (gc x) x
let get_num_simplifiers = Z3native.get_num_simplifiers
let get_simplifier_names (ctx:context) =
let n = get_num_simplifiers ctx in
let f i = Z3native.get_simplifier_name ctx i in
mk_list f n
let get_simplifier_description = Z3native.simplifier_get_descr
let mk_simplifier = Z3native.mk_simplifier
let and_then (ctx:context) (t1:simplifier) (t2:simplifier) (ts:simplifier list) =
let f p c = (match p with
| None -> Some c
| Some(x) -> Some (Z3native.simplifier_and_then ctx c x)) in
match (List.fold_left f None ts) with
| None -> Z3native.simplifier_and_then ctx t1 t2
| Some(x) -> let o = Z3native.simplifier_and_then ctx t2 x in
Z3native.simplifier_and_then ctx t1 o
let using_params = Z3native.simplifier_using_params
let with_ = using_params
end
module Statistics =
struct
@ -1868,6 +1901,7 @@ struct
let mk_solver_s ctx logic = mk_solver ctx (Some (Symbol.mk_string ctx logic))
let mk_simple_solver = Z3native.mk_simple_solver
let mk_solver_t = Z3native.mk_solver_from_tactic
let add_simplifier = Z3native.solver_add_simplifier
let translate x = Z3native.solver_translate (gc x) x
let to_string x = Z3native.solver_to_string (gc x) x
end

View file

@ -3102,6 +3102,38 @@ sig
val interrupt : context -> unit
end
module Simplifier :
sig
type simplifier
(** A string containing a description of parameters accepted by the simplifier. *)
val get_help : simplifier -> string
(** Retrieves parameter descriptions for Simplifiers. *)
val get_param_descrs : simplifier -> Params.ParamDescrs.param_descrs
(** The number of supported simplifiers. *)
val get_num_simplifiers : context -> int
(** The names of all supported simplifiers. *)
val get_simplifier_names : context -> string list
(** Returns a string containing a description of the simplifier with the given name. *)
val get_simplifier_description : context -> string -> string
(** Creates a new Simplifier. *)
val mk_simplifier : context -> string -> simplifier
(** Create a simplifier that applies one simplifier to a Goal and
then another one to every subgoal produced by the first one. *)
val and_then : context -> simplifier -> simplifier -> simplifier list -> simplifier
(** Create a simplifier that applies a simplifier using the given set of parameters. *)
val using_params : context -> simplifier -> Params.params -> simplifier
val with_ : context -> simplifier -> Params.params -> simplifier
end
(** Objects that track statistical information. *)
module Statistics :
sig
@ -3265,6 +3297,9 @@ sig
will always solve each check from scratch. *)
val mk_solver_t : context -> Tactic.tactic -> solver
(** Create a solver with simplifying pre-processing **)
val add_simplifier : context -> solver -> Simplifier.simplifier -> solver
(** Create a clone of the current solver with respect to a context. *)
val translate : solver -> context -> solver

View file

@ -20,6 +20,7 @@ and solver = ptr
and solver_callback = ptr
and goal = ptr
and tactic = ptr
and simplifier = ptr
and params = ptr
and parser_context = ptr
and probe = ptr

View file

@ -424,6 +424,7 @@ MK_PLUS_OBJ(func_interp, 32)
MK_PLUS_OBJ(func_entry, 32)
MK_PLUS_OBJ(goal, 64)
MK_PLUS_OBJ(tactic, 64)
MK_PLUS_OBJ(simplifier, 64)
MK_PLUS_OBJ(probe, 64)
MK_PLUS_OBJ(apply_result, 32)
MK_PLUS_OBJ(solver, 20 * 1000)

View file

@ -277,7 +277,7 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
# linux builds should be built in the centos 5 vm for maximum compatibility
# see https://github.com/pypa/manylinux
# see also https://github.com/angr/angr-dev/blob/master/admin/bdist.py
plat_name = 'manylinux1_' + platform.machine()
plat_name = 'manylinux2014_' + platform.machine()
elif 'mingw' in name:
if platform.architecture()[0] == '64bit':
plat_name = 'win_amd64'
@ -296,9 +296,9 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
)
elif distos == 'glibc':
if arch == 'x64':
plat_name = 'manylinux1_x86_64'
plat_name = 'manylinux2014_x86_64'
else:
plat_name = 'manylinux1_i686'
plat_name = 'manylinux2014_i686'
elif distos == 'linux' and os_id == 'alpine':
if arch == 'x64':
plat_name = 'musllinux_1_1_x86_64'

View file

@ -763,8 +763,6 @@ class FuncDeclRef(AstRef):
>>> f.domain(1)
Real
"""
if z3_debug():
_z3_assert(i < self.arity(), "Index out of bounds")
return _to_sort_ref(Z3_get_domain(self.ctx_ref(), self.ast, i), self.ctx)
def range(self):
@ -834,8 +832,6 @@ class FuncDeclRef(AstRef):
"""
args = _get_args(args)
num = len(args)
if z3_debug():
_z3_assert(num == self.arity(), "Incorrect number of arguments to %s" % self)
_args = (Ast * num)()
saved = []
for i in range(num):
@ -1194,7 +1190,7 @@ def _coerce_expr_merge(s, a):
else:
if z3_debug():
_z3_assert(s1.ctx == s.ctx, "context mismatch")
_z3_assert(False, "sort mismatch")
_z3_assert(False, "sort mismatch")
else:
return s
@ -1207,6 +1203,11 @@ def _coerce_exprs(a, b, ctx=None):
a = StringVal(a, b.ctx)
if isinstance(b, str) and isinstance(a, SeqRef):
b = StringVal(b, a.ctx)
if isinstance(a, float) and isinstance(b, ArithRef):
a = RealVal(a, b.ctx)
if isinstance(b, float) and isinstance(a, ArithRef):
b = RealVal(b, a.ctx)
s = None
s = _coerce_expr_merge(s, a)
s = _coerce_expr_merge(s, b)
@ -1464,7 +1465,9 @@ def FreshConst(sort, prefix="c"):
def Var(idx, s):
"""Create a Z3 free variable. Free variables are used to create quantified formulas.
A free variable with index n is bound when it occurs within the scope of n+1 quantified
declarations.
>>> Var(0, IntSort())
Var(0)
>>> eq(Var(0, IntSort()), Var(0, BoolSort()))
@ -1552,13 +1555,15 @@ class BoolRef(ExprRef):
def __mul__(self, other):
"""Create the Z3 expression `self * other`.
"""
if other == 1:
return self
if other == 0:
return 0
if isinstance(other, int) and other == 1:
return If(self, 1, 0)
if isinstance(other, int) and other == 0:
return IntVal(0, self.ctx)
if isinstance(other, BoolRef):
other = If(other, 1, 0)
return If(self, other, 0)
def is_bool(a):
"""Return `True` if `a` is a Z3 Boolean expression.
@ -4588,10 +4593,10 @@ class ArrayRef(ExprRef):
def _array_select(ar, arg):
if isinstance(arg, tuple):
args = [ar.domain_n(i).cast(arg[i]) for i in range(len(arg))]
args = [ar.sort().domain_n(i).cast(arg[i]) for i in range(len(arg))]
_args, sz = _to_ast_array(args)
return _to_expr_ref(Z3_mk_select_n(ar.ctx_ref(), ar.as_ast(), sz, _args), ar.ctx)
arg = ar.domain().cast(arg)
arg = ar.sort().domain().cast(arg)
return _to_expr_ref(Z3_mk_select(ar.ctx_ref(), ar.as_ast(), arg.as_ast()), ar.ctx)
@ -6653,7 +6658,7 @@ class ModelRef(Z3PPObject):
n = Z3_func_entry_get_num_args(x.ctx_ref(), e.entry)
v = AstVector()
for j in range(n):
v.push(entry.arg_value(j))
v.push(e.arg_value(j))
val = Z3_func_entry_get_value(x.ctx_ref(), e.entry)
Z3_func_interp_add_entry(x.ctx_ref(), fi2.f, v.vector, val)
return
@ -7232,6 +7237,22 @@ class Solver(Z3PPObject):
cube are likely more useful to cube on."""
return self.cube_vs
def root(self, t):
t = _py2expr(t, self.ctx)
"""Retrieve congruence closure root of the term t relative to the current search state
The function primarily works for SimpleSolver. Terms and variables that are
eliminated during pre-processing are not visible to the congruence closure.
"""
return _to_expr_ref(Z3_solver_congruence_root(self.ctx.ref(), self.solver, t.ast), self.ctx)
def next(self, t):
t = _py2expr(t, self.ctx)
"""Retrieve congruence closure sibling of the term t relative to the current search state
The function primarily works for SimpleSolver. Terms and variables that are
eliminated during pre-processing are not visible to the congruence closure.
"""
return _to_expr_ref(Z3_solver_congruence_next(self.ctx.ref(), self.solver, t.ast), self.ctx)
def proof(self):
"""Return a proof for the last `check()`. Proof construction must be enabled."""
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)
@ -8148,6 +8169,64 @@ class ApplyResult(Z3PPObject):
else:
return Or([self[i].as_expr() for i in range(len(self))])
#########################################
#
# Simplifiers
#
#########################################
class Simplifier:
"""Simplifiers act as pre-processing utilities for solvers.
Build a custom simplifier and add it to a solver"""
def __init__(self, simplifier, ctx=None):
self.ctx = _get_ctx(ctx)
self.simplifier = None
if isinstance(simplifier, SimplifierObj):
self.simplifier = simplifier
elif isinstance(simplifier, list):
simps = [Simplifier(s, ctx) for s in simplifier]
self.simplifier = simps[0].simplifier
for i in range(1, len(simps)):
self.simplifier = Z3_simplifier_and_then(self.ctx.ref(), self.simplifier, simps[i].simplifier)
Z3_simplifier_inc_ref(self.ctx.ref(), self.simplifier)
return
else:
if z3_debug():
_z3_assert(isinstance(simplifier, str), "simplifier name expected")
try:
self.simplifier = Z3_mk_simplifier(self.ctx.ref(), str(simplifier))
except Z3Exception:
raise Z3Exception("unknown simplifier '%s'" % simplifier)
Z3_simplifier_inc_ref(self.ctx.ref(), self.simplifier)
def __deepcopy__(self, memo={}):
return Simplifier(self.simplifier, self.ctx)
def __del__(self):
if self.simplifier is not None and self.ctx.ref() is not None and Z3_simplifier_dec_ref is not None:
Z3_simplifier_dec_ref(self.ctx.ref(), self.simplifier)
def using_params(self, *args, **keys):
"""Return a simplifier that uses the given configuration options"""
p = args2params(args, keys, self.ctx)
return Simplifier(Z3_simplifier_using_params(self.ctx.ref(), self.simplifier, p.params), self.ctx)
def add(self, solver):
"""Return a solver that applies the simplification pre-processing specified by the simplifier"""
print(solver.solver)
print(self.simplifier)
return Solver(Z3_solver_add_simplifier(self.ctx.ref(), solver.solver, self.simplifier), self.ctx)
def help(self):
"""Display a string containing a description of the available options for the `self` simplifier."""
print(Z3_simplifier_get_help(self.ctx.ref(), self.simplifier))
def param_descrs(self):
"""Return the parameter description set."""
return ParamDescrsRef(Z3_simplifier_get_param_descrs(self.ctx.ref(), self.simplifier), self.ctx)
#########################################
#
# Tactics
@ -8832,7 +8911,7 @@ def substitute_vars(t, *m):
return _to_expr_ref(Z3_substitute_vars(t.ctx.ref(), t.as_ast(), num, _to), t.ctx)
def substitute_funs(t, *m):
"""Apply subistitution m on t, m is a list of pairs of a function and expression (from, to)
"""Apply substitution m on t, m is a list of pairs of a function and expression (from, to)
Every occurrence in to of the function from is replaced with the expression to.
The expression to can have free variables, that refer to the arguments of from.
For examples, see
@ -10079,7 +10158,7 @@ def FPs(names, fpsort, ctx=None):
>>> x.ebits()
8
>>> fpMul(RNE(), fpAdd(RNE(), x, y), z)
fpMul(RNE(), fpAdd(RNE(), x, y), z)
x + y * z
"""
ctx = _get_ctx(ctx)
if isinstance(names, str):
@ -10186,9 +10265,9 @@ def fpAdd(rm, a, b, ctx=None):
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpAdd(rm, x, y)
fpAdd(RNE(), x, y)
>>> fpAdd(RTZ(), x, y) # default rounding mode is RTZ
x + y
>>> fpAdd(RTZ(), x, y) # default rounding mode is RTZ
fpAdd(RTZ(), x, y)
>>> fpAdd(rm, x, y).sort()
FPSort(8, 24)
"""
@ -10203,7 +10282,7 @@ def fpSub(rm, a, b, ctx=None):
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpSub(rm, x, y)
fpSub(RNE(), x, y)
x - y
>>> fpSub(rm, x, y).sort()
FPSort(8, 24)
"""
@ -10218,7 +10297,7 @@ def fpMul(rm, a, b, ctx=None):
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpMul(rm, x, y)
fpMul(RNE(), x, y)
x * y
>>> fpMul(rm, x, y).sort()
FPSort(8, 24)
"""
@ -10233,7 +10312,7 @@ def fpDiv(rm, a, b, ctx=None):
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpDiv(rm, x, y)
fpDiv(RNE(), x, y)
x / y
>>> fpDiv(rm, x, y).sort()
FPSort(8, 24)
"""
@ -11301,6 +11380,45 @@ def TransitiveClosure(f):
"""
return FuncDeclRef(Z3_mk_transitive_closure(f.ctx_ref(), f.ast), f.ctx)
def to_Ast(ptr,):
ast = Ast(ptr)
super(ctypes.c_void_p, ast).__init__(ptr)
return ast
def to_ContextObj(ptr,):
ctx = ContextObj(ptr)
super(ctypes.c_void_p, ctx).__init__(ptr)
return ctx
def to_AstVectorObj(ptr,):
v = AstVectorObj(ptr)
super(ctypes.c_void_p, v).__init__(ptr)
return v
# NB. my-hacky-class only works for a single instance of OnClause
# it should be replaced with a proper correlation between OnClause
# and object references that can be passed over the FFI.
# for UserPropagator we use a global dictionary, which isn't great code.
_my_hacky_class = None
def on_clause_eh(ctx, p, clause):
onc = _my_hacky_class
p = _to_expr_ref(to_Ast(p), onc.ctx)
clause = AstVector(to_AstVectorObj(clause), onc.ctx)
onc.on_clause(p, clause)
_on_clause_eh = Z3_on_clause_eh(on_clause_eh)
class OnClause:
def __init__(self, s, on_clause):
self.s = s
self.ctx = s.ctx
self.on_clause = on_clause
self.idx = 22
global _my_hacky_class
_my_hacky_class = self
Z3_solver_register_on_clause(self.ctx.ref(), self.s.solver, self.idx, _on_clause_eh)
class PropClosures:
def __init__(self):
@ -11358,11 +11476,6 @@ def user_prop_pop(ctx, cb, num_scopes):
prop.cb = cb
prop.pop(num_scopes)
def to_ContextObj(ptr,):
ctx = ContextObj(ptr)
super(ctypes.c_void_p, ctx).__init__(ptr)
return ctx
def user_prop_fresh(ctx, _new_ctx):
_prop_closures.set_threaded()
@ -11377,10 +11490,6 @@ def user_prop_fresh(ctx, _new_ctx):
_prop_closures.set(new_prop.id, new_prop)
return new_prop.id
def to_Ast(ptr,):
ast = Ast(ptr)
super(ctypes.c_void_p, ast).__init__(ptr)
return ast
def user_prop_fixed(ctx, cb, id, value):
prop = _prop_closures.get(ctx)
@ -11442,6 +11551,7 @@ _user_prop_eq = Z3_eq_eh(user_prop_eq)
_user_prop_diseq = Z3_eq_eh(user_prop_diseq)
_user_prop_decide = Z3_decide_eh(user_prop_decide)
def PropagateFunction(name, *sig):
"""Create a function that gets tracked by user propagator.
Every term headed by this function symbol is tracked.
@ -11462,7 +11572,8 @@ def PropagateFunction(name, *sig):
dom[i] = sig[i].ast
ctx = rng.ctx
return FuncDeclRef(Z3_solver_propagate_declare(ctx.ref(), to_symbol(name, ctx), arity, dom, rng.ast), ctx)
class UserPropagateBase:

View file

@ -120,6 +120,12 @@ class TacticObj(ctypes.c_void_p):
def from_param(obj):
return obj
class SimplifierObj(ctypes.c_void_p):
def __init__(self, simplifier):
self._as_parameter_ = simplifier
def from_param(obj):
return obj
class ProbeObj(ctypes.c_void_p):
def __init__(self, probe):

View file

@ -23,6 +23,7 @@ DEFINE_TYPE(Z3_param_descrs);
DEFINE_TYPE(Z3_parser_context);
DEFINE_TYPE(Z3_goal);
DEFINE_TYPE(Z3_tactic);
DEFINE_TYPE(Z3_simplifier);
DEFINE_TYPE(Z3_probe);
DEFINE_TYPE(Z3_stats);
DEFINE_TYPE(Z3_solver);
@ -69,6 +70,7 @@ DEFINE_TYPE(Z3_rcf_num);
- \c Z3_ast_map: mapping from \c Z3_ast to \c Z3_ast objects.
- \c Z3_goal: set of formulas that can be solved and/or transformed using tactics and solvers.
- \c Z3_tactic: basic building block for creating custom solvers for specific problem domains.
- \c Z3_simplifier: basic building block for creating custom pre-processing simplifiers.
- \c Z3_probe: function/predicate used to inspect a goal and collect information that may be used to decide which solver and/or preprocessing step will be used.
- \c Z3_apply_result: collection of subgoals resulting from applying of a tactic to a goal.
- \c Z3_solver: (incremental) solver, possibly specialized by a particular tactic or logic.
@ -1403,6 +1405,7 @@ typedef enum
def_Type('PARSER_CONTEXT', 'Z3_parser_context', 'ParserContextObj')
def_Type('GOAL', 'Z3_goal', 'GoalObj')
def_Type('TACTIC', 'Z3_tactic', 'TacticObj')
def_Type('SIMPLIFIER', 'Z3_simplifier', 'SimplifierObj')
def_Type('PARAMS', 'Z3_params', 'Params')
def_Type('PROBE', 'Z3_probe', 'ProbeObj')
def_Type('STATS', 'Z3_stats', 'StatsObj')
@ -1433,6 +1436,7 @@ Z3_DECLARE_CLOSURE(Z3_eq_eh, void, (void* ctx, Z3_solver_callback cb, Z3_as
Z3_DECLARE_CLOSURE(Z3_final_eh, void, (void* ctx, Z3_solver_callback cb));
Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t));
Z3_DECLARE_CLOSURE(Z3_decide_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast* t, unsigned* idx, Z3_lbool* phase));
Z3_DECLARE_CLOSURE(Z3_on_clause_eh, void, (void* ctx, Z3_ast proof_hint, Z3_ast_vector literals));
/**
@ -3416,12 +3420,22 @@ extern "C" {
\sa Z3_mk_numeral
\sa Z3_mk_int
\sa Z3_mk_real_int64
\sa Z3_mk_unsigned_int
def_API('Z3_mk_real', AST, (_in(CONTEXT), _in(INT), _in(INT)))
*/
Z3_ast Z3_API Z3_mk_real(Z3_context c, int num, int den);
/**
\brief Create a real from a fraction of int64.
\sa Z3_mk_real
def_API('Z3_mk_real_int64', AST, (_in(CONTEXT), _in(INT64), _in(INT64)))
*/
Z3_ast Z3_API Z3_mk_real_int64(Z3_context c, int64_t num, int64_t den);
/**
\brief Create a numeral of an int, bit-vector, or finite-domain sort.
@ -3762,7 +3776,7 @@ extern "C" {
If \c s does not contain \c substr, then the value is -1,
def_API('Z3_mk_seq_last_index', AST, (_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_mk_seq_last_index(Z3_context c, Z3_ast, Z3_ast substr);
Z3_ast Z3_API Z3_mk_seq_last_index(Z3_context c, Z3_ast s, Z3_ast substr);
/**
\brief Convert string to integer.
@ -3892,7 +3906,7 @@ extern "C" {
def_API('Z3_mk_re_power', AST, (_in(CONTEXT), _in(AST), _in(UINT)))
*/
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast, unsigned n);
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast re, unsigned n);
/**
\brief Create the intersection of the regular languages.
@ -4050,7 +4064,10 @@ extern "C" {
Z3_pattern Z3_API Z3_mk_pattern(Z3_context c, unsigned num_patterns, Z3_ast const terms[]);
/**
\brief Create a bound variable.
\brief Create a variable.
Variables are intended to be bound by a scope created by a quantifier. So we call them bound variables
even if they appear as free variables in the expression produced by \c Z3_mk_bound.
Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain
the meaning of de-Bruijn indices by indicating the compilation process from
@ -5317,8 +5334,9 @@ extern "C" {
Z3_ast const to[]);
/**
\brief Substitute the free variables in \c a with the expressions in \c to.
\brief Substitute the variables in \c a with the expressions in \c to.
For every \c i smaller than \c num_exprs, the variable with de-Bruijn index \c i is replaced with term \ccode{to[i]}.
Note that a variable is created using the function \ref Z3_mk_bound.
def_API('Z3_substitute_vars', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
*/
@ -5876,7 +5894,7 @@ extern "C" {
def_API('Z3_eval_smtlib2_string', STRING, (_in(CONTEXT), _in(STRING),))
*/
Z3_string Z3_API Z3_eval_smtlib2_string(Z3_context, Z3_string str);
Z3_string Z3_API Z3_eval_smtlib2_string(Z3_context c, Z3_string str);
/**
@ -6192,7 +6210,7 @@ extern "C" {
/**@}*/
/** @name Tactics and Probes */
/** @name Tactics, Simplifiers and Probes */
/**@{*/
/**
\brief Return a tactic associated with the given name.
@ -6344,6 +6362,97 @@ extern "C" {
*/
Z3_tactic Z3_API Z3_tactic_using_params(Z3_context c, Z3_tactic t, Z3_params p);
/**
\brief Return a simplifier associated with the given name.
The complete list of simplifiers may be obtained using the procedures #Z3_get_num_simplifiers and #Z3_get_simplifier_name.
It may also be obtained using the command \ccode{(help-simplifier)} in the SMT 2.0 front-end.
Simplifiers are the basic building block for creating custom solvers for specific problem domains.
def_API('Z3_mk_simplifier', SIMPLIFIER, (_in(CONTEXT), _in(STRING)))
*/
Z3_simplifier Z3_API Z3_mk_simplifier(Z3_context c, Z3_string name);
/**
\brief Increment the reference counter of the given simplifier.
def_API('Z3_simplifier_inc_ref', VOID, (_in(CONTEXT), _in(SIMPLIFIER)))
*/
void Z3_API Z3_simplifier_inc_ref(Z3_context c, Z3_simplifier t);
/**
\brief Decrement the reference counter of the given simplifier.
def_API('Z3_simplifier_dec_ref', VOID, (_in(CONTEXT), _in(SIMPLIFIER)))
*/
void Z3_API Z3_simplifier_dec_ref(Z3_context c, Z3_simplifier g);
/**
\brief Attach simplifier to a solver. The solver will use the simplifier for incremental pre-processing.
def_API('Z3_solver_add_simplifier', SOLVER, (_in(CONTEXT), _in(SOLVER), _in(SIMPLIFIER)))
*/
Z3_solver Z3_API Z3_solver_add_simplifier(Z3_context c, Z3_solver solver, Z3_simplifier simplifier);
/**
\brief Return a simplifier that applies \c t1 to a given goal and \c t2
to every subgoal produced by \c t1.
def_API('Z3_simplifier_and_then', SIMPLIFIER, (_in(CONTEXT), _in(SIMPLIFIER), _in(SIMPLIFIER)))
*/
Z3_simplifier Z3_API Z3_simplifier_and_then(Z3_context c, Z3_simplifier t1, Z3_simplifier t2);
/**
\brief Return a simplifier that applies \c t using the given set of parameters.
def_API('Z3_simplifier_using_params', SIMPLIFIER, (_in(CONTEXT), _in(SIMPLIFIER), _in(PARAMS)))
*/
Z3_simplifier Z3_API Z3_simplifier_using_params(Z3_context c, Z3_simplifier t, Z3_params p);
/**
\brief Return the number of builtin simplifiers available in Z3.
\sa Z3_get_simplifier_name
def_API('Z3_get_num_simplifiers', UINT, (_in(CONTEXT),))
*/
unsigned Z3_API Z3_get_num_simplifiers(Z3_context c);
/**
\brief Return the name of the idx simplifier.
\pre i < Z3_get_num_simplifiers(c)
\sa Z3_get_num_simplifiers
def_API('Z3_get_simplifier_name', STRING, (_in(CONTEXT), _in(UINT)))
*/
Z3_string Z3_API Z3_get_simplifier_name(Z3_context c, unsigned i);
/**
\brief Return a string containing a description of parameters accepted by the given simplifier.
def_API('Z3_simplifier_get_help', STRING, (_in(CONTEXT), _in(SIMPLIFIER)))
*/
Z3_string Z3_API Z3_simplifier_get_help(Z3_context c, Z3_simplifier t);
/**
\brief Return the parameter description set for the given simplifier object.
def_API('Z3_simplifier_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(SIMPLIFIER)))
*/
Z3_param_descrs Z3_API Z3_simplifier_get_param_descrs(Z3_context c, Z3_simplifier t);
/**
\brief Return a string containing a description of the simplifier with the given name.
def_API('Z3_simplifier_get_descr', STRING, (_in(CONTEXT), _in(STRING)))
*/
Z3_string Z3_API Z3_simplifier_get_descr(Z3_context c, Z3_string name);
/**
\brief Return a probe that always evaluates to val.
@ -6877,6 +6986,44 @@ extern "C" {
*/
void Z3_API Z3_solver_get_levels(Z3_context c, Z3_solver s, Z3_ast_vector literals, unsigned sz, unsigned levels[]);
/**
\brief retrieve the congruence closure root of an expression.
The root is retrieved relative to the state where the solver was in when it completed.
If it completed during a set of case splits, the congruence roots are relative to these case splits.
That is, the congruences are not consequences but they are true under the current state.
def_API('Z3_solver_congruence_root', AST, (_in(CONTEXT), _in(SOLVER), _in(AST)))
*/
Z3_ast Z3_API Z3_solver_congruence_root(Z3_context c, Z3_solver s, Z3_ast a);
/**
\brief retrieve the next expression in the congruence class. The set of congruent siblings form a cyclic list.
Repeated calls on the siblings will result in returning to the original expression.
def_API('Z3_solver_congruence_next', AST, (_in(CONTEXT), _in(SOLVER), _in(AST)))
*/
Z3_ast Z3_API Z3_solver_congruence_next(Z3_context c, Z3_solver s, Z3_ast a);
/**
\brief register a callback to that retrieves assumed, inferred and deleted clauses during search.
\param c - context.
\param s - solver object.
\param user_context - a context used to maintain state for callbacks.
\param on_clause_eh - a callback that is invoked by when a clause is
- asserted to the CDCL engine (corresponding to an input clause after pre-processing)
- inferred by CDCL(T) using either a SAT or theory conflict/propagation
- deleted by the CDCL(T) engine
def_API('Z3_solver_register_on_clause', VOID, (_in(CONTEXT), _in(SOLVER), _in(VOID_PTR), _fnptr(Z3_on_clause_eh)))
*/
void Z3_API Z3_solver_register_on_clause(
Z3_context c,
Z3_solver s,
void* user_context,
Z3_on_clause_eh on_clause_eh);
/**
\brief register a user-properator with the solver.
@ -7006,7 +7153,7 @@ extern "C" {
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, AST), _in(UINT), _in_array(4, AST), _in_array(4, AST), _in(AST)))
*/
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
/**
\brief Check whether the assertions in a given solver are consistent or not.

View file

@ -447,12 +447,17 @@ public:
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(arith_family_id, OP_ADD, arg1, arg2, arg3); }
app * mk_add(expr_ref_vector const& args) const { return mk_add(args.size(), args.data()); }
app * mk_add(expr_ref_buffer const& args) const { return mk_add(args.size(), args.data()); }
app * mk_add(ptr_buffer<expr> const& args) const { return mk_add(args.size(), args.data()); }
app * mk_add(ptr_vector<expr> const& args) const { return mk_add(args.size(), args.data()); }
app * mk_sub(expr * arg1, expr * arg2) const { return m_manager.mk_app(arith_family_id, OP_SUB, arg1, arg2); }
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(arith_family_id, OP_SUB, num_args, args); }
app * mk_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(arith_family_id, OP_MUL, arg1, arg2); }
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(arith_family_id, OP_MUL, arg1, arg2, arg3); }
app * mk_mul(unsigned num_args, expr * const * args) const { return num_args == 1 && is_app(args[0]) ? to_app(args[0]) : m_manager.mk_app(arith_family_id, OP_MUL, num_args, args); }
app * mk_mul(ptr_buffer<expr> const& args) const { return mk_mul(args.size(), args.data()); }
app * mk_mul(ptr_vector<expr> const& args) const { return mk_mul(args.size(), args.data()); }
app * mk_mul(expr_ref_vector const& args) const { return mk_mul(args.size(), args.data()); }
app * mk_uminus(expr * arg) const { return m_manager.mk_app(arith_family_id, OP_UMINUS, arg); }
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_DIV, arg1, arg2); }
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_IDIV, arg1, arg2); }

View file

@ -529,19 +529,6 @@ func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
return nullptr;
}
return mk_array_ext(arity, domain, parameters[0].get_int());
case OP_ARRAY_MAXDIFF:
case OP_ARRAY_MINDIFF: {
if (num_parameters != 0)
m_manager->raise_exception("min/maxdiff don't take any parameters");
if (arity != 2 || domain[0] != domain[1] || !is_array_sort(domain[0]) || 1 != get_array_arity(domain[0]))
m_manager->raise_exception("min/maxdiff don't take two arrays of same sort and with integer index");
sort* idx = get_array_domain(domain[0], 0);
arith_util arith(*m_manager);
if (!arith.is_int(idx))
m_manager->raise_exception("min/maxdiff take integer index domain");
return m_manager->mk_func_decl(k == OP_ARRAY_MAXDIFF ? symbol("maxdiff") : symbol("mindiff"),
arity, domain, arith.mk_int(), func_decl_info(m_family_id, k));
}
case OP_ARRAY_DEFAULT:
return mk_default(arity, domain);
case OP_SET_UNION:
@ -603,9 +590,6 @@ void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
op_names.push_back(builtin_name("as-array", OP_AS_ARRAY));
op_names.push_back(builtin_name("array-ext", OP_ARRAY_EXT));
op_names.push_back(builtin_name("mindiff", OP_ARRAY_MINDIFF));
op_names.push_back(builtin_name("maxdiff", OP_ARRAY_MAXDIFF));
#if 0
op_names.push_back(builtin_name("set-has-size", OP_SET_HAS_SIZE));
op_names.push_back(builtin_name("card", OP_SET_CARD));

View file

@ -45,8 +45,6 @@ enum array_op_kind {
OP_ARRAY_EXT,
OP_ARRAY_DEFAULT,
OP_ARRAY_MAP,
OP_ARRAY_MAXDIFF,
OP_ARRAY_MINDIFF,
OP_SET_UNION,
OP_SET_INTERSECT,
OP_SET_DIFFERENCE,
@ -161,8 +159,6 @@ public:
bool is_complement(expr* n) const { return is_app_of(n, m_fid, OP_SET_COMPLEMENT); }
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
bool is_maxdiff(expr const* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAXDIFF); }
bool is_mindiff(expr const* n) const { return is_app_of(n, m_fid, OP_ARRAY_MINDIFF); }
bool is_set_has_size(expr* e) const { return is_app_of(e, m_fid, OP_SET_HAS_SIZE); }
bool is_set_card(expr* e) const { return is_app_of(e, m_fid, OP_SET_CARD); }
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
@ -189,8 +185,6 @@ public:
bool is_store_ext(expr* e, expr_ref& a, expr_ref_vector& args, expr_ref& value);
MATCH_BINARY(is_subset);
MATCH_BINARY(is_maxdiff);
MATCH_BINARY(is_mindiff);
};
class array_util : public array_recognizers {
@ -213,6 +207,10 @@ public:
return mk_store(args.size(), args.data());
}
app* mk_store(ptr_buffer<expr> const& args) const {
return mk_store(args.size(), args.data());
}
app * mk_select(unsigned num_args, expr * const * args) const {
return m_manager.mk_app(m_fid, OP_SELECT, 0, nullptr, num_args, args);
}

View file

@ -856,11 +856,11 @@ func_decl * basic_decl_plugin::mk_proof_decl(basic_op_kind k, unsigned num_paren
case PR_MODUS_PONENS_OEQ: return mk_proof_decl("mp~", k, 2, m_mp_oeq_decl);
case PR_TH_LEMMA: return mk_proof_decl("th-lemma", k, num_parents, m_th_lemma_decls);
case PR_HYPER_RESOLVE: return mk_proof_decl("hyper-res", k, num_parents, m_hyper_res_decl0);
case PR_ASSUMPTION_ADD: return mk_proof_decl("add-assume", k, num_parents, m_assumption_add_decl);
case PR_LEMMA_ADD: return mk_proof_decl("add-lemma", k, num_parents, m_lemma_add_decl);
case PR_TH_ASSUMPTION_ADD: return mk_proof_decl("add-th-assume", k, num_parents, m_th_assumption_add_decl);
case PR_TH_LEMMA_ADD: return mk_proof_decl("add-th-lemma", k, num_parents, m_th_lemma_add_decl);
case PR_REDUNDANT_DEL: return mk_proof_decl("del-redundant", k, num_parents, m_redundant_del_decl);
case PR_ASSUMPTION_ADD: return mk_proof_decl("assume", k, num_parents, m_assumption_add_decl);
case PR_LEMMA_ADD: return mk_proof_decl("infer", k, num_parents, m_lemma_add_decl);
case PR_TH_ASSUMPTION_ADD: return mk_proof_decl("th-assume", k, num_parents, m_th_assumption_add_decl);
case PR_TH_LEMMA_ADD: return mk_proof_decl("th-lemma", k, num_parents, m_th_lemma_add_decl);
case PR_REDUNDANT_DEL: return mk_proof_decl("del", k, num_parents, m_redundant_del_decl);
case PR_CLAUSE_TRAIL: return mk_proof_decl("proof-trail", k, num_parents, false);
default:
UNREACHABLE();
@ -1673,6 +1673,7 @@ bool ast_manager::are_distinct(expr* a, expr* b) const {
}
void ast_manager::add_lambda_def(func_decl* f, quantifier* q) {
TRACE("model", tout << "add lambda def " << mk_pp(q, *this) << "\n");
m_lambda_defs.insert(f, q);
f->get_info()->set_lambda(true);
inc_ref(q);
@ -1969,6 +1970,14 @@ app * ast_manager::mk_app(family_id fid, decl_kind k, expr * arg1, expr * arg2,
return mk_app(fid, k, 0, nullptr, 3, args);
}
app * ast_manager::mk_app(symbol const& name, unsigned n, expr* const* args, sort* range) {
ptr_buffer<sort> sorts;
for (unsigned i = 0; i < n; ++i)
sorts.push_back(args[i]->get_sort());
return mk_app(mk_func_decl(name, n, sorts.data(), range), n, args);
}
sort * ast_manager::mk_sort(symbol const & name, sort_info * info) {
unsigned sz = sort::get_obj_size();
void * mem = allocate_node(sz);
@ -2242,7 +2251,9 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
if (type_error) {
std::ostringstream buffer;
buffer << "Wrong number of arguments (" << num_args
<< ") passed to function " << mk_pp(decl, *this);
<< ") passed to function " << mk_pp(decl, *this) << " ";
for (unsigned i = 0; i < num_args; ++i)
buffer << "\narg: " << mk_pp(args[i], *this) << "\n";
throw ast_exception(std::move(buffer).str());
}
app * r = nullptr;

View file

@ -731,6 +731,8 @@ public:
unsigned get_num_args() const { return m_num_args; }
expr * get_arg(unsigned idx) const { SASSERT(idx < m_num_args); return m_args[idx]; }
expr * const * get_args() const { return m_args; }
std::tuple<expr*,expr*> args2() const { SASSERT(m_num_args == 2); return {get_arg(0), get_arg(1)}; }
std::tuple<expr*,expr*,expr*> args3() const { SASSERT(m_num_args == 3); return {get_arg(0), get_arg(1), get_arg(2)}; }
unsigned get_size() const { return get_obj_size(get_num_args()); }
expr * const * begin() const { return m_args; }
expr * const * end() const { return m_args + m_num_args; }
@ -1385,6 +1387,7 @@ inline bool is_app_of(expr const * n, family_id fid, decl_kind k) { return n->ge
inline bool is_sort_of(sort const * s, family_id fid, decl_kind k) { return s->is_sort_of(fid, k); }
inline bool is_uninterp_const(expr const * n) { return n->get_kind() == AST_APP && to_app(n)->get_num_args() == 0 && to_app(n)->get_family_id() == null_family_id; }
inline bool is_uninterp(expr const * n) { return n->get_kind() == AST_APP && to_app(n)->get_family_id() == null_family_id; }
inline bool is_uninterp(func_decl const * n) { return n->get_family_id() == null_family_id; }
inline bool is_decl_of(func_decl const * d, family_id fid, decl_kind k) { return d->get_family_id() == fid && d->get_decl_kind() == k; }
inline bool is_ground(expr const * n) { return is_app(n) && to_app(n)->is_ground(); }
inline bool is_non_ground(expr const * n) { return ( ! is_ground(n)); }
@ -1628,6 +1631,7 @@ public:
void add_lambda_def(func_decl* f, quantifier* q);
quantifier* is_lambda_def(func_decl* f);
quantifier* is_lambda_def(app* e) { return is_lambda_def(e->get_decl()); }
obj_map<func_decl, quantifier*> const& lambda_defs() const { return m_lambda_defs; }
symbol const& lambda_def_qid() const { return m_lambda_def; }
@ -1881,6 +1885,8 @@ public:
return mk_app(decl, 3, args);
}
app * mk_app(symbol const& name, unsigned n, expr* const* args, sort* range);
app * mk_const(func_decl * decl) {
SASSERT(decl->get_arity() == 0);
return mk_app(decl, static_cast<unsigned>(0), static_cast<expr**>(nullptr));

View file

@ -86,6 +86,7 @@ class ll_printer {
default:
display_child_ref(n);
}
}
template<typename T>

View file

@ -64,6 +64,17 @@ void ast_pp_util::display_decls(std::ostream& out) {
m_rec_decls = n;
}
void ast_pp_util::reset() {
coll.reset();
m_removed.reset();
m_sorts.clear(0u);
m_decls.clear(0u);
m_rec_decls.clear(0u);
m_is_defined.reset();
m_defined.reset();
m_defined_lim.reset();
}
void ast_pp_util::display_skolem_decls(std::ostream& out) {
ast_smt_pp pp(m);
unsigned n = coll.get_num_decls();

View file

@ -40,8 +40,7 @@ class ast_pp_util {
ast_pp_util(ast_manager& m): m(m), m_env(m), m_rec_decls(0), m_decls(0), m_sorts(0), m_defined(m), coll(m) {}
void reset() { coll.reset(); m_removed.reset(); m_sorts.clear(0u); m_decls.clear(0u); m_rec_decls.clear(0u);
m_is_defined.reset(); m_defined.reset(); m_defined_lim.reset(); }
void reset();
void collect(expr* e);

View file

@ -561,15 +561,18 @@ class smt2_printer {
void pp_var(var * v) {
format * f;
if (v->get_idx() < m_var_names.size()) {
symbol s = m_var_names[m_var_names.size() - v->get_idx() - 1];
unsigned idx = v->get_idx();
if (idx < m_var_names.size()) {
symbol s;
if (m_reverse && idx < m_arity)
s = m_var_names[m_var_names.size() - m_arity + idx];
else
s = m_var_names[m_var_names.size() - idx - 1];
std::string vname;
if (is_smt2_quoted_symbol (s)) {
vname = mk_smt2_quoted_symbol (s);
}
else {
vname = s.str();
}
if (is_smt2_quoted_symbol (s))
vname = mk_smt2_quoted_symbol (s);
else
vname = s.str();
f = mk_string(m(), vname);
}
else {
@ -1139,9 +1142,13 @@ public:
r = mk_seq1<format**, f2f>(m(), args, args+3, f2f(), cmd);
}
bool m_reverse = false;
unsigned m_arity = 0;
void operator()(func_decl * f, expr * e, format_ref & r, char const* cmd) {
void operator()(func_decl * f, expr * e, format_ref & r, char const* cmd, bool reverse) {
unsigned len;
flet<bool> _reverse(m_reverse, reverse);
m_arity = f->get_arity();
format * fname = m_env.pp_fdecl_name(f, len);
register_var_names(f->get_arity());
format * args[4];
@ -1202,9 +1209,9 @@ void mk_smt2_format(func_decl * f, smt2_pp_environment & env, params_ref const &
pr(f, r, cmd);
}
void mk_smt2_format(func_decl * f, expr * e, smt2_pp_environment & env, params_ref const & p, format_ref & r, char const* cmd) {
void mk_smt2_format(func_decl * f, expr * e, smt2_pp_environment & env, params_ref const & p, format_ref & r, char const* cmd, bool reverse) {
smt2_printer pr(env, p);
pr(f, e, r, cmd);
pr(f, e, r, cmd, reverse);
}
void mk_smt2_format(unsigned sz, expr * const* es, smt2_pp_environment & env, params_ref const & p,
@ -1251,7 +1258,6 @@ std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, smt2_pp_environmen
if (!f) return out << "null";
ast_manager & m = env.get_manager();
format_ref r(fm(m));
sbuffer<symbol> var_names;
mk_smt2_format(f, env, p, r, cmd);
if (indent > 0)
r = mk_indent(m, indent, r.get());
@ -1259,18 +1265,25 @@ std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, smt2_pp_environmen
return out;
}
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p, unsigned indent, char const* cmd) {
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p, unsigned indent, char const* cmd, bool reverse) {
if (!f) return out << "null";
ast_manager & m = env.get_manager();
format_ref r(fm(m));
sbuffer<symbol> var_names;
mk_smt2_format(f, e, env, p, r, cmd);
mk_smt2_format(f, e, env, p, r, cmd, reverse);
if (indent > 0)
r = mk_indent(m, indent, r.get());
pp(out, r.get(), m, p);
return out;
}
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p, unsigned indent, char const* cmd) {
return ast_smt2_pp(out, f, e, env, p, indent, cmd, false);
}
std::ostream & ast_smt2_pp_rev(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p, unsigned indent, char const* cmd) {
return ast_smt2_pp(out, f, e, env, p, indent, cmd, true);
}
std::ostream & ast_smt2_pp(std::ostream & out, unsigned sz, expr * const* es, smt2_pp_environment & env, params_ref const & p, unsigned indent,
unsigned num_vars, char const * var_prefix) {

View file

@ -104,7 +104,8 @@ std::ostream & ast_smt2_pp(std::ostream & out, expr * n, smt2_pp_environment & e
unsigned num_vars = 0, char const * var_prefix = nullptr);
std::ostream & ast_smt2_pp(std::ostream & out, sort * s, smt2_pp_environment & env, params_ref const & p = params_ref(), unsigned indent = 0);
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, smt2_pp_environment & env, params_ref const & p = params_ref(), unsigned indent = 0, char const* cmd = "declare-fun");
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p = params_ref(), unsigned indent = 0, char const* cmd = "define-fun");
std::ostream & ast_smt2_pp(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p = params_ref(), unsigned indent = 0, char const* cmd = "define-fun", bool reverse = false);
std::ostream & ast_smt2_pp_rev(std::ostream & out, func_decl * f, expr* e, smt2_pp_environment & env, params_ref const & p = params_ref(), unsigned indent = 0, char const* cmd = "define-fun");
std::ostream & ast_smt2_pp(std::ostream & out, symbol const& s, bool is_skolem, smt2_pp_environment & env, params_ref const& p = params_ref());
std::ostream & ast_smt2_pp_recdefs(std::ostream & out, vector<std::pair<func_decl*, expr*>> const& funs, smt2_pp_environment & env, params_ref const & p = params_ref());

View file

@ -101,6 +101,8 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
*/
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
app * mk_and(ast_manager & m, unsigned num_args, app * const * args);
inline expr * mk_and(ast_manager & m, ptr_vector<expr> const& args) { return mk_and(m, args.size(), args.data()); }
inline expr * mk_and(ast_manager & m, ptr_buffer<expr> const& args) { return mk_and(m, args.size(), args.data()); }
inline expr * mk_and(ast_manager & m, expr* a, expr* b) { expr* args[2] = { a, b }; return mk_and(m, 2, args); }
inline app_ref mk_and(app_ref_vector const& args) { return app_ref(mk_and(args.get_manager(), args.size(), args.data()), args.get_manager()); }
inline expr_ref mk_and(expr_ref_vector const& args) { return expr_ref(mk_and(args.get_manager(), args.size(), args.data()), args.get_manager()); }

Some files were not shown because too many files have changed in this diff Show more