mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge branch 'master' into polysat
This commit is contained in:
		
						commit
						f54f33551e
					
				
					 308 changed files with 6606 additions and 18485 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -9,9 +9,12 @@ callgrind.out.*
 | 
			
		|||
.z3-trace
 | 
			
		||||
# OCaml generated files
 | 
			
		||||
*.a
 | 
			
		||||
*.o
 | 
			
		||||
*.cma
 | 
			
		||||
*.cmo
 | 
			
		||||
*.cmi
 | 
			
		||||
*.cmx
 | 
			
		||||
*.byte
 | 
			
		||||
*.cmxa
 | 
			
		||||
ocamlz3
 | 
			
		||||
# Java generated files
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +25,7 @@ ocamlz3
 | 
			
		|||
# Directories with generated code and documentation
 | 
			
		||||
release/*
 | 
			
		||||
build/*
 | 
			
		||||
trace/*
 | 
			
		||||
build-dist/*
 | 
			
		||||
dist/*
 | 
			
		||||
src/out/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.12.2.0 LANGUAGES CXX C)
 | 
			
		||||
project(Z3 VERSION 4.12.3.0 LANGUAGES CXX C)
 | 
			
		||||
 | 
			
		||||
################################################################################
 | 
			
		||||
# Project version
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,6 +90,37 @@ CFLAGS="-m32" CXXFLAGS="-m32" CC=gcc CXX=g++ cmake ../
 | 
			
		|||
Note like with the ``CC`` and ``CXX`` flags this must be done on the very first invocation
 | 
			
		||||
to CMake in the build directory.
 | 
			
		||||
 | 
			
		||||
### Adding Z3 as a dependency to a CMAKE Project
 | 
			
		||||
 | 
			
		||||
CMake's [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) allows
 | 
			
		||||
the fetching and populating of an external project. This is useful when a certain version
 | 
			
		||||
of z3 is required that may not match with the system version. With the following code in the 
 | 
			
		||||
cmake file of your project, z3 version 4.12.1 is downloaded to the build directory and the
 | 
			
		||||
cmake targets are added to the project:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
FetchContent_Declare(z3
 | 
			
		||||
        GIT_REPOSITORY https://github.com/Z3Prover/z3
 | 
			
		||||
        GIT_TAG        z3-4.12.1
 | 
			
		||||
)
 | 
			
		||||
FetchContent_MakeAvailable(z3)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The header files can be added to the included directories as follows:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
include_directories( ${z3_SOURCE_DIR}/src/api )
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Finally, the z3 library can be linked to a `yourTarget` using
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
target_link_libraries(yourTarget libz3)
 | 
			
		||||
```
 | 
			
		||||
Note that this is `libz3` not `z3` (`libz3` refers to the library target from `src/CMakeLists.txt`).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Ninja
 | 
			
		||||
 | 
			
		||||
[Ninja](https://ninja-build.org/) is a simple build system that is built for speed.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,9 @@ 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.3
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Version 4.12.2
 | 
			
		||||
==============
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +30,10 @@ Version 4.12.2
 | 
			
		|||
  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.
 | 
			
		||||
- Optimize added to JS API, thanks to gbagan
 | 
			
		||||
- SMTLIB2 proposal for bit-vector overflow predicates added, thanks to aehyvari 
 | 
			
		||||
- bug fixes, thanks to Clemens Eisenhofer, hgvk94, Lev Nachmanson, and others
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Version 4.12.1
 | 
			
		||||
==============
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ def help(ous):
 | 
			
		|||
    out = subprocess.Popen([z3_exe, "-pm"],stdout=subprocess.PIPE).communicate()[0]
 | 
			
		||||
    modules = ["global"]
 | 
			
		||||
    if out != None:
 | 
			
		||||
        out = out.decode(sys.stdout.encoding)
 | 
			
		||||
        out = out.decode(sys.getdefaultencoding())
 | 
			
		||||
        module_re = re.compile(r"\[module\] (.*)\,")
 | 
			
		||||
        lines = out.split("\n")
 | 
			
		||||
        for line in lines:
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ def help(ous):
 | 
			
		|||
            out = subprocess.Popen([z3_exe, "-pmmd:%s" % module],stdout=subprocess.PIPE).communicate()[0]
 | 
			
		||||
            if out == None:
 | 
			
		||||
                continue
 | 
			
		||||
            out = out.decode(sys.stdout.encoding)
 | 
			
		||||
            out = out.decode(sys.getdefaultencoding())
 | 
			
		||||
            out = out.replace("\r","")
 | 
			
		||||
            ous.write(out)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ def extract_params(ous, tac):
 | 
			
		|||
    out = subprocess.Popen([z3_exe, f"-tacticsmd:{tac}"], stdout=subprocess.PIPE).communicate()[0]
 | 
			
		||||
    if not out:
 | 
			
		||||
        return
 | 
			
		||||
    out = out.decode(sys.stdout.encoding)
 | 
			
		||||
    out = out.decode(sys.getdefaultencoding())
 | 
			
		||||
    if is_ws(out):
 | 
			
		||||
        return
 | 
			
		||||
    ous.write("### Parameters\n\n")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2259,6 +2259,24 @@ class JavaExample
 | 
			
		|||
        System.out.println(e1.equals(e3));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void stringExample() {
 | 
			
		||||
	System.out.println("String example");
 | 
			
		||||
	Context ctx = new Context();
 | 
			
		||||
	Expr a = ctx.mkToRe(ctx.mkString("abcd"));
 | 
			
		||||
	Expr b = ctx.mkFullRe(ctx.mkReSort(ctx.mkStringSort()));
 | 
			
		||||
	System.out.println(a);
 | 
			
		||||
	System.out.println(b);
 | 
			
		||||
	System.out.println(a.getSort());
 | 
			
		||||
	System.out.println(b.getSort());
 | 
			
		||||
	Expr c = ctx.mkConcat(ctx.mkToRe(ctx.mkString("abc")),
 | 
			
		||||
			     ctx.mkFullRe(ctx.mkReSort(ctx.mkStringSort())),
 | 
			
		||||
			     ctx.mkEmptyRe(ctx.mkReSort(ctx.mkStringSort())),
 | 
			
		||||
			     ctx.mkAllcharRe(ctx.mkReSort(ctx.mkStringSort())),
 | 
			
		||||
			     ctx.mkToRe(ctx.mkString("d")));
 | 
			
		||||
	System.out.println(c);
 | 
			
		||||
	
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
    public static void main(String[] args)
 | 
			
		||||
    {
 | 
			
		||||
        JavaExample p = new JavaExample();
 | 
			
		||||
| 
						 | 
				
			
			@ -2274,12 +2292,15 @@ class JavaExample
 | 
			
		|||
            System.out.print("Z3 Full Version String: ");
 | 
			
		||||
            System.out.println(Version.getFullVersion());
 | 
			
		||||
 | 
			
		||||
	    p.stringExample();
 | 
			
		||||
 | 
			
		||||
            p.simpleExample();
 | 
			
		||||
 | 
			
		||||
            { // These examples need model generation turned on.
 | 
			
		||||
                HashMap<String, String> cfg = new HashMap<String, String>();
 | 
			
		||||
                cfg.put("model", "true");
 | 
			
		||||
                Context ctx = new Context(cfg);
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
                p.optimizeExample(ctx);
 | 
			
		||||
                p.basicTests(ctx);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,8 +24,8 @@ def mk_dir(d):
 | 
			
		|||
os_info = {  'ubuntu-latest' : ('so', 'linux-x64'),
 | 
			
		||||
             'ubuntu-18' : ('so', 'linux-x64'),
 | 
			
		||||
             'ubuntu-20' : ('so', 'linux-x64'),
 | 
			
		||||
             'glibc-2.31' : ('so', 'linux-x64'),
 | 
			
		||||
             'glibc' : ('so', 'linux-x64'),
 | 
			
		||||
             #'glibc-2.35' : ('so', 'linux-x64'),
 | 
			
		||||
             'x64-win' : ('dll', 'win-x64'),
 | 
			
		||||
             'x86-win' : ('dll', 'win-x86'),
 | 
			
		||||
             'x64-osx' : ('dylib', 'osx-x64'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
from mk_util import *
 | 
			
		||||
 | 
			
		||||
def init_version():
 | 
			
		||||
    set_version(4, 12, 2, 0) # express a default build version or pick up ci build version
 | 
			
		||||
    set_version(4, 12, 3, 0) # express a default build version or pick up ci build version
 | 
			
		||||
    
 | 
			
		||||
# Z3 Project definition
 | 
			
		||||
def init_project_def():
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,7 +122,7 @@ FPMATH_ENABLED=getenv("FPMATH_ENABLED", "True")
 | 
			
		|||
def check_output(cmd):
 | 
			
		||||
    out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
 | 
			
		||||
    if out != None:
 | 
			
		||||
        enc = sys.stdout.encoding
 | 
			
		||||
        enc = sys.getdefaultencoding()
 | 
			
		||||
        if enc != None: return out.decode(enc).rstrip('\r\n')
 | 
			
		||||
        else: return out.rstrip('\r\n')
 | 
			
		||||
    else:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
variables:
 | 
			
		||||
  Major: '4'
 | 
			
		||||
  Minor: '12'
 | 
			
		||||
  Patch: '2'
 | 
			
		||||
  Patch: '3'
 | 
			
		||||
  AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId)
 | 
			
		||||
  NightlyVersion: $(AssemblyVersion)-$(Build.DefinitionName)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +35,20 @@ stages:
 | 
			
		|||
        artifactName: 'MacArm64'
 | 
			
		||||
        targetPath: $(Build.ArtifactStagingDirectory)
 | 
			
		||||
 | 
			
		||||
  - job: Ubuntu20
 | 
			
		||||
    displayName: "Ubuntu20 build"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: "ubuntu-20.04"
 | 
			
		||||
    steps:
 | 
			
		||||
    - script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
 | 
			
		||||
    - script: git clone https://github.com/z3prover/z3test z3test
 | 
			
		||||
    - script: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2    
 | 
			
		||||
    - script: cp dist/*.zip $(Build.ArtifactStagingDirectory)/.
 | 
			
		||||
    - task: PublishPipelineArtifact@0
 | 
			
		||||
      inputs:
 | 
			
		||||
        artifactName: 'Ubuntu-20.04'
 | 
			
		||||
        targetPath: $(Build.ArtifactStagingDirectory)
 | 
			
		||||
 | 
			
		||||
  - job: Ubuntu
 | 
			
		||||
    displayName: "Ubuntu build"
 | 
			
		||||
    pool:
 | 
			
		||||
| 
						 | 
				
			
			@ -512,6 +526,11 @@ stages:
 | 
			
		|||
      inputs:
 | 
			
		||||
        artifactName: 'Ubuntu'
 | 
			
		||||
        targetPath: tmp
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: "Download Ubuntu-20.04"
 | 
			
		||||
      inputs:
 | 
			
		||||
        artifactName: 'Ubuntu-20.04'
 | 
			
		||||
        targetPath: tmp
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: "Download Doc"
 | 
			
		||||
      inputs:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
trigger: none
 | 
			
		||||
 | 
			
		||||
variables:
 | 
			
		||||
  ReleaseVersion: '4.12.2'
 | 
			
		||||
  ReleaseVersion: '4.12.3'
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +85,35 @@ stages:
 | 
			
		|||
        artifactName: 'UbuntuBuild'
 | 
			
		||||
        targetPath: $(Build.ArtifactStagingDirectory)
 | 
			
		||||
 | 
			
		||||
  - job: UbuntuBuild20
 | 
			
		||||
    displayName: "Ubuntu build 20"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: "ubuntu-20.04"
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: PythonScript@0
 | 
			
		||||
      displayName: Build
 | 
			
		||||
      inputs:
 | 
			
		||||
        scriptSource: 'filepath'
 | 
			
		||||
        scriptPath: scripts/mk_unix_dist.py
 | 
			
		||||
        arguments: --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk
 | 
			
		||||
    - script: git clone https://github.com/z3prover/z3test z3test
 | 
			
		||||
      displayName: 'Clone z3test'
 | 
			
		||||
    - task: PythonScript@0
 | 
			
		||||
      displayName: Test
 | 
			
		||||
      inputs:
 | 
			
		||||
        scriptSource: 'filepath'
 | 
			
		||||
        scriptPath: z3test/scripts/test_benchmarks.py
 | 
			
		||||
        arguments: build-dist/z3 z3test/regressions/smt2
 | 
			
		||||
    - task: CopyFiles@2
 | 
			
		||||
      inputs:
 | 
			
		||||
        sourceFolder: dist
 | 
			
		||||
        contents: '*.zip'
 | 
			
		||||
        targetFolder: $(Build.ArtifactStagingDirectory)
 | 
			
		||||
    - task: PublishPipelineArtifact@0
 | 
			
		||||
      inputs:
 | 
			
		||||
        artifactName: 'UbuntuBuild20'
 | 
			
		||||
        targetPath: $(Build.ArtifactStagingDirectory)
 | 
			
		||||
 | 
			
		||||
  - job: UbuntuDoc
 | 
			
		||||
    displayName: "Ubuntu Doc build"
 | 
			
		||||
    pool:
 | 
			
		||||
| 
						 | 
				
			
			@ -191,6 +220,11 @@ stages:
 | 
			
		|||
      inputs:
 | 
			
		||||
        artifact: 'UbuntuBuild'
 | 
			
		||||
        path: $(Agent.TempDirectory)\package
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: 'Download Ubuntu20 Build'
 | 
			
		||||
      inputs:
 | 
			
		||||
        artifact: 'UbuntuBuild20'
 | 
			
		||||
        path: $(Agent.TempDirectory)\package
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: 'Download macOS Build'
 | 
			
		||||
      inputs:
 | 
			
		||||
| 
						 | 
				
			
			@ -436,6 +470,11 @@ stages:
 | 
			
		|||
    pool:
 | 
			
		||||
      vmImage: "windows-latest"
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: 'Download Ubuntu Build'
 | 
			
		||||
      inputs:
 | 
			
		||||
        artifact: 'UbuntuBuild20'
 | 
			
		||||
        path: $(Agent.TempDirectory)
 | 
			
		||||
    - task: DownloadPipelineArtifact@2
 | 
			
		||||
      displayName: 'Download Ubuntu Build'
 | 
			
		||||
      inputs:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -633,7 +633,72 @@ def mk_java(java_src, java_dir, package_name):
 | 
			
		|||
    java_native.write('      }\n')
 | 
			
		||||
    java_native.write('    }\n')
 | 
			
		||||
    java_native.write('  }\n')
 | 
			
		||||
    java_native.write("""
 | 
			
		||||
  public static native long propagateInit(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateRegisterCreated(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateRegisterFixed(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateRegisterEq(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateRegisterDecide(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateRegisterFinal(Object o, long ctx, long solver);
 | 
			
		||||
  public static native void propagateConflict(Object o, long ctx, long solver, long javainfo, int num_fixed, long[] fixed, long num_eqs, long[] eq_lhs, long[] eq_rhs, long conseq);
 | 
			
		||||
  public static native void propagateAdd(Object o, long ctx, long solver, long javainfo, long e);
 | 
			
		||||
  public static native void propagateNextSplit(Object o, long ctx, long solver, long javainfo, long e, long idx, long phase);
 | 
			
		||||
  public static native void propagateDestroy(Object o, long ctx, long solver, long javainfo);
 | 
			
		||||
 | 
			
		||||
  public static abstract class UserPropagatorBase implements AutoCloseable {
 | 
			
		||||
    protected long ctx;
 | 
			
		||||
    protected long solver;
 | 
			
		||||
    protected long javainfo;
 | 
			
		||||
 | 
			
		||||
    public UserPropagatorBase(long _ctx, long _solver) {
 | 
			
		||||
        ctx = _ctx;
 | 
			
		||||
        solver = _solver;
 | 
			
		||||
        javainfo = propagateInit(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void close() {
 | 
			
		||||
        Native.propagateDestroy(this, ctx, solver, javainfo);
 | 
			
		||||
        javainfo = 0;
 | 
			
		||||
        solver = 0;
 | 
			
		||||
        ctx = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final void registerCreated() {
 | 
			
		||||
        Native.propagateRegisterCreated(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final void registerFixed() {
 | 
			
		||||
        Native.propagateRegisterFixed(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final void registerEq() {
 | 
			
		||||
        Native.propagateRegisterEq(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final void registerDecide() {
 | 
			
		||||
        Native.propagateRegisterDecide(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected final void registerFinal() {
 | 
			
		||||
        Native.propagateRegisterFinal(this, ctx, solver);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected abstract void pushWrapper();
 | 
			
		||||
 | 
			
		||||
    protected abstract void popWrapper(int number);
 | 
			
		||||
 | 
			
		||||
    protected abstract void finWrapper();
 | 
			
		||||
 | 
			
		||||
    protected abstract void eqWrapper(long lx, long ly);
 | 
			
		||||
 | 
			
		||||
    protected abstract UserPropagatorBase freshWrapper(long lctx);
 | 
			
		||||
 | 
			
		||||
    protected abstract void createdWrapper(long le);
 | 
			
		||||
 | 
			
		||||
    protected abstract void fixedWrapper(long lvar, long lvalue);
 | 
			
		||||
  }
 | 
			
		||||
    """)
 | 
			
		||||
    java_native.write('\n')
 | 
			
		||||
    for name, result, params in _dotnet_decls:
 | 
			
		||||
        java_native.write('  protected static native %s INTERNAL%s(' % (type2java(result), java_method_name(name)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1825,6 +1890,7 @@ if _lib is None:
 | 
			
		|||
  else:
 | 
			
		||||
    print("    import builtins")
 | 
			
		||||
    print("    builtins.Z3_LIB_DIRS = [ '/path/to/libz3.%s' ] " % _ext)
 | 
			
		||||
  print(_failures)
 | 
			
		||||
  raise Z3Exception("libz3.%s not found." % _ext)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1836,14 +1902,14 @@ if sys.version < '3':
 | 
			
		|||
else:
 | 
			
		||||
  def _str_to_bytes(s):
 | 
			
		||||
    if isinstance(s, str):
 | 
			
		||||
        enc = sys.stdout.encoding
 | 
			
		||||
        enc = sys.getdefaultencoding()
 | 
			
		||||
        return s.encode(enc if enc != None else 'latin-1')
 | 
			
		||||
    else:
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
  def _to_pystr(s):
 | 
			
		||||
     if s != None:
 | 
			
		||||
        enc = sys.stdout.encoding
 | 
			
		||||
        enc = sys.getdefaultencoding()
 | 
			
		||||
        return s.decode(enc if enc != None else 'latin-1')
 | 
			
		||||
     else:
 | 
			
		||||
        return ""
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,10 +120,8 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        // 
 | 
			
		||||
        recfun::promise_def def = 
 | 
			
		||||
            mk_c(c)->recfun().get_plugin().mk_def(to_symbol(s),                                      
 | 
			
		||||
                                          domain_size,
 | 
			
		||||
                                          to_sorts(domain),
 | 
			
		||||
                                          to_sort(range));
 | 
			
		||||
            mk_c(c)->recfun().get_plugin().mk_def(
 | 
			
		||||
                to_symbol(s), domain_size, to_sorts(domain), to_sort(range), false);
 | 
			
		||||
        func_decl* d = def.get_def()->get_decl();
 | 
			
		||||
        mk_c(c)->save_ast_trail(d);
 | 
			
		||||
        RETURN_Z3(of_func_decl(d));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        std::ostringstream buffer;
 | 
			
		||||
        if (!to_goal_ref(g)->is_cnf()) { 
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG, "If this is not what you want, then preprocess by optional bit-blasting and applying tseitin-cnf");
 | 
			
		||||
            SET_ERROR_CODE(Z3_INVALID_ARG, "Goal is not converted into CNF. Preprocess by optional bit-blasting and applying tseitin-cnf");
 | 
			
		||||
            RETURN_Z3(nullptr);
 | 
			
		||||
        }
 | 
			
		||||
        to_goal_ref(g)->display_dimacs(buffer, include_names);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -128,7 +128,8 @@ extern "C" {
 | 
			
		|||
 | 
			
		||||
    static Z3_ast_vector Z3_parser_context_parse_stream(Z3_context c, scoped_ptr<cmd_context>& ctx, bool owned, std::istream& is) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
 | 
			
		||||
        ast_manager& m = mk_c(c)->m();
 | 
			
		||||
        Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), m);        
 | 
			
		||||
        mk_c(c)->save_object(v);        
 | 
			
		||||
        std::stringstream errstrm;
 | 
			
		||||
        ctx->set_regular_stream(errstrm);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,8 +148,11 @@ extern "C" {
 | 
			
		|||
            SET_ERROR_CODE(Z3_PARSER_ERROR, errstrm.str());
 | 
			
		||||
            return of_ast_vector(v);
 | 
			
		||||
        }
 | 
			
		||||
        for (expr* e : ctx->tracked_assertions()) 
 | 
			
		||||
            v->m_ast_vector.push_back(e);
 | 
			
		||||
        for (auto const& [asr, an] : ctx->tracked_assertions())
 | 
			
		||||
            if (an)
 | 
			
		||||
                v->m_ast_vector.push_back(m.mk_implies(an, asr));
 | 
			
		||||
            else
 | 
			
		||||
                v->m_ast_vector.push_back(asr);
 | 
			
		||||
        ctx->reset_tracked_assertions();        
 | 
			
		||||
        return of_ast_vector(v);
 | 
			
		||||
        Z3_CATCH_RETURN(nullptr);        
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -314,8 +314,11 @@ extern "C" {
 | 
			
		|||
        bool initialized = to_solver(s)->m_solver.get() != nullptr;
 | 
			
		||||
        if (!initialized)
 | 
			
		||||
            init_solver(c, s);
 | 
			
		||||
        for (expr* e : ctx->tracked_assertions()) 
 | 
			
		||||
            to_solver(s)->assert_expr(e);
 | 
			
		||||
        for (auto const& [asr, an] : ctx->tracked_assertions())
 | 
			
		||||
            if (an)
 | 
			
		||||
                to_solver(s)->assert_expr(asr, an);
 | 
			
		||||
            else
 | 
			
		||||
                to_solver(s)->assert_expr(asr);
 | 
			
		||||
        ctx->reset_tracked_assertions();
 | 
			
		||||
        to_solver_ref(s)->set_model_converter(ctx->get_model_converter());
 | 
			
		||||
        auto* ctx_s = ctx->get_solver();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ Revision History:
 | 
			
		|||
#include "util/scoped_ctrl_c.h"
 | 
			
		||||
#include "util/cancel_eh.h"
 | 
			
		||||
#include "util/scoped_timer.h"
 | 
			
		||||
#include "ast/simplifiers/seq_simplifier.h"
 | 
			
		||||
#include "ast/simplifiers/then_simplifier.h"
 | 
			
		||||
 | 
			
		||||
Z3_apply_result_ref::Z3_apply_result_ref(api::context& c, ast_manager & m): api::object(c) {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -589,7 +589,7 @@ extern "C" {
 | 
			
		|||
        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);
 | 
			
		||||
            auto* r = alloc(then_simplifier, m, p, st);
 | 
			
		||||
            r->add_simplifier(fac1(m, p, st));
 | 
			
		||||
            r->add_simplifier(fac2(m, p, st));
 | 
			
		||||
            return r;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -151,6 +151,7 @@ namespace z3 {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief A Context manages all other Z3 objects, global configuration options, etc.
 | 
			
		||||
    */
 | 
			
		||||
| 
						 | 
				
			
			@ -360,11 +361,19 @@ namespace z3 {
 | 
			
		|||
        func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & d4, sort const & d5, sort const & range);
 | 
			
		||||
 | 
			
		||||
        func_decl recfun(symbol const & name, unsigned arity, sort const * domain, sort const & range);
 | 
			
		||||
        func_decl recfun(symbol const & name, const sort_vector& domain, sort const & range);
 | 
			
		||||
        func_decl recfun(char const * name, sort_vector const& domain, sort const & range);
 | 
			
		||||
        func_decl recfun(char const * name, unsigned arity, sort const * domain, sort const & range);
 | 
			
		||||
        func_decl recfun(char const * name, sort const & domain, sort const & range);
 | 
			
		||||
        func_decl recfun(char const * name, sort const & d1, sort const & d2, sort const & range);
 | 
			
		||||
 | 
			
		||||
        void      recdef(func_decl, expr_vector const& args, expr const& body);
 | 
			
		||||
        /**
 | 
			
		||||
         * \brief add function definition body to declaration decl. decl needs to be declared using context::<recfun>.
 | 
			
		||||
         * @param decl
 | 
			
		||||
         * @param args
 | 
			
		||||
         * @param body
 | 
			
		||||
         */
 | 
			
		||||
        void      recdef(func_decl decl, expr_vector const& args, expr const& body);
 | 
			
		||||
        func_decl user_propagate_function(symbol const& name, sort_vector const& domain, sort const& range);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
| 
						 | 
				
			
			@ -742,6 +751,7 @@ namespace z3 {
 | 
			
		|||
        func_decl_vector recognizers();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Function declaration (aka function definition). It is the signature of interpreted and uninterpreted functions in Z3.
 | 
			
		||||
       The basic building block in Z3 is the function application.
 | 
			
		||||
| 
						 | 
				
			
			@ -762,6 +772,8 @@ namespace z3 {
 | 
			
		|||
        sort range() const { Z3_sort r = Z3_get_range(ctx(), *this); check_error(); return sort(ctx(), r); }
 | 
			
		||||
        symbol name() const { Z3_symbol s = Z3_get_decl_name(ctx(), *this); check_error(); return symbol(ctx(), s); }
 | 
			
		||||
        Z3_decl_kind decl_kind() const { return Z3_get_decl_kind(ctx(), *this); }
 | 
			
		||||
        unsigned num_parameters() const { return Z3_get_decl_num_parameters(ctx(), *this); }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        func_decl transitive_closure(func_decl const&) {
 | 
			
		||||
            Z3_func_decl tc = Z3_mk_transitive_closure(ctx(), *this); check_error(); return func_decl(ctx(), tc); 
 | 
			
		||||
| 
						 | 
				
			
			@ -2679,6 +2691,43 @@ namespace z3 {
 | 
			
		|||
        return out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
        \brief class for auxiliary parameters associated with func_decl 
 | 
			
		||||
        The class is initialized with a func_decl or application expression and an index
 | 
			
		||||
        The accessor get_expr, get_sort, ... is available depending on the value of kind().
 | 
			
		||||
        The caller is responsible to check that the kind of the parameter aligns with the call (get_expr etc).
 | 
			
		||||
 | 
			
		||||
        Parameters are available on some declarations to contain additional information that is not passed as
 | 
			
		||||
        arguments when a function is applied to arguments. For example, bit-vector extraction has two 
 | 
			
		||||
        integer parameters. Array map has a function parameter.
 | 
			
		||||
    */
 | 
			
		||||
    class parameter {
 | 
			
		||||
        Z3_parameter_kind m_kind;
 | 
			
		||||
        func_decl         m_decl;
 | 
			
		||||
        unsigned          m_index;
 | 
			
		||||
        context& ctx() const { return m_decl.ctx(); }
 | 
			
		||||
        void check_error() const { ctx().check_error(); }
 | 
			
		||||
    public:
 | 
			
		||||
        parameter(func_decl const& d, unsigned idx) : m_decl(d), m_index(idx) { 
 | 
			
		||||
            if (ctx().enable_exceptions() && idx >= d.num_parameters())
 | 
			
		||||
                Z3_THROW(exception("parameter index is out of bounds"));
 | 
			
		||||
            m_kind = Z3_get_decl_parameter_kind(ctx(), d, idx); 
 | 
			
		||||
        }
 | 
			
		||||
        parameter(expr const& e, unsigned idx) : m_decl(e.decl()), m_index(idx) {
 | 
			
		||||
            if (ctx().enable_exceptions() && idx >= m_decl.num_parameters())
 | 
			
		||||
                Z3_THROW(exception("parameter index is out of bounds"));
 | 
			
		||||
            m_kind = Z3_get_decl_parameter_kind(ctx(), m_decl, idx);
 | 
			
		||||
        }
 | 
			
		||||
        Z3_parameter_kind kind() const { return m_kind; }
 | 
			
		||||
        expr get_expr() const { Z3_ast a = Z3_get_decl_ast_parameter(ctx(), m_decl, m_index); check_error(); return expr(ctx(), a); }
 | 
			
		||||
        sort get_sort() const { Z3_sort s = Z3_get_decl_sort_parameter(ctx(), m_decl, m_index); check_error(); return sort(ctx(), s); }
 | 
			
		||||
        func_decl get_decl() const { Z3_func_decl f = Z3_get_decl_func_decl_parameter(ctx(), m_decl, m_index); check_error(); return func_decl(ctx(), f); }
 | 
			
		||||
        symbol get_symbol() const { Z3_symbol s = Z3_get_decl_symbol_parameter(ctx(), m_decl, m_index); check_error(); return symbol(ctx(), s); }
 | 
			
		||||
        std::string get_rational() const { Z3_string s = Z3_get_decl_rational_parameter(ctx(), m_decl, m_index); check_error(); return s; }
 | 
			
		||||
        double get_double() const { double d = Z3_get_decl_double_parameter(ctx(), m_decl, m_index); check_error(); return d; }
 | 
			
		||||
        int get_int() const { int i = Z3_get_decl_int_parameter(ctx(), m_decl, m_index); check_error(); return i; }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class solver : public object {
 | 
			
		||||
        Z3_solver m_solver;
 | 
			
		||||
| 
						 | 
				
			
			@ -2712,6 +2761,16 @@ namespace z3 {
 | 
			
		|||
        void set(char const * k, double v) { params p(ctx()); p.set(k, v); set(p); }
 | 
			
		||||
        void set(char const * k, symbol const & v) { params p(ctx()); p.set(k, v); set(p); }
 | 
			
		||||
        void set(char const * k, char const* v) { params p(ctx()); p.set(k, v); set(p); }
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Create a backtracking point.
 | 
			
		||||
 | 
			
		||||
           The solver contains a stack of assertions.
 | 
			
		||||
 | 
			
		||||
           \sa Z3_solver_get_num_scopes
 | 
			
		||||
           \sa Z3_solver_pop
 | 
			
		||||
 | 
			
		||||
           def_API('Z3_solver_push', VOID, (_in(CONTEXT), _in(SOLVER)))
 | 
			
		||||
        */
 | 
			
		||||
        void push() { Z3_solver_push(ctx(), m_solver); check_error(); }
 | 
			
		||||
        void pop(unsigned n = 1) { Z3_solver_pop(ctx(), m_solver, n); check_error(); }
 | 
			
		||||
        void reset() { Z3_solver_reset(ctx(), m_solver); check_error(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -3604,6 +3663,19 @@ namespace z3 {
 | 
			
		|||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline func_decl context::recfun(symbol const & name, sort_vector const& domain, sort const & range) {
 | 
			
		||||
        check_context(domain, range);
 | 
			
		||||
        array<Z3_sort> domain1(domain);
 | 
			
		||||
        Z3_func_decl f = Z3_mk_rec_func_decl(m_ctx, name, domain1.size(), domain1.ptr(), range);
 | 
			
		||||
        check_error();
 | 
			
		||||
        return func_decl(*this, f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline func_decl context::recfun(char const * name, sort_vector const& domain, sort const & range) {
 | 
			
		||||
        return recfun(str_symbol(name), domain, range);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline func_decl context::recfun(char const * name, unsigned arity, sort const * domain, sort const & range) {
 | 
			
		||||
        return recfun(str_symbol(name), arity, domain, range);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -179,6 +179,7 @@ set(Z3_JAVA_JAR_SOURCE_FILES
 | 
			
		|||
  Tactic.java
 | 
			
		||||
  TupleSort.java
 | 
			
		||||
  UninterpretedSort.java
 | 
			
		||||
  UserPropagatorBase.java
 | 
			
		||||
  Version.java
 | 
			
		||||
  Z3Exception.java
 | 
			
		||||
  Z3Object.java
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -227,7 +227,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new array sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> ArraySort<D, R> mkArraySort(D domain, R range)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> ArraySort<D, R> mkArraySort(D domain, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +238,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new array sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> ArraySort<Sort, R> mkArraySort(Sort[] domains, R range)
 | 
			
		||||
    public final <R extends Sort> ArraySort<Sort, R> mkArraySort(Sort[] domains, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domains);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
| 
						 | 
				
			
			@ -256,7 +256,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new sequence sort
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> SeqSort<R> mkSeqSort(R s)
 | 
			
		||||
    public final <R extends Sort> SeqSort<R> mkSeqSort(R s)
 | 
			
		||||
    {
 | 
			
		||||
        return new SeqSort<>(this, Native.mkSeqSort(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +264,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new regular expression sort
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> ReSort<R> mkReSort(R s)
 | 
			
		||||
    public final <R extends Sort> ReSort<R> mkReSort(R s)
 | 
			
		||||
    {
 | 
			
		||||
        return new ReSort<>(this, Native.mkReSort(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +286,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new enumeration sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> EnumSort<R> mkEnumSort(Symbol name, Symbol... enumNames)
 | 
			
		||||
    public final <R> EnumSort<R> mkEnumSort(Symbol name, Symbol... enumNames)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
| 
						 | 
				
			
			@ -297,7 +297,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new enumeration sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> EnumSort<R> mkEnumSort(String name, String... enumNames)
 | 
			
		||||
    public final <R> EnumSort<R> mkEnumSort(String name, String... enumNames)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        return new EnumSort<>(this, mkSymbol(name), mkSymbols(enumNames));
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +306,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new list sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> ListSort<R> mkListSort(Symbol name, R elemSort)
 | 
			
		||||
    public final <R extends Sort> ListSort<R> mkListSort(Symbol name, R elemSort)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(elemSort);
 | 
			
		||||
| 
						 | 
				
			
			@ -316,7 +316,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new list sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> ListSort<R> mkListSort(String name, R elemSort)
 | 
			
		||||
    public final <R extends Sort> ListSort<R> mkListSort(String name, R elemSort)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(elemSort);
 | 
			
		||||
        return new ListSort<>(this, mkSymbol(name), elemSort);
 | 
			
		||||
| 
						 | 
				
			
			@ -325,7 +325,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new finite domain sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> FiniteDomainSort<R> mkFiniteDomainSort(Symbol name, long size)
 | 
			
		||||
    public final <R> FiniteDomainSort<R> mkFiniteDomainSort(Symbol name, long size)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +335,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new finite domain sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> FiniteDomainSort<R> mkFiniteDomainSort(String name, long size)
 | 
			
		||||
    public final <R> FiniteDomainSort<R> mkFiniteDomainSort(String name, long size)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        return new FiniteDomainSort<>(this, mkSymbol(name), size);
 | 
			
		||||
| 
						 | 
				
			
			@ -352,7 +352,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * an index referring to one of the recursive datatypes that is
 | 
			
		||||
     * declared.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> Constructor<R> mkConstructor(Symbol name, Symbol recognizer,
 | 
			
		||||
    public final <R> Constructor<R> mkConstructor(Symbol name, Symbol recognizer,
 | 
			
		||||
            Symbol[] fieldNames, Sort[] sorts, int[] sortRefs)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -362,7 +362,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a datatype constructor. 
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> Constructor<R> mkConstructor(String name, String recognizer,
 | 
			
		||||
    public final <R> Constructor<R> mkConstructor(String name, String recognizer,
 | 
			
		||||
            String[] fieldNames, Sort[] sorts, int[] sortRefs)
 | 
			
		||||
    {
 | 
			
		||||
        return of(this, mkSymbol(name), mkSymbol(recognizer), mkSymbols(fieldNames), sorts, sortRefs);
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +371,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new datatype sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> DatatypeSort<R> mkDatatypeSort(Symbol name, Constructor<R>[] constructors)
 | 
			
		||||
    public final <R> DatatypeSort<R> mkDatatypeSort(Symbol name, Constructor<R>[] constructors)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(constructors);
 | 
			
		||||
| 
						 | 
				
			
			@ -381,7 +381,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a new datatype sort.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R> DatatypeSort<R> mkDatatypeSort(String name, Constructor<R>[] constructors)
 | 
			
		||||
    public final <R> DatatypeSort<R> mkDatatypeSort(String name, Constructor<R>[] constructors)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(constructors);
 | 
			
		||||
| 
						 | 
				
			
			@ -431,7 +431,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * that is passed in as argument is updated with value v,
 | 
			
		||||
     * the remaining fields of t are unchanged.
 | 
			
		||||
     **/
 | 
			
		||||
    public <F extends Sort, R extends Sort> Expr<R> mkUpdateField(FuncDecl<F> field, Expr<R> t, Expr<F> v)
 | 
			
		||||
    public final <F extends Sort, R extends Sort> Expr<R> mkUpdateField(FuncDecl<F> field, Expr<R> t, Expr<F> v)
 | 
			
		||||
        throws Z3Exception
 | 
			
		||||
    {
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -444,7 +444,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort[] domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort[] domain, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
| 
						 | 
				
			
			@ -452,10 +452,25 @@ public class Context implements AutoCloseable {
 | 
			
		|||
        return new FuncDecl<>(this, name, domain, range);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkPropagateFunction(Symbol name, Sort[] domain, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
        long f = Native.solverPropagateDeclare(
 | 
			
		||||
            this.nCtx(), 
 | 
			
		||||
            name.getNativeObject(), 
 | 
			
		||||
            AST.arrayLength(domain), 
 | 
			
		||||
            AST.arrayToNative(domain),
 | 
			
		||||
            range.getNativeObject());
 | 
			
		||||
        return new FuncDecl<>(this, f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFuncDecl(Symbol name, Sort domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
| 
						 | 
				
			
			@ -468,7 +483,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort[] domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort[] domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
| 
						 | 
				
			
			@ -479,7 +494,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFuncDecl(String name, Sort domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
| 
						 | 
				
			
			@ -491,7 +506,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new recursive function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkRecFuncDecl(Symbol name, Sort[] domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkRecFuncDecl(Symbol name, Sort[] domain, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
| 
						 | 
				
			
			@ -506,7 +521,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * MkRecFuncDecl. The body may contain recursive uses of the function or
 | 
			
		||||
     * other mutually recursive functions. 
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> void AddRecDef(FuncDecl<R> f, Expr<?>[] args, Expr<R> body)
 | 
			
		||||
    public final <R extends Sort> void AddRecDef(FuncDecl<R> f, Expr<?>[] args, Expr<R> body)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(f);
 | 
			
		||||
        checkContextMatch(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -521,7 +536,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkFuncDecl(String,Sort,Sort)
 | 
			
		||||
     * @see #mkFuncDecl(String,Sort[],Sort)
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFreshFuncDecl(String prefix, Sort[] domain, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFreshFuncDecl(String prefix, Sort[] domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
| 
						 | 
				
			
			@ -532,7 +547,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new constant function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkConstDecl(Symbol name, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkConstDecl(Symbol name, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
| 
						 | 
				
			
			@ -542,7 +557,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Creates a new constant function declaration.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkConstDecl(String name, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkConstDecl(String name, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
        return new FuncDecl<>(this, mkSymbol(name), null, range);
 | 
			
		||||
| 
						 | 
				
			
			@ -554,7 +569,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkFuncDecl(String,Sort,Sort)
 | 
			
		||||
     * @see #mkFuncDecl(String,Sort[],Sort)
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> FuncDecl<R> mkFreshConstDecl(String prefix, R range)
 | 
			
		||||
    public final <R extends Sort> FuncDecl<R> mkFreshConstDecl(String prefix, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
| 
						 | 
				
			
			@ -566,7 +581,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @param index The de-Bruijn index of the variable 
 | 
			
		||||
     * @param ty The sort of the variable
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkBound(int index, R ty)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkBound(int index, R ty)
 | 
			
		||||
    {
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
                Native.mkBound(nCtx(), index, ty.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -590,7 +605,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Creates a new Constant of sort {@code range} and named
 | 
			
		||||
     * {@code name}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkConst(Symbol name, R range)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkConst(Symbol name, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(name);
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
| 
						 | 
				
			
			@ -605,7 +620,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Creates a new Constant of sort {@code range} and named
 | 
			
		||||
     * {@code name}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkConst(String name, R range)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkConst(String name, R range)
 | 
			
		||||
    {
 | 
			
		||||
        return mkConst(mkSymbol(name), range);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -614,7 +629,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Creates a fresh Constant of sort {@code range} and a name
 | 
			
		||||
     * prefixed with {@code prefix}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkFreshConst(String prefix, R range)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkFreshConst(String prefix, R range)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(range);
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -625,7 +640,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Creates a fresh constant from the FuncDecl {@code f}. 
 | 
			
		||||
     * @param f A decl of a 0-arity function
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkConst(FuncDecl<R> f)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkConst(FuncDecl<R> f)
 | 
			
		||||
    {
 | 
			
		||||
        return mkApp(f, (Expr<?>[]) null);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -754,7 +769,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an expression representing {@code not(a)}.
 | 
			
		||||
     **/
 | 
			
		||||
    public BoolExpr mkNot(Expr<BoolSort> a)
 | 
			
		||||
    public final BoolExpr mkNot(Expr<BoolSort> a)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        return new BoolExpr(this, Native.mkNot(nCtx(), a.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -767,7 +782,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @param t2 An expression  
 | 
			
		||||
     * @param t3 An expression with the same sort as {@code t2}
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkITE(Expr<BoolSort> t1, Expr<? extends R> t2, Expr<? extends R> t3)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkITE(Expr<BoolSort> t1, Expr<? extends R> t2, Expr<? extends R> t3)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(t1);
 | 
			
		||||
        checkContextMatch(t2);
 | 
			
		||||
| 
						 | 
				
			
			@ -867,7 +882,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an expression representing {@code -t}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends ArithSort> ArithExpr<R> mkUnaryMinus(Expr<R> t)
 | 
			
		||||
    public final <R extends ArithSort> ArithExpr<R> mkUnaryMinus(Expr<R> t)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(t);
 | 
			
		||||
        return (ArithExpr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -877,7 +892,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an expression representing {@code t1 / t2}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends ArithSort> ArithExpr<R> mkDiv(Expr<? extends R> t1, Expr<? extends R> t2)
 | 
			
		||||
    public final <R extends ArithSort> ArithExpr<R> mkDiv(Expr<? extends R> t1, Expr<? extends R> t2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(t1);
 | 
			
		||||
        checkContextMatch(t2);
 | 
			
		||||
| 
						 | 
				
			
			@ -914,7 +929,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an expression representing {@code t1 ^ t2}.
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends ArithSort> ArithExpr<R> mkPower(Expr<? extends R> t1,
 | 
			
		||||
    public final <R extends ArithSort> ArithExpr<R> mkPower(Expr<? extends R> t1,
 | 
			
		||||
            Expr<? extends R> t2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(t1);
 | 
			
		||||
| 
						 | 
				
			
			@ -1693,7 +1708,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an array constant.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(Symbol name, D domain, R range)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(Symbol name, D domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        return (ArrayExpr<D, R>) mkConst(name, mkArraySort(domain, range));
 | 
			
		||||
| 
						 | 
				
			
			@ -1702,7 +1717,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an array constant.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(String name, D domain, R range)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkArrayConst(String name, D domain, R range)
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        return (ArrayExpr<D, R>) mkConst(mkSymbol(name), mkArraySort(domain, range));
 | 
			
		||||
| 
						 | 
				
			
			@ -1720,7 +1735,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkArraySort(Sort[], R)
 | 
			
		||||
     * @see #mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> Expr<R> mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> Expr<R> mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(i);
 | 
			
		||||
| 
						 | 
				
			
			@ -1742,7 +1757,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkArraySort(Sort[], R)
 | 
			
		||||
     * @see #mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkSelect(Expr<ArraySort<Sort, R>> a, Expr<?>[] args)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkSelect(Expr<ArraySort<Sort, R>> a, Expr<?>[] args)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -1767,7 +1782,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
 | 
			
		||||
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkStore(Expr<ArraySort<D, R>> a, Expr<D> i, Expr<R> v)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(i);
 | 
			
		||||
| 
						 | 
				
			
			@ -1792,7 +1807,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
 | 
			
		||||
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> ArrayExpr<Sort, R> mkStore(Expr<ArraySort<Sort, R>> a, Expr<?>[] args, Expr<R> v)
 | 
			
		||||
    public final <R extends Sort> ArrayExpr<Sort, R> mkStore(Expr<ArraySort<Sort, R>> a, Expr<?>[] args, Expr<R> v)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a);
 | 
			
		||||
        checkContextMatch(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -1810,7 +1825,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @see #mkSelect(Expr<ArraySort<D, R>> a, Expr<D> i)
 | 
			
		||||
     *
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> ArrayExpr<D, R> mkConstArray(D domain, Expr<R> v)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> ArrayExpr<D, R> mkConstArray(D domain, Expr<R> v)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
        checkContextMatch(v);
 | 
			
		||||
| 
						 | 
				
			
			@ -1847,7 +1862,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * value, for arrays that can be represented as finite maps with a default
 | 
			
		||||
     * range value. 
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> Expr<R> mkTermArray(Expr<ArraySort<D, R>> array)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> Expr<R> mkTermArray(Expr<ArraySort<D, R>> array)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(array);
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -1857,7 +1872,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create Extentionality index. Two arrays are equal if and only if they are equal on the index returned by MkArrayExt.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort, R extends Sort> Expr<D> mkArrayExt(Expr<ArraySort<D, R>> arg1, Expr<ArraySort<D, R>> arg2)
 | 
			
		||||
    public final <D extends Sort, R extends Sort> Expr<D> mkArrayExt(Expr<ArraySort<D, R>> arg1, Expr<ArraySort<D, R>> arg2)
 | 
			
		||||
    {
 | 
			
		||||
    checkContextMatch(arg1);
 | 
			
		||||
    checkContextMatch(arg2);
 | 
			
		||||
| 
						 | 
				
			
			@ -1868,7 +1883,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a set type.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> SetSort<D> mkSetSort(D ty)
 | 
			
		||||
    public final <D extends Sort> SetSort<D> mkSetSort(D ty)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(ty);
 | 
			
		||||
        return new SetSort<>(this, ty);
 | 
			
		||||
| 
						 | 
				
			
			@ -1877,7 +1892,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create an empty set.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkEmptySet(D domain)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkEmptySet(D domain)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
        return (ArrayExpr<D, BoolSort>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -1887,7 +1902,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create the full set.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkFullSet(D domain)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkFullSet(D domain)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(domain);
 | 
			
		||||
        return (ArrayExpr<D, BoolSort>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -1897,7 +1912,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Add an element to the set.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkSetAdd(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetAdd(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(set);
 | 
			
		||||
        checkContextMatch(element);
 | 
			
		||||
| 
						 | 
				
			
			@ -1909,7 +1924,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Remove an element from a set.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkSetDel(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetDel(Expr<ArraySort<D, BoolSort>> set, Expr<D> element)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(set);
 | 
			
		||||
        checkContextMatch(element);
 | 
			
		||||
| 
						 | 
				
			
			@ -1945,7 +1960,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the difference between two sets.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkSetDifference(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetDifference(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(arg1);
 | 
			
		||||
        checkContextMatch(arg2);
 | 
			
		||||
| 
						 | 
				
			
			@ -1957,7 +1972,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the complement of a set.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> ArrayExpr<D, BoolSort> mkSetComplement(Expr<ArraySort<D, BoolSort>> arg)
 | 
			
		||||
    public final <D extends Sort> ArrayExpr<D, BoolSort> mkSetComplement(Expr<ArraySort<D, BoolSort>> arg)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(arg);
 | 
			
		||||
        return (ArrayExpr<D, BoolSort>)Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -1967,7 +1982,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Check for set membership.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> BoolExpr mkSetMembership(Expr<D> elem, Expr<ArraySort<D, BoolSort>> set)
 | 
			
		||||
    public final <D extends Sort> BoolExpr mkSetMembership(Expr<D> elem, Expr<ArraySort<D, BoolSort>> set)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(elem);
 | 
			
		||||
        checkContextMatch(set);
 | 
			
		||||
| 
						 | 
				
			
			@ -1979,7 +1994,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Check for subsetness of sets.
 | 
			
		||||
     **/
 | 
			
		||||
    public <D extends Sort> BoolExpr mkSetSubset(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
 | 
			
		||||
    public final <D extends Sort> BoolExpr mkSetSubset(Expr<ArraySort<D, BoolSort>> arg1, Expr<ArraySort<D, BoolSort>> arg2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(arg1);
 | 
			
		||||
        checkContextMatch(arg2);
 | 
			
		||||
| 
						 | 
				
			
			@ -1996,7 +2011,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create the empty sequence.
 | 
			
		||||
    */
 | 
			
		||||
    public <R extends Sort> SeqExpr<R> mkEmptySeq(R s)
 | 
			
		||||
    public final <R extends Sort> SeqExpr<R> mkEmptySeq(R s)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s);
 | 
			
		||||
        return (SeqExpr<R>) Expr.create(this, Native.mkSeqEmpty(nCtx(), s.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2005,7 +2020,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create the singleton sequence.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> SeqExpr<R> mkUnit(Expr<R> elem)
 | 
			
		||||
    public final <R extends Sort> SeqExpr<R> mkUnit(Expr<R> elem)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(elem);
 | 
			
		||||
        return (SeqExpr<R>) Expr.create(this, Native.mkSeqUnit(nCtx(), elem.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2018,11 +2033,11 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    {
 | 
			
		||||
        StringBuilder buf = new StringBuilder();
 | 
			
		||||
        for (int i = 0; i < s.length(); ++i) {
 | 
			
		||||
	    int code = s.codePointAt(i);
 | 
			
		||||
	    if (code <= 32 || 127 < code) 
 | 
			
		||||
	        buf.append(String.format("\\u{%x}", code));
 | 
			
		||||
	    else
 | 
			
		||||
	        buf.append(s.charAt(i));
 | 
			
		||||
            int code = s.codePointAt(i);
 | 
			
		||||
            if (code <= 32 || 127 < code) 
 | 
			
		||||
                buf.append(String.format("\\u{%x}", code));
 | 
			
		||||
            else
 | 
			
		||||
                buf.append(s.charAt(i));
 | 
			
		||||
        }
 | 
			
		||||
        return (SeqExpr<CharSort>) Expr.create(this, Native.mkString(nCtx(), buf.toString()));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2073,7 +2088,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Retrieve the length of a given sequence.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> IntExpr mkLength(Expr<SeqSort<R>> s)
 | 
			
		||||
    public final <R extends Sort> IntExpr mkLength(Expr<SeqSort<R>> s)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s);
 | 
			
		||||
        return (IntExpr) Expr.create(this, Native.mkSeqLength(nCtx(), s.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2082,7 +2097,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Check for sequence prefix.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> BoolExpr mkPrefixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    public final <R extends Sort> BoolExpr mkPrefixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s1, s2);
 | 
			
		||||
        return (BoolExpr) Expr.create(this, Native.mkSeqPrefix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2091,7 +2106,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Check for sequence suffix.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> BoolExpr mkSuffixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    public final <R extends Sort> BoolExpr mkSuffixOf(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s1, s2);
 | 
			
		||||
        return (BoolExpr)Expr.create(this, Native.mkSeqSuffix(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2100,7 +2115,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Check for sequence containment of s2 in s1.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> BoolExpr mkContains(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    public final <R extends Sort> BoolExpr mkContains(Expr<SeqSort<R>> s1, Expr<SeqSort<R>> s2)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s1, s2);
 | 
			
		||||
        return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2129,7 +2144,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Retrieve sequence of length one at index.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> SeqExpr<R> mkAt(Expr<SeqSort<R>> s, Expr<IntSort> index)
 | 
			
		||||
    public final <R extends Sort> SeqExpr<R> mkAt(Expr<SeqSort<R>> s, Expr<IntSort> index)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, index);
 | 
			
		||||
        return (SeqExpr<R>) Expr.create(this, Native.mkSeqAt(nCtx(), s.getNativeObject(), index.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2138,7 +2153,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     *  Retrieve element at index.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> Expr<R> mkNth(Expr<SeqSort<R>> s, Expr<IntSort> index)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkNth(Expr<SeqSort<R>> s, Expr<IntSort> index)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, index);
 | 
			
		||||
        return (Expr<R>) Expr.create(this, Native.mkSeqNth(nCtx(), s.getNativeObject(), index.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2148,7 +2163,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Extract subsequence.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> SeqExpr<R> mkExtract(Expr<SeqSort<R>> s, Expr<IntSort> offset, Expr<IntSort> length)
 | 
			
		||||
    public final <R extends Sort> SeqExpr<R> mkExtract(Expr<SeqSort<R>> s, Expr<IntSort> offset, Expr<IntSort> length)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, offset, length);
 | 
			
		||||
        return (SeqExpr<R>) Expr.create(this, Native.mkSeqExtract(nCtx(), s.getNativeObject(), offset.getNativeObject(), length.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2157,7 +2172,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Extract index of sub-string starting at offset.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> IntExpr mkIndexOf(Expr<SeqSort<R>> s, Expr<SeqSort<R>> substr, Expr<IntSort> offset)
 | 
			
		||||
    public final <R extends Sort> IntExpr mkIndexOf(Expr<SeqSort<R>> s, Expr<SeqSort<R>> substr, Expr<IntSort> offset)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, substr, offset);
 | 
			
		||||
        return (IntExpr)Expr.create(this, Native.mkSeqIndex(nCtx(), s.getNativeObject(), substr.getNativeObject(), offset.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2166,7 +2181,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Replace the first occurrence of src by dst in s.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> SeqExpr<R> mkReplace(Expr<SeqSort<R>> s, Expr<SeqSort<R>> src, Expr<SeqSort<R>> dst)
 | 
			
		||||
    public final <R extends Sort> SeqExpr<R> mkReplace(Expr<SeqSort<R>> s, Expr<SeqSort<R>> src, Expr<SeqSort<R>> dst)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, src, dst);
 | 
			
		||||
        return (SeqExpr<R>) Expr.create(this, Native.mkSeqReplace(nCtx(), s.getNativeObject(), src.getNativeObject(), dst.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2175,17 +2190,17 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Convert a regular expression that accepts sequence s.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkToRe(Expr<SeqSort<R>> s)
 | 
			
		||||
    public final <R extends Sort> ReExpr<SeqSort<R>> mkToRe(Expr<SeqSort<R>> s)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
 | 
			
		||||
        return (ReExpr<SeqSort<R>>) Expr.create(this, Native.mkSeqToRe(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check for regular expression membership.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> BoolExpr mkInRe(Expr<SeqSort<R>> s, Expr<ReSort<R>> re)
 | 
			
		||||
    public final <R extends Sort> BoolExpr mkInRe(Expr<SeqSort<R>> s, ReExpr<SeqSort<R>> re)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(s, re);
 | 
			
		||||
        return (BoolExpr) Expr.create(this, Native.mkSeqInRe(nCtx(), s.getNativeObject(), re.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2194,7 +2209,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the Kleene star of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkStar(Expr<ReSort<R>> re)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkStar(Expr<ReSort<R>> re)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(re);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2203,7 +2218,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create power regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkRePower(nCtx(), re.getNativeObject(), n));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2211,7 +2226,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the lower and upper-bounded Kleene star of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo, int hi)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo, int hi)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, hi));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2219,7 +2234,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the lower-bounded Kleene star of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkLoop(Expr<ReSort<R>> re, int lo)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReLoop(nCtx(), re.getNativeObject(), lo, 0));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2228,7 +2243,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Take the Kleene plus of a regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkPlus(Expr<ReSort<R>> re)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkPlus(Expr<ReSort<R>> re)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(re);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkRePlus(nCtx(), re.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2237,7 +2252,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create the optional regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkOption(Expr<ReSort<R>> re)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkOption(Expr<ReSort<R>> re)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(re);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReOption(nCtx(), re.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2246,7 +2261,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create the complement regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkComplement(Expr<ReSort<R>> re)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkComplement(Expr<ReSort<R>> re)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(re);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReComplement(nCtx(), re.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2285,10 +2300,10 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a difference regular expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkDiff(Expr<ReSort<R>> a, Expr<ReSort<R>> b)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkDiff(Expr<ReSort<R>> a, Expr<ReSort<R>> b)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(a, b);
 | 
			
		||||
	return (ReExpr<R>) Expr.create(this, Native.mkReDiff(nCtx(), a.getNativeObject(), b.getNativeObject()));
 | 
			
		||||
    return (ReExpr<R>) Expr.create(this, Native.mkReDiff(nCtx(), a.getNativeObject(), b.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2296,7 +2311,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Create the empty regular expression.
 | 
			
		||||
     * Coresponds to re.none
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkEmptyRe(R s)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkEmptyRe(ReSort<R> s)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReEmpty(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2305,16 +2320,17 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Create the full regular expression.
 | 
			
		||||
     * Corresponds to re.all
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkFullRe(R s)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkFullRe(ReSort<R> s)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReFull(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create regular expression that accepts all characters
 | 
			
		||||
     * R has to be a sequence sort.
 | 
			
		||||
     * Corresponds to re.allchar
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkAllcharRe(R s)
 | 
			
		||||
    public final <R extends Sort> ReExpr<R> mkAllcharRe(ReSort<R> s)
 | 
			
		||||
    {
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReAllchar(nCtx(), s.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2322,10 +2338,10 @@ public class Context implements AutoCloseable {
 | 
			
		|||
    /**
 | 
			
		||||
     * Create a range expression.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> ReExpr<R> mkRange(Expr<SeqSort<CharSort>> lo, Expr<SeqSort<CharSort>> hi)
 | 
			
		||||
    public final ReExpr<SeqSort<CharSort>> mkRange(Expr<SeqSort<CharSort>> lo, Expr<SeqSort<CharSort>> hi)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(lo, hi);
 | 
			
		||||
        return (ReExpr<R>) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
 | 
			
		||||
        return (ReExpr<SeqSort<CharSort>>) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -2429,7 +2445,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     *
 | 
			
		||||
     * @return A Term with value {@code v} and sort {@code ty}
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkNumeral(String v, R ty)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkNumeral(String v, R ty)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(ty);
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -2446,7 +2462,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     *
 | 
			
		||||
     * @return A Term with value {@code v} and type {@code ty}
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkNumeral(int v, R ty)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkNumeral(int v, R ty)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(ty);
 | 
			
		||||
        return (Expr<R>) Expr.create(this, Native.mkInt(nCtx(), v, ty.getNativeObject()));
 | 
			
		||||
| 
						 | 
				
			
			@ -2462,7 +2478,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     *
 | 
			
		||||
     * @return A Term with value {@code v} and type {@code ty}
 | 
			
		||||
     **/
 | 
			
		||||
    public <R extends Sort> Expr<R> mkNumeral(long v, R ty)
 | 
			
		||||
    public final <R extends Sort> Expr<R> mkNumeral(long v, R ty)
 | 
			
		||||
    {
 | 
			
		||||
        checkContextMatch(ty);
 | 
			
		||||
        return (Expr<R>) Expr.create(this,
 | 
			
		||||
| 
						 | 
				
			
			@ -2717,7 +2733,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @param names names of the bound variables.
 | 
			
		||||
     * @param body the body of the quantifier.
 | 
			
		||||
     **/
 | 
			
		||||
     public <R extends Sort> Lambda<R> mkLambda(Sort[] sorts, Symbol[] names, Expr<R> body)
 | 
			
		||||
     public final <R extends Sort> Lambda<R> mkLambda(Sort[] sorts, Symbol[] names, Expr<R> body)
 | 
			
		||||
     {
 | 
			
		||||
         return Lambda.of(this, sorts, names, body);
 | 
			
		||||
     }
 | 
			
		||||
| 
						 | 
				
			
			@ -2728,7 +2744,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * Creates a lambda expression using a list of constants that will
 | 
			
		||||
     * form the set of bound variables.
 | 
			
		||||
     **/
 | 
			
		||||
     public <R extends Sort> Lambda<R> mkLambda(Expr<?>[] boundConstants, Expr<R> body)
 | 
			
		||||
     public final <R extends Sort> Lambda<R> mkLambda(Expr<?>[] boundConstants, Expr<R> body)
 | 
			
		||||
     {
 | 
			
		||||
         return Lambda.of(this, boundConstants, body);
 | 
			
		||||
     }
 | 
			
		||||
| 
						 | 
				
			
			@ -4179,7 +4195,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @param index The index of the order.
 | 
			
		||||
     * @param sort The sort of the order.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> FuncDecl<BoolSort> mkLinearOrder(R sort, int index) {
 | 
			
		||||
    public final <R extends Sort> FuncDecl<BoolSort> mkLinearOrder(R sort, int index) {
 | 
			
		||||
        return (FuncDecl<BoolSort>) FuncDecl.create(
 | 
			
		||||
                this,
 | 
			
		||||
                Native.mkLinearOrder(
 | 
			
		||||
| 
						 | 
				
			
			@ -4195,7 +4211,7 @@ public class Context implements AutoCloseable {
 | 
			
		|||
     * @param index The index of the order.
 | 
			
		||||
     * @param sort The sort of the order.
 | 
			
		||||
     */
 | 
			
		||||
    public <R extends Sort> FuncDecl<BoolSort> mkPartialOrder(R sort, int index) {
 | 
			
		||||
    public final <R extends Sort> FuncDecl<BoolSort> mkPartialOrder(R sort, int index) {
 | 
			
		||||
        return (FuncDecl<BoolSort>) FuncDecl.create(
 | 
			
		||||
                this,
 | 
			
		||||
                Native.mkPartialOrder(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,3 +77,156 @@ DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_setInternalErrorHand
 | 
			
		|||
  Z3_set_error_handler((Z3_context)a0, Z3JavaErrorHandler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
 | 
			
		||||
struct JavaInfo {
 | 
			
		||||
  JNIEnv *jenv = nullptr;
 | 
			
		||||
  jobject jobj = nullptr;
 | 
			
		||||
 | 
			
		||||
  jmethodID push = nullptr;
 | 
			
		||||
  jmethodID pop = nullptr;
 | 
			
		||||
  jmethodID fresh = nullptr;
 | 
			
		||||
  jmethodID created = nullptr;
 | 
			
		||||
  jmethodID fixed = nullptr;
 | 
			
		||||
  jmethodID eq = nullptr;
 | 
			
		||||
  jmethodID final = nullptr;
 | 
			
		||||
 | 
			
		||||
  Z3_solver_callback cb = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ScopedCB {
 | 
			
		||||
  JavaInfo *info;
 | 
			
		||||
  ScopedCB(JavaInfo *_info, Z3_solver_callback cb): info(_info) {
 | 
			
		||||
    info->cb = cb;
 | 
			
		||||
  }
 | 
			
		||||
  ~ScopedCB() {
 | 
			
		||||
    info->cb = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void push_eh(void* _p, Z3_solver_callback cb) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->push);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pop_eh(void* _p, Z3_solver_callback cb, unsigned int number) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->pop, number);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void* fresh_eh(void* _p, Z3_context new_context) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  return info->jenv->CallObjectMethod(info->jobj, info->fresh, (jlong)new_context); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->created, (jlong)_e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void fixed_eh(void* _p, Z3_solver_callback cb, Z3_ast _var, Z3_ast _value) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->fixed, (jlong)_var, (jlong)_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void eq_eh(void* _p, Z3_solver_callback cb, Z3_ast _x, Z3_ast _y) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->eq, (jlong)_x, (jlong)_y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void final_eh(void* _p, Z3_solver_callback cb) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
  info->jenv->CallVoidMethod(info->jobj, info->final);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: implement decide
 | 
			
		||||
static void decide_eh(void* _p, Z3_solver_callback cb, Z3_ast* _val, unsigned* bit, Z3_lbool* is_pos) {
 | 
			
		||||
  JavaInfo *info = static_cast<JavaInfo*>(_p);
 | 
			
		||||
  ScopedCB scoped(info, cb);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT jlong JNICALL Java_com_microsoft_z3_Native_propagateInit(JNIEnv *jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  JavaInfo *info = new JavaInfo;
 | 
			
		||||
 | 
			
		||||
  info->jenv = jenv;
 | 
			
		||||
  info->jobj = jenv->NewGlobalRef(jobj);
 | 
			
		||||
  jclass jcls = jenv->GetObjectClass(info->jobj);
 | 
			
		||||
  info->push = jenv->GetMethodID(jcls, "pushWrapper", "()V");
 | 
			
		||||
  info->pop = jenv->GetMethodID(jcls, "popWrapper", "(I)V");
 | 
			
		||||
  info->fresh = jenv->GetMethodID(jcls, "freshWrapper", "(J)Lcom/microsoft/z3/Native$UserPropagatorBase;");
 | 
			
		||||
  info->created = jenv->GetMethodID(jcls, "createdWrapper", "(J)V");
 | 
			
		||||
  info->fixed = jenv->GetMethodID(jcls, "fixedWrapper", "(JJ)V");
 | 
			
		||||
  info->eq = jenv->GetMethodID(jcls, "eqWrapper", "(JJ)V");
 | 
			
		||||
  info->final = jenv->GetMethodID(jcls, "finWrapper", "()V");
 | 
			
		||||
  
 | 
			
		||||
  if (!info->push || !info->pop || !info->fresh || !info->created || !info->fixed || !info->eq || !info->final) {
 | 
			
		||||
    assert(false);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Z3_solver_propagate_init((Z3_context)ctx, (Z3_solver)solver, info, push_eh, pop_eh, fresh_eh);
 | 
			
		||||
 | 
			
		||||
  return (jlong)info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateDestroy(JNIEnv *jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo) {
 | 
			
		||||
  JavaInfo *info = (JavaInfo*)javainfo;
 | 
			
		||||
  info->jenv->DeleteGlobalRef(info->jobj);
 | 
			
		||||
  delete info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterCreated(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  Z3_solver_propagate_created((Z3_context)ctx, (Z3_solver)solver, created_eh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterFinal(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  Z3_solver_propagate_final((Z3_context)ctx, (Z3_solver)solver, final_eh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterFixed(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  Z3_solver_propagate_fixed((Z3_context)ctx, (Z3_solver)solver, fixed_eh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterEq(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  Z3_solver_propagate_eq((Z3_context)ctx, (Z3_solver)solver, eq_eh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateRegisterDecide(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver) {
 | 
			
		||||
  Z3_solver_propagate_decide((Z3_context)ctx, (Z3_solver)solver, decide_eh);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateConflict(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, jlong num_fixed, jlongArray fixed, jlong num_eqs, jlongArray eq_lhs, jlongArray eq_rhs, jlong conseq) {
 | 
			
		||||
  JavaInfo *info = (JavaInfo*)javainfo;
 | 
			
		||||
  GETLONGAELEMS(Z3_ast, fixed, _fixed);
 | 
			
		||||
  GETLONGAELEMS(Z3_ast, eq_lhs, _eq_lhs);
 | 
			
		||||
  GETLONGAELEMS(Z3_ast, eq_rhs, _eq_rhs);
 | 
			
		||||
  Z3_solver_propagate_consequence((Z3_context)ctx, info->cb, num_fixed, _fixed, num_eqs, _eq_lhs, _eq_rhs, (Z3_ast)conseq);
 | 
			
		||||
  RELEASELONGAELEMS(fixed, _fixed);
 | 
			
		||||
  RELEASELONGAELEMS(eq_lhs, _eq_lhs);
 | 
			
		||||
  RELEASELONGAELEMS(eq_rhs, _eq_rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateAdd(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, jlong e) {
 | 
			
		||||
  JavaInfo *info = (JavaInfo*)javainfo;
 | 
			
		||||
  Z3_solver_callback cb = info->cb;
 | 
			
		||||
  if (cb)
 | 
			
		||||
    Z3_solver_propagate_register_cb((Z3_context)ctx, cb, (Z3_ast)e);
 | 
			
		||||
  else if (solver)
 | 
			
		||||
    Z3_solver_propagate_register((Z3_context)ctx, (Z3_solver)solver, (Z3_ast)e);
 | 
			
		||||
  else {
 | 
			
		||||
    assert(false);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DLL_VIS JNIEXPORT void JNICALL Java_com_microsoft_z3_Native_propagateNextSplit(JNIEnv * jenv, jclass cls, jobject jobj, jlong ctx, jlong solver, jlong javainfo, long e, long idx, long phase) {
 | 
			
		||||
  JavaInfo *info = (JavaInfo*)javainfo;
 | 
			
		||||
  Z3_solver_callback cb = info->cb;
 | 
			
		||||
  Z3_solver_next_split((Z3_context)ctx, cb, (Z3_ast)e, idx, Z3_lbool(phase));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										97
									
								
								src/api/java/UserPropagatorBase.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								src/api/java/UserPropagatorBase.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
package com.microsoft.z3;
 | 
			
		||||
 | 
			
		||||
import com.microsoft.z3.Context;
 | 
			
		||||
import com.microsoft.z3.enumerations.Z3_lbool;
 | 
			
		||||
 | 
			
		||||
public abstract class UserPropagatorBase extends Native.UserPropagatorBase {
 | 
			
		||||
    private Context ctx;
 | 
			
		||||
    private Solver solver;
 | 
			
		||||
 | 
			
		||||
    public UserPropagatorBase(Context _ctx, Solver _solver) {
 | 
			
		||||
        super(_ctx.nCtx(), _solver.getNativeObject());   
 | 
			
		||||
        ctx = _ctx;
 | 
			
		||||
        solver = _solver; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final Context getCtx() {
 | 
			
		||||
        return ctx;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final Solver getSolver() {
 | 
			
		||||
        return solver;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void pushWrapper() {
 | 
			
		||||
        push();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void popWrapper(int number) {
 | 
			
		||||
        pop(number);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void finWrapper() {
 | 
			
		||||
        fin();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void eqWrapper(long lx, long ly) {
 | 
			
		||||
        Expr x = new Expr(ctx, lx);
 | 
			
		||||
        Expr y = new Expr(ctx, ly);
 | 
			
		||||
        eq(x, y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final UserPropagatorBase freshWrapper(long lctx) {
 | 
			
		||||
        return fresh(new Context(lctx));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void createdWrapper(long last) {
 | 
			
		||||
        created(new Expr(ctx, last));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected final void fixedWrapper(long lvar, long lvalue) {
 | 
			
		||||
        Expr var = new Expr(ctx, lvar);
 | 
			
		||||
        Expr value = new Expr(ctx, lvalue);
 | 
			
		||||
        fixed(var, value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public abstract void push();
 | 
			
		||||
 | 
			
		||||
    public abstract void pop(int number);
 | 
			
		||||
 | 
			
		||||
    public abstract UserPropagatorBase fresh(Context ctx);
 | 
			
		||||
 | 
			
		||||
    public <R extends Sort> void created(Expr<R> ast) {}
 | 
			
		||||
 | 
			
		||||
    public <R extends Sort> void fixed(Expr<R> var, Expr<R> value) {}
 | 
			
		||||
 | 
			
		||||
    public <R extends Sort> void eq(Expr<R> x, Expr<R> y) {}
 | 
			
		||||
 | 
			
		||||
    public void fin() {}
 | 
			
		||||
 | 
			
		||||
    public final <R extends Sort> void add(Expr<R> expr) {
 | 
			
		||||
        Native.propagateAdd(this, ctx.nCtx(), solver.getNativeObject(), javainfo, expr.getNativeObject());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final <R extends Sort> void conflict(Expr<R>[] fixed) {
 | 
			
		||||
        conflict(fixed, new Expr[0], new Expr[0]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final <R extends Sort> void conflict(Expr<R>[] fixed, Expr<R>[] lhs, Expr<R>[] rhs) {
 | 
			
		||||
        AST conseq = ctx.mkBool(false);
 | 
			
		||||
        Native.propagateConflict(
 | 
			
		||||
            this, ctx.nCtx(), solver.getNativeObject(), javainfo,
 | 
			
		||||
            fixed.length, AST.arrayToNative(fixed), lhs.length, AST.arrayToNative(lhs), AST.arrayToNative(rhs), conseq.getNativeObject());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public final <R extends Sort> void nextSplit(Expr<R> e, long idx, Z3_lbool phase) {
 | 
			
		||||
        Native.propagateNextSplit(
 | 
			
		||||
            this, ctx.nCtx(), solver.getNativeObject(), javainfo,
 | 
			
		||||
            e.getNativeObject(), idx, phase.toInt());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								src/api/js/examples/high-level/using_smtlib2.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/api/js/examples/high-level/using_smtlib2.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
// @ts-ignore we're not going to bother with types for this
 | 
			
		||||
import process from 'process';
 | 
			
		||||
import { init } from '../../build/node';
 | 
			
		||||
import assert from 'assert';
 | 
			
		||||
 | 
			
		||||
(async () => {
 | 
			
		||||
  let { Context, em } = await init();
 | 
			
		||||
  let z3 = Context('main');
 | 
			
		||||
 | 
			
		||||
  const x = z3.BitVec.const('x', 256);
 | 
			
		||||
  const y = z3.BitVec.const('y', 256);
 | 
			
		||||
  const z = z3.BitVec.const('z', 256);
 | 
			
		||||
  const xPlusY = x.add(y);
 | 
			
		||||
  const xPlusZ = x.add(z);
 | 
			
		||||
  const expr = xPlusY.mul(xPlusZ);
 | 
			
		||||
 | 
			
		||||
  const to_check = expr.eq(z3.Const('test', expr.sort));
 | 
			
		||||
 | 
			
		||||
  const solver = new z3.Solver();
 | 
			
		||||
  solver.add(to_check);
 | 
			
		||||
  const cr = await solver.check();
 | 
			
		||||
  console.log(cr);
 | 
			
		||||
  assert(cr === 'sat');
 | 
			
		||||
 | 
			
		||||
  const model = solver.model();
 | 
			
		||||
  let modelStr = model.sexpr();
 | 
			
		||||
  modelStr = modelStr.replace(/\n/g, ' ');
 | 
			
		||||
  console.log("Model: ", modelStr);
 | 
			
		||||
 | 
			
		||||
  const exprs = z3.ast_from_string(modelStr);
 | 
			
		||||
  console.log(exprs);
 | 
			
		||||
 | 
			
		||||
})().catch(e => {
 | 
			
		||||
  console.error('error', e);
 | 
			
		||||
  process.exit(1);
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,4 @@
 | 
			
		|||
// @ts-ignore we're not going to bother with types for this
 | 
			
		||||
import process from 'process';
 | 
			
		||||
import { init, Z3_error_code } from '../../build/node';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										44
									
								
								src/api/js/package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										44
									
								
								src/api/js/package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -4461,14 +4461,14 @@
 | 
			
		|||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "shiki": {
 | 
			
		||||
      "version": "0.10.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz",
 | 
			
		||||
      "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==",
 | 
			
		||||
      "version": "0.11.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz",
 | 
			
		||||
      "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "jsonc-parser": "^3.0.0",
 | 
			
		||||
        "vscode-oniguruma": "^1.6.1",
 | 
			
		||||
        "vscode-textmate": "5.2.0"
 | 
			
		||||
        "vscode-textmate": "^6.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "side-channel": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4826,16 +4826,15 @@
 | 
			
		|||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "typedoc": {
 | 
			
		||||
      "version": "0.22.18",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.18.tgz",
 | 
			
		||||
      "integrity": "sha512-NK9RlLhRUGMvc6Rw5USEYgT4DVAUFk7IF7Q6MYfpJ88KnTZP7EneEa4RcP+tX1auAcz7QT1Iy0bUSZBYYHdoyA==",
 | 
			
		||||
      "version": "0.23.16",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.16.tgz",
 | 
			
		||||
      "integrity": "sha512-rumYsCeNRXlyuZVzefD7050n7ptL2uudsCJg50dY0v/stKniqIlRpvx/F/6expC0/Q6Dbab+g/JpZuB7Sw90FA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "glob": "^8.0.3",
 | 
			
		||||
        "lunr": "^2.3.9",
 | 
			
		||||
        "marked": "^4.0.16",
 | 
			
		||||
        "marked": "^4.0.19",
 | 
			
		||||
        "minimatch": "^5.1.0",
 | 
			
		||||
        "shiki": "^0.10.1"
 | 
			
		||||
        "shiki": "^0.11.1"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "brace-expansion": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4847,19 +4846,6 @@
 | 
			
		|||
            "balanced-match": "^1.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "glob": {
 | 
			
		||||
          "version": "8.0.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
 | 
			
		||||
          "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "fs.realpath": "^1.0.0",
 | 
			
		||||
            "inflight": "^1.0.4",
 | 
			
		||||
            "inherits": "2",
 | 
			
		||||
            "minimatch": "^5.0.1",
 | 
			
		||||
            "once": "^1.3.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "minimatch": {
 | 
			
		||||
          "version": "5.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4872,9 +4858,9 @@
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "typescript": {
 | 
			
		||||
      "version": "4.5.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
 | 
			
		||||
      "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
 | 
			
		||||
      "version": "4.8.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
 | 
			
		||||
      "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "typical": {
 | 
			
		||||
| 
						 | 
				
			
			@ -4945,9 +4931,9 @@
 | 
			
		|||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "vscode-textmate": {
 | 
			
		||||
      "version": "5.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==",
 | 
			
		||||
      "version": "6.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "walker": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "z3-solver",
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "Z3",
 | 
			
		||||
    "theorem",
 | 
			
		||||
| 
						 | 
				
			
			@ -26,8 +27,8 @@
 | 
			
		|||
    "build:ts:generate": "ts-node --transpileOnly scripts/make-ts-wrapper.ts src/low-level/wrapper.__GENERATED__.ts src/low-level/types.__GENERATED__.ts",
 | 
			
		||||
    "build:wasm": "ts-node --transpileOnly ./scripts/build-wasm.ts",
 | 
			
		||||
    "clean": "rimraf build 'src/**/*.__GENERATED__.*'",
 | 
			
		||||
    "lint": "prettier -c '{,src/,scripts/,examples}*.{js,ts}'",
 | 
			
		||||
    "format": "prettier --write '{,src/,scripts/}*.{js,ts}'",
 | 
			
		||||
    "lint": "prettier -c '{./,src/,scripts/,examples/}**/*.{js,ts}'",
 | 
			
		||||
    "format": "prettier --write '{./,src/,scripts/}**/*.{js,ts}'",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
    "docs": "typedoc",
 | 
			
		||||
    "check-engine": "check-engine"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,8 +54,8 @@
 | 
			
		|||
    "ts-expect": "^1.3.0",
 | 
			
		||||
    "ts-jest": "^28.0.3",
 | 
			
		||||
    "ts-node": "^10.8.0",
 | 
			
		||||
    "typedoc": "^0.22.17",
 | 
			
		||||
    "typescript": "^4.5.4"
 | 
			
		||||
    "typedoc": "^0.23.16",
 | 
			
		||||
    "typescript": "^4.8.4"
 | 
			
		||||
  },
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ function spawnSync(command: string, opts: SpawnOptions = {}) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
function exportedFuncs(): string[] {
 | 
			
		||||
  const extras = ['_set_throwy_error_handler', '_set_noop_error_handler', ...asyncFuncs.map(f => '_async_' + f)];
 | 
			
		||||
  const extras = ['_malloc', '_set_throwy_error_handler', '_set_noop_error_handler', ...asyncFuncs.map(f => '_async_' + f)];
 | 
			
		||||
 | 
			
		||||
  // TODO(ritave): This variable is unused in original script, find out if it's important
 | 
			
		||||
  const fns: any[] = (functions as any[]).filter(f => !asyncFuncs.includes(f.name));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,6 +76,7 @@ function makeTsWrapper() {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  const isInParam = (p: FuncParam) => p.kind !== undefined && ['in', 'in_array'].includes(p.kind);
 | 
			
		||||
 | 
			
		||||
  function wrapFunction(fn: Func) {
 | 
			
		||||
    if (CUSTOM_IMPLEMENTATIONS.includes(fn.name)) {
 | 
			
		||||
      return null;
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +105,7 @@ function makeTsWrapper() {
 | 
			
		|||
 | 
			
		||||
    let isAsync = asyncFuncs.includes(fn.name);
 | 
			
		||||
    let trivial =
 | 
			
		||||
      !['string', 'boolean'].includes(fn.ret) &&
 | 
			
		||||
      !['string', 'boolean', 'unsigned'].includes(fn.ret) &&
 | 
			
		||||
      !fn.nullableRet &&
 | 
			
		||||
      outParams.length === 0 &&
 | 
			
		||||
      !inParams.some(p => p.type === 'string' || p.isArray || p.nullable);
 | 
			
		||||
| 
						 | 
				
			
			@ -234,6 +235,7 @@ function makeTsWrapper() {
 | 
			
		|||
          function setArg() {
 | 
			
		||||
            args[outParam.idx] = memIdx === 0 ? 'outAddress' : `outAddress + ${memIdx * 4}`;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          let read, type;
 | 
			
		||||
          if (outParam.type === 'string') {
 | 
			
		||||
            read = `Mod.UTF8ToString(getOutUint(${memIdx}))`;
 | 
			
		||||
| 
						 | 
				
			
			@ -330,11 +332,15 @@ function makeTsWrapper() {
 | 
			
		|||
      if (ret === 0) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
    `.trim();
 | 
			
		||||
      `.trim();
 | 
			
		||||
    } else if (fn.ret === 'unsigned') {
 | 
			
		||||
      infix += `
 | 
			
		||||
      ret = (new Uint32Array([ret]))[0];
 | 
			
		||||
      `.trim();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // prettier-ignore
 | 
			
		||||
    let invocation = `Mod.ccall('${isAsync ? 'async_' : ''}${fn.name}', '${cReturnType}', ${JSON.stringify(ctypes)}, [${args.map(toEm).join(', ')}])`;
 | 
			
		||||
    let invocation = `Mod.ccall('${isAsync ? "async_" : ""}${fn.name}', '${cReturnType}', ${JSON.stringify(ctypes)}, [${args.map(toEm).join(", ")}])`;
 | 
			
		||||
 | 
			
		||||
    if (isAsync) {
 | 
			
		||||
      invocation = `await Mod.async_call(() => ${invocation})`;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ 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 
 | 
			
		||||
  // 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',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
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";
 | 
			
		||||
import { Arith, Bool, Model, Quantifier, Z3AssertionError, Z3HighLevel, AstVector } from './types';
 | 
			
		||||
import { expectType } from 'ts-expect';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generate all possible solutions from given assumptions.
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +58,7 @@ async function* allSolutions<Name extends string>(...assertions: Bool<Name>[]):
 | 
			
		|||
 | 
			
		||||
async function prove(conjecture: Bool): Promise<void> {
 | 
			
		||||
  const solver = new conjecture.ctx.Solver();
 | 
			
		||||
  solver.set('timeout', 1000);
 | 
			
		||||
  const { Not } = solver.ctx;
 | 
			
		||||
  solver.add(Not(conjecture));
 | 
			
		||||
  expect(await solver.check()).toStrictEqual('unsat');
 | 
			
		||||
| 
						 | 
				
			
			@ -113,11 +114,11 @@ describe('high-level', () => {
 | 
			
		|||
  it('test loading a solver state from a string', async () => {
 | 
			
		||||
    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')
 | 
			
		||||
    const x = Int.const('x')
 | 
			
		||||
    solver.add(Not(x.eq(1)))
 | 
			
		||||
    expect(await solver.check()).toStrictEqual('unsat')
 | 
			
		||||
    solver.fromString('(declare-const x Int) (assert (and (< x 2) (> x 0)))');
 | 
			
		||||
    expect(await solver.check()).toStrictEqual('sat');
 | 
			
		||||
    const x = Int.const('x');
 | 
			
		||||
    solver.add(Not(x.eq(1)));
 | 
			
		||||
    expect(await solver.check()).toStrictEqual('unsat');
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('disproves x = y implies g(g(x)) = g(y)', async () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -393,14 +394,13 @@ 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));
 | 
			
		||||
      const conjecture = arr.store(idx, val).select(idx).eq(val);
 | 
			
		||||
      await prove(conjecture);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -428,7 +428,7 @@ describe('high-level', () => {
 | 
			
		|||
      // 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');
 | 
			
		||||
| 
						 | 
				
			
			@ -447,13 +447,6 @@ describe('high-level', () => {
 | 
			
		|||
      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 () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -465,18 +458,16 @@ describe('high-level', () => {
 | 
			
		|||
      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)
 | 
			
		||||
      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))
 | 
			
		||||
        );
 | 
			
		||||
        .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))
 | 
			
		||||
      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)));
 | 
			
		||||
| 
						 | 
				
			
			@ -485,11 +476,105 @@ describe('high-level', () => {
 | 
			
		|||
 | 
			
		||||
      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);
 | 
			
		||||
      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]);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Array type inference', async () => {
 | 
			
		||||
      const z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const Z3_ADDR = z3.BitVec.const('Vault_addr', 160);
 | 
			
		||||
      const Z3_GLOBAL_STORAGE = z3.Array.const(
 | 
			
		||||
        'global_storage',
 | 
			
		||||
        z3.BitVec.sort(160),
 | 
			
		||||
        z3.Array.sort(z3.BitVec.sort(160), z3.BitVec.sort(256)),
 | 
			
		||||
      );
 | 
			
		||||
      const Z3_STORAGE = Z3_GLOBAL_STORAGE.select(Z3_ADDR);
 | 
			
		||||
 | 
			
		||||
      // We are so far unable to properly infer the type of Z3_STORAGE
 | 
			
		||||
      // expectType<
 | 
			
		||||
      //   SMTArray<'main', [BitVecSort<160>], BitVecSort<256>>
 | 
			
		||||
      // >(Z3_STORAGE);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('quantifiers', () => {
 | 
			
		||||
    it('Basic Universal', async () => {
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const [x, y] = Z3.Int.consts('x y');
 | 
			
		||||
 | 
			
		||||
      const conjecture = Z3.ForAll([x, y], x.neq(y).implies(x.lt(y).or(x.gt(y))));
 | 
			
		||||
      expect(Z3.isBool(conjecture)).toBeTruthy();
 | 
			
		||||
      expect(conjecture.var_name(0)).toBe('x');
 | 
			
		||||
      expect(conjecture.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
 | 
			
		||||
      expect(conjecture.var_name(1)).toBe('y');
 | 
			
		||||
      expect(conjecture.var_sort(1).eqIdentity(Z3.Int.sort())).toBeTruthy();
 | 
			
		||||
      await prove(conjecture);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Basic Existential', async () => {
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const [x, y, z] = Z3.Int.consts('x y z');
 | 
			
		||||
 | 
			
		||||
      const quantifier = Z3.Exists([z], Z3.Not(z.lt(x)).and(Z3.Not(z.gt(y))));
 | 
			
		||||
      expect(Z3.isBool(quantifier)).toBeTruthy();
 | 
			
		||||
      expect(quantifier.var_name(0)).toBe('z');
 | 
			
		||||
      expect(quantifier.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
      const conjecture = Z3.Not(x.gt(y)).implies(quantifier); // Can be trivially discovered with z = x or x = y
 | 
			
		||||
      await prove(conjecture);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Basic Lambda', async () => {
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const [x, y] = Z3.Int.consts('x y z');
 | 
			
		||||
      const L = Z3.Lambda([x, y], x.add(y));
 | 
			
		||||
      expect(Z3.isArraySort(L.sort)).toBeTruthy();
 | 
			
		||||
      expect(Z3.isArray(L)).toBeFalsy();
 | 
			
		||||
      expect(L.var_name(0)).toBe('x');
 | 
			
		||||
      expect(L.var_sort(0).eqIdentity(Z3.Int.sort())).toBeTruthy();
 | 
			
		||||
      expect(L.var_name(1)).toBe('y');
 | 
			
		||||
      expect(L.var_sort(1).eqIdentity(Z3.Int.sort())).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
      const conjecture = L.select(Z3.Int.val(2), Z3.Int.val(5)).eq(Z3.Int.val(7));
 | 
			
		||||
      await prove(conjecture);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Loading Quantifier Preserves Type', async () => {
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const [x, y, z] = Z3.Int.consts('x y z');
 | 
			
		||||
      const quantifier = Z3.Exists([z], Z3.Not(z.lt(x)).and(Z3.Not(z.gt(y))));
 | 
			
		||||
      expect(Z3.isBool(quantifier)).toBeTruthy();
 | 
			
		||||
 | 
			
		||||
      const solver = new Z3.Solver();
 | 
			
		||||
      solver.add(quantifier);
 | 
			
		||||
 | 
			
		||||
      const dumped_str = solver.toString();
 | 
			
		||||
 | 
			
		||||
      const solver2 = new Z3.Solver();
 | 
			
		||||
      solver2.fromString(dumped_str);
 | 
			
		||||
      const quantifier2 = solver2.assertions().get(0) as unknown as Quantifier;
 | 
			
		||||
      expect(Z3.isBool(quantifier2)).toBeTruthy();
 | 
			
		||||
      expect(quantifier2.var_name(0)).toBe('z');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('uninterpreted functions', () => {
 | 
			
		||||
    it('Type Inference', async () => {
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const f = Z3.Function.declare('f', Z3.Int.sort(), Z3.Bool.sort());
 | 
			
		||||
      const input = Z3.Int.val(6);
 | 
			
		||||
      const output = f.call(input);
 | 
			
		||||
      expectType<Bool>(output);
 | 
			
		||||
      expect(output.sort.eqIdentity(Z3.Bool.sort())).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Solver', () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -543,10 +628,11 @@ describe('high-level', () => {
 | 
			
		|||
 | 
			
		||||
  describe('AstVector', () => {
 | 
			
		||||
    it('can use basic methods', async () => {
 | 
			
		||||
      const { Solver, AstVector, Int } = api.Context('main');
 | 
			
		||||
      const Z3 = api.Context('main');
 | 
			
		||||
      const { Solver, Int } = Z3;
 | 
			
		||||
      const solver = new Solver();
 | 
			
		||||
 | 
			
		||||
      const vector = new AstVector<Arith>();
 | 
			
		||||
      const vector = new Z3.AstVector<Arith>();
 | 
			
		||||
      for (let i = 0; i < 5; i++) {
 | 
			
		||||
        vector.push(Int.const(`int__${i}`));
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -559,4 +645,104 @@ describe('high-level', () => {
 | 
			
		|||
      expect(await solver.check()).toStrictEqual('sat');
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Substitution', () => {
 | 
			
		||||
    it('basic variable substitution', async () => {
 | 
			
		||||
      const { Int, substitute } = api.Context('main');
 | 
			
		||||
      const x = Int.const('x');
 | 
			
		||||
      const y = Int.const('y');
 | 
			
		||||
      const z = Int.const('z');
 | 
			
		||||
 | 
			
		||||
      const expr = x.add(y);
 | 
			
		||||
      const subst = substitute(expr, [x, z]);
 | 
			
		||||
      expect(subst.eqIdentity(z.add(y))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('term substitution', async () => {
 | 
			
		||||
      const { Int, substitute } = api.Context('main');
 | 
			
		||||
      const x = Int.const('x');
 | 
			
		||||
      const y = Int.const('y');
 | 
			
		||||
      const z = Int.const('z');
 | 
			
		||||
 | 
			
		||||
      const expr = x.add(y).mul(Int.val(1).sub(x.add(y)));
 | 
			
		||||
      const subst = substitute(expr, [x.add(y), z]);
 | 
			
		||||
      expect(subst.eqIdentity(z.mul(Int.val(1).sub(z)))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Model', () => {
 | 
			
		||||
    it('Assigning constants', async () => {
 | 
			
		||||
      const { Int, Model } = api.Context('main');
 | 
			
		||||
      const m = new Model();
 | 
			
		||||
 | 
			
		||||
      const [x, y] = Int.consts('x y');
 | 
			
		||||
 | 
			
		||||
      m.updateValue(x, Int.val(6));
 | 
			
		||||
      m.updateValue(y, Int.val(12));
 | 
			
		||||
 | 
			
		||||
      expect(m.eval(x.add(y)).eqIdentity(Int.val(18))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Creating Func Interpretations', async () => {
 | 
			
		||||
      const { Int, Function, Model } = api.Context('main');
 | 
			
		||||
      const m = new Model();
 | 
			
		||||
 | 
			
		||||
      const f = Function.declare('f', Int.sort(), Int.sort(), Int.sort());
 | 
			
		||||
 | 
			
		||||
      const f_interp = m.addFuncInterp(f, 0);
 | 
			
		||||
      f_interp.addEntry([Int.val(1), Int.val(2)], Int.val(3));
 | 
			
		||||
      f_interp.addEntry([Int.val(4), Int.val(5)], Int.val(6));
 | 
			
		||||
 | 
			
		||||
      expect(m.eval(f.call(1, 2)).eqIdentity(Int.val(3))).toBeTruthy();
 | 
			
		||||
      expect(m.eval(f.call(4, 5)).eqIdentity(Int.val(6))).toBeTruthy();
 | 
			
		||||
      expect(m.eval(f.call(0, 0)).eqIdentity(Int.val(0))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('optimize', () => {
 | 
			
		||||
    it("maximization problem over reals", async () => {
 | 
			
		||||
      const { Real, Optimize } = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const opt = new Optimize();
 | 
			
		||||
      const x = Real.const('x');
 | 
			
		||||
      const y = Real.const('y');
 | 
			
		||||
      const z = Real.const('z');
 | 
			
		||||
 | 
			
		||||
      opt.add(x.ge(0), y.ge(0), z.ge(0));
 | 
			
		||||
      opt.add(x.le(1), y.le(1), z.le(1));
 | 
			
		||||
      opt.maximize(x.mul(7).add(y.mul(9)).sub(z.mul(3)))
 | 
			
		||||
 | 
			
		||||
      const result = await opt.check()
 | 
			
		||||
      expect(result).toStrictEqual('sat');
 | 
			
		||||
      const model = opt.model();
 | 
			
		||||
      expect(model.eval(x).eqIdentity(Real.val(1))).toBeTruthy();
 | 
			
		||||
      expect(model.eval(y).eqIdentity(Real.val(1))).toBeTruthy();
 | 
			
		||||
      expect(model.eval(z).eqIdentity(Real.val(0))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("minimization problem over integers using addSoft", async () => {
 | 
			
		||||
      const { Int, Optimize } = api.Context('main');
 | 
			
		||||
 | 
			
		||||
      const opt = new Optimize();
 | 
			
		||||
      const x = Int.const('x');
 | 
			
		||||
      const y = Int.const('y');
 | 
			
		||||
      const z = Int.const('z');
 | 
			
		||||
 | 
			
		||||
      opt.add(x.ge(0), y.ge(0));
 | 
			
		||||
      opt.add(x.le(1), y.le(1));
 | 
			
		||||
      opt.addSoft(x.eq(1), 2);
 | 
			
		||||
      opt.addSoft(y.eq(1), 1);
 | 
			
		||||
      opt.add(z.eq(x.mul(5).add(y.mul(5))));
 | 
			
		||||
      opt.add(z.le(5));
 | 
			
		||||
      opt.minimize(z);
 | 
			
		||||
 | 
			
		||||
      const result = await opt.check()
 | 
			
		||||
      expect(result).toStrictEqual('sat');
 | 
			
		||||
      const model = opt.model();
 | 
			
		||||
      expect(model.eval(x).eqIdentity(Int.val(1))).toBeTruthy();
 | 
			
		||||
      expect(model.eval(y).eqIdentity(Int.val(0))).toBeTruthy();
 | 
			
		||||
      expect(model.eval(z).eqIdentity(Int.val(5))).toBeTruthy();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -5,13 +5,14 @@ import {
 | 
			
		|||
  Z3_context,
 | 
			
		||||
  Z3_decl_kind,
 | 
			
		||||
  Z3_func_decl,
 | 
			
		||||
  Z3_func_entry,
 | 
			
		||||
  Z3_func_interp,
 | 
			
		||||
  Z3_model,
 | 
			
		||||
  Z3_probe,
 | 
			
		||||
  Z3_solver,
 | 
			
		||||
  Z3_optimize,
 | 
			
		||||
  Z3_sort,
 | 
			
		||||
  Z3_sort_kind,
 | 
			
		||||
  Z3_symbol,
 | 
			
		||||
  Z3_tactic,
 | 
			
		||||
} from '../low-level';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +22,7 @@ export type AnySort<Name extends string = 'main'> =
 | 
			
		|||
  | BoolSort<Name>
 | 
			
		||||
  | ArithSort<Name>
 | 
			
		||||
  | BitVecSort<number, Name>
 | 
			
		||||
  | SMTArraySort<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
 | 
			
		||||
  | SMTArraySort<Name>;
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type AnyExpr<Name extends string = 'main'> =
 | 
			
		||||
  | Expr<Name>
 | 
			
		||||
| 
						 | 
				
			
			@ -31,53 +32,64 @@ export type AnyExpr<Name extends string = 'main'> =
 | 
			
		|||
  | RatNum<Name>
 | 
			
		||||
  | BitVec<number, Name>
 | 
			
		||||
  | BitVecNum<number, Name>
 | 
			
		||||
  | SMTArray<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
 | 
			
		||||
  | SMTArray<Name>;
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type AnyAst<Name extends string = 'main'> = AnyExpr<Name> | AnySort<Name> | FuncDecl<Name>;
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type SortToExprMap<S extends AnySort<Name>, Name extends string = 'main'> =
 | 
			
		||||
  S extends BoolSort
 | 
			
		||||
    ? Bool<Name>
 | 
			
		||||
    : S extends ArithSort<Name>
 | 
			
		||||
      ? Arith<Name>
 | 
			
		||||
      : S extends BitVecSort<infer Size, Name>
 | 
			
		||||
        ? BitVec<Size, Name>
 | 
			
		||||
        : S extends SMTArraySort<Name, infer DomainSort, infer RangeSort>
 | 
			
		||||
          ? SMTArray<Name, DomainSort, RangeSort>
 | 
			
		||||
          : S extends Sort<Name>
 | 
			
		||||
            ? Expr<Name, S, Z3_ast>
 | 
			
		||||
            : never;
 | 
			
		||||
export type SortToExprMap<S extends AnySort<Name>, Name extends string = 'main'> = S extends BoolSort
 | 
			
		||||
  ? Bool<Name>
 | 
			
		||||
  : S extends ArithSort<Name>
 | 
			
		||||
  ? Arith<Name>
 | 
			
		||||
  : S extends BitVecSort<infer Size, Name>
 | 
			
		||||
  ? BitVec<Size, Name>
 | 
			
		||||
  : S extends SMTArraySort<Name, infer DomainSort, infer RangeSort>
 | 
			
		||||
  ? SMTArray<Name, DomainSort, RangeSort>
 | 
			
		||||
  : S extends Sort<Name>
 | 
			
		||||
  ? Expr<Name, S, Z3_ast>
 | 
			
		||||
  : never;
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToExprMap<S extends CoercibleToExpr<Name>, Name extends string = 'main'> =
 | 
			
		||||
  S extends bigint
 | 
			
		||||
    ? ArithSort<Name>
 | 
			
		||||
    : S extends number | CoercibleRational
 | 
			
		||||
      ? RatNum<Name>
 | 
			
		||||
      : S extends boolean
 | 
			
		||||
        ? Bool<Name>
 | 
			
		||||
        : S extends Expr<Name>
 | 
			
		||||
          ? S
 | 
			
		||||
          : never;
 | 
			
		||||
export type CoercibleFromMap<S extends CoercibleToExpr<Name>, Name extends string = 'main'> = S extends bigint
 | 
			
		||||
  ? Arith<Name>
 | 
			
		||||
  : S extends number | CoercibleRational
 | 
			
		||||
  ? RatNum<Name>
 | 
			
		||||
  : S extends boolean
 | 
			
		||||
  ? Bool<Name>
 | 
			
		||||
  : S extends Expr<Name>
 | 
			
		||||
  ? S
 | 
			
		||||
  : never;
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleFromMap<S extends AnyExpr<Name>, Name extends string = 'main'> =
 | 
			
		||||
  S extends Bool<Name>
 | 
			
		||||
    ? (boolean | Bool<Name>)
 | 
			
		||||
    : S extends IntNum<Name>
 | 
			
		||||
      ? (bigint | number | IntNum<Name>)
 | 
			
		||||
      : S extends RatNum<Name>
 | 
			
		||||
        ? (bigint | number | CoercibleRational | RatNum<Name>)
 | 
			
		||||
        : S extends Arith<Name>
 | 
			
		||||
          ? (bigint | number | CoercibleRational | Arith<Name>)
 | 
			
		||||
          : S extends BitVec<infer Size, Name>
 | 
			
		||||
            ? (number | BitVec<Size, Name>)
 | 
			
		||||
            : S extends SMTArray<Name, infer DomainSort, infer RangeSort>
 | 
			
		||||
              ? SMTArray<Name, DomainSort, RangeSort>
 | 
			
		||||
              : S extends Expr<Name>
 | 
			
		||||
                ? Expr<Name>
 | 
			
		||||
                : never;
 | 
			
		||||
export type CoercibleToBitVec<Bits extends number = number, Name extends string = 'main'> =
 | 
			
		||||
  | bigint
 | 
			
		||||
  | number
 | 
			
		||||
  | BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number };
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToExpr<Name extends string = 'main'> = number | bigint | boolean | CoercibleRational | Expr<Name>;
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToArith<Name extends string = 'main'> = number | string | bigint | CoercibleRational | Arith<Name>;
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToMap<T extends AnyExpr<Name>, Name extends string = 'main'> = T extends Bool<Name>
 | 
			
		||||
  ? boolean | Bool<Name>
 | 
			
		||||
  : T extends IntNum<Name>
 | 
			
		||||
  ? bigint | number | IntNum<Name>
 | 
			
		||||
  : T extends RatNum<Name>
 | 
			
		||||
  ? bigint | number | CoercibleRational | RatNum<Name>
 | 
			
		||||
  : T extends Arith<Name>
 | 
			
		||||
  ? CoercibleToArith<Name>
 | 
			
		||||
  : T extends BitVec<infer Size, Name>
 | 
			
		||||
  ? CoercibleToBitVec<Size, Name>
 | 
			
		||||
  : T extends SMTArray<Name, infer DomainSort, infer RangeSort>
 | 
			
		||||
  ? SMTArray<Name, DomainSort, RangeSort>
 | 
			
		||||
  : T extends Expr<Name>
 | 
			
		||||
  ? Expr<Name>
 | 
			
		||||
  : never;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Used to create a Real constant
 | 
			
		||||
| 
						 | 
				
			
			@ -97,16 +109,10 @@ export type CoercibleFromMap<S extends AnyExpr<Name>, Name extends string = 'mai
 | 
			
		|||
 * @see {@link Context.from}
 | 
			
		||||
 * @category Global
 | 
			
		||||
 */
 | 
			
		||||
export type CoercibleRational = { numerator: bigint | number; denominator: bigint | number };
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToExpr<Name extends string = 'main'> = number | bigint | boolean | CoercibleRational | Expr<Name>;
 | 
			
		||||
export class Z3Error extends Error {}
 | 
			
		||||
 | 
			
		||||
export class Z3Error extends Error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Z3AssertionError extends Z3Error {
 | 
			
		||||
}
 | 
			
		||||
export class Z3AssertionError extends Z3Error {}
 | 
			
		||||
 | 
			
		||||
/** @category Global */
 | 
			
		||||
export type CheckSatResult = 'sat' | 'unsat' | 'unknown';
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +155,9 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  /** @category Functions */
 | 
			
		||||
  isFuncDecl(obj: unknown): obj is FuncDecl<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isFuncInterp(obj: unknown): obj is FuncInterp<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isApp(obj: unknown): boolean;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -191,6 +200,9 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  /** @category Functions */
 | 
			
		||||
  isDistinct(obj: unknown): boolean;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isQuantifier(obj: unknown): obj is Quantifier<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isArith(obj: unknown): obj is Arith<Name>;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,10 +237,10 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  isBitVecVal(obj: unknown): obj is BitVecNum<number, Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isArraySort(obj: unknown): obj is SMTArraySort<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
 | 
			
		||||
  isArraySort(obj: unknown): obj is SMTArraySort<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isArray(obj: unknown): obj is SMTArray<Name, [AnySort<Name>, ...AnySort<Name>[]], AnySort<Name>>;
 | 
			
		||||
  isArray(obj: unknown): obj is SMTArray<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Functions */
 | 
			
		||||
  isConstArray(obj: unknown): boolean;
 | 
			
		||||
| 
						 | 
				
			
			@ -306,6 +318,9 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
   * @category Classes
 | 
			
		||||
   */
 | 
			
		||||
  readonly Solver: new (logic?: string) => Solver<Name>;
 | 
			
		||||
 | 
			
		||||
  readonly Optimize: new () => Optimize<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Creates an empty Model
 | 
			
		||||
   * @see {@link Solver.model} for common usage of Model
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +330,11 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  /** @category Classes */
 | 
			
		||||
  readonly AstVector: new <Item extends Ast<Name> = AnyAst<Name>>() => AstVector<Name, Item>;
 | 
			
		||||
  /** @category Classes */
 | 
			
		||||
  readonly AstMap: new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>() => AstMap<Name, Key, Value>;
 | 
			
		||||
  readonly AstMap: new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>() => AstMap<
 | 
			
		||||
    Name,
 | 
			
		||||
    Key,
 | 
			
		||||
    Value
 | 
			
		||||
  >;
 | 
			
		||||
  /** @category Classes */
 | 
			
		||||
  readonly Tactic: new (name: string) => Tactic<Name>;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -363,7 +382,7 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
    condition: Bool<Name> | boolean,
 | 
			
		||||
    onTrue: OnTrueRef,
 | 
			
		||||
    onFalse: OnFalseRef,
 | 
			
		||||
  ): CoercibleToExprMap<OnTrueRef | OnFalseRef, Name>;
 | 
			
		||||
  ): CoercibleFromMap<OnTrueRef | OnFalseRef, Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Distinct(...args: CoercibleToExpr<Name>[]): Bool<Name>;
 | 
			
		||||
| 
						 | 
				
			
			@ -371,6 +390,9 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  /** @category Operations */
 | 
			
		||||
  Implies(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Iff(a: Bool<Name> | boolean, b: Bool<Name> | boolean): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Eq(a: CoercibleToExpr<Name>, b: CoercibleToExpr<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -407,6 +429,28 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  /** @category Operations */
 | 
			
		||||
  Or(...args: Probe<Name>[]): Probe<Name>;
 | 
			
		||||
 | 
			
		||||
  // Quantifiers
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  ForAll<QVarSorts extends NonEmptySortArray<Name>>(
 | 
			
		||||
    quantifiers: ArrayIndexType<Name, QVarSorts>,
 | 
			
		||||
    body: Bool<Name>,
 | 
			
		||||
    weight?: number,
 | 
			
		||||
  ): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Exists<QVarSorts extends NonEmptySortArray<Name>>(
 | 
			
		||||
    quantifiers: ArrayIndexType<Name, QVarSorts>,
 | 
			
		||||
    body: Bool<Name>,
 | 
			
		||||
    weight?: number,
 | 
			
		||||
  ): Quantifier<Name, QVarSorts, BoolSort<Name>> & Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Lambda<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
 | 
			
		||||
    quantifiers: ArrayIndexType<Name, DomainSort>,
 | 
			
		||||
    expr: SortToExprMap<RangeSort, Name>,
 | 
			
		||||
  ): Quantifier<Name, DomainSort, SMTArraySort<Name, DomainSort, RangeSort>> & SMTArray<Name, DomainSort, RangeSort>;
 | 
			
		||||
 | 
			
		||||
  // Arithmetic
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  ToReal(expr: Arith<Name> | bigint): Arith<Name>;
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +481,7 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
   * // a**(1/2)
 | 
			
		||||
   * ```
 | 
			
		||||
   * @category Operations */
 | 
			
		||||
  Sqrt(a: Arith<Name> | number | bigint | string | CoercibleRational): Arith<Name>;
 | 
			
		||||
  Sqrt(a: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a Z3 expression representing cubic root of a
 | 
			
		||||
| 
						 | 
				
			
			@ -449,7 +493,7 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
   * // a**(1/3)
 | 
			
		||||
   * ```
 | 
			
		||||
   * @category Operations */
 | 
			
		||||
  Cbrt(a: Arith<Name> | number | bigint | string | CoercibleRational): Arith<Name>;
 | 
			
		||||
  Cbrt(a: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  // Bit Vectors
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +506,102 @@ export interface Context<Name extends string = 'main'> {
 | 
			
		|||
  Concat(...bitvecs: BitVec<number, Name>[]): BitVec<number, Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Cond(probe: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>
 | 
			
		||||
  Cond(probe: Probe<Name>, onTrue: Tactic<Name>, onFalse: Tactic<Name>): Tactic<Name>;
 | 
			
		||||
 | 
			
		||||
  // Arith
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  LT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  GT(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  LE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  GE(a: Arith<Name>, b: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  // Bit Vectors
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  ULT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  UGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  ULE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  UGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  SLT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  SGT<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  SGE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  SLE<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Sum(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Sum<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  Sub(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Sub<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  Product(arg0: Arith<Name>, ...args: CoercibleToArith<Name>[]): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Product<Bits extends number>(arg0: BitVec<Bits, Name>, ...args: CoercibleToBitVec<Bits, Name>[]): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  Div(arg0: Arith<Name>, arg1: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Div<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  BUDiv<Bits extends number>(arg0: BitVec<Bits, Name>, arg1: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  Neg(a: Arith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Neg<Bits extends number>(a: BitVec<Bits, Name>): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  Mod(a: Arith<Name>, b: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  Mod<Bits extends number>(a: BitVec<Bits, Name>, b: CoercibleToBitVec<Bits, Name>): BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
  // Arrays
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Select<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(
 | 
			
		||||
    array: SMTArray<Name, DomainSort, RangeSort>,
 | 
			
		||||
    ...indices: CoercibleToArrayIndexType<Name, DomainSort>
 | 
			
		||||
  ): SortToExprMap<RangeSort, Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Store<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name> = Sort<Name>>(
 | 
			
		||||
    array: SMTArray<Name, DomainSort, RangeSort>,
 | 
			
		||||
    ...indicesAndValue: [
 | 
			
		||||
      ...CoercibleToArrayIndexType<Name, DomainSort>,
 | 
			
		||||
      CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
 | 
			
		||||
    ]
 | 
			
		||||
  ): SMTArray<Name, DomainSort, RangeSort>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  Extract<Bits extends number>(hi: number, lo: number, val: BitVec<Bits, Name>): BitVec<number, Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  ast_from_string(s: string): Ast<Name>;
 | 
			
		||||
 | 
			
		||||
  /** @category Operations */
 | 
			
		||||
  substitute(t: Expr<Name>, ...substitutions: [Expr<Name>, Expr<Name>][]): Expr<Name>;
 | 
			
		||||
 | 
			
		||||
  simplify(expr: Expr<Name>): Promise<Expr<Name>>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Ast<Name extends string = 'main', Ptr = unknown> {
 | 
			
		||||
| 
						 | 
				
			
			@ -490,7 +629,7 @@ export interface Ast<Name extends string = 'main', Ptr = unknown> {
 | 
			
		|||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export interface SolverCtor<Name extends string> {
 | 
			
		||||
  new(): Solver<Name>;
 | 
			
		||||
  new (): Solver<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Solver<Name extends string = 'main'> {
 | 
			
		||||
| 
						 | 
				
			
			@ -500,10 +639,11 @@ export interface Solver<Name extends string = 'main'> {
 | 
			
		|||
  readonly ctx: Context<Name>;
 | 
			
		||||
  readonly ptr: Z3_solver;
 | 
			
		||||
 | 
			
		||||
  /* TODO(ritave): Decide on how to discern between integer and float parameters
 | 
			
		||||
  set(key: string, value: any): void;
 | 
			
		||||
  set(params: Record<string, any>): void;
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  /* TODO(ritave): Decide on how to discern between integer and float parameters
 | 
			
		||||
      set(params: Record<string, any>): void;
 | 
			
		||||
      */
 | 
			
		||||
  push(): void;
 | 
			
		||||
 | 
			
		||||
  pop(num?: number): void;
 | 
			
		||||
| 
						 | 
				
			
			@ -525,9 +665,42 @@ export interface Solver<Name extends string = 'main'> {
 | 
			
		|||
  model(): Model<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Optimize<Name extends string = 'main'> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'Optimize';
 | 
			
		||||
 | 
			
		||||
  readonly ctx: Context<Name>;
 | 
			
		||||
  readonly ptr: Z3_optimize;
 | 
			
		||||
 | 
			
		||||
  set(key: string, value: any): void;
 | 
			
		||||
 | 
			
		||||
  push(): void;
 | 
			
		||||
 | 
			
		||||
  pop(num?: number): void;
 | 
			
		||||
 | 
			
		||||
  add(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): void;
 | 
			
		||||
 | 
			
		||||
  addSoft(expr: Bool<Name>, weight: number | bigint | string | CoercibleRational, id?: number | string): void;
 | 
			
		||||
 | 
			
		||||
  addAndTrack(expr: Bool<Name>, constant: Bool<Name> | string): void;
 | 
			
		||||
 | 
			
		||||
  assertions(): AstVector<Name, Bool<Name>>;
 | 
			
		||||
 | 
			
		||||
  fromString(s: string): void;
 | 
			
		||||
 | 
			
		||||
  maximize(expr: Arith<Name>): void;
 | 
			
		||||
 | 
			
		||||
  minimize(expr: Arith<Name>): void;
 | 
			
		||||
 | 
			
		||||
  check(...exprs: (Bool<Name> | AstVector<Name, Bool<Name>>)[]): Promise<CheckSatResult>;
 | 
			
		||||
 | 
			
		||||
  model(): Model<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export interface ModelCtor<Name extends string> {
 | 
			
		||||
  new(): Model<Name>;
 | 
			
		||||
  new (): Model<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Model<Name extends string = 'main'> extends Iterable<FuncDecl<Name>> {
 | 
			
		||||
| 
						 | 
				
			
			@ -566,6 +739,13 @@ export interface Model<Name extends string = 'main'> extends Iterable<FuncDecl<N
 | 
			
		|||
  get(constant: Expr<Name>): Expr<Name>;
 | 
			
		||||
 | 
			
		||||
  get(sort: Sort<Name>): AstVector<Name, AnyExpr<Name>>;
 | 
			
		||||
 | 
			
		||||
  updateValue(decl: FuncDecl<Name> | Expr<Name>, a: Ast<Name> | FuncInterp<Name>): void;
 | 
			
		||||
 | 
			
		||||
  addFuncInterp<DomainSort extends Sort<Name>[] = Sort<Name>[], RangeSort extends Sort<Name> = Sort<Name>>(
 | 
			
		||||
    decl: FuncDecl<Name, DomainSort, RangeSort>,
 | 
			
		||||
    defaultValue: CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
 | 
			
		||||
  ): FuncInterp<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -608,6 +788,23 @@ export interface Sort<Name extends string = 'main'> extends Ast<Name, Z3_sort> {
 | 
			
		|||
  name(): string | number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @category Functions
 | 
			
		||||
 */
 | 
			
		||||
export interface FuncEntry<Name extends string = 'main'> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'FuncEntry';
 | 
			
		||||
 | 
			
		||||
  readonly ctx: Context<Name>;
 | 
			
		||||
  readonly ptr: Z3_func_entry;
 | 
			
		||||
 | 
			
		||||
  numArgs(): number;
 | 
			
		||||
 | 
			
		||||
  argValue(i: number): Expr<Name>;
 | 
			
		||||
 | 
			
		||||
  value(): Expr<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @category Functions
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -617,6 +814,16 @@ export interface FuncInterp<Name extends string = 'main'> {
 | 
			
		|||
 | 
			
		||||
  readonly ctx: Context<Name>;
 | 
			
		||||
  readonly ptr: Z3_func_interp;
 | 
			
		||||
 | 
			
		||||
  elseValue(): Expr<Name>;
 | 
			
		||||
 | 
			
		||||
  numEntries(): number;
 | 
			
		||||
 | 
			
		||||
  arity(): number;
 | 
			
		||||
 | 
			
		||||
  entry(i: number): FuncEntry<Name>;
 | 
			
		||||
 | 
			
		||||
  addEntry(args: Expr<Name>[], value: Expr<Name>): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
| 
						 | 
				
			
			@ -639,9 +846,14 @@ export interface FuncDeclCreation<Name extends string> {
 | 
			
		|||
   * @param name Name of the function
 | 
			
		||||
   * @param signature The domains, and last parameter - the range of the function
 | 
			
		||||
   */
 | 
			
		||||
  declare(name: string, ...signature: FuncDeclSignature<Name>): FuncDecl<Name>;
 | 
			
		||||
  declare<DomainSort extends Sort<Name>[], RangeSort extends Sort<Name>>(
 | 
			
		||||
    name: string,
 | 
			
		||||
    ...signature: [...DomainSort, RangeSort]
 | 
			
		||||
  ): FuncDecl<Name, DomainSort, RangeSort>;
 | 
			
		||||
 | 
			
		||||
  fresh(...signature: FuncDeclSignature<Name>): FuncDecl<Name>;
 | 
			
		||||
  fresh<DomainSort extends Sort<Name>[], RangeSort extends Sort<Name>>(
 | 
			
		||||
    ...signature: [...DomainSort, RangeSort]
 | 
			
		||||
  ): FuncDecl<Name, DomainSort, RangeSort>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -656,7 +868,11 @@ export interface RecFuncCreation<Name extends string> {
 | 
			
		|||
/**
 | 
			
		||||
 * @category Functions
 | 
			
		||||
 */
 | 
			
		||||
export interface FuncDecl<Name extends string = 'main'> extends Ast<Name, Z3_func_decl> {
 | 
			
		||||
export interface FuncDecl<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  DomainSort extends Sort<Name>[] = Sort<Name>[],
 | 
			
		||||
  RangeSort extends Sort<Name> = Sort<Name>,
 | 
			
		||||
> extends Ast<Name, Z3_func_decl> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'FuncDecl';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -664,21 +880,26 @@ export interface FuncDecl<Name extends string = 'main'> extends Ast<Name, Z3_fun
 | 
			
		|||
 | 
			
		||||
  arity(): number;
 | 
			
		||||
 | 
			
		||||
  domain(i: number): Sort<Name>;
 | 
			
		||||
  domain<T extends number>(i: T): DomainSort[T];
 | 
			
		||||
 | 
			
		||||
  range(): Sort<Name>;
 | 
			
		||||
  range(): RangeSort;
 | 
			
		||||
 | 
			
		||||
  kind(): Z3_decl_kind;
 | 
			
		||||
 | 
			
		||||
  params(): (number | string | Z3_symbol | Sort<Name> | Expr<Name> | FuncDecl<Name>)[];
 | 
			
		||||
  params(): (number | string | Sort<Name> | Expr<Name> | FuncDecl<Name>)[];
 | 
			
		||||
 | 
			
		||||
  call(...args: CoercibleToExpr<Name>[]): AnyExpr<Name>;
 | 
			
		||||
  call(...args: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySort<Name>, Ptr = unknown>
 | 
			
		||||
  extends Ast<Name, Ptr> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'Expr' | Bool['__typename'] | Arith['__typename'] | BitVec['__typename'] | SMTArray['__typename'];
 | 
			
		||||
  readonly __typename:
 | 
			
		||||
    | 'Expr'
 | 
			
		||||
    | Bool['__typename']
 | 
			
		||||
    | Arith['__typename']
 | 
			
		||||
    | BitVec['__typename']
 | 
			
		||||
    | SMTArray['__typename'];
 | 
			
		||||
 | 
			
		||||
  get sort(): S;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -688,6 +909,8 @@ export interface Expr<Name extends string = 'main', S extends Sort<Name> = AnySo
 | 
			
		|||
 | 
			
		||||
  params(): ReturnType<FuncDecl<Name>['params']>;
 | 
			
		||||
 | 
			
		||||
  name(): ReturnType<FuncDecl<Name>['name']>;
 | 
			
		||||
 | 
			
		||||
  decl(): FuncDecl<Name>;
 | 
			
		||||
 | 
			
		||||
  numArgs(): number;
 | 
			
		||||
| 
						 | 
				
			
			@ -725,7 +948,7 @@ export interface BoolCreation<Name extends string = 'main'> {
 | 
			
		|||
/** @category Booleans */
 | 
			
		||||
export interface Bool<Name extends string = 'main'> extends Expr<Name, BoolSort<Name>, Z3_ast> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'Bool';
 | 
			
		||||
  readonly __typename: 'Bool' | 'NonLambdaQuantifier';
 | 
			
		||||
 | 
			
		||||
  not(): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -738,6 +961,13 @@ export interface Bool<Name extends string = 'main'> extends Expr<Name, BoolSort<
 | 
			
		|||
  implies(other: Bool<Name> | boolean): Bool<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: properly implement pattern
 | 
			
		||||
/** @category Quantifiers */
 | 
			
		||||
export interface Pattern<Name extends string = 'main'> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'Pattern';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A Sort that represents Integers or Real numbers
 | 
			
		||||
 * @category Arithmetic
 | 
			
		||||
| 
						 | 
				
			
			@ -798,17 +1028,17 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
 | 
			
		|||
  /**
 | 
			
		||||
   * Adds two numbers together
 | 
			
		||||
   */
 | 
			
		||||
  add(other: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  add(other: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Multiplies two numbers together
 | 
			
		||||
   */
 | 
			
		||||
  mul(other: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  mul(other: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Subtract second number from the first one
 | 
			
		||||
   */
 | 
			
		||||
  sub(other: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  sub(other: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Applies power to the number
 | 
			
		||||
| 
						 | 
				
			
			@ -820,12 +1050,12 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
 | 
			
		|||
   * // x=-2
 | 
			
		||||
   * ```
 | 
			
		||||
   */
 | 
			
		||||
  pow(exponent: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  pow(exponent: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Divides the number by the second one
 | 
			
		||||
   */
 | 
			
		||||
  div(other: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  div(other: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a number modulo second one
 | 
			
		||||
| 
						 | 
				
			
			@ -837,7 +1067,7 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
 | 
			
		|||
   * // x=8
 | 
			
		||||
   * ```
 | 
			
		||||
   */
 | 
			
		||||
  mod(other: Arith<Name> | number | bigint | string): Arith<Name>;
 | 
			
		||||
  mod(other: CoercibleToArith<Name>): Arith<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns a negation of the number
 | 
			
		||||
| 
						 | 
				
			
			@ -847,22 +1077,22 @@ export interface Arith<Name extends string = 'main'> extends Expr<Name, ArithSor
 | 
			
		|||
  /**
 | 
			
		||||
   * Return whether the number is less or equal than the second one (`<=`)
 | 
			
		||||
   */
 | 
			
		||||
  le(other: Arith<Name> | number | bigint | string): Bool<Name>;
 | 
			
		||||
  le(other: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns whether the number is less than the second one (`<`)
 | 
			
		||||
   */
 | 
			
		||||
  lt(other: Arith<Name> | number | bigint | string): Bool<Name>;
 | 
			
		||||
  lt(other: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns whether the number is greater than the second one (`>`)
 | 
			
		||||
   */
 | 
			
		||||
  gt(other: Arith<Name> | number | bigint | string): Bool<Name>;
 | 
			
		||||
  gt(other: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Returns whether the number is greater or equal than the second one (`>=`)
 | 
			
		||||
   */
 | 
			
		||||
  ge(other: Arith<Name> | number | bigint | string): Bool<Name>;
 | 
			
		||||
  ge(other: CoercibleToArith<Name>): Bool<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -939,12 +1169,6 @@ export interface BitVecSort<Bits extends number = number, Name extends string =
 | 
			
		|||
  cast(other: CoercibleToExpr<Name>): Expr<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export type CoercibleToBitVec<Bits extends number = number, Name extends string = 'main'> =
 | 
			
		||||
  | bigint
 | 
			
		||||
  | number
 | 
			
		||||
  | BitVec<Bits, Name>;
 | 
			
		||||
 | 
			
		||||
/** @category Bit Vectors */
 | 
			
		||||
export interface BitVecCreation<Name extends string> {
 | 
			
		||||
  sort<Bits extends number = number>(bits: Bits): BitVecSort<Bits, Name>;
 | 
			
		||||
| 
						 | 
				
			
			@ -1213,10 +1437,11 @@ export interface BitVecNum<Bits extends number = number, Name extends string = '
 | 
			
		|||
 * @typeParam RangeSort The sort of the array range
 | 
			
		||||
 * @category Arrays
 | 
			
		||||
 */
 | 
			
		||||
export interface SMTArraySort<Name extends string = 'main',
 | 
			
		||||
  DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
export interface SMTArraySort<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  DomainSort extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
  RangeSort extends AnySort<Name> = AnySort<Name>,
 | 
			
		||||
  > extends Sort<Name> {
 | 
			
		||||
> extends Sort<Name> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'ArraySort';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1236,36 +1461,47 @@ export interface SMTArraySort<Name extends string = 'main',
 | 
			
		|||
   * The sort of the range
 | 
			
		||||
   */
 | 
			
		||||
  range(): RangeSort;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** @category Arrays */
 | 
			
		||||
export interface SMTArrayCreation<Name extends string> {
 | 
			
		||||
  sort<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
 | 
			
		||||
  sort<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
 | 
			
		||||
    ...sig: [...DomainSort, RangeSort]
 | 
			
		||||
  ): SMTArraySort<Name, DomainSort, RangeSort>;
 | 
			
		||||
 | 
			
		||||
  const<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
 | 
			
		||||
    name: string, ...sig: [...DomainSort, RangeSort]
 | 
			
		||||
  const<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
 | 
			
		||||
    name: string,
 | 
			
		||||
    ...sig: [...DomainSort, RangeSort]
 | 
			
		||||
  ): SMTArray<Name, DomainSort, RangeSort>;
 | 
			
		||||
 | 
			
		||||
  consts<DomainSort extends [AnySort<Name>, ...AnySort<Name>[]], RangeSort extends AnySort<Name>>(
 | 
			
		||||
  consts<DomainSort extends NonEmptySortArray<Name>, RangeSort extends Sort<Name>>(
 | 
			
		||||
    names: string | string[],
 | 
			
		||||
    ...sig: [...DomainSort, RangeSort]
 | 
			
		||||
  ): SMTArray<Name, DomainSort, RangeSort>[];
 | 
			
		||||
 | 
			
		||||
  K<DomainSort extends AnySort<Name>, RangeSort extends AnySort<Name>>(
 | 
			
		||||
    domain: DomainSort,
 | 
			
		||||
    value: SortToExprMap<RangeSort, Name>
 | 
			
		||||
    value: SortToExprMap<RangeSort, Name>,
 | 
			
		||||
  ): SMTArray<Name, [DomainSort], RangeSort>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type ArrayIndexType<Name extends string = 'main',
 | 
			
		||||
  DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]]> = [...{
 | 
			
		||||
  [Index in keyof DomainSort]: DomainSort[Index] extends AnySort<Name> ?
 | 
			
		||||
    CoercibleFromMap<SortToExprMap<DomainSort[Index], Name>, Name> :
 | 
			
		||||
    DomainSort[Index];
 | 
			
		||||
}]
 | 
			
		||||
export type NonEmptySortArray<Name extends string = 'main'> = [Sort<Name>, ...Array<Sort<Name>>];
 | 
			
		||||
 | 
			
		||||
export type ArrayIndexType<Name extends string, DomainSort extends Sort<Name>[]> = [
 | 
			
		||||
  ...{
 | 
			
		||||
    [Key in keyof DomainSort]: DomainSort[Key] extends AnySort<Name>
 | 
			
		||||
      ? SortToExprMap<DomainSort[Key], Name>
 | 
			
		||||
      : DomainSort[Key];
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export type CoercibleToArrayIndexType<Name extends string, DomainSort extends Sort<Name>[]> = [
 | 
			
		||||
  ...{
 | 
			
		||||
    [Key in keyof DomainSort]: DomainSort[Key] extends AnySort<Name>
 | 
			
		||||
      ? CoercibleToMap<SortToExprMap<DomainSort[Key], Name>, Name>
 | 
			
		||||
      : DomainSort[Key];
 | 
			
		||||
  },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents Array expression
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,13 +1510,13 @@ export type ArrayIndexType<Name extends string = 'main',
 | 
			
		|||
 * @typeParam RangeSort The sort of the array range
 | 
			
		||||
 * @category Arrays
 | 
			
		||||
 */
 | 
			
		||||
export interface SMTArray<Name extends string = 'main',
 | 
			
		||||
  DomainSort extends [AnySort<Name>, ...AnySort<Name>[]] = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
  RangeSort extends AnySort<Name> = AnySort<Name>>
 | 
			
		||||
  extends Expr<Name, SMTArraySort<Name, DomainSort, RangeSort>, Z3_ast> {
 | 
			
		||||
 | 
			
		||||
export interface SMTArray<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  DomainSort extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
  RangeSort extends Sort<Name> = Sort<Name>,
 | 
			
		||||
> extends Expr<Name, SMTArraySort<Name, DomainSort, RangeSort>, Z3_ast> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'Array';
 | 
			
		||||
  readonly __typename: 'Array' | 'Lambda';
 | 
			
		||||
 | 
			
		||||
  domain(): DomainSort[0];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1288,7 +1524,7 @@ export interface SMTArray<Name extends string = 'main',
 | 
			
		|||
 | 
			
		||||
  range(): RangeSort;
 | 
			
		||||
 | 
			
		||||
  select(...indices: ArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
 | 
			
		||||
  select(...indices: CoercibleToArrayIndexType<Name, DomainSort>): SortToExprMap<RangeSort, Name>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * value should be coercible to RangeSort
 | 
			
		||||
| 
						 | 
				
			
			@ -1297,11 +1533,60 @@ export interface SMTArray<Name extends string = 'main',
 | 
			
		|||
   */
 | 
			
		||||
  store(
 | 
			
		||||
    ...indicesAndValue: [
 | 
			
		||||
      ...ArrayIndexType<Name, DomainSort>,
 | 
			
		||||
      CoercibleFromMap<SortToExprMap<RangeSort, Name>, Name>
 | 
			
		||||
      ...CoercibleToArrayIndexType<Name, DomainSort>,
 | 
			
		||||
      CoercibleToMap<SortToExprMap<RangeSort, Name>, Name>,
 | 
			
		||||
    ]
 | 
			
		||||
  ): SMTArray<Name, DomainSort, RangeSort>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Defines the expression type of the body of a quantifier expression
 | 
			
		||||
 *
 | 
			
		||||
 * @category Quantifiers
 | 
			
		||||
 */
 | 
			
		||||
export type BodyT<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  QVarSorts extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
  QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts> = BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
 | 
			
		||||
> = QSort extends BoolSort<Name>
 | 
			
		||||
  ? Bool<Name>
 | 
			
		||||
  : QSort extends SMTArray<Name, QVarSorts, infer RangeSort>
 | 
			
		||||
  ? SortToExprMap<RangeSort, Name>
 | 
			
		||||
  : never;
 | 
			
		||||
 | 
			
		||||
/** @category Quantifiers */
 | 
			
		||||
export interface Quantifier<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  QVarSorts extends NonEmptySortArray<Name> = [Sort<Name>, ...Sort<Name>[]],
 | 
			
		||||
  QSort extends BoolSort<Name> | SMTArraySort<Name, QVarSorts> = BoolSort<Name> | SMTArraySort<Name, QVarSorts>,
 | 
			
		||||
> extends Expr<Name, QSort> {
 | 
			
		||||
  readonly __typename: 'NonLambdaQuantifier' | 'Lambda';
 | 
			
		||||
 | 
			
		||||
  is_forall(): boolean;
 | 
			
		||||
 | 
			
		||||
  is_exists(): boolean;
 | 
			
		||||
 | 
			
		||||
  is_lambda(): boolean;
 | 
			
		||||
 | 
			
		||||
  weight(): number;
 | 
			
		||||
 | 
			
		||||
  num_patterns(): number;
 | 
			
		||||
 | 
			
		||||
  pattern(i: number): Pattern<Name>;
 | 
			
		||||
 | 
			
		||||
  num_no_patterns(): number;
 | 
			
		||||
 | 
			
		||||
  no_pattern(i: number): Expr<Name>;
 | 
			
		||||
 | 
			
		||||
  body(): BodyT<Name, QVarSorts, QSort>;
 | 
			
		||||
 | 
			
		||||
  num_vars(): number;
 | 
			
		||||
 | 
			
		||||
  var_name(i: number): string | number;
 | 
			
		||||
 | 
			
		||||
  var_sort<T extends number>(i: T): QVarSorts[T];
 | 
			
		||||
 | 
			
		||||
  children(): [BodyT<Name, QVarSorts, QSort>];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Probe<Name extends string = 'main'> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1314,7 +1599,7 @@ export interface Probe<Name extends string = 'main'> {
 | 
			
		|||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export interface TacticCtor<Name extends string> {
 | 
			
		||||
  new(name: string): Tactic<Name>;
 | 
			
		||||
  new (name: string): Tactic<Name>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Tactic<Name extends string = 'main'> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1327,7 +1612,7 @@ export interface Tactic<Name extends string = 'main'> {
 | 
			
		|||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export interface AstVectorCtor<Name extends string> {
 | 
			
		||||
  new<Item extends Ast<Name> = AnyAst<Name>>(): AstVector<Name, Item>;
 | 
			
		||||
  new <Item extends Ast<Name> = AnyAst<Name>>(): AstVector<Name, Item>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1378,7 +1663,7 @@ export interface AstVector<Name extends string = 'main', Item extends Ast<Name>
 | 
			
		|||
 | 
			
		||||
/** @hidden */
 | 
			
		||||
export interface AstMapCtor<Name extends string> {
 | 
			
		||||
  new<Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>(): AstMap<Name, Key, Value>;
 | 
			
		||||
  new <Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>(): AstMap<Name, Key, Value>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -1402,8 +1687,11 @@ export interface AstMapCtor<Name extends string> {
 | 
			
		|||
 * // 0
 | 
			
		||||
 * ```
 | 
			
		||||
 */
 | 
			
		||||
export interface AstMap<Name extends string = 'main', Key extends Ast<Name> = AnyAst<Name>, Value extends Ast<Name> = AnyAst<Name>>
 | 
			
		||||
  extends Iterable<[Key, Value]> {
 | 
			
		||||
export interface AstMap<
 | 
			
		||||
  Name extends string = 'main',
 | 
			
		||||
  Key extends Ast<Name> = AnyAst<Name>,
 | 
			
		||||
  Value extends Ast<Name> = AnyAst<Name>,
 | 
			
		||||
> extends Iterable<[Key, Value]> {
 | 
			
		||||
  /** @hidden */
 | 
			
		||||
  readonly __typename: 'AstMap';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1253,7 +1253,9 @@ struct
 | 
			
		|||
  let mk_re_sort = Z3native.mk_re_sort
 | 
			
		||||
  let is_re_sort = Z3native.is_re_sort
 | 
			
		||||
  let mk_string_sort = Z3native.mk_string_sort
 | 
			
		||||
  let mk_char_sort = Z3native.mk_char_sort
 | 
			
		||||
  let is_string_sort = Z3native.is_string_sort
 | 
			
		||||
  let is_char_sort = Z3native.is_char_sort
 | 
			
		||||
  let mk_string = Z3native.mk_string
 | 
			
		||||
  let is_string = Z3native.is_string
 | 
			
		||||
  let get_string = Z3native.get_string
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,6 +1276,10 @@ struct
 | 
			
		|||
  let mk_str_le = Z3native.mk_str_le
 | 
			
		||||
  let mk_str_lt = Z3native.mk_str_lt
 | 
			
		||||
  let mk_int_to_str = Z3native.mk_int_to_str
 | 
			
		||||
  let mk_string_to_code = Z3native.mk_string_to_code
 | 
			
		||||
  let mk_string_from_code = Z3native.mk_string_from_code
 | 
			
		||||
  let mk_ubv_to_str = Z3native.mk_ubv_to_str
 | 
			
		||||
  let mk_sbv_to_str = Z3native.mk_sbv_to_str
 | 
			
		||||
  let mk_seq_to_re = Z3native.mk_seq_to_re
 | 
			
		||||
  let mk_seq_in_re = Z3native.mk_seq_in_re
 | 
			
		||||
  let mk_re_plus = Z3native.mk_re_plus
 | 
			
		||||
| 
						 | 
				
			
			@ -1287,6 +1293,12 @@ struct
 | 
			
		|||
  let mk_re_complement = Z3native.mk_re_complement
 | 
			
		||||
  let mk_re_empty = Z3native.mk_re_empty
 | 
			
		||||
  let mk_re_full = Z3native.mk_re_full
 | 
			
		||||
  let mk_char = Z3native.mk_char
 | 
			
		||||
  let mk_char_le = Z3native.mk_char_le
 | 
			
		||||
  let mk_char_to_int = Z3native.mk_char_to_int
 | 
			
		||||
  let mk_char_to_bv = Z3native.mk_char_to_bv
 | 
			
		||||
  let mk_char_from_bv = Z3native.mk_char_from_bv
 | 
			
		||||
  let mk_char_is_digit = Z3native.mk_char_is_digit
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
module FloatingPoint =
 | 
			
		||||
| 
						 | 
				
			
			@ -1542,7 +1554,7 @@ struct
 | 
			
		|||
 | 
			
		||||
      let to_string (x:func_entry) =
 | 
			
		||||
        let a = get_args x in
 | 
			
		||||
        let f c p = (p ^ (Expr.to_string c) ^ ", ") in
 | 
			
		||||
        let f c p = ((Expr.to_string c) ^ ", " ^ p) in
 | 
			
		||||
        "[" ^ List.fold_right f a ((Expr.to_string (get_value x)) ^ "]")
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1881,9 +1881,15 @@ sig
 | 
			
		|||
  (** create string sort *)
 | 
			
		||||
  val mk_string_sort : context -> Sort.sort
 | 
			
		||||
 | 
			
		||||
  (** create char sort *)
 | 
			
		||||
  val mk_char_sort : context -> Sort.sort
 | 
			
		||||
 | 
			
		||||
  (** test if sort is a string sort (a sequence of 8-bit bit-vectors) *)
 | 
			
		||||
  val is_string_sort : context -> Sort.sort -> bool 
 | 
			
		||||
 | 
			
		||||
  (** test if sort is a char sort *)
 | 
			
		||||
  val is_char_sort : context -> Sort.sort -> bool
 | 
			
		||||
 | 
			
		||||
  (** create a string literal *)
 | 
			
		||||
  val mk_string : context -> string -> Expr.expr
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1936,6 +1942,7 @@ sig
 | 
			
		|||
  (** retrieve integer expression encoded in string *)
 | 
			
		||||
  val mk_str_to_int : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  (** compare strings less-than-or-equal *)
 | 
			
		||||
  val mk_str_le : context -> Expr.expr -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1945,6 +1952,18 @@ sig
 | 
			
		|||
  (** convert an integer expression to a string *)
 | 
			
		||||
  val mk_int_to_str : context -> Expr.expr -> Expr.expr 
 | 
			
		||||
 | 
			
		||||
  (** [mk_string_to_code ctx s] convert a unit length string [s] to integer code *)
 | 
			
		||||
  val mk_string_to_code : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_string_from_code ctx c] convert code [c] to a string *)
 | 
			
		||||
  val mk_string_from_code : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_ubv_to_str ctx ubv] convert a unsigned bitvector [ubv] to a string  *)
 | 
			
		||||
  val mk_ubv_to_str : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_sbv_to_str ctx sbv] convert a signed bitvector [sbv] to a string  *)
 | 
			
		||||
  val mk_sbv_to_str : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** create regular expression that accepts the argument sequence *)
 | 
			
		||||
  val mk_seq_to_re : context -> Expr.expr -> Expr.expr 
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1984,6 +2003,24 @@ sig
 | 
			
		|||
  (** the regular expression that accepts all sequences *)
 | 
			
		||||
  val mk_re_full : context -> Sort.sort -> Expr.expr 
 | 
			
		||||
 | 
			
		||||
  (** [mk_char ctx i] converts an integer to a character *)
 | 
			
		||||
  val mk_char : context -> int -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_char_le ctx lc rc] compares two characters *)
 | 
			
		||||
  val mk_char_le : context -> Expr.expr -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_char_to_int ctx c] converts the character [c] to an integer *)
 | 
			
		||||
  val mk_char_to_int : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_char_to_bv ctx c] converts the character [c] to a bitvector *)
 | 
			
		||||
  val mk_char_to_bv : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_char_from_bv ctx bv] converts the bitvector [bv] to a character *)
 | 
			
		||||
  val mk_char_from_bv : context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
  (** [mk_char_is_digit ctx c] checks if the character [c] is a digit *)
 | 
			
		||||
  val mk_char_is_digit: context -> Expr.expr -> Expr.expr
 | 
			
		||||
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
(** Floating-Point Arithmetic *)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3173,12 +3173,8 @@ def _to_int_str(val):
 | 
			
		|||
            return "1"
 | 
			
		||||
        else:
 | 
			
		||||
            return "0"
 | 
			
		||||
    elif _is_int(val):
 | 
			
		||||
    else:
 | 
			
		||||
        return str(val)
 | 
			
		||||
    elif isinstance(val, str):
 | 
			
		||||
        return val
 | 
			
		||||
    if z3_debug():
 | 
			
		||||
        _z3_assert(False, "Python value cannot be used as a Z3 integer")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def IntVal(val, ctx=None):
 | 
			
		||||
| 
						 | 
				
			
			@ -11343,7 +11339,7 @@ def Range(lo, hi, ctx=None):
 | 
			
		|||
    return ReRef(Z3_mk_re_range(lo.ctx_ref(), lo.ast, hi.ast), lo.ctx)
 | 
			
		||||
 | 
			
		||||
def Diff(a, b, ctx=None):
 | 
			
		||||
    """Create the difference regular epression
 | 
			
		||||
    """Create the difference regular expression
 | 
			
		||||
    """
 | 
			
		||||
    return ReRef(Z3_mk_re_diff(a.ctx_ref(), a.ast, b.ast), a.ctx)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -365,7 +365,6 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
 | 
			
		|||
    case OP_MOD:     return m_i_mod_decl;
 | 
			
		||||
    case OP_DIV0:    return m_manager->mk_func_decl(symbol("/0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_DIV0));
 | 
			
		||||
    case OP_IDIV0:   return m_manager->mk_func_decl(symbol("div0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_IDIV0));
 | 
			
		||||
    case OP_REM0:    return m_manager->mk_func_decl(symbol("rem0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_REM0));
 | 
			
		||||
    case OP_MOD0:    return m_manager->mk_func_decl(symbol("mod0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_MOD0));
 | 
			
		||||
    case OP_POWER0:  
 | 
			
		||||
        if (is_real) { 
 | 
			
		||||
| 
						 | 
				
			
			@ -612,7 +611,6 @@ void arith_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
 | 
			
		|||
        op_names.push_back(builtin_name("euler", OP_E));
 | 
			
		||||
        op_names.push_back(builtin_name("/0",OP_DIV0));
 | 
			
		||||
        op_names.push_back(builtin_name("div0",OP_IDIV0));
 | 
			
		||||
        op_names.push_back(builtin_name("rem0",OP_REM0));
 | 
			
		||||
        op_names.push_back(builtin_name("mod0",OP_MOD0));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -821,7 +819,7 @@ bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* con
 | 
			
		|||
    }
 | 
			
		||||
    if (is_decl_of(f, arith_family_id, OP_REM) && n == 2 && is_numeral(args[1], r) && r.is_zero()) {
 | 
			
		||||
        sort* rs[2] = { mk_int(), mk_int() };
 | 
			
		||||
        f_out = m_manager.mk_func_decl(arith_family_id, OP_REM0, 0, nullptr, 2, rs, mk_int());
 | 
			
		||||
        f_out = m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_decl_of(f, arith_family_id, OP_POWER) && n == 2 && is_numeral(args[1], r) && r.is_zero() && is_numeral(args[0], r) && r.is_zero()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -857,7 +855,7 @@ func_decl* arith_util::mk_idiv0() {
 | 
			
		|||
 | 
			
		||||
func_decl* arith_util::mk_rem0() {
 | 
			
		||||
    sort* rs[2] = { mk_int(), mk_int() };
 | 
			
		||||
    return m_manager.mk_func_decl(arith_family_id, OP_REM0, 0, nullptr, 2, rs, mk_int());
 | 
			
		||||
    return m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl* arith_util::mk_mod0() {
 | 
			
		||||
| 
						 | 
				
			
			@ -942,7 +940,6 @@ bool arith_util::is_underspecified(expr* e) const {
 | 
			
		|||
        case OP_MOD:
 | 
			
		||||
        case OP_DIV0:
 | 
			
		||||
        case OP_IDIV0:
 | 
			
		||||
        case OP_REM0:
 | 
			
		||||
        case OP_MOD0:
 | 
			
		||||
            return true;
 | 
			
		||||
        default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,7 +50,6 @@ enum arith_op_kind {
 | 
			
		|||
    OP_IDIVIDES,
 | 
			
		||||
    OP_REM,
 | 
			
		||||
    OP_MOD,
 | 
			
		||||
    OP_REM0,
 | 
			
		||||
    OP_MOD0,
 | 
			
		||||
    OP_TO_REAL,
 | 
			
		||||
    OP_TO_INT,
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +215,6 @@ public:
 | 
			
		|||
        case OP_U_ACOS:
 | 
			
		||||
        case OP_DIV0:
 | 
			
		||||
        case OP_IDIV0:
 | 
			
		||||
        case OP_REM0:
 | 
			
		||||
        case OP_MOD0:
 | 
			
		||||
        case OP_POWER0:
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +268,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    bool is_div0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_DIV0); }
 | 
			
		||||
    bool is_idiv0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_IDIV0); }
 | 
			
		||||
    bool is_rem0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_REM0); }
 | 
			
		||||
    bool is_rem0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_MOD0); }
 | 
			
		||||
    bool is_mod0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_MOD0); }
 | 
			
		||||
    bool is_power0(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_POWER0); }
 | 
			
		||||
    bool is_power(func_decl const * n) const { return is_decl_of(n, arith_family_id, OP_POWER); }
 | 
			
		||||
| 
						 | 
				
			
			@ -296,7 +294,7 @@ public:
 | 
			
		|||
    bool is_mod(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD); }
 | 
			
		||||
    bool is_rem(expr const * n) const { return is_app_of(n, arith_family_id, OP_REM); }
 | 
			
		||||
    bool is_mod0(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD0); }
 | 
			
		||||
    bool is_rem0(expr const * n) const { return is_app_of(n, arith_family_id, OP_REM0); }
 | 
			
		||||
    bool is_rem0(expr const * n) const { return is_app_of(n, arith_family_id, OP_MOD0); }
 | 
			
		||||
    bool is_to_real(expr const * n) const { return is_app_of(n, arith_family_id, OP_TO_REAL); }
 | 
			
		||||
    bool is_to_int(expr const * n) const { return is_app_of(n, arith_family_id, OP_TO_INT); }
 | 
			
		||||
    bool is_is_int(expr const * n) const { return is_app_of(n, arith_family_id, OP_IS_INT); }
 | 
			
		||||
| 
						 | 
				
			
			@ -355,7 +353,7 @@ public:
 | 
			
		|||
    MATCH_BINARY(is_div);
 | 
			
		||||
    MATCH_BINARY(is_idiv);
 | 
			
		||||
    MATCH_BINARY(is_mod0);
 | 
			
		||||
    MATCH_BINARY(is_rem0);
 | 
			
		||||
    // MATCH_BINARY(is_rem0);
 | 
			
		||||
    MATCH_BINARY(is_div0);
 | 
			
		||||
    MATCH_BINARY(is_idiv0);
 | 
			
		||||
    MATCH_BINARY(is_power);
 | 
			
		||||
| 
						 | 
				
			
			@ -465,7 +463,7 @@ public:
 | 
			
		|||
    app * mk_mod(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD, arg1, arg2); }
 | 
			
		||||
    app * mk_div0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_DIV0, arg1, arg2); }
 | 
			
		||||
    app * mk_idiv0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_IDIV0, arg1, arg2); }
 | 
			
		||||
    app * mk_rem0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_REM0, arg1, arg2); }
 | 
			
		||||
    app * mk_rem0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD0, arg1, arg2); }
 | 
			
		||||
    app * mk_mod0(expr * arg1, expr * arg2) { return m_manager.mk_app(arith_family_id, OP_MOD0, arg1, arg2); }
 | 
			
		||||
    app * mk_to_real(expr * arg1) { return m_manager.mk_app(arith_family_id, OP_TO_REAL, arg1); }
 | 
			
		||||
    app * mk_to_int(expr * arg1) { return m_manager.mk_app(arith_family_id, OP_TO_INT, arg1); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -315,13 +315,13 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
 | 
			
		|||
 | 
			
		||||
func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domain, unsigned i) {
 | 
			
		||||
    if (arity != 2 || domain[0] != domain[1]) {
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        m_manager->raise_exception("incorrect arguments passed to array-ext");        
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    sort * s = domain[0];
 | 
			
		||||
    unsigned num_parameters = s->get_num_parameters();
 | 
			
		||||
    if (num_parameters == 0 || i >= num_parameters - 1) {
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        m_manager->raise_exception("incorrect arguments passed to array-ext");        
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    sort * r = to_sort(s->get_parameter(i).get_ast());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2322,6 +2322,14 @@ func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const
 | 
			
		|||
    return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ast_manager::is_parametric_function(func_decl* f, func_decl *& g) const {
 | 
			
		||||
    // is-as-array
 | 
			
		||||
    // is-map
 | 
			
		||||
    // is-transitive-closure
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sort * ast_manager::mk_fresh_sort(char const * prefix) {
 | 
			
		||||
    string_buffer<32> buffer;
 | 
			
		||||
    buffer << prefix << "!" << m_fresh_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -3296,7 +3304,7 @@ proof * ast_manager::mk_redundant_del(expr* e) {
 | 
			
		|||
    return mk_clause_trail_elem(nullptr, e, PR_REDUNDANT_DEL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
proof * ast_manager::mk_clause_trail(unsigned n, proof* const* ps) {    
 | 
			
		||||
proof * ast_manager::mk_clause_trail(unsigned n, expr* const* ps) {    
 | 
			
		||||
    ptr_buffer<expr> args;
 | 
			
		||||
    args.append(n, (expr**) ps);
 | 
			
		||||
    return mk_app(basic_family_id, PR_CLAUSE_TRAIL, 0, nullptr, args.size(), args.data());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,13 +180,13 @@ public:
 | 
			
		|||
    */
 | 
			
		||||
    void del_eh(ast_manager & m, family_id fid);
 | 
			
		||||
 | 
			
		||||
    int get_int() const { return std::get<int>(m_val); }
 | 
			
		||||
    ast * get_ast() const { return std::get<ast*>(m_val); }
 | 
			
		||||
    symbol get_symbol() const { return std::get<symbol>(m_val); }
 | 
			
		||||
    rational const & get_rational() const { return *std::get<rational*>(m_val); }
 | 
			
		||||
    zstring const& get_zstring() const { return *std::get<zstring*>(m_val); }
 | 
			
		||||
    double get_double() const { return std::get<double>(m_val); }
 | 
			
		||||
    unsigned get_ext_id() const { return std::get<unsigned>(m_val); }
 | 
			
		||||
    int get_int() const { SASSERT(is_int()); return std::get<int>(m_val); }
 | 
			
		||||
    ast * get_ast() const { SASSERT(is_ast()); return std::get<ast*>(m_val); }
 | 
			
		||||
    symbol get_symbol() const { SASSERT(is_symbol()); return std::get<symbol>(m_val); }
 | 
			
		||||
    rational const & get_rational() const { SASSERT(is_rational()); return *std::get<rational*>(m_val); }
 | 
			
		||||
    zstring const& get_zstring() const { SASSERT(is_zstring()); return *std::get<zstring*>(m_val); }
 | 
			
		||||
    double get_double() const { SASSERT(is_double()); return std::get<double>(m_val); }
 | 
			
		||||
    unsigned get_ext_id() const { SASSERT(is_external()); return std::get<unsigned>(m_val); }
 | 
			
		||||
 | 
			
		||||
    bool operator==(parameter const & p) const;
 | 
			
		||||
    bool operator!=(parameter const & p) const { return !operator==(p); }
 | 
			
		||||
| 
						 | 
				
			
			@ -1924,6 +1924,8 @@ public:
 | 
			
		|||
        return mk_fresh_func_decl(symbol(prefix), symbol::null, arity, domain, range, skolem);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool is_parametric_function(func_decl* f, func_decl *& g) const;
 | 
			
		||||
 | 
			
		||||
    app * mk_fresh_const(char const * prefix, sort * s, bool skolem = true) { 
 | 
			
		||||
        return mk_const(mk_fresh_func_decl(prefix, 0, nullptr, s, skolem)); 
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -2335,7 +2337,7 @@ public:
 | 
			
		|||
    proof * mk_th_assumption_add(proof* pr, expr* e);
 | 
			
		||||
    proof * mk_th_lemma_add(proof* pr, expr* e);
 | 
			
		||||
    proof * mk_redundant_del(expr* e);
 | 
			
		||||
    proof * mk_clause_trail(unsigned n, proof* const* ps);
 | 
			
		||||
    proof * mk_clause_trail(unsigned n, expr* const* ps);
 | 
			
		||||
 | 
			
		||||
    proof * mk_def_axiom(expr * ax);
 | 
			
		||||
    proof * mk_unit_resolution(unsigned num_proofs, proof * const * proofs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,11 +43,11 @@ void ast_pp_util::display_decls(std::ostream& out) {
 | 
			
		|||
    for (unsigned i = m_sorts; i < n; ++i) 
 | 
			
		||||
        pp.display_sort_decl(out, coll.get_sorts()[i], seen);
 | 
			
		||||
    m_sorts = n;
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    n = coll.get_num_decls();
 | 
			
		||||
    for (unsigned i = m_decls; i < n; ++i) {
 | 
			
		||||
        func_decl* f = coll.get_func_decls()[i];
 | 
			
		||||
        if (f->get_family_id() == null_family_id && !m_removed.contains(f)) 
 | 
			
		||||
        if (coll.should_declare(f) && !m_removed.contains(f)) 
 | 
			
		||||
            ast_smt2_pp(out, f, m_env) << "\n";
 | 
			
		||||
    }
 | 
			
		||||
    m_decls = n;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ void ast_pp_util::display_skolem_decls(std::ostream& out) {
 | 
			
		|||
    unsigned n = coll.get_num_decls();
 | 
			
		||||
    for (unsigned i = m_decls; i < n; ++i) {
 | 
			
		||||
        func_decl* f = coll.get_func_decls()[i];
 | 
			
		||||
        if (f->get_family_id() == null_family_id && !m_removed.contains(f) && f->is_skolem()) 
 | 
			
		||||
        if (coll.should_declare(f) && !m_removed.contains(f) && f->is_skolem()) 
 | 
			
		||||
            ast_smt2_pp(out, f, m_env) << "\n";
 | 
			
		||||
    }
 | 
			
		||||
    m_decls = n;    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,8 +121,10 @@ format * smt2_pp_environment::pp_fdecl_params(format * fname, func_decl * f) {
 | 
			
		|||
            std::string str = f->get_parameter(i).get_rational().to_string();
 | 
			
		||||
            fs.push_back(mk_string(get_manager(), str));
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            fs.push_back(pp_fdecl_ref(to_func_decl(f->get_parameter(i).get_ast())));
 | 
			
		||||
        else {
 | 
			
		||||
            unsigned len;
 | 
			
		||||
            fs.push_back(pp_fdecl_name(to_func_decl(f->get_parameter(i).get_ast()), len));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return mk_seq1(get_manager(), fs.begin(), fs.end(), f2f(), "_");
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,6 +34,7 @@ Revision History:
 | 
			
		|||
#include "ast/for_each_ast.h"
 | 
			
		||||
#include "ast/decl_collector.h"
 | 
			
		||||
#include "math/polynomial/algebraic_numbers.h"
 | 
			
		||||
#include "ast/pp_params.hpp"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -911,7 +912,9 @@ ast_smt_pp::ast_smt_pp(ast_manager& m):
 | 
			
		|||
void ast_smt_pp::display_expr_smt2(std::ostream& strm, expr* n, unsigned indent, unsigned num_var_names, char const* const* var_names) {
 | 
			
		||||
    ptr_vector<quantifier> ql;
 | 
			
		||||
    smt_renaming rn;
 | 
			
		||||
    smt_printer p(strm, m_manager, ql, rn, m_logic, false, m_simplify_implies, indent, num_var_names, var_names);
 | 
			
		||||
    pp_params params;
 | 
			
		||||
    bool no_lets = params.no_lets();
 | 
			
		||||
    smt_printer p(strm, m_manager, ql, rn, m_logic, no_lets, m_simplify_implies, indent, num_var_names, var_names);
 | 
			
		||||
    p(n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,9 +118,22 @@ void bv_decl_plugin::finalize() {
 | 
			
		|||
    DEC_REF(m_bv_redand);
 | 
			
		||||
    DEC_REF(m_bv_comp);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_mul_no_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_smul_no_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_smul_no_udfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_mul_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_smul_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_smul_udfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_neg_ovfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_uadd_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_sadd_ovfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_usub_ovfl);
 | 
			
		||||
    DEC_REF(m_bv_ssub_ovfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_sdiv_ovfl);
 | 
			
		||||
 | 
			
		||||
    DEC_REF(m_bv_shl);
 | 
			
		||||
    DEC_REF(m_bv_lshr);
 | 
			
		||||
| 
						 | 
				
			
			@ -245,6 +258,16 @@ func_decl * bv_decl_plugin::mk_bv2int(unsigned bv_size, unsigned num_parameters,
 | 
			
		|||
    return m_bv2int[bv_size];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl * bv_decl_plugin::mk_unary_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
 | 
			
		||||
    force_ptr_array_size(decls, bv_size+1);
 | 
			
		||||
 | 
			
		||||
    if (decls[bv_size] == 0) {
 | 
			
		||||
        decls[bv_size] = m_manager->mk_func_decl(symbol(name), get_bv_sort(bv_size), m_manager->mk_bool_sort(), func_decl_info(m_family_id, k));
 | 
			
		||||
        m_manager->inc_ref(decls[bv_size]);
 | 
			
		||||
    }
 | 
			
		||||
    return decls[bv_size];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func_decl * bv_decl_plugin::mk_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size) {
 | 
			
		||||
    force_ptr_array_size(decls, bv_size + 1);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -289,6 +312,7 @@ func_decl * bv_decl_plugin::mk_comp(unsigned bv_size) {
 | 
			
		|||
func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
 | 
			
		||||
    switch (k) {
 | 
			
		||||
    case OP_BNEG:     return mk_unary(m_bv_neg, k, "bvneg", bv_size);
 | 
			
		||||
    case OP_BNEG_OVFL: return mk_unary_pred(m_bv_neg_ovfl, k, "bvnego", bv_size);
 | 
			
		||||
    case OP_BADD:     return mk_binary(m_bv_add, k, "bvadd", bv_size, true);
 | 
			
		||||
    case OP_BSUB:     return mk_binary(m_bv_sub, k, "bvsub", bv_size, false);
 | 
			
		||||
    case OP_BMUL:     return mk_binary(m_bv_mul, k, "bvmul", bv_size, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -327,9 +351,16 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned bv_size) {
 | 
			
		|||
    case OP_BREDOR:   return mk_reduction(m_bv_redor, k, "bvredor", bv_size);
 | 
			
		||||
    case OP_BREDAND:  return mk_reduction(m_bv_redand, k, "bvredand", bv_size);
 | 
			
		||||
    case OP_BCOMP:    return mk_comp(bv_size);
 | 
			
		||||
    case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumul_noovfl", bv_size);
 | 
			
		||||
    case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmul_noovfl", bv_size);
 | 
			
		||||
    case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_udfl, k, "bvsmul_noudfl", bv_size);
 | 
			
		||||
    case OP_BUMUL_NO_OVFL: return mk_pred(m_bv_mul_no_ovfl, k, "bvumul_noovfl", bv_size);
 | 
			
		||||
    case OP_BSMUL_NO_OVFL: return mk_pred(m_bv_smul_no_ovfl, k, "bvsmul_noovfl", bv_size);
 | 
			
		||||
    case OP_BSMUL_NO_UDFL: return mk_pred(m_bv_smul_no_udfl, k, "bvsmul_noudfl", bv_size);
 | 
			
		||||
    case OP_BUMUL_OVFL: return mk_pred(m_bv_mul_ovfl, k, "bvumulo", bv_size);
 | 
			
		||||
    case OP_BSMUL_OVFL: return mk_pred(m_bv_smul_ovfl, k, "bvsmulo", bv_size);
 | 
			
		||||
    case OP_BSDIV_OVFL: return mk_pred(m_bv_sdiv_ovfl, k, "bvsdivo", bv_size);
 | 
			
		||||
    case OP_BUADD_OVFL: return mk_pred(m_bv_uadd_ovfl, k, "bvuaddo", bv_size);
 | 
			
		||||
    case OP_BSADD_OVFL: return mk_pred(m_bv_sadd_ovfl, k, "bvsaddo", bv_size);
 | 
			
		||||
    case OP_BUSUB_OVFL: return mk_pred(m_bv_usub_ovfl, k, "bvusubo", bv_size);
 | 
			
		||||
    case OP_BSSUB_OVFL: return mk_pred(m_bv_ssub_ovfl, k, "bvssubo", bv_size);
 | 
			
		||||
 | 
			
		||||
    case OP_BSHL:     return mk_binary(m_bv_shl, k, "bvshl", bv_size, false);
 | 
			
		||||
    case OP_BLSHR:    return mk_binary(m_bv_lshr, k, "bvlshr", bv_size, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -681,10 +712,18 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
 | 
			
		|||
    op_names.push_back(builtin_name("bit1",OP_BIT1));
 | 
			
		||||
    op_names.push_back(builtin_name("bit0",OP_BIT0));
 | 
			
		||||
    op_names.push_back(builtin_name("bvneg",OP_BNEG));
 | 
			
		||||
    op_names.push_back(builtin_name("bvnego", OP_BNEG_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvadd",OP_BADD));
 | 
			
		||||
    op_names.push_back(builtin_name("bvuaddo",OP_BUADD_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsaddo",OP_BSADD_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsub",OP_BSUB));
 | 
			
		||||
    op_names.push_back(builtin_name("bvusubo",OP_BUSUB_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvssubo",OP_BSSUB_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvmul",OP_BMUL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvumulo",OP_BUMUL_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsmulo",OP_BSMUL_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsdiv",OP_BSDIV));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsdivo",OP_BSDIV_OVFL));
 | 
			
		||||
    op_names.push_back(builtin_name("bvudiv",OP_BUDIV));
 | 
			
		||||
    op_names.push_back(builtin_name("bvsrem",OP_BSREM));
 | 
			
		||||
    op_names.push_back(builtin_name("bvurem",OP_BUREM));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,6 +93,19 @@ enum bv_op_kind {
 | 
			
		|||
    OP_BSMUL_NO_OVFL, // no signed multiplication overflow predicate
 | 
			
		||||
    OP_BSMUL_NO_UDFL, // no signed multiplication underflow predicate
 | 
			
		||||
 | 
			
		||||
    OP_BUMUL_OVFL, // unsigned multiplication overflow predicate (negation of OP_BUMUL_NO_OVFL)
 | 
			
		||||
    OP_BSMUL_OVFL, // signed multiplication over/underflow predicate
 | 
			
		||||
 | 
			
		||||
    OP_BSDIV_OVFL, // signed division overflow perdicate
 | 
			
		||||
 | 
			
		||||
    OP_BNEG_OVFL, // negation overflow predicate
 | 
			
		||||
 | 
			
		||||
    OP_BUADD_OVFL, // unsigned addition overflow predicate
 | 
			
		||||
    OP_BSADD_OVFL, // signed addition overflow predicate
 | 
			
		||||
 | 
			
		||||
    OP_BUSUB_OVFL, // unsigned subtraction overflow predicate
 | 
			
		||||
    OP_BSSUB_OVFL, // signed subtraction overflow predicate
 | 
			
		||||
 | 
			
		||||
    OP_BIT2BOOL, // predicate
 | 
			
		||||
    OP_MKBV,     // bools to bv
 | 
			
		||||
    OP_INT2BV,
 | 
			
		||||
| 
						 | 
				
			
			@ -189,9 +202,22 @@ protected:
 | 
			
		|||
    ptr_vector<func_decl>  m_bv_redand;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_comp;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_mul_ovfl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_smul_ovfl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_smul_udfl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_mul_no_ovfl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_smul_no_ovfl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_smul_no_udfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl> m_bv_mul_ovfl;
 | 
			
		||||
    ptr_vector<func_decl> m_bv_smul_ovfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl> m_bv_sdiv_ovfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl> m_bv_neg_ovfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl> m_bv_uadd_ovfl;
 | 
			
		||||
    ptr_vector<func_decl> m_bv_sadd_ovfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl> m_bv_usub_ovfl;
 | 
			
		||||
    ptr_vector<func_decl> m_bv_ssub_ovfl;
 | 
			
		||||
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_shl;
 | 
			
		||||
    ptr_vector<func_decl>  m_bv_lshr;
 | 
			
		||||
| 
						 | 
				
			
			@ -213,6 +239,7 @@ protected:
 | 
			
		|||
    func_decl * mk_unary(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
 | 
			
		||||
    func_decl * mk_pred(ptr_vector<func_decl> & decls, decl_kind k,
 | 
			
		||||
                        char const * name, unsigned bv_size);
 | 
			
		||||
    func_decl * mk_unary_pred(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
 | 
			
		||||
    func_decl * mk_reduction(ptr_vector<func_decl> & decls, decl_kind k, char const * name, unsigned bv_size);
 | 
			
		||||
    func_decl * mk_comp(unsigned bv_size);
 | 
			
		||||
    bool get_bv_size(sort * t, int & result);
 | 
			
		||||
| 
						 | 
				
			
			@ -490,9 +517,19 @@ public:
 | 
			
		|||
 | 
			
		||||
    app * mk_bv2int(expr* e);
 | 
			
		||||
 | 
			
		||||
    // TODO: all these binary ops commute (right?) but it'd be more logical to swap `n` & `m` in the `return`
 | 
			
		||||
    app * mk_bvsmul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvsmul_no_udfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_NO_UDFL, n, m); }
 | 
			
		||||
    app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvsmul_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSMUL_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvumul_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvsdiv_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSDIV_OVFL, m, n); }
 | 
			
		||||
    app * mk_bvneg_ovfl(expr* m) { return m_manager.mk_app(get_fid(), OP_BNEG_OVFL, m); }
 | 
			
		||||
    app * mk_bvuadd_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUADD_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvsadd_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSADD_OVFL, n, m); }
 | 
			
		||||
    app * mk_bvusub_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUSUB_OVFL, m, n); }
 | 
			
		||||
    app * mk_bvssub_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BSSUB_OVFL, m, n); }
 | 
			
		||||
 | 
			
		||||
    app * mk_bit2bool(expr* e, unsigned idx) { parameter p(idx); return m_manager.mk_app(get_fid(), OP_BIT2BOOL, 1, &p, 1, &e); }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ Author:
 | 
			
		|||
#include "ast/ast_ll_pp.h"
 | 
			
		||||
#include "ast/ast_util.h"
 | 
			
		||||
#include "ast/arith_decl_plugin.h"
 | 
			
		||||
#include "ast/seq_decl_plugin.h"
 | 
			
		||||
#include "ast/converters/expr_inverter.h"
 | 
			
		||||
 | 
			
		||||
class basic_expr_inverter : public iexpr_inverter {
 | 
			
		||||
| 
						 | 
				
			
			@ -742,6 +743,54 @@ public:
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class seq_expr_inverter : public iexpr_inverter {
 | 
			
		||||
    seq_util seq;
 | 
			
		||||
public:
 | 
			
		||||
    seq_expr_inverter(ast_manager& m) : iexpr_inverter(m), seq(m) {}
 | 
			
		||||
    
 | 
			
		||||
    family_id get_fid() const override { return seq.get_family_id(); }
 | 
			
		||||
 | 
			
		||||
    bool operator()(func_decl* f, unsigned num, expr* const* args, expr_ref& r) override {
 | 
			
		||||
        switch (f->get_decl_kind()) {
 | 
			
		||||
        case _OP_STRING_CONCAT:
 | 
			
		||||
        case OP_SEQ_CONCAT: {
 | 
			
		||||
            expr* x, *y;
 | 
			
		||||
            
 | 
			
		||||
            if (uncnstr(args[0]) && num == 2 &&
 | 
			
		||||
                args[1]->get_ref_count() == 1 && 
 | 
			
		||||
                seq.str.is_concat(args[1], x, y) &&
 | 
			
		||||
                uncnstr(x)) {
 | 
			
		||||
                mk_fresh_uncnstr_var_for(f, r);
 | 
			
		||||
                if (m_mc) {
 | 
			
		||||
                    add_def(args[0], seq.str.mk_empty(args[0]->get_sort()));
 | 
			
		||||
                    add_def(x, r);
 | 
			
		||||
                }
 | 
			
		||||
                r = seq.str.mk_concat(r, y);
 | 
			
		||||
                return true;                
 | 
			
		||||
            }
 | 
			
		||||
                
 | 
			
		||||
            if (!uncnstr(num, args)) 
 | 
			
		||||
                return false;
 | 
			
		||||
            mk_fresh_uncnstr_var_for(f, r);
 | 
			
		||||
            if (m_mc) {
 | 
			
		||||
                add_def(args[0], r);
 | 
			
		||||
                for (unsigned i = 1; i < num; ++i)
 | 
			
		||||
                    add_def(args[i], seq.str.mk_empty(args[0]->get_sort()));
 | 
			
		||||
            }            
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            return false;                
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    bool mk_diff(expr* t, expr_ref& r) override {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
expr_inverter::~expr_inverter() {
 | 
			
		||||
    for (auto* v : m_inverters)
 | 
			
		||||
| 
						 | 
				
			
			@ -796,6 +845,7 @@ expr_inverter::expr_inverter(ast_manager& m): iexpr_inverter(m) {
 | 
			
		|||
    add(alloc(array_expr_inverter, m, *this));
 | 
			
		||||
    add(alloc(dt_expr_inverter, m));
 | 
			
		||||
    add(alloc(basic_expr_inverter, m, *this));
 | 
			
		||||
    add(alloc(seq_expr_inverter, m));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,7 +24,7 @@ Revision History:
 | 
			
		|||
void decl_collector::visit_sort(sort * n) {
 | 
			
		||||
    SASSERT(!m_visited.is_marked(n));
 | 
			
		||||
    family_id fid = n->get_family_id();
 | 
			
		||||
    if (m().is_uninterp(n))
 | 
			
		||||
    if (m.is_uninterp(n))
 | 
			
		||||
        m_sorts.push_back(n);
 | 
			
		||||
    else if (fid == m_dt_fid) {
 | 
			
		||||
        m_sorts.push_back(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ void decl_collector::visit_sort(sort * n) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool decl_collector::is_bool(sort * s) {
 | 
			
		||||
    return m().is_bool(s);
 | 
			
		||||
    return m.is_bool(s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void decl_collector::visit_func(func_decl * n) {
 | 
			
		||||
| 
						 | 
				
			
			@ -51,10 +51,10 @@ void decl_collector::visit_func(func_decl * n) {
 | 
			
		|||
 | 
			
		||||
    if (!m_visited.is_marked(n)) {
 | 
			
		||||
        family_id fid = n->get_family_id();
 | 
			
		||||
        if (fid == null_family_id) 
 | 
			
		||||
        if (should_declare(n))
 | 
			
		||||
            m_decls.push_back(n);
 | 
			
		||||
        else if (fid == m_rec_fid) {
 | 
			
		||||
            recfun::util u(m());
 | 
			
		||||
            recfun::util u(m);
 | 
			
		||||
            if (u.has_def(n)) {
 | 
			
		||||
                m_rec_decls.push_back(n);
 | 
			
		||||
                m_todo.push_back(u.get_def(n).get_rhs());
 | 
			
		||||
| 
						 | 
				
			
			@ -69,12 +69,17 @@ void decl_collector::visit_func(func_decl * n) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool decl_collector::should_declare(func_decl* f) const {
 | 
			
		||||
    return f->get_family_id() == null_family_id || m.is_model_value(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
decl_collector::decl_collector(ast_manager & m):
 | 
			
		||||
    m_manager(m),
 | 
			
		||||
    m(m),
 | 
			
		||||
    m_trail(m),
 | 
			
		||||
    m_dt_util(m),
 | 
			
		||||
    m_ar_util(m) {
 | 
			
		||||
    m_basic_fid = m_manager.get_basic_family_id();
 | 
			
		||||
    m_basic_fid = m.get_basic_family_id();
 | 
			
		||||
    m_dt_fid = m_dt_util.get_family_id();
 | 
			
		||||
    recfun::util rec_util(m);
 | 
			
		||||
    m_rec_fid = rec_util.get_family_id();
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +88,7 @@ decl_collector::decl_collector(ast_manager & m):
 | 
			
		|||
void decl_collector::visit(ast* n) {
 | 
			
		||||
    if (m_visited.is_marked(n)) 
 | 
			
		||||
        return;
 | 
			
		||||
    datatype_util util(m());
 | 
			
		||||
    datatype_util util(m);
 | 
			
		||||
    m_todo.push_back(n);
 | 
			
		||||
    while (!m_todo.empty()) {
 | 
			
		||||
        n = m_todo.back();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ Revision History:
 | 
			
		|||
#include "ast/array_decl_plugin.h"
 | 
			
		||||
 | 
			
		||||
class decl_collector {
 | 
			
		||||
    ast_manager &         m_manager;
 | 
			
		||||
    ast_manager &         m;
 | 
			
		||||
    lim_svector<sort*>      m_sorts;
 | 
			
		||||
    lim_svector<func_decl*> m_decls;
 | 
			
		||||
    lim_svector<func_decl*> m_rec_decls;
 | 
			
		||||
| 
						 | 
				
			
			@ -48,10 +48,10 @@ class decl_collector {
 | 
			
		|||
    void collect_deps(top_sort<sort>& st);
 | 
			
		||||
    void collect_deps(sort* s, sort_set& set);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    decl_collector(ast_manager & m);
 | 
			
		||||
    ast_manager & m() { return m_manager; }
 | 
			
		||||
 | 
			
		||||
    bool should_declare(func_decl* f) const;
 | 
			
		||||
 | 
			
		||||
    void reset() { m_sorts.reset(); m_decls.reset(); m_visited.reset(); m_trail.reset(); }
 | 
			
		||||
    void visit_func(func_decl* n);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,8 @@ struct dimacs_pp {
 | 
			
		|||
        }
 | 
			
		||||
        for (unsigned j = 0; j < num_lits; j++) {
 | 
			
		||||
            expr * l = lits[j];
 | 
			
		||||
            if (m.is_false(l))
 | 
			
		||||
                continue;
 | 
			
		||||
            if (m.is_not(l))
 | 
			
		||||
                l = to_app(l)->get_arg(0);
 | 
			
		||||
            if (!is_uninterp_const(l)) 
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +103,12 @@ struct dimacs_pp {
 | 
			
		|||
        }
 | 
			
		||||
        for (unsigned j = 0; j < num_lits; j++) {
 | 
			
		||||
            expr * l = lits[j];
 | 
			
		||||
            if (m.is_false(l))
 | 
			
		||||
                continue;
 | 
			
		||||
            if (m.is_true(l)) {
 | 
			
		||||
                out << "1 -1 ";
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (m.is_not(l)) {
 | 
			
		||||
                out << "-";
 | 
			
		||||
                l = to_app(l)->get_arg(0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,8 @@ namespace euf {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    enode_bool_pair egraph::insert_table(enode* p) {
 | 
			
		||||
        TRACE("euf", tout << bpp(p) << "\n");
 | 
			
		||||
        //SASSERT(!m_table.contains_ptr(p));
 | 
			
		||||
        auto rc = m_table.insert(p);
 | 
			
		||||
        p->m_cg = rc.first;
 | 
			
		||||
        return rc;
 | 
			
		||||
| 
						 | 
				
			
			@ -280,6 +282,7 @@ namespace euf {
 | 
			
		|||
        if (!m.is_bool(n->get_sort()))
 | 
			
		||||
            return;
 | 
			
		||||
        if (enable_merge_tf != n->merge_tf()) {
 | 
			
		||||
            TRACE("euf", tout << "set tf " << enable_merge_tf << " " << bpp(n) << "\n");
 | 
			
		||||
            n->set_merge_tf(enable_merge_tf);
 | 
			
		||||
            m_updates.push_back(update_record(n, update_record::toggle_merge_tf()));
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -487,6 +490,7 @@ namespace euf {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    void egraph::remove_parents(enode* r) {
 | 
			
		||||
        TRACE("euf", tout << bpp(r) << "\n");
 | 
			
		||||
        for (enode* p : enode_parents(r)) {
 | 
			
		||||
            if (p->is_marked1())
 | 
			
		||||
                continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -496,6 +500,7 @@ namespace euf {
 | 
			
		|||
                SASSERT(m_table.contains_ptr(p));
 | 
			
		||||
                p->mark1();
 | 
			
		||||
                erase_from_table(p);
 | 
			
		||||
                CTRACE("euf", m_table.contains_ptr(p), tout << bpp(p) << "\n"; display(tout));
 | 
			
		||||
                SASSERT(!m_table.contains_ptr(p));
 | 
			
		||||
            }
 | 
			
		||||
            else if (p->is_equality())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,49 @@ unsigned get_num_exprs(expr * n) {
 | 
			
		|||
    return get_num_exprs(n, visited);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void get_num_internal_exprs(unsigned_vector& counts, ptr_vector<expr>& todo, expr * n) {
 | 
			
		||||
    counts.reserve(n->get_id() + 1);
 | 
			
		||||
    unsigned& rc = counts[n->get_id()];
 | 
			
		||||
    if (rc > 0) {
 | 
			
		||||
        --rc;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    rc = n->get_ref_count() - 1;
 | 
			
		||||
    unsigned i = todo.size();
 | 
			
		||||
    todo.push_back(n);
 | 
			
		||||
    for (; i < todo.size(); ++i) {
 | 
			
		||||
        n = todo[i];
 | 
			
		||||
        if (!is_app(n))
 | 
			
		||||
            continue;
 | 
			
		||||
        for (expr* arg : *to_app(n)) {
 | 
			
		||||
            unsigned id = arg->get_id();
 | 
			
		||||
            counts.reserve(id + 1);
 | 
			
		||||
            unsigned& rc = counts[id];
 | 
			
		||||
            if (rc > 0) {
 | 
			
		||||
                --rc;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            rc = arg->get_ref_count() - 1;
 | 
			
		||||
            todo.push_back(arg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned count_internal_nodes(unsigned_vector& counts, ptr_vector<expr>& todo) {
 | 
			
		||||
    unsigned internal_nodes = 0;
 | 
			
		||||
    for (expr* t : todo) {
 | 
			
		||||
        if (counts[t->get_id()] == 0)
 | 
			
		||||
            ++internal_nodes;
 | 
			
		||||
        else
 | 
			
		||||
            counts[t->get_id()] = 0;
 | 
			
		||||
    }
 | 
			
		||||
    todo.reset();
 | 
			
		||||
    return internal_nodes;
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace has_skolem_functions_ns {
 | 
			
		||||
    struct found {};
 | 
			
		||||
    struct proc {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,10 +163,13 @@ struct for_each_expr_proc : public EscapeProc {
 | 
			
		|||
unsigned get_num_exprs(expr * n);
 | 
			
		||||
unsigned get_num_exprs(expr * n, expr_mark & visited);
 | 
			
		||||
unsigned get_num_exprs(expr * n, expr_fast_mark1 & visited);
 | 
			
		||||
void get_num_internal_exprs(unsigned_vector& counts, ptr_vector<expr>& todo, expr * n);
 | 
			
		||||
unsigned count_internal_nodes(unsigned_vector& counts, ptr_vector<expr>& todo);
 | 
			
		||||
 | 
			
		||||
bool has_skolem_functions(expr * n);
 | 
			
		||||
 | 
			
		||||
// pre-order traversal of subterms
 | 
			
		||||
 | 
			
		||||
class subterms {
 | 
			
		||||
    bool            m_include_bound = false;
 | 
			
		||||
    expr_ref_vector m_es;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -149,7 +149,7 @@ class skolemizer {
 | 
			
		|||
        p = nullptr;
 | 
			
		||||
        if (m_proofs_enabled) {
 | 
			
		||||
            if (q->get_kind() == forall_k) 
 | 
			
		||||
                p = m.mk_skolemization(mk_not(m, q), mk_not(m, r));
 | 
			
		||||
                p = m.mk_skolemization(mk_not(m, q), m.mk_not(r));
 | 
			
		||||
            else
 | 
			
		||||
                p = m.mk_skolemization(q, r);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -405,6 +405,44 @@ bool pattern_inference_cfg::pattern_weight_lt::operator()(expr * n1, expr * n2)
 | 
			
		|||
    return num_free_vars1 > num_free_vars2 || (num_free_vars1 == num_free_vars2 && i1.m_size < i2.m_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app* pattern_inference_cfg::mk_pattern(app* candidate) {
 | 
			
		||||
    auto has_var_arg = [&](expr* e) {
 | 
			
		||||
        if (!is_app(e))
 | 
			
		||||
            return false;
 | 
			
		||||
        for (expr* arg : *to_app(e))
 | 
			
		||||
            if (is_var(arg))
 | 
			
		||||
                return true;
 | 
			
		||||
        return false;
 | 
			
		||||
    };
 | 
			
		||||
    if (has_var_arg(candidate))
 | 
			
		||||
        return m.mk_pattern(candidate);
 | 
			
		||||
    m_args.reset();
 | 
			
		||||
    for (expr* arg : *candidate) {
 | 
			
		||||
        if (!is_app(arg))
 | 
			
		||||
            return m.mk_pattern(candidate);
 | 
			
		||||
        m_args.push_back(to_app(arg));
 | 
			
		||||
    }
 | 
			
		||||
    for (unsigned i = 0; i < m_args.size(); ++i) {
 | 
			
		||||
        app* arg = m_args[i];
 | 
			
		||||
        if (has_var_arg(arg))
 | 
			
		||||
            continue;
 | 
			
		||||
        m_args[i] = m_args.back();
 | 
			
		||||
        --i;
 | 
			
		||||
        m_args.pop_back();
 | 
			
		||||
 | 
			
		||||
        if (is_ground(arg))
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        for (expr* e : *to_app(arg)) {
 | 
			
		||||
            if (!is_app(e))
 | 
			
		||||
                return m.mk_pattern(candidate);
 | 
			
		||||
            m_args.push_back(to_app(e));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return m.mk_pattern(m_args.size(), m_args.data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief Create unary patterns (single expressions that contain all
 | 
			
		||||
   bound variables).  If a candidate does not contain all bound
 | 
			
		||||
| 
						 | 
				
			
			@ -418,7 +456,7 @@ void pattern_inference_cfg::candidates2unary_patterns(ptr_vector<app> const & ca
 | 
			
		|||
        expr2info::obj_map_entry * e = m_candidates_info.find_core(candidate);
 | 
			
		||||
        info const & i = e->get_data().m_value;
 | 
			
		||||
        if (i.m_free_vars.num_elems() == m_num_bindings) {
 | 
			
		||||
            app * new_pattern = m.mk_pattern(candidate);
 | 
			
		||||
            app * new_pattern = mk_pattern(candidate);
 | 
			
		||||
            result.push_back(new_pattern);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -188,6 +188,9 @@ class pattern_inference_cfg :  public default_rewriter_cfg {
 | 
			
		|||
    ptr_vector<pre_pattern>      m_pre_patterns;
 | 
			
		||||
    expr_pattern_match           m_database;
 | 
			
		||||
 | 
			
		||||
    ptr_buffer<app> m_args;
 | 
			
		||||
    app* mk_pattern(app* candidate);
 | 
			
		||||
 | 
			
		||||
    void candidates2unary_patterns(ptr_vector<app> const & candidate_patterns,
 | 
			
		||||
                                   ptr_vector<app> & remaining_candidate_patterns,
 | 
			
		||||
                                   app_ref_buffer & result);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ def_module_params('pp',
 | 
			
		|||
                          ('max_width', UINT, 80, 'max. width in pretty printer'),
 | 
			
		||||
                          ('max_ribbon', UINT, 80, 'max. ribbon (width - indentation) in pretty printer'),
 | 
			
		||||
                          ('max_depth', UINT, 5, 'max. term depth (when pretty printing SMT2 terms/formulas)'),
 | 
			
		||||
			  ('no_lets', BOOL, False, 'dont print lets in low level SMT printer'),
 | 
			
		||||
                          ('min_alias_size', UINT, 10, 'min. size for creating an alias for a shared term (when pretty printing SMT2 terms/formulas)'),
 | 
			
		||||
                          ('decimal', BOOL, False, 'pretty print real numbers using decimal notation (the output may be truncated). Z3 adds a ? if the value is not precise'),
 | 
			
		||||
                          ('decimal_precision', UINT, 10, 'maximum number of decimal places to be used when pp.decimal=true'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -492,7 +492,7 @@ namespace recfun {
 | 
			
		|||
        def* plugin::mk_def(replace& subst, bool is_macro,
 | 
			
		||||
                            symbol const& name, unsigned n, sort ** params, sort * range,
 | 
			
		||||
                            unsigned n_vars, var ** vars, expr * rhs) {
 | 
			
		||||
            promise_def d = mk_def(name, n, params, range);
 | 
			
		||||
            promise_def d = mk_def(name, n, params, range, false);
 | 
			
		||||
            SASSERT(! m_defs.contains(d.get_def()->get_decl()));
 | 
			
		||||
            set_definition(subst, d, is_macro, n_vars, vars, rhs);
 | 
			
		||||
            return d.get_def();
 | 
			
		||||
| 
						 | 
				
			
			@ -581,7 +581,7 @@ namespace recfun {
 | 
			
		|||
                }
 | 
			
		||||
                                
 | 
			
		||||
                symbol fresh_name("fold-rec-" + std::to_string(m().mk_fresh_id())); 
 | 
			
		||||
                auto pd = mk_def(fresh_name, n, domain.data(), max_expr->get_sort());
 | 
			
		||||
                auto pd = mk_def(fresh_name, n, domain.data(), max_expr->get_sort(), false);
 | 
			
		||||
                func_decl* f = pd.get_def()->get_decl();
 | 
			
		||||
                expr_ref new_body(m().mk_app(f, n, args.data()), m());
 | 
			
		||||
                set_definition(subst, pd, false, n, vars, max_expr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,9 +192,9 @@ namespace recfun {
 | 
			
		|||
 | 
			
		||||
            void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
 | 
			
		||||
            
 | 
			
		||||
            promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
 | 
			
		||||
            promise_def mk_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated);
 | 
			
		||||
 | 
			
		||||
            promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated = false);
 | 
			
		||||
            promise_def ensure_def(symbol const& name, unsigned n, sort *const * params, sort * range, bool is_generated);
 | 
			
		||||
            
 | 
			
		||||
            void set_definition(replace& r, promise_def & d, bool is_macro, unsigned n_vars, var * const * vars, expr * rhs);
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +248,7 @@ namespace recfun {
 | 
			
		|||
        bool is_defined(expr * e) const { return is_app_of(e, m_fid, OP_FUN_DEFINED); }
 | 
			
		||||
        bool is_defined(func_decl* f) const { return is_decl_of(f, m_fid, OP_FUN_DEFINED); }
 | 
			
		||||
        bool is_generated(func_decl* f) const { return is_defined(f) && f->get_parameter(0).get_int() == 1; }
 | 
			
		||||
        bool is_macro(func_decl* f) { return is_defined(f) && get_def(f).is_macro(); }
 | 
			
		||||
        bool is_num_rounds(expr * e) const { return is_app_of(e, m_fid, OP_NUM_ROUNDS); }
 | 
			
		||||
        bool owns_app(app * e) const { return e->get_family_id() == m_fid; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ Author:
 | 
			
		|||
Notes:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#include "params/arith_rewriter_params.hpp"
 | 
			
		||||
#include "ast/rewriter/arith_rewriter.h"
 | 
			
		||||
#include "ast/rewriter/poly_rewriter_def.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -1046,19 +1047,21 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
 | 
			
		|||
    set_curr_sort(arg1->get_sort());
 | 
			
		||||
    numeral v1, v2;
 | 
			
		||||
    bool is_int;
 | 
			
		||||
    if (m_util.is_numeral(arg1, v1, is_int) && m_util.is_numeral(arg2, v2, is_int) && !v2.is_zero()) {
 | 
			
		||||
    bool is_num1 = m_util.is_numeral(arg1, v1, is_int);
 | 
			
		||||
    bool is_num2 = m_util.is_numeral(arg2, v2, is_int);
 | 
			
		||||
    if (is_num1 && is_num2 && !v2.is_zero()) {
 | 
			
		||||
        result = m_util.mk_numeral(div(v1, v2), is_int);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.is_numeral(arg2, v2, is_int) && v2.is_one()) {
 | 
			
		||||
    if (is_num2 && v2.is_one()) {
 | 
			
		||||
        result = arg1; 
 | 
			
		||||
        return BR_DONE; 
 | 
			
		||||
    } 
 | 
			
		||||
    if (m_util.is_numeral(arg2, v2, is_int) && v2.is_minus_one()) {
 | 
			
		||||
    if (is_num2 && v2.is_minus_one()) {
 | 
			
		||||
        result = m_util.mk_mul(m_util.mk_int(-1), arg1); 
 | 
			
		||||
        return BR_REWRITE1; 
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.is_numeral(arg2, v2, is_int) && v2.is_zero()) { 
 | 
			
		||||
    if (is_num2 && v2.is_zero()) { 
 | 
			
		||||
        return BR_FAILED; 
 | 
			
		||||
    } 
 | 
			
		||||
    if (arg1 == arg2) { 
 | 
			
		||||
| 
						 | 
				
			
			@ -1066,7 +1069,7 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
 | 
			
		|||
        result = m.mk_ite(m.mk_eq(arg1, zero), m_util.mk_idiv(zero, zero), m_util.mk_int(1)); 
 | 
			
		||||
        return BR_REWRITE3; 
 | 
			
		||||
    } 
 | 
			
		||||
    if (m_util.is_numeral(arg2, v2, is_int) && v2.is_pos() && m_util.is_add(arg1)) { 
 | 
			
		||||
    if (is_num2 && v2.is_pos() && m_util.is_add(arg1)) { 
 | 
			
		||||
        expr_ref_buffer args(m);
 | 
			
		||||
        bool change = false;
 | 
			
		||||
        rational add(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -1092,7 +1095,14 @@ br_status arith_rewriter::mk_idiv_core(expr * arg1, expr * arg2, expr_ref & resu
 | 
			
		|||
        expr_ref zero(m_util.mk_int(0), m); 
 | 
			
		||||
        result = m.mk_ite(m.mk_eq(zero, arg2), m_util.mk_idiv(arg1, zero), result);
 | 
			
		||||
        return BR_REWRITE_FULL; 
 | 
			
		||||
    } 
 | 
			
		||||
    }
 | 
			
		||||
#if 0
 | 
			
		||||
    expr* x = nullptr, *y = nullptr, *z = nullptr;
 | 
			
		||||
    if (is_num2 && m_util.is_idiv(arg1, x, y) && m_util.is_numeral(y, v1) && v1 > 0 && v2 > 0) {
 | 
			
		||||
        result = m_util.mk_idiv(x, m_util.mk_numeral(v1*v2, is_int));
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ Notes:
 | 
			
		|||
#include "params/bool_rewriter_params.hpp"
 | 
			
		||||
#include "ast/rewriter/rewriter_def.h"
 | 
			
		||||
#include "ast/ast_lt.h"
 | 
			
		||||
#include "ast/for_each_expr.h"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
void bool_rewriter::updt_params(params_ref const & _p) {
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +33,7 @@ void bool_rewriter::updt_params(params_ref const & _p) {
 | 
			
		|||
    m_blast_distinct       = p.blast_distinct();
 | 
			
		||||
    m_blast_distinct_threshold = p.blast_distinct_threshold();
 | 
			
		||||
    m_ite_extra_rules      = p.ite_extra_rules();
 | 
			
		||||
    m_hoist.set_elim_and(m_elim_and);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void bool_rewriter::get_param_descrs(param_descrs & r) {
 | 
			
		||||
| 
						 | 
				
			
			@ -269,13 +271,26 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
 | 
			
		|||
 | 
			
		||||
#if 1
 | 
			
		||||
        br_status st;
 | 
			
		||||
        st = m_hoist.mk_or(buffer.size(), buffer.data(), result);
 | 
			
		||||
        expr_ref r(m());
 | 
			
		||||
        st = m_hoist.mk_or(buffer.size(), buffer.data(), r);
 | 
			
		||||
        if (st != BR_FAILED) {
 | 
			
		||||
            m_counts1.reserve(m().get_num_asts() + 1);
 | 
			
		||||
            m_counts2.reserve(m().get_num_asts() + 1);
 | 
			
		||||
            get_num_internal_exprs(m_counts1, m_todo1, r);
 | 
			
		||||
            for (unsigned i = 0; i < num_args; ++i)
 | 
			
		||||
                get_num_internal_exprs(m_counts2, m_todo2, args[i]);
 | 
			
		||||
            unsigned count1 = count_internal_nodes(m_counts1, m_todo1);
 | 
			
		||||
            unsigned count2 = count_internal_nodes(m_counts2, m_todo2);
 | 
			
		||||
            if (count1 > count2)
 | 
			
		||||
                st = BR_FAILED;
 | 
			
		||||
        }
 | 
			
		||||
        if (st != BR_FAILED)
 | 
			
		||||
            result = r;
 | 
			
		||||
        if (st == BR_DONE)
 | 
			
		||||
            return BR_REWRITE1;
 | 
			
		||||
        if (st != BR_FAILED)
 | 
			
		||||
            return st;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        if (s) {
 | 
			
		||||
            ast_lt lt;
 | 
			
		||||
            std::sort(buffer.begin(), buffer.end(), lt);       
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,8 @@ class bool_rewriter {
 | 
			
		|||
    unsigned       m_local_ctx_limit;
 | 
			
		||||
    unsigned       m_local_ctx_cost;
 | 
			
		||||
    bool           m_elim_ite;
 | 
			
		||||
    ptr_vector<expr> m_todo1, m_todo2;
 | 
			
		||||
    unsigned_vector m_counts1, m_counts2;
 | 
			
		||||
 | 
			
		||||
    br_status mk_flat_and_core(unsigned num_args, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_flat_or_core(unsigned num_args, expr * const * args, expr_ref & result);
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +83,9 @@ class bool_rewriter {
 | 
			
		|||
    void push_new_arg(expr* arg, expr_ref_vector& new_args, expr_fast_mark1& neg_lits, expr_fast_mark2& pos_lits);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_hoist(m), m_local_ctx_cost(0) { updt_params(p); }
 | 
			
		||||
    bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_hoist(m), m_local_ctx_cost(0) { 
 | 
			
		||||
        updt_params(p); 
 | 
			
		||||
    }
 | 
			
		||||
    ast_manager & m() const { return m_manager; }
 | 
			
		||||
    family_id get_fid() const { return m().get_basic_family_id(); }
 | 
			
		||||
    bool is_eq(expr * t) const { return m().is_eq(t); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -185,7 +185,7 @@ namespace bv {
 | 
			
		|||
                    m_args.push_back(arg);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (!m_bv.is_extract(arg) && m_bound.find(arg, b)) {
 | 
			
		||||
                if (!m_bv.is_extract(arg) && m_bound.find(arg, b) && b.lo() <= b.hi()) {
 | 
			
		||||
                    unsigned num_bits = b.hi().get_num_bits();
 | 
			
		||||
                    unsigned bv_size = m_bv.get_bv_size(arg);
 | 
			
		||||
                    if (0 < num_bits && num_bits < bv_size) {
 | 
			
		||||
| 
						 | 
				
			
			@ -202,6 +202,7 @@ namespace bv {
 | 
			
		|||
 | 
			
		||||
            if (simplified) {
 | 
			
		||||
                result = m.mk_app(to_app(t)->get_decl(), m_args);
 | 
			
		||||
                TRACE("bv", tout << mk_pp(t, m) << " -> " << result << "\n");
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,6 +94,10 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
 | 
			
		|||
    case OP_BNEG:
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_uminus(args[0], result);
 | 
			
		||||
    case OP_BNEG_OVFL:
 | 
			
		||||
        SASSERT(num_args == 1);
 | 
			
		||||
        return mk_bvneg_overflow(args[0], result);
 | 
			
		||||
 | 
			
		||||
    case OP_BSHL:
 | 
			
		||||
        SASSERT(num_args == 2);
 | 
			
		||||
        return mk_bv_shl(args[0], args[1], result);
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +204,20 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
 | 
			
		|||
        return mk_bvsmul_no_overflow(num_args, args, false, result);
 | 
			
		||||
    case OP_BUMUL_NO_OVFL:
 | 
			
		||||
        return mk_bvumul_no_overflow(num_args, args, result);
 | 
			
		||||
    case OP_BSMUL_OVFL:
 | 
			
		||||
        return mk_bvsmul_overflow(num_args, args, result);
 | 
			
		||||
    case OP_BUMUL_OVFL:
 | 
			
		||||
        return mk_bvumul_overflow(num_args, args, result);
 | 
			
		||||
    case OP_BSDIV_OVFL:
 | 
			
		||||
        return mk_bvsdiv_overflow(num_args, args, result);
 | 
			
		||||
    case OP_BUADD_OVFL:
 | 
			
		||||
        return mk_bvuadd_overflow(num_args, args, result);
 | 
			
		||||
    case OP_BSADD_OVFL:
 | 
			
		||||
        return mk_bvsadd_over_underflow(num_args, args, result);
 | 
			
		||||
    case OP_BUSUB_OVFL:
 | 
			
		||||
        return mk_bvusub_underflow(num_args, args, result);
 | 
			
		||||
    case OP_BSSUB_OVFL:
 | 
			
		||||
        return mk_bvssub_overflow(num_args, args, result);
 | 
			
		||||
    default:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1555,7 +1573,7 @@ br_status bv_rewriter::mk_concat(unsigned num_args, expr * const * args, expr_re
 | 
			
		|||
        if (eq_args) {
 | 
			
		||||
            if (m.is_ite(new_args.back(), x, y, z)) {
 | 
			
		||||
                ptr_buffer<expr> args1, args2;
 | 
			
		||||
                for (expr* arg : new_args)
 | 
			
		||||
                for (unsigned i = 0; i < new_args.size(); ++i)
 | 
			
		||||
                    args1.push_back(y), args2.push_back(z);
 | 
			
		||||
                result = m.mk_ite(x, m_util.mk_concat(args1), m_util.mk_concat(args2));
 | 
			
		||||
                return BR_REWRITE2;
 | 
			
		||||
| 
						 | 
				
			
			@ -2925,6 +2943,21 @@ br_status bv_rewriter::mk_distinct(unsigned num_args, expr * const * args, expr_
 | 
			
		|||
    return BR_DONE;     
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvsmul_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    result = m.mk_or(
 | 
			
		||||
            m.mk_not(m_util.mk_bvsmul_no_ovfl(args[0], args[1])),
 | 
			
		||||
            m.mk_not(m_util.mk_bvsmul_no_udfl(args[0], args[1]))
 | 
			
		||||
    );
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvumul_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    result = m.mk_not(m_util.mk_bvumul_no_ovfl(args[0], args[1]));
 | 
			
		||||
    return BR_REWRITE2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    unsigned bv_sz;
 | 
			
		||||
| 
						 | 
				
			
			@ -2984,5 +3017,95 @@ br_status bv_rewriter::mk_bvumul_no_overflow(unsigned num, expr * const * args,
 | 
			
		|||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvneg_overflow(expr * const arg, expr_ref & result) {
 | 
			
		||||
    unsigned int sz = get_bv_size(arg);
 | 
			
		||||
    auto maxUnsigned = mk_numeral(rational::power_of_two(sz)-1, sz);
 | 
			
		||||
    result = m.mk_eq(arg, maxUnsigned);
 | 
			
		||||
    return BR_REWRITE3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvuadd_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    unsigned sz = get_bv_size(args[0]);
 | 
			
		||||
    auto a1 = mk_zero_extend(1, args[0]);
 | 
			
		||||
    auto a2 = mk_zero_extend(1, args[1]);
 | 
			
		||||
    auto r = mk_bv_add(a1, a2);
 | 
			
		||||
    auto extract = m_mk_extract(sz, sz, r);
 | 
			
		||||
    result = m.mk_eq(extract, mk_one(1));
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvsadd_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    unsigned sz = get_bv_size(args[0]);
 | 
			
		||||
    auto zero = mk_zero(sz);
 | 
			
		||||
    auto r = mk_bv_add(args[0], args[1]);
 | 
			
		||||
    auto l1 = m_util.mk_slt(zero, args[0]);
 | 
			
		||||
    auto l2 = m_util.mk_slt(zero, args[1]);
 | 
			
		||||
    auto args_pos = m.mk_and(l1, l2);
 | 
			
		||||
    auto non_pos_sum = m_util.mk_sle(r, zero);
 | 
			
		||||
    result = m.mk_and(args_pos, non_pos_sum);
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvsadd_underflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    unsigned sz = get_bv_size(args[0]);
 | 
			
		||||
    auto zero = mk_zero(sz);
 | 
			
		||||
    auto r = mk_bv_add(args[0], args[1]);
 | 
			
		||||
    auto l1 = m_util.mk_slt(args[0], zero);
 | 
			
		||||
    auto l2 = m_util.mk_slt(args[1], zero);
 | 
			
		||||
    auto args_neg = m.mk_and(l1, l2);
 | 
			
		||||
    expr_ref non_neg_sum{m};
 | 
			
		||||
    auto res_rewrite = mk_sge(r, zero, non_neg_sum);
 | 
			
		||||
    SASSERT(res_rewrite != BR_FAILED); (void)res_rewrite;
 | 
			
		||||
    result = m.mk_and(args_neg, non_neg_sum);
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvsadd_over_underflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    expr_ref l1{m};
 | 
			
		||||
    expr_ref l2{m};
 | 
			
		||||
    (void)mk_bvsadd_overflow(2, args, l1);
 | 
			
		||||
    (void)mk_bvsadd_underflow(2, args, l2);
 | 
			
		||||
    result = m.mk_or(l1, l2);
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvusub_underflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    br_status status = mk_ult(args[0], args[1], result);
 | 
			
		||||
    SASSERT(status != BR_FAILED);
 | 
			
		||||
    return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status bv_rewriter::mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    auto sz = get_bv_size(args[0]);
 | 
			
		||||
    auto minSigned = mk_numeral(-rational::power_of_two(sz-1), sz);
 | 
			
		||||
    expr_ref bvsaddo {m};
 | 
			
		||||
    expr * args2[2] = { args[0], m_util.mk_bv_neg(args[1]) };
 | 
			
		||||
    auto bvsaddo_stat = mk_bvsadd_overflow(2, args2, bvsaddo);
 | 
			
		||||
    SASSERT(bvsaddo_stat != BR_FAILED); (void)bvsaddo_stat;
 | 
			
		||||
    auto first_arg_ge_zero = m_util.mk_sle(mk_zero(sz), args[0]);
 | 
			
		||||
    result = m.mk_ite(m.mk_eq(args[1], minSigned), first_arg_ge_zero, bvsaddo);
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
br_status bv_rewriter::mk_bvsdiv_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | 
			
		||||
    SASSERT(num == 2);
 | 
			
		||||
    SASSERT(get_bv_size(args[0]) == get_bv_size(args[1]));
 | 
			
		||||
    auto sz = get_bv_size(args[1]);
 | 
			
		||||
    auto minSigned = mk_numeral(-rational::power_of_two(sz-1), sz);
 | 
			
		||||
    auto minusOne = mk_numeral(rational::power_of_two(sz) - 1, sz);
 | 
			
		||||
    result = m.mk_and(m.mk_eq(args[0], minSigned), m.mk_eq(args[1], minusOne));
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template class poly_rewriter<bv_rewriter_core>;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,6 +139,22 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
 | 
			
		|||
    br_status mk_mkbv(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result);
 | 
			
		||||
    br_status mk_bvumul_no_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_bvsmul_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvumul_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_bvsdiv_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_bvneg_overflow(expr * const arg, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_bvuadd_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvsadd_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvsadd_underflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvsadd_over_underflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_bvusub_underflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
    br_status mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    bool is_minus_one_times_t(expr * arg);
 | 
			
		||||
    void mk_t1_add_t2_eq_c(expr * t1, expr * t2, expr * c, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,9 +197,10 @@ void der::reduce1(quantifier * q, expr_ref & r, proof_ref & pr) {
 | 
			
		|||
 | 
			
		||||
        m_pos2var.reserve(num_args, -1);
 | 
			
		||||
 | 
			
		||||
        // Find all disequalities
 | 
			
		||||
        // Find all equalities/disequalities
 | 
			
		||||
        for (unsigned i = 0; i < num_args; i++) {
 | 
			
		||||
            is_eq = is_forall(q) ? is_var_diseq(literals.get(i), num_decls, v, t) : is_var_eq(literals.get(i), num_decls, v, t);
 | 
			
		||||
            expr* arg = literals.get(i);
 | 
			
		||||
            is_eq = is_forall(q) ? is_var_diseq(arg, num_decls, v, t) : is_var_eq(arg, num_decls, v, t);
 | 
			
		||||
            if (is_eq) {
 | 
			
		||||
                unsigned idx = v->get_idx();
 | 
			
		||||
                if (m_map.get(idx, nullptr) == nullptr) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ Revision History:
 | 
			
		|||
 | 
			
		||||
#include "ast/used_vars.h"
 | 
			
		||||
#include "util/obj_hashtable.h"
 | 
			
		||||
#include "ast/rewriter/rewriter_def.h"
 | 
			
		||||
#include "ast/rewriter/var_subst.h"
 | 
			
		||||
#include "ast/rewriter/elim_bounds.h"
 | 
			
		||||
#include "ast/ast_pp.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,16 +17,36 @@ Author:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
#include "ast/rewriter/hoist_rewriter.h"
 | 
			
		||||
#include "ast/rewriter/bool_rewriter.h"
 | 
			
		||||
#include "ast/ast_util.h"
 | 
			
		||||
#include "ast/ast_pp.h"
 | 
			
		||||
#include "ast/ast_ll_pp.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
hoist_rewriter::hoist_rewriter(ast_manager & m, params_ref const & p):
 | 
			
		||||
    m(m), m_args1(m), m_args2(m), m_subst(m) { 
 | 
			
		||||
    m(m), m_args1(m), m_args2(m), m_refs(m), m_subst(m) { 
 | 
			
		||||
    updt_params(p); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref hoist_rewriter::mk_and(expr_ref_vector const& args) {
 | 
			
		||||
    if (m_elim_and) {
 | 
			
		||||
        expr_ref_vector negs(m);
 | 
			
		||||
        for (expr* a : args)
 | 
			
		||||
            if (m.is_false(a))
 | 
			
		||||
                return expr_ref(m.mk_false(), m);
 | 
			
		||||
            else if (m.is_true(a))
 | 
			
		||||
                continue;
 | 
			
		||||
            else
 | 
			
		||||
                negs.push_back(::mk_not(m, a));
 | 
			
		||||
        return ::mk_not(mk_or(negs));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        return ::mk_and(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref hoist_rewriter::mk_or(expr_ref_vector const& args) {
 | 
			
		||||
    return ::mk_or(args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status hoist_rewriter::mk_or(unsigned num_args, expr * const * es, expr_ref & result) {
 | 
			
		||||
    if (num_args < 2) 
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,28 +164,26 @@ unsigned hoist_rewriter::mk_var(expr* e) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
expr_ref hoist_rewriter::hoist_predicates(obj_hashtable<expr> const& preds, unsigned num_args, expr* const* es) {
 | 
			
		||||
    expr_ref result(m);
 | 
			
		||||
    expr_ref_vector args(m), fmls(m);
 | 
			
		||||
    expr_ref_vector args(m), args1(m), fmls(m);
 | 
			
		||||
    for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
        VERIFY(is_and(es[i], &m_args1));
 | 
			
		||||
        VERIFY(is_and(es[i], &args1));
 | 
			
		||||
        fmls.reset();
 | 
			
		||||
        for (expr* e : m_args1) 
 | 
			
		||||
        for (expr* e : args1) 
 | 
			
		||||
            if (!preds.contains(e))
 | 
			
		||||
                fmls.push_back(e);
 | 
			
		||||
        args.push_back(::mk_and(fmls));
 | 
			
		||||
        args.push_back(mk_and(fmls));
 | 
			
		||||
    }
 | 
			
		||||
    fmls.reset();
 | 
			
		||||
    fmls.push_back(::mk_or(args));
 | 
			
		||||
    fmls.push_back(mk_or(args));
 | 
			
		||||
    for (auto* p : preds) 
 | 
			
		||||
        fmls.push_back(p);
 | 
			
		||||
    result = ::mk_and(fmls);
 | 
			
		||||
    return result;
 | 
			
		||||
    return mk_and(fmls);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
br_status hoist_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
 | 
			
		||||
    switch (f->get_decl_kind()) {
 | 
			
		||||
    case OP_OR:
 | 
			
		||||
    case OP_OR:        
 | 
			
		||||
        return mk_or(num_args, args, result);
 | 
			
		||||
    default:
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
| 
						 | 
				
			
			@ -173,6 +191,33 @@ br_status hoist_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
bool hoist_rewriter::is_and(expr * e, expr_ref_vector* args) {
 | 
			
		||||
#if 0
 | 
			
		||||
    if (!args) 
 | 
			
		||||
        return m.is_and(e) || (m.is_not(e, e) && m.is_or(e));
 | 
			
		||||
    expr_fast_mark1 visited;
 | 
			
		||||
    args->reset();
 | 
			
		||||
    args->push_back(e);
 | 
			
		||||
    m_refs.reset();
 | 
			
		||||
    for (unsigned i = 0; i < args->size(); ++i) {
 | 
			
		||||
        e = args->get(i);
 | 
			
		||||
        if (visited.is_marked(e)) 
 | 
			
		||||
            goto drop;
 | 
			
		||||
        m_refs.push_back(e);
 | 
			
		||||
        visited.mark(e, true);
 | 
			
		||||
        if (m.is_and(e)) 
 | 
			
		||||
            args->append(to_app(e)->get_num_args(), to_app(e)->get_args());
 | 
			
		||||
        else if (m.is_not(e, e) && m.is_or(e)) 
 | 
			
		||||
            for (expr* arg : *to_app(e)) 
 | 
			
		||||
                args->push_back(::mk_not(m, arg));
 | 
			
		||||
        else 
 | 
			
		||||
            continue;
 | 
			
		||||
    drop:
 | 
			
		||||
        (*args)[i] = args->back();
 | 
			
		||||
        args->pop_back();
 | 
			
		||||
        --i;
 | 
			
		||||
    }
 | 
			
		||||
    return args->size() > 1;
 | 
			
		||||
#else
 | 
			
		||||
    if (m.is_and(e)) {
 | 
			
		||||
        if (args) {
 | 
			
		||||
            args->reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -185,9 +230,11 @@ bool hoist_rewriter::is_and(expr * e, expr_ref_vector* args) {
 | 
			
		|||
            args->reset();
 | 
			
		||||
            for (expr* arg : *to_app(e)) 
 | 
			
		||||
                args->push_back(::mk_not(m, arg));
 | 
			
		||||
            TRACE("hoist", tout << args << " " <<  * args << "\n");
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,9 +25,11 @@ Notes:
 | 
			
		|||
#include "util/union_find.h"
 | 
			
		||||
#include "util/obj_hashtable.h"
 | 
			
		||||
 | 
			
		||||
class bool_rewriter;
 | 
			
		||||
 | 
			
		||||
class hoist_rewriter {
 | 
			
		||||
    ast_manager &                   m;
 | 
			
		||||
    expr_ref_vector                 m_args1, m_args2;
 | 
			
		||||
    expr_ref_vector                 m_args1, m_args2, m_refs;
 | 
			
		||||
    obj_hashtable<expr>             m_preds1, m_preds2;
 | 
			
		||||
    basic_union_find                m_uf1, m_uf2, m_uf0;
 | 
			
		||||
    ptr_vector<expr>                m_es;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,8 +39,11 @@ class hoist_rewriter {
 | 
			
		|||
    obj_map<expr, unsigned>         m_expr2var;
 | 
			
		||||
    ptr_vector<expr>                m_var2expr;
 | 
			
		||||
    expr_mark                       m_mark;
 | 
			
		||||
    bool                            m_elim_and = false;
 | 
			
		||||
 | 
			
		||||
    bool is_and(expr* e, expr_ref_vector* args);
 | 
			
		||||
    expr_ref mk_and(expr_ref_vector const& args);
 | 
			
		||||
    expr_ref mk_or(expr_ref_vector const& args);
 | 
			
		||||
 | 
			
		||||
    bool is_var(expr* e) { return m_expr2var.contains(e); }
 | 
			
		||||
    expr* mk_expr(unsigned v) { return m_var2expr[v]; }
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +53,7 @@ class hoist_rewriter {
 | 
			
		|||
 | 
			
		||||
    expr_ref hoist_predicates(obj_hashtable<expr> const& p, unsigned num_args, expr* const* args);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    hoist_rewriter(ast_manager & m, params_ref const & p = params_ref());
 | 
			
		||||
    family_id get_fid() const { return m.get_basic_family_id(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +62,7 @@ public:
 | 
			
		|||
    static void get_param_descrs(param_descrs & r) {}
 | 
			
		||||
    br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);    
 | 
			
		||||
    br_status mk_or(unsigned num_args, expr * const * args, expr_ref & result);    
 | 
			
		||||
    void set_elim_and(bool b) { m_elim_and = b; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hoist_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ br_status maximize_ac_sharing::reduce_app(func_decl * f, unsigned num_args, expr
 | 
			
		|||
            else {
 | 
			
		||||
                result = m.mk_app(f, numeral, _args[0]);
 | 
			
		||||
            }
 | 
			
		||||
            TRACE("ac_sharing_detail", tout << "result: " << mk_pp(result, m) << "\n";);
 | 
			
		||||
            TRACE("ac_sharing_detail", tout << "result: " << result << "\n";);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -825,16 +825,17 @@ struct pb2bv_rewriter::imp {
 | 
			
		|||
            if (a->get_family_id() == au.get_family_id()) {
 | 
			
		||||
                switch (a->get_decl_kind()) {
 | 
			
		||||
                case OP_ADD:
 | 
			
		||||
                    for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
                        if (!is_pb(a->get_arg(i), mul)) return false;
 | 
			
		||||
                    }
 | 
			
		||||
                    for (unsigned i = 0; i < sz; ++i) 
 | 
			
		||||
                        if (!is_pb(a->get_arg(i), mul)) 
 | 
			
		||||
                            return false;
 | 
			
		||||
                    return true;
 | 
			
		||||
                case OP_SUB: {
 | 
			
		||||
                    if (!is_pb(a->get_arg(0), mul)) return false;
 | 
			
		||||
                    if (!is_pb(a->get_arg(0), mul)) 
 | 
			
		||||
                        return false;
 | 
			
		||||
                    r = -mul;
 | 
			
		||||
                    for (unsigned i = 1; i < sz; ++i) {
 | 
			
		||||
                        if (!is_pb(a->get_arg(1), r)) return false;
 | 
			
		||||
                    }
 | 
			
		||||
                    for (unsigned i = 1; i < sz; ++i) 
 | 
			
		||||
                        if (!is_pb(a->get_arg(i), r)) 
 | 
			
		||||
                            return false;
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                case OP_UMINUS:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ Revision History:
 | 
			
		|||
 | 
			
		||||
--*/
 | 
			
		||||
#include "ast/rewriter/push_app_ite.h"
 | 
			
		||||
#include "ast/rewriter/rewriter_def.h"
 | 
			
		||||
#include "ast/ast_pp.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -347,7 +347,7 @@ public:
 | 
			
		|||
    Config & cfg() { return m_cfg; }
 | 
			
		||||
    Config const & cfg() const { return m_cfg; }
 | 
			
		||||
 | 
			
		||||
    ~rewriter_tpl() override;
 | 
			
		||||
    ~rewriter_tpl() override {};
 | 
			
		||||
    
 | 
			
		||||
    void reset();
 | 
			
		||||
    void cleanup();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -640,10 +640,6 @@ rewriter_tpl<Config>::rewriter_tpl(ast_manager & m, bool proof_gen, Config & cfg
 | 
			
		|||
    m_pr2(m) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Config>
 | 
			
		||||
rewriter_tpl<Config>::~rewriter_tpl() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename Config>
 | 
			
		||||
void rewriter_tpl<Config>::reset() {
 | 
			
		||||
    m_cfg.reset();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -513,8 +513,8 @@ namespace seq {
 | 
			
		|||
 | 
			
		||||
       !contains(t, s) => i = -1   
 | 
			
		||||
       |t| = 0 => |s| = 0 or i = -1
 | 
			
		||||
       |t| = 0 & |s| = 0 => i = 0
 | 
			
		||||
       |t| != 0 & contains(t, s) => t = xsy & i = len(x) 
 | 
			
		||||
       |s| = 0 => i = len(t)
 | 
			
		||||
       |s| = 0 or s = s_head*s_tail
 | 
			
		||||
       |s| = 0 or !contains(s_tail*y, s)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -540,7 +540,7 @@ namespace seq {
 | 
			
		|||
 | 
			
		||||
        add_clause(cnt, i_eq_m1);
 | 
			
		||||
        add_clause(~t_eq_empty, s_eq_empty, i_eq_m1);
 | 
			
		||||
        add_clause(~t_eq_empty, ~s_eq_empty, i_eq_0);
 | 
			
		||||
        add_clause(~s_eq_empty, mk_eq(i, mk_len(t)));
 | 
			
		||||
        add_clause(t_eq_empty, ~cnt, mk_seq_eq(t, xsy));
 | 
			
		||||
        add_clause(t_eq_empty, ~cnt, mk_eq(i, mk_len(x)));
 | 
			
		||||
        add_clause(s_eq_empty, mk_eq(s, mk_concat(s_head, s_tail)));
 | 
			
		||||
| 
						 | 
				
			
			@ -928,7 +928,6 @@ namespace seq {
 | 
			
		|||
       e1 < e2 => prefix(e1, e2) or e1 = xcy 
 | 
			
		||||
       e1 < e2 => prefix(e1, e2) or c < d 
 | 
			
		||||
       e1 < e2 => prefix(e1, e2) or e2 = xdz 
 | 
			
		||||
       e1 < e2 => e1 != e2
 | 
			
		||||
       !(e1 < e2) => prefix(e2, e1) or e2 = xdz 
 | 
			
		||||
       !(e1 < e2) => prefix(e2, e1) or d < c 
 | 
			
		||||
       !(e1 < e2) => prefix(e2, e1) or e1 = xcy 
 | 
			
		||||
| 
						 | 
				
			
			@ -938,6 +937,7 @@ namespace seq {
 | 
			
		|||
       e1 < e2 or e1 = e2 or e2 < e1 
 | 
			
		||||
       !(e1 = e2) or !(e2 < e1) 
 | 
			
		||||
       !(e1 < e2) or !(e2 < e1)
 | 
			
		||||
 | 
			
		||||
    */
 | 
			
		||||
    void axioms::lt_axiom(expr* n) {
 | 
			
		||||
        expr* _e1 = nullptr, *_e2 = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -948,6 +948,7 @@ namespace seq {
 | 
			
		|||
        sort* char_sort = nullptr;
 | 
			
		||||
        VERIFY(seq.is_seq(s, char_sort));
 | 
			
		||||
        expr_ref lt = expr_ref(n, m);
 | 
			
		||||
        expr_ref gt = expr_ref(seq.str.mk_lex_lt(e2, e1), m);
 | 
			
		||||
        expr_ref x = m_sk.mk("str.<.x", e1, e2);
 | 
			
		||||
        expr_ref y = m_sk.mk("str.<.y", e1, e2);
 | 
			
		||||
        expr_ref z = m_sk.mk("str.<.z", e1, e2);
 | 
			
		||||
| 
						 | 
				
			
			@ -969,6 +970,7 @@ namespace seq {
 | 
			
		|||
        add_clause(lt, pref21, ltdc);
 | 
			
		||||
        add_clause(lt, pref21, e2xdz);
 | 
			
		||||
        add_clause(~eq, ~lt);
 | 
			
		||||
        add_clause(eq, lt, gt); 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -1235,7 +1237,7 @@ namespace seq {
 | 
			
		|||
            seq.str.is_string(x)) {
 | 
			
		||||
            expr_ref len(n, m);
 | 
			
		||||
            m_rewrite(len);
 | 
			
		||||
            SASSERT(n != len);
 | 
			
		||||
            SASSERT(m.limit().is_canceled() || n != len);
 | 
			
		||||
            add_clause(mk_eq(len, n));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -190,8 +190,8 @@ namespace seq {
 | 
			
		|||
            expr_ref digit = m_ax.sk().mk_digit2int(u);
 | 
			
		||||
            add_consequence(m_ax.mk_ge(digit, 1));
 | 
			
		||||
        }
 | 
			
		||||
	    expr_ref y(seq.str.mk_concat(es, es[0]->get_sort()), m);
 | 
			
		||||
	    ctx.add_solution(seq.str.mk_itos(n), y);
 | 
			
		||||
        expr_ref y(seq.str.mk_concat(es, es[0]->get_sort()), m);
 | 
			
		||||
        ctx.add_solution(seq.str.mk_itos(n), y);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5024,12 +5024,14 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
 | 
			
		|||
 * (re.range c_1 c_n) 
 | 
			
		||||
 */
 | 
			
		||||
br_status seq_rewriter::mk_re_range(expr* lo, expr* hi, expr_ref& result) {
 | 
			
		||||
    zstring s;
 | 
			
		||||
    zstring slo, shi;
 | 
			
		||||
    unsigned len = 0;
 | 
			
		||||
    bool is_empty = false;
 | 
			
		||||
    if (str().is_string(lo, s) && s.length() != 1) 
 | 
			
		||||
    if (str().is_string(lo, slo) && slo.length() != 1) 
 | 
			
		||||
        is_empty = true;
 | 
			
		||||
    if (str().is_string(hi, s) && s.length() != 1) 
 | 
			
		||||
    if (str().is_string(hi, shi) && shi.length() != 1) 
 | 
			
		||||
        is_empty = true;
 | 
			
		||||
    if (slo.length() == 1 && shi.length() == 1 && slo[0] > shi[0])
 | 
			
		||||
        is_empty = true;
 | 
			
		||||
    len = min_length(lo).second;
 | 
			
		||||
    if (len > 1)
 | 
			
		||||
| 
						 | 
				
			
			@ -5246,7 +5248,17 @@ br_status seq_rewriter::reduce_re_is_empty(expr* r, expr_ref& result) {
 | 
			
		|||
    else if (re().is_range(r, r1, r2) && 
 | 
			
		||||
             str().is_string(r1, s1) && str().is_string(r2, s2) && 
 | 
			
		||||
             s1.length() == 1 && s2.length() == 1) {
 | 
			
		||||
        result = m().mk_bool_val(s1[0] <= s2[0]);
 | 
			
		||||
        result = m().mk_bool_val(s1[0] > s2[0]);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    else if (re().is_range(r, r1, r2) && 
 | 
			
		||||
             str().is_string(r1, s1) && s1.length() != 1) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    else if (re().is_range(r, r1, r2) && 
 | 
			
		||||
             str().is_string(r2, s2) && s2.length() != 1) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    else if ((re().is_loop(r, r1, lo) ||
 | 
			
		||||
| 
						 | 
				
			
			@ -5307,6 +5319,7 @@ br_status seq_rewriter::mk_le_core(expr * l, expr * r, expr_ref & result) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_eq_core(expr * l, expr * r, expr_ref & result) {
 | 
			
		||||
    TRACE("seq", tout << mk_pp(l, m()) << " == " << mk_pp(r, m()) << "\n");
 | 
			
		||||
    expr_ref_vector res(m());
 | 
			
		||||
    expr_ref_pair_vector new_eqs(m());
 | 
			
		||||
    if (m_util.is_re(l)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5518,6 +5531,7 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
 | 
			
		|||
        reduce_front(ls, rs, eqs) &&
 | 
			
		||||
        reduce_itos(ls, rs, eqs) &&
 | 
			
		||||
        reduce_itos(rs, ls, eqs) &&
 | 
			
		||||
        reduce_value_clash(ls, rs, eqs) && 
 | 
			
		||||
        reduce_by_length(ls, rs, eqs) &&
 | 
			
		||||
        reduce_subsequence(ls, rs, eqs) &&
 | 
			
		||||
        reduce_non_overlap(ls, rs, eqs) && 
 | 
			
		||||
| 
						 | 
				
			
			@ -5943,6 +5957,47 @@ bool seq_rewriter::reduce_non_overlap(expr_ref_vector& ls, expr_ref_vector& rs,
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * partial check for value clash.
 | 
			
		||||
 * checks that elements that do not occur in 
 | 
			
		||||
 * other sequence are non-values.
 | 
			
		||||
 * The check could be extended to take non-value 
 | 
			
		||||
 * characters (units) into account.
 | 
			
		||||
 */
 | 
			
		||||
bool seq_rewriter::reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
 | 
			
		||||
    ptr_buffer<expr> es;
 | 
			
		||||
 | 
			
		||||
    if (ls.empty() || rs.empty())
 | 
			
		||||
        return true;
 | 
			
		||||
    es.append(ls.size(), ls.data());
 | 
			
		||||
    auto remove = [&](expr* r) {
 | 
			
		||||
        for (unsigned i = 0; i < es.size(); ++i) {
 | 
			
		||||
            if (r == es[i]) {
 | 
			
		||||
                es[i] = es.back();
 | 
			
		||||
                es.pop_back();
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;                
 | 
			
		||||
    };
 | 
			
		||||
    auto is_unit_value = [&](expr* r) {
 | 
			
		||||
        return m().is_value(r) && str().is_unit(r);
 | 
			
		||||
    };
 | 
			
		||||
    for (expr* r : rs) {
 | 
			
		||||
        if (remove(r))
 | 
			
		||||
            continue;
 | 
			
		||||
        if (!is_unit_value(r))
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
    if (es.empty())
 | 
			
		||||
        return true;
 | 
			
		||||
    for (expr* e : es)
 | 
			
		||||
        if (!is_unit_value(e))
 | 
			
		||||
            return true;
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool seq_rewriter::reduce_subsequence(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& eqs) {
 | 
			
		||||
 | 
			
		||||
    if (ls.size() > rs.size()) 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -340,6 +340,7 @@ class seq_rewriter {
 | 
			
		|||
    bool is_sequence(expr* e, expr_ref_vector& seq);
 | 
			
		||||
    bool is_sequence(eautomaton& aut, expr_ref_vector& seq);
 | 
			
		||||
    bool get_lengths(expr* e, expr_ref_vector& lens, rational& pos);
 | 
			
		||||
    bool reduce_value_clash(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
 | 
			
		||||
    bool reduce_back(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
 | 
			
		||||
    bool reduce_front(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_pair_vector& new_eqs);
 | 
			
		||||
    void remove_empty_and_concats(expr_ref_vector& es);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ Notes:
 | 
			
		|||
#include "ast/rewriter/seq_rewriter.h"
 | 
			
		||||
#include "ast/rewriter/rewriter_def.h"
 | 
			
		||||
#include "ast/rewriter/var_subst.h"
 | 
			
		||||
#include "ast/rewriter/der.h"
 | 
			
		||||
#include "ast/rewriter/expr_safe_replace.h"
 | 
			
		||||
#include "ast/expr_substitution.h"
 | 
			
		||||
#include "ast/ast_smt2_pp.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -54,6 +55,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		|||
    recfun_rewriter     m_rec_rw;
 | 
			
		||||
    arith_util          m_a_util;
 | 
			
		||||
    bv_util             m_bv_util;
 | 
			
		||||
    der                 m_der;
 | 
			
		||||
    expr_safe_replace   m_rep;
 | 
			
		||||
    expr_ref_vector     m_pinned;
 | 
			
		||||
      // substitution support
 | 
			
		||||
| 
						 | 
				
			
			@ -821,6 +823,26 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		|||
 | 
			
		||||
        TRACE("reduce_quantifier", tout << "after elim_unused_vars:\n" << result << " " << result_pr << "\n" ;);
 | 
			
		||||
 | 
			
		||||
        proof_ref p2(m());
 | 
			
		||||
        expr_ref r(m());
 | 
			
		||||
 | 
			
		||||
        bool der_change = false;
 | 
			
		||||
        if (is_quantifier(result) && to_quantifier(result)->get_num_patterns() == 0) {
 | 
			
		||||
            m_der(to_quantifier(result), r, p2);
 | 
			
		||||
            der_change = result.get() != r.get();
 | 
			
		||||
            if (m().proofs_enabled() && der_change)
 | 
			
		||||
                result_pr = m().mk_transitivity(result_pr, p2);            
 | 
			
		||||
            result = r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (der_change) {
 | 
			
		||||
            th_rewriter rw(m());
 | 
			
		||||
            rw(result, r, p2);
 | 
			
		||||
            if (m().proofs_enabled() && result.get() != r.get()) 
 | 
			
		||||
                result_pr = m().mk_transitivity(result_pr, p2);
 | 
			
		||||
            result = r;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        SASSERT(old_q->get_sort() == result->get_sort());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -839,6 +861,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		|||
        m_rec_rw(m),
 | 
			
		||||
        m_a_util(m),
 | 
			
		||||
        m_bv_util(m),
 | 
			
		||||
        m_der(m),
 | 
			
		||||
        m_rep(m),
 | 
			
		||||
        m_pinned(m),
 | 
			
		||||
        m_used_dependencies(m) {
 | 
			
		||||
| 
						 | 
				
			
			@ -944,17 +967,41 @@ void th_rewriter::reset() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void th_rewriter::operator()(expr_ref & term) {
 | 
			
		||||
    expr_ref result(term.get_manager());
 | 
			
		||||
    m_imp->operator()(term, result);
 | 
			
		||||
    term = std::move(result);
 | 
			
		||||
    expr_ref result(term.get_manager());    
 | 
			
		||||
    try {
 | 
			
		||||
        m_imp->operator()(term, result);
 | 
			
		||||
        term = std::move(result);
 | 
			
		||||
    }
 | 
			
		||||
    catch (...) {
 | 
			
		||||
        if (!term.get_manager().inc())
 | 
			
		||||
            return;
 | 
			
		||||
        throw;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void th_rewriter::operator()(expr * t, expr_ref & result) {
 | 
			
		||||
    m_imp->operator()(t, result);
 | 
			
		||||
    try {
 | 
			
		||||
        m_imp->operator()(t, result);
 | 
			
		||||
    }
 | 
			
		||||
    catch (...) {
 | 
			
		||||
        result = t;
 | 
			
		||||
        if (!result.get_manager().inc())
 | 
			
		||||
            return;
 | 
			
		||||
        throw;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void th_rewriter::operator()(expr * t, expr_ref & result, proof_ref & result_pr) {
 | 
			
		||||
    m_imp->operator()(t, result, result_pr);
 | 
			
		||||
    try {
 | 
			
		||||
        m_imp->operator()(t, result, result_pr);
 | 
			
		||||
    }
 | 
			
		||||
    catch (...) {
 | 
			
		||||
        result = t;
 | 
			
		||||
        result_pr = nullptr;
 | 
			
		||||
        if (!result.get_manager().inc())
 | 
			
		||||
            return;
 | 
			
		||||
        throw;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref th_rewriter::operator()(expr * n, unsigned num_bindings, expr * const * bindings) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -663,19 +663,21 @@ void seq_decl_plugin::add_map_sig() {
 | 
			
		|||
    m_sigs[OP_SEQ_MAP]       = alloc(psig, m, "seq.map",      2, 2, arrABseqA, seqB);
 | 
			
		||||
    m_sigs[OP_SEQ_MAPI]      = alloc(psig, m, "seq.mapi",     2, 3, arrIABintTseqA, seqB);
 | 
			
		||||
    m_sigs[OP_SEQ_FOLDL]     = alloc(psig, m, "seq.fold_left",    2, 3, arrBAB_BseqA, B);
 | 
			
		||||
    m_sigs[OP_SEQ_FOLDLI]    = alloc(psig, m, "seq.fold_leftli",   2, 4, arrIBABintTBseqA, B);
 | 
			
		||||
    m_sigs[OP_SEQ_FOLDLI]    = alloc(psig, m, "seq.fold_lefti",   2, 4, arrIBABintTBseqA, B);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seq_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
 | 
			
		||||
    init();
 | 
			
		||||
    for (unsigned i = 0; i < m_sigs.size(); ++i) {
 | 
			
		||||
        if (m_sigs[i]) 
 | 
			
		||||
            op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));        
 | 
			
		||||
        if (m_sigs[i])
 | 
			
		||||
            op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));
 | 
			
		||||
    }
 | 
			
		||||
    op_names.push_back(builtin_name("seq.map",    OP_SEQ_MAP));
 | 
			
		||||
    op_names.push_back(builtin_name("seq.mapi",   OP_SEQ_MAPI));
 | 
			
		||||
    op_names.push_back(builtin_name("seq.foldl",  OP_SEQ_FOLDL));
 | 
			
		||||
    op_names.push_back(builtin_name("seq.foldli", OP_SEQ_FOLDLI));
 | 
			
		||||
    op_names.push_back(builtin_name("seq.fold_lefti", OP_SEQ_FOLDLI));
 | 
			
		||||
    op_names.push_back(builtin_name("seq.fold_left",  OP_SEQ_FOLDL));
 | 
			
		||||
    op_names.push_back(builtin_name("str.in.re", _OP_STRING_IN_REGEXP));
 | 
			
		||||
    op_names.push_back(builtin_name("str.in-re", _OP_STRING_IN_REGEXP));
 | 
			
		||||
    op_names.push_back(builtin_name("str.to.re", _OP_STRING_TO_REGEXP));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -81,7 +81,7 @@ void dependent_expr_state::freeze_recfun() {
 | 
			
		|||
    ast_mark visited;
 | 
			
		||||
    for (func_decl* f : rec.get_rec_funs()) {
 | 
			
		||||
        auto& d = rec.get_def(f);
 | 
			
		||||
        if (!d.is_macro()) 
 | 
			
		||||
        if (!d.is_macro() && d.get_rhs())
 | 
			
		||||
            freeze_terms(d.get_rhs(), false, visited);
 | 
			
		||||
    }
 | 
			
		||||
    m_trail.push(value_trail(m_num_recfun));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ class dominator_simplifier : public dependent_expr_simplifier {
 | 
			
		|||
    bool is_subexpr(expr * a, expr * b);
 | 
			
		||||
 | 
			
		||||
    expr_ref get_cached(expr* t) { expr* r = nullptr; if (!m_result.find(t, r)) r = t; return expr_ref(r, m); }
 | 
			
		||||
    void cache(expr *t, expr* r) { m_result.insert(t, r); m_trail.push_back(r); }
 | 
			
		||||
    void cache(expr *t, expr* r) { m_result.insert(t, r); m_trail.push_back(r); m_trail.push_back(t); }
 | 
			
		||||
    void reset_cache() { m_result.reset(); }
 | 
			
		||||
 | 
			
		||||
    ptr_vector<expr> const & tree(expr * e);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,9 +52,9 @@ monotonicity or reflexivity rules.
 | 
			
		|||
#include "ast/simplifiers/elim_unconstrained.h"
 | 
			
		||||
 | 
			
		||||
elim_unconstrained::elim_unconstrained(ast_manager& m, dependent_expr_state& fmls) :
 | 
			
		||||
    dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m) {
 | 
			
		||||
    dependent_expr_simplifier(m, fmls), m_inverter(m), m_lt(*this), m_heap(1024, m_lt), m_trail(m), m_args(m) {
 | 
			
		||||
    std::function<bool(expr*)> is_var = [&](expr* e) {
 | 
			
		||||
        return is_uninterp_const(e) && !m_fmls.frozen(e) && get_node(e).m_refcount <= 1;
 | 
			
		||||
        return is_uninterp_const(e) && !m_fmls.frozen(e) && is_node(e) && get_node(e).m_refcount <= 1;
 | 
			
		||||
    };
 | 
			
		||||
    m_inverter.set_is_var(is_var);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ void elim_unconstrained::eliminate() {
 | 
			
		|||
        node& n = get_node(v);
 | 
			
		||||
        if (n.m_refcount == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
        if (n.m_refcount > 1)
 | 
			
		||||
        if (n.m_refcount > 1) 
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        if (n.m_parents.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -90,10 +90,10 @@ void elim_unconstrained::eliminate() {
 | 
			
		|||
        unsigned sz = m_args.size();
 | 
			
		||||
        for (expr* arg : *to_app(t))
 | 
			
		||||
            m_args.push_back(reconstruct_term(get_node(arg)));
 | 
			
		||||
        bool inverted = m_inverter(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz, r);
 | 
			
		||||
        bool inverted = m_inverter(t->get_decl(), t->get_num_args(), m_args.data() + sz, r);
 | 
			
		||||
        proof_ref pr(m);
 | 
			
		||||
        if (inverted && m_enable_proofs) {
 | 
			
		||||
            expr * s    = m.mk_app(t->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz);
 | 
			
		||||
            expr * s    = m.mk_app(t->get_decl(), t->get_num_args(), m_args.data() + sz);
 | 
			
		||||
            expr * eq   = m.mk_eq(s, r);
 | 
			
		||||
            proof * pr1 = m.mk_def_intro(eq);
 | 
			
		||||
            proof * pr  = m.mk_apply_def(s, r, pr1);
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ void elim_unconstrained::eliminate() {
 | 
			
		|||
        gc(e);
 | 
			
		||||
        invalidate_parents(e);
 | 
			
		||||
        freeze_rec(r);
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        m_root.setx(r->get_id(), e->get_id(), UINT_MAX);
 | 
			
		||||
        get_node(e).m_term = r;
 | 
			
		||||
        get_node(e).m_proof = pr;
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +291,7 @@ expr_ref elim_unconstrained::reconstruct_term(node& n0) {
 | 
			
		|||
        unsigned sz0 = todo.size();
 | 
			
		||||
        if (is_app(t)) {            
 | 
			
		||||
            for (expr* arg : *to_app(t)) 
 | 
			
		||||
                if (get_node(arg).m_dirty)
 | 
			
		||||
                if (get_node(arg).m_dirty || !get_node(arg).m_term)
 | 
			
		||||
                    todo.push_back(arg);
 | 
			
		||||
            if (todo.size() != sz0)
 | 
			
		||||
                continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -300,18 +300,20 @@ expr_ref elim_unconstrained::reconstruct_term(node& n0) {
 | 
			
		|||
            for (expr* arg : *to_app(t)) 
 | 
			
		||||
                m_args.push_back(get_node(arg).m_term);            
 | 
			
		||||
            n.m_term = m.mk_app(to_app(t)->get_decl(), to_app(t)->get_num_args(), m_args.data() + sz);
 | 
			
		||||
 | 
			
		||||
            m_args.shrink(sz);
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_quantifier(t)) {
 | 
			
		||||
            expr* body = to_quantifier(t)->get_expr();
 | 
			
		||||
            node& n2 = get_node(body);
 | 
			
		||||
            if (n2.m_dirty) {
 | 
			
		||||
            if (n2.m_dirty || !n2.m_term) {
 | 
			
		||||
                todo.push_back(body);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            n.m_term = m.update_quantifier(to_quantifier(t), n2.m_term);            
 | 
			
		||||
        }
 | 
			
		||||
        m_trail.push_back(n.m_term);
 | 
			
		||||
        m_root.setx(n.m_term->get_id(), n.m_term->get_id(), UINT_MAX);
 | 
			
		||||
        todo.pop_back();
 | 
			
		||||
        n.m_dirty = false;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,8 @@ Author:
 | 
			
		|||
 | 
			
		||||
class elim_unconstrained : public dependent_expr_simplifier {
 | 
			
		||||
 | 
			
		||||
    friend class seq_simplifier;
 | 
			
		||||
    
 | 
			
		||||
    struct node {
 | 
			
		||||
        unsigned         m_refcount = 0;
 | 
			
		||||
        expr*            m_term = nullptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,13 +48,15 @@ class elim_unconstrained : public dependent_expr_simplifier {
 | 
			
		|||
    var_lt                   m_lt;
 | 
			
		||||
    heap<var_lt>             m_heap;
 | 
			
		||||
    expr_ref_vector          m_trail;
 | 
			
		||||
    ptr_vector<expr>         m_args;
 | 
			
		||||
    expr_ref_vector          m_args;
 | 
			
		||||
    stats                    m_stats;
 | 
			
		||||
    unsigned_vector          m_root;
 | 
			
		||||
    bool                     m_created_compound = false;
 | 
			
		||||
    bool                     m_enable_proofs = false;
 | 
			
		||||
 | 
			
		||||
    bool is_var_lt(int v1, int v2) const;
 | 
			
		||||
    bool is_node(unsigned n) const { return m_nodes.size() > n; }
 | 
			
		||||
    bool is_node(expr* t) const { return is_node(t->get_id()); }
 | 
			
		||||
    node& get_node(unsigned n) { return m_nodes[n]; }
 | 
			
		||||
    node const& get_node(unsigned n) const { return m_nodes[n]; }
 | 
			
		||||
    node& get_node(expr* t) { return m_nodes[root(t)]; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,7 +174,7 @@ bool eliminate_predicates::can_be_quasi_macro_head(expr* _head, unsigned num_bou
 | 
			
		|||
// then replace (f x y z) by (if (= z (+ x y)) s (f' x y z))
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause const& cl) {
 | 
			
		||||
void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause& cl) {
 | 
			
		||||
    expr_ref _body(body, m);
 | 
			
		||||
    uint_set indices;
 | 
			
		||||
    expr_ref_vector args(m), eqs(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -205,9 +205,10 @@ void eliminate_predicates::insert_quasi_macro(app* head, expr* body, clause cons
 | 
			
		|||
    
 | 
			
		||||
    // forall vars . f(args) = if eqs then body else f'(args)
 | 
			
		||||
    f1 = m.mk_fresh_func_decl(f->get_name(), symbol::null, sorts.size(), sorts.data(), f->get_range());
 | 
			
		||||
 | 
			
		||||
    lhs = m.mk_app(f, args);
 | 
			
		||||
    rhs = m.mk_ite(mk_and(eqs), body, m.mk_app(f1, args));
 | 
			
		||||
    insert_macro(lhs, rhs, cl.m_dep);
 | 
			
		||||
    insert_macro(lhs, rhs, cl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -310,6 +311,12 @@ bool eliminate_predicates::is_macro_safe(expr* e) {
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eliminate_predicates::insert_macro(app* head, expr* def, clause& cl) {
 | 
			
		||||
    insert_macro(head, def, cl.m_dep);
 | 
			
		||||
    TRACE("elim_predicates", tout << "remove " << cl << "\n");
 | 
			
		||||
    cl.m_alive = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eliminate_predicates::insert_macro(app* head, expr* def, expr_dependency* dep) {
 | 
			
		||||
    unsigned num = head->get_num_args();
 | 
			
		||||
    ptr_buffer<expr> vars, subst_args;
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +341,7 @@ void eliminate_predicates::insert_macro(app* head, expr* def, expr_dependency* d
 | 
			
		|||
    auto* info = alloc(macro_def, _head, _def, _dep);
 | 
			
		||||
    m_macros.insert(head->get_decl(), info);
 | 
			
		||||
    m_fmls.model_trail().push(head->get_decl(), _def, _dep, {}); // augment with definition for head
 | 
			
		||||
    m_is_macro.mark(head->get_decl(), true);
 | 
			
		||||
    m_is_macro.mark(head->get_decl(), true);    
 | 
			
		||||
    TRACE("elim_predicates", tout << "insert " << _head << " " << _def << "\n");
 | 
			
		||||
    ++m_stats.m_num_macros;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -367,26 +374,22 @@ void eliminate_predicates::try_find_macro(clause& cl) {
 | 
			
		|||
    // (= (f x) t)
 | 
			
		||||
    if (cl.is_unit() && !cl.sign(0) && m.is_eq(cl.atom(0), x, y)) {
 | 
			
		||||
        if (can_be_def(x, y)) {
 | 
			
		||||
            insert_macro(to_app(x), y, cl.m_dep);
 | 
			
		||||
            cl.m_alive = false;
 | 
			
		||||
            insert_macro(to_app(x), y, cl);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (can_be_def(y, x)) {
 | 
			
		||||
            insert_macro(to_app(y), x, cl.m_dep);
 | 
			
		||||
            cl.m_alive = false;
 | 
			
		||||
            insert_macro(to_app(y), x, cl);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // not (= (p x) t) -> (p x) = (not t)
 | 
			
		||||
    if (cl.is_unit() && cl.sign(0) && m.is_iff(cl.atom(0), x, y)) {
 | 
			
		||||
        if (can_be_def(x, y)) {
 | 
			
		||||
            insert_macro(to_app(x), m.mk_not(y), cl.m_dep);
 | 
			
		||||
            cl.m_alive = false;
 | 
			
		||||
            insert_macro(to_app(x), m.mk_not(y), cl);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (can_be_def(y, x)) {
 | 
			
		||||
            insert_macro(to_app(y), m.mk_not(x), cl.m_dep);
 | 
			
		||||
            cl.m_alive = false;
 | 
			
		||||
            insert_macro(to_app(y), m.mk_not(x), cl);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -413,8 +416,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
 | 
			
		|||
        m_fmls.model_trail().hide(fn); // hide definition of fn
 | 
			
		||||
        k = m.mk_app(fn, f->get_num_args(), f->get_args());        
 | 
			
		||||
        def = m.mk_ite(cond, t, k);
 | 
			
		||||
        insert_macro(f, def, cl.m_dep);
 | 
			
		||||
        cl.m_alive = false;
 | 
			
		||||
        insert_macro(f, def, cl);
 | 
			
		||||
        fml = m.mk_not(m.mk_eq(k, t));
 | 
			
		||||
        clause* new_cl = init_clause(fml, cl.m_dep, UINT_MAX);
 | 
			
		||||
        add_use_list(*new_cl);
 | 
			
		||||
| 
						 | 
				
			
			@ -531,8 +533,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
 | 
			
		|||
                expr_ref y1 = subtract(y, to_app(x), i);
 | 
			
		||||
                if (inv) 
 | 
			
		||||
                    y1 = uminus(y1);                
 | 
			
		||||
                insert_macro(to_app(arg), y1, cl.m_dep);
 | 
			
		||||
                cl.m_alive = false;
 | 
			
		||||
                insert_macro(to_app(arg), y1, cl);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        next:
 | 
			
		||||
| 
						 | 
				
			
			@ -572,7 +573,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
 | 
			
		|||
            !occurs(x->get_decl(), y);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (cl.is_unit() && m.is_eq(cl.atom(0), x, y)) {
 | 
			
		||||
    if (cl.is_unit() && m.is_eq(cl.atom(0), x, y) && !cl.m_bound.empty()) {
 | 
			
		||||
        if (!cl.sign(0) && can_be_qdef(x, y)) {
 | 
			
		||||
            insert_quasi_macro(to_app(x), y, cl);
 | 
			
		||||
            return;
 | 
			
		||||
| 
						 | 
				
			
			@ -590,7 +591,7 @@ void eliminate_predicates::try_find_macro(clause& cl) {
 | 
			
		|||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (cl.is_unit()) {
 | 
			
		||||
    if (cl.is_unit() && !cl.m_bound.empty()) {
 | 
			
		||||
        expr* body = cl.sign(0) ? m.mk_false() : m.mk_true();
 | 
			
		||||
        expr* x = cl.atom(0);
 | 
			
		||||
        if (can_be_qdef(x, body)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -736,6 +737,7 @@ void eliminate_predicates::update_model(func_decl* p) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    rewrite(def);
 | 
			
		||||
    TRACE("elim_predicates", tout << "insert " << p->get_name() << " " << def << "\n");
 | 
			
		||||
    m_fmls.model_trail().push(p, def, dep, deleted);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,8 +1010,6 @@ void eliminate_predicates::reset() {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void eliminate_predicates::reduce() {
 | 
			
		||||
    if (!m_fmls.has_quantifiers())
 | 
			
		||||
        return;
 | 
			
		||||
    reset();
 | 
			
		||||
    init_clauses();
 | 
			
		||||
    find_definitions();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,9 +111,10 @@ private:
 | 
			
		|||
    bool try_find_binary_definition(func_decl* p, app_ref& head, expr_ref& def, expr_dependency_ref& dep);
 | 
			
		||||
    void try_resolve_definition(func_decl* p);
 | 
			
		||||
    void insert_macro(app* head, expr* def, expr_dependency* dep);
 | 
			
		||||
    void insert_macro(app* head, expr* def, clause& cl);
 | 
			
		||||
    expr_ref bind_free_variables_in_def(clause& cl, app* head, expr* def);
 | 
			
		||||
    bool can_be_macro_head(expr* head, unsigned num_bound);
 | 
			
		||||
    void insert_quasi_macro(app* head, expr* body, clause const& cl);
 | 
			
		||||
    void insert_quasi_macro(app* head, expr* body, clause& cl);
 | 
			
		||||
    bool can_be_quasi_macro_head(expr* head, unsigned num_bound);
 | 
			
		||||
    bool is_macro_safe(expr* e);
 | 
			
		||||
    void try_find_macro(clause& cl);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -262,6 +262,47 @@ namespace euf {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void solve_eqs::collect_num_occs(expr * t, expr_fast_mark1 & visited) {
 | 
			
		||||
        ptr_buffer<app, 128> stack;
 | 
			
		||||
        
 | 
			
		||||
        auto visit = [&](expr* arg) {
 | 
			
		||||
            if (is_uninterp_const(arg))                    
 | 
			
		||||
                m_num_occs.insert_if_not_there(arg, 0)++;
 | 
			
		||||
            if (!visited.is_marked(arg) && is_app(arg)) {                          
 | 
			
		||||
                visited.mark(arg, true);                            
 | 
			
		||||
                stack.push_back(to_app(arg));                               
 | 
			
		||||
            }                                                       
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        visit(t);
 | 
			
		||||
        
 | 
			
		||||
        while (!stack.empty()) {
 | 
			
		||||
            app * t = stack.back();
 | 
			
		||||
            stack.pop_back();
 | 
			
		||||
            for (expr* arg : *t) 
 | 
			
		||||
                visit(arg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void solve_eqs::collect_num_occs() {
 | 
			
		||||
        if (m_config.m_max_occs == UINT_MAX)
 | 
			
		||||
            return; // no need to compute num occs
 | 
			
		||||
        m_num_occs.reset();
 | 
			
		||||
        expr_fast_mark1 visited;
 | 
			
		||||
        for (unsigned i : indices())
 | 
			
		||||
            collect_num_occs(m_fmls[i].fml(), visited);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check if the number of occurrences of t is below the specified threshold :solve-eqs-max-occs
 | 
			
		||||
    bool solve_eqs::check_occs(expr * t) const {
 | 
			
		||||
        if (m_config.m_max_occs == UINT_MAX)
 | 
			
		||||
            return true;
 | 
			
		||||
        unsigned num = 0;
 | 
			
		||||
        m_num_occs.find(t, num);
 | 
			
		||||
        TRACE("solve_eqs_check_occs", tout << mk_ismt2_pp(t, m) << " num_occs: " << num << " max: " << m_config.m_max_occs << "\n";);
 | 
			
		||||
        return num <= m_config.m_max_occs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void solve_eqs::save_subst(vector<dependent_expr> const& old_fmls) {
 | 
			
		||||
        if (!m_subst->empty())   
 | 
			
		||||
            m_fmls.model_trail().push(m_subst.detach(), old_fmls);                
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,10 +56,12 @@ namespace euf {
 | 
			
		|||
        expr_mark                     m_unsafe_vars;   // expressions that cannot be replaced
 | 
			
		||||
        ptr_vector<expr>              m_todo;
 | 
			
		||||
        expr_mark                     m_visited;
 | 
			
		||||
        obj_map<expr, unsigned>       m_num_occs;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        bool is_var(expr* e) const { return e->get_id() < m_var2id.size() && m_var2id[e->get_id()] != UINT_MAX; }
 | 
			
		||||
        unsigned var2id(expr* v) const { return m_var2id[v->get_id()]; }
 | 
			
		||||
        bool can_be_var(expr* e) const { return is_uninterp_const(e) && !m_unsafe_vars.is_marked(e); }
 | 
			
		||||
        bool can_be_var(expr* e) const { return is_uninterp_const(e) && !m_unsafe_vars.is_marked(e) && check_occs(e); }
 | 
			
		||||
        void get_eqs(dep_eq_vector& eqs);
 | 
			
		||||
        void filter_unsafe_vars();        
 | 
			
		||||
        void extract_subst();
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +69,9 @@ namespace euf {
 | 
			
		|||
        void normalize();
 | 
			
		||||
        void apply_subst(vector<dependent_expr>& old_fmls);
 | 
			
		||||
        void save_subst(vector<dependent_expr> const& old_fmls);
 | 
			
		||||
        void collect_num_occs(expr * t, expr_fast_mark1 & visited);
 | 
			
		||||
        void collect_num_occs();
 | 
			
		||||
        bool check_occs(expr* t) const;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ Copyright (c) 2022 Microsoft Corporation
 | 
			
		|||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    seq_simplifier.h
 | 
			
		||||
    then_simplifier.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ Author:
 | 
			
		|||
#include "ast/simplifiers/dependent_expr_state.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class seq_simplifier : public dependent_expr_simplifier {
 | 
			
		||||
class then_simplifier : public dependent_expr_simplifier {
 | 
			
		||||
    scoped_ptr_vector<dependent_expr_simplifier> m_simplifiers;
 | 
			
		||||
 | 
			
		||||
    struct collect_stats {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ class seq_simplifier : public dependent_expr_simplifier {
 | 
			
		|||
 | 
			
		||||
public:
 | 
			
		||||
    
 | 
			
		||||
    seq_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
 | 
			
		||||
    then_simplifier(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
 | 
			
		||||
        dependent_expr_simplifier(m, fmls) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +47,7 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
 | 
			
		|||
    if (!m_manager->is_bool(range)) {
 | 
			
		||||
        m_manager->raise_exception("range type is expected to be Boolean for special relations");
 | 
			
		||||
    }
 | 
			
		||||
    m_has_special_relation = true;
 | 
			
		||||
    func_decl_info info(m_family_id, k, num_parameters, parameters);
 | 
			
		||||
    symbol name;
 | 
			
		||||
    switch(k) {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +55,11 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
 | 
			
		|||
    case OP_SPECIAL_RELATION_LO: name = m_lo; break;
 | 
			
		||||
    case OP_SPECIAL_RELATION_PLO: name = m_plo; break;
 | 
			
		||||
    case OP_SPECIAL_RELATION_TO: name = m_to; break;
 | 
			
		||||
    case OP_SPECIAL_RELATION_TC: name = m_tc; break;
 | 
			
		||||
    case OP_SPECIAL_RELATION_TC: 
 | 
			
		||||
        name = m_tc; 
 | 
			
		||||
        if (num_parameters != 1 || !parameters[0].is_ast() || !is_func_decl(parameters[0].get_ast()))
 | 
			
		||||
            m_manager->raise_exception("parameter to transitive closure should be a function declaration");
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return m_manager->mk_func_decl(name, arity, domain, range, info);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,7 @@ class special_relations_decl_plugin : public decl_plugin {
 | 
			
		|||
    symbol m_plo;
 | 
			
		||||
    symbol m_to;
 | 
			
		||||
    symbol m_tc;
 | 
			
		||||
    bool   m_has_special_relation = false;
 | 
			
		||||
public:
 | 
			
		||||
    special_relations_decl_plugin();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,8 @@ public:
 | 
			
		|||
    void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
 | 
			
		||||
    
 | 
			
		||||
    sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { return nullptr; }
 | 
			
		||||
 | 
			
		||||
    bool has_special_relation() const { return m_has_special_relation; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum sr_property {
 | 
			
		||||
| 
						 | 
				
			
			@ -71,15 +74,19 @@ class special_relations_util {
 | 
			
		|||
    ast_manager& m;
 | 
			
		||||
    mutable family_id    m_fid;
 | 
			
		||||
    func_decl* mk_rel_decl(func_decl* f, decl_kind k) {
 | 
			
		||||
        SASSERT(f);
 | 
			
		||||
        parameter p(f); SASSERT(f->get_arity() == 2); 
 | 
			
		||||
        return m.mk_func_decl(fid(), k, 1, &p, 2, f->get_domain(), f->get_range()); 
 | 
			
		||||
    }    
 | 
			
		||||
    family_id fid() const {        
 | 
			
		||||
        if (null_family_id == m_fid) m_fid = m.get_family_id("specrels");
 | 
			
		||||
        if (null_family_id == m_fid) 
 | 
			
		||||
            m_fid = m.get_family_id("specrels");
 | 
			
		||||
        return m_fid;
 | 
			
		||||
    }
 | 
			
		||||
public:
 | 
			
		||||
    special_relations_util(ast_manager& m) : m(m), m_fid(null_family_id) { }
 | 
			
		||||
 | 
			
		||||
    bool has_special_relation() const { return static_cast<special_relations_decl_plugin*>(m.get_plugin(m.mk_family_id("specrels")))->has_special_relation(); }
 | 
			
		||||
    
 | 
			
		||||
    bool is_special_relation(func_decl* f) const { return f->get_family_id() == fid(); }
 | 
			
		||||
    bool is_special_relation(app* e) const { return is_special_relation(e->get_decl()); }
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +106,12 @@ public:
 | 
			
		|||
    bool is_to(expr const * e) const { return is_app_of(e, fid(), OP_SPECIAL_RELATION_TO); }
 | 
			
		||||
    bool is_tc(expr const * e) const { return is_app_of(e, fid(), OP_SPECIAL_RELATION_TC); }
 | 
			
		||||
    
 | 
			
		||||
    bool is_lo(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_LO); }
 | 
			
		||||
    bool is_po(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_PO); }
 | 
			
		||||
    bool is_plo(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_PLO); }
 | 
			
		||||
    bool is_to(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_TO); }
 | 
			
		||||
    bool is_tc(func_decl const * e) const { return is_decl_of(e, fid(), OP_SPECIAL_RELATION_TC); }
 | 
			
		||||
 | 
			
		||||
    app * mk_lo (expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_LO,  arg1, arg2); }
 | 
			
		||||
    app * mk_po (expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_PO,  arg1, arg2); }
 | 
			
		||||
    app * mk_plo(expr * arg1, expr * arg2) { return m.mk_app( fid(), OP_SPECIAL_RELATION_PLO, arg1, arg2); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -361,7 +361,7 @@ void cmd_context::insert_macro(symbol const& s, unsigned arity, sort*const* doma
 | 
			
		|||
        vars.push_back(m().mk_var(i, domain[i]));
 | 
			
		||||
        rvars.push_back(m().mk_var(i, domain[arity - i - 1]));
 | 
			
		||||
    }
 | 
			
		||||
    recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort());
 | 
			
		||||
    recfun::promise_def d = p.ensure_def(s, arity, domain, t->get_sort(), false);
 | 
			
		||||
 | 
			
		||||
    // recursive functions have opposite calling convention from macros!
 | 
			
		||||
    var_subst sub(m(), true);
 | 
			
		||||
| 
						 | 
				
			
			@ -984,7 +984,7 @@ recfun::decl::plugin& cmd_context::get_recfun_plugin() {
 | 
			
		|||
 | 
			
		||||
recfun::promise_def cmd_context::decl_rec_fun(const symbol &name, unsigned int arity, sort *const *domain, sort *range) {        
 | 
			
		||||
    SASSERT(logic_has_recfun());
 | 
			
		||||
    return get_recfun_plugin().mk_def(name, arity, domain, range);
 | 
			
		||||
    return get_recfun_plugin().mk_def(name, arity, domain, range, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, svector<symbol> const& ids, expr* rhs) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1237,7 +1237,10 @@ bool cmd_context::try_mk_pdecl_app(symbol const & s, unsigned num_args, expr * c
 | 
			
		|||
    if (num_args != 1)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    for (auto* a : dt.plugin().get_accessors(s)) {        
 | 
			
		||||
    if (!dt.is_datatype(args[0]->get_sort()))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    for (auto* a : dt.plugin().get_accessors(s)) {     
 | 
			
		||||
        fn = a->instantiate(args[0]->get_sort());
 | 
			
		||||
        r = m().mk_app(fn, num_args, args);
 | 
			
		||||
        return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -1979,23 +1982,28 @@ void cmd_context::complete_model(model_ref& md) const {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (auto kd : m_func_decls) {
 | 
			
		||||
        symbol const & k = kd.m_key;
 | 
			
		||||
        func_decls & v = kd.m_value;
 | 
			
		||||
    for (auto& [k, v] : m_func_decls) {
 | 
			
		||||
        IF_VERBOSE(12, verbose_stream() << "(model.completion " << k << ")\n"; );
 | 
			
		||||
        for (unsigned i = 0; i < v.get_num_entries(); i++) {
 | 
			
		||||
            func_decl * f = v.get_entry(i);
 | 
			
		||||
            if (!md->has_interpretation(f)) {
 | 
			
		||||
                sort * range = f->get_range();
 | 
			
		||||
                expr * some_val = m().get_some_value(range);
 | 
			
		||||
                if (f->get_arity() > 0) {
 | 
			
		||||
                    func_interp * fi = alloc(func_interp, m(), f->get_arity());
 | 
			
		||||
                    fi->set_else(some_val);
 | 
			
		||||
                    md->register_decl(f, fi);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    md->register_decl(f, some_val);
 | 
			
		||||
            
 | 
			
		||||
            if (md->has_interpretation(f))
 | 
			
		||||
                continue;
 | 
			
		||||
            macro_decls decls;
 | 
			
		||||
            expr* body = nullptr;
 | 
			
		||||
                
 | 
			
		||||
            if (m_macros.find(k, decls)) 
 | 
			
		||||
                body = decls.find(f->get_arity(), f->get_domain());
 | 
			
		||||
            sort * range = f->get_range();
 | 
			
		||||
            if (!body)
 | 
			
		||||
                body = m().get_some_value(range);
 | 
			
		||||
            if (f->get_arity() > 0) {
 | 
			
		||||
                func_interp * fi = alloc(func_interp, m(), f->get_arity());
 | 
			
		||||
                fi->set_else(body);
 | 
			
		||||
                md->register_decl(f, fi);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                md->register_decl(f, body);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2201,21 +2209,18 @@ void cmd_context::display_statistics(bool show_total_time, double total_time) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
expr_ref_vector cmd_context::tracked_assertions() {
 | 
			
		||||
    expr_ref_vector result(m());
 | 
			
		||||
vector<std::pair<expr*,expr*>> cmd_context::tracked_assertions() {
 | 
			
		||||
    vector<std::pair<expr*,expr*>> result;
 | 
			
		||||
    if (assertion_names().size() == assertions().size()) {
 | 
			
		||||
        for (unsigned i = 0; i < assertions().size(); ++i) {
 | 
			
		||||
            expr* an  = assertion_names()[i];
 | 
			
		||||
            expr* asr = assertions()[i];
 | 
			
		||||
            if (an) 
 | 
			
		||||
                result.push_back(m().mk_implies(an, asr));
 | 
			
		||||
            else 
 | 
			
		||||
                result.push_back(asr);
 | 
			
		||||
            result.push_back({ asr, an });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        for (expr * e : assertions()) 
 | 
			
		||||
            result.push_back(e);
 | 
			
		||||
            result.push_back({ e, nullptr});
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -523,7 +523,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    ptr_vector<expr> const& assertions() const { return m_assertions; }
 | 
			
		||||
    ptr_vector<expr> const& assertion_names() const { return m_assertion_names; }
 | 
			
		||||
    expr_ref_vector tracked_assertions();
 | 
			
		||||
    vector<std::pair<expr*,expr*>> tracked_assertions();
 | 
			
		||||
    void reset_tracked_assertions();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ Author:
 | 
			
		|||
#include "cmd_context/parametric_cmd.h"
 | 
			
		||||
#include "model/model_smt2_pp.h"
 | 
			
		||||
#include "ast/ast_smt2_pp.h"
 | 
			
		||||
#include "ast/simplifiers/seq_simplifier.h"
 | 
			
		||||
#include "ast/simplifiers/then_simplifier.h"
 | 
			
		||||
#include "solver/simplifier_solver.h"
 | 
			
		||||
 | 
			
		||||
typedef dependent_expr_simplifier simplifier;
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ static simplifier_factory mk_and_then(cmd_context & ctx, sexpr * n) {
 | 
			
		|||
    for (unsigned i = 1; i < num_children; i++)
 | 
			
		||||
        args.push_back(sexpr2simplifier(ctx, n->get_child(i)));
 | 
			
		||||
    simplifier_factory result = [args](ast_manager& m, const params_ref& p, dependent_expr_state& st) {
 | 
			
		||||
        scoped_ptr<seq_simplifier> s = alloc(seq_simplifier, m, p, st);
 | 
			
		||||
        scoped_ptr<then_simplifier> s = alloc(then_simplifier, m, p, st);
 | 
			
		||||
        for (auto &  simp : args)
 | 
			
		||||
            s->add_simplifier(simp(m, p, st));
 | 
			
		||||
        return s.detach();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,7 @@ public:
 | 
			
		|||
    void set_upper_is_open(interval & a, bool v) { a.m_upper_open = v; }
 | 
			
		||||
    void set_lower_is_inf(interval & a, bool v) { a.m_lower_inf = v; }
 | 
			
		||||
    void set_upper_is_inf(interval & a, bool v) { a.m_upper_inf = v; }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    // Reference to numeral manager
 | 
			
		||||
    numeral_manager & m() const { return m_manager; }
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +185,14 @@ public:
 | 
			
		|||
    bool upper_is_open(interval const & a) const { return m_c.upper_is_open(a); }
 | 
			
		||||
    bool lower_is_inf(interval const & a) const { return m_c.lower_is_inf(a); }
 | 
			
		||||
    bool upper_is_inf(interval const & a) const { return m_c.upper_is_inf(a); }
 | 
			
		||||
    bool is_empty(interval const& a) const {
 | 
			
		||||
        if (lower_is_inf(a) || upper_is_inf(a))
 | 
			
		||||
            return false;
 | 
			
		||||
        ext_numeral_kind lk = lower_kind(a), uk = upper_kind(a);
 | 
			
		||||
        if (lower_is_open(a) || upper_is_open(a))
 | 
			
		||||
            return !(::lt(m(), lower(a), lk, upper(a), uk));
 | 
			
		||||
        return ::lt(m(), upper(a), uk, lower(a), lk);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    bool lower_is_neg(interval const & a) const { return ::is_neg(m(), lower(a), lower_kind(a)); }
 | 
			
		||||
    bool lower_is_pos(interval const & a) const { return ::is_pos(m(), lower(a), lower_kind(a)); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -681,7 +681,7 @@ void interval_manager<C>::set(interval & t, interval const & s) {
 | 
			
		|||
    }
 | 
			
		||||
    set_lower_is_open(t, lower_is_open(s));
 | 
			
		||||
    set_upper_is_open(t, upper_is_open(s));
 | 
			
		||||
    SASSERT(check_invariant(t));
 | 
			
		||||
    SASSERT(is_empty(t) || check_invariant(t));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename C>
 | 
			
		||||
| 
						 | 
				
			
			@ -813,7 +813,7 @@ void interval_manager<C>::add(interval const & a, interval const & b, interval &
 | 
			
		|||
    set_upper_is_inf(c, new_u_kind == EN_PLUS_INFINITY);
 | 
			
		||||
    set_lower_is_open(c, lower_is_open(a) || lower_is_open(b));
 | 
			
		||||
    set_upper_is_open(c, upper_is_open(a) || upper_is_open(b));
 | 
			
		||||
    SASSERT(check_invariant(c));
 | 
			
		||||
    SASSERT(is_empty(a) || is_empty(b) || check_invariant(c));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename C>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,7 @@
 | 
			
		|||
z3_add_component(lp
 | 
			
		||||
  SOURCES
 | 
			
		||||
    binary_heap_priority_queue.cpp
 | 
			
		||||
    binary_heap_upair_queue.cpp
 | 
			
		||||
    core_solver_pretty_printer.cpp
 | 
			
		||||
    dense_matrix.cpp
 | 
			
		||||
    eta_matrix.cpp
 | 
			
		||||
    emonics.cpp
 | 
			
		||||
    factorization.cpp
 | 
			
		||||
    factorization_factory_imp.cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -19,14 +16,8 @@ z3_add_component(lp
 | 
			
		|||
    lar_solver.cpp
 | 
			
		||||
    lar_core_solver.cpp
 | 
			
		||||
    lp_core_solver_base.cpp
 | 
			
		||||
    lp_dual_core_solver.cpp
 | 
			
		||||
    lp_dual_simplex.cpp
 | 
			
		||||
    lp_primal_core_solver.cpp
 | 
			
		||||
    lp_primal_simplex.cpp
 | 
			
		||||
    lp_settings.cpp
 | 
			
		||||
    lp_solver.cpp
 | 
			
		||||
    lu.cpp
 | 
			
		||||
    lp_utils.cpp
 | 
			
		||||
    matrix.cpp
 | 
			
		||||
    mon_eq.cpp
 | 
			
		||||
    monomial_bounds.cpp
 | 
			
		||||
| 
						 | 
				
			
			@ -45,10 +36,6 @@ z3_add_component(lp
 | 
			
		|||
    nra_solver.cpp    
 | 
			
		||||
    permutation_matrix.cpp
 | 
			
		||||
    random_updater.cpp      
 | 
			
		||||
    row_eta_matrix.cpp
 | 
			
		||||
    scaler.cpp
 | 
			
		||||
    square_dense_submatrix.cpp
 | 
			
		||||
    square_sparse_matrix.cpp
 | 
			
		||||
    static_matrix.cpp
 | 
			
		||||
  COMPONENT_DEPENDENCIES
 | 
			
		||||
    util
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2017 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    <name>
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    <abstract>
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Lev Nachmanson (levnach)
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#include "math/lp/numeric_pair.h"
 | 
			
		||||
#include "math/lp/binary_heap_priority_queue_def.h"
 | 
			
		||||
namespace lp {
 | 
			
		||||
template binary_heap_priority_queue<int>::binary_heap_priority_queue(unsigned int);
 | 
			
		||||
template unsigned binary_heap_priority_queue<int>::dequeue();
 | 
			
		||||
template void binary_heap_priority_queue<int>::enqueue(unsigned int, int const&);
 | 
			
		||||
template void binary_heap_priority_queue<double>::enqueue(unsigned int, double const&);
 | 
			
		||||
template void binary_heap_priority_queue<mpq>::enqueue(unsigned int, mpq const&);
 | 
			
		||||
template void binary_heap_priority_queue<int>::remove(unsigned int);
 | 
			
		||||
template unsigned binary_heap_priority_queue<numeric_pair<mpq> >::dequeue();
 | 
			
		||||
template unsigned binary_heap_priority_queue<double>::dequeue();
 | 
			
		||||
template unsigned binary_heap_priority_queue<mpq>::dequeue();
 | 
			
		||||
template void binary_heap_priority_queue<numeric_pair<mpq> >::enqueue(unsigned int, numeric_pair<mpq> const&);
 | 
			
		||||
template void binary_heap_priority_queue<numeric_pair<mpq> >::resize(unsigned int);
 | 
			
		||||
template void lp::binary_heap_priority_queue<double>::resize(unsigned int);
 | 
			
		||||
template binary_heap_priority_queue<unsigned int>::binary_heap_priority_queue(unsigned int);
 | 
			
		||||
template void binary_heap_priority_queue<unsigned>::resize(unsigned int);
 | 
			
		||||
template unsigned binary_heap_priority_queue<unsigned int>::dequeue();
 | 
			
		||||
template void binary_heap_priority_queue<unsigned int>::enqueue(unsigned int, unsigned int const&);
 | 
			
		||||
template void binary_heap_priority_queue<unsigned int>::remove(unsigned int);
 | 
			
		||||
template void lp::binary_heap_priority_queue<mpq>::resize(unsigned int);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,83 +0,0 @@
 | 
			
		|||
 | 
			
		||||
/*++
 | 
			
		||||
Copyright (c) 2017 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    <name>
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    <abstract>
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Lev Nachmanson (levnach)
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "util/vector.h"
 | 
			
		||||
#include "util/debug.h"
 | 
			
		||||
#include "math/lp/lp_utils.h"
 | 
			
		||||
namespace lp {
 | 
			
		||||
// the elements with the smallest priority are dequeued first
 | 
			
		||||
template <typename T>
 | 
			
		||||
class binary_heap_priority_queue {
 | 
			
		||||
    vector<T> m_priorities;
 | 
			
		||||
 | 
			
		||||
    // indexing for A starts from 1
 | 
			
		||||
    vector<unsigned> m_heap; // keeps the elements of the queue
 | 
			
		||||
    vector<int> m_heap_inverse; // o = m_heap[m_heap_inverse[o]]
 | 
			
		||||
    unsigned m_heap_size;
 | 
			
		||||
    // is is the child place in heap
 | 
			
		||||
    void swap_with_parent(unsigned i);
 | 
			
		||||
    void put_at(unsigned i, unsigned h);
 | 
			
		||||
    void decrease_priority(unsigned o, T newPriority);
 | 
			
		||||
public:
 | 
			
		||||
#ifdef Z3DEBUG
 | 
			
		||||
    bool is_consistent() const;
 | 
			
		||||
#endif
 | 
			
		||||
public:
 | 
			
		||||
    void remove(unsigned o);
 | 
			
		||||
    unsigned size() const { return m_heap_size; }
 | 
			
		||||
    binary_heap_priority_queue(): m_heap(1), m_heap_size(0) {} // the empty constructror
 | 
			
		||||
    // n is the initial queue capacity.
 | 
			
		||||
    // The capacity will be enlarged each time twice if needed
 | 
			
		||||
    binary_heap_priority_queue(unsigned n);
 | 
			
		||||
 | 
			
		||||
    void clear() {
 | 
			
		||||
        for (unsigned i = 0; i < m_heap_size; i++) {
 | 
			
		||||
            unsigned o = m_heap[i+1];
 | 
			
		||||
            m_heap_inverse[o] = -1;
 | 
			
		||||
        }
 | 
			
		||||
        m_heap_size = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void resize(unsigned n);
 | 
			
		||||
    void put_to_heap(unsigned i, unsigned o);
 | 
			
		||||
 | 
			
		||||
    void enqueue_new(unsigned o, const T& priority);
 | 
			
		||||
 | 
			
		||||
    // This method can work with an element that is already in the queue.
 | 
			
		||||
    // In this case the priority will be changed and the queue adjusted.
 | 
			
		||||
    void enqueue(unsigned o, const T & priority);
 | 
			
		||||
    void change_priority_for_existing(unsigned o, const T & priority);
 | 
			
		||||
    T get_priority(unsigned o) const { return m_priorities[o]; }
 | 
			
		||||
    bool is_empty() const { return m_heap_size == 0; }
 | 
			
		||||
 | 
			
		||||
    /// return the first element of the queue and removes it from the queue
 | 
			
		||||
    unsigned dequeue_and_get_priority(T & priority);
 | 
			
		||||
    void fix_heap_under(unsigned i);
 | 
			
		||||
    void put_the_last_at_the_top_and_fix_the_heap();
 | 
			
		||||
    /// return the first element of the queue and removes it from the queue
 | 
			
		||||
    unsigned dequeue();
 | 
			
		||||
    unsigned peek() const {
 | 
			
		||||
        lp_assert(m_heap_size > 0);
 | 
			
		||||
        return m_heap[1];
 | 
			
		||||
    }
 | 
			
		||||
    void print(std::ostream & out);
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,214 +0,0 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2017 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    <name>
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    <abstract>
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Lev Nachmanson (levnach)
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "util/vector.h"
 | 
			
		||||
#include "math/lp/binary_heap_priority_queue.h"
 | 
			
		||||
namespace lp {
 | 
			
		||||
// "i" is the child's place in the heap
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::swap_with_parent(unsigned i) {
 | 
			
		||||
    unsigned parent = m_heap[i >> 1];
 | 
			
		||||
    put_at(i >> 1, m_heap[i]);
 | 
			
		||||
    put_at(i, parent);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::put_at(unsigned i, unsigned h) {
 | 
			
		||||
    m_heap[i] = h;
 | 
			
		||||
    m_heap_inverse[h] = i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::decrease_priority(unsigned o, T newPriority) {
 | 
			
		||||
    m_priorities[o] = newPriority;
 | 
			
		||||
    int i = m_heap_inverse[o];
 | 
			
		||||
    while (i > 1) {
 | 
			
		||||
        if (m_priorities[m_heap[i]] < m_priorities[m_heap[i >> 1]])
 | 
			
		||||
            swap_with_parent(i);
 | 
			
		||||
        else
 | 
			
		||||
            break;
 | 
			
		||||
        i >>= 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef Z3DEBUG
 | 
			
		||||
template <typename T> bool binary_heap_priority_queue<T>::is_consistent() const {
 | 
			
		||||
    for (int i = 0; i < m_heap_inverse.size(); i++) {
 | 
			
		||||
        int i_index = m_heap_inverse[i];
 | 
			
		||||
        lp_assert(i_index <= static_cast<int>(m_heap_size));
 | 
			
		||||
        lp_assert(i_index == -1 || m_heap[i_index] == i);
 | 
			
		||||
    }
 | 
			
		||||
    for (unsigned i = 1; i < m_heap_size; i++) {
 | 
			
		||||
        unsigned ch = i << 1;
 | 
			
		||||
        for (int k = 0; k < 2; k++) {
 | 
			
		||||
            if (ch > m_heap_size) break;
 | 
			
		||||
            if (!(m_priorities[m_heap[i]] <= m_priorities[m_heap[ch]])){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            ch++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::remove(unsigned o) {
 | 
			
		||||
    T priority_of_o = m_priorities[o];
 | 
			
		||||
    int o_in_heap = m_heap_inverse[o];
 | 
			
		||||
    if (o_in_heap == -1)  {
 | 
			
		||||
        return;  // nothing to do
 | 
			
		||||
    }
 | 
			
		||||
    lp_assert(static_cast<unsigned>(o_in_heap) <= m_heap_size);
 | 
			
		||||
    if (static_cast<unsigned>(o_in_heap) < m_heap_size) {
 | 
			
		||||
        put_at(o_in_heap, m_heap[m_heap_size--]);
 | 
			
		||||
        if (m_priorities[m_heap[o_in_heap]] > priority_of_o) {
 | 
			
		||||
            fix_heap_under(o_in_heap);
 | 
			
		||||
        } else { // we need to propagate the m_heap[o_in_heap] up
 | 
			
		||||
            unsigned i = o_in_heap;
 | 
			
		||||
            while (i > 1) {
 | 
			
		||||
                unsigned ip = i >> 1;
 | 
			
		||||
                if (m_priorities[m_heap[i]] < m_priorities[m_heap[ip]])
 | 
			
		||||
                    swap_with_parent(i);
 | 
			
		||||
                else
 | 
			
		||||
                    break;
 | 
			
		||||
                i = ip;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        lp_assert(static_cast<unsigned>(o_in_heap) == m_heap_size);
 | 
			
		||||
        m_heap_size--;
 | 
			
		||||
    }
 | 
			
		||||
    m_heap_inverse[o] = -1;
 | 
			
		||||
    // lp_assert(is_consistent());
 | 
			
		||||
}
 | 
			
		||||
// n is the initial queue capacity.
 | 
			
		||||
// The capacity will be enlarged two times automatically if needed
 | 
			
		||||
template <typename T> binary_heap_priority_queue<T>::binary_heap_priority_queue(unsigned n) :
 | 
			
		||||
    m_priorities(n),
 | 
			
		||||
    m_heap(n + 1), // because the indexing for A starts from 1
 | 
			
		||||
    m_heap_inverse(n, -1),
 | 
			
		||||
    m_heap_size(0)
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::resize(unsigned n) {
 | 
			
		||||
    m_priorities.resize(n);
 | 
			
		||||
    m_heap.resize(n + 1);
 | 
			
		||||
    m_heap_inverse.resize(n, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::put_to_heap(unsigned i, unsigned o) {
 | 
			
		||||
    m_heap[i] = o;
 | 
			
		||||
    m_heap_inverse[o] = i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::enqueue_new(unsigned o, const T& priority) {
 | 
			
		||||
    m_heap_size++;
 | 
			
		||||
    int i = m_heap_size;
 | 
			
		||||
    lp_assert(o < m_priorities.size());
 | 
			
		||||
    m_priorities[o] = priority;
 | 
			
		||||
    put_at(i, o);
 | 
			
		||||
    while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) {
 | 
			
		||||
        swap_with_parent(i);
 | 
			
		||||
        i >>= 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// This method can work with an element that is already in the queue.
 | 
			
		||||
// In this case the priority will be changed and the queue adjusted.
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::enqueue(unsigned o, const T & priority) {
 | 
			
		||||
    if (o >= m_priorities.size()) {
 | 
			
		||||
        if (o == 0)
 | 
			
		||||
            resize(2);
 | 
			
		||||
        else 
 | 
			
		||||
            resize(o << 1); // make the size twice larger
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (m_heap_inverse[o] == -1)
 | 
			
		||||
        enqueue_new(o, priority);
 | 
			
		||||
    else
 | 
			
		||||
        change_priority_for_existing(o, priority);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::change_priority_for_existing(unsigned o, const T & priority) {
 | 
			
		||||
    if (m_priorities[o] > priority) {
 | 
			
		||||
        decrease_priority(o, priority);
 | 
			
		||||
    } else {
 | 
			
		||||
        m_priorities[o] = priority;
 | 
			
		||||
        fix_heap_under(m_heap_inverse[o]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// return the first element of the queue and removes it from the queue
 | 
			
		||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue_and_get_priority(T & priority) {
 | 
			
		||||
    lp_assert(m_heap_size != 0);
 | 
			
		||||
    int ret = m_heap[1];
 | 
			
		||||
    priority = m_priorities[ret];
 | 
			
		||||
    put_the_last_at_the_top_and_fix_the_heap();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::fix_heap_under(unsigned i) {
 | 
			
		||||
    while (true) {
 | 
			
		||||
        unsigned smallest = i;
 | 
			
		||||
        unsigned l = i << 1;
 | 
			
		||||
        if (l <= m_heap_size && m_priorities[m_heap[l]] < m_priorities[m_heap[i]])
 | 
			
		||||
            smallest = l;
 | 
			
		||||
        unsigned r = l + 1;
 | 
			
		||||
        if (r <= m_heap_size && m_priorities[m_heap[r]] < m_priorities[m_heap[smallest]])
 | 
			
		||||
            smallest = r;
 | 
			
		||||
        if (smallest != i)
 | 
			
		||||
            swap_with_parent(smallest);
 | 
			
		||||
        else
 | 
			
		||||
            break;
 | 
			
		||||
        i = smallest;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::put_the_last_at_the_top_and_fix_the_heap() {
 | 
			
		||||
    if (m_heap_size > 1) {
 | 
			
		||||
        put_at(1, m_heap[m_heap_size--]);
 | 
			
		||||
        fix_heap_under(1);
 | 
			
		||||
    } else {
 | 
			
		||||
        m_heap_size--;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/// return the first element of the queue and removes it from the queue
 | 
			
		||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue() {
 | 
			
		||||
    lp_assert(m_heap_size > 0);
 | 
			
		||||
    int ret = m_heap[1];
 | 
			
		||||
    put_the_last_at_the_top_and_fix_the_heap();
 | 
			
		||||
    m_heap_inverse[ret] = -1;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
template <typename T> void binary_heap_priority_queue<T>::print(std::ostream & out) {
 | 
			
		||||
    vector<int> index;
 | 
			
		||||
    vector<T> prs;
 | 
			
		||||
    while (size()) {
 | 
			
		||||
        T prior;
 | 
			
		||||
        int j = dequeue_and_get_priority(prior);
 | 
			
		||||
        index.push_back(j);
 | 
			
		||||
        prs.push_back(prior);
 | 
			
		||||
        out << "(" << j << ", " << prior << ")";
 | 
			
		||||
    }
 | 
			
		||||
    out << std::endl;
 | 
			
		||||
    // restore the queue
 | 
			
		||||
    for (int i = 0; i < index.size(); i++)
 | 
			
		||||
        enqueue(index[i], prs[i]);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue