3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-05 17:14:07 +00:00
This commit is contained in:
Christoph M. Wintersteiger 2017-06-25 20:46:14 +01:00
commit ffbf19d944
150 changed files with 851 additions and 561 deletions

11
.gitignore vendored
View file

@ -75,14 +75,3 @@ src/api/ml/z3.mllib
*.bak
doc/api
doc/code
# CMake files copied over by the ``contrib/cmake/boostrap.py`` script
# See #461
examples/CMakeLists.txt
examples/*/CMakeLists.txt
src/CMakeLists.txt
src/*/CMakeLists.txt
src/*/*/CMakeLists.txt
src/*/*/*/CMakeLists.txt
src/api/dotnet/cmake_install_gac.cmake.in
src/api/dotnet/cmake_uninstall_gac.cmake.in

View file

@ -14,16 +14,6 @@ if (POLICY CMP0054)
cmake_policy(SET CMP0054 OLD)
endif()
# Provide a friendly message if the user hasn't run the bootstrap script
# to copy all the CMake files into their correct location.
# It is unfortunate that we have to do this, see #461 for the discussion
# on this.
if (NOT (EXISTS "${CMAKE_SOURCE_DIR}/src/CMakeLists.txt"))
message(FATAL_ERROR "Cannot find \"${CMAKE_SOURCE_DIR}/src/CMakeLists.txt\""
". This probably means you need to run"
"``python contrib/cmake/bootstrap.py create``")
endif()
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake")
project(Z3 CXX)

View file

@ -33,34 +33,6 @@ git clean -fx src
which will remove the generated source files.
### Bootstrapping
Most of Z3's CMake files do not live in their correct location. Instead those
files live in the ``contrib/cmake`` folder and a script is provided that will
copy (or hard link) the files into their correct location.
To copy the files run
```
python contrib/cmake/bootstrap.py create
```
in the root of the repository. Once you have done this you can now build Z3 using CMake.
Make sure you remember to rerun this command if you pull down new code/rebase/change branch so
that the copied CMake files are up to date.
To remove the copied files run
```
python contrib/cmake/bootstrap.py remove
```
Note if you plan to do development on Z3 you should read the developer
notes on bootstrapping in this document.
What follows is a brief walk through of how to build Z3 using some
of the more commonly used CMake generators.
### Unix Makefiles
Run the following in the top level directory of the Z3 repository.
@ -328,44 +300,6 @@ link is not created when building under Windows.
These notes are help developers and packagers of Z3.
### Boostrapping the CMake build
Z3's CMake system is experimental and not officially supported. Consequently
Z3's developers have decided that they do not want the CMake files in the
``src/`` and ``examples/`` folders. Instead the ``contrib/cmake/bootstrap.py``
script copies or hard links them into the correct locations. For context
on this decision see https://github.com/Z3Prover/z3/pull/461 .
The ``contrib/cmake/bootstrap.py create`` command just copies over files which makes
development harder because you have to copy your modifications over to the
files in ``contrib/cmake`` for your changes to committed to git. If you are on a UNIX like
platform you can create hard links instead by running
```
contrib/cmake/boostrap.py create --hard-link
```
Using hard links means that modifying any of the "copied" files also modifies the
file under version control. Using hard links also means that the file modification time
will appear correct (i.e. the hard-linked "copies" have the same file modification time
as the corresponding file under version control) which means CMake will correctly reconfigure
when invoked. This is why using symbolic links is not an option because the file modification
time of a symbolic link is not the same as the file modification of the file being pointed to.
Unfortunately a downside to using hard links (or just plain copies) is that if
you pull down new code (i.e. ``git pull``) then some of the CMake files under
version control may change but the corresponding hard-linked "copies" will not.
This mean that (regardless of whether or not you use hard links) every time you
pull down new code or change branch or do an interactive rebase you must run
(with or without ``--hard-link``):
```
contrb/cmake/boostrap.py create
```
in order to be sure that the copied CMake files are not out of date.
### Install/Uninstall
Install and uninstall targets are supported. Use ``CMAKE_INSTALL_PREFIX`` to

View file

@ -1,25 +1,13 @@
#!/usr/bin/env python
"""
This script is used to copy or delete the
CMake build system files from the contrib/cmake
folder into the their correct location in the Z3
repository.
This script is an artifact of compromise that was
made when the CMake build system was first introduced
(see #461).
It offers two modes
* create - This will symlink the ``cmake`` directory and copy (or hard link)
the appropriate files into their correct locations in the repository.
* remove - This will remove the symlinked ``cmake``
directory and remove the files added by the above
methods.
This has the advantage
that editing the hard link edits the underlying file
(making development easier because copying files is
not neccessary) and CMake will regenerate correctly
because the modification time stamps will be correct.
This script now does nothing. It remains only to not
break out-of-tree scripts that build Z3 using CMake.
Eventually this script will be removed.
"""
import argparse
import logging
@ -28,189 +16,6 @@ import pprint
import shutil
import sys
def get_full_path_to_script():
return os.path.abspath(__file__)
def get_cmake_contrib_dir():
return os.path.dirname(get_full_path_to_script())
def get_repo_root_dir():
r = os.path.dirname(os.path.dirname(get_cmake_contrib_dir()))
assert os.path.isdir(r)
return r
# These are paths that should be ignored when checking if a folder
# in the ``contrib/cmake`` exists in the root of the repository
verificationExceptions = {
os.path.join(get_repo_root_dir(), 'cmake'),
os.path.join(get_repo_root_dir(), 'cmake', 'modules')
}
def contribPathToRepoPath(path):
assert path.startswith(get_cmake_contrib_dir())
stripped = path[len(get_cmake_contrib_dir()) + 1:] # Plus one is to remove leading slash
assert not os.path.isabs(stripped)
logging.debug('stripped:{}'.format(stripped))
r = os.path.join(get_repo_root_dir(), stripped)
assert os.path.isabs(r)
logging.debug('Converted contrib path "{}" to repo path "{}"'.format(path, r))
return r
def verify_mirrored_directory_struture():
"""
Check that the directories contained in ``contrib/cmake`` exist
in the root of the repo.
"""
for (dirpath, _, _) in os.walk(get_cmake_contrib_dir()):
expectedDir = contribPathToRepoPath(dirpath)
logging.debug('expectedDir:{}'.format(expectedDir))
if (not (os.path.exists(expectedDir) and os.path.isdir(expectedDir)) and
expectedDir not in verificationExceptions):
logging.error(('Expected to find directory "{}" but it does not exist'
' or is not a directory').format(expectedDir))
return 1
return 0
def mk_sym_link(target, linkName):
logging.info('Making symbolic link target="{}", linkName="{}"'.format(target, linkName))
if os.path.exists(linkName):
logging.info('Removing existing link "{}"'.format(linkName))
if not os.path.islink(linkName):
logging.warning('"{}" overwriting file that is not a symlink'.format(linkName))
delete_path(linkName)
if os.name == 'posix':
os.symlink(target, linkName)
else:
# TODO: Windows does support symlinks but the implementation to do that
# from python is a little complicated so for now lets just copy everyting
logging.warning('Creating symbolic links is not supported. Just making a copy instead')
if os.path.isdir(target):
# Recursively copy directory
shutil.copytree(src=target, dst=linkName, symlinks=False)
else:
# Copy file
assert os.path.isfile(target)
shutil.copy2(src=target, dst=linkName)
def delete_path(path):
logging.info('Removing "{}"'.format(path))
if not os.path.exists(path):
logging.warning('"{}" does not exist'.format(path))
return
if os.path.isdir(path) and not os.path.islink(path):
# FIXME: If we can get symbolic link support on Windows we
# can disallow this completely.
assert os.name == 'nt'
shutil.rmtree(path)
else:
os.remove(path)
def shouldSkipFile(path):
# Skip this script
if path == get_full_path_to_script():
return True
# Skip the maintainers file
if path == os.path.join(get_cmake_contrib_dir(), 'maintainers.txt'):
return True
# Skip Vim temporary files
if os.path.basename(path).startswith('.') and path.endswith('.swp'):
return True
return False
def create(useHardLinks):
"""
Copy or hard link files in the CMake contrib directory
into the repository where they are intended to live.
Note that symbolic links for the CMakeLists.txt files
are not appropriate because they won't have the right
file modification time when the files they point to
are modified. This would prevent CMake from correctly
reconfiguring when it detects this is required.
"""
# Make the ``cmake`` directory a symbolic link.
# We treat this one specially as it is the only directory
# that doesn't already exist in the repository root so
# we can just use a symlink here
linkName = os.path.join(get_repo_root_dir(), 'cmake')
target = os.path.join(get_cmake_contrib_dir(), 'cmake')
specialDir = target
mk_sym_link(target, linkName)
for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()):
# Skip the special directory and its children
if dirPath.startswith(specialDir):
logging.info('Skipping directory "{}"'.format(dirPath))
continue
for fileName in fileNames:
fileInContrib = os.path.join(dirPath, fileName)
# Skip files
if shouldSkipFile(fileInContrib):
logging.info('Skipping "{}"'.format(fileInContrib))
continue
fileInRepo = contribPathToRepoPath(fileInContrib)
logging.info('"{}" => "{}"'.format(fileInContrib, fileInRepo))
if useHardLinks:
if not os.name == 'posix':
logging.error('Hard links are not supported on your platform')
return False
if os.path.exists(fileInRepo):
delete_path(fileInRepo)
os.link(fileInContrib, fileInRepo)
else:
try:
shutil.copy2(src=fileInContrib, dst=fileInRepo)
except shutil.Error as e:
# Can hit this if used created hard links first and then run again without
# wanting hard links
if sys.version_info.major <= 2:
logging.error(e.message)
else:
# Python >= 3
if isinstance(e, shutil.SameFileError):
logging.error('Trying to copy "{}" to "{}" but they are the same file'.format(
fileInContrib, fileInRepo))
else:
logging.error(e)
logging.error('You should remove the files using the "remove" mode '
'and try to create again. You probably are mixing the '
'hard-link and non-hard-link create modes')
return False
return True
def remove():
"""
Remove the CMake files from their intended location in
the repository. This is used to remove
the files created by the ``create()`` function.
"""
# This directory is treated specially as it is normally
# a symlink.
linkName = os.path.join(get_repo_root_dir(), 'cmake')
delete_path(linkName)
specialDir = os.path.join(get_cmake_contrib_dir(), 'cmake')
for (dirPath,_ , fileNames) in os.walk(get_cmake_contrib_dir()):
# Skip the special directory and its children
if dirPath.startswith(specialDir):
logging.info('Skipping directory "{}"'.format(dirPath))
continue
for fileName in fileNames:
fileInContrib = os.path.join(dirPath, fileName)
# Skip files
if shouldSkipFile(fileInContrib):
logging.info('Skipping "{}"'.format(fileInContrib))
continue
fileInRepo = contribPathToRepoPath(fileInContrib)
if os.path.exists(fileInRepo):
logging.info('Removing "{}"'.format(fileInRepo))
delete_path(fileInRepo)
return True
def main(args):
logging.basicConfig(level=logging.INFO)
parser = argparse.ArgumentParser(description=__doc__)
@ -233,28 +38,10 @@ def main(args):
logLevel = getattr(logging, pargs.log_level.upper(),None)
logging.basicConfig(level=logLevel)
# Before we start make sure we can transplant the CMake files on to
# repository
if verify_mirrored_directory_struture() != 0:
logging.error('"{}" does not mirror "{}"'.format(get_cmake_contrib_dir(), get_repo_root_dir()))
return 1
if pargs.mode == "create":
if not create(useHardLinks=pargs.hard_link):
logging.error("Failed to create")
return 1
elif pargs.mode == "create_hard_link":
if not create(useHardLinks=True):
logging.error("Failed to create_hard_link")
return 1
elif pargs.mode == "remove":
if not remove():
logging.error("Failed to remove")
return 1
else:
logging.error('Unknown mode "{}"'.format(pargs.mode))
logging.warning('Use of this script is deprecated. The script will be removed in the future')
logging.warning('Action "{}" ignored'.format(pargs.mode))
if pargs.hard_link:
logging.warning('Hard link option ignored')
return 0
if __name__ == '__main__':

View file

@ -704,10 +704,13 @@ INPUT_ENCODING = UTF-8
FILE_PATTERNS = website.dox \
z3_api.h \
z3_algebraic.h \
z3_ast_containers.h \
z3_fixedpoint.h \
z3_fpa.h \
z3_interp.h \
z3_optimization.h \
z3_polynomial.h \
z3_rcf.h \
z3_interp.h \
z3_fpa.h \
z3++.h \
@PYTHON_API_FILES@ @DOTNET_API_FILES@ @JAVA_API_FILES@

View file

@ -2152,6 +2152,31 @@ namespace test_mapi
Console.WriteLine("OK, model: {0}", s.Model.ToString());
}
public static void TranslationExample()
{
Context ctx1 = new Context();
Context ctx2 = new Context();
Sort s1 = ctx1.IntSort;
Sort s2 = ctx2.IntSort;
Sort s3 = s1.Translate(ctx2);
Console.WriteLine(s1 == s2);
Console.WriteLine(s1.Equals(s2));
Console.WriteLine(s2.Equals(s3));
Console.WriteLine(s1.Equals(s3));
Expr e1 = ctx1.MkIntConst("e1");
Expr e2 = ctx2.MkIntConst("e1");
Expr e3 = e1.Translate(ctx2);
Console.WriteLine(e1 == e2);
Console.WriteLine(e1.Equals(e2));
Console.WriteLine(e2.Equals(e3));
Console.WriteLine(e1.Equals(e3));
}
static void Main(string[] args)
{
try
@ -2225,6 +2250,8 @@ namespace test_mapi
QuantifierExample4(ctx);
}
TranslationExample();
Log.Close();
if (Log.isOpen())
Console.WriteLine("Log is still open!");

View file

@ -281,7 +281,7 @@ class JavaExample
}
void disprove(Context ctx, BoolExpr f, boolean useMBQI)
throws TestFailedException
throws TestFailedException
{
BoolExpr[] a = {};
disprove(ctx, f, useMBQI, a);
@ -2279,6 +2279,29 @@ class JavaExample
System.out.println(my);
}
public void translationExample() {
Context ctx1 = new Context();
Context ctx2 = new Context();
Sort s1 = ctx1.getIntSort();
Sort s2 = ctx2.getIntSort();
Sort s3 = s1.translate(ctx2);
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
System.out.println(s2.equals(s3));
System.out.println(s1.equals(s3));
Expr e1 = ctx1.mkIntConst("e1");
Expr e2 = ctx2.mkIntConst("e1");
Expr e3 = e1.translate(ctx2);
System.out.println(e1 == e2);
System.out.println(e1.equals(e2));
System.out.println(e2.equals(e3));
System.out.println(e1.equals(e3));
}
public static void main(String[] args)
{
JavaExample p = new JavaExample();
@ -2300,8 +2323,8 @@ class JavaExample
HashMap<String, String> cfg = new HashMap<String, String>();
cfg.put("model", "true");
Context ctx = new Context(cfg);
p.optimizeExample(ctx);
p.optimizeExample(ctx);
p.basicTests(ctx);
p.castingTest(ctx);
p.sudokuExample(ctx);
@ -2355,7 +2378,9 @@ class JavaExample
Context ctx = new Context(cfg);
p.quantifierExample3(ctx);
p.quantifierExample4(ctx);
}
}
p.translationExample();
Log.close();
if (Log.isOpen())

View file

@ -558,6 +558,7 @@ extern "C" {
Z3_TRY;
LOG_Z3_get_sort(c, a);
RESET_ERROR_CODE();
CHECK_IS_EXPR(a, 0);
Z3_sort r = of_sort(mk_c(c)->m().get_sort(to_expr(a)));
RETURN_Z3(r);
Z3_CATCH_RETURN(0);
@ -821,9 +822,13 @@ extern "C" {
RESET_ERROR_CODE();
std::ostringstream buffer;
switch (mk_c(c)->get_print_mode()) {
case Z3_PRINT_SMTLIB_FULL:
buffer << mk_pp(to_ast(a), mk_c(c)->m());
case Z3_PRINT_SMTLIB_FULL: {
params_ref p;
p.set_uint("max_depth", 4294967295u);
p.set_uint("min_alias_size", 4294967295u);
buffer << mk_pp(to_ast(a), mk_c(c)->m(), p);
break;
}
case Z3_PRINT_LOW_LEVEL:
buffer << mk_ll_pp(to_ast(a), mk_c(c)->m());
break;
@ -1066,7 +1071,7 @@ extern "C" {
case OP_BIT2BOOL: return Z3_OP_BIT2BOOL;
case OP_BSMUL_NO_OVFL: return Z3_OP_BSMUL_NO_OVFL;
case OP_BUMUL_NO_OVFL: return Z3_OP_BUMUL_NO_OVFL;
case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL;
case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL;
case OP_BSDIV_I: return Z3_OP_BSDIV_I;
case OP_BUDIV_I: return Z3_OP_BUDIV_I;
case OP_BSREM_I: return Z3_OP_BSREM_I;
@ -1124,6 +1129,20 @@ extern "C" {
case OP_SEQ_TO_RE: return Z3_OP_SEQ_TO_RE;
case OP_SEQ_IN_RE: return Z3_OP_SEQ_IN_RE;
case _OP_STRING_STRREPL: return Z3_OP_SEQ_REPLACE;
case _OP_STRING_CONCAT: return Z3_OP_SEQ_CONCAT;
case _OP_STRING_LENGTH: return Z3_OP_SEQ_LENGTH;
case _OP_STRING_STRCTN: return Z3_OP_SEQ_CONTAINS;
case _OP_STRING_PREFIX: return Z3_OP_SEQ_PREFIX;
case _OP_STRING_SUFFIX: return Z3_OP_SEQ_SUFFIX;
case _OP_STRING_IN_REGEXP: return Z3_OP_SEQ_IN_RE;
case _OP_STRING_TO_REGEXP: return Z3_OP_SEQ_TO_RE;
case _OP_STRING_CHARAT: return Z3_OP_SEQ_AT;
case _OP_STRING_SUBSTR: return Z3_OP_SEQ_EXTRACT;
case _OP_STRING_STRIDOF: return Z3_OP_SEQ_INDEX;
case _OP_REGEXP_EMPTY: return Z3_OP_RE_EMPTY_SET;
case _OP_REGEXP_FULL: return Z3_OP_RE_FULL_SET;
case OP_STRING_STOI: return Z3_OP_STR_TO_INT;
case OP_STRING_ITOS: return Z3_OP_INT_TO_STR;

View file

@ -14,7 +14,7 @@ Author:
Christoph Wintersteiger (cwinter) 2012-03-16
Notes:
--*/
using System;
@ -25,7 +25,7 @@ using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// The abstract syntax tree (AST) class.
/// The abstract syntax tree (AST) class.
/// </summary>
[ContractVerification(true)]
public class AST : Z3Object, IComparable
@ -35,7 +35,7 @@ namespace Microsoft.Z3
/// </summary>
/// <param name="a">An AST</param>
/// <param name="b">An AST</param>
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are from the same context
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are from the same context
/// and represent the same sort; false otherwise.</returns>
public static bool operator ==(AST a, AST b)
{
@ -51,7 +51,7 @@ namespace Microsoft.Z3
/// </summary>
/// <param name="a">An AST</param>
/// <param name="b">An AST</param>
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are not from the same context
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are not from the same context
/// or represent different sorts; false otherwise.</returns>
public static bool operator !=(AST a, AST b)
{
@ -120,12 +120,12 @@ namespace Microsoft.Z3
if (ReferenceEquals(Context, ctx))
return this;
else
return new AST(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx));
return Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx));
}
/// <summary>
/// The kind of the AST.
/// </summary>
/// </summary>
public Z3_ast_kind ASTKind
{
get { return (Z3_ast_kind)Native.Z3_get_ast_kind(Context.nCtx, NativeObject); }
@ -224,10 +224,10 @@ namespace Microsoft.Z3
{
Native.Z3_dec_ref(ctx.nCtx, obj);
}
};
};
internal override void IncRef(IntPtr o)
{
{
// Console.WriteLine("AST IncRef()");
if (Context == null || o == IntPtr.Zero)
return;

View file

@ -163,13 +163,7 @@ namespace Microsoft.Z3
/// <returns>A copy of the term which is associated with <paramref name="ctx"/></returns>
new public Expr Translate(Context ctx)
{
Contract.Requires(ctx != null);
Contract.Ensures(Contract.Result<Expr>() != null);
if (ReferenceEquals(Context, ctx))
return this;
else
return Expr.Create(ctx, Native.Z3_translate(Context.nCtx, NativeObject, ctx.nCtx));
return (Expr)base.Translate(ctx);
}
/// <summary>
@ -797,6 +791,77 @@ namespace Microsoft.Z3
public bool IsLabelLit { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_LABEL_LIT; } }
#endregion
#region Sequences and Strings
/// <summary>
/// Check whether expression is a string constant.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsString { get { return IsApp && 0 != Native.Z3_is_string(Context.nCtx, NativeObject); } }
/// <summary>
/// Retrieve string corresponding to string constant.
/// </summary>
/// <remarks>the expression should be a string constant, (IsString should be true).</remarks>
public string String { get { return Native.Z3_get_string(Context.nCtx, NativeObject); } }
/// <summary>
/// Check whether expression is a concatentation.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsConcat { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONCAT; } }
/// <summary>
/// Check whether expression is a prefix.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsPrefix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_PREFIX; } }
/// <summary>
/// Check whether expression is a suffix.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsSuffix { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_SUFFIX; } }
/// <summary>
/// Check whether expression is a contains.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsContains { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_CONTAINS; } }
/// <summary>
/// Check whether expression is an extract.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsExtract { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_EXTRACT; } }
/// <summary>
/// Check whether expression is a replace.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsReplace { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_REPLACE; } }
/// <summary>
/// Check whether expression is an at.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsAt { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_AT; } }
/// <summary>
/// Check whether expression is a sequence length.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsLength { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_LENGTH; } }
/// <summary>
/// Check whether expression is a sequence index.
/// </summary>
/// <returns>a Boolean</returns>
public bool IsIndex { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_SEQ_INDEX; } }
#endregion
#region Proof Terms
/// <summary>
/// Indicates whether the term is a binary equivalence modulo namings.

View file

@ -14,7 +14,7 @@ Author:
Christoph Wintersteiger (cwinter) 2012-03-16
Notes:
--*/
using System;
@ -23,7 +23,7 @@ using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// Function declarations.
/// Function declarations.
/// </summary>
[ContractVerification(true)]
public class FuncDecl : AST
@ -62,7 +62,7 @@ namespace Microsoft.Z3
/// <summary>
/// A hash code.
/// </summary>
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
@ -205,7 +205,7 @@ namespace Microsoft.Z3
}
/// <summary>
/// Function declarations can have Parameters associated with them.
/// Function declarations can have Parameters associated with them.
/// </summary>
public class Parameter
{
@ -315,6 +315,17 @@ namespace Microsoft.Z3
#endif
#endregion
/// <summary>
/// Translates (copies) the function declaration to the Context <paramref name="ctx"/>.
/// </summary>
/// <param name="ctx">A context</param>
/// <returns>A copy of the function declaration which is associated with <paramref name="ctx"/></returns>
new public FuncDecl Translate(Context ctx)
{
return (FuncDecl) base.Translate(ctx);
}
/// <summary>
/// Create expression that applies function to arguments.
/// </summary>
@ -342,6 +353,5 @@ namespace Microsoft.Z3
Context.CheckContextMatch<Expr>(args);
return Expr.Create(Context, this, args);
}
}
}

View file

@ -19,6 +19,7 @@ Notes:
using System;
using System.Diagnostics.Contracts;
using System.Collections.Generic;
namespace Microsoft.Z3
{
@ -131,6 +132,24 @@ namespace Microsoft.Z3
}
}
/// <summary>
/// Enumerate constants in model.
/// </summary>
public IEnumerable<KeyValuePair<FuncDecl, Expr>> Consts
{
get
{
uint nc = NumConsts;
for (uint i = 0; i < nc; ++i)
{
var f = new FuncDecl(Context, Native.Z3_model_get_const_decl(Context.nCtx, NativeObject, i));
IntPtr n = Native.Z3_model_get_const_interp(Context.nCtx, NativeObject, f.NativeObject);
if (n == IntPtr.Zero) continue;
yield return new KeyValuePair<FuncDecl, Expr>(f, Expr.Create(Context, n));
}
}
}
/// <summary>
/// The number of function interpretations in the model.
/// </summary>

View file

@ -14,7 +14,7 @@ Author:
Christoph Wintersteiger (cwinter) 2012-03-19
Notes:
--*/
using System;
@ -157,6 +157,16 @@ namespace Microsoft.Z3
}
}
/// <summary>
/// Translates (copies) the quantifier to the Context <paramref name="ctx"/>.
/// </summary>
/// <param name="ctx">A context</param>
/// <returns>A copy of the quantifier which is associated with <paramref name="ctx"/></returns>
new public Quantifier Translate(Context ctx)
{
return (Quantifier)base.Translate(ctx);
}
#region Internal
[ContractVerification(false)] // F: Clousot ForAll decompilation gets confused below. Setting verification off until I fixed the bug
internal Quantifier(Context ctx, bool isForall, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)

View file

@ -14,7 +14,7 @@ Author:
Christoph Wintersteiger (cwinter) 2012-03-15
Notes:
--*/
using System;
@ -33,7 +33,7 @@ namespace Microsoft.Z3
/// </summary>
/// <param name="a">A Sort</param>
/// <param name="b">A Sort</param>
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are from the same context
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are from the same context
/// and represent the same sort; false otherwise.</returns>
public static bool operator ==(Sort a, Sort b)
{
@ -49,7 +49,7 @@ namespace Microsoft.Z3
/// </summary>
/// <param name="a">A Sort</param>
/// <param name="b">A Sort</param>
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are not from the same context
/// <returns>True if <paramref name="a"/> and <paramref name="b"/> are not from the same context
/// or represent different sorts; false otherwise.</returns>
public static bool operator !=(Sort a, Sort b)
{
@ -113,10 +113,20 @@ namespace Microsoft.Z3
return Native.Z3_sort_to_string(Context.nCtx, NativeObject);
}
/// <summary>
/// Translates (copies) the sort to the Context <paramref name="ctx"/>.
/// </summary>
/// <param name="ctx">A context</param>
/// <returns>A copy of the sort which is associated with <paramref name="ctx"/></returns>
new public Sort Translate(Context ctx)
{
return (Sort)base.Translate(ctx);
}
#region Internal
/// <summary>
/// Sort constructor
/// </summary>
/// </summary>
internal Sort(Context ctx, IntPtr obj) : base(ctx, obj) { Contract.Requires(ctx != null); }
#if DEBUG
@ -154,5 +164,5 @@ namespace Microsoft.Z3
}
}
#endregion
}
}
}

View file

@ -87,12 +87,10 @@ public class AST extends Z3Object implements Comparable<AST>
**/
public AST translate(Context ctx)
{
if (getContext() == ctx) {
return this;
} else {
return new AST(ctx, Native.translate(getContext().nCtx(),
getNativeObject(), ctx.nCtx()));
return create(ctx, Native.translate(getContext().nCtx(), getNativeObject(), ctx.nCtx()));
}
}

View file

@ -194,14 +194,7 @@ public class Expr extends AST
**/
public Expr translate(Context ctx)
{
if (getContext() == ctx) {
return this;
} else {
return Expr.create(
ctx,
Native.translate(getContext().nCtx(), getNativeObject(),
ctx.nCtx()));
}
return (Expr) super.translate(ctx);
}
/**
@ -1277,6 +1270,35 @@ public class Expr extends AST
return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_LABEL_LIT;
}
/**
* Check whether expression is a string constant.
* @return a boolean
*/
public boolean isString()
{
return isApp() && Native.isString(getContext().nCtx(), getNativeObject());
}
/**
* Retrieve string corresponding to string constant.
* Remark: the expression should be a string constant, (isString() should return true).
* @throws Z3Exception on error
* @return a string
*/
public String getString()
{
return Native.getString(getContext().nCtx(), getNativeObject());
}
/**
* Check whether expression is a concatenation
* @return a boolean
*/
public boolean isConcat()
{
return isApp() && getFuncDecl().getDeclKind() == Z3_decl_kind.Z3_OP_SEQ_CONCAT;
}
/**
* Indicates whether the term is a binary equivalence modulo namings.
* Remarks: This binary predicate is used in proof terms. It captures

View file

@ -1,6 +1,6 @@
/**
Copyright (c) 2012-2014 Microsoft Corporation
Module Name:
FuncDecl.java
@ -12,8 +12,8 @@ Author:
@author Christoph Wintersteiger (cwinter) 2012-03-15
Notes:
**/
**/
package com.microsoft.z3;
@ -59,6 +59,18 @@ public class FuncDecl extends AST
return Native.getFuncDeclId(getContext().nCtx(), getNativeObject());
}
/**
* Translates (copies) the function declaration to the Context {@code ctx}.
* @param ctx A context
*
* @return A copy of the function declaration which is associated with {@code ctx}
* @throws Z3Exception on error
**/
public FuncDecl translate(Context ctx)
{
return (FuncDecl) super.translate(ctx);
}
/**
* The arity of the function declaration
**/
@ -68,7 +80,7 @@ public class FuncDecl extends AST
}
/**
* The size of the domain of the function declaration
* The size of the domain of the function declaration
* @see #getArity
**/
public int getDomainSize()
@ -324,7 +336,7 @@ public class FuncDecl extends AST
}
FuncDecl(Context ctx, Symbol name, Sort[] domain, Sort range)
{
super(ctx, Native.mkFuncDecl(ctx.nCtx(), name.getNativeObject(),
AST.arrayLength(domain), AST.arrayToNative(domain),
@ -333,7 +345,7 @@ public class FuncDecl extends AST
}
FuncDecl(Context ctx, String prefix, Sort[] domain, Sort range)
{
super(ctx, Native.mkFreshFuncDecl(ctx.nCtx(), prefix,
AST.arrayLength(domain), AST.arrayToNative(domain),
@ -351,7 +363,7 @@ public class FuncDecl extends AST
}
/**
* Create expression that applies function to arguments.
* Create expression that applies function to arguments.
**/
public Expr apply(Expr ... args)
{

View file

@ -145,6 +145,19 @@ public class Quantifier extends BoolExpr
.nCtx(), getNativeObject()));
}
/**
* Translates (copies) the quantifier to the Context {@code ctx}.
*
* @param ctx A context
*
* @return A copy of the quantifier which is associated with {@code ctx}
* @throws Z3Exception on error
**/
public Quantifier translate(Context ctx)
{
return (Quantifier) super.translate(ctx);
}
/**
* Create a quantified expression.
*

View file

@ -87,6 +87,19 @@ public class Sort extends AST
return Native.sortToString(getContext().nCtx(), getNativeObject());
}
/**
* Translates (copies) the sort to the Context {@code ctx}.
*
* @param ctx A context
*
* @return A copy of the sort which is associated with {@code ctx}
* @throws Z3Exception on error
**/
public Sort translate(Context ctx)
{
return (Sort) super.translate(ctx);
}
/**
* Sort constructor
**/

View file

@ -50,6 +50,7 @@ from fractions import Fraction
import sys
import io
import math
import copy
if sys.version < '3':
def _is_int(v):
@ -288,6 +289,9 @@ class AstRef(Z3PPObject):
if self.ctx.ref() is not None:
Z3_dec_ref(self.ctx.ref(), self.as_ast())
def __deepcopy__(self, memo={}):
return _to_ast_ref(self.ast, self.ctx)
def __str__(self):
return obj_to_string(self)
@ -314,7 +318,7 @@ class AstRef(Z3PPObject):
raise Z3Exception("Symbolic expressions cannot be cast to concrete Boolean values.")
def sexpr(self):
"""Return an string representing the AST node in s-expression notation.
"""Return a string representing the AST node in s-expression notation.
>>> x = Int('x')
>>> ((x + 1)*x).sexpr()
@ -4357,6 +4361,11 @@ class Datatype:
self.name = name
self.constructors = []
def __deepcopy__(self, memo={}):
r = Datatype(self.name, self.ctx)
r.constructors = copy.deepcopy(self.constructors)
return r
def declare_core(self, name, rec_name, *args):
if __debug__:
_z3_assert(isinstance(name, str), "String expected")
@ -4647,11 +4656,17 @@ class ParamsRef:
Consider using the function `args2params` to create instances of this object.
"""
def __init__(self, ctx=None):
def __init__(self, ctx=None, params=None):
self.ctx = _get_ctx(ctx)
self.params = Z3_mk_params(self.ctx.ref())
if params is None:
self.params = Z3_mk_params(self.ctx.ref())
else:
self.params = params
Z3_params_inc_ref(self.ctx.ref(), self.params)
def __deepcopy__(self, memo={}):
return ParamsRef(self.ctx, self.params)
def __del__(self):
if self.ctx.ref() is not None:
Z3_params_dec_ref(self.ctx.ref(), self.params)
@ -4711,6 +4726,9 @@ class ParamDescrsRef:
self.descr = descr
Z3_param_descrs_inc_ref(self.ctx.ref(), self.descr)
def __deepcopy__(self, memo={}):
return ParamsDescrsRef(self.descr, self.ctx)
def __del__(self):
if self.ctx.ref() is not None:
Z3_param_descrs_dec_ref(self.ctx.ref(), self.descr)
@ -4772,6 +4790,9 @@ class Goal(Z3PPObject):
self.goal = Z3_mk_goal(self.ctx.ref(), models, unsat_cores, proofs)
Z3_goal_inc_ref(self.ctx.ref(), self.goal)
def __deepcopy__(self, memo={}):
return Goal(False, False, False, self.ctx, self.goal)
def __del__(self):
if self.goal is not None and self.ctx.ref() is not None:
Z3_goal_dec_ref(self.ctx.ref(), self.goal)
@ -5034,6 +5055,9 @@ class AstVector(Z3PPObject):
self.ctx = ctx
Z3_ast_vector_inc_ref(self.ctx.ref(), self.vector)
def __deepcopy__(self, memo={}):
return AstVector(self.vector, self.ctx)
def __del__(self):
if self.vector is not None and self.ctx.ref() is not None:
Z3_ast_vector_dec_ref(self.ctx.ref(), self.vector)
@ -5169,6 +5193,9 @@ class AstMap:
self.ctx = ctx
Z3_ast_map_inc_ref(self.ctx.ref(), self.map)
def __deepcopy__(self, memo={}):
return AstMap(self.map, self.ctx)
def __del__(self):
if self.map is not None and self.ctx.ref() is not None:
Z3_ast_map_dec_ref(self.ctx.ref(), self.map)
@ -5284,6 +5311,9 @@ class FuncEntry:
self.ctx = ctx
Z3_func_entry_inc_ref(self.ctx.ref(), self.entry)
def __deepcopy__(self, memo={}):
return FuncEntry(self.entry, self.ctx)
def __del__(self):
if self.ctx.ref() is not None:
Z3_func_entry_dec_ref(self.ctx.ref(), self.entry)
@ -5390,6 +5420,9 @@ class FuncInterp(Z3PPObject):
if self.f is not None:
Z3_func_interp_inc_ref(self.ctx.ref(), self.f)
def __deepcopy__(self, memo={}):
return FuncInterp(self.f, self.ctx)
def __del__(self):
if self.f is not None and self.ctx.ref() is not None:
Z3_func_interp_dec_ref(self.ctx.ref(), self.f)
@ -5500,6 +5533,9 @@ class ModelRef(Z3PPObject):
self.ctx = ctx
Z3_model_inc_ref(self.ctx.ref(), self.model)
def __deepcopy__(self, memo={}):
return ModelRef(self.m, self.ctx)
def __del__(self):
if self.ctx.ref() is not None:
Z3_model_dec_ref(self.ctx.ref(), self.model)
@ -5776,6 +5812,9 @@ class Statistics:
self.ctx = ctx
Z3_stats_inc_ref(self.ctx.ref(), self.stats)
def __deepcopy__(self, memo={}):
return Statistics(self.stats, self.ctx)
def __del__(self):
if self.ctx.ref() is not None:
Z3_stats_dec_ref(self.ctx.ref(), self.stats)
@ -5910,6 +5949,9 @@ class CheckSatResult:
def __init__(self, r):
self.r = r
def __deepcopy__(self, memo={}):
return CheckSatResult(self.r)
def __eq__(self, other):
return isinstance(other, CheckSatResult) and self.r == other.r
@ -5949,6 +5991,9 @@ class Solver(Z3PPObject):
self.solver = solver
Z3_solver_inc_ref(self.ctx.ref(), self.solver)
def __deepcopy__(self, memo={}):
return Solver(self.solver, self.ctx)
def __del__(self):
if self.solver is not None and self.ctx.ref() is not None:
Z3_solver_dec_ref(self.ctx.ref(), self.solver)
@ -6369,6 +6414,9 @@ class Fixedpoint(Z3PPObject):
Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint)
self.vars = []
def __deepcopy__(self, memo={}):
return FixedPoint(self.fixedpoint, self.ctx)
def __del__(self):
if self.fixedpoint is not None and self.ctx.ref() is not None:
Z3_fixedpoint_dec_ref(self.ctx.ref(), self.fixedpoint)
@ -6743,6 +6791,9 @@ class Optimize(Z3PPObject):
self.optimize = Z3_mk_optimize(self.ctx.ref())
Z3_optimize_inc_ref(self.ctx.ref(), self.optimize)
def __deepcopy__(self, memo={}):
return Optimize(self.optimize, self.ctx)
def __del__(self):
if self.optimize is not None and self.ctx.ref() is not None:
Z3_optimize_dec_ref(self.ctx.ref(), self.optimize)
@ -6895,6 +6946,9 @@ class ApplyResult(Z3PPObject):
self.ctx = ctx
Z3_apply_result_inc_ref(self.ctx.ref(), self.result)
def __deepcopy__(self, memo={}):
return ApplyResult(self.result, self.ctx)
def __del__(self):
if self.ctx.ref() is not None:
Z3_apply_result_dec_ref(self.ctx.ref(), self.result)
@ -7023,6 +7077,9 @@ class Tactic:
raise Z3Exception("unknown tactic '%s'" % tactic)
Z3_tactic_inc_ref(self.ctx.ref(), self.tactic)
def __deepcopy__(self, memo={}):
return Tactic(self.tactic, self.ctx)
def __del__(self):
if self.tactic is not None and self.ctx.ref() is not None:
Z3_tactic_dec_ref(self.ctx.ref(), self.tactic)
@ -7295,6 +7352,9 @@ class Probe:
raise Z3Exception("unknown probe '%s'" % probe)
Z3_probe_inc_ref(self.ctx.ref(), self.probe)
def __deepcopy__(self, memo={}):
return Probe(self.probe, self.ctx)
def __del__(self):
if self.probe is not None and self.ctx.ref() is not None:
Z3_probe_dec_ref(self.ctx.ref(), self.probe)

View file

@ -48,6 +48,7 @@ DEFINE_TYPE(Z3_rcf_num);
/*@{*/
/** @name Types
@{
Most of the types in the C API are opaque pointers.
@ -5238,7 +5239,6 @@ extern "C" {
def_API('Z3_get_error_msg', STRING, (_in(CONTEXT), _in(ERROR_CODE)))
*/
Z3_string Z3_API Z3_get_error_msg(Z3_context c, Z3_error_code err);
/*@}*/
/**
\brief Return a string describing the given error code.
@ -5349,6 +5349,10 @@ extern "C" {
/**
\brief Add a new formula \c a to the given goal.
Conjunctions are split into separate formulas.
If the goal is \c false, adding new formulas is a no-op.
If the formula \c a is \c true, then nothing is added.
If the formula \c a is \c false, then the entire goal is replaced by the formula \c false.
def_API('Z3_goal_assert', VOID, (_in(CONTEXT), _in(GOAL), _in(AST)))
*/
@ -5791,9 +5795,35 @@ extern "C" {
/** @name Solvers*/
/*@{*/
/**
\brief Create a new (incremental) solver. This solver also uses a
set of builtin tactics for handling the first check-sat command, and
check-sat commands that take more than a given number of milliseconds to be solved.
\brief Create a new solver. This solver is a "combined solver" (see
combined_solver module) that internally uses a non-incremental (solver1) and an
incremental solver (solver2). This combined solver changes its behaviour based
on how it is used and how its parameters are set.
If the solver is used in a non incremental way (i.e. no calls to
`Z3_solver_push()` or `Z3_solver_pop()`, and no calls to
`Z3_solver_assert()` or `Z3_solver_assert_and_track()` after checking
satisfiability without an intervening `Z3_solver_reset()`) then solver1
will be used. This solver will apply Z3's "default" tactic.
The "default" tactic will attempt to probe the logic used by the
assertions and will apply a specialized tactic if one is supported.
Otherwise the general `(and-then simplify smt)` tactic will be used.
If the solver is used in an incremental way then the combined solver
will switch to using solver2 (which behaves similarly to the general
"smt" tactic).
Note however it is possible to set the `solver2_timeout`,
`solver2_unknown`, and `ignore_solver1` parameters of the combined
solver to change its behaviour.
The function #Z3_solver_get_model retrieves a model if the
assertions is satisfiable (i.e., the result is \c
Z3_L_TRUE) and model construction is enabled.
The function #Z3_solver_get_model can also be used even
if the result is \c Z3_L_UNDEF, but the returned model
is not guaranteed to satisfy quantified assertions.
\remark User must use #Z3_solver_inc_ref and #Z3_solver_dec_ref to manage solver objects.
Even if the context was created using #Z3_mk_context instead of #Z3_mk_context_rc.
@ -5803,7 +5833,17 @@ extern "C" {
Z3_solver Z3_API Z3_mk_solver(Z3_context c);
/**
\brief Create a new (incremental) solver.
\brief Create a new incremental solver.
This is equivalent to applying the "smt" tactic.
Unlike `Z3_mk_solver()` this solver
- Does not attempt to apply any logic specific tactics.
- Does not change its behaviour based on whether it used
incrementally/non-incrementally.
Note that these differences can result in very different performance
compared to `Z3_mk_solver()`.
The function #Z3_solver_get_model retrieves a model if the
assertions is satisfiable (i.e., the result is \c

View file

@ -75,7 +75,7 @@ extern "C" {
\brief Add a maximization constraint.
\param c - context
\param o - optimization context
\param a - arithmetical term
\param t - arithmetical term
def_API('Z3_optimize_maximize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST)))
*/
unsigned Z3_API Z3_optimize_maximize(Z3_context c, Z3_optimize o, Z3_ast t);
@ -84,7 +84,7 @@ extern "C" {
\brief Add a minimization constraint.
\param c - context
\param o - optimization context
\param a - arithmetical term
\param t - arithmetical term
def_API('Z3_optimize_minimize', UINT, (_in(CONTEXT), _in(OPTIMIZE), _in(AST)))
*/

View file

@ -2082,6 +2082,7 @@ public:
bool is_undef_proof(expr const * e) const { return e == m_undef_proof; }
bool is_asserted(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_ASSERTED); }
bool is_hypothesis (expr const *e) const {return is_app_of (e, m_basic_family_id, PR_HYPOTHESIS);}
bool is_goal(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_GOAL); }
bool is_modus_ponens(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_MODUS_PONENS); }
bool is_reflexivity(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_REFLEXIVITY); }
@ -2112,6 +2113,7 @@ public:
bool is_skolemize(expr const * e) const { return is_app_of(e, m_basic_family_id, PR_SKOLEMIZE); }
MATCH_UNARY(is_asserted);
MATCH_UNARY(is_hypothesis);
MATCH_UNARY(is_lemma);
bool has_fact(proof const * p) const {

View file

@ -557,7 +557,14 @@ class smt2_printer {
format * f;
if (v->get_idx() < m_var_names.size()) {
symbol s = m_var_names[m_var_names.size() - v->get_idx() - 1];
f = mk_string(m(), s.str().c_str());
std::string vname;
if (is_smt2_quoted_symbol (s)) {
vname = mk_smt2_quoted_symbol (s);
}
else {
vname = s.str();
}
f = mk_string(m(), vname.c_str ());
}
else {
// fallback... it is not supposed to happen when the printer is correctly used.
@ -884,7 +891,14 @@ class smt2_printer {
symbol * it = m_var_names.end() - num_decls;
for (unsigned i = 0; i < num_decls; i++, it++) {
format * fs[1] = { m_env.pp_sort(q->get_decl_sort(i)) };
buf.push_back(mk_seq1<format**,f2f>(m(), fs, fs+1, f2f(), it->str().c_str()));
std::string var_name;
if (is_smt2_quoted_symbol (*it)) {
var_name = mk_smt2_quoted_symbol (*it);
}
else {
var_name = it->str ();\
}
buf.push_back(mk_seq1<format**,f2f>(m(), fs, fs+1, f2f(), var_name.c_str ()));
}
return mk_seq5(m(), buf.begin(), buf.end(), f2f());
}

View file

@ -35,6 +35,13 @@ class expr_map {
obj_map<expr, expr*> m_expr2expr;
obj_map<expr, proof*> m_expr2pr;
public:
typedef obj_map<expr, expr*> Map;
typedef Map::iterator iterator;
typedef Map::key key;
typedef Map::value value;
typedef Map::data data;
typedef Map::entry entry;
expr_map(ast_manager & m);
expr_map(ast_manager & m, bool store_proofs);
~expr_map();
@ -44,6 +51,8 @@ public:
void erase(expr * k);
void reset();
void flush();
iterator begin () const { return m_expr2expr.begin (); }
iterator end () const {return m_expr2expr.end (); }
void set_store_proofs(bool f) {
if (m_store_proofs != f) flush();
m_store_proofs = f;

View file

@ -39,7 +39,7 @@ class help_cmd : public cmd {
ctx.regular_stream() << " (" << s;
if (usage)
ctx.regular_stream() << " " << escaped(usage, true) << ")\n";
else
else
ctx.regular_stream() << ")\n";
if (descr) {
ctx.regular_stream() << " " << escaped(descr, true, 4) << "\n";
@ -62,7 +62,7 @@ public:
}
m_cmds.push_back(s);
}
typedef std::pair<symbol, cmd*> named_cmd;
struct named_cmd_lt {
bool operator()(named_cmd const & c1, named_cmd const & c2) const { return c1.first.str() < c2.first.str(); }
@ -104,14 +104,14 @@ class get_model_cmd : public cmd {
unsigned m_index;
public:
get_model_cmd(): cmd("get-model"), m_index(0) {}
virtual char const * get_usage() const { return "[<index of box objective>]"; }
virtual char const * get_descr(cmd_context & ctx) const {
return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective";
virtual char const * get_usage() const { return "[<index of box objective>]"; }
virtual char const * get_descr(cmd_context & ctx) const {
return "retrieve model for the last check-sat command.\nSupply optional index if retrieving a model corresponding to a box optimization objective";
}
virtual unsigned get_arity() const { return VAR_ARITY; }
virtual unsigned get_arity() const { return VAR_ARITY; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_UINT; }
virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; }
virtual void execute(cmd_context & ctx) {
virtual void set_next_arg(cmd_context & ctx, unsigned index) { m_index = index; }
virtual void execute(cmd_context & ctx) {
if (!ctx.is_model_available() || ctx.get_check_sat_result() == 0)
throw cmd_exception("model is not available");
model_ref m;
@ -122,7 +122,7 @@ public:
ctx.get_check_sat_result()->get_model(m);
}
ctx.display_model(m);
}
}
virtual void reset(cmd_context& ctx) {
m_index = 0;
}
@ -149,7 +149,14 @@ ATOMIC_CMD(get_assignment_cmd, "get-assignment", "retrieve assignment", {
first = false;
else
ctx.regular_stream() << " ";
ctx.regular_stream() << "(" << name << " " << (ctx.m().is_true(val) ? "true" : "false") << ")";
ctx.regular_stream() << "(";
if (is_smt2_quoted_symbol(name)) {
ctx.regular_stream() << mk_smt2_quoted_symbol(name);
}
else {
ctx.regular_stream() << name;
}
ctx.regular_stream() << " " << (ctx.m().is_true(val) ? "true" : "false") << ")";
}
}
}
@ -160,11 +167,11 @@ class cmd_is_declared : public ast_smt_pp::is_declared {
cmd_context& m_ctx;
public:
cmd_is_declared(cmd_context& ctx): m_ctx(ctx) {}
virtual bool operator()(func_decl* d) const {
virtual bool operator()(func_decl* d) const {
return m_ctx.is_func_decl(d->get_name());
}
virtual bool operator()(sort* s) const {
virtual bool operator()(sort* s) const {
return m_ctx.is_sort_decl(s->get_name());
}
};
@ -182,13 +189,13 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", {
if (ctx.well_sorted_check_enabled() && !is_well_sorted(ctx.m(), pr)) {
throw cmd_exception("proof is not well sorted");
}
pp_params params;
if (params.pretty_proof()) {
ctx.regular_stream() << mk_pp(pr, ctx.m()) << std::endl;
}
else {
// TODO: reimplement a new SMT2 pretty printer
// TODO: reimplement a new SMT2 pretty printer
ast_smt_pp pp(ctx.m());
cmd_is_declared isd(ctx);
pp.set_is_declared(&isd);
@ -198,20 +205,21 @@ ATOMIC_CMD(get_proof_cmd, "get-proof", "retrieve proof", {
}
});
#define PRINT_CORE() \
ptr_vector<expr> core; \
ctx.get_check_sat_result()->get_unsat_core(core); \
ctx.regular_stream() << "("; \
ptr_vector<expr>::const_iterator it = core.begin(); \
ptr_vector<expr>::const_iterator end = core.end(); \
for (bool first = true; it != end; ++it) { \
if (first) \
first = false; \
else \
ctx.regular_stream() << " "; \
ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m()); \
} \
ctx.regular_stream() << ")" << std::endl; \
static void print_core(cmd_context& ctx) {
ptr_vector<expr> core;
ctx.get_check_sat_result()->get_unsat_core(core);
ctx.regular_stream() << "(";
ptr_vector<expr>::const_iterator it = core.begin();
ptr_vector<expr>::const_iterator end = core.end();
for (bool first = true; it != end; ++it) {
if (first)
first = false;
else
ctx.regular_stream() << " ";
ctx.regular_stream() << mk_ismt2_pp(*it, ctx.m());
}
ctx.regular_stream() << ")" << std::endl;
}
ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", {
if (!ctx.produce_unsat_cores())
@ -219,7 +227,7 @@ ATOMIC_CMD(get_unsat_core_cmd, "get-unsat-core", "retrieve unsat core", {
if (!ctx.has_manager() ||
ctx.cs_state() != cmd_context::css_unsat)
throw cmd_exception("unsat core is not available");
PRINT_CORE();
print_core(ctx);
});
ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset of assumptions sufficient for unsatisfiability", {
@ -228,7 +236,7 @@ ATOMIC_CMD(get_unsat_assumptions_cmd, "get-unsat-assumptions", "retrieve subset
if (!ctx.has_manager() || ctx.cs_state() != cmd_context::css_unsat) {
throw cmd_exception("unsat assumptions is not available");
}
PRINT_CORE();
print_core(ctx);
});
@ -250,9 +258,9 @@ ATOMIC_CMD(get_assertions_cmd, "get-assertions", "retrieve asserted terms when i
ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions(););
ATOMIC_CMD(reset_assertions_cmd, "reset-assertions", "reset all asserted formulas (but retain definitions and declarations)", ctx.reset_assertions(); ctx.print_success(););
UNARY_CMD(set_logic_cmd, "set-logic", "<symbol>", "set the background logic.", CPK_SYMBOL, symbol const &,
UNARY_CMD(set_logic_cmd, "set-logic", "<symbol>", "set the background logic.", CPK_SYMBOL, symbol const &,
if (ctx.set_logic(arg))
ctx.print_success();
else {
@ -261,12 +269,14 @@ UNARY_CMD(set_logic_cmd, "set-logic", "<symbol>", "set the background logic.", C
}
);
UNARY_CMD(pp_cmd, "display", "<term>", "display the given term.", CPK_EXPR, expr *, {
UNARY_CMD(pp_cmd, "display", "<term>", "display the given term.", CPK_EXPR, expr *, {
ctx.display(ctx.regular_stream(), arg);
ctx.regular_stream() << std::endl;
ctx.regular_stream() << std::endl;
});
UNARY_CMD(echo_cmd, "echo", "<string>", "display the given string", CPK_STRING, char const *, ctx.regular_stream() << arg << std::endl;);
UNARY_CMD(echo_cmd, "echo", "<string>", "display the given string", CPK_STRING, char const *,
bool smt2c = ctx.params().m_smtlib2_compliant;
ctx.regular_stream() << (smt2c ? "\"" : "") << arg << (smt2c ? "\"" : "") << std::endl;);
class set_get_option_cmd : public cmd {
@ -297,18 +307,18 @@ protected:
symbol m_reproducible_resource_limit;
bool is_builtin_option(symbol const & s) const {
return
s == m_print_success || s == m_print_warning || s == m_expand_definitions ||
return
s == m_print_success || s == m_print_warning || s == m_expand_definitions ||
s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores || s == m_produce_unsat_assumptions ||
s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants ||
s == m_regular_output_channel || s == m_diagnostic_output_channel ||
s == m_regular_output_channel || s == m_diagnostic_output_channel ||
s == m_random_seed || s == m_verbosity || s == m_global_decls || s == m_global_declarations ||
s == m_produce_assertions || s == m_reproducible_resource_limit;
}
public:
set_get_option_cmd(char const * name):
cmd(name),
cmd(name),
m_true("true"),
m_false("false"),
m_print_success(":print-success"),
@ -340,7 +350,7 @@ public:
class set_option_cmd : public set_get_option_cmd {
bool m_unsupported;
symbol m_option;
bool to_bool(symbol const & value) const {
if (value != m_true && value != m_false)
throw cmd_exception("invalid option value, true/false expected");
@ -361,7 +371,7 @@ class set_option_cmd : public set_get_option_cmd {
throw cmd_exception(msg);
}
}
void set_param(cmd_context & ctx, char const * value) {
try {
gparams::set(m_option, value);
@ -458,11 +468,11 @@ public:
virtual void prepare(cmd_context & ctx) { m_unsupported = false; m_option = symbol::null; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
return m_option == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE;
}
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
if (m_option == symbol::null) {
m_option = opt;
}
@ -517,7 +527,7 @@ class get_option_cmd : public set_get_option_cmd {
static void print_bool(cmd_context & ctx, bool b) {
ctx.regular_stream() << (b ? "true" : "false") << std::endl;
}
static void print_unsigned(cmd_context & ctx, unsigned v) {
ctx.regular_stream() << v << std::endl;
}
@ -534,11 +544,11 @@ public:
virtual char const * get_descr(cmd_context & ctx) const { return "get configuration option."; }
virtual unsigned get_arity() const { return 1; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; }
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
if (opt == m_print_success) {
print_bool(ctx, ctx.print_success_enabled());
print_bool(ctx, ctx.print_success_enabled());
}
// TODO:
// TODO:
// else if (opt == m_print_warning) {
// print_bool(ctx, );
// }
@ -628,7 +638,7 @@ public:
virtual char const * get_descr(cmd_context & ctx) const { return "get information."; }
virtual unsigned get_arity() const { return 1; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_KEYWORD; }
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
virtual void set_next_arg(cmd_context & ctx, symbol const & opt) {
if (opt == m_error_behavior) {
if (ctx.exit_on_error())
ctx.regular_stream() << "(:error-behavior immediate-exit)" << std::endl;
@ -684,12 +694,12 @@ public:
virtual char const * get_descr(cmd_context & ctx) const { return "set information."; }
virtual unsigned get_arity() const { return 2; }
virtual void prepare(cmd_context & ctx) { m_info = symbol::null; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE;
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
return m_info == symbol::null ? CPK_KEYWORD : CPK_OPTION_VALUE;
}
virtual void set_next_arg(cmd_context & ctx, rational const & val) {}
virtual void set_next_arg(cmd_context & ctx, char const * val) {}
virtual void set_next_arg(cmd_context & ctx, symbol const & s) {
virtual void set_next_arg(cmd_context & ctx, symbol const & s) {
if (m_info == symbol::null) {
m_info = s;
}
@ -737,7 +747,7 @@ public:
virtual char const * get_descr(cmd_context & ctx) const { return "declare a new array map operator with name <symbol> using the given function declaration.\n<func-decl-ref> ::= <symbol>\n | (<symbol> (<sort>*) <sort>)\n | ((_ <symbol> <numeral>+) (<sort>*) <sort>)\nThe last two cases are used to disumbiguate between declarations with the same name and/or select (indexed) builtin declarations.\nFor more details about the the array map operator, see 'Generalized and Efficient Array Decision Procedures' (FMCAD 2009).\nExample: (declare-map set-union (Int) (or (Bool Bool) Bool))\nDeclares a new function (declare-fun set-union ((Array Int Bool) (Array Int Bool)) (Array Int Bool)).\nThe instance of the map axiom for this new declaration is:\n(forall ((a1 (Array Int Bool)) (a2 (Array Int Bool)) (i Int)) (= (select (set-union a1 a2) i) (or (select a1 i) (select a2 i))))"; }
virtual unsigned get_arity() const { return 3; }
virtual void prepare(cmd_context & ctx) { m_name = symbol::null; m_domain.reset(); }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
if (m_name == symbol::null) return CPK_SYMBOL;
if (m_domain.empty()) return CPK_SORT_LIST;
return CPK_FUNC_DECL;
@ -748,10 +758,10 @@ public:
throw cmd_exception("invalid map declaration, empty sort list");
m_domain.append(num, slist);
}
virtual void set_next_arg(cmd_context & ctx, func_decl * f) {
m_f = f;
if (m_f->get_arity() == 0)
throw cmd_exception("invalid map declaration, function declaration must have arity > 0");
virtual void set_next_arg(cmd_context & ctx, func_decl * f) {
m_f = f;
if (m_f->get_arity() == 0)
throw cmd_exception("invalid map declaration, function declaration must have arity > 0");
}
virtual void reset(cmd_context & ctx) {
m_array_fid = null_family_id;
@ -790,7 +800,7 @@ public:
virtual char const * get_descr(cmd_context & ctx) const { return "retrieve consequences that fix values for supplied variables"; }
virtual unsigned get_arity() const { return 2; }
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR_LIST; }
virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) {
virtual void set_next_arg(cmd_context & ctx, unsigned num, expr * const * tlist) {
if (m_count == 0) {
m_assumptions.append(num, tlist);
++m_count;
@ -850,7 +860,7 @@ void install_basic_cmds(cmd_context & ctx) {
ctx.insert(alloc(builtin_cmd, "declare-fun", "<symbol> (<sort>*) <sort>", "declare a new function/constant."));
ctx.insert(alloc(builtin_cmd, "declare-const", "<symbol> <sort>", "declare a new constant."));
ctx.insert(alloc(builtin_cmd, "declare-datatypes", "(<symbol>*) (<datatype-declaration>+)", "declare mutually recursive datatypes.\n<datatype-declaration> ::= (<symbol> <constructor-decl>+)\n<constructor-decl> ::= (<symbol> <accessor-decl>*)\n<accessor-decl> ::= (<symbol> <sort>)\nexample: (declare-datatypes (T) ((BinTree (leaf (value T)) (node (left BinTree) (right BinTree)))))"));
ctx.insert(alloc(builtin_cmd, "check-sat-asuming", "( hprop_literali* )", "check sat assuming a collection of literals"));
ctx.insert(alloc(builtin_cmd, "check-sat-assuming", "( hprop_literali* )", "check sat assuming a collection of literals"));
ctx.insert(alloc(get_unsat_assumptions_cmd));
ctx.insert(alloc(reset_assertions_cmd));

View file

@ -15,6 +15,7 @@ Author:
Notes:
--*/
#include<signal.h>
#include"tptr.h"
#include"cmd_context.h"
@ -325,8 +326,8 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l):
m_status(UNKNOWN),
m_numeral_as_real(false),
m_ignore_check(false),
m_exit_on_error(false),
m_processing_pareto(false),
m_exit_on_error(false),
m_manager(m),
m_own_manager(m == 0),
m_manager_initialized(false),

View file

@ -159,7 +159,7 @@ protected:
bool m_produce_assignments;
status m_status;
bool m_numeral_as_real;
bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files.
bool m_ignore_check; // used by the API to disable check-sat() commands when parsing SMT 2.0 files.
bool m_processing_pareto; // used when re-entering check-sat for pareto front.
bool m_exit_on_error;

View file

@ -784,7 +784,7 @@ namespace datalog {
SASSERT(tail.size()==tail_neg.size());
rule_ref old_r = r;
r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr());
r = mk(head, tail.size(), tail.c_ptr(), tail_neg.c_ptr(), old_r->name());
r->set_accounting_parent_object(m_ctx, old_r);
}
@ -1003,6 +1003,7 @@ namespace datalog {
void rule::display(context & ctx, std::ostream & out) const {
ast_manager & m = ctx.get_manager();
out << m_name.str () << ":\n";
//out << mk_pp(m_head, m);
output_predicate(ctx, m_head, out);
if (m_tail_size == 0) {

View file

@ -298,7 +298,7 @@ namespace datalog {
static unsigned get_obj_size(unsigned n) { return sizeof(rule) + n * sizeof(app *); }
rule() : m_ref_cnt(0) {}
rule() : m_ref_cnt(0), m_name(symbol::null) {}
~rule() {}
void deallocate(ast_manager & m);
@ -355,7 +355,12 @@ namespace datalog {
void display(context & ctx, std::ostream & out) const;
symbol const& name() const { return m_name; }
/**
\brief Return the name(s) associated with this rule. Plural for preprocessed (e.g. obtained by inlining) rules.
This possibly returns a ";"-separated list of names.
*/
symbol const& name() const { return m_name; } ;
unsigned hash() const;

View file

@ -140,7 +140,7 @@ namespace datalog {
if (rule_modified) {
remove_duplicate_tails(new_tail, new_is_negated);
SASSERT(new_tail.size() == new_is_negated.size());
rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr());
rule * new_rule = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), new_is_negated.c_ptr(), r->name());
new_rule->set_accounting_parent_object(m_context, m_current);
m_result->add_rule(new_rule);
m_context.get_rule_manager().mk_rule_rewrite_proof(*r, *new_rule);

View file

@ -84,7 +84,7 @@ namespace datalog {
mk_rule_inliner::remove_duplicate_tails(m_tail, m_neg);
SASSERT(m_tail.size() == m_neg.size());
res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr());
res = m_context.get_rule_manager().mk(m_head, m_tail.size(), m_tail.c_ptr(), m_neg.c_ptr(),m_rule->name());
res->set_accounting_parent_object(m_context, m_rule);
res->norm_vars(res.get_manager());
}
@ -557,7 +557,7 @@ namespace datalog {
}
SASSERT(m_tail.size() == m_tail_neg.size());
res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr());
res = m_context.get_rule_manager().mk(head, m_tail.size(), m_tail.c_ptr(), m_tail_neg.c_ptr(), r->name());
res->set_accounting_parent_object(m_context, r);
}
else {

View file

@ -280,7 +280,7 @@ namespace datalog {
new_tail.push_back(create_magic_literal(new_head));
negations.push_back(false);
rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr());
rule * nr = m_context.get_rule_manager().mk(new_head, new_tail.size(), new_tail.c_ptr(), negations.c_ptr(), r->name());
result.add_rule(nr);
nr->set_accounting_parent_object(m_context, r);
}

View file

@ -341,7 +341,7 @@ namespace datalog {
head = mk_head(source, *result, r.get_head(), cnt);
fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), head);
proof_ref pr(m);
rm.mk_rule(fml, pr, *result);
rm.mk_rule(fml, pr, *result, r.name());
TRACE("dl", result->last()->display(m_ctx, tout););
}

View file

@ -232,7 +232,7 @@ namespace datalog {
rule_set added_rules(m_ctx);
proof_ref pr(m);
rm.mk_rule(fml, pr, added_rules);
rm.mk_rule(fml, pr, added_rules, r.name());
if (r.get_proof()) {
// use def-axiom to encode that new rule is a weakening of the original.
proof* p1 = r.get_proof();

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